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 01/78] 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 02/78] 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 03/78] 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(); } /** From 36372fd18da2d5d26de1e1783afa0deb20dbeb0f Mon Sep 17 00:00:00 2001 From: Ganom Date: Thu, 16 May 2019 17:24:13 -0400 Subject: [PATCH 04/78] FreezeTimers Text Overhaul (#268) * FreezeTimers Text Overhaul * Adjustable X Offset for Image Timers * Fix Position of Offset in Config --- .../plugins/freezetimers/FontStyle.java | 46 ++++++++++++ .../freezetimers/FreezeTimersConfig.java | 64 +++++++++++++++- .../freezetimers/FreezeTimersOverlay.java | 73 ++++++++++++++++--- .../freezetimers/FreezeTimersPlugin.java | 24 ++++++ .../freezetimers/PlayerSpellEffect.java | 26 ++++++- .../plugins/freezetimers/PrayerTracker.java | 23 ++++++ .../plugins/freezetimers/TimerType.java | 23 ++++++ .../client/plugins/freezetimers/Timers.java | 23 ++++++ 8 files changed, 289 insertions(+), 13 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FontStyle.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FontStyle.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FontStyle.java new file mode 100644 index 0000000000..47cbd82c69 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FontStyle.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019, ganom + * 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.freezetimers; + +import java.awt.Font; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum FontStyle +{ + BOLD("Bold", Font.BOLD), + ITALIC("Italic", Font.ITALIC), + PLAIN("Plain", Font.PLAIN); + + private String name; + private int font; + + @Override + public String toString() + { + return getName(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersConfig.java index 2d5949a838..5ad0d7b33f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersConfig.java @@ -1,8 +1,33 @@ +/* + * Copyright (c) 2019, ganom + * Copyright (c) 2019, pklite + * 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.freezetimers; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; @ConfigGroup("freezetimers") public interface FreezeTimersConfig extends Config @@ -63,14 +88,51 @@ public interface FreezeTimersConfig extends Config return true; } + @ConfigItem( + keyName = "xoffset", + name = "X Offset", + description = "Increasing this will push further away from model. Does not apply to text timers.", + position = 6 + ) + default int offset() + { + return 20; + } + @ConfigItem( keyName = "noImage", name = "Text Timers", description = "Remove Images from Timers", - position = 6 + position = 7 ) default boolean noImage() { return false; } + + @ConfigItem( + keyName = "fontStyle", + name = "Font Style", + description = "Bold/Italics/Plain", + position = 8 + ) + default FontStyle fontStyle() + { + return FontStyle.BOLD; + } + + @Range( + min = 9, + max = 14 + ) + @ConfigItem( + keyName = "textSize", + name = "Text Size", + description = "Text Size for Timers.", + position = 9 + ) + default int textSize() + { + return 11; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java index 5054c12b98..9a9bf58828 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2019, ganom + * Copyright (c) 2019, pklite + * 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.freezetimers; import java.awt.Color; @@ -7,7 +31,6 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.Rectangle; import java.awt.image.BufferedImage; import javax.inject.Inject; import net.runelite.api.Actor; @@ -94,6 +117,7 @@ public class FreezeTimersOverlay extends Overlay long finishedAt = timers.getTimerEnd(actor, TimerType.FREEZE); String text = processTickCounter(finishedAt); + int test = Integer.parseInt(text); Point poi = actor.getCanvasTextLocation(g, text, 0); int xpoi = poi.getX(); int ypoi = poi.getY(); @@ -101,7 +125,14 @@ public class FreezeTimersOverlay extends Overlay if (config.noImage()) { - renderTextLocation(g, text, 11, Font.BOLD, Color.WHITE, FixedPoint); + if (test > 3) + { + renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.WHITE, FixedPoint); + } + else + { + renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.YELLOW, FixedPoint); + } } else { @@ -133,15 +164,15 @@ public class FreezeTimersOverlay extends Overlay { if (timers.getTimerEnd(actor, TimerType.FREEZE) <= currentTick) { - renderTextLocation(g, text, 11, Font.BOLD, Color.CYAN, poi); + renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, poi); } if (timers.getTimerEnd(actor, TimerType.FREEZE) >= currentTick) { - renderTextLocation(g, " | " + text, 11, Font.BOLD, Color.CYAN, FixedPoint); + renderTextLocation(g, " | " + text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, FixedPoint); } if (timers.getTimerEnd(actor, TimerType.VENG) >= currentTick) { - renderTextLocation(g, " | " + text, 11, Font.BOLD, Color.CYAN, FixedPoint); + renderTextLocation(g, " | " + text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, FixedPoint); } } else @@ -173,15 +204,15 @@ public class FreezeTimersOverlay extends Overlay { if (timers.getTimerEnd(actor, TimerType.FREEZE) <= currentTick) { - renderTextLocation(g, text, 11, Font.BOLD, Color.RED, poi); + renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.RED, poi); } if (timers.getTimerEnd(actor, TimerType.FREEZE) >= currentTick) { - renderTextLocation(g, text + " | ", 11, Font.BOLD, Color.RED, FixedPoint); + renderTextLocation(g, text + " | ", config.textSize(), config.fontStyle().getFont(), Color.RED, FixedPoint); } if (timers.getTimerEnd(actor, TimerType.TELEBLOCK) >= currentTick) { - renderTextLocation(g, text + " | ", 11, Font.BOLD, Color.RED, FixedPoint); + renderTextLocation(g, text + " | ", config.textSize(), config.fontStyle().getFont(), Color.RED, FixedPoint); } } else @@ -208,9 +239,8 @@ public class FreezeTimersOverlay extends Overlay int yOffset = (overlaysDrawn * 18); g.setFont(timerFont); g.setColor(WHITE); - Rectangle rect = actor.getConvexHull().getBounds(); - int xOffset = (int) rect.getWidth(); - OverlayUtil.renderActorTextAndImage(g, actor, text, Color.WHITE, image, yOffset, + int xOffset = config.offset(); + renderActorTextAndImage(g, actor, text, Color.WHITE, image, yOffset, xOffset); } @@ -230,6 +260,27 @@ public class FreezeTimersOverlay extends Overlay } } + public void renderImageLocation(Graphics2D graphics, Point imgLoc, BufferedImage image) + { + int x = imgLoc.getX(); + int y = imgLoc.getY(); + + graphics.drawImage(image, x, y, null); + } + + public void renderActorTextAndImage(Graphics2D graphics, Actor actor, String text, Color color, + BufferedImage image, int yOffset, int xOffset) + { + Point textLocation = new Point(actor.getCanvasImageLocation(image, 0).getX() + xOffset, + actor.getCanvasImageLocation(image, 0).getY() + yOffset); + + renderImageLocation(graphics, textLocation, image); + xOffset = image.getWidth() + 1; + yOffset = (image.getHeight() - (int) graphics.getFontMetrics().getStringBounds(text, graphics).getHeight()); + textLocation = new Point(textLocation.getX() + xOffset, textLocation.getY() + image.getHeight() - yOffset); + net.runelite.client.ui.overlay.OverlayUtil.renderTextLocation(graphics, textLocation, text, color); + } + private String processTickCounter(long finishedAt) { long currentTick = System.currentTimeMillis(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersPlugin.java index d3fd38f653..dc58487c50 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersPlugin.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2019, ganom + * Copyright (c) 2019, pklite + * 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.freezetimers; import com.google.inject.Provides; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java index 1d8f22a0e5..41df487ee8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2019, ganom + * Copyright (c) 2019, pklite + * 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.freezetimers; import lombok.AllArgsConstructor; @@ -12,7 +36,7 @@ public enum PlayerSpellEffect RUSH("Ice Rush", 361, 5000, false, 3, TimerType.FREEZE), BURST("Ice Burst", 363, 10000, false, 4, TimerType.FREEZE), BLITZ("Ice Blitz", 367, 15000, false, 5, TimerType.FREEZE), - BARRAGE("Ice Barrage", 369, 20000, false, 6, TimerType.FREEZE), + BARRAGE("Ice Barrage", 369, 22200, false, 6, TimerType.FREEZE), TELEBLOCK("Teleblock", 345, 300000, true, 7, TimerType.TELEBLOCK), VENG("Vengeance", 726, 30000, false, 8, TimerType.VENG), VENG_OTHER("Vengeance Other", 725, 30000, false, 9, TimerType.VENG), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java index 3cecf8519a..13228de07b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2019, pklite + * 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.freezetimers; import java.util.HashMap; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/TimerType.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/TimerType.java index c9e30c4dc1..1464df2405 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/TimerType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/TimerType.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2019, pklite + * 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.freezetimers; public enum TimerType diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/Timers.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/Timers.java index 58345fcc06..17cb1bb1b6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/Timers.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/Timers.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2019, pklite + * 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.freezetimers; import java.util.HashMap; From b3924317665c2f961a9889990bcabd5021f42740 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Thu, 16 May 2019 22:26:40 +0100 Subject: [PATCH 05/78] Update ClanChatPlugin.java (#266) * Update ClanChatPlugin.java * Update ClanChatPlugin.java --- .../net/runelite/client/plugins/clanchat/ClanChatPlugin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java index 617ca8d0a7..8e2f32f2ba 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java @@ -97,8 +97,8 @@ import net.runelite.client.util.Text; public class ClanChatPlugin extends Plugin { private static final int MAX_CHATS = 20; - private static final String CLAN_CHAT_TITLE = " Clan Chat"; - private static final String RECENT_TITLE = " Recent Clan Chats"; + private static final String CLAN_CHAT_TITLE = "CC"; + private static final String RECENT_TITLE = "Recent CCs"; private static final int JOIN_LEAVE_DURATION = 20; private static final int MESSAGE_DELAY = 10; From bdcb825e64850f113f60a13cf9fdf9223b20b898 Mon Sep 17 00:00:00 2001 From: Ganom Date: Thu, 16 May 2019 17:28:30 -0400 Subject: [PATCH 06/78] Fix NPE on Login Screen --- .../client/plugins/zulrah/ZulrahPlugin.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java index 6a5409bb24..4bdfcd6804 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java @@ -196,20 +196,34 @@ public class ZulrahPlugin extends Plugin @Subscribe public void onNpcSpawned(NpcSpawned event) { - NPC npc = event.getNpc(); - if (npc != null && npc.getName().toLowerCase().contains("zulrah")) + try { - zulrah = npc; + NPC npc = event.getNpc(); + if (npc != null && npc.getName().toLowerCase().contains("zulrah")) + { + zulrah = npc; + } + } + catch (Exception e) + { + } } @Subscribe public void onNpcDespawned(NpcDespawned event) { - NPC npc = event.getNpc(); - if (npc != null && npc.getName().toLowerCase().contains("zulrah")) + try { - zulrah = null; + NPC npc = event.getNpc(); + if (npc != null && npc.getName().toLowerCase().contains("zulrah")) + { + zulrah = null; + } + } + catch (Exception e) + { + } } From b99b4c21257d46fec8d40d324be1861fa16a322f Mon Sep 17 00:00:00 2001 From: Ganom Date: Thu, 16 May 2019 17:34:35 -0400 Subject: [PATCH 07/78] Adding correct param identifiers. --- .../src/main/java/net/runelite/api/Client.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 1fc9f42af0..e83b343311 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1614,7 +1614,18 @@ public interface Client extends GameEngine void toggleRenderSelf(); - void invokeMenuAction(int var1, int var2, int var3, int var4, String var5, String var6, int var7, int var8); + /** + * + * @param param0 This is SceneX for gameObject, index for items, and 0 for npc. + * @param param1 This is SceneY for gameObject, static for items, and 0 for npc. + * @param type Menu entry Action type. + * @param id Targets ID + * @param menuEntry Do these actually matter? + * @param targetString Do these actually matter? + * @param canvasX Canvas X Point + * @param canvasY Canvas Y Point + */ + void invokeMenuAction(int param0, int param1, int type, int id, String menuEntry, String targetString, int canvasX, int canvasY); MouseRecorder getMouseRecorder(); From ac616215c27959d92e66427209b12cc9be59a40f Mon Sep 17 00:00:00 2001 From: Ganom Date: Thu, 16 May 2019 17:51:26 -0400 Subject: [PATCH 08/78] Fix Menuoverload (#270) * To be fixed later. * To be fixed later. * Update PlayerIndicatorsPlugin.java --- .../plugins/playerindicators/PlayerIndicatorsConfig.java | 4 ++-- .../plugins/playerindicators/PlayerIndicatorsPlugin.java | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java index 969103036b..79bd8a7eb7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java @@ -296,7 +296,7 @@ public interface PlayerIndicatorsConfig extends Config return false; } - @ConfigItem( +/* @ConfigItem( position = 23, keyName = "rightClickOverhead", name = "Add Overheads to Right Click Menu", @@ -305,7 +305,7 @@ public interface PlayerIndicatorsConfig extends Config default boolean rightClickOverhead() { return false; - } + }*/ @ConfigItem( keyName = "useClanchatRanks", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index cbac52ca72..425726a461 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -287,7 +287,7 @@ public class PlayerIndicatorsPlugin extends Plugin { color = config.getTargetColor(); } - if (config.rightClickOverhead() && !player.isClanMember() && player.getOverheadIcon() != null) +/* if (config.rightClickOverhead() && !player.isClanMember() && player.getOverheadIcon() != null) { if (player.getOverheadIcon().equals(HeadIcon.MAGIC)) { @@ -313,8 +313,7 @@ public class PlayerIndicatorsPlugin extends Plugin { image = 34; } - - } + }*/ if (config.playerSkull() && !player.isClanMember() && player.getSkullIcon() != null) { image2 = 35; @@ -346,10 +345,10 @@ public class PlayerIndicatorsPlugin extends Plugin lastEntry.setTarget(ColorUtil.prependColorTag(target, color)); } - if (image != -1 && config.showClanRanks() || image != -1 && config.rightClickOverhead()) +/* if (image != -1 && config.showClanRanks() || image != -1 && config.rightClickOverhead()) { lastEntry.setTarget(lastEntry.getTarget() + ""); - } + }*/ if (image2 != -1 && config.playerSkull()) { lastEntry.setTarget("" + lastEntry.getTarget()); From f5528aa39998cad69bff2fb5c793b814f38e27a8 Mon Sep 17 00:00:00 2001 From: Ganom Date: Thu, 16 May 2019 18:46:59 -0400 Subject: [PATCH 09/78] Adding config option for skull (#272) * Adding config option for skull * Update TimersConfig.java --- .../runelite/client/plugins/timers/TimersConfig.java | 10 ++++++++++ .../runelite/client/plugins/timers/TimersPlugin.java | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java index 81f5e818dc..39f228d994 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java @@ -181,6 +181,16 @@ public interface TimersConfig extends Config return true; } + @ConfigItem( + keyName = "showSkull", + name = "Skull timer", + description = "Configures whether skull timer is displayed" + ) + default boolean showSkull() + { + return true; + } + @ConfigItem( keyName = "showStaffOfTheDead", name = "Staff of the Dead timer", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java index ebe8f976b0..889feb3bba 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java @@ -44,9 +44,9 @@ import net.runelite.api.NPC; import net.runelite.api.NpcID; import net.runelite.api.Player; import net.runelite.api.Prayer; +import net.runelite.api.Skill; import net.runelite.api.SkullIcon; import net.runelite.api.VarPlayer; -import net.runelite.api.Skill; import net.runelite.api.Varbits; import net.runelite.api.WorldType; import net.runelite.api.coords.WorldPoint; @@ -590,7 +590,7 @@ public class TimersPlugin extends Plugin final boolean isSkulled = player.getSkullIcon() != null && player.getSkullIcon() != SkullIcon.SKULL_FIGHT_PIT; - if (isSkulled != skulledLastTick) + if (isSkulled != skulledLastTick && config.showSkull()) { skulledLastTick = isSkulled; if (isSkulled) @@ -655,7 +655,7 @@ public class TimersPlugin extends Plugin if (config.showAbyssalSireStun() && actor instanceof NPC) { - int npcId = ((NPC)actor).getId(); + int npcId = ((NPC) actor).getId(); switch (npcId) { From 373475288d67e25ad497c9978fa664d2671ef5f0 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Fri, 17 May 2019 01:12:47 +0100 Subject: [PATCH 10/78] Codestyle check fixup (#276) * Update AnimationID.java * Update ProjectileID.java * Update InteractChanged.java * Update WidgetInfo.java * Update WidgetID.java * Update VarClientInt.java --- .../java/net/runelite/api/AnimationID.java | 6 +++--- .../java/net/runelite/api/ProjectileID.java | 2 +- .../java/net/runelite/api/VarClientInt.java | 18 +++++++++--------- .../runelite/api/events/InteractChanged.java | 4 ++-- .../net/runelite/api/widgets/WidgetID.java | 11 +++++++---- .../net/runelite/api/widgets/WidgetInfo.java | 4 ++-- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index 694d6cba2d..6c0e3662f8 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -214,8 +214,8 @@ public final class AnimationID // POH Animations public static final int INCENSE_BURNER = 3687; public static final int LOW_LEVEL_MAGIC_ATTACK = 1162; - public static final int HIGH_LEVEL_MAGIC_ATTACK = 1167; - public static final int BLOWPIPE_ATTACK = 5061; + public static final int HIGH_LEVEL_MAGIC_ATTACK = 1167; + public static final int BLOWPIPE_ATTACK = 5061; // Hydra public static final int HYDRA_POISON_1 = 8234; @@ -238,4 +238,4 @@ public final class AnimationID public static final int HYDRA_RANGED_4 = 8255; public static final int HYDRA_4_1 = 8257; public static final int HYDRA_4_2 = 8258; -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/ProjectileID.java b/runelite-api/src/main/java/net/runelite/api/ProjectileID.java index 06cab49768..c7d9c836cc 100644 --- a/runelite-api/src/main/java/net/runelite/api/ProjectileID.java +++ b/runelite-api/src/main/java/net/runelite/api/ProjectileID.java @@ -98,5 +98,5 @@ public class ProjectileID public static final int HYDRA_POISON = 1644; public static final int HYDRA_LIGHTNING = 1664; public static final int HYDRA_LIGHTNING_2 = 1665; - public static final int DRAKE_BREATH = 1637; + public static final int DRAKE_BREATH = 1637; } diff --git a/runelite-api/src/main/java/net/runelite/api/VarClientInt.java b/runelite-api/src/main/java/net/runelite/api/VarClientInt.java index b58e879437..27df154f62 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarClientInt.java +++ b/runelite-api/src/main/java/net/runelite/api/VarClientInt.java @@ -36,20 +36,20 @@ public enum VarClientInt { TOOLTIP_TIMEOUT(1), - /** - * 0 = no tooltip displayed - * 1 = tooltip displaying - */ +/** + * 0 = no tooltip displayed + * 1 = tooltip displaying +*/ TOOLTIP_VISIBLE(2), INPUT_TYPE(5), MEMBERSHIP_STATUS(103), - /** - * -1 = player inventory closed - * 3 = player inventory opened - */ - PLAYER_INVENTORY_OPENED(171), +/** + * -1 = player inventory closed + * 3 = player inventory opened +*/ + PLAYER_INVENTORY_OPENED(171), INVENTORY_TAB(171), diff --git a/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java b/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java index 70f5452387..d9de9eddb1 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java @@ -30,5 +30,5 @@ import net.runelite.api.Actor; @Data public class InteractChanged { - private Actor actor; -} \ No newline at end of file + private Actor actor; +} diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index effa4e462f..12fe00ed39 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -930,7 +930,7 @@ public class WidgetID static final int OURANIA_TELEPORT = 142; // ARCEUUS SPELLS - static final int ARCEUUS_HOME_TELEPORT = 143; + static final int ARCEUUS_HOME_TELEPORT = 143; } static class Pvp @@ -1034,7 +1034,8 @@ public class WidgetID static final int CUSTOM_TEXT_CONTAINER = 33; } - public static class TradeScreen { + public static class TradeScreen + { public static final int SECOND_GROUP_ID = 334; public static final int SECOND_TRADING_WITH = 30; public static final int SECOND_MY_OFFER = 23; @@ -1043,7 +1044,8 @@ public class WidgetID public static final int SECOND_ACCEPT_TEXT = 25; } - public static class DuelConfig { + public static class DuelConfig + { public static final int CONFIG_GROUP_IP = 482; public static final int TITLE = 35; public static final int OPPONENT_ATT = 9; @@ -1052,7 +1054,8 @@ public class WidgetID public static final int OPPONENT_HP = 21; } - public static class DuelResult { + public static class DuelResult + { public static final int RESULT_GROUP_ID = 372; public static final int TITLE = 16; public static final int TOTAL_STAKED = 32; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 51c771c0c5..a059fd9d49 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -502,8 +502,8 @@ public enum WidgetInfo PVP_BOUNTY_HUNTER_INFO(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.BOUNTY_HUNTER_INFO), PVP_KILLDEATH_COUNTER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.KILLDEATH_RATIO), - SPELLBOOK_FILTERED_BOUNDS(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.FILTERED_SPELLS_BOUNDS), - + SPELLBOOK_FILTERED_BOUNDS(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.FILTERED_SPELLS_BOUNDS), + /* STANDARD SPELL BOOK WIDGETS*/ SPELL_LUMBRIDGE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.LUMBRIDGE_HOME_TELEPORT), SPELL_WIND_STRIKE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.WIND_STRIKE), From f8ee0c6775309c547330cfa7caf45ff9b6973666 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Fri, 17 May 2019 01:28:14 +0100 Subject: [PATCH 11/78] Update EasyscapePlugin.java --- .../net/runelite/client/plugins/easyscape/EasyscapePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index a0f6a66712..ef4741434f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -301,7 +301,7 @@ public class EasyscapePlugin extends Plugin { } if (config.getGlory()) { - if (target.toLowerCase().contains("amulet of glory")) { + if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) { switch (config.getGloryMode()) { case EDGEVILLE: swap(client, GloryMode.EDGEVILLE.toString(), option, target); From 7988b785ac307ccac165e7daa027caf1d617b735 Mon Sep 17 00:00:00 2001 From: Ganom Date: Thu, 16 May 2019 23:30:28 -0400 Subject: [PATCH 12/78] Update GameTimer.java --- .../client/plugins/timers/GameTimer.java | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java index f846c8718b..dcd739fad6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java @@ -49,10 +49,7 @@ enum GameTimer HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Half Teleblock", 150, ChronoUnit.SECONDS, true), DMM_FULLTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Full Teleblock", 150, ChronoUnit.SECONDS, true), DMM_HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Half Teleblock", 75, ChronoUnit.SECONDS, true), - ANTIVENOMPLUS(ItemID.ANTIVENOM4_12913, GameTimerImageType.ITEM, "Anti-venom+", 3, ChronoUnit.MINUTES), - ANTIVENOMPLUS_ANTIPOSION(ItemID.SUPERANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom+ Antipoison", 15, ChronoUnit.MINUTES, 3), SUPERANTIFIRE(ItemID.SUPER_ANTIFIRE_POTION4, GameTimerImageType.ITEM, "Super antifire", 3, ChronoUnit.MINUTES), - ANTIDOTEPLUSPLUS(ItemID.ANTIDOTE4_5952, GameTimerImageType.ITEM, "Antidote++", 12, ChronoUnit.MINUTES), BIND(SpriteID.SPELL_BIND, GameTimerImageType.SPRITE, "Bind", GraphicID.BIND, 5, ChronoUnit.SECONDS, true), HALFBIND(SpriteID.SPELL_BIND, GameTimerImageType.SPRITE, "Half Bind", GraphicID.BIND, 2500, ChronoUnit.MILLIS, true), SNARE(SpriteID.SPELL_SNARE, GameTimerImageType.SPRITE, "Snare", GraphicID.SNARE, 10, ChronoUnit.SECONDS, true), @@ -65,22 +62,18 @@ enum GameTimer ICEBARRAGE(SpriteID.SPELL_ICE_BARRAGE, GameTimerImageType.SPRITE, "Ice barrage", GraphicID.ICE_BARRAGE, 20, ChronoUnit.SECONDS, true), IMBUEDHEART(ItemID.IMBUED_HEART, GameTimerImageType.ITEM, "Imbued heart", GraphicID.IMBUED_HEART, 420, ChronoUnit.SECONDS), VENGEANCE(SpriteID.SPELL_VENGEANCE, GameTimerImageType.SPRITE, "Vengeance", 30, ChronoUnit.SECONDS), - ANTIDOTEPLUS(ItemID.ANTIDOTE4, GameTimerImageType.ITEM, "Antidote+", 518, ChronoUnit.SECONDS), - ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom", 1, ChronoUnit.MINUTES), - ANTIVENOM_ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom Antipoison", 12, ChronoUnit.MINUTES, 1), EXSUPERANTIFIRE(ItemID.EXTENDED_SUPER_ANTIFIRE4, GameTimerImageType.ITEM, "Extended Super AntiFire", 6, ChronoUnit.MINUTES), - SANFEW(ItemID.SANFEW_SERUM4, GameTimerImageType.ITEM, "Sanfew serum", 6, ChronoUnit.MINUTES), OVERLOAD_RAID(ItemID.OVERLOAD_4_20996, GameTimerImageType.ITEM, "Overload", 5, ChronoUnit.MINUTES, true), PRAYER_ENHANCE(ItemID.PRAYER_ENHANCE_4, GameTimerImageType.ITEM, "Prayer enhance", 290, ChronoUnit.SECONDS, true), GOD_WARS_ALTAR(SpriteID.SKILL_PRAYER, GameTimerImageType.SPRITE, "God wars altar", 10, ChronoUnit.MINUTES), - ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Antipoison", 90, ChronoUnit.SECONDS), - SUPERANTIPOISON(ItemID.SUPERANTIPOISON4, GameTimerImageType.ITEM, "Superantipoison", 346, ChronoUnit.SECONDS), CHARGE(SpriteID.SPELL_CHARGE, GameTimerImageType.SPRITE, "Charge", 6, ChronoUnit.MINUTES), STAFF_OF_THE_DEAD(ItemID.STAFF_OF_THE_DEAD, GameTimerImageType.ITEM, "Staff of the Dead", 1, ChronoUnit.MINUTES), ABYSSAL_SIRE_STUN(ItemID.ABYSSAL_ORPHAN, GameTimerImageType.ITEM, "Abyssal Sire Stun", 30, ChronoUnit.SECONDS, true), HOME_TELEPORT(SpriteID.SPELL_LUMBRIDGE_HOME_TELEPORT, GameTimerImageType.SPRITE, "Home Teleport", 30, ChronoUnit.MINUTES), MINIGAME_TELEPORT(SpriteID.TAB_QUESTS_RED_MINIGAMES, GameTimerImageType.SPRITE, "Minigame Teleport", 20, ChronoUnit.MINUTES), - SKULL(SpriteID.PLAYER_KILLER_SKULL_523, GameTimerImageType.SPRITE, "Skull", 20, ChronoUnit.MINUTES); + SKULL(SpriteID.PLAYER_KILLER_SKULL_523, GameTimerImageType.SPRITE, "Skull", 20, ChronoUnit.MINUTES), + ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Antipoison"), + ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom"); @Getter private final Duration duration; @@ -90,12 +83,11 @@ enum GameTimer private final String description; @Getter private final boolean removedOnDeath; - @Getter - private final Duration initialDelay; + private final int imageId; private final GameTimerImageType imageType; - GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit, long delay, boolean removedOnDeath) + GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit, boolean removedOnDeath) { this.description = description; this.graphicId = graphicId; @@ -103,12 +95,6 @@ enum GameTimer this.imageId = imageId; this.imageType = idType; this.removedOnDeath = removedOnDeath; - this.initialDelay = Duration.of(delay, unit); - } - - GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit, boolean removedOnDeath) - { - this(imageId, idType, description, graphicId, time, unit, 0, removedOnDeath); } GameTimer(int imageId, GameTimerImageType idType, String description, long time, ChronoUnit unit, boolean removeOnDeath) @@ -116,19 +102,19 @@ enum GameTimer this(imageId, idType, description, null, time, unit, removeOnDeath); } - GameTimer(int imageId, GameTimerImageType idType, String description, long time, ChronoUnit unit) - { - this(imageId, idType, description, null, time, unit, false); - } - GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit) { this(imageId, idType, description, graphicId, time, unit, false); } - GameTimer(int imageId, GameTimerImageType idType, String description, long time, ChronoUnit unit, long delay) + GameTimer(int imageId, GameTimerImageType idType, String description, long time, ChronoUnit unit) { - this(imageId, idType, description, null, time, unit, delay, false); + this(imageId, idType, description, null, time, unit, false); + } + + GameTimer(int imageId, GameTimerImageType idType, String description) + { + this(imageId, idType, description, null, 1, ChronoUnit.MILLIS, false); } BufferedImage getImage(ItemManager itemManager, SpriteManager spriteManager) From b58fc451ea149949e8d357acd9169d509341c20c Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 01:38:22 +0200 Subject: [PATCH 13/78] Enable checkstyle in travis --- travis/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis/settings.xml b/travis/settings.xml index 06f13271e0..99ee60758a 100644 --- a/travis/settings.xml +++ b/travis/settings.xml @@ -258,7 +258,7 @@ under the License. true - true + false false From 88f286c70515c99b456293d4e6fccf10fed813cb Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 02:16:34 +0200 Subject: [PATCH 14/78] fix antidrag copyright/config imports --- .../plugins/antidrag/AntiDragConfig.java | 3 +-- .../plugins/antidrag/AntiDragPlugin.java | 25 +------------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java index 5caf44293b..58c959eb52 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, DennisDeV * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.antidrag; -import net.runelite.api.Constants; import java.awt.Color; import java.awt.event.KeyEvent; import net.runelite.client.config.Alpha; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java index 6b8584a57a..3c1c3eced0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java @@ -23,30 +23,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package net.runelite.client.plugins.antidrag; -/* - * Copyright (c) 2018, https://runelitepl.us - * 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. - */ + import com.google.inject.Provides; import javax.inject.Inject; import net.runelite.api.Client; From 0d8dbfee383e20fa318285da22ffb50ffa04ee3c Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 02:27:16 +0200 Subject: [PATCH 15/78] checkstyle --- .../src/main/java/net/runelite/api/AnimationID.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index 6c0e3662f8..f9201118df 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -175,7 +175,7 @@ public final class AnimationID public static final int VORKATH_ACID_ATTACK = 7957; public static final int BLACKJACK_KO = 838; public static final int VETION_EARTHQUAKE = 5507; - public static final int ZULRAH_DEATH = 5804; + public static final int ZULRAH_DEATH = 5804; // Farming public static final int FARMING_HARVEST_FRUIT_TREE = 2280; @@ -214,8 +214,8 @@ public final class AnimationID // POH Animations public static final int INCENSE_BURNER = 3687; public static final int LOW_LEVEL_MAGIC_ATTACK = 1162; - public static final int HIGH_LEVEL_MAGIC_ATTACK = 1167; - public static final int BLOWPIPE_ATTACK = 5061; + public static final int HIGH_LEVEL_MAGIC_ATTACK = 1167; + public static final int BLOWPIPE_ATTACK = 5061; // Hydra public static final int HYDRA_POISON_1 = 8234; From 7740b7a85ee8ea570b605fcf6163c17316364149 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 03:04:15 +0200 Subject: [PATCH 16/78] checkstyle - mixin processor --- .../mixinprocessor/MethodGarbageValue.java | 6 +++--- .../mixinprocessor/MixinProcessorMojo.java | 15 ++++----------- .../mixinprocessor/enums/InjectionType.java | 2 +- .../generators/PatchGenerator.java | 2 -- .../generators/StaticGenerator.java | 18 ++++++------------ .../generators/StaticStageTwoGenerator.java | 1 - .../parsers/GamepackDownloader.java | 8 ++++---- .../mixinprocessor/parsers/HooksParser.java | 4 ++-- .../parsers/MethodAnnotationParser.java | 4 ++-- .../AnnotationRemoverTransformer.java | 2 +- .../transformers/AsmBaseTransformer.java | 7 ++++--- .../AsmMethodGarbageTransformer.java | 6 ++---- .../AsmMethodSignatureTransformer.java | 2 +- .../AsmStaticUsageTransformer.java | 7 +------ .../transformers/DoNothingTransformer.java | 4 ++-- .../ProvidedRemoverTransformer.java | 12 ++++++------ .../mixinprocessor/util/RefUtils.java | 18 +++++------------- .../mixinprocessor/util/WebUtils.java | 11 +++++++---- 18 files changed, 51 insertions(+), 78 deletions(-) diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MethodGarbageValue.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MethodGarbageValue.java index 6cfb99110e..8dc0202ada 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MethodGarbageValue.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MethodGarbageValue.java @@ -33,11 +33,11 @@ public class MethodGarbageValue public MethodGarbageValue(int value) { - if(value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) + if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) { type = "B"; } - else if(value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) + else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) { type = "S"; } @@ -60,6 +60,6 @@ public class MethodGarbageValue public String toString() { - return "MethodGarbageValue[type="+getType()+",value="+getValue()+"]"; + return "MethodGarbageValue[type=" + getType() + ",value=" + getValue() + "]"; } } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MixinProcessorMojo.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MixinProcessorMojo.java index 99dd5fc32e..b28f09abb3 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MixinProcessorMojo.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/MixinProcessorMojo.java @@ -33,10 +33,6 @@ import io.sigpipe.jbsdiff.Patch; import javassist.ClassPool; import javassist.CtClass; import javassist.LoaderClassPath; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import us.runelitepl.mixinprocessor.generators.AnnotationProcessor; import us.runelitepl.mixinprocessor.generators.PatchGenerator; @@ -50,14 +46,11 @@ import us.runelitepl.mixinprocessor.util.JavassistUtils; import us.runelitepl.mixinprocessor.util.RefUtils; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; - -import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -111,9 +104,9 @@ public class MixinProcessorMojo public static HashMap methodGarbageValues = new HashMap<>(); - public static HashMap gamepack = new HashMap<>(); + private static HashMap gamepack = new HashMap<>(); - public static final int BUFFER_SIZE = 1024 * 1024 * 4; + private static final int BUFFER_SIZE = 1024 * 1024 * 4; public void execute() throws MojoExecutionException @@ -257,7 +250,7 @@ public class MixinProcessorMojo } - public void stderr(String s, Object... format) + private void stderr(String s, Object... format) { getLog().info(String.format(s, format)); } @@ -267,7 +260,7 @@ public class MixinProcessorMojo INST.stderr(s, format); } - static void deleteDir(File file) throws IOException + private static void deleteDir(File file) throws IOException { if (!file.exists()) { diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/enums/InjectionType.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/enums/InjectionType.java index 0ce52fdcd9..7f6296cd2d 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/enums/InjectionType.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/enums/InjectionType.java @@ -31,5 +31,5 @@ public enum InjectionType APPEND, OVERWRITE, PREPEND, - PROVIDED; + PROVIDED } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/PatchGenerator.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/PatchGenerator.java index 106aac77dd..37749c4034 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/PatchGenerator.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/PatchGenerator.java @@ -26,8 +26,6 @@ package us.runelitepl.mixinprocessor.generators; import us.runelitepl.mixinprocessor.transformers.AnnotationRemoverTransformer; -import us.runelitepl.mixinprocessor.transformers.AsmMethodGarbageTransformer; -import us.runelitepl.mixinprocessor.transformers.AsmMethodSignatureTransformer; import us.runelitepl.mixinprocessor.transformers.AsmNameTransformer; import us.runelitepl.mixinprocessor.transformers.AsmStaticUsageTransformer; import us.runelitepl.mixinprocessor.transformers.DoNothingTransformer; diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticGenerator.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticGenerator.java index 3cb1441327..cffacd567e 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticGenerator.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticGenerator.java @@ -25,18 +25,12 @@ package us.runelitepl.mixinprocessor.generators; -import javassist.CannotCompileException; -import javassist.CtClass; -import javassist.NotFoundException; import us.runelitepl.mixinprocessor.MixinProcessorMojo; -import us.runelitepl.mixinprocessor.util.JavassistUtils; import us.runelitepl.mixinprocessor.util.RefUtils; import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodNode; - -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -45,11 +39,11 @@ import java.util.Set; public class StaticGenerator { - public static HashMap> staticMethods = new HashMap<>(); - public static HashMap> staticFields = new HashMap<>(); - public static Set modifiedClasses = new HashSet<>(); + static HashMap> staticMethods = new HashMap<>(); + static HashMap> staticFields = new HashMap<>(); + static Set modifiedClasses = new HashSet<>(); - public void run(byte[] bytecode) throws NotFoundException, IOException, CannotCompileException + public void run(byte[] bytecode) { ClassReader cr = new ClassReader(bytecode); @@ -68,7 +62,7 @@ public class StaticGenerator continue; } String reobbed = RefUtils.reobMethodName(RefUtils.STATICS_STRING, methodName, method.desc); - if(reobbed == null) + if (reobbed == null) { MixinProcessorMojo.log("Failed to reob static method: %s %s", methodName, method.desc); throw new RuntimeException(); @@ -93,7 +87,7 @@ public class StaticGenerator continue; } String reobbed = RefUtils.reobFieldName(RefUtils.STATICS_STRING, fieldName, field.desc); - if(reobbed == null) + if (reobbed == null) { MixinProcessorMojo.log("Failed to reob static field: %s %s", fieldName, field.desc); throw new RuntimeException(); diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticStageTwoGenerator.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticStageTwoGenerator.java index f0c0019943..fcc5ffaf9c 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticStageTwoGenerator.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/generators/StaticStageTwoGenerator.java @@ -36,7 +36,6 @@ import org.objectweb.asm.tree.AnnotationNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.TypeAnnotationNode; -import us.runelitepl.mixinprocessor.MixinProcessorMojo; import us.runelitepl.mixinprocessor.parsers.MethodReflector; import java.util.HashMap; diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/GamepackDownloader.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/GamepackDownloader.java index d10b80823a..b2d1666ad5 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/GamepackDownloader.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/GamepackDownloader.java @@ -48,7 +48,7 @@ public class GamepackDownloader ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(gamepackJarAry)); byte[] buffer = new byte[2048]; ZipEntry entry; - ByteArrayOutputStream fileContent = new ByteArrayOutputStream(1024*1024*4); + ByteArrayOutputStream fileContent = new ByteArrayOutputStream(1024 * 1024 * 4); while ((entry = zipInputStream.getNextEntry()) != null) { if (entry.getName().startsWith("META-INF")) @@ -56,8 +56,8 @@ public class GamepackDownloader continue; } String key = entry.getName().replace(".class", ""); - int len = 0; - while((len = zipInputStream.read(buffer)) > 0) + int len; + while ((len = zipInputStream.read(buffer)) > 0) { fileContent.write(buffer, 0, len); } @@ -83,7 +83,7 @@ public class GamepackDownloader } } - public static String getGamepackUrl() + private static String getGamepackUrl() { return codebase + initial_jar; } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/HooksParser.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/HooksParser.java index 111303da75..52f53d2fa1 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/HooksParser.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/HooksParser.java @@ -71,7 +71,7 @@ public class HooksParser String f_owner = (String) field.get("owner"); long f_decoder = (long) field.getOrDefault("decoder", (long) 1); String f_deobbedOwner = null; - if(f_deobbedName.startsWith("__")) + if (f_deobbedName.startsWith("__")) { continue; } @@ -104,7 +104,7 @@ public class HooksParser String m_deobbedOwner = null; String m_obbedName = (String) method.get("name"); String m_descriptor = (String) method.get("descriptor"); - if(m_deobbedName.startsWith("__")) + if (m_deobbedName.startsWith("__")) { continue; } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/MethodAnnotationParser.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/MethodAnnotationParser.java index fbb68d444c..0a9bb6b9e8 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/MethodAnnotationParser.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/parsers/MethodAnnotationParser.java @@ -51,7 +51,7 @@ public class MethodAnnotationParser public void run() throws ClassNotFoundException { - for(CtMethod method : patch.getDeclaredMethods()) + for (CtMethod method : patch.getDeclaredMethods()) { Object[] annotations = method.getAnnotations(); @@ -112,7 +112,7 @@ public class MethodAnnotationParser } } - if(reobfuscate) + if (reobfuscate) { MixinProcessorMojo.log("Marking: %s %s %s", method.getDeclaringClass().getSimpleName(), methodName, RefUtils.reobMethodDescriptor(method.getSignature())); diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AnnotationRemoverTransformer.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AnnotationRemoverTransformer.java index af745a80a3..cf0f588b8b 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AnnotationRemoverTransformer.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AnnotationRemoverTransformer.java @@ -96,7 +96,7 @@ public class AnnotationRemoverTransformer extends AsmBaseTransformer return cw.toByteArray(); } - public static String makeAnnotationDescriptor(String s) + static String makeAnnotationDescriptor(String s) { return "Lus/runelitepl/mixinprocessor/annotations/" + s + ";"; } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmBaseTransformer.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmBaseTransformer.java index 5c44dbf62d..fa3166a7cf 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmBaseTransformer.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmBaseTransformer.java @@ -34,11 +34,12 @@ public abstract class AsmBaseTransformer implements Opcodes protected final ArrayList validMethods = new ArrayList<>(); protected final ArrayList validFields = new ArrayList<>(); - + + // CHECKSTYLE:OFF protected void buildMethodList(){} - protected void buildFieldList(){} - + // CHECKSTYLE:ON + public abstract byte[] transform(); } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodGarbageTransformer.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodGarbageTransformer.java index e6532132ef..4b190bece0 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodGarbageTransformer.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodGarbageTransformer.java @@ -32,8 +32,6 @@ import org.objectweb.asm.MethodVisitor; import us.runelitepl.mixinprocessor.MethodGarbageValue; import us.runelitepl.mixinprocessor.MixinProcessorMojo; import us.runelitepl.mixinprocessor.util.RefUtils; - -import java.sql.Ref; import java.util.HashMap; public class AsmMethodGarbageTransformer extends AsmBaseTransformer @@ -74,13 +72,13 @@ public class AsmMethodGarbageTransformer extends AsmBaseTransformer // mv.visitLdcInsn(BIPUSH, constant); // call super method with new descriptor - if(RefUtils.shouldReobMethod(owner, name, desc)) + if (RefUtils.shouldReobMethod(owner, name, desc)) { String nc = RefUtils.reobMethodName(owner, name, desc).split(" ")[0]; String nn = RefUtils.reobMethodName(owner, name, desc).split(" ")[1]; String nd = RefUtils.reobMethodDescriptor(desc); MethodGarbageValue value; - if((value = MixinProcessorMojo.methodGarbageValues.getOrDefault(String.format("%s.%s%s", + if ((value = MixinProcessorMojo.methodGarbageValues.getOrDefault(String.format("%s.%s%s", nc, nn, nd), null)) != null) { switch (value.getType()) diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodSignatureTransformer.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodSignatureTransformer.java index 56138d4324..5cb971d12e 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodSignatureTransformer.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmMethodSignatureTransformer.java @@ -72,7 +72,7 @@ public class AsmMethodSignatureTransformer extends AsmBaseTransformer private String fixMethodDesc(String className, String name, String desc) { - if(className.startsWith(RefUtils.TYPE_PREFIX)) + if (className.startsWith(RefUtils.TYPE_PREFIX)) { className = className.substring(RefUtils.TYPE_PREFIX.length()); } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmStaticUsageTransformer.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmStaticUsageTransformer.java index 2f0f1b8a35..76e40fdfe9 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmStaticUsageTransformer.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/AsmStaticUsageTransformer.java @@ -32,11 +32,6 @@ import org.objectweb.asm.MethodVisitor; import us.runelitepl.mixinprocessor.MixinProcessorMojo; import us.runelitepl.mixinprocessor.util.RefUtils; -import static org.objectweb.asm.Opcodes.ASM6; -import static org.objectweb.asm.Opcodes.GETSTATIC; -import static org.objectweb.asm.Opcodes.INVOKESTATIC; -import static org.objectweb.asm.Opcodes.PUTSTATIC; - public class AsmStaticUsageTransformer extends AsmBaseTransformer { @@ -89,7 +84,7 @@ public class AsmStaticUsageTransformer extends AsmBaseTransformer @Override public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { - if(opcode == INVOKESTATIC && owner.endsWith(RefUtils.STATICS_STRING)) + if (opcode == INVOKESTATIC && owner.endsWith(RefUtils.STATICS_STRING)) { String originalOwner = owner.replace(TYPE_PREFIX, ""); String temp = RefUtils.reobMethodName(RefUtils.STATICS_STRING, name, descriptor); diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/DoNothingTransformer.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/DoNothingTransformer.java index b5174d3bd7..507019586a 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/DoNothingTransformer.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/DoNothingTransformer.java @@ -47,10 +47,10 @@ public class DoNothingTransformer extends AsmBaseTransformer ClassReader cr = new ClassReader(bytecode); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); - + // CHECKSTYLE:OFF cr.accept(new ClassVisitor(ASM6, cw) {}, 0); - + //CHECKSTYLE:ON return cw.toByteArray(); } } \ No newline at end of file diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/ProvidedRemoverTransformer.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/ProvidedRemoverTransformer.java index 8334cad1cb..f34b6dea52 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/ProvidedRemoverTransformer.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/transformers/ProvidedRemoverTransformer.java @@ -53,22 +53,22 @@ public class ProvidedRemoverTransformer extends AsmBaseTransformer ClassNode node = new ClassNode(); cr.accept(node, 0); - for(Object obj : node.methods) + for (Object obj : node.methods) { MethodNode method = (MethodNode) obj; - if(method == null) + if (method == null) { MixinProcessorMojo.log("ProvidedRemoverTransformer: Method null?"); continue; } - if(method.visibleAnnotations == null) + if (method.visibleAnnotations == null) { continue; } - for(Object obj2 : method.visibleAnnotations) + for (Object obj2 : method.visibleAnnotations) { AnnotationNode annot = (AnnotationNode) obj2; - if(annot.desc.equals(AnnotationRemoverTransformer.makeAnnotationDescriptor("Provided"))) + if (annot.desc.equals(AnnotationRemoverTransformer.makeAnnotationDescriptor("Provided"))) { validMethods.add(method.access + " " + method.desc + " " + method.name); } @@ -88,7 +88,7 @@ public class ProvidedRemoverTransformer extends AsmBaseTransformer public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - if(validMethods.contains(access + " " + desc + " " + name)) + if (validMethods.contains(access + " " + desc + " " + name)) { return null; } diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/RefUtils.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/RefUtils.java index 11b94125a0..a03ba17937 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/RefUtils.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/RefUtils.java @@ -125,7 +125,7 @@ public class RefUtils public static String reobMethodName(String owner, String deob, String signature) { String prefix = ""; - if(owner.startsWith(RefUtils.TYPE_PREFIX)) + if (owner.startsWith(RefUtils.TYPE_PREFIX)) { owner = owner.substring(RefUtils.TYPE_PREFIX.length()); } @@ -169,11 +169,7 @@ public class RefUtils i++; } } - if (i == 1) - { - return true; - } - return false; + return i == 1; } @Deprecated @@ -187,11 +183,7 @@ public class RefUtils i++; } } - if (i == 1) - { - return true; - } - return false; + return i == 1; } public static boolean shouldReobField(String owner, String deob, String desc) @@ -205,7 +197,7 @@ public class RefUtils public static boolean shouldReobMethod(String owner, String deob, String desc) { - if(owner.startsWith(RefUtils.TYPE_PREFIX)) + if (owner.startsWith(RefUtils.TYPE_PREFIX)) { owner = owner.substring(RefUtils.TYPE_PREFIX.length()); } @@ -275,7 +267,7 @@ public class RefUtils { obbedName = className; } - deobbed.append("L" + obbedName + ";"); + deobbed.append("L").append(obbedName ).append(";"); strIndex += sigPart.length(); } catch (StringIndexOutOfBoundsException ex) diff --git a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/WebUtils.java b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/WebUtils.java index 0b4364be6b..f4a89bf7f1 100644 --- a/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/WebUtils.java +++ b/extended-mixin-processor/src/main/java/us/runelitepl/mixinprocessor/util/WebUtils.java @@ -50,14 +50,17 @@ public class WebUtils return pageText; } - public static byte[] downloadFile(String urlText) throws IOException { + public static byte[] downloadFile(String urlText) throws IOException + { URL url = new URL(urlText); ByteArrayOutputStream output = new ByteArrayOutputStream(); - try (InputStream inputStream = url.openStream()) { - int n = 0; + try (InputStream inputStream = url.openStream()) + { + int n; byte [] buffer = new byte[ 1024 ]; - while (-1 != (n = inputStream.read(buffer))) { + while (-1 != (n = inputStream.read(buffer))) + { output.write(buffer, 0, n); } } From 60e92469ddacc77d59618b4caa31b7ac3ef312c7 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 03:32:42 +0200 Subject: [PATCH 17/78] checkstyle - extended-mixins --- .../java/us/runelitepl/mixins/Client.java | 137 +++++++++--------- .../java/us/runelitepl/mixins/Player.java | 2 +- .../main/java/us/runelitepl/mixins/Scene.java | 4 +- .../java/us/runelitepl/mixins/_Statics_.java | 4 +- 4 files changed, 73 insertions(+), 74 deletions(-) diff --git a/extended-mixins/src/main/java/us/runelitepl/mixins/Client.java b/extended-mixins/src/main/java/us/runelitepl/mixins/Client.java index 048876ffe7..1038a3a516 100644 --- a/extended-mixins/src/main/java/us/runelitepl/mixins/Client.java +++ b/extended-mixins/src/main/java/us/runelitepl/mixins/Client.java @@ -41,170 +41,170 @@ import java.util.List; public class Client { - + @Provided public static boolean isHidingEntities; - + @Provided public static boolean hideLocalPlayer2D; - + @Provided public static boolean hideLocalPlayer; - + @Provided public static boolean hidePlayers2D; - + @Provided public static boolean hidePlayers; - + @Provided public static boolean hideAttackers; - + @Provided public static boolean hideProjectiles; - + @Provided public static boolean hideNPCs2D; - + @Provided public static boolean hideNPCs; - + @Provided public static boolean hideFriends; - + @Provided public static boolean hideClanMates; - + @Inject public static Client INSTANCE; - + @Inject public static boolean printMenuActions; - + @Provided public static int oldMenuEntryCount; - + @Reobfuscate @Provided static boolean renderSelf; - + @Provided public static final int[] rl$modelViewportXs = new int[0]; - + @Provided public static final int[] rl$modelViewportYs = new int[0]; - + @Prepend private void prepend$rl$$init() { INSTANCE = this; printMenuActions = false; } - + @Inject public void toggleRenderSelf() { renderSelf = !renderSelf; } - + @Provided public int getMenuOptionCount() { throw new RuntimeException(); } - + @Provided public String[] getMenuOptions() { throw new RuntimeException(); } - + @Provided public String[] getMenuTargets() { throw new RuntimeException(); } - + @Provided public int[] getMenuIdentifiers() { throw new RuntimeException(); } - + @Provided public int[] getMenuTypes() { throw new RuntimeException(); } - + @Provided public int[] getMenuActionParams0() { throw new RuntimeException(); } - + @Provided public int[] getMenuActionParams1() { throw new RuntimeException(); } - + @Provided public boolean[] getMenuForceLeftClick() { throw new RuntimeException(); } - + @Provided public void setMenuOptionCount(int i) { throw new RuntimeException(); } - + @Provided public Callbacks getCallbacks() { throw new RuntimeException(); } - + @Provided public RSCollisionData[] getRsCollisionMaps() { throw new RuntimeException(); } - + @Provided public RSDeque getProjectilesDeque() { throw new RuntimeException(); } - + @Overwrite public List getProjectiles() { List list = new java.util.ArrayList(); RSNode head = getProjectilesDeque().getHead(); for (Node node = ((Node) head).getNext(); - node != head; - node = node.getNext()) + node != head; + node = node.getNext()) { list.add(node); } return list; } - + @Inject public void setPrintMenuActions(boolean b) { printMenuActions = b; } - + @Overwrite public RSCollisionData[] getCollisionMaps() { return getRsCollisionMaps(); } - + @Overwrite public void setMenuEntries(MenuEntry[] arrmenuEntry) { @@ -242,7 +242,7 @@ public class Client } while (true); } - + @Overwrite public static void onMenuOptionsChanged(int n2) { @@ -254,28 +254,28 @@ public class Client return; } net.runelite.api.events.MenuEntryAdded menuEntryAdded = - new net.runelite.api.events.MenuEntryAdded(INSTANCE.getMenuOptions()[n3 - 1], - INSTANCE.getMenuTargets()[n3 - 1], - INSTANCE.getMenuTypes()[n3 - 1], - INSTANCE.getMenuIdentifiers()[n3 - 1], - INSTANCE.getMenuActionParams0()[n3 - 1], - INSTANCE.getMenuActionParams1()[n3 - 1]); + new net.runelite.api.events.MenuEntryAdded(INSTANCE.getMenuOptions()[n3 - 1], + INSTANCE.getMenuTargets()[n3 - 1], + INSTANCE.getMenuTypes()[n3 - 1], + INSTANCE.getMenuIdentifiers()[n3 - 1], + INSTANCE.getMenuActionParams0()[n3 - 1], + INSTANCE.getMenuActionParams1()[n3 - 1]); INSTANCE.getCallbacks().post(menuEntryAdded); } - + @Overwrite public static void copy$processClientError(String s, Throwable e, byte b) { System.err.println("[RL+] Error thrown: " + s); e.printStackTrace(); } - + @Inject public net.runelite.api.MouseRecorder getMouseRecorder() { return _Statics_.mouseRecorder; } - + @Inject public boolean boundingboxCheck2(net.runelite.api.Model model, int n2, int n3, int n4) { @@ -349,7 +349,7 @@ public class Client } return false; } - + @Overwrite public void checkClickbox(net.runelite.api.Model model, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int n9, long l2) { @@ -441,10 +441,10 @@ public class Client int n29 = rl$modelViewportXs[n10]; int n30 = rl$modelViewportXs[n24]; if (n25 != -5000 && n26 != -5000 && n27 != -5000 && (bl5 = (n23 = (n22 = rSModel.isClickable() ? 20 - : 5) + n11) < n28 && n23 < n29 && n23 < n30 ? false - : ((n23 = n11 - n22) > n28 && n23 > n29 && n23 > n30 ? false - : ((n23 = n22 + n14) < n25 && n23 < n26 && n23 < n27 ? false - : (n23 = n14 - n22) <= n25 || n23 <= n26 || n23 <= n27)))) + : 5) + n11) < n28 && n23 < n29 && n23 < n30 ? false + : ((n23 = n11 - n22) > n28 && n23 > n29 && n23 > n30 ? false + : ((n23 = n22 + n14) < n25 && n23 < n26 && n23 < n27 ? false + : (n23 = n14 - n22) <= n25 || n23 <= n26 || n23 <= n27)))) { this.addHashAtMouse(l2); return; @@ -453,91 +453,90 @@ public class Client ++n13; } } - + @Provided public boolean getViewportContainsMouse() { throw new RuntimeException(); } - + @Provided public void addHashAtMouse(long l) { throw new RuntimeException(); } - + @Provided public int getCameraPitch() { throw new RuntimeException(); } - + @Provided public int getCameraYaw() { throw new RuntimeException(); } - + @Provided public int getCenterX() { throw new RuntimeException(); } - + @Provided public int getCenterY() { throw new RuntimeException(); } - + @Provided public int getViewportMouseX() { throw new RuntimeException(); } - + @Provided public int getViewportMouseY() { throw new RuntimeException(); } - + @Provided public int get3dZoom() { throw new RuntimeException(); } - + @Provided public static int rl$rot1(int a, int b, int c, int d) { throw new RuntimeException(); } - + @Provided public static int rl$rot2(int a, int b, int c, int d) { throw new RuntimeException(); } - + @Provided public static int rl$rot3(int a, int b, int c, int d) { throw new RuntimeException(); } - + @Provided public static int rl$rot4(int a, int b, int c, int d) { throw new RuntimeException(); } - + @Inject - public void invokeMenuAction(int actionParam, int widgetId, int opcode, int targetId, String menuOption, - String menuTarget, int mouseX, int mouseY) + public void invokeMenuAction(int actionParam, int widgetId, int opcode, int targetId, String menuOption, String menuTarget, int mouseX, int mouseY) { _Statics_.menuAction(actionParam, widgetId, opcode, targetId, menuOption, menuTarget, mouseX, mouseY); } - + } \ No newline at end of file diff --git a/extended-mixins/src/main/java/us/runelitepl/mixins/Player.java b/extended-mixins/src/main/java/us/runelitepl/mixins/Player.java index 6039aedf28..074b52364c 100644 --- a/extended-mixins/src/main/java/us/runelitepl/mixins/Player.java +++ b/extended-mixins/src/main/java/us/runelitepl/mixins/Player.java @@ -51,7 +51,7 @@ public class Player @Overwrite public SkullIcon getSkullIcon() { - switch(getHeadIconPk()) + switch (getHeadIconPk()) { case 0: return SkullIcon.SKULL; diff --git a/extended-mixins/src/main/java/us/runelitepl/mixins/Scene.java b/extended-mixins/src/main/java/us/runelitepl/mixins/Scene.java index 646050b350..53198e5101 100644 --- a/extended-mixins/src/main/java/us/runelitepl/mixins/Scene.java +++ b/extended-mixins/src/main/java/us/runelitepl/mixins/Scene.java @@ -43,10 +43,10 @@ public class Scene return true; } - if(renderable instanceof RSPlayer) + if (renderable instanceof RSPlayer) { RSPlayer p = (RSPlayer) renderable; - if(Client.hideClanMates && p.isClanMember()) + if (Client.hideClanMates && p.isClanMember()) { return false; } diff --git a/extended-mixins/src/main/java/us/runelitepl/mixins/_Statics_.java b/extended-mixins/src/main/java/us/runelitepl/mixins/_Statics_.java index 6bb32f9feb..f686506dd3 100644 --- a/extended-mixins/src/main/java/us/runelitepl/mixins/_Statics_.java +++ b/extended-mixins/src/main/java/us/runelitepl/mixins/_Statics_.java @@ -41,10 +41,10 @@ public class _Statics_ static final void prepend$menuAction(int actionParam, int widgetId, int opcode, int targetId, String menuOption, String menuTarget, int mouseX, int mouseY) { - if(Client.printMenuActions) + if (Client.printMenuActions) { int printOpcode = opcode; - if(opcode >= 2000) + if (opcode >= 2000) { printOpcode -= 2000; } From 34b16cf300ad6e0e6693b832942bd207aa1d68e9 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 03:33:05 +0200 Subject: [PATCH 18/78] checkstyle - blackjack/player indicators/shayzien infirmary --- .../plugins/blackjack/BlackjackPlugin.java | 155 +++++++----- .../PlayerIndicatorsMinimapOverlay.java | 45 ++-- .../PlayerIndicatorsOverlay.java | 52 ++-- .../PlayerIndicatorsPlugin.java | 20 +- .../PlayerIndicatorsService.java | 18 +- .../PlayerIndicatorsTileOverlay.java | 5 - .../ShayzienInfirmaryOverlay.java | 197 +++++++-------- .../ShayzienInfirmaryPlugin.java | 239 +++++++++--------- 8 files changed, 354 insertions(+), 377 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java index 72e3735318..c3a8a0876b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java @@ -46,88 +46,107 @@ import net.runelite.client.plugins.PluginType; * Authors gazivodag longstreet */ @PluginDescriptor( - name = "Blackjack", - description = "Uses chat messages and tick timers instead of animations to read", - tags = {"blackjack", "thieving"}, - type = PluginType.UTILITY + name = "Blackjack", + description = "Uses chat messages and tick timers instead of animations to read", + tags = {"blackjack", "thieving"}, + type = PluginType.UTILITY ) @Singleton @Slf4j -public class BlackjackPlugin extends Plugin { +public class BlackjackPlugin extends Plugin +{ - @Inject - Client client; + @Inject + Client client; - private static long timeSinceKnockout; - private static long timeSinceAggro; + private static long timeSinceKnockout; + private static long timeSinceAggro; - @Getter - private static long currentGameTick; + @Getter + private static long currentGameTick; - @Override - public void configure(Binder binder) { - } + @Override + public void configure(Binder binder) + { + } - @Override - protected void startUp() throws Exception { - currentGameTick = 0; - } + @Override + protected void startUp() throws Exception + { + currentGameTick = 0; + } - @Override - protected void shutDown() throws Exception { - currentGameTick = 0; - } + @Override + protected void shutDown() throws Exception + { + currentGameTick = 0; + } - @Subscribe - public void onGameTick(GameTick gameTick) { - currentGameTick++; - } + @Subscribe + public void onGameTick(GameTick gameTick) + { + currentGameTick++; + } - @Subscribe - public void onChatMessage(ChatMessage chatMessage) { - if (chatMessage.getType() == ChatMessageType.SPAM) { - if (chatMessage.getMessage().equals("You smack the bandit over the head and render them unconscious.")) { - timeSinceKnockout = getCurrentGameTick(); - } - if (chatMessage.getMessage().equals("Your blow only glances off the bandit's head.")) { - timeSinceAggro = getCurrentGameTick(); - } - } - } + @Subscribe + public void onChatMessage(ChatMessage chatMessage) + { + if (chatMessage.getType() == ChatMessageType.SPAM) + { + if (chatMessage.getMessage().equals("You smack the bandit over the head and render them unconscious.")) + { + timeSinceKnockout = getCurrentGameTick(); + } + if (chatMessage.getMessage().equals("Your blow only glances off the bandit's head.")) + { + timeSinceAggro = getCurrentGameTick(); + } + } + } - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) { - String target = menuEntryAdded.getTarget().toLowerCase(); - if ((target.contains("bandit") | target.contains("menaphite thug"))) { - Quest quest = Quest.THE_FEUD; - if (quest.getState(client) == QuestState.FINISHED) { - if (currentGameTick < (timeSinceKnockout + 4)) { - stripSpecificEntries("pickpocket"); - } - if (currentGameTick < (timeSinceAggro + 4)) { - stripSpecificEntries("pickpocket"); - } - stripSpecificEntries("knock-out"); - } - } - } + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) + { + String target = menuEntryAdded.getTarget().toLowerCase(); + if ((target.contains("bandit") | target.contains("menaphite thug"))) + { + Quest quest = Quest.THE_FEUD; + if (quest.getState(client) == QuestState.FINISHED) + { + if (currentGameTick < (timeSinceKnockout + 4)) + { + stripSpecificEntries("pickpocket"); + } + if (currentGameTick < (timeSinceAggro + 4)) + { + stripSpecificEntries("pickpocket"); + } + stripSpecificEntries("knock-out"); + } + } + } - private void stripSpecificEntries(String exceptFor) { - MenuEntry[] currentEntires = client.getMenuEntries(); - MenuEntry[] newEntries = new MenuEntry[2]; + private void stripSpecificEntries(String exceptFor) + { + MenuEntry[] currentEntires = client.getMenuEntries(); + MenuEntry[] newEntries = new MenuEntry[2]; - for (MenuEntry currentEntry : currentEntires) { - if (currentEntry.getOption().toLowerCase().equals(exceptFor.toLowerCase())) { - newEntries[1] = currentEntry; - } - if (currentEntry.getOption().toLowerCase().equals("lure")) { - newEntries[0] = currentEntry; - } - } + for (MenuEntry currentEntry : currentEntires) + { + if (currentEntry.getOption().toLowerCase().equals(exceptFor.toLowerCase())) + { + newEntries[1] = currentEntry; + } + if (currentEntry.getOption().toLowerCase().equals("lure")) + { + newEntries[0] = currentEntry; + } + } - if (newEntries[0] != null && newEntries[1] != null) { - client.setMenuEntries(newEntries); - } - } + if (newEntries[0] != null && newEntries[1] != null) + { + client.setMenuEntries(newEntries); + } + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java index 10e722ea01..32f4b3c07b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java @@ -30,10 +30,9 @@ import java.awt.Graphics2D; import java.awt.image.BufferedImage; import javax.inject.Inject; import javax.inject.Singleton; -import net.runelite.api.Client; import net.runelite.api.Player; import net.runelite.api.Point; -import net.runelite.client.game.ItemManager; +import net.runelite.api.SkullIcon; import net.runelite.client.plugins.friendtagging.FriendTaggingPlugin; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; @@ -49,10 +48,6 @@ public class PlayerIndicatorsMinimapOverlay extends Overlay private final PlayerIndicatorsConfig config; private final BufferedImage skullIcon = ImageUtil.getResourceStreamFromClass(PlayerIndicatorsPlugin.class, "skull.png"); - @Inject - private ItemManager itemManager; - @Inject - private Client client; @Inject private PlayerIndicatorsMinimapOverlay(PlayerIndicatorsConfig config, PlayerIndicatorsService playerIndicatorsService) @@ -98,31 +93,23 @@ public class PlayerIndicatorsMinimapOverlay extends Overlay } if (config.drawMinimapNames()) { - if (actor.getSkullIcon() != null && config.playerSkull()) + if (actor.getSkullIcon() != null && config.playerSkull() && actor.getSkullIcon() == SkullIcon.SKULL) { - switch (actor.getSkullIcon()) + int width = graphics.getFontMetrics().stringWidth(name); + int height = graphics.getFontMetrics().getHeight(); + if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) { - case SKULL: - - int width = graphics.getFontMetrics().stringWidth(name); - int height = graphics.getFontMetrics().getHeight(); - if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) - { - OverlayUtil.renderImageLocation(graphics, new Point(minimapLocation.getX() - + width, minimapLocation.getY() - height), - ImageUtil.resizeImage(skullIcon, height, height)); - } - else - { - OverlayUtil.renderImageLocation(graphics, new Point(minimapLocation.getX(), - minimapLocation.getY() - height), - ImageUtil.resizeImage(skullIcon, height, height)); - minimapLocation = new Point(minimapLocation.getX() + skullIcon.getWidth(), - minimapLocation.getY()); - } - break; - default: - break; + OverlayUtil.renderImageLocation(graphics, new Point(minimapLocation.getX() + + width, minimapLocation.getY() - height), + ImageUtil.resizeImage(skullIcon, height, height)); + } + else + { + OverlayUtil.renderImageLocation(graphics, new Point(minimapLocation.getX(), + minimapLocation.getY() - height), + ImageUtil.resizeImage(skullIcon, height, height)); + minimapLocation = new Point(minimapLocation.getX() + skullIcon.getWidth(), + minimapLocation.getY()); } } OverlayUtil.renderTextLocation(graphics, minimapLocation, name, color); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java index d475f0ea42..97ba662798 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java @@ -36,12 +36,11 @@ import net.runelite.api.Client; import net.runelite.api.ItemComposition; import net.runelite.api.Player; import net.runelite.api.Point; +import net.runelite.api.SkullIcon; import net.runelite.api.kit.KitType; import net.runelite.client.game.ClanManager; import net.runelite.client.game.ItemManager; -import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.friendtagging.FriendTaggingPlugin; -import net.runelite.client.plugins.pvptools.PvpToolsPlugin; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPriority; @@ -62,12 +61,9 @@ public class PlayerIndicatorsOverlay extends Overlay private final ClanManager clanManager; private final BufferedImage skullIcon = ImageUtil.getResourceStreamFromClass(PlayerIndicatorsPlugin.class, "skull.png"); - PvpToolsPlugin pvpToolsPlugin; @Inject private Client client; @Inject - private SpriteManager spriteManager; - @Inject private PlayerIndicatorsPlugin playerIndicatorsPlugin; @Inject private ItemManager itemManager; @@ -164,7 +160,7 @@ public class PlayerIndicatorsOverlay extends Overlay } } - String tag = ""; + String tag; String prefix = "tag_"; if (FriendTaggingPlugin.taggedFriends.containsKey(prefix + name.trim().toLowerCase())) { @@ -190,13 +186,13 @@ public class PlayerIndicatorsOverlay extends Overlay if (config.targetRisk() && PvPUtil.isAttackable(client, actor) && actor.getPlayerComposition() != null) { long totalValue = 0; - int newValue = 0; + int newValue; StringBuilder stringBuilder = new StringBuilder(" "); for (KitType kitType : KitType.values()) { ItemComposition itemComposition = itemManager.getItemComposition(actor.getPlayerComposition().getEquipmentId(kitType)); - if (itemComposition != null || itemComposition.getName() != null) + if (itemComposition != null && itemComposition.getName() != null) { totalValue = totalValue + itemComposition.getPrice(); } @@ -204,7 +200,7 @@ public class PlayerIndicatorsOverlay extends Overlay newValue = (int) (totalValue / 1000); if (newValue != 0) { - stringBuilder.append("(" + formatNumber(newValue) + "K)"); + stringBuilder.append("(").append(formatNumber(newValue)).append("K)"); name = name + stringBuilder; } } @@ -216,30 +212,24 @@ public class PlayerIndicatorsOverlay extends Overlay name = name + " cGLORY"; } } - if (actor.getSkullIcon() != null && config.playerSkull()) + + if (actor.getSkullIcon() != null && config.playerSkull() && actor.getSkullIcon() == SkullIcon.SKULL) { - switch (actor.getSkullIcon()) + int width = graphics.getFontMetrics().stringWidth(name); + int height = graphics.getFontMetrics().getHeight(); + if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) { - case SKULL: - int width = graphics.getFontMetrics().stringWidth(name); - int height = graphics.getFontMetrics().getHeight(); - if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) - { - OverlayUtil.renderImageLocation(graphics, new Point(textLocation.getX() - + width, textLocation.getY() - height), - ImageUtil.resizeImage(skullIcon, height, height)); - } - else - { - OverlayUtil.renderImageLocation(graphics, new Point(textLocation.getX(), - textLocation.getY() - height), - ImageUtil.resizeImage(skullIcon, height, height)); - textLocation = new Point(textLocation.getX() + skullIcon.getWidth(), - textLocation.getY()); - } - break; - default: - break; + OverlayUtil.renderImageLocation(graphics, new Point(textLocation.getX() + + width, textLocation.getY() - height), + ImageUtil.resizeImage(skullIcon, height, height)); + } + else + { + OverlayUtil.renderImageLocation(graphics, new Point(textLocation.getX(), + textLocation.getY() - height), + ImageUtil.resizeImage(skullIcon, height, height)); + textLocation = new Point(textLocation.getX() + skullIcon.getWidth(), + textLocation.getY()); } } OverlayUtil.renderTextLocation(graphics, textLocation, name, color); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index 425726a461..2c38b7fc3d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -31,15 +31,12 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; import javax.inject.Inject; - import net.runelite.api.Actor; import net.runelite.api.ClanMember; import net.runelite.api.ClanMemberRank; import static net.runelite.api.ClanMemberRank.UNRANKED; import net.runelite.api.Client; import static net.runelite.api.MenuAction.*; - -import net.runelite.api.HeadIcon; import net.runelite.api.MenuEntry; import net.runelite.api.Player; import net.runelite.api.events.ClanMemberJoined; @@ -128,7 +125,7 @@ public class PlayerIndicatorsPlugin extends Plugin { for (String name:callers) { - Actor pile = null; + Actor pile; String finalName = name.toLowerCase().replace("_", " "); if (p.getName().toLowerCase().replace("_", " ").equals(finalName)) { @@ -160,7 +157,7 @@ public class PlayerIndicatorsPlugin extends Plugin getCallerList(); } - public void getCallerList() + private void getCallerList() { callers.clear(); if (config.useClanchatRanks() && client.getClanMembers() != null) @@ -187,7 +184,7 @@ public class PlayerIndicatorsPlugin extends Plugin pileList = Arrays.asList(new String[callers.size()]); } - public boolean isCaller(Player player) + boolean isCaller(Player player) { if (callers != null) { @@ -200,18 +197,15 @@ public class PlayerIndicatorsPlugin extends Plugin } } } - else {return false;} + return false; } - public boolean isPile(Player player) + boolean isPile(Player player) { if (Objects.nonNull(pileList) && pileList.size() > 0) { - if (pileList.contains(player.getName())) - { - return true; - } + return pileList.contains(player.getName()); } return false; } @@ -359,7 +353,7 @@ public class PlayerIndicatorsPlugin extends Plugin } } - public static enum minimapSkullLocations + public enum minimapSkullLocations { BEFORE_NAME, AFTER_NAME diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsService.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsService.java index 5dda29c978..0fae391e05 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsService.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsService.java @@ -51,7 +51,7 @@ public class PlayerIndicatorsService { if (!config.highlightOwnPlayer() && !config.drawClanMemberNames() && !config.highlightFriends() && !config.highlightNonClanMembers() && !config.highlightTargets() - && !config.highlightPile() && !config.highlightCallers() && !config.highlightTeamMembers()) + && !config.highlightPile() && !config.highlightCallers() && !config.highlightTeamMembers()) { return; } @@ -94,14 +94,14 @@ public class PlayerIndicatorsService else if (config.highlightTargets() && PvPUtil.isAttackable(client, player) && !client.isFriended(player.getName(), false) && !player.isClanMember()) { - if (config.skulledTargetsOnly() && player.getSkullIcon() != null) - { - consumer.accept(player, config.getTargetColor()); - } - else if (!config.skulledTargetsOnly()) - { - consumer.accept(player, config.getTargetColor()); - } + if (config.skulledTargetsOnly() && player.getSkullIcon() != null) + { + consumer.accept(player, config.getTargetColor()); + } + else if (!config.skulledTargetsOnly()) + { + consumer.accept(player, config.getTargetColor()); + } } if (config.highlightCallers() && config.callers() != null && playerIndicatorsPlugin.isCaller(player)) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java index bc5a49fbc1..98602e7a4c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java @@ -63,11 +63,6 @@ public class PlayerIndicatorsTileOverlay extends Overlay Polygon objectClickbox = player.getConvexHull(); renderPoly(graphics, config.pileColor(), objectClickbox); - - if (objectClickbox != null) - { - - } } }); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryOverlay.java index 726702f8eb..e6191b1015 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryOverlay.java @@ -1,100 +1,97 @@ -/* - * Copyright (c) 2019, Yani - * 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.shayzieninfirmary; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.image.BufferedImage; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.ItemID; -import net.runelite.api.NPC; -import net.runelite.api.Point; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; - -public class ShayzienInfirmaryOverlay extends Overlay -{ - private final ShayzienInfirmaryPlugin plugin; - private final Client client; - - private BufferedImage medPackImage; - - @Inject - public ShayzienInfirmaryOverlay(ShayzienInfirmaryPlugin plugin, Client client, ItemManager itemManager) - { - setPosition(OverlayPosition.DYNAMIC); - this.plugin = plugin; - this.client = client; - - medPackImage = itemManager.getImage(ItemID.SHAYZIEN_MEDPACK); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isAtInfirmary()) - { - return null; - } - - for (NPC npc : plugin.getUnhealedSoldiers()) - { - - Polygon tilePoly = npc.getCanvasTilePoly(); - - if (tilePoly == null) - { - continue; - } - - OverlayUtil.renderPolygon(graphics, npc.getCanvasTilePoly(), Color.ORANGE); - - Point imageLocation = npc.getCanvasImageLocation(medPackImage, 25); - - if (imageLocation == null) - { - continue; - } - - Composite originalComposite = graphics.getComposite(); - Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f); - - graphics.setComposite(translucentComposite); - - OverlayUtil.renderImageLocation(graphics, imageLocation, medPackImage); - - graphics.setComposite(originalComposite); - } - - return null; - } -} +/* + * Copyright (c) 2019, Yani + * 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.shayzieninfirmary; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.api.ItemID; +import net.runelite.api.NPC; +import net.runelite.api.Point; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; + +public class ShayzienInfirmaryOverlay extends Overlay +{ + private final ShayzienInfirmaryPlugin plugin; + + private BufferedImage medPackImage; + + @Inject + public ShayzienInfirmaryOverlay(ShayzienInfirmaryPlugin plugin, ItemManager itemManager) + { + setPosition(OverlayPosition.DYNAMIC); + this.plugin = plugin; + + medPackImage = itemManager.getImage(ItemID.SHAYZIEN_MEDPACK); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isAtInfirmary()) + { + return null; + } + + for (NPC npc : plugin.getUnhealedSoldiers()) + { + + Polygon tilePoly = npc.getCanvasTilePoly(); + + if (tilePoly == null) + { + continue; + } + + OverlayUtil.renderPolygon(graphics, npc.getCanvasTilePoly(), Color.ORANGE); + + Point imageLocation = npc.getCanvasImageLocation(medPackImage, 25); + + if (imageLocation == null) + { + continue; + } + + Composite originalComposite = graphics.getComposite(); + Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f); + + graphics.setComposite(translucentComposite); + + OverlayUtil.renderImageLocation(graphics, imageLocation, medPackImage); + + graphics.setComposite(originalComposite); + } + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryPlugin.java index 70f47daf4c..f84ace58de 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shayzieninfirmary/ShayzienInfirmaryPlugin.java @@ -1,123 +1,118 @@ -/* - * Copyright (c) 2019, Yani - * 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.shayzieninfirmary; - -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.NPC; -import net.runelite.api.events.GameTick; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.OverlayManager; - -@Slf4j -@PluginDescriptor( - name = "Shayzien Infirmary", - description = "Shows the status of wounded soldiers", - tags = {"shayzien", "infirmary", "soldiers"}, - type = PluginType.UTILITY -) -public class ShayzienInfirmaryPlugin extends Plugin -{ - @Getter(AccessLevel.PACKAGE) - private List unhealedSoldiers = new ArrayList(); - - @Inject - private OverlayManager overlayManager; - - @Inject - private Client client; - - @Inject - private ShayzienInfirmaryOverlay overlay; - - @Override - protected void startUp() throws Exception - { - loadPlugin(); - } - - @Override - protected void shutDown() throws Exception - { - unloadPlugin(); - } - - private void loadPlugin() - { - overlayManager.add(overlay); - } - - private void unloadPlugin() - { - overlayManager.remove(overlay); - } - - @Subscribe - public void onGameTick(GameTick event) - { - if(!isAtInfirmary()) - { - return; - } - - unhealedSoldiers.clear(); - - for (NPC npc : client.getNpcs()) - { - if (isUnhealedSoldierId(npc.getId())) - { - unhealedSoldiers.add(npc); - } - } - } - - public boolean isSoldierId(int npcId) - { - return (npcId >= 6826 && npcId <= 6857); - } - - public boolean isUnhealedSoldierId(int npcId) - { - return (isSoldierId(npcId) && npcId % 2 == 0); - } - - public boolean isHealedSoldierId(int npcId) - { - return (isSoldierId(npcId) && npcId % 2 == 1); - } - - public boolean isAtInfirmary() - { - return client.getLocalPlayer().getWorldLocation().getRegionID() == 6200; - } +/* + * Copyright (c) 2019, Yani + * 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.shayzieninfirmary; + +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.events.GameTick; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; + +@Slf4j +@PluginDescriptor( + name = "Shayzien Infirmary", + description = "Shows the status of wounded soldiers", + tags = {"shayzien", "infirmary", "soldiers"}, + type = PluginType.UTILITY +) +public class ShayzienInfirmaryPlugin extends Plugin +{ + @Getter(AccessLevel.PACKAGE) + private List unhealedSoldiers = new ArrayList(); + + @Inject + private OverlayManager overlayManager; + + @Inject + private Client client; + + @Inject + private ShayzienInfirmaryOverlay overlay; + + @Override + protected void startUp() throws Exception + { + loadPlugin(); + } + + @Override + protected void shutDown() throws Exception + { + unloadPlugin(); + } + + private void loadPlugin() + { + overlayManager.add(overlay); + } + + private void unloadPlugin() + { + overlayManager.remove(overlay); + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (!isAtInfirmary()) + { + return; + } + + unhealedSoldiers.clear(); + + for (NPC npc : client.getNpcs()) + { + if (isUnhealedSoldierId(npc.getId())) + { + unhealedSoldiers.add(npc); + } + } + } + + private boolean isSoldierId(int npcId) + { + return (npcId >= 6826 && npcId <= 6857); + } + + private boolean isUnhealedSoldierId(int npcId) + { + return (isSoldierId(npcId) && npcId % 2 == 0); + } + + boolean isAtInfirmary() + { + return client.getLocalPlayer().getWorldLocation().getRegionID() == 6200; + } } \ No newline at end of file From 11543b5739776b84d572b63766549dc0343335c8 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 04:10:20 +0200 Subject: [PATCH 19/78] plugins checkstyle --- .../net/runelite/client/plugins/Plugin.java | 113 +- .../client/plugins/PluginDescriptor.java | 126 +- .../client/plugins/PluginManager.java | 1107 +-- .../runelite/client/plugins/PluginType.java | 31 +- .../client/plugins/PluginWatcher.java | 546 +- .../plugins/achievementdiary/Requirement.java | 57 +- .../diaries/KourendDiaryRequirement.java | 272 +- .../plugins/agility/AgilityOverlay.java | 282 +- .../client/plugins/agility/AgilityPlugin.java | 925 +-- .../client/plugins/agility/Obstacles.java | 465 +- .../plugins/alchemicalhydra/HydraPhase.java | 140 +- .../plugins/alchemicalhydra/HydraPlugin.java | 10 +- .../alchemicalhydra/HydraPoisonOverlay.java | 288 +- .../plugins/antidrag/AntiDragConfig.java | 2 +- .../aoewarnings/AoeProjectileInfo.java | 7 +- .../aoewarnings/AoeWarningOverlay.java | 16 +- .../plugins/aoewarnings/AoeWarningPlugin.java | 4 +- .../plugins/aoewarnings/BombOverlay.java | 14 +- .../plugins/banktags/BankTagsConfig.java | 226 +- .../BarbarianAssaultPlugin.java | 1 - .../plugins/barbarianassault/HealerTeam.java | 88 +- .../barrows/BarrowsBrotherSlainOverlay.java | 198 +- .../plugins/barrows/BarrowsOverlay.java | 485 +- .../client/plugins/barrows/BarrowsPlugin.java | 14 +- .../plugins/batools/BAToolsOverlay.java | 2 - .../client/plugins/batools/BAToolsPlugin.java | 19 +- .../client/plugins/batools/Calls.java | 4 +- .../client/plugins/batools/CycleCounter.java | 3 +- .../client/plugins/batools/Healer.java | 7 +- .../client/plugins/batools/HealerCode.java | 20 +- .../blastmine/BlastMineOreCountOverlay.java | 1 - .../blastmine/BlastMinePluginConfig.java | 201 +- .../client/plugins/boosts/BoostsPlugin.java | 13 +- .../client/plugins/bosstimer/Boss.java | 2 +- .../client/plugins/cannon/CannonOverlay.java | 281 +- .../plugins/cerberus/CerberusGhost.java | 1 + .../plugins/cerberus/CerberusOverlay.java | 14 +- .../ChatboxPerformancePlugin.java | 316 +- .../chatcommands/ChatCommandsPlugin.java | 26 +- .../chathistory/ChatHistoryPlugin.java | 525 +- .../ChatNotificationsPlugin.java | 462 +- .../plugins/clanchat/ClanChatPlugin.java | 23 +- .../clanmanmode/ClanManModeOverlay.java | 4 +- .../clanmanmode/ClanManModePlugin.java | 42 +- .../clanmanmode/ClanManModeService.java | 116 +- .../plugins/cluescrolls/ClueScrollPlugin.java | 2 +- .../cluescrolls/clues/AnagramClue.java | 4 +- .../plugins/cluescrolls/clues/CipherClue.java | 2 +- .../cluescrolls/clues/CrypticClue.java | 71 +- .../plugins/cluescrolls/clues/EmoteClue.java | 1139 ++- .../cluescrolls/clues/FaloTheBardClue.java | 2 +- .../cluescrolls/clues/HotColdClue.java | 820 +- .../plugins/cluescrolls/clues/MapClue.java | 449 +- .../plugins/cluescrolls/clues/MusicClue.java | 214 +- .../cluescrolls/clues/emote/Emote.java | 176 +- .../combatlevel/CombatLevelOverlay.java | 31 +- .../combatlevel/CombatLevelPlugin.java | 488 +- .../client/plugins/config/ConfigPanel.java | 51 +- .../client/plugins/config/PluginListItem.java | 60 +- .../dailytaskindicators/DailyTasksPlugin.java | 2 +- .../defaultworld/DefaultWorldPlugin.java | 304 +- .../demonicgorilla/DemonicGorillaOverlay.java | 309 +- .../demonicgorilla/DemonicGorillaPlugin.java | 1430 ++-- .../plugins/devtools/CameraOverlay.java | 196 +- .../plugins/devtools/DevToolsPanel.java | 4 +- .../plugins/devtools/DevToolsPlugin.java | 6 +- .../plugins/devtools/LocationOverlay.java | 244 +- .../devtools/WorldMapLocationOverlay.java | 212 +- .../plugins/discord/DiscordGameEventType.java | 189 +- .../client/plugins/discord/DiscordPlugin.java | 12 +- .../plugins/easyscape/DuelingRingMode.java | 87 +- .../plugins/easyscape/EasyscapePlugin.java | 605 +- .../easyscape/EasyscapePluginConfig.java | 516 +- .../client/plugins/easyscape/EssenceMode.java | 85 +- .../plugins/easyscape/GamesNecklaceMode.java | 91 +- .../client/plugins/easyscape/GloryMode.java | 89 +- .../plugins/easyscape/WealthRingMode.java | 89 +- .../plugins/equipmentinspector/ItemPanel.java | 24 +- .../client/plugins/examine/CacheKey.java | 146 +- .../client/plugins/examine/ExamineType.java | 66 +- .../plugins/experiencedrop/PrayerType.java | 64 +- .../plugins/experiencedrop/XpDropConfig.java | 224 +- .../plugins/experiencedrop/XpDropOverlay.java | 145 +- .../plugins/experiencedrop/XpDropPlugin.java | 922 +-- .../plugins/experiencedrop/XpPrayer.java | 141 +- .../plugins/fairyring/FairyRingPlugin.java | 732 +- .../client/plugins/fightcave/JadAttack.java | 104 +- .../client/plugins/fightcave/JadOverlay.java | 172 +- .../client/plugins/fightcave/WaveOverlay.java | 249 +- .../plugins/fishing/FishingSpotOverlay.java | 364 +- .../client/plugins/flexo/FlexoOverlay.java | 2 - .../client/plugins/fps/FpsDrawListener.java | 2 +- .../freezetimers/PlayerSpellEffect.java | 6 +- .../friendtagging/FriendTaggingPlugin.java | 24 +- .../client/plugins/gpu/GpuPlugin.java | 42 +- .../client/plugins/gpu/GpuPluginConfig.java | 174 +- .../grandexchange/GrandExchangeOfferSlot.java | 554 +- .../grandexchange/GrandExchangePlugin.java | 994 +-- .../GrotesqueGuardiansPlugin.java | 116 +- .../grounditems/GroundItemsConfig.java | 766 +- .../grounditems/GroundItemsOverlay.java | 782 +- .../grounditems/GroundItemsPlugin.java | 1360 ++-- .../groundmarkers/GroundMarkerPlugin.java | 572 +- .../groundmarkers/GroundMarkerPoint.java | 88 +- .../plugins/herbiboars/HerbiboarPlugin.java | 710 +- .../HidePrayersINDIVIDUALConfig.java | 563 +- .../HidePrayersINDIVIDUALPlugin.java | 329 +- .../hideprayers/PVM/HidePrayersPVMConfig.java | 136 +- .../hideprayers/PVM/HidePrayersPVMPlugin.java | 114 +- .../hideprayers/PVP/CombatPrayers.java | 2 +- .../hideprayers/PVP/HidePrayersPVPConfig.java | 17 +- .../hideprayers/PVP/HidePrayersPVPPlugin.java | 406 +- .../hideprayers/util/PrayerTabStates.java | 8 +- .../highalchemy/HighAlchemyOverlay.java | 2 - .../highalchemy/HighAlchemyPlugin.java | 2 +- .../client/plugins/hiscore/HiscorePlugin.java | 512 +- .../plugins/hiscore/NameAutocompleter.java | 528 +- .../client/plugins/hunter/HunterPlugin.java | 780 +- .../client/plugins/hunter/TrapOverlay.java | 378 +- .../client/plugins/hydra/HydraPlugin.java | 1 - .../idlenotifier/IdleNotifierPlugin.java | 115 +- .../plugins/implings/ImplingsConfig.java | 9 +- .../plugins/implings/ImplingsOverlay.java | 4 +- .../client/plugins/info/InfoPanel.java | 623 +- .../client/plugins/info/InfoPlugin.java | 140 +- .../instancemap/InstanceMapOverlay.java | 544 +- .../interfacestyles/SpriteOverride.java | 298 +- .../interfacestyles/WidgetOverride.java | 110 +- .../InventoryViewerConfig.java | 126 +- .../InventoryViewerOverlay.java | 18 +- .../plugins/itemcharges/ItemChargePlugin.java | 2 +- .../plugins/itemcharges/ItemWithCharge.java | 128 +- .../ItemIdentification.java | 4 +- .../plugins/itemstats/BoostedStatBoost.java | 102 +- .../client/plugins/itemstats/Food.java | 90 +- .../plugins/itemstats/ItemStatChanges.java | 421 +- .../plugins/itemstats/ItemStatConfig.java | 299 +- .../plugins/itemstats/ItemStatOverlay.java | 582 +- .../plugins/itemstats/ItemStatPlugin.java | 874 +-- .../plugins/itemstats/SimpleStatBoost.java | 102 +- .../client/plugins/itemstats/StatBoost.java | 192 +- .../itemstats/potions/SaradominBrew.java | 161 +- .../itemstats/potions/SuperRestore.java | 168 +- .../itemstats/special/CastleWarsBandage.java | 168 +- .../plugins/itemstats/special/SpicyStew.java | 326 +- .../client/plugins/itemstats/stats/Stat.java | 117 +- .../keptondeath/ActuallyTradeableItem.java | 308 +- .../plugins/keptondeath/AlwaysLostItem.java | 139 +- .../keptondeath/BrokenOnDeathItem.java | 225 +- .../keptondeath/KeptOnDeathPlugin.java | 1195 +-- .../plugins/keptondeath/WidgetButton.java | 351 +- .../plugins/kourendlibrary/Library.java | 1622 ++-- .../kourendlibrary/LibraryCustomer.java | 133 +- .../plugins/kourendlibrary/SolvedState.java | 64 +- .../LizardmenShamanConfig.java | 111 +- .../LizardmenShamanPlugin.java | 235 +- .../lizardmenshaman/ShamanSpawnOverlay.java | 229 +- .../loginscreen/LoginScreenPlugin.java | 416 +- .../plugins/lootassist/LootAssistPlugin.java | 1 - .../client/plugins/lootassist/LootPile.java | 1 - .../LootingBagViewerOverlay.java | 14 +- .../LootingBagViewerPlugin.java | 121 +- .../loottracker/LootTrackerConfig.java | 6 +- .../loottracker/LootTrackerPlugin.java | 22 +- .../loottracker/LootTrackerRecord.java | 101 +- .../client/plugins/maxhit/MaxHitPlugin.java | 277 +- .../maxhit/attackstyle/WeaponType.java | 186 +- .../maxhit/calculators/MaxHitCalculator.java | 355 +- .../maxhit/config/CustomFormulaConfig.java | 465 +- .../maxhit/config/EquipmentBonusConfig.java | 842 +- .../maxhit/equipment/EquipmentSlotItem.java | 101 +- .../AutocastSpellRequirement.java | 115 +- .../MenuEntrySwapperConfig.java | 10 +- .../MenuEntrySwapperPlugin.java | 46 +- .../menumodifier/MenuModifierConfig.java | 46 +- .../client/plugins/mining/MiningOverlay.java | 252 +- .../client/plugins/mining/MiningPlugin.java | 38 +- .../plugins/mining/MiningRocksOverlay.java | 225 +- .../client/plugins/mining/MiningSession.java | 279 +- .../plugins/motherlode/MotherlodeOverlay.java | 257 +- .../motherlode/MotherlodeRocksOverlay.java | 282 +- .../plugins/mta/graveyard/GraveyardRoom.java | 2 +- .../mta/telekinetic/TelekineticRoom.java | 14 +- .../plugins/multiindicators/MapLocations.java | 6956 ++++++++--------- .../MultiIndicatorsConfig.java | 220 +- .../MultiIndicatorsMinimapOverlay.java | 230 +- .../MultiIndicatorsOverlay.java | 224 +- .../MultiIndicatorsPlugin.java | 598 +- .../multiindicators/ZoneVisibility.java | 84 +- .../musicmodifier/MidiFileAdjuster.java | 367 +- .../musicmodifier/MusicCustomizerPlugin.java | 720 +- .../musicmodifier/RealTimeMIDIPlayer.java | 511 +- .../nightmarezone/AbsorptionCounter.java | 132 +- .../nightmarezone/NightmareZoneOverlay.java | 320 +- .../nightmarezone/NightmareZonePlugin.java | 400 +- .../client/plugins/notes/NotesPlugin.java | 186 +- .../npchighlight/NpcIndicatorsPlugin.java | 1 - .../plugins/npchighlight/NpcSceneOverlay.java | 2 +- .../npcunaggroarea/NpcAggroAreaOverlay.java | 238 +- .../npcunaggroarea/NpcAggroAreaPlugin.java | 2 +- .../ObjectIndicatorsPlugin.java | 780 +- .../opponentinfo/PlayerComparisonOverlay.java | 374 +- .../plugins/party/PartyPluginService.java | 81 +- .../pestcontrol/PortalWeaknessOverlay.java | 390 +- .../plugins/pestcontrol/WidgetOverlay.java | 420 +- .../PlayerIndicatorsConfig.java | 168 +- .../PlayerIndicatorsOverlay.java | 2 +- .../PlayerIndicatorsPlugin.java | 136 +- .../PlayerIndicatorsTileOverlay.java | 8 +- .../plugins/playerinfo/PlayerInfoConfig.java | 245 +- .../playerinfo/PlayerInfoCustomIndicator.java | 280 +- .../plugins/playerinfo/PlayerInfoPlugin.java | 219 +- .../runelite/client/plugins/poh/PohIcons.java | 161 +- .../client/plugins/poh/PohOverlay.java | 296 +- .../client/plugins/poh/PohPlugin.java | 2 +- .../client/plugins/poison/PoisonInfobox.java | 160 +- .../client/plugins/poison/PoisonPlugin.java | 712 +- .../PrayAgainstPlayerPlugin.java | 3 - .../plugins/prayagainstplayer/WeaponType.java | 93 +- .../plugins/prayer/PrayerDoseOverlay.java | 2 +- .../plugins/profiles/ProfilesPanel.java | 2 +- .../puzzlesolver/PuzzleSolverOverlay.java | 956 +-- .../puzzlesolver/lightbox/Combination.java | 60 +- .../puzzlesolver/solver/PuzzleState.java | 446 +- .../solver/PuzzleSwapPattern.java | 132 +- .../solver/heuristics/ManhattanDistance.java | 268 +- .../solver/pathfinding/IDAStar.java | 212 +- .../solver/pathfinding/IDAStarMM.java | 1445 ++-- .../plugins/pvptools/PvpToolsPanel.java | 1 - .../pyramidplunder/PyramidPlunderOverlay.java | 263 +- .../pyramidplunder/PyramidPlunderPlugin.java | 542 +- .../quests/cooksassistant/CooksAssistant.java | 114 +- .../quests/impcatcher/ImpCatcher.java | 116 +- .../quests/xmarksthespot/XMarksTheSpot.java | 160 +- .../questhelper/steps/NpcTalkStep.java | 319 +- .../plugins/questlist/QuestListPlugin.java | 796 +- .../client/plugins/raids/RaidsConfig.java | 12 +- .../client/plugins/raids/RaidsOverlay.java | 36 +- .../client/plugins/raids/RaidsPlugin.java | 1751 ++--- .../plugins/raids/RaidsPointsOverlay.java | 241 +- .../raids/shortcuts/ShortcutConfig.java | 3 +- .../raids/shortcuts/ShortcutOverlay.java | 66 +- .../raids/shortcuts/ShortcutPlugin.java | 37 +- .../plugins/raids/solver/LayoutSolver.java | 444 +- .../plugins/raids/solver/RotationSolver.java | 300 +- .../raidsthieving/BatSolver/BatSolver.java | 386 +- .../BatSolver/ChestIdentifier.java | 522 +- .../raidsthieving/BatSolver/SolutionSet.java | 330 +- .../plugins/raidsthieving/ChestOverlay.java | 344 +- .../plugins/raidsthieving/InstancePoint.java | 201 +- .../raidsthieving/RaidsThievingConfig.java | 134 +- .../raidsthieving/RaidsThievingPlugin.java | 544 +- .../rememberclan/RememberClanConfig.java | 96 +- .../rememberclan/RememberClanPlugin.java | 155 +- .../reorderprayers/ReorderPrayersPlugin.java | 906 +-- .../client/plugins/roguesden/Obstacles.java | 117 +- .../plugins/runecraft/AbyssOverlay.java | 482 +- .../plugins/runecraft/RunecraftConfig.java | 1 + .../plugins/runecraft/RunecraftPlugin.java | 10 +- .../plugins/runedoku/RunedokuConfig.java | 123 +- .../plugins/runedoku/RunedokuOverlay.java | 79 +- .../plugins/runedoku/RunedokuPiece.java | 21 +- .../plugins/runedoku/RunedokuPlugin.java | 25 +- .../client/plugins/runedoku/RunedokuUtil.java | 74 +- .../client/plugins/runedoku/Sudoku.java | 78 +- .../plugins/runenergy/RunEnergyPlugin.java | 102 +- .../plugins/runepouch/RunepouchOverlay.java | 358 +- .../client/plugins/runepouch/Runes.java | 2 +- .../plugins/screenshot/ScreenshotPlugin.java | 1508 ++-- .../shiftwalker/ShiftWalkerConfig.java | 132 +- .../shiftwalker/ShiftWalkerInputListener.java | 121 +- .../shiftwalker/ShiftWalkerPlugin.java | 28 +- .../skillcalculator/BankedCalculator.java | 1339 ++-- .../skillcalculator/SkillCalculator.java | 973 +-- .../SkillCalculatorConfig.java | 108 +- .../skillcalculator/SkillCalculatorPanel.java | 484 +- .../skillcalculator/banked/CriticalItem.java | 825 +- .../banked/beans/Activity.java | 819 +- .../banked/ui/CriticalItemPanel.java | 801 +- .../client/plugins/slayer/KnapsackSolver.java | 14 +- .../client/plugins/slayer/SlayerPlugin.java | 73 +- .../plugins/slayer/SlayerTaskPanel.java | 7 +- .../plugins/slayer/SlayerXpDropLookup.java | 28 +- .../plugins/slayer/TargetWeaknessOverlay.java | 2 +- .../runelite/client/plugins/slayer/Task.java | 7 +- .../client/plugins/slayer/TaskData.java | 2 +- .../plugins/slayermusiq/QuestGuideLinks.java | 386 +- .../slayermusiq/SlayermusiqPlugin.java | 26 +- .../plugins/smelting/SmeltingOverlay.java | 30 +- .../client/plugins/specbar/SpecBarPlugin.java | 149 +- .../plugins/spellbook/SpellbookPlugin.java | 19 +- .../plugins/statusbars/StatusBarsPlugin.java | 264 +- .../client/plugins/statusbars/Viewport.java | 94 +- .../stretchedmode/TranslateMouseListener.java | 196 +- .../TranslateMouseWheelListener.java | 124 +- .../plugins/suppliestracker/ActionType.java | 66 +- .../plugins/suppliestracker/ItemType.java | 155 +- .../plugins/suppliestracker/SuppliesBox.java | 719 +- .../suppliestracker/SuppliesTrackerPanel.java | 421 +- .../SuppliesTrackerPlugin.java | 1674 ++-- .../client/plugins/tarnslair/Obstacles.java | 348 +- .../plugins/teamcapes/TeamCapesPlugin.java | 252 +- .../tickcounter/TickCounterOverlay.java | 1 - .../client/plugins/timers/TimersPlugin.java | 36 +- .../timetracking/OverviewTabPanel.java | 300 +- .../timetracking/TimeTrackingPanel.java | 356 +- .../timetracking/farming/FarmingTracker.java | 618 +- .../timetracking/hunter/BirdHouseTracker.java | 507 +- .../tobdamagecount/DamageCounterPlugin.java | 716 +- .../client/plugins/twitch/irc/Message.java | 219 +- .../plugins/vanguards/VanguardOverlay.java | 280 +- .../plugins/vanguards/VanguardPlugin.java | 139 +- .../client/plugins/vetion/VetionPlugin.java | 3 - .../warindicators/WarIndicatorPlugin.java | 13 +- .../plugins/wasdcamera/WASDCameraPlugin.java | 416 +- .../whalewatchers/WhaleWatchersConfig.java | 2 - .../WhaleWatchersGloryOverlay.java | 1 - .../whalewatchers/WhaleWatchersOverlay.java | 2 +- .../whalewatchers/WhaleWatchersPlugin.java | 10 +- .../WhaleWatchersProtOverlay.java | 1 - .../WhaleWatchersSmiteableOverlay.java | 3 +- .../wiki/WikiSearchChatboxTextInput.java | 612 +- .../WildernessLocationsConfig.java | 8 +- .../WildernessLocationsOverlay.java | 5 +- .../worldhopper/WorldHopperConfig.java | 252 +- .../worldhopper/WorldHopperPlugin.java | 2 +- .../worldhopper/WorldSwitcherPanel.java | 1289 ++- .../plugins/worldhopper/WorldTableHeader.java | 9 +- .../plugins/worldhopper/WorldTableRow.java | 2 +- .../worldmap/AgilityShortcutPoint.java | 86 +- .../plugins/worldmap/QuestStartPoint.java | 78 +- .../plugins/worldmap/RareTreePoint.java | 87 +- .../worldmap/TeleportLocationData.java | 94 +- .../plugins/worldmap/TransportationPoint.java | 80 +- .../worldmap/TransportationPointLocation.java | 386 +- .../plugins/worldmap/WorldMapPlugin.java | 548 +- .../plugins/xpglobes/XpGlobesPlugin.java | 374 +- .../plugins/xptracker/XpInfoBoxOverlay.java | 28 +- .../client/plugins/xptracker/XpState.java | 473 +- .../plugins/xptracker/XpTrackerPlugin.java | 2 + .../client/plugins/zoom/ZoomPlugin.java | 4 +- .../plugins/ztob/BloatTimerOverlay.java | 207 +- .../client/plugins/ztob/TheatreConfig.java | 230 +- .../client/plugins/ztob/TheatreOverlay.java | 380 +- .../client/plugins/ztob/TheatrePlugin.java | 1831 +++-- .../plugins/ztob/TheatreXarpusOverlay.java | 143 +- .../plugins/ztob/VerzikNyloOverlay.java | 206 +- 347 files changed, 49724 insertions(+), 46654 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java index 192f587665..353e8eac07 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java @@ -1,57 +1,56 @@ -/* - * Copyright (c) 2016-2017, Adam - * 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; - -import com.google.inject.Binder; -import com.google.inject.Injector; -import com.google.inject.Module; - -import java.io.File; - -public abstract class Plugin implements Module -{ - protected Injector injector; - - public File file; - public PluginClassLoader loader; - - @Override - public void configure(Binder binder) - { - } - - protected void startUp() throws Exception - { - } - - protected void shutDown() throws Exception - { - } - - public final Injector getInjector() - { - return injector; - } -} +/* + * Copyright (c) 2016-2017, Adam + * 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; + +import com.google.inject.Binder; +import com.google.inject.Injector; +import com.google.inject.Module; +import java.io.File; + +public abstract class Plugin implements Module +{ + protected Injector injector; + + public File file; + public PluginClassLoader loader; + + @Override + public void configure(Binder binder) + { + } + + protected void startUp() throws Exception + { + } + + protected void shutDown() throws Exception + { + } + + public final Injector getInjector() + { + return injector; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java index fafcaebcbd..c505eac5bb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java @@ -1,63 +1,63 @@ -/* - * Copyright (c) 2017, Adam - * 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; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Documented -public @interface PluginDescriptor -{ - String name(); - - /** - * A short, one-line summary of the plugin. - */ - String description() default ""; - - /** - * A list of plugin keywords, used (together with the name) when searching for plugins. - * Each tag should not contain any spaces, and should be fully lowercase. - */ - String[] tags() default {}; - - boolean enabledByDefault() default true; - - /** - * Whether or not plugin is hidden from configuration panel - */ - boolean hidden() default false; - - boolean developerPlugin() default false; - - boolean loadWhenOutdated() default false; - - PluginType type() default PluginType.GENERAL_USE; -} +/* + * Copyright (c) 2017, Adam + * 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; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +public @interface PluginDescriptor +{ + String name(); + + /** + * A short, one-line summary of the plugin. + */ + String description() default ""; + + /** + * A list of plugin keywords, used (together with the name) when searching for plugins. + * Each tag should not contain any spaces, and should be fully lowercase. + */ + String[] tags() default {}; + + boolean enabledByDefault() default true; + + /** + * Whether or not plugin is hidden from configuration panel + */ + boolean hidden() default false; + + boolean developerPlugin() default false; + + boolean loadWhenOutdated() default false; + + PluginType type() default PluginType.GENERAL_USE; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java index 62e8a22aa8..32eea3d5c9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java @@ -1,553 +1,554 @@ -/* - * Copyright (c) 2016-2017, Adam - * 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; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.graph.Graph; -import com.google.common.graph.GraphBuilder; -import com.google.common.graph.Graphs; -import com.google.common.graph.MutableGraph; -import com.google.common.reflect.ClassPath; -import com.google.common.reflect.ClassPath.ClassInfo; -import com.google.inject.Binder; -import com.google.inject.CreationException; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ScheduledExecutorService; -import java.util.stream.Collectors; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Provider; -import javax.inject.Singleton; -import javax.swing.SwingUtilities; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.RuneLite; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.events.PluginChanged; -import net.runelite.client.task.Schedule; -import net.runelite.client.task.ScheduledMethod; -import net.runelite.client.task.Scheduler; -import net.runelite.client.util.GameEventManager; - -@Singleton -@Slf4j -public class PluginManager -{ - /** - * Base package where the core plugins are - */ - private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins"; - - private final boolean developerMode; - private final EventBus eventBus; - private final Scheduler scheduler; - private final ConfigManager configManager; - private final ScheduledExecutorService executor; - private final Provider sceneTileManager; - private final List plugins = new CopyOnWriteArrayList<>(); - private final List activePlugins = new CopyOnWriteArrayList<>(); - private final String runeliteGroupName = RuneLiteConfig.class - .getAnnotation(ConfigGroup.class).value(); - - @Inject - PluginWatcher pluginWatcher; - - @Setter - boolean isOutdated; - - @Inject - @VisibleForTesting - PluginManager( - @Named("developerMode") final boolean developerMode, - final EventBus eventBus, - final Scheduler scheduler, - final ConfigManager configManager, - final ScheduledExecutorService executor, - final Provider sceneTileManager) - { - this.developerMode = developerMode; - this.eventBus = eventBus; - this.scheduler = scheduler; - this.configManager = configManager; - this.executor = executor; - this.sceneTileManager = sceneTileManager; - } - - public void watch() - { - pluginWatcher.start(); - } - - @Subscribe - public void onSessionOpen(SessionOpen event) - { - refreshPlugins(); - } - - @Subscribe - public void onSessionClose(SessionClose event) - { - refreshPlugins(); - } - - private void refreshPlugins() - { - loadDefaultPluginConfiguration(); - getPlugins() - .forEach(plugin -> executor.submit(() -> - { - try - { - if (!startPlugin(plugin)) - { - stopPlugin(plugin); - } - } - catch (PluginInstantiationException e) - { - log.warn("Error during starting/stopping plugin {}. {}", plugin.getClass().getSimpleName(), e); - } - })); - } - - public Config getPluginConfigProxy(Plugin plugin) - { - final Injector injector = plugin.getInjector(); - - for (Key key : injector.getAllBindings().keySet()) - { - Class type = key.getTypeLiteral().getRawType(); - if (Config.class.isAssignableFrom(type)) - { - return (Config) injector.getInstance(key); - } - } - - return null; - } - - public List getPluginConfigProxies() - { - List injectors = new ArrayList<>(); - injectors.add(RuneLite.getInjector()); - getPlugins().forEach(pl -> injectors.add(pl.getInjector())); - - List list = new ArrayList<>(); - for (Injector injector : injectors) - { - for (Key key : injector.getAllBindings().keySet()) - { - Class type = key.getTypeLiteral().getRawType(); - if (Config.class.isAssignableFrom(type)) - { - Config config = (Config) injector.getInstance(key); - list.add(config); - } - } - } - - return list; - } - - public void loadDefaultPluginConfiguration() - { - for (Object config : getPluginConfigProxies()) - { - configManager.setDefaultConfiguration(config, false); - } - } - - public void loadCorePlugins() throws IOException - { - plugins.addAll(scanAndInstantiate(getClass().getClassLoader(), PLUGIN_PACKAGE)); - } - - public void startCorePlugins() - { - List scannedPlugins = new ArrayList<>(plugins); - for (Plugin plugin : scannedPlugins) - { - try - { - startPlugin(plugin); - } - catch (PluginInstantiationException ex) - { - log.warn("Unable to start plugin {}. {}", plugin.getClass().getSimpleName(), ex); - plugins.remove(plugin); - } - } - } - - List scanAndInstantiate(ClassLoader classLoader, String packageName) throws IOException - { - MutableGraph> graph = GraphBuilder - .directed() - .build(); - - List scannedPlugins = new ArrayList<>(); - ClassPath classPath = ClassPath.from(classLoader); - - ImmutableSet classes = packageName == null ? classPath.getAllClasses() - : classPath.getTopLevelClassesRecursive(packageName); - for (ClassInfo classInfo : classes) - { - Class clazz = classInfo.load(); - PluginDescriptor pluginDescriptor = clazz.getAnnotation(PluginDescriptor.class); - - if (pluginDescriptor == null) - { - if (clazz.getSuperclass() == Plugin.class) - { - log.warn("Class {} is a plugin, but has no plugin descriptor", - clazz); - } - continue; - } - - if (clazz.getSuperclass() != Plugin.class) - { - log.warn("Class {} has plugin descriptor, but is not a plugin", - clazz); - continue; - } - - if (!pluginDescriptor.loadWhenOutdated() && isOutdated) - { - continue; - } - - if (pluginDescriptor.developerPlugin() && !developerMode) - { - continue; - } - - Class pluginClass = (Class) clazz; - graph.addNode(pluginClass); - } - - // Build plugin graph - for (Class pluginClazz : graph.nodes()) - { - PluginDependency[] pluginDependencies = pluginClazz.getAnnotationsByType(PluginDependency.class); - - for (PluginDependency pluginDependency : pluginDependencies) - { - graph.putEdge(pluginClazz, pluginDependency.value()); - } - } - - if (Graphs.hasCycle(graph)) - { - throw new RuntimeException("Plugin dependency graph contains a cycle!"); - } - - List> sortedPlugins = topologicalSort(graph); - sortedPlugins = Lists.reverse(sortedPlugins); - - for (Class pluginClazz : sortedPlugins) - { - Plugin plugin; - try - { - plugin = instantiate(scannedPlugins, (Class) pluginClazz); - } - catch (PluginInstantiationException ex) - { - log.warn("Error instantiating plugin!", ex); - continue; - } - - scannedPlugins.add(plugin); - } - - return scannedPlugins; - } - - public synchronized boolean startPlugin(Plugin plugin) throws PluginInstantiationException - { - if (activePlugins.contains(plugin) || !isPluginEnabled(plugin)) - { - return false; - } - - activePlugins.add(plugin); - - try - { - // plugins always start in the event thread - SwingUtilities.invokeAndWait(() -> - { - try - { - plugin.startUp(); - } - catch (Exception ex) - { - throw new RuntimeException(ex); - } - }); - - log.debug("Plugin {} is now running", plugin.getClass().getSimpleName()); - if (!isOutdated && sceneTileManager != null) - { - final GameEventManager gameEventManager = this.sceneTileManager.get(); - if (gameEventManager != null) - { - gameEventManager.simulateGameEvents(plugin); - } - } - - eventBus.register(plugin); - schedule(plugin); - eventBus.post(new PluginChanged(plugin, true)); - } - catch (InterruptedException | InvocationTargetException | IllegalArgumentException ex) - { - throw new PluginInstantiationException(ex); - } - - return true; - } - - public synchronized boolean stopPlugin(Plugin plugin) throws PluginInstantiationException - { - if (!activePlugins.contains(plugin) || isPluginEnabled(plugin)) - { - return false; - } - - activePlugins.remove(plugin); - - try - { - unschedule(plugin); - eventBus.unregister(plugin); - - // plugins always stop in the event thread - SwingUtilities.invokeAndWait(() -> - { - try - { - plugin.shutDown(); - } - catch (Exception ex) - { - throw new RuntimeException(ex); - } - }); - - log.debug("Plugin {} is now stopped", plugin.getClass().getSimpleName()); - eventBus.post(new PluginChanged(plugin, false)); - - } - catch (InterruptedException | InvocationTargetException ex) - { - throw new PluginInstantiationException(ex); - } - - return true; - } - - public void setPluginEnabled(Plugin plugin, boolean enabled) - { - final String keyName = plugin.getClass().getSimpleName().toLowerCase(); - configManager.setConfiguration(runeliteGroupName, keyName, String.valueOf(enabled)); - } - - public boolean isPluginEnabled(Plugin plugin) - { - final String keyName = plugin.getClass().getSimpleName().toLowerCase(); - final String value = configManager.getConfiguration(runeliteGroupName, keyName); - - if (value != null) - { - return Boolean.valueOf(value); - } - - final PluginDescriptor pluginDescriptor = plugin.getClass().getAnnotation(PluginDescriptor.class); - return pluginDescriptor == null || pluginDescriptor.enabledByDefault(); - } - - private Plugin instantiate(List scannedPlugins, Class clazz) throws PluginInstantiationException - { - PluginDependency[] pluginDependencies = clazz.getAnnotationsByType(PluginDependency.class); - List deps = new ArrayList<>(); - for (PluginDependency pluginDependency : pluginDependencies) - { - Optional dependency = scannedPlugins.stream().filter(p -> p.getClass() == pluginDependency.value()).findFirst(); - if (!dependency.isPresent()) - { - throw new PluginInstantiationException("Unmet dependency for " + clazz.getSimpleName() + ": " + pluginDependency.value().getSimpleName()); - } - deps.add(dependency.get()); - } - - Plugin plugin; - try - { - plugin = clazz.newInstance(); - } - catch (InstantiationException | IllegalAccessException ex) - { - throw new PluginInstantiationException(ex); - } - - try - { - Module pluginModule = (Binder binder) -> - { - binder.bind(clazz).toInstance(plugin); - binder.install(plugin); - for (Plugin p : deps) - { - Module p2 = (Binder binder2) -> - { - binder2.bind((Class) p.getClass()).toInstance(p); - binder2.install(p); - }; - binder.install(p2); - } - }; - Injector pluginInjector = RuneLite.getInjector().createChildInjector(pluginModule); - pluginInjector.injectMembers(plugin); - plugin.injector = pluginInjector; - } - catch (CreationException ex) - { - throw new PluginInstantiationException(ex); - } - - log.debug("Loaded plugin {}", clazz.getSimpleName()); - return plugin; - } - - void add(Plugin plugin) - { - plugins.add(plugin); - } - - void remove(Plugin plugin) - { - plugins.remove(plugin); - } - - public Collection getPlugins() - { - return plugins; - } - - private void schedule(Plugin plugin) - { - for (Method method : plugin.getClass().getMethods()) - { - Schedule schedule = method.getAnnotation(Schedule.class); - - if (schedule == null) - { - continue; - } - - ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin); - log.debug("Scheduled task {}", scheduledMethod); - - scheduler.addScheduledMethod(scheduledMethod); - } - } - - private void unschedule(Plugin plugin) - { - List methods = new ArrayList<>(scheduler.getScheduledMethods()); - - for (ScheduledMethod method : methods) - { - if (method.getObject() != plugin) - { - continue; - } - - log.debug("Removing scheduled task {}", method); - scheduler.removeScheduledMethod(method); - } - } - - /** - * Topologically sort a graph. Uses Kahn's algorithm. - * @param graph - * @param - * @return - */ - private List topologicalSort(Graph graph) - { - MutableGraph graphCopy = Graphs.copyOf(graph); - List l = new ArrayList<>(); - Set s = graphCopy.nodes().stream() - .filter(node -> graphCopy.inDegree(node) == 0) - .collect(Collectors.toSet()); - while (!s.isEmpty()) - { - Iterator it = s.iterator(); - T n = it.next(); - it.remove(); - - l.add(n); - - for (T m : graphCopy.successors(n)) - { - graphCopy.removeEdge(n, m); - if (graphCopy.inDegree(m) == 0) - { - s.add(m); - } - } - } - if (!graphCopy.edges().isEmpty()) - { - throw new RuntimeException("Graph has at least one cycle"); - } - return l; - } -} +/* + * Copyright (c) 2016-2017, Adam + * 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; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.graph.Graph; +import com.google.common.graph.GraphBuilder; +import com.google.common.graph.Graphs; +import com.google.common.graph.MutableGraph; +import com.google.common.reflect.ClassPath; +import com.google.common.reflect.ClassPath.ClassInfo; +import com.google.inject.Binder; +import com.google.inject.CreationException; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledExecutorService; +import java.util.stream.Collectors; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; +import javax.swing.SwingUtilities; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLite; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.PluginChanged; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.task.Schedule; +import net.runelite.client.task.ScheduledMethod; +import net.runelite.client.task.Scheduler; +import net.runelite.client.util.GameEventManager; + +@Singleton +@Slf4j +public class PluginManager +{ + /** + * Base package where the core plugins are + */ + private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins"; + + private final boolean developerMode; + private final EventBus eventBus; + private final Scheduler scheduler; + private final ConfigManager configManager; + private final ScheduledExecutorService executor; + private final Provider sceneTileManager; + private final List plugins = new CopyOnWriteArrayList<>(); + private final List activePlugins = new CopyOnWriteArrayList<>(); + private final String runeliteGroupName = RuneLiteConfig.class + .getAnnotation(ConfigGroup.class).value(); + + @Inject + PluginWatcher pluginWatcher; + + @Setter + boolean isOutdated; + + @Inject + @VisibleForTesting + PluginManager( + @Named("developerMode") final boolean developerMode, + final EventBus eventBus, + final Scheduler scheduler, + final ConfigManager configManager, + final ScheduledExecutorService executor, + final Provider sceneTileManager) + { + this.developerMode = developerMode; + this.eventBus = eventBus; + this.scheduler = scheduler; + this.configManager = configManager; + this.executor = executor; + this.sceneTileManager = sceneTileManager; + } + + public void watch() + { + pluginWatcher.start(); + } + + @Subscribe + public void onSessionOpen(SessionOpen event) + { + refreshPlugins(); + } + + @Subscribe + public void onSessionClose(SessionClose event) + { + refreshPlugins(); + } + + private void refreshPlugins() + { + loadDefaultPluginConfiguration(); + getPlugins() + .forEach(plugin -> executor.submit(() -> + { + try + { + if (!startPlugin(plugin)) + { + stopPlugin(plugin); + } + } + catch (PluginInstantiationException e) + { + log.warn("Error during starting/stopping plugin {}. {}", plugin.getClass().getSimpleName(), e); + } + })); + } + + public Config getPluginConfigProxy(Plugin plugin) + { + final Injector injector = plugin.getInjector(); + + for (Key key : injector.getAllBindings().keySet()) + { + Class type = key.getTypeLiteral().getRawType(); + if (Config.class.isAssignableFrom(type)) + { + return (Config) injector.getInstance(key); + } + } + + return null; + } + + public List getPluginConfigProxies() + { + List injectors = new ArrayList<>(); + injectors.add(RuneLite.getInjector()); + getPlugins().forEach(pl -> injectors.add(pl.getInjector())); + + List list = new ArrayList<>(); + for (Injector injector : injectors) + { + for (Key key : injector.getAllBindings().keySet()) + { + Class type = key.getTypeLiteral().getRawType(); + if (Config.class.isAssignableFrom(type)) + { + Config config = (Config) injector.getInstance(key); + list.add(config); + } + } + } + + return list; + } + + public void loadDefaultPluginConfiguration() + { + for (Object config : getPluginConfigProxies()) + { + configManager.setDefaultConfiguration(config, false); + } + } + + public void loadCorePlugins() throws IOException + { + plugins.addAll(scanAndInstantiate(getClass().getClassLoader(), PLUGIN_PACKAGE)); + } + + public void startCorePlugins() + { + List scannedPlugins = new ArrayList<>(plugins); + for (Plugin plugin : scannedPlugins) + { + try + { + startPlugin(plugin); + } + catch (PluginInstantiationException ex) + { + log.warn("Unable to start plugin {}. {}", plugin.getClass().getSimpleName(), ex); + plugins.remove(plugin); + } + } + } + + List scanAndInstantiate(ClassLoader classLoader, String packageName) throws IOException + { + MutableGraph> graph = GraphBuilder + .directed() + .build(); + + List scannedPlugins = new ArrayList<>(); + ClassPath classPath = ClassPath.from(classLoader); + + ImmutableSet classes = packageName == null ? classPath.getAllClasses() + : classPath.getTopLevelClassesRecursive(packageName); + for (ClassInfo classInfo : classes) + { + Class clazz = classInfo.load(); + PluginDescriptor pluginDescriptor = clazz.getAnnotation(PluginDescriptor.class); + + if (pluginDescriptor == null) + { + if (clazz.getSuperclass() == Plugin.class) + { + log.warn("Class {} is a plugin, but has no plugin descriptor", + clazz); + } + continue; + } + + if (clazz.getSuperclass() != Plugin.class) + { + log.warn("Class {} has plugin descriptor, but is not a plugin", + clazz); + continue; + } + + if (!pluginDescriptor.loadWhenOutdated() && isOutdated) + { + continue; + } + + if (pluginDescriptor.developerPlugin() && !developerMode) + { + continue; + } + + Class pluginClass = (Class) clazz; + graph.addNode(pluginClass); + } + + // Build plugin graph + for (Class pluginClazz : graph.nodes()) + { + PluginDependency[] pluginDependencies = pluginClazz.getAnnotationsByType(PluginDependency.class); + + for (PluginDependency pluginDependency : pluginDependencies) + { + graph.putEdge(pluginClazz, pluginDependency.value()); + } + } + + if (Graphs.hasCycle(graph)) + { + throw new RuntimeException("Plugin dependency graph contains a cycle!"); + } + + List> sortedPlugins = topologicalSort(graph); + sortedPlugins = Lists.reverse(sortedPlugins); + + for (Class pluginClazz : sortedPlugins) + { + Plugin plugin; + try + { + plugin = instantiate(scannedPlugins, (Class) pluginClazz); + } + catch (PluginInstantiationException ex) + { + log.warn("Error instantiating plugin!", ex); + continue; + } + + scannedPlugins.add(plugin); + } + + return scannedPlugins; + } + + public synchronized boolean startPlugin(Plugin plugin) throws PluginInstantiationException + { + if (activePlugins.contains(plugin) || !isPluginEnabled(plugin)) + { + return false; + } + + activePlugins.add(plugin); + + try + { + // plugins always start in the event thread + SwingUtilities.invokeAndWait(() -> + { + try + { + plugin.startUp(); + } + catch (Exception ex) + { + throw new RuntimeException(ex); + } + }); + + log.debug("Plugin {} is now running", plugin.getClass().getSimpleName()); + if (!isOutdated && sceneTileManager != null) + { + final GameEventManager gameEventManager = this.sceneTileManager.get(); + if (gameEventManager != null) + { + gameEventManager.simulateGameEvents(plugin); + } + } + + eventBus.register(plugin); + schedule(plugin); + eventBus.post(new PluginChanged(plugin, true)); + } + catch (InterruptedException | InvocationTargetException | IllegalArgumentException ex) + { + throw new PluginInstantiationException(ex); + } + + return true; + } + + public synchronized boolean stopPlugin(Plugin plugin) throws PluginInstantiationException + { + if (!activePlugins.contains(plugin) || isPluginEnabled(plugin)) + { + return false; + } + + activePlugins.remove(plugin); + + try + { + unschedule(plugin); + eventBus.unregister(plugin); + + // plugins always stop in the event thread + SwingUtilities.invokeAndWait(() -> + { + try + { + plugin.shutDown(); + } + catch (Exception ex) + { + throw new RuntimeException(ex); + } + }); + + log.debug("Plugin {} is now stopped", plugin.getClass().getSimpleName()); + eventBus.post(new PluginChanged(plugin, false)); + + } + catch (InterruptedException | InvocationTargetException ex) + { + throw new PluginInstantiationException(ex); + } + + return true; + } + + public void setPluginEnabled(Plugin plugin, boolean enabled) + { + final String keyName = plugin.getClass().getSimpleName().toLowerCase(); + configManager.setConfiguration(runeliteGroupName, keyName, String.valueOf(enabled)); + } + + public boolean isPluginEnabled(Plugin plugin) + { + final String keyName = plugin.getClass().getSimpleName().toLowerCase(); + final String value = configManager.getConfiguration(runeliteGroupName, keyName); + + if (value != null) + { + return Boolean.valueOf(value); + } + + final PluginDescriptor pluginDescriptor = plugin.getClass().getAnnotation(PluginDescriptor.class); + return pluginDescriptor == null || pluginDescriptor.enabledByDefault(); + } + + private Plugin instantiate(List scannedPlugins, Class clazz) throws PluginInstantiationException + { + PluginDependency[] pluginDependencies = clazz.getAnnotationsByType(PluginDependency.class); + List deps = new ArrayList<>(); + for (PluginDependency pluginDependency : pluginDependencies) + { + Optional dependency = scannedPlugins.stream().filter(p -> p.getClass() == pluginDependency.value()).findFirst(); + if (!dependency.isPresent()) + { + throw new PluginInstantiationException("Unmet dependency for " + clazz.getSimpleName() + ": " + pluginDependency.value().getSimpleName()); + } + deps.add(dependency.get()); + } + + Plugin plugin; + try + { + plugin = clazz.newInstance(); + } + catch (InstantiationException | IllegalAccessException ex) + { + throw new PluginInstantiationException(ex); + } + + try + { + Module pluginModule = (Binder binder) -> + { + binder.bind(clazz).toInstance(plugin); + binder.install(plugin); + for (Plugin p : deps) + { + Module p2 = (Binder binder2) -> + { + binder2.bind((Class) p.getClass()).toInstance(p); + binder2.install(p); + }; + binder.install(p2); + } + }; + Injector pluginInjector = RuneLite.getInjector().createChildInjector(pluginModule); + pluginInjector.injectMembers(plugin); + plugin.injector = pluginInjector; + } + catch (CreationException ex) + { + throw new PluginInstantiationException(ex); + } + + log.debug("Loaded plugin {}", clazz.getSimpleName()); + return plugin; + } + + void add(Plugin plugin) + { + plugins.add(plugin); + } + + void remove(Plugin plugin) + { + plugins.remove(plugin); + } + + public Collection getPlugins() + { + return plugins; + } + + private void schedule(Plugin plugin) + { + for (Method method : plugin.getClass().getMethods()) + { + Schedule schedule = method.getAnnotation(Schedule.class); + + if (schedule == null) + { + continue; + } + + ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin); + log.debug("Scheduled task {}", scheduledMethod); + + scheduler.addScheduledMethod(scheduledMethod); + } + } + + private void unschedule(Plugin plugin) + { + List methods = new ArrayList<>(scheduler.getScheduledMethods()); + + for (ScheduledMethod method : methods) + { + if (method.getObject() != plugin) + { + continue; + } + + log.debug("Removing scheduled task {}", method); + scheduler.removeScheduledMethod(method); + } + } + + /** + * Topologically sort a graph. Uses Kahn's algorithm. + * + * @param graph + * @param + * @return + */ + private List topologicalSort(Graph graph) + { + MutableGraph graphCopy = Graphs.copyOf(graph); + List l = new ArrayList<>(); + Set s = graphCopy.nodes().stream() + .filter(node -> graphCopy.inDegree(node) == 0) + .collect(Collectors.toSet()); + while (!s.isEmpty()) + { + Iterator it = s.iterator(); + T n = it.next(); + it.remove(); + + l.add(n); + + for (T m : graphCopy.successors(n)) + { + graphCopy.removeEdge(n, m); + if (graphCopy.inDegree(m) == 0) + { + s.add(m); + } + } + } + if (!graphCopy.edges().isEmpty()) + { + throw new RuntimeException("Graph has at least one cycle"); + } + return l; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginType.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginType.java index 1ba59834cb..687b79e3d4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginType.java @@ -1,15 +1,16 @@ -package net.runelite.client.plugins; - -public enum PluginType { - - PVM, - PVP, - - UTILITY, - GENERAL_USE, - - EXTERNAL, - - PLUGIN_ORGANIZER - -} +package net.runelite.client.plugins; + +public enum PluginType +{ + + PVM, + PVP, + + UTILITY, + GENERAL_USE, + + EXTERNAL, + + PLUGIN_ORGANIZER + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java index 031d408c03..5505efbee5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java @@ -1,273 +1,273 @@ -/* - * Copyright (c) 2016-2017, Adam - * 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; - -import com.google.inject.Injector; -import com.google.inject.Key; -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URLClassLoader; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; -import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; -import java.nio.file.WatchEvent; -import java.nio.file.WatchEvent.Kind; -import java.nio.file.WatchKey; -import java.nio.file.WatchService; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.RuneLite; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.config.RuneLiteConfig; - -@Singleton -@Slf4j -public class PluginWatcher extends Thread -{ - private static final File BASE = RuneLite.PLUGIN_DIR; - - private final RuneLiteConfig runeliteConfig; - private final PluginManager pluginManager; - private final WatchService watchService; - private final WatchKey watchKey; - - @Inject - private ConfigManager configManager; - - @Inject - public PluginWatcher(RuneLiteConfig runeliteConfig, PluginManager pluginManager) throws IOException - { - this.runeliteConfig = runeliteConfig; - this.pluginManager = pluginManager; - - setName("Plugin Watcher"); - setDaemon(true); - - watchService = FileSystems.getDefault().newWatchService(); - BASE.mkdirs(); - Path dir = BASE.toPath(); - watchKey = dir.register(watchService, ENTRY_MODIFY, ENTRY_DELETE); - } - - public void cancel() - { - watchKey.cancel(); - } - - @Override - public void run() - { - if (runeliteConfig.enablePlugins()) - { - scan(); - } - - for (;;) - { - try - { - WatchKey key = watchService.take(); - Thread.sleep(50); - - if (!runeliteConfig.enablePlugins()) - { - key.reset(); - continue; - } - - for (WatchEvent event : key.pollEvents()) - { - Kind kind = event.kind(); - Path path = (Path) event.context(); - File file = new File(BASE, path.toFile().getName()); - - log.debug("Event {} file {}", kind, file); - - if (kind == ENTRY_MODIFY) - { - Plugin existing = findPluginForFile(file); - if (existing != null) - { - log.info("Reloading plugin {}", file); - unload(existing); - } - else - { - log.info("Loading plugin {}", file); - } - - load(file); - } - else if (kind == ENTRY_DELETE) - { - Plugin existing = findPluginForFile(file); - if (existing != null) - { - log.info("Unloading plugin {}", file); - - unload(existing); - } - } - } - key.reset(); - - } - catch (InterruptedException ex) - { - log.warn("error polling for plugins", ex); - } - } - } - - private void scan() - { - for (File file : BASE.listFiles()) - { - if (!file.getName().endsWith(".jar")) - { - continue; - } - - log.info("Loading plugin from {}", file); - load(file); - } - } - - private Plugin findPluginForFile(File file) - { - for (Plugin plugin : pluginManager.getPlugins()) - { - if (plugin.file != null && plugin.file.equals(file)) - { - return plugin; - } - } - return null; - } - - private void load(File pluginFile) - { - PluginClassLoader loader; - try - { - loader = new PluginClassLoader(pluginFile, getClass().getClassLoader()); - } - catch (MalformedURLException ex) - { - log.warn("Error loading plugin", ex); - return; - } - - List loadedPlugins; - try - { - loadedPlugins = pluginManager.scanAndInstantiate(loader, null); - } - catch (IOException ex) - { - close(loader); - log.warn("Error loading plugin", ex); - return; - } - - if (loadedPlugins.isEmpty()) - { - close(loader); - log.warn("No plugin found in plugin {}", pluginFile); - return; - } - - if (loadedPlugins.size() != 1) - { - close(loader); - log.warn("You can not have more than one plugin per jar"); - return; - } - - Plugin plugin = loadedPlugins.get(0); - plugin.file = pluginFile; - plugin.loader = loader; - - // Initialize default configuration - Injector injector = plugin.getInjector(); - for (Key key : injector.getAllBindings().keySet()) - { - Class type = key.getTypeLiteral().getRawType(); - if (Config.class.isAssignableFrom(type)) - { - Config config = (Config) injector.getInstance(key); - configManager.setDefaultConfiguration(config, false); - } - } - - try - { - pluginManager.startPlugin(plugin); - } - catch (PluginInstantiationException ex) - { - close(loader); - log.warn("unable to start plugin", ex); - return; - } - - // Plugin is now running - pluginManager.add(plugin); - } - - private void unload(Plugin plugin) - { - try - { - pluginManager.stopPlugin(plugin); - } - catch (PluginInstantiationException ex) - { - log.warn("unable to stop plugin", ex); - } - - pluginManager.remove(plugin); // remove it regardless - - close(plugin.loader); - } - - private void close(URLClassLoader classLoader) - { - try - { - classLoader.close(); - } - catch (IOException ex1) - { - log.warn(null, ex1); - } - } - -} +/* + * Copyright (c) 2016-2017, Adam + * 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; + +import com.google.inject.Injector; +import com.google.inject.Key; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URLClassLoader; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; +import java.nio.file.WatchEvent; +import java.nio.file.WatchEvent.Kind; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLite; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; + +@Singleton +@Slf4j +public class PluginWatcher extends Thread +{ + private static final File BASE = RuneLite.PLUGIN_DIR; + + private final RuneLiteConfig runeliteConfig; + private final PluginManager pluginManager; + private final WatchService watchService; + private final WatchKey watchKey; + + @Inject + private ConfigManager configManager; + + @Inject + public PluginWatcher(RuneLiteConfig runeliteConfig, PluginManager pluginManager) throws IOException + { + this.runeliteConfig = runeliteConfig; + this.pluginManager = pluginManager; + + setName("Plugin Watcher"); + setDaemon(true); + + watchService = FileSystems.getDefault().newWatchService(); + BASE.mkdirs(); + Path dir = BASE.toPath(); + watchKey = dir.register(watchService, ENTRY_MODIFY, ENTRY_DELETE); + } + + public void cancel() + { + watchKey.cancel(); + } + + @Override + public void run() + { + if (runeliteConfig.enablePlugins()) + { + scan(); + } + + for (; ; ) + { + try + { + WatchKey key = watchService.take(); + Thread.sleep(50); + + if (!runeliteConfig.enablePlugins()) + { + key.reset(); + continue; + } + + for (WatchEvent event : key.pollEvents()) + { + Kind kind = event.kind(); + Path path = (Path) event.context(); + File file = new File(BASE, path.toFile().getName()); + + log.debug("Event {} file {}", kind, file); + + if (kind == ENTRY_MODIFY) + { + Plugin existing = findPluginForFile(file); + if (existing != null) + { + log.info("Reloading plugin {}", file); + unload(existing); + } + else + { + log.info("Loading plugin {}", file); + } + + load(file); + } + else if (kind == ENTRY_DELETE) + { + Plugin existing = findPluginForFile(file); + if (existing != null) + { + log.info("Unloading plugin {}", file); + + unload(existing); + } + } + } + key.reset(); + + } + catch (InterruptedException ex) + { + log.warn("error polling for plugins", ex); + } + } + } + + private void scan() + { + for (File file : BASE.listFiles()) + { + if (!file.getName().endsWith(".jar")) + { + continue; + } + + log.info("Loading plugin from {}", file); + load(file); + } + } + + private Plugin findPluginForFile(File file) + { + for (Plugin plugin : pluginManager.getPlugins()) + { + if (plugin.file != null && plugin.file.equals(file)) + { + return plugin; + } + } + return null; + } + + private void load(File pluginFile) + { + PluginClassLoader loader; + try + { + loader = new PluginClassLoader(pluginFile, getClass().getClassLoader()); + } + catch (MalformedURLException ex) + { + log.warn("Error loading plugin", ex); + return; + } + + List loadedPlugins; + try + { + loadedPlugins = pluginManager.scanAndInstantiate(loader, null); + } + catch (IOException ex) + { + close(loader); + log.warn("Error loading plugin", ex); + return; + } + + if (loadedPlugins.isEmpty()) + { + close(loader); + log.warn("No plugin found in plugin {}", pluginFile); + return; + } + + if (loadedPlugins.size() != 1) + { + close(loader); + log.warn("You can not have more than one plugin per jar"); + return; + } + + Plugin plugin = loadedPlugins.get(0); + plugin.file = pluginFile; + plugin.loader = loader; + + // Initialize default configuration + Injector injector = plugin.getInjector(); + for (Key key : injector.getAllBindings().keySet()) + { + Class type = key.getTypeLiteral().getRawType(); + if (Config.class.isAssignableFrom(type)) + { + Config config = (Config) injector.getInstance(key); + configManager.setDefaultConfiguration(config, false); + } + } + + try + { + pluginManager.startPlugin(plugin); + } + catch (PluginInstantiationException ex) + { + close(loader); + log.warn("unable to start plugin", ex); + return; + } + + // Plugin is now running + pluginManager.add(plugin); + } + + private void unload(Plugin plugin) + { + try + { + pluginManager.stopPlugin(plugin); + } + catch (PluginInstantiationException ex) + { + log.warn("unable to stop plugin", ex); + } + + pluginManager.remove(plugin); // remove it regardless + + close(plugin.loader); + } + + private void close(URLClassLoader classLoader) + { + try + { + classLoader.close(); + } + catch (IOException ex1) + { + log.warn(null, ex1); + } + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/Requirement.java b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/Requirement.java index d7d0b32a13..9216d120c4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/Requirement.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/Requirement.java @@ -1,28 +1,29 @@ -/* - * Copyright (c) 2019 Abex - * 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.achievementdiary; - -public interface Requirement -{ -} +/* + * Copyright (c) 2019 Abex + * 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.achievementdiary; + +public interface Requirement +{ +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KourendDiaryRequirement.java b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KourendDiaryRequirement.java index 182b288a3b..4fe0ea04c2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KourendDiaryRequirement.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KourendDiaryRequirement.java @@ -1,136 +1,136 @@ -/* - * Copyright (c) 2019 William - * 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.achievementdiary.diaries; - -import net.runelite.api.Favour; -import net.runelite.api.Quest; -import net.runelite.api.Skill; -import net.runelite.client.plugins.achievementdiary.GenericDiaryRequirement; -import net.runelite.client.plugins.achievementdiary.SkillRequirement; -import net.runelite.client.plugins.achievementdiary.QuestRequirement; -import net.runelite.client.plugins.achievementdiary.FavourRequirement; - -public class KourendDiaryRequirement extends GenericDiaryRequirement -{ - public KourendDiaryRequirement() - { - //EASY - add("Mine some Iron at the Mount Karuulm mine.", - new SkillRequirement(Skill.MINING, 15)); - add("Steal from a Hosidius Food Stall.", - new SkillRequirement(Skill.THIEVING, 25), - new FavourRequirement(Favour.HOSIDIUS, 15)); - add("Browse the Warrens General Store.", - new QuestRequirement(Quest.THE_QUEEN_OF_THIEVES, true)); - add("Enter your Player Owned House from Hosidius.", - new SkillRequirement(Skill.CONSTRUCTION, 25)); - add("Create a Strength potion in the Lovakengj Pub.", - new SkillRequirement(Skill.HERBLORE, 12)); - add("Fish a Trout from the River Molch.", - new SkillRequirement(Skill.FISHING, 20)); - - //MEDIUM - add("Travel to the Fairy Ring south of Mount Karuulm.", - new QuestRequirement(Quest.FAIRYTALE_II__CURE_A_QUEEN, true)); - add("Use Kharedst's memoirs to teleport to all five cities in Great Kourend.", - new QuestRequirement(Quest.THE_DEPTHS_OF_DESPAIR), - new QuestRequirement(Quest.THE_QUEEN_OF_THIEVES), - new QuestRequirement(Quest.TALE_OF_THE_RIGHTEOUS), - new QuestRequirement(Quest.THE_FORSAKEN_TOWER), - new QuestRequirement(Quest.THE_ASCENT_OF_ARCEUUS)); - add("Mine some Volcanic sulphur.", - new SkillRequirement(Skill.MINING, 42)); - add("Enter the Farming Guild.", - new SkillRequirement(Skill.FARMING, 45)); - add("Switch to the Necromancy Spellbook at Tyss.", - new FavourRequirement(Favour.ARCEUUS, 60)); - add("Repair a Piscarilius crane.", - new SkillRequirement(Skill.CRAFTING, 30)); - add("Deliver some intelligence to Captain Ginea.", - new FavourRequirement(Favour.SHAYZIEN, 40)); - add("Catch a Bluegill on Molch Island.", - new SkillRequirement(Skill.FISHING, 43), - new SkillRequirement(Skill.HUNTER, 35)); - add("Use the boulder leap in the Arceuus essence mine.", - new SkillRequirement(Skill.AGILITY, 49)); - add("Subdue the Wintertodt.", - new SkillRequirement(Skill.FIREMAKING, 50)); - add("Catch a Chinchompa in the Kourend Woodland.", - new SkillRequirement(Skill.HUNTER, 53), - new QuestRequirement(Quest.EAGLES_PEAK)); - add("Chop some Mahogany logs north of the Farming Guild.", - new SkillRequirement(Skill.WOODCUTTING, 50)); - - //HARD - add("Enter the Woodcutting Guild.", - new SkillRequirement(Skill.WOODCUTTING, 60), - new FavourRequirement(Favour.HOSIDIUS, 75)); - add("Smelt an Adamantite bar in The Forsaken Tower.", - new SkillRequirement(Skill.SMITHING, 70), - new QuestRequirement(Quest.THE_FORSAKEN_TOWER, true)); - add("Kill a Lizardman Shaman in Molch.", - new FavourRequirement(Favour.SHAYZIEN, 100)); - add("Mine some Lovakite.", - new SkillRequirement(Skill.MINING, 65), - new FavourRequirement(Favour.LOVAKENGJ, 30)); - add("Plant some Logavano seeds at the Tithe Farm.", - new SkillRequirement(Skill.FARMING, 74), - new FavourRequirement(Favour.HOSIDIUS, 100)); - add("Teleport to Xeric's Heart using Xeric's Talisman.", - new QuestRequirement(Quest.ARCHITECTURAL_ALLIANCE)); - add("Deliver an artefact to Captain Khaled.", - new SkillRequirement(Skill.THIEVING, 49), - new FavourRequirement(Favour.PISCARILIUS, 75)); - add("Kill a Wyrm in the Karuulm Slayer Dungeon.", - new SkillRequirement(Skill.SLAYER, 62)); - add("Cast Monster Examine on a Troll south of Mount Quidamortem.", - new SkillRequirement(Skill.MAGIC, 66), - new QuestRequirement(Quest.DREAM_MENTOR)); - - //ELITE - add("Craft one or more Blood runes.", - new SkillRequirement(Skill.RUNECRAFT, 77), - new SkillRequirement(Skill.MINING, 38), - new SkillRequirement(Skill.CRAFTING, 38), - new FavourRequirement(Favour.ARCEUUS, 100)); - add("Chop some Redwood logs.", - new SkillRequirement(Skill.WOODCUTTING, 90), - new FavourRequirement(Favour.HOSIDIUS, 75)); - add("Catch an Anglerfish and cook it whilst in Great Kourend.", - new SkillRequirement(Skill.FISHING, 82), - new SkillRequirement(Skill.COOKING, 84), - new FavourRequirement(Favour.PISCARILIUS, 100)); - add("Kill a Hydra in the Karuulm Slayer Dungeon.", - new SkillRequirement(Skill.SLAYER, 95)); - add("Create an Ape Atoll teleport tablet.", - new SkillRequirement(Skill.MAGIC, 90), - new SkillRequirement(Skill.MINING, 38), - new SkillRequirement(Skill.CRAFTING, 38), - new FavourRequirement(Favour.ARCEUUS, 100)); - add("Create your own Battlestaff from scratch within the Farming Guild.", - new SkillRequirement(Skill.FARMING, 85), - new SkillRequirement(Skill.FLETCHING, 40)); - } -} +/* + * Copyright (c) 2019 William + * 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.achievementdiary.diaries; + +import net.runelite.api.Favour; +import net.runelite.api.Quest; +import net.runelite.api.Skill; +import net.runelite.client.plugins.achievementdiary.FavourRequirement; +import net.runelite.client.plugins.achievementdiary.GenericDiaryRequirement; +import net.runelite.client.plugins.achievementdiary.QuestRequirement; +import net.runelite.client.plugins.achievementdiary.SkillRequirement; + +public class KourendDiaryRequirement extends GenericDiaryRequirement +{ + public KourendDiaryRequirement() + { + //EASY + add("Mine some Iron at the Mount Karuulm mine.", + new SkillRequirement(Skill.MINING, 15)); + add("Steal from a Hosidius Food Stall.", + new SkillRequirement(Skill.THIEVING, 25), + new FavourRequirement(Favour.HOSIDIUS, 15)); + add("Browse the Warrens General Store.", + new QuestRequirement(Quest.THE_QUEEN_OF_THIEVES, true)); + add("Enter your Player Owned House from Hosidius.", + new SkillRequirement(Skill.CONSTRUCTION, 25)); + add("Create a Strength potion in the Lovakengj Pub.", + new SkillRequirement(Skill.HERBLORE, 12)); + add("Fish a Trout from the River Molch.", + new SkillRequirement(Skill.FISHING, 20)); + + //MEDIUM + add("Travel to the Fairy Ring south of Mount Karuulm.", + new QuestRequirement(Quest.FAIRYTALE_II__CURE_A_QUEEN, true)); + add("Use Kharedst's memoirs to teleport to all five cities in Great Kourend.", + new QuestRequirement(Quest.THE_DEPTHS_OF_DESPAIR), + new QuestRequirement(Quest.THE_QUEEN_OF_THIEVES), + new QuestRequirement(Quest.TALE_OF_THE_RIGHTEOUS), + new QuestRequirement(Quest.THE_FORSAKEN_TOWER), + new QuestRequirement(Quest.THE_ASCENT_OF_ARCEUUS)); + add("Mine some Volcanic sulphur.", + new SkillRequirement(Skill.MINING, 42)); + add("Enter the Farming Guild.", + new SkillRequirement(Skill.FARMING, 45)); + add("Switch to the Necromancy Spellbook at Tyss.", + new FavourRequirement(Favour.ARCEUUS, 60)); + add("Repair a Piscarilius crane.", + new SkillRequirement(Skill.CRAFTING, 30)); + add("Deliver some intelligence to Captain Ginea.", + new FavourRequirement(Favour.SHAYZIEN, 40)); + add("Catch a Bluegill on Molch Island.", + new SkillRequirement(Skill.FISHING, 43), + new SkillRequirement(Skill.HUNTER, 35)); + add("Use the boulder leap in the Arceuus essence mine.", + new SkillRequirement(Skill.AGILITY, 49)); + add("Subdue the Wintertodt.", + new SkillRequirement(Skill.FIREMAKING, 50)); + add("Catch a Chinchompa in the Kourend Woodland.", + new SkillRequirement(Skill.HUNTER, 53), + new QuestRequirement(Quest.EAGLES_PEAK)); + add("Chop some Mahogany logs north of the Farming Guild.", + new SkillRequirement(Skill.WOODCUTTING, 50)); + + //HARD + add("Enter the Woodcutting Guild.", + new SkillRequirement(Skill.WOODCUTTING, 60), + new FavourRequirement(Favour.HOSIDIUS, 75)); + add("Smelt an Adamantite bar in The Forsaken Tower.", + new SkillRequirement(Skill.SMITHING, 70), + new QuestRequirement(Quest.THE_FORSAKEN_TOWER, true)); + add("Kill a Lizardman Shaman in Molch.", + new FavourRequirement(Favour.SHAYZIEN, 100)); + add("Mine some Lovakite.", + new SkillRequirement(Skill.MINING, 65), + new FavourRequirement(Favour.LOVAKENGJ, 30)); + add("Plant some Logavano seeds at the Tithe Farm.", + new SkillRequirement(Skill.FARMING, 74), + new FavourRequirement(Favour.HOSIDIUS, 100)); + add("Teleport to Xeric's Heart using Xeric's Talisman.", + new QuestRequirement(Quest.ARCHITECTURAL_ALLIANCE)); + add("Deliver an artefact to Captain Khaled.", + new SkillRequirement(Skill.THIEVING, 49), + new FavourRequirement(Favour.PISCARILIUS, 75)); + add("Kill a Wyrm in the Karuulm Slayer Dungeon.", + new SkillRequirement(Skill.SLAYER, 62)); + add("Cast Monster Examine on a Troll south of Mount Quidamortem.", + new SkillRequirement(Skill.MAGIC, 66), + new QuestRequirement(Quest.DREAM_MENTOR)); + + //ELITE + add("Craft one or more Blood runes.", + new SkillRequirement(Skill.RUNECRAFT, 77), + new SkillRequirement(Skill.MINING, 38), + new SkillRequirement(Skill.CRAFTING, 38), + new FavourRequirement(Favour.ARCEUUS, 100)); + add("Chop some Redwood logs.", + new SkillRequirement(Skill.WOODCUTTING, 90), + new FavourRequirement(Favour.HOSIDIUS, 75)); + add("Catch an Anglerfish and cook it whilst in Great Kourend.", + new SkillRequirement(Skill.FISHING, 82), + new SkillRequirement(Skill.COOKING, 84), + new FavourRequirement(Favour.PISCARILIUS, 100)); + add("Kill a Hydra in the Karuulm Slayer Dungeon.", + new SkillRequirement(Skill.SLAYER, 95)); + add("Create an Ape Atoll teleport tablet.", + new SkillRequirement(Skill.MAGIC, 90), + new SkillRequirement(Skill.MINING, 38), + new SkillRequirement(Skill.CRAFTING, 38), + new FavourRequirement(Favour.ARCEUUS, 100)); + add("Create your own Battlestaff from scratch within the Farming Guild.", + new SkillRequirement(Skill.FARMING, 85), + new SkillRequirement(Skill.FLETCHING, 40)); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java index e9c205f64f..5599fca791 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java @@ -1,141 +1,141 @@ -/* - * Copyright (c) 2018, Adam - * Copyright (c) 2018, Cas - * 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.agility; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.geom.Area; -import java.util.List; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Point; -import net.runelite.api.Tile; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.game.AgilityShortcut; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; - -class AgilityOverlay extends Overlay -{ - private static final int MAX_DISTANCE = 2350; - private static final Color SHORTCUT_HIGH_LEVEL_COLOR = Color.ORANGE; - - private final Client client; - private final AgilityPlugin plugin; - private final AgilityConfig config; - - @Inject - private AgilityOverlay(Client client, AgilityPlugin plugin, AgilityConfig config) - { - super(plugin); - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.client = client; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D graphics) - { - LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation(); - Point mousePosition = client.getMouseCanvasPosition(); - final List marksOfGrace = plugin.getMarksOfGrace(); - plugin.getObstacles().forEach((object, obstacle) -> - { - if (Obstacles.SHORTCUT_OBSTACLE_IDS.containsKey(object.getId()) && !config.highlightShortcuts() || - Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId()) && !config.showTrapOverlay()) - { - return; - } - - Tile tile = obstacle.getTile(); - if (tile.getPlane() == client.getPlane() - && object.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) - { - // This assumes that the obstacle is not clickable. - if (Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId())) - { - Polygon polygon = object.getCanvasTilePoly(); - if (polygon != null) - { - OverlayUtil.renderPolygon(graphics, polygon, config.getTrapColor()); - } - return; - } - Area objectClickbox = object.getClickbox(); - if (objectClickbox != null) - { - AgilityShortcut agilityShortcut = obstacle.getShortcut(); - Color configColor = agilityShortcut == null || agilityShortcut.getLevel() <= plugin.getAgilityLevel() ? config.getOverlayColor() : SHORTCUT_HIGH_LEVEL_COLOR; - if (config.highlightMarks() && !marksOfGrace.isEmpty()) - { - configColor = config.getMarkColor(); - } - - if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) - { - graphics.setColor(configColor.darker()); - } - else - { - graphics.setColor(configColor); - } - - graphics.draw(objectClickbox); - graphics.setColor(new Color(configColor.getRed(), configColor.getGreen(), configColor.getBlue(), 50)); - graphics.fill(objectClickbox); - } - } - - }); - - if (config.highlightMarks() && !marksOfGrace.isEmpty()) - { - for (Tile markOfGraceTile : marksOfGrace) - { - if (markOfGraceTile.getPlane() == client.getPlane() && markOfGraceTile.getItemLayer() != null - && markOfGraceTile.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) - { - final Polygon poly = markOfGraceTile.getItemLayer().getCanvasTilePoly(); - - if (poly == null) - { - continue; - } - - OverlayUtil.renderPolygon(graphics, poly, config.getMarkColor()); - } - } - } - - return null; - } -} +/* + * Copyright (c) 2018, Adam + * Copyright (c) 2018, Cas + * 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.agility; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.geom.Area; +import java.util.List; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.Tile; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.game.AgilityShortcut; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; + +class AgilityOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2350; + private static final Color SHORTCUT_HIGH_LEVEL_COLOR = Color.ORANGE; + + private final Client client; + private final AgilityPlugin plugin; + private final AgilityConfig config; + + @Inject + private AgilityOverlay(Client client, AgilityPlugin plugin, AgilityConfig config) + { + super(plugin); + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation(); + Point mousePosition = client.getMouseCanvasPosition(); + final List marksOfGrace = plugin.getMarksOfGrace(); + plugin.getObstacles().forEach((object, obstacle) -> + { + if (Obstacles.SHORTCUT_OBSTACLE_IDS.containsKey(object.getId()) && !config.highlightShortcuts() || + Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId()) && !config.showTrapOverlay()) + { + return; + } + + Tile tile = obstacle.getTile(); + if (tile.getPlane() == client.getPlane() + && object.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) + { + // This assumes that the obstacle is not clickable. + if (Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId())) + { + Polygon polygon = object.getCanvasTilePoly(); + if (polygon != null) + { + OverlayUtil.renderPolygon(graphics, polygon, config.getTrapColor()); + } + return; + } + Area objectClickbox = object.getClickbox(); + if (objectClickbox != null) + { + AgilityShortcut agilityShortcut = obstacle.getShortcut(); + Color configColor = agilityShortcut == null || agilityShortcut.getLevel() <= plugin.getAgilityLevel() ? config.getOverlayColor() : SHORTCUT_HIGH_LEVEL_COLOR; + if (config.highlightMarks() && !marksOfGrace.isEmpty()) + { + configColor = config.getMarkColor(); + } + + if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) + { + graphics.setColor(configColor.darker()); + } + else + { + graphics.setColor(configColor); + } + + graphics.draw(objectClickbox); + graphics.setColor(new Color(configColor.getRed(), configColor.getGreen(), configColor.getBlue(), 50)); + graphics.fill(objectClickbox); + } + } + + }); + + if (config.highlightMarks() && !marksOfGrace.isEmpty()) + { + for (Tile markOfGraceTile : marksOfGrace) + { + if (markOfGraceTile.getPlane() == client.getPlane() && markOfGraceTile.getItemLayer() != null + && markOfGraceTile.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) + { + final Polygon poly = markOfGraceTile.getItemLayer().getCanvasTilePoly(); + + if (poly == null) + { + continue; + } + + OverlayUtil.renderPolygon(graphics, poly, config.getMarkColor()); + } + } + } + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java index 942fdd93b0..3074ab1eb5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java @@ -1,462 +1,463 @@ -/* - * Copyright (c) 2018, Adam - * 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.agility; - -import com.google.inject.Provides; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.inject.Inject; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.Item; -import net.runelite.api.ItemID; -import static net.runelite.api.ItemID.AGILITY_ARENA_TICKET; -import net.runelite.api.Player; -import net.runelite.api.Skill; -import static net.runelite.api.Skill.AGILITY; -import net.runelite.api.Tile; -import net.runelite.api.TileObject; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.BoostedLevelChanged; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.DecorativeObjectChanged; -import net.runelite.api.events.DecorativeObjectDespawned; -import net.runelite.api.events.DecorativeObjectSpawned; -import net.runelite.api.events.ExperienceChanged; -import net.runelite.api.events.GameObjectChanged; -import net.runelite.api.events.GameObjectDespawned; -import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.GroundObjectChanged; -import net.runelite.api.events.GroundObjectDespawned; -import net.runelite.api.events.GroundObjectSpawned; -import net.runelite.api.events.ItemDespawned; -import net.runelite.api.events.ItemSpawned; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.events.WallObjectChanged; -import net.runelite.api.events.WallObjectDespawned; -import net.runelite.api.events.WallObjectSpawned; -import net.runelite.client.Notifier; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.AgilityShortcut; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; -import net.runelite.api.MenuEntry; -import net.runelite.client.util.ColorUtil; -import net.runelite.api.MenuAction; -import java.awt.Color; - -@PluginDescriptor( - name = "Agility", - description = "Show helpful information about agility courses and obstacles", - tags = {"grace", "marks", "overlay", "shortcuts", "skilling", "traps"} -) -@Slf4j -public class AgilityPlugin extends Plugin -{ - private static final int AGILITY_ARENA_REGION_ID = 11157; - - @Getter - private final Map obstacles = new HashMap<>(); - - @Getter - private final List marksOfGrace = new ArrayList<>(); - - @Inject - private OverlayManager overlayManager; - - @Inject - private AgilityOverlay agilityOverlay; - - @Inject - private LapCounterOverlay lapCounterOverlay; - - @Inject - private Notifier notifier; - - @Inject - private Client client; - - @Inject - private InfoBoxManager infoBoxManager; - - @Inject - private AgilityConfig config; - - @Inject - private ItemManager itemManager; - - @Getter - private AgilitySession session; - - private int lastAgilityXp; - private WorldPoint lastArenaTicketPosition; - - @Getter - private int agilityLevel; - - @Provides - AgilityConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(AgilityConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(agilityOverlay); - overlayManager.add(lapCounterOverlay); - agilityLevel = client.getBoostedSkillLevel(Skill.AGILITY); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(agilityOverlay); - overlayManager.remove(lapCounterOverlay); - marksOfGrace.clear(); - obstacles.clear(); - session = null; - agilityLevel = 0; - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - switch (event.getGameState()) - { - case HOPPING: - case LOGIN_SCREEN: - session = null; - lastArenaTicketPosition = null; - removeAgilityArenaTimer(); - break; - case LOADING: - marksOfGrace.clear(); - obstacles.clear(); - break; - case LOGGED_IN: - if (!isInAgilityArena()) - { - lastArenaTicketPosition = null; - removeAgilityArenaTimer(); - } - break; - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (!config.showAgilityArenaTimer()) - { - removeAgilityArenaTimer(); - } - } - - @Subscribe - public void onExperienceChanged(ExperienceChanged event) - { - if (event.getSkill() != AGILITY || !config.showLapCount()) - { - return; - } - - // Determine how much EXP was actually gained - int agilityXp = client.getSkillExperience(AGILITY); - int skillGained = agilityXp - lastAgilityXp; - lastAgilityXp = agilityXp; - - // Get course - Courses course = Courses.getCourse(client.getLocalPlayer().getWorldLocation().getRegionID()); - if (course == null - || (course.getCourseEndWorldPoints().length == 0 - ? Math.abs(course.getLastObstacleXp() - skillGained) > 1 - : Arrays.stream(course.getCourseEndWorldPoints()).noneMatch(wp -> wp.equals(client.getLocalPlayer().getWorldLocation())))) - { - return; - } - - if (session != null && session.getCourse() == course) - { - session.incrementLapCount(client); - } - else - { - session = new AgilitySession(course); - // New course found, reset lap count and set new course - session.resetLapCount(); - session.incrementLapCount(client); - } - } - - - @Subscribe - public void onBoostedLevelChanged(BoostedLevelChanged boostedLevelChanged) - { - Skill skill = boostedLevelChanged.getSkill(); - if (skill == AGILITY) - { - agilityLevel = client.getBoostedSkillLevel(skill); - } - } - - @Subscribe - public void onItemSpawned(ItemSpawned itemSpawned) - { - if (obstacles.isEmpty()) - { - return; - } - - final Item item = itemSpawned.getItem(); - final Tile tile = itemSpawned.getTile(); - - if (item.getId() == ItemID.MARK_OF_GRACE) - { - marksOfGrace.add(tile); - } - } - - @Subscribe - public void onItemDespawned(ItemDespawned itemDespawned) - { - final Tile tile = itemDespawned.getTile(); - marksOfGrace.remove(tile); - } - - @Subscribe - public void onGameTick(GameTick tick) - { - if (isInAgilityArena()) - { - // Hint arrow has no plane, and always returns the current plane - WorldPoint newTicketPosition = client.getHintArrowPoint(); - WorldPoint oldTickPosition = lastArenaTicketPosition; - - lastArenaTicketPosition = newTicketPosition; - - if (oldTickPosition != null && newTicketPosition != null - && (oldTickPosition.getX() != newTicketPosition.getX() || oldTickPosition.getY() != newTicketPosition.getY())) - { - log.debug("Ticked position moved from {} to {}", oldTickPosition, newTicketPosition); - - if (config.notifyAgilityArena()) - { - notifier.notify("Ticket location changed"); - } - - if (config.showAgilityArenaTimer()) - { - showNewAgilityArenaTimer(); - } - } - } - } - - private boolean isInAgilityArena() - { - Player local = client.getLocalPlayer(); - if (local == null) - { - return false; - } - - WorldPoint location = local.getWorldLocation(); - return location.getRegionID() == AGILITY_ARENA_REGION_ID; - } - - private void removeAgilityArenaTimer() - { - infoBoxManager.removeIf(infoBox -> infoBox instanceof AgilityArenaTimer); - } - - private void showNewAgilityArenaTimer() - { - removeAgilityArenaTimer(); - infoBoxManager.addInfoBox(new AgilityArenaTimer(this, itemManager.getImage(AGILITY_ARENA_TICKET))); - } - - @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) - { - onTileObject(event.getTile(), null, event.getGameObject()); - } - - @Subscribe - public void onGameObjectChanged(GameObjectChanged event) - { - onTileObject(event.getTile(), event.getPrevious(), event.getGameObject()); - } - - @Subscribe - public void onGameObjectDespawned(GameObjectDespawned event) - { - onTileObject(event.getTile(), event.getGameObject(), null); - } - - @Subscribe - public void onGroundObjectSpawned(GroundObjectSpawned event) - { - onTileObject(event.getTile(), null, event.getGroundObject()); - } - - @Subscribe - public void onGroundObjectChanged(GroundObjectChanged event) - { - onTileObject(event.getTile(), event.getPrevious(), event.getGroundObject()); - } - - @Subscribe - public void onGroundObjectDespawned(GroundObjectDespawned event) - { - onTileObject(event.getTile(), event.getGroundObject(), null); - } - - @Subscribe - public void onWallObjectSpawned(WallObjectSpawned event) - { - onTileObject(event.getTile(), null, event.getWallObject()); - } - - @Subscribe - public void onWallObjectChanged(WallObjectChanged event) - { - onTileObject(event.getTile(), event.getPrevious(), event.getWallObject()); - } - - @Subscribe - public void onWallObjectDespawned(WallObjectDespawned event) - { - onTileObject(event.getTile(), event.getWallObject(), null); - } - - @Subscribe - public void onDecorativeObjectSpawned(DecorativeObjectSpawned event) - { - onTileObject(event.getTile(), null, event.getDecorativeObject()); - } - - @Subscribe - public void onDecorativeObjectChanged(DecorativeObjectChanged event) - { - onTileObject(event.getTile(), event.getPrevious(), event.getDecorativeObject()); - } - - @Subscribe - public void onDecorativeObjectDespawned(DecorativeObjectDespawned event) - { - onTileObject(event.getTile(), event.getDecorativeObject(), null); - } - - private void onTileObject(Tile tile, TileObject oldObject, TileObject newObject) - { - obstacles.remove(oldObject); - - if (newObject == null) - { - return; - } - - if (Obstacles.COURSE_OBSTACLE_IDS.contains(newObject.getId()) || - (Obstacles.TRAP_OBSTACLE_IDS.contains(newObject.getId()) - && Obstacles.TRAP_OBSTACLE_REGIONS.contains(newObject.getWorldLocation().getRegionID()))) - { - obstacles.put(newObject, new Obstacle(tile, null)); - } - - if (Obstacles.SHORTCUT_OBSTACLE_IDS.containsKey(newObject.getId())) - { - AgilityShortcut closestShortcut = null; - int distance = -1; - - // Find the closest shortcut to this object - for (AgilityShortcut shortcut : Obstacles.SHORTCUT_OBSTACLE_IDS.get(newObject.getId())) - { - if (shortcut.getWorldLocation() == null) - { - closestShortcut = shortcut; - break; - } - else - { - int newDistance = shortcut.getWorldLocation().distanceTo2D(newObject.getWorldLocation()); - if (closestShortcut == null || newDistance < distance) - { - closestShortcut = shortcut; - distance = newDistance; - } - } - } - - if (closestShortcut != null) - { - obstacles.put(newObject, new Obstacle(tile, closestShortcut)); - } - } - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) - { - if (!config.showShortcutLevel()) - { - return; - } - - //Guarding against non-first option because agility shortcuts are always that type of event. - if (event.getType() != MenuAction.GAME_OBJECT_FIRST_OPTION.getId()) - { - return; - } - - final int entryId = event.getIdentifier(); - MenuEntry[] menuEntries = client.getMenuEntries(); - - for (Obstacle nearbyObstacle : getObstacles().values()) - { - AgilityShortcut shortcut = nearbyObstacle.getShortcut(); - if (shortcut != null && Arrays.stream(shortcut.getObstacleIds()).anyMatch(i -> i == entryId)) { - MenuEntry entry = menuEntries[menuEntries.length - 1]; - int level = shortcut.getLevel(); - Color color = level <= getAgilityLevel() ? Color.GREEN : Color.RED; - String requirementText = " (level-" + level + ")"; - - entry.setTarget(event.getTarget() + ColorUtil.prependColorTag(requirementText, color)); - client.setMenuEntries(menuEntries); - return; - } - } - } -} +/* + * Copyright (c) 2018, Adam + * 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.agility; + +import com.google.inject.Provides; +import java.awt.Color; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.inject.Inject; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.Item; +import net.runelite.api.ItemID; +import static net.runelite.api.ItemID.AGILITY_ARENA_TICKET; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.Player; +import net.runelite.api.Skill; +import static net.runelite.api.Skill.AGILITY; +import net.runelite.api.Tile; +import net.runelite.api.TileObject; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.BoostedLevelChanged; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.DecorativeObjectChanged; +import net.runelite.api.events.DecorativeObjectDespawned; +import net.runelite.api.events.DecorativeObjectSpawned; +import net.runelite.api.events.ExperienceChanged; +import net.runelite.api.events.GameObjectChanged; +import net.runelite.api.events.GameObjectDespawned; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.GroundObjectChanged; +import net.runelite.api.events.GroundObjectDespawned; +import net.runelite.api.events.GroundObjectSpawned; +import net.runelite.api.events.ItemDespawned; +import net.runelite.api.events.ItemSpawned; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.WallObjectChanged; +import net.runelite.api.events.WallObjectDespawned; +import net.runelite.api.events.WallObjectSpawned; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.AgilityShortcut; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.util.ColorUtil; + +@PluginDescriptor( + name = "Agility", + description = "Show helpful information about agility courses and obstacles", + tags = {"grace", "marks", "overlay", "shortcuts", "skilling", "traps"} +) +@Slf4j +public class AgilityPlugin extends Plugin +{ + private static final int AGILITY_ARENA_REGION_ID = 11157; + + @Getter + private final Map obstacles = new HashMap<>(); + + @Getter + private final List marksOfGrace = new ArrayList<>(); + + @Inject + private OverlayManager overlayManager; + + @Inject + private AgilityOverlay agilityOverlay; + + @Inject + private LapCounterOverlay lapCounterOverlay; + + @Inject + private Notifier notifier; + + @Inject + private Client client; + + @Inject + private InfoBoxManager infoBoxManager; + + @Inject + private AgilityConfig config; + + @Inject + private ItemManager itemManager; + + @Getter + private AgilitySession session; + + private int lastAgilityXp; + private WorldPoint lastArenaTicketPosition; + + @Getter + private int agilityLevel; + + @Provides + AgilityConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(AgilityConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(agilityOverlay); + overlayManager.add(lapCounterOverlay); + agilityLevel = client.getBoostedSkillLevel(Skill.AGILITY); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(agilityOverlay); + overlayManager.remove(lapCounterOverlay); + marksOfGrace.clear(); + obstacles.clear(); + session = null; + agilityLevel = 0; + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + switch (event.getGameState()) + { + case HOPPING: + case LOGIN_SCREEN: + session = null; + lastArenaTicketPosition = null; + removeAgilityArenaTimer(); + break; + case LOADING: + marksOfGrace.clear(); + obstacles.clear(); + break; + case LOGGED_IN: + if (!isInAgilityArena()) + { + lastArenaTicketPosition = null; + removeAgilityArenaTimer(); + } + break; + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!config.showAgilityArenaTimer()) + { + removeAgilityArenaTimer(); + } + } + + @Subscribe + public void onExperienceChanged(ExperienceChanged event) + { + if (event.getSkill() != AGILITY || !config.showLapCount()) + { + return; + } + + // Determine how much EXP was actually gained + int agilityXp = client.getSkillExperience(AGILITY); + int skillGained = agilityXp - lastAgilityXp; + lastAgilityXp = agilityXp; + + // Get course + Courses course = Courses.getCourse(client.getLocalPlayer().getWorldLocation().getRegionID()); + if (course == null + || (course.getCourseEndWorldPoints().length == 0 + ? Math.abs(course.getLastObstacleXp() - skillGained) > 1 + : Arrays.stream(course.getCourseEndWorldPoints()).noneMatch(wp -> wp.equals(client.getLocalPlayer().getWorldLocation())))) + { + return; + } + + if (session != null && session.getCourse() == course) + { + session.incrementLapCount(client); + } + else + { + session = new AgilitySession(course); + // New course found, reset lap count and set new course + session.resetLapCount(); + session.incrementLapCount(client); + } + } + + + @Subscribe + public void onBoostedLevelChanged(BoostedLevelChanged boostedLevelChanged) + { + Skill skill = boostedLevelChanged.getSkill(); + if (skill == AGILITY) + { + agilityLevel = client.getBoostedSkillLevel(skill); + } + } + + @Subscribe + public void onItemSpawned(ItemSpawned itemSpawned) + { + if (obstacles.isEmpty()) + { + return; + } + + final Item item = itemSpawned.getItem(); + final Tile tile = itemSpawned.getTile(); + + if (item.getId() == ItemID.MARK_OF_GRACE) + { + marksOfGrace.add(tile); + } + } + + @Subscribe + public void onItemDespawned(ItemDespawned itemDespawned) + { + final Tile tile = itemDespawned.getTile(); + marksOfGrace.remove(tile); + } + + @Subscribe + public void onGameTick(GameTick tick) + { + if (isInAgilityArena()) + { + // Hint arrow has no plane, and always returns the current plane + WorldPoint newTicketPosition = client.getHintArrowPoint(); + WorldPoint oldTickPosition = lastArenaTicketPosition; + + lastArenaTicketPosition = newTicketPosition; + + if (oldTickPosition != null && newTicketPosition != null + && (oldTickPosition.getX() != newTicketPosition.getX() || oldTickPosition.getY() != newTicketPosition.getY())) + { + log.debug("Ticked position moved from {} to {}", oldTickPosition, newTicketPosition); + + if (config.notifyAgilityArena()) + { + notifier.notify("Ticket location changed"); + } + + if (config.showAgilityArenaTimer()) + { + showNewAgilityArenaTimer(); + } + } + } + } + + private boolean isInAgilityArena() + { + Player local = client.getLocalPlayer(); + if (local == null) + { + return false; + } + + WorldPoint location = local.getWorldLocation(); + return location.getRegionID() == AGILITY_ARENA_REGION_ID; + } + + private void removeAgilityArenaTimer() + { + infoBoxManager.removeIf(infoBox -> infoBox instanceof AgilityArenaTimer); + } + + private void showNewAgilityArenaTimer() + { + removeAgilityArenaTimer(); + infoBoxManager.addInfoBox(new AgilityArenaTimer(this, itemManager.getImage(AGILITY_ARENA_TICKET))); + } + + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) + { + onTileObject(event.getTile(), null, event.getGameObject()); + } + + @Subscribe + public void onGameObjectChanged(GameObjectChanged event) + { + onTileObject(event.getTile(), event.getPrevious(), event.getGameObject()); + } + + @Subscribe + public void onGameObjectDespawned(GameObjectDespawned event) + { + onTileObject(event.getTile(), event.getGameObject(), null); + } + + @Subscribe + public void onGroundObjectSpawned(GroundObjectSpawned event) + { + onTileObject(event.getTile(), null, event.getGroundObject()); + } + + @Subscribe + public void onGroundObjectChanged(GroundObjectChanged event) + { + onTileObject(event.getTile(), event.getPrevious(), event.getGroundObject()); + } + + @Subscribe + public void onGroundObjectDespawned(GroundObjectDespawned event) + { + onTileObject(event.getTile(), event.getGroundObject(), null); + } + + @Subscribe + public void onWallObjectSpawned(WallObjectSpawned event) + { + onTileObject(event.getTile(), null, event.getWallObject()); + } + + @Subscribe + public void onWallObjectChanged(WallObjectChanged event) + { + onTileObject(event.getTile(), event.getPrevious(), event.getWallObject()); + } + + @Subscribe + public void onWallObjectDespawned(WallObjectDespawned event) + { + onTileObject(event.getTile(), event.getWallObject(), null); + } + + @Subscribe + public void onDecorativeObjectSpawned(DecorativeObjectSpawned event) + { + onTileObject(event.getTile(), null, event.getDecorativeObject()); + } + + @Subscribe + public void onDecorativeObjectChanged(DecorativeObjectChanged event) + { + onTileObject(event.getTile(), event.getPrevious(), event.getDecorativeObject()); + } + + @Subscribe + public void onDecorativeObjectDespawned(DecorativeObjectDespawned event) + { + onTileObject(event.getTile(), event.getDecorativeObject(), null); + } + + private void onTileObject(Tile tile, TileObject oldObject, TileObject newObject) + { + obstacles.remove(oldObject); + + if (newObject == null) + { + return; + } + + if (Obstacles.COURSE_OBSTACLE_IDS.contains(newObject.getId()) || + (Obstacles.TRAP_OBSTACLE_IDS.contains(newObject.getId()) + && Obstacles.TRAP_OBSTACLE_REGIONS.contains(newObject.getWorldLocation().getRegionID()))) + { + obstacles.put(newObject, new Obstacle(tile, null)); + } + + if (Obstacles.SHORTCUT_OBSTACLE_IDS.containsKey(newObject.getId())) + { + AgilityShortcut closestShortcut = null; + int distance = -1; + + // Find the closest shortcut to this object + for (AgilityShortcut shortcut : Obstacles.SHORTCUT_OBSTACLE_IDS.get(newObject.getId())) + { + if (shortcut.getWorldLocation() == null) + { + closestShortcut = shortcut; + break; + } + else + { + int newDistance = shortcut.getWorldLocation().distanceTo2D(newObject.getWorldLocation()); + if (closestShortcut == null || newDistance < distance) + { + closestShortcut = shortcut; + distance = newDistance; + } + } + } + + if (closestShortcut != null) + { + obstacles.put(newObject, new Obstacle(tile, closestShortcut)); + } + } + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + if (!config.showShortcutLevel()) + { + return; + } + + //Guarding against non-first option because agility shortcuts are always that type of event. + if (event.getType() != MenuAction.GAME_OBJECT_FIRST_OPTION.getId()) + { + return; + } + + final int entryId = event.getIdentifier(); + MenuEntry[] menuEntries = client.getMenuEntries(); + + for (Obstacle nearbyObstacle : getObstacles().values()) + { + AgilityShortcut shortcut = nearbyObstacle.getShortcut(); + if (shortcut != null && Arrays.stream(shortcut.getObstacleIds()).anyMatch(i -> i == entryId)) + { + MenuEntry entry = menuEntries[menuEntries.length - 1]; + int level = shortcut.getLevel(); + Color color = level <= getAgilityLevel() ? Color.GREEN : Color.RED; + String requirementText = " (level-" + level + ")"; + + entry.setTarget(event.getTarget() + ColorUtil.prependColorTag(requirementText, color)); + client.setMenuEntries(menuEntries); + return; + } + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java index 92df605a36..8017ba2581 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java @@ -1,131 +1,334 @@ -/* - * Copyright (c) 2018, SomeoneWithAnInternetConnection - * 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.agility; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimap; -import java.util.List; -import java.util.Set; -import static net.runelite.api.NullObjectID.NULL_10872; -import static net.runelite.api.NullObjectID.NULL_10873; -import static net.runelite.api.NullObjectID.NULL_12945; -import static net.runelite.api.NullObjectID.NULL_18083; -import static net.runelite.api.NullObjectID.NULL_18116; -import static net.runelite.api.NullObjectID.NULL_18122; -import static net.runelite.api.NullObjectID.NULL_18124; -import static net.runelite.api.NullObjectID.NULL_18129; -import static net.runelite.api.NullObjectID.NULL_18130; -import static net.runelite.api.NullObjectID.NULL_18132; -import static net.runelite.api.NullObjectID.NULL_18133; -import static net.runelite.api.NullObjectID.NULL_18135; -import static net.runelite.api.NullObjectID.NULL_18136; -import static net.runelite.api.NullObjectID.NULL_3550; -import static net.runelite.api.ObjectID.*; -import net.runelite.client.game.AgilityShortcut; - -class Obstacles -{ - static final Set COURSE_OBSTACLE_IDS = ImmutableSet.of( - // Gnome - OBSTACLE_NET_23134, TREE_BRANCH_23559, TREE_BRANCH_23560, OBSTACLE_NET_23135, OBSTACLE_PIPE_23138, - OBSTACLE_PIPE_23139, LOG_BALANCE_23145, BALANCING_ROPE_23557, - // Brimhaven - PLANK_3572, PLANK_3571, PLANK_3570, ROPE_SWING, PILLAR_3578, LOW_WALL, LOG_BALANCE, LOG_BALANCE_3557, - BALANCING_LEDGE_3561, BALANCING_LEDGE, MONKEY_BARS_3564, BALANCING_ROPE, HAND_HOLDS_3583, - // Draynor - ROUGH_WALL, TIGHTROPE, TIGHTROPE_10075, NARROW_WALL, WALL_10084, GAP_10085, CRATE_10086, STILE_7527, - // Al-Kharid - ROUGH_WALL_10093, TIGHTROPE_10284, CABLE, ZIP_LINE, TROPICAL_TREE_10357, ROOF_TOP_BEAMS, - TIGHTROPE_10583, GAP_10352, - // Pyramid - STAIRS_10857, LOW_WALL_10865, LEDGE_10860, PLANK_10868, GAP_10882, LEDGE_10886, STAIRS_10857, GAP_10884, - GAP_10859, GAP_10861, LOW_WALL_10865, GAP_10859, LEDGE_10888, PLANK_10868, CLIMBING_ROCKS_10851, DOORWAY_10855, - // Varrock - ROUGH_WALL_10586, CLOTHES_LINE, GAP_10642, WALL_10777, GAP_10778, GAP_10779, GAP_10780, LEDGE_10781, EDGE, - // Penguin - STEPPING_STONE_21120, STEPPING_STONE_21126, STEPPING_STONE_21128, STEPPING_STONE_21129, - STEPPING_STONE_21130, STEPPING_STONE_21131, STEPPING_STONE_21132, STEPPING_STONE_21133, - ICICLES, ICE, ICE_21149, ICE_21150, ICE_21151, ICE_21152, ICE_21153, ICE_21154, ICE_21155, ICE_21156, - // Barbarian - ROPESWING_23131, LOG_BALANCE_23144, OBSTACLE_NET_20211, BALANCING_LEDGE_23547, LADDER_16682, CRUMBLING_WALL_1948, - // Canifis - TALL_TREE_10819, GAP_10820, GAP_10821, GAP_10828, GAP_10822, POLEVAULT, GAP_10823, GAP_10832, - // Ape atoll - STEPPING_STONE_15412, TROPICAL_TREE_15414, MONKEYBARS_15417, SKULL_SLOPE_15483, ROPE_15487, TROPICAL_TREE_16062, - // Falador - ROUGH_WALL_10833, TIGHTROPE_10834, HAND_HOLDS_10836, GAP_11161, GAP_11360, TIGHTROPE_11361, - TIGHTROPE_11364, GAP_11365, LEDGE_11366, LEDGE_11367, LEDGE_11369, LEDGE_11370, EDGE_11371, - // Wilderness - OBSTACLE_PIPE_23137, ROPESWING_23132, STEPPING_STONE_23556, LOG_BALANCE_23542, ROCKS_23640, - // Seers - WALL_11373, GAP_11374, TIGHTROPE_11378, GAP_11375, GAP_11376, EDGE_11377, - // Dorgesh-Kaan - CABLE_22569, CABLE_22572, LADDER_22564, JUTTING_WALL_22552, TUNNEL_22557, PYLON_22664, - CONSOLE, BOILER_22635, STAIRS_22650, STAIRS_22651, STAIRS_22609, STAIRS_22608, - // Pollniveach - BASKET_11380, MARKET_STALL_11381, BANNER_11382, GAP_11383, TREE_11384, ROUGH_WALL_11385, - MONKEYBARS, TREE_11389, DRYING_LINE, - // Rellaka - ROUGH_WALL_11391, GAP_11392, TIGHTROPE_11393, GAP_11395, GAP_11396, TIGHTROPE_11397, PILE_OF_FISH, - // Ardougne - GAP_11406, GAP_11429, GAP_11430, STEEP_ROOF, GAP_11630, PLANK_11631, WOODEN_BEAMS, - // Meiyerditch - NULL_12945, ROCK_17958, ROCK_17959, ROCK_17960, BOAT_17961, NULL_18122, NULL_18124, WALL_RUBBLE, - WALL_RUBBLE_18038, FLOORBOARDS, FLOORBOARDS_18071, FLOORBOARDS_18072, FLOORBOARDS_18073, NULL_18129, NULL_18130, - WALL_18078, NULL_18132, NULL_18133, NULL_18083, TUNNEL_18085, SHELF_18086, SHELF_18087, WALL_18088, - FLOORBOARDS_18089, FLOORBOARDS_18090, DOOR_18091, FLOORBOARDS_18093, FLOORBOARDS_18094, SHELF_18095, - SHELF_18096, FLOORBOARDS_18097, FLOORBOARDS_18098, WASHING_LINE_18099, WASHING_LINE_18100, - NULL_18135, NULL_18136, SHELF_18105, SHELF_18106, SHELF_18107, SHELF_18108, FLOORBOARDS_18109, - FLOORBOARDS_18110, FLOORBOARDS_18112, FLOORBOARDS_18111, FLOORBOARDS_18114, FLOORBOARDS_18113, - NULL_18116, FLOORBOARDS_18117, FLOORBOARDS_18118, STAIRS_DOWN, WALL_17980, - // Werewolf - STEPPING_STONE_11643, HURDLE, HURDLE_11639, HURDLE_11640, PIPE_11657, SKULL_SLOPE, ZIP_LINE_11644, - ZIP_LINE_11645, ZIP_LINE_11646 - ); - - static final Multimap SHORTCUT_OBSTACLE_IDS; - - static final Set TRAP_OBSTACLE_IDS = ImmutableSet.of( - // Agility pyramid - NULL_3550, NULL_10872, NULL_10873 - ); - - static final List TRAP_OBSTACLE_REGIONS = ImmutableList.of(12105, 13356); - - static - { - final ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); - for (final AgilityShortcut item : AgilityShortcut.values()) - { - for (int obstacle : item.getObstacleIds()) - { - builder.put(obstacle, item); - } - } - SHORTCUT_OBSTACLE_IDS = builder.build(); - } -} +/* + * Copyright (c) 2018, SomeoneWithAnInternetConnection + * 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.agility; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import java.util.List; +import java.util.Set; +import static net.runelite.api.NullObjectID.NULL_10872; +import static net.runelite.api.NullObjectID.NULL_10873; +import static net.runelite.api.NullObjectID.NULL_12945; +import static net.runelite.api.NullObjectID.NULL_18083; +import static net.runelite.api.NullObjectID.NULL_18116; +import static net.runelite.api.NullObjectID.NULL_18122; +import static net.runelite.api.NullObjectID.NULL_18124; +import static net.runelite.api.NullObjectID.NULL_18129; +import static net.runelite.api.NullObjectID.NULL_18130; +import static net.runelite.api.NullObjectID.NULL_18132; +import static net.runelite.api.NullObjectID.NULL_18133; +import static net.runelite.api.NullObjectID.NULL_18135; +import static net.runelite.api.NullObjectID.NULL_18136; +import static net.runelite.api.NullObjectID.NULL_3550; +import static net.runelite.api.ObjectID.BALANCING_LEDGE; +import static net.runelite.api.ObjectID.BALANCING_LEDGE_23547; +import static net.runelite.api.ObjectID.BALANCING_LEDGE_3561; +import static net.runelite.api.ObjectID.BALANCING_ROPE; +import static net.runelite.api.ObjectID.BALANCING_ROPE_23557; +import static net.runelite.api.ObjectID.BANNER_11382; +import static net.runelite.api.ObjectID.BASKET_11380; +import static net.runelite.api.ObjectID.BOAT_17961; +import static net.runelite.api.ObjectID.BOILER_22635; +import static net.runelite.api.ObjectID.CABLE; +import static net.runelite.api.ObjectID.CABLE_22569; +import static net.runelite.api.ObjectID.CABLE_22572; +import static net.runelite.api.ObjectID.CLIMBING_ROCKS_10851; +import static net.runelite.api.ObjectID.CLOTHES_LINE; +import static net.runelite.api.ObjectID.CONSOLE; +import static net.runelite.api.ObjectID.CRATE_10086; +import static net.runelite.api.ObjectID.CRUMBLING_WALL_1948; +import static net.runelite.api.ObjectID.DOORWAY_10855; +import static net.runelite.api.ObjectID.DOOR_18091; +import static net.runelite.api.ObjectID.DRYING_LINE; +import static net.runelite.api.ObjectID.EDGE; +import static net.runelite.api.ObjectID.EDGE_11371; +import static net.runelite.api.ObjectID.EDGE_11377; +import static net.runelite.api.ObjectID.FLOORBOARDS; +import static net.runelite.api.ObjectID.FLOORBOARDS_18071; +import static net.runelite.api.ObjectID.FLOORBOARDS_18072; +import static net.runelite.api.ObjectID.FLOORBOARDS_18073; +import static net.runelite.api.ObjectID.FLOORBOARDS_18089; +import static net.runelite.api.ObjectID.FLOORBOARDS_18090; +import static net.runelite.api.ObjectID.FLOORBOARDS_18093; +import static net.runelite.api.ObjectID.FLOORBOARDS_18094; +import static net.runelite.api.ObjectID.FLOORBOARDS_18097; +import static net.runelite.api.ObjectID.FLOORBOARDS_18098; +import static net.runelite.api.ObjectID.FLOORBOARDS_18109; +import static net.runelite.api.ObjectID.FLOORBOARDS_18110; +import static net.runelite.api.ObjectID.FLOORBOARDS_18111; +import static net.runelite.api.ObjectID.FLOORBOARDS_18112; +import static net.runelite.api.ObjectID.FLOORBOARDS_18113; +import static net.runelite.api.ObjectID.FLOORBOARDS_18114; +import static net.runelite.api.ObjectID.FLOORBOARDS_18117; +import static net.runelite.api.ObjectID.FLOORBOARDS_18118; +import static net.runelite.api.ObjectID.GAP_10085; +import static net.runelite.api.ObjectID.GAP_10352; +import static net.runelite.api.ObjectID.GAP_10642; +import static net.runelite.api.ObjectID.GAP_10778; +import static net.runelite.api.ObjectID.GAP_10779; +import static net.runelite.api.ObjectID.GAP_10780; +import static net.runelite.api.ObjectID.GAP_10820; +import static net.runelite.api.ObjectID.GAP_10821; +import static net.runelite.api.ObjectID.GAP_10822; +import static net.runelite.api.ObjectID.GAP_10823; +import static net.runelite.api.ObjectID.GAP_10828; +import static net.runelite.api.ObjectID.GAP_10832; +import static net.runelite.api.ObjectID.GAP_10859; +import static net.runelite.api.ObjectID.GAP_10861; +import static net.runelite.api.ObjectID.GAP_10882; +import static net.runelite.api.ObjectID.GAP_10884; +import static net.runelite.api.ObjectID.GAP_11161; +import static net.runelite.api.ObjectID.GAP_11360; +import static net.runelite.api.ObjectID.GAP_11365; +import static net.runelite.api.ObjectID.GAP_11374; +import static net.runelite.api.ObjectID.GAP_11375; +import static net.runelite.api.ObjectID.GAP_11376; +import static net.runelite.api.ObjectID.GAP_11383; +import static net.runelite.api.ObjectID.GAP_11392; +import static net.runelite.api.ObjectID.GAP_11395; +import static net.runelite.api.ObjectID.GAP_11396; +import static net.runelite.api.ObjectID.GAP_11406; +import static net.runelite.api.ObjectID.GAP_11429; +import static net.runelite.api.ObjectID.GAP_11430; +import static net.runelite.api.ObjectID.GAP_11630; +import static net.runelite.api.ObjectID.HAND_HOLDS_10836; +import static net.runelite.api.ObjectID.HAND_HOLDS_3583; +import static net.runelite.api.ObjectID.HURDLE; +import static net.runelite.api.ObjectID.HURDLE_11639; +import static net.runelite.api.ObjectID.HURDLE_11640; +import static net.runelite.api.ObjectID.ICE; +import static net.runelite.api.ObjectID.ICE_21149; +import static net.runelite.api.ObjectID.ICE_21150; +import static net.runelite.api.ObjectID.ICE_21151; +import static net.runelite.api.ObjectID.ICE_21152; +import static net.runelite.api.ObjectID.ICE_21153; +import static net.runelite.api.ObjectID.ICE_21154; +import static net.runelite.api.ObjectID.ICE_21155; +import static net.runelite.api.ObjectID.ICE_21156; +import static net.runelite.api.ObjectID.ICICLES; +import static net.runelite.api.ObjectID.JUTTING_WALL_22552; +import static net.runelite.api.ObjectID.LADDER_16682; +import static net.runelite.api.ObjectID.LADDER_22564; +import static net.runelite.api.ObjectID.LEDGE_10781; +import static net.runelite.api.ObjectID.LEDGE_10860; +import static net.runelite.api.ObjectID.LEDGE_10886; +import static net.runelite.api.ObjectID.LEDGE_10888; +import static net.runelite.api.ObjectID.LEDGE_11366; +import static net.runelite.api.ObjectID.LEDGE_11367; +import static net.runelite.api.ObjectID.LEDGE_11369; +import static net.runelite.api.ObjectID.LEDGE_11370; +import static net.runelite.api.ObjectID.LOG_BALANCE; +import static net.runelite.api.ObjectID.LOG_BALANCE_23144; +import static net.runelite.api.ObjectID.LOG_BALANCE_23145; +import static net.runelite.api.ObjectID.LOG_BALANCE_23542; +import static net.runelite.api.ObjectID.LOG_BALANCE_3557; +import static net.runelite.api.ObjectID.LOW_WALL; +import static net.runelite.api.ObjectID.LOW_WALL_10865; +import static net.runelite.api.ObjectID.MARKET_STALL_11381; +import static net.runelite.api.ObjectID.MONKEYBARS; +import static net.runelite.api.ObjectID.MONKEYBARS_15417; +import static net.runelite.api.ObjectID.MONKEY_BARS_3564; +import static net.runelite.api.ObjectID.NARROW_WALL; +import static net.runelite.api.ObjectID.OBSTACLE_NET_20211; +import static net.runelite.api.ObjectID.OBSTACLE_NET_23134; +import static net.runelite.api.ObjectID.OBSTACLE_NET_23135; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_23137; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_23138; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_23139; +import static net.runelite.api.ObjectID.PILE_OF_FISH; +import static net.runelite.api.ObjectID.PILLAR_3578; +import static net.runelite.api.ObjectID.PIPE_11657; +import static net.runelite.api.ObjectID.PLANK_10868; +import static net.runelite.api.ObjectID.PLANK_11631; +import static net.runelite.api.ObjectID.PLANK_3570; +import static net.runelite.api.ObjectID.PLANK_3571; +import static net.runelite.api.ObjectID.PLANK_3572; +import static net.runelite.api.ObjectID.POLEVAULT; +import static net.runelite.api.ObjectID.PYLON_22664; +import static net.runelite.api.ObjectID.ROCKS_23640; +import static net.runelite.api.ObjectID.ROCK_17958; +import static net.runelite.api.ObjectID.ROCK_17959; +import static net.runelite.api.ObjectID.ROCK_17960; +import static net.runelite.api.ObjectID.ROOF_TOP_BEAMS; +import static net.runelite.api.ObjectID.ROPESWING_23131; +import static net.runelite.api.ObjectID.ROPESWING_23132; +import static net.runelite.api.ObjectID.ROPE_15487; +import static net.runelite.api.ObjectID.ROPE_SWING; +import static net.runelite.api.ObjectID.ROUGH_WALL; +import static net.runelite.api.ObjectID.ROUGH_WALL_10093; +import static net.runelite.api.ObjectID.ROUGH_WALL_10586; +import static net.runelite.api.ObjectID.ROUGH_WALL_10833; +import static net.runelite.api.ObjectID.ROUGH_WALL_11385; +import static net.runelite.api.ObjectID.ROUGH_WALL_11391; +import static net.runelite.api.ObjectID.SHELF_18086; +import static net.runelite.api.ObjectID.SHELF_18087; +import static net.runelite.api.ObjectID.SHELF_18095; +import static net.runelite.api.ObjectID.SHELF_18096; +import static net.runelite.api.ObjectID.SHELF_18105; +import static net.runelite.api.ObjectID.SHELF_18106; +import static net.runelite.api.ObjectID.SHELF_18107; +import static net.runelite.api.ObjectID.SHELF_18108; +import static net.runelite.api.ObjectID.SKULL_SLOPE; +import static net.runelite.api.ObjectID.SKULL_SLOPE_15483; +import static net.runelite.api.ObjectID.STAIRS_10857; +import static net.runelite.api.ObjectID.STAIRS_22608; +import static net.runelite.api.ObjectID.STAIRS_22609; +import static net.runelite.api.ObjectID.STAIRS_22650; +import static net.runelite.api.ObjectID.STAIRS_22651; +import static net.runelite.api.ObjectID.STAIRS_DOWN; +import static net.runelite.api.ObjectID.STEEP_ROOF; +import static net.runelite.api.ObjectID.STEPPING_STONE_11643; +import static net.runelite.api.ObjectID.STEPPING_STONE_15412; +import static net.runelite.api.ObjectID.STEPPING_STONE_21120; +import static net.runelite.api.ObjectID.STEPPING_STONE_21126; +import static net.runelite.api.ObjectID.STEPPING_STONE_21128; +import static net.runelite.api.ObjectID.STEPPING_STONE_21129; +import static net.runelite.api.ObjectID.STEPPING_STONE_21130; +import static net.runelite.api.ObjectID.STEPPING_STONE_21131; +import static net.runelite.api.ObjectID.STEPPING_STONE_21132; +import static net.runelite.api.ObjectID.STEPPING_STONE_21133; +import static net.runelite.api.ObjectID.STEPPING_STONE_23556; +import static net.runelite.api.ObjectID.STILE_7527; +import static net.runelite.api.ObjectID.TALL_TREE_10819; +import static net.runelite.api.ObjectID.TIGHTROPE; +import static net.runelite.api.ObjectID.TIGHTROPE_10075; +import static net.runelite.api.ObjectID.TIGHTROPE_10284; +import static net.runelite.api.ObjectID.TIGHTROPE_10583; +import static net.runelite.api.ObjectID.TIGHTROPE_10834; +import static net.runelite.api.ObjectID.TIGHTROPE_11361; +import static net.runelite.api.ObjectID.TIGHTROPE_11364; +import static net.runelite.api.ObjectID.TIGHTROPE_11378; +import static net.runelite.api.ObjectID.TIGHTROPE_11393; +import static net.runelite.api.ObjectID.TIGHTROPE_11397; +import static net.runelite.api.ObjectID.TREE_11384; +import static net.runelite.api.ObjectID.TREE_11389; +import static net.runelite.api.ObjectID.TREE_BRANCH_23559; +import static net.runelite.api.ObjectID.TREE_BRANCH_23560; +import static net.runelite.api.ObjectID.TROPICAL_TREE_10357; +import static net.runelite.api.ObjectID.TROPICAL_TREE_15414; +import static net.runelite.api.ObjectID.TROPICAL_TREE_16062; +import static net.runelite.api.ObjectID.TUNNEL_18085; +import static net.runelite.api.ObjectID.TUNNEL_22557; +import static net.runelite.api.ObjectID.WALL_10084; +import static net.runelite.api.ObjectID.WALL_10777; +import static net.runelite.api.ObjectID.WALL_11373; +import static net.runelite.api.ObjectID.WALL_17980; +import static net.runelite.api.ObjectID.WALL_18078; +import static net.runelite.api.ObjectID.WALL_18088; +import static net.runelite.api.ObjectID.WALL_RUBBLE; +import static net.runelite.api.ObjectID.WALL_RUBBLE_18038; +import static net.runelite.api.ObjectID.WASHING_LINE_18099; +import static net.runelite.api.ObjectID.WASHING_LINE_18100; +import static net.runelite.api.ObjectID.WOODEN_BEAMS; +import static net.runelite.api.ObjectID.ZIP_LINE; +import static net.runelite.api.ObjectID.ZIP_LINE_11644; +import static net.runelite.api.ObjectID.ZIP_LINE_11645; +import static net.runelite.api.ObjectID.ZIP_LINE_11646; +import net.runelite.client.game.AgilityShortcut; + +class Obstacles +{ + static final Set COURSE_OBSTACLE_IDS = ImmutableSet.of( + // Gnome + OBSTACLE_NET_23134, TREE_BRANCH_23559, TREE_BRANCH_23560, OBSTACLE_NET_23135, OBSTACLE_PIPE_23138, + OBSTACLE_PIPE_23139, LOG_BALANCE_23145, BALANCING_ROPE_23557, + // Brimhaven + PLANK_3572, PLANK_3571, PLANK_3570, ROPE_SWING, PILLAR_3578, LOW_WALL, LOG_BALANCE, LOG_BALANCE_3557, + BALANCING_LEDGE_3561, BALANCING_LEDGE, MONKEY_BARS_3564, BALANCING_ROPE, HAND_HOLDS_3583, + // Draynor + ROUGH_WALL, TIGHTROPE, TIGHTROPE_10075, NARROW_WALL, WALL_10084, GAP_10085, CRATE_10086, STILE_7527, + // Al-Kharid + ROUGH_WALL_10093, TIGHTROPE_10284, CABLE, ZIP_LINE, TROPICAL_TREE_10357, ROOF_TOP_BEAMS, + TIGHTROPE_10583, GAP_10352, + // Pyramid + STAIRS_10857, LOW_WALL_10865, LEDGE_10860, PLANK_10868, GAP_10882, LEDGE_10886, STAIRS_10857, GAP_10884, + GAP_10859, GAP_10861, LOW_WALL_10865, GAP_10859, LEDGE_10888, PLANK_10868, CLIMBING_ROCKS_10851, DOORWAY_10855, + // Varrock + ROUGH_WALL_10586, CLOTHES_LINE, GAP_10642, WALL_10777, GAP_10778, GAP_10779, GAP_10780, LEDGE_10781, EDGE, + // Penguin + STEPPING_STONE_21120, STEPPING_STONE_21126, STEPPING_STONE_21128, STEPPING_STONE_21129, + STEPPING_STONE_21130, STEPPING_STONE_21131, STEPPING_STONE_21132, STEPPING_STONE_21133, + ICICLES, ICE, ICE_21149, ICE_21150, ICE_21151, ICE_21152, ICE_21153, ICE_21154, ICE_21155, ICE_21156, + // Barbarian + ROPESWING_23131, LOG_BALANCE_23144, OBSTACLE_NET_20211, BALANCING_LEDGE_23547, LADDER_16682, CRUMBLING_WALL_1948, + // Canifis + TALL_TREE_10819, GAP_10820, GAP_10821, GAP_10828, GAP_10822, POLEVAULT, GAP_10823, GAP_10832, + // Ape atoll + STEPPING_STONE_15412, TROPICAL_TREE_15414, MONKEYBARS_15417, SKULL_SLOPE_15483, ROPE_15487, TROPICAL_TREE_16062, + // Falador + ROUGH_WALL_10833, TIGHTROPE_10834, HAND_HOLDS_10836, GAP_11161, GAP_11360, TIGHTROPE_11361, + TIGHTROPE_11364, GAP_11365, LEDGE_11366, LEDGE_11367, LEDGE_11369, LEDGE_11370, EDGE_11371, + // Wilderness + OBSTACLE_PIPE_23137, ROPESWING_23132, STEPPING_STONE_23556, LOG_BALANCE_23542, ROCKS_23640, + // Seers + WALL_11373, GAP_11374, TIGHTROPE_11378, GAP_11375, GAP_11376, EDGE_11377, + // Dorgesh-Kaan + CABLE_22569, CABLE_22572, LADDER_22564, JUTTING_WALL_22552, TUNNEL_22557, PYLON_22664, + CONSOLE, BOILER_22635, STAIRS_22650, STAIRS_22651, STAIRS_22609, STAIRS_22608, + // Pollniveach + BASKET_11380, MARKET_STALL_11381, BANNER_11382, GAP_11383, TREE_11384, ROUGH_WALL_11385, + MONKEYBARS, TREE_11389, DRYING_LINE, + // Rellaka + ROUGH_WALL_11391, GAP_11392, TIGHTROPE_11393, GAP_11395, GAP_11396, TIGHTROPE_11397, PILE_OF_FISH, + // Ardougne + GAP_11406, GAP_11429, GAP_11430, STEEP_ROOF, GAP_11630, PLANK_11631, WOODEN_BEAMS, + // Meiyerditch + NULL_12945, ROCK_17958, ROCK_17959, ROCK_17960, BOAT_17961, NULL_18122, NULL_18124, WALL_RUBBLE, + WALL_RUBBLE_18038, FLOORBOARDS, FLOORBOARDS_18071, FLOORBOARDS_18072, FLOORBOARDS_18073, NULL_18129, NULL_18130, + WALL_18078, NULL_18132, NULL_18133, NULL_18083, TUNNEL_18085, SHELF_18086, SHELF_18087, WALL_18088, + FLOORBOARDS_18089, FLOORBOARDS_18090, DOOR_18091, FLOORBOARDS_18093, FLOORBOARDS_18094, SHELF_18095, + SHELF_18096, FLOORBOARDS_18097, FLOORBOARDS_18098, WASHING_LINE_18099, WASHING_LINE_18100, + NULL_18135, NULL_18136, SHELF_18105, SHELF_18106, SHELF_18107, SHELF_18108, FLOORBOARDS_18109, + FLOORBOARDS_18110, FLOORBOARDS_18112, FLOORBOARDS_18111, FLOORBOARDS_18114, FLOORBOARDS_18113, + NULL_18116, FLOORBOARDS_18117, FLOORBOARDS_18118, STAIRS_DOWN, WALL_17980, + // Werewolf + STEPPING_STONE_11643, HURDLE, HURDLE_11639, HURDLE_11640, PIPE_11657, SKULL_SLOPE, ZIP_LINE_11644, + ZIP_LINE_11645, ZIP_LINE_11646 + ); + + static final Multimap SHORTCUT_OBSTACLE_IDS; + + static final Set TRAP_OBSTACLE_IDS = ImmutableSet.of( + // Agility pyramid + NULL_3550, NULL_10872, NULL_10873 + ); + + static final List TRAP_OBSTACLE_REGIONS = ImmutableList.of(12105, 13356); + + static + { + final ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + for (final AgilityShortcut item : AgilityShortcut.values()) + { + for (int obstacle : item.getObstacleIds()) + { + builder.put(obstacle, item); + } + } + SHORTCUT_OBSTACLE_IDS = builder.build(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java index 471e8517fb..d06588e168 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPhase.java @@ -1,71 +1,71 @@ -/* - * Copyright (c) 2019, Lucas - * 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.alchemicalhydra; - -import lombok.Getter; -import net.runelite.api.AnimationID; -import net.runelite.api.ProjectileID; -import net.runelite.api.SpriteID; -import net.runelite.api.coords.WorldPoint; - -enum HydraPhase -{ // Sorry for the autism - ONE (3, AnimationID.HYDRA_1_1, AnimationID.HYDRA_1_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, new WorldPoint(1371, 10263, 0)), - TWO (3, AnimationID.HYDRA_2_1, AnimationID.HYDRA_2_2, 0, AnimationID.HYDRA_LIGHTNING, SpriteID.BIG_SPEC_TRANSFER, new WorldPoint(1371, 10272, 0)), - THREE (3, AnimationID.HYDRA_3_1, AnimationID.HYDRA_3_2, 0, AnimationID.HYDRA_FIRE, SpriteID.BIG_SUPERHEAT, new WorldPoint(1362, 10272, 0)), - FOUR (1, AnimationID.HYDRA_4_1, AnimationID.HYDRA_4_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, null); - - @Getter - private final int attacksPerSwitch; - - @Getter - private final int deathAnim1; - - @Getter - private final int deathAnim2; - - @Getter - private final int specProjectileId; - - @Getter - private final int specAnimationId; - - @Getter - private final int specImage; - - @Getter - private WorldPoint fountain; - - HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage, WorldPoint fountain) - { - this.attacksPerSwitch = attacksPerSwitch; - this.deathAnim1 = deathAnim1; - this.deathAnim2 = deathAnim2; - this.specProjectileId = specProjectileId; - this.specAnimationId = specAnimationId; - this.specImage = specImage; - this.fountain = fountain; - } +/* + * Copyright (c) 2019, Lucas + * 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.alchemicalhydra; + +import lombok.Getter; +import net.runelite.api.AnimationID; +import net.runelite.api.ProjectileID; +import net.runelite.api.SpriteID; +import net.runelite.api.coords.WorldPoint; + +enum HydraPhase +{ // Sorry for the autism + ONE(3, AnimationID.HYDRA_1_1, AnimationID.HYDRA_1_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, new WorldPoint(1371, 10263, 0)), + TWO(3, AnimationID.HYDRA_2_1, AnimationID.HYDRA_2_2, 0, AnimationID.HYDRA_LIGHTNING, SpriteID.BIG_SPEC_TRANSFER, new WorldPoint(1371, 10272, 0)), + THREE(3, AnimationID.HYDRA_3_1, AnimationID.HYDRA_3_2, 0, AnimationID.HYDRA_FIRE, SpriteID.BIG_SUPERHEAT, new WorldPoint(1362, 10272, 0)), + FOUR(1, AnimationID.HYDRA_4_1, AnimationID.HYDRA_4_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL, null); + + @Getter + private final int attacksPerSwitch; + + @Getter + private final int deathAnim1; + + @Getter + private final int deathAnim2; + + @Getter + private final int specProjectileId; + + @Getter + private final int specAnimationId; + + @Getter + private final int specImage; + + @Getter + private WorldPoint fountain; + + HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage, WorldPoint fountain) + { + this.attacksPerSwitch = attacksPerSwitch; + this.deathAnim1 = deathAnim1; + this.deathAnim2 = deathAnim2; + this.specProjectileId = specProjectileId; + this.specAnimationId = specAnimationId; + this.specImage = specImage; + this.fountain = fountain; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java index 13026e660c..940c34c76f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java @@ -117,9 +117,9 @@ public class HydraPlugin extends Plugin { if (hydra != null) - { - removeOverlays(); - hydra = null; + { + removeOverlays(); + hydra = null; } return; } @@ -305,8 +305,8 @@ public class HydraPlugin extends Plugin } else { - hydra.setNextSwitch(hydra.getNextSwitch() - 1); - hydra.setLastAttack(hydra.getNextAttack()); + hydra.setNextSwitch(hydra.getNextSwitch() - 1); + hydra.setLastAttack(hydra.getNextAttack()); } hydra.setAttackCount(hydra.getAttackCount() + 1); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java index 2d8b9b843b..f4cd114acc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java @@ -1,145 +1,145 @@ -/* - * Copyright (c) 2019, Lucas - * 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.alchemicalhydra; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.geom.Area; -import java.util.Collection; -import java.util.Map; -import javax.inject.Inject; -import javax.inject.Singleton; -import net.runelite.api.Client; -import static net.runelite.api.Perspective.getCanvasTileAreaPoly; -import net.runelite.api.Projectile; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldArea; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -@Singleton -class HydraPoisonOverlay extends Overlay -{ - private final HydraPlugin plugin; - private final Client client; - - @Inject - public HydraPoisonOverlay(Client client, HydraPlugin plugin) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.UNDER_WIDGETS); - this.plugin = plugin; - this.client = client; - } - - @Override - public Dimension render(Graphics2D graphics) - { - Hydra hydra = plugin.getHydra(); - final Map poisonProjectiles = plugin.getPoisonProjectiles(); - - if (!poisonProjectiles.isEmpty()) - { - drawPoisonArea(graphics, poisonProjectiles); - } - - if (hydra.getPhase().getFountain() != null) - { - drawFountain(graphics, hydra); - } - - return null; - } - - private void drawPoisonArea(Graphics2D graphics, Map poisonProjectiles) - { - Area poisonTiles = new Area(); - - for (Map.Entry entry : poisonProjectiles.entrySet()) - { - if (entry.getValue().getEndCycle() < client.getGameCycle()) - { - continue; - } - - LocalPoint point = entry.getKey(); - Polygon poly = getCanvasTileAreaPoly(client, point, 3); - - if (poly != null) - { - poisonTiles.add(new Area(poly)); - } - } - - graphics.setPaintMode(); - graphics.setColor(new Color(255, 0, 0, 100)); - graphics.draw(poisonTiles); - graphics.setColor(new Color(255, 0, 0, 50)); - graphics.fill(poisonTiles); - } - - private void drawFountain(Graphics2D graphics, Hydra hydra) - { - Collection fountainWorldPoint = WorldPoint.toLocalInstance(client, hydra.getPhase().getFountain()); // thanks - if (fountainWorldPoint.size() > 1) // for - { - return; - } - - WorldPoint wp = null; - for (WorldPoint p : fountainWorldPoint) // this - { - wp = p; - } - - LocalPoint fountainPoint = wp == null ? null : LocalPoint.fromWorld(client, wp); // trash - - if (fountainPoint == null || hydra.isWeakened()) // I - { - return; - } - - final Polygon poly = getCanvasTileAreaPoly(client, fountainPoint, 3); // don't - - if (poly == null) - { - return; - } - - Color color = new Color(255, 0, 0, 100); // like - - if (hydra.getNpc().getWorldArea().intersectsWith(new WorldArea(wp, 1, 1))) // coords - { // WHICH FUCKING RETARD DID X, Y, dX, dY, Z???? IT'S XYZdXdY REEEEEEEEEE - color = new Color(0, 255, 0, 100); - } - - graphics.setColor(color); - graphics.draw(poly); - } +/* + * Copyright (c) 2019, Lucas + * 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.alchemicalhydra; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.geom.Area; +import java.util.Collection; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Singleton; +import net.runelite.api.Client; +import static net.runelite.api.Perspective.getCanvasTileAreaPoly; +import net.runelite.api.Projectile; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldArea; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +@Singleton +class HydraPoisonOverlay extends Overlay +{ + private final HydraPlugin plugin; + private final Client client; + + @Inject + public HydraPoisonOverlay(Client client, HydraPlugin plugin) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.UNDER_WIDGETS); + this.plugin = plugin; + this.client = client; + } + + @Override + public Dimension render(Graphics2D graphics) + { + Hydra hydra = plugin.getHydra(); + final Map poisonProjectiles = plugin.getPoisonProjectiles(); + + if (!poisonProjectiles.isEmpty()) + { + drawPoisonArea(graphics, poisonProjectiles); + } + + if (hydra.getPhase().getFountain() != null) + { + drawFountain(graphics, hydra); + } + + return null; + } + + private void drawPoisonArea(Graphics2D graphics, Map poisonProjectiles) + { + Area poisonTiles = new Area(); + + for (Map.Entry entry : poisonProjectiles.entrySet()) + { + if (entry.getValue().getEndCycle() < client.getGameCycle()) + { + continue; + } + + LocalPoint point = entry.getKey(); + Polygon poly = getCanvasTileAreaPoly(client, point, 3); + + if (poly != null) + { + poisonTiles.add(new Area(poly)); + } + } + + graphics.setPaintMode(); + graphics.setColor(new Color(255, 0, 0, 100)); + graphics.draw(poisonTiles); + graphics.setColor(new Color(255, 0, 0, 50)); + graphics.fill(poisonTiles); + } + + private void drawFountain(Graphics2D graphics, Hydra hydra) + { + Collection fountainWorldPoint = WorldPoint.toLocalInstance(client, hydra.getPhase().getFountain()); // thanks + if (fountainWorldPoint.size() > 1) // for + { + return; + } + + WorldPoint wp = null; + for (WorldPoint p : fountainWorldPoint) // this + { + wp = p; + } + + LocalPoint fountainPoint = wp == null ? null : LocalPoint.fromWorld(client, wp); // trash + + if (fountainPoint == null || hydra.isWeakened()) // I + { + return; + } + + final Polygon poly = getCanvasTileAreaPoly(client, fountainPoint, 3); // don't + + if (poly == null) + { + return; + } + + Color color = new Color(255, 0, 0, 100); // like + + if (hydra.getNpc().getWorldArea().intersectsWith(new WorldArea(wp, 1, 1))) // coords + { // WHICH FUCKING RETARD DID X, Y, dX, dY, Z???? IT'S XYZdXdY REEEEEEEEEE + color = new Color(0, 255, 0, 100); + } + + graphics.setColor(color); + graphics.draw(poly); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java index 58c959eb52..bde5839c8d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java @@ -26,8 +26,8 @@ package net.runelite.client.plugins.antidrag; import java.awt.Color; import java.awt.event.KeyEvent; -import net.runelite.client.config.Alpha; import net.runelite.api.Constants; +import net.runelite.client.config.Alpha; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java index 1fb9a72b29..35d2072a19 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java @@ -32,7 +32,6 @@ import java.util.Map; import net.runelite.api.ProjectileID; - public enum AoeProjectileInfo { LIZARDMAN_SHAMAN_AOE(ProjectileID.LIZARDMAN_SHAMAN_AOE, 5), @@ -108,10 +107,10 @@ public enum AoeProjectileInfo ADDY_DRAG_POISON(ProjectileID.ADDY_DRAG_POISON, 1), /** - * the Breath of the Drake - */ + * the Breath of the Drake + */ DRAKE_BREATH(ProjectileID.DRAKE_BREATH, 1), - + /** * Cerbs fire */ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningOverlay.java index 6b6bed9569..c063c3c92e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningOverlay.java @@ -71,7 +71,7 @@ public class AoeWarningOverlay extends Overlay { for (WorldPoint point : plugin.getLightningTrail()) { - drawTile(graphics, point, new Color(0,150,200), 2, 150, 50); + drawTile(graphics, point, new Color(0, 150, 200), 2, 150, 50); } for (WorldPoint point : plugin.getAcidTrail()) { @@ -84,7 +84,7 @@ public class AoeWarningOverlay extends Overlay Instant now = Instant.now(); Map projectiles = plugin.getProjectiles(); - for (Iterator it = projectiles.values().iterator(); it.hasNext();) + for (Iterator it = projectiles.values().iterator(); it.hasNext(); ) { AoeProjectile aoeProjectile = it.next(); @@ -145,18 +145,22 @@ public class AoeWarningOverlay extends Overlay return null; } - private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) { + private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) + { WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); - if (point.distanceTo(playerLocation) >= 32) { + if (point.distanceTo(playerLocation) >= 32) + { return; } LocalPoint lp = LocalPoint.fromWorld(client, point); - if (lp == null) { + if (lp == null) + { return; } Polygon poly = Perspective.getCanvasTilePoly(client, lp); - if (poly == null) { + if (poly == null) + { return; } //OverlayUtil.renderPolygon(graphics, poly, color); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java index 53c5a36b6c..b380dc3a55 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java @@ -301,8 +301,8 @@ public class AoeWarningPlugin extends Plugin return config.isXarpusEnabled(); case ADDY_DRAG_POISON: return config.addyDrags(); - case DRAKE_BREATH: - return config.isDrakeEnabled(); + case DRAKE_BREATH: + return config.isDrakeEnabled(); case CERB_FIRE: return config.isCerbFireEnabled(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/BombOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/BombOverlay.java index c117ba5853..b538b3df25 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/BombOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/BombOverlay.java @@ -73,7 +73,7 @@ public class BombOverlay extends Overlay //Utilized from the npc highlight code for formatting text being displayed on the client canvas. private static final NumberFormat TIME_LEFT_FORMATTER = - DecimalFormat.getInstance(Locale.US); + DecimalFormat.getInstance(Locale.US); static { @@ -157,22 +157,22 @@ public class BombOverlay extends Overlay Instant now = Instant.now(); double timeLeft = ((BOMB_DETONATE_TIME - (client.getTickCount() - - bomb.getTickStarted())) * ESTIMATED_TICK_LENGTH) - - (now.toEpochMilli() - bomb.getLastClockUpdate().toEpochMilli()) / 1000.0; - //divided by 1000.00 because of milliseconds :) + bomb.getTickStarted())) * ESTIMATED_TICK_LENGTH) - + (now.toEpochMilli() - bomb.getLastClockUpdate().toEpochMilli()) / 1000.0; + //divided by 1000.00 because of milliseconds :) timeLeft = Math.max(0.0, timeLeft); String bombTimerString = TIME_LEFT_FORMATTER.format(timeLeft); int textWidth = graphics.getFontMetrics().stringWidth(bombTimerString); int textHeight = graphics.getFontMetrics().getAscent(); Point canvasPoint = Perspective.localToCanvas(client, localLoc.getX(), - localLoc.getY(), bomb.getWorldLocation().getPlane()); + localLoc.getY(), bomb.getWorldLocation().getPlane()); if (canvasPoint != null) { Point canvasCenterPoint = new Point( - canvasPoint.getX() - textWidth / 2, - canvasPoint.getY() + textHeight / 2); + canvasPoint.getX() - textWidth / 2, + canvasPoint.getY() + textHeight / 2); OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, bombTimerString, color_code); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsConfig.java index c1e7f9ffde..ce3320b7e0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsConfig.java @@ -1,113 +1,113 @@ -/* - * Copyright (c) 2018, Ron Young - * 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.banktags; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("banktags") -public interface BankTagsConfig extends Config -{ - @ConfigItem( - keyName = "useTabs", - name = "Use Tag Tabs", - description = "Enable the ability to add tabs to your bank which allow fast access to tags.", - position = 1 - ) - default boolean tabs() - { - return true; - } - - @ConfigItem( - keyName = "rememberTab", - name = "Remember last Tag Tab", - description = "Enable the ability to remember last Tag Tab when closing/opening the bank.", - position = 2 - ) - default boolean rememberTab() - { - return true; - } - - @ConfigItem( - keyName = "removeSeparators", - name = "Remove tab separators in Tag Tabs", - description = "Removes tab separators and corrects item layouts in Tag Tabs to mimic a regular tab", - position = 3 - ) - default boolean removeSeparators() - { - return true; - } - - @ConfigItem( - keyName = "hidePlaceholders", - name = "Hide placeholders", - description = "Hide placeholders in tag tabs or tag search.", - position = 4 - ) - default boolean hidePlaceholders() - { - return false; - } - - @ConfigItem( - keyName = "position", - name = "", - description = "", - hidden = true - ) - default int position() - { - return 0; - } - - @ConfigItem( - keyName = "position", - name = "", - description = "" - ) - void position(int idx); - - @ConfigItem( - keyName = "tab", - name = "", - description = "", - hidden = true - ) - default String tab() - { - return ""; - } - - @ConfigItem( - keyName = "tab", - name = "", - description = "" - ) - void tab(String tab); -} +/* + * Copyright (c) 2018, Ron Young + * 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.banktags; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("banktags") +public interface BankTagsConfig extends Config +{ + @ConfigItem( + keyName = "useTabs", + name = "Use Tag Tabs", + description = "Enable the ability to add tabs to your bank which allow fast access to tags.", + position = 1 + ) + default boolean tabs() + { + return true; + } + + @ConfigItem( + keyName = "rememberTab", + name = "Remember last Tag Tab", + description = "Enable the ability to remember last Tag Tab when closing/opening the bank.", + position = 2 + ) + default boolean rememberTab() + { + return true; + } + + @ConfigItem( + keyName = "removeSeparators", + name = "Remove tab separators in Tag Tabs", + description = "Removes tab separators and corrects item layouts in Tag Tabs to mimic a regular tab", + position = 3 + ) + default boolean removeSeparators() + { + return true; + } + + @ConfigItem( + keyName = "hidePlaceholders", + name = "Hide placeholders", + description = "Hide placeholders in tag tabs or tag search.", + position = 4 + ) + default boolean hidePlaceholders() + { + return false; + } + + @ConfigItem( + keyName = "position", + name = "", + description = "", + hidden = true + ) + default int position() + { + return 0; + } + + @ConfigItem( + keyName = "position", + name = "", + description = "" + ) + void position(int idx); + + @ConfigItem( + keyName = "tab", + name = "", + description = "", + hidden = true + ) + default String tab() + { + return ""; + } + + @ConfigItem( + keyName = "tab", + name = "", + description = "" + ) + void tab(String tab); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java index 4d4c1addb2..c5ecb74d6e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.barbarianassault; -import com.google.common.collect.ImmutableList; import com.google.inject.Provides; import java.awt.Color; import java.awt.Font; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/HealerTeam.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/HealerTeam.java index 5521d620f7..1d8994f2ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/HealerTeam.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/HealerTeam.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2018, whartd - * 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.barbarianassault; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import net.runelite.api.Point; -import net.runelite.api.widgets.WidgetInfo; - -@Getter -@AllArgsConstructor -enum HealerTeam -{ - TEAMMATE1(WidgetInfo.BA_HEAL_TEAMMATE1, new Point(28, 2), 115), - TEAMMATE2(WidgetInfo.BA_HEAL_TEAMMATE2, new Point(26, 2), 115), - TEAMMATE3(WidgetInfo.BA_HEAL_TEAMMATE3, new Point(26, 2), 115), - TEAMMATE4(WidgetInfo.BA_HEAL_TEAMMATE4, new Point(25, 2), 115); - - private WidgetInfo teammate; - private Point offset; - private int width; -} +/* + * Copyright (c) 2018, whartd + * 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.barbarianassault; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.runelite.api.Point; +import net.runelite.api.widgets.WidgetInfo; + +@Getter +@AllArgsConstructor +enum HealerTeam +{ + TEAMMATE1(WidgetInfo.BA_HEAL_TEAMMATE1, new Point(28, 2), 115), + TEAMMATE2(WidgetInfo.BA_HEAL_TEAMMATE2, new Point(26, 2), 115), + TEAMMATE3(WidgetInfo.BA_HEAL_TEAMMATE3, new Point(26, 2), 115), + TEAMMATE4(WidgetInfo.BA_HEAL_TEAMMATE4, new Point(25, 2), 115); + + private WidgetInfo teammate; + private Point offset; + private int width; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java index 678ed41834..d851b406fa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java @@ -1,99 +1,99 @@ -/* - * Copyright (c) 2018, Seth - * 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.barrows; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; -import net.runelite.api.Varbits; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.ui.overlay.Overlay; -import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; -import net.runelite.client.ui.overlay.OverlayMenuEntry; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; - -public class BarrowsBrotherSlainOverlay extends Overlay -{ - private final Client client; - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - private BarrowsBrotherSlainOverlay(BarrowsPlugin plugin, Client client) - { - super(plugin); - setPosition(OverlayPosition.TOP_LEFT); - setPriority(OverlayPriority.LOW); - this.client = client; - getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Barrows overlay")); - } - - @Override - public Dimension render(Graphics2D graphics) - { - // Do not display overlay if potential is null/hidden - final Widget potential = client.getWidget(WidgetInfo.BARROWS_POTENTIAL); - if (potential == null || potential.isHidden()) - { - return null; - } - - // Hide original overlay - final Widget barrowsBrothers = client.getWidget(WidgetInfo.BARROWS_BROTHERS); - if (barrowsBrothers != null) - { - barrowsBrothers.setHidden(true); - potential.setHidden(true); - } - - panelComponent.getChildren().clear(); - - for (BarrowsBrothers brother : BarrowsBrothers.values()) - { - final boolean brotherSlain = client.getVar(brother.getKilledVarbit()) > 0; - String slain = brotherSlain ? "\u2713" : "\u2717"; - panelComponent.getChildren().add(LineComponent.builder() - .left(brother.getName()) - .right(slain) - .rightColor(brotherSlain ? Color.GREEN : Color.RED) - .build()); - } - - float rewardPercent = client.getVar(Varbits.BARROWS_REWARD_POTENTIAL) / 10.0f; - panelComponent.getChildren().add(LineComponent.builder() - .left("Potential") - .right(rewardPercent != 0 ? rewardPercent + "%" : "0%") - .rightColor(rewardPercent >= 73.0f && rewardPercent <= 88.0f ? Color.GREEN : rewardPercent < 65.6f ? Color.WHITE : Color.YELLOW) - .build()); - - return panelComponent.render(graphics); - } -} +/* + * Copyright (c) 2018, Seth + * 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.barrows; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.api.Varbits; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.overlay.Overlay; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +public class BarrowsBrotherSlainOverlay extends Overlay +{ + private final Client client; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + private BarrowsBrotherSlainOverlay(BarrowsPlugin plugin, Client client) + { + super(plugin); + setPosition(OverlayPosition.TOP_LEFT); + setPriority(OverlayPriority.LOW); + this.client = client; + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Barrows overlay")); + } + + @Override + public Dimension render(Graphics2D graphics) + { + // Do not display overlay if potential is null/hidden + final Widget potential = client.getWidget(WidgetInfo.BARROWS_POTENTIAL); + if (potential == null || potential.isHidden()) + { + return null; + } + + // Hide original overlay + final Widget barrowsBrothers = client.getWidget(WidgetInfo.BARROWS_BROTHERS); + if (barrowsBrothers != null) + { + barrowsBrothers.setHidden(true); + potential.setHidden(true); + } + + panelComponent.getChildren().clear(); + + for (BarrowsBrothers brother : BarrowsBrothers.values()) + { + final boolean brotherSlain = client.getVar(brother.getKilledVarbit()) > 0; + String slain = brotherSlain ? "\u2713" : "\u2717"; + panelComponent.getChildren().add(LineComponent.builder() + .left(brother.getName()) + .right(slain) + .rightColor(brotherSlain ? Color.GREEN : Color.RED) + .build()); + } + + float rewardPercent = client.getVar(Varbits.BARROWS_REWARD_POTENTIAL) / 10.0f; + panelComponent.getChildren().add(LineComponent.builder() + .left("Potential") + .right(rewardPercent != 0 ? rewardPercent + "%" : "0%") + .rightColor(rewardPercent >= 73.0f && rewardPercent <= 88.0f ? Color.GREEN : rewardPercent < 65.6f ? Color.WHITE : Color.YELLOW) + .build()); + + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsOverlay.java index 4ecdebccf3..e3d5ca2619 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsOverlay.java @@ -1,243 +1,244 @@ -/* - * Copyright (c) 2018, Seth - * 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.barrows; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.util.List; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.GameObject; -import net.runelite.api.NPC; -import net.runelite.api.NPCComposition; -import net.runelite.api.ObjectComposition; -import net.runelite.api.Perspective; -import net.runelite.api.Player; -import net.runelite.api.WallObject; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.widgets.Widget; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -class BarrowsOverlay extends Overlay -{ - private static final int MAX_DISTANCE = 2350; - - private final Client client; - private final BarrowsPlugin plugin; - private final BarrowsConfig config; - - @Inject - private BarrowsOverlay(Client client, BarrowsPlugin plugin, BarrowsConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_WIDGETS); - this.client = client; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D graphics) - { - Player local = client.getLocalPlayer(); - final Color npcColor = getMinimapDotColor(1); - final Color playerColor = getMinimapDotColor(2); - Widget puzzleAnswer = plugin.getPuzzleAnswer(); - - // tunnels are only on z=0 - if (!plugin.getWalls().isEmpty() && client.getPlane() == 0 && config.showMinimap()) - { - // NPC dots - graphics.setColor(npcColor); - final List npcs = client.getNpcs(); - for (NPC npc : npcs) - { - final NPCComposition composition = npc.getComposition(); - - if (composition != null && !composition.isMinimapVisible()) - { - continue; - } - - net.runelite.api.Point minimapLocation = npc.getMinimapLocation(); - if (minimapLocation != null) - { - graphics.fillOval(minimapLocation.getX(), minimapLocation.getY(), 4, 4); - } - } - - // Player dots - graphics.setColor(playerColor); - final List players = client.getPlayers(); - for (Player player : players) - { - if (player == local) - { - // Skip local player as we draw square for it later - continue; - } - - net.runelite.api.Point minimapLocation = player.getMinimapLocation(); - if (minimapLocation != null) - { - graphics.fillOval(minimapLocation.getX(), minimapLocation.getY(), 4, 4); - } - } - - // Render barrows walls/doors - renderObjects(graphics, local); - - // Local player square - graphics.setColor(playerColor); - graphics.fillRect(local.getMinimapLocation().getX(), local.getMinimapLocation().getY(), 3, 3); - } - else if (config.showBrotherLoc()) - { - renderBarrowsBrothers(graphics); - } - - if (puzzleAnswer != null && config.showPuzzleAnswer() && !puzzleAnswer.isHidden()) - { - Rectangle answerRect = puzzleAnswer.getBounds(); - graphics.setColor(Color.GREEN); - graphics.draw(answerRect); - } - - return null; - } - - private void renderObjects(Graphics2D graphics, Player localPlayer) - { - LocalPoint localLocation = localPlayer.getLocalLocation(); - for (WallObject wall : plugin.getWalls()) - { - LocalPoint location = wall.getLocalLocation(); - if (localLocation.distanceTo(location) <= MAX_DISTANCE) - { - renderWalls(graphics, wall); - } - } - - for (GameObject ladder : plugin.getLadders()) - { - LocalPoint location = ladder.getLocalLocation(); - if (localLocation.distanceTo(location) <= MAX_DISTANCE) - { - renderLadders(graphics, ladder); - } - } - } - - private void renderWalls(Graphics2D graphics, WallObject wall) - { - net.runelite.api.Point minimapLocation = wall.getMinimapLocation(); - - if (minimapLocation == null) - { - return; - } - - ObjectComposition objectComp = client.getObjectDefinition(wall.getId()); - ObjectComposition impostor = objectComp.getImpostorIds() != null ? objectComp.getImpostor() : null; - - if (impostor != null && impostor.getActions()[0] != null) - { - graphics.setColor(Color.green); - } - else - { - graphics.setColor(Color.gray); - } - - graphics.fillRect(minimapLocation.getX(), minimapLocation.getY(), 3, 3); - } - - /** - * Get minimap dot color from client - * @param typeIndex index of minimap dot type (1 npcs, 2 players) - * @return color - */ - private Color getMinimapDotColor(int typeIndex) - { - final int pixel = client.getMapDots()[typeIndex].getPixels()[1]; - return new Color(pixel); - } - - private void renderLadders(Graphics2D graphics, GameObject ladder) - { - net.runelite.api.Point minimapLocation = ladder.getMinimapLocation(); - - if (minimapLocation == null) - { - return; - } - - ObjectComposition objectComp = client.getObjectDefinition(ladder.getId()); - - if (objectComp.getImpostorIds() != null && objectComp.getImpostor() != null) - { - graphics.setColor(Color.orange); - graphics.fillRect(minimapLocation.getX(), minimapLocation.getY(), 6, 6); - } - } - - private void renderBarrowsBrothers(Graphics2D graphics) - { - for (BarrowsBrothers brother : BarrowsBrothers.values()) - { - LocalPoint localLocation = LocalPoint.fromWorld(client, brother.getLocation()); - - if (localLocation == null) - { - continue; - } - - String brotherLetter = Character.toString(brother.getName().charAt(0)); - net.runelite.api.Point minimapText = Perspective.getCanvasTextMiniMapLocation(client, graphics, - localLocation, brotherLetter); - - if (minimapText != null) - { - graphics.setColor(Color.black); - graphics.drawString(brotherLetter, minimapText.getX() + 1, minimapText.getY() + 1); - - if (client.getVar(brother.getKilledVarbit()) > 0) - { - graphics.setColor(config.deadBrotherLocColor()); - } - else - { - graphics.setColor(config.brotherLocColor()); - } - - graphics.drawString(brotherLetter, minimapText.getX(), minimapText.getY()); - } - } - } +/* + * Copyright (c) 2018, Seth + * 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.barrows; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.util.List; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; +import net.runelite.api.ObjectComposition; +import net.runelite.api.Perspective; +import net.runelite.api.Player; +import net.runelite.api.WallObject; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.widgets.Widget; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +class BarrowsOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2350; + + private final Client client; + private final BarrowsPlugin plugin; + private final BarrowsConfig config; + + @Inject + private BarrowsOverlay(Client client, BarrowsPlugin plugin, BarrowsConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + Player local = client.getLocalPlayer(); + final Color npcColor = getMinimapDotColor(1); + final Color playerColor = getMinimapDotColor(2); + Widget puzzleAnswer = plugin.getPuzzleAnswer(); + + // tunnels are only on z=0 + if (!plugin.getWalls().isEmpty() && client.getPlane() == 0 && config.showMinimap()) + { + // NPC dots + graphics.setColor(npcColor); + final List npcs = client.getNpcs(); + for (NPC npc : npcs) + { + final NPCComposition composition = npc.getComposition(); + + if (composition != null && !composition.isMinimapVisible()) + { + continue; + } + + net.runelite.api.Point minimapLocation = npc.getMinimapLocation(); + if (minimapLocation != null) + { + graphics.fillOval(minimapLocation.getX(), minimapLocation.getY(), 4, 4); + } + } + + // Player dots + graphics.setColor(playerColor); + final List players = client.getPlayers(); + for (Player player : players) + { + if (player == local) + { + // Skip local player as we draw square for it later + continue; + } + + net.runelite.api.Point minimapLocation = player.getMinimapLocation(); + if (minimapLocation != null) + { + graphics.fillOval(minimapLocation.getX(), minimapLocation.getY(), 4, 4); + } + } + + // Render barrows walls/doors + renderObjects(graphics, local); + + // Local player square + graphics.setColor(playerColor); + graphics.fillRect(local.getMinimapLocation().getX(), local.getMinimapLocation().getY(), 3, 3); + } + else if (config.showBrotherLoc()) + { + renderBarrowsBrothers(graphics); + } + + if (puzzleAnswer != null && config.showPuzzleAnswer() && !puzzleAnswer.isHidden()) + { + Rectangle answerRect = puzzleAnswer.getBounds(); + graphics.setColor(Color.GREEN); + graphics.draw(answerRect); + } + + return null; + } + + private void renderObjects(Graphics2D graphics, Player localPlayer) + { + LocalPoint localLocation = localPlayer.getLocalLocation(); + for (WallObject wall : plugin.getWalls()) + { + LocalPoint location = wall.getLocalLocation(); + if (localLocation.distanceTo(location) <= MAX_DISTANCE) + { + renderWalls(graphics, wall); + } + } + + for (GameObject ladder : plugin.getLadders()) + { + LocalPoint location = ladder.getLocalLocation(); + if (localLocation.distanceTo(location) <= MAX_DISTANCE) + { + renderLadders(graphics, ladder); + } + } + } + + private void renderWalls(Graphics2D graphics, WallObject wall) + { + net.runelite.api.Point minimapLocation = wall.getMinimapLocation(); + + if (minimapLocation == null) + { + return; + } + + ObjectComposition objectComp = client.getObjectDefinition(wall.getId()); + ObjectComposition impostor = objectComp.getImpostorIds() != null ? objectComp.getImpostor() : null; + + if (impostor != null && impostor.getActions()[0] != null) + { + graphics.setColor(Color.green); + } + else + { + graphics.setColor(Color.gray); + } + + graphics.fillRect(minimapLocation.getX(), minimapLocation.getY(), 3, 3); + } + + /** + * Get minimap dot color from client + * + * @param typeIndex index of minimap dot type (1 npcs, 2 players) + * @return color + */ + private Color getMinimapDotColor(int typeIndex) + { + final int pixel = client.getMapDots()[typeIndex].getPixels()[1]; + return new Color(pixel); + } + + private void renderLadders(Graphics2D graphics, GameObject ladder) + { + net.runelite.api.Point minimapLocation = ladder.getMinimapLocation(); + + if (minimapLocation == null) + { + return; + } + + ObjectComposition objectComp = client.getObjectDefinition(ladder.getId()); + + if (objectComp.getImpostorIds() != null && objectComp.getImpostor() != null) + { + graphics.setColor(Color.orange); + graphics.fillRect(minimapLocation.getX(), minimapLocation.getY(), 6, 6); + } + } + + private void renderBarrowsBrothers(Graphics2D graphics) + { + for (BarrowsBrothers brother : BarrowsBrothers.values()) + { + LocalPoint localLocation = LocalPoint.fromWorld(client, brother.getLocation()); + + if (localLocation == null) + { + continue; + } + + String brotherLetter = Character.toString(brother.getName().charAt(0)); + net.runelite.api.Point minimapText = Perspective.getCanvasTextMiniMapLocation(client, graphics, + localLocation, brotherLetter); + + if (minimapText != null) + { + graphics.setColor(Color.black); + graphics.drawString(brotherLetter, minimapText.getX() + 1, minimapText.getY() + 1); + + if (client.getVar(brother.getKilledVarbit()) > 0) + { + graphics.setColor(config.deadBrotherLocColor()); + } + else + { + graphics.setColor(config.brotherLocColor()); + } + + graphics.drawString(brotherLetter, minimapText.getX(), minimapText.getY()); + } + } + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java index 30ecefb885..0b8de1c15b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java @@ -81,13 +81,13 @@ public class BarrowsPlugin extends Plugin { @Getter(AccessLevel.PACKAGE) private static final Set BARROWS_WALLS = Sets.newHashSet - ( - ObjectID.DOOR_20678, NullObjectID.NULL_20681, NullObjectID.NULL_20682, NullObjectID.NULL_20683, NullObjectID.NULL_20684, NullObjectID.NULL_20685, NullObjectID.NULL_20686, NullObjectID.NULL_20687, - NullObjectID.NULL_20688, NullObjectID.NULL_20689, NullObjectID.NULL_20690, NullObjectID.NULL_20691, NullObjectID.NULL_20692, NullObjectID.NULL_20693, NullObjectID.NULL_20694, NullObjectID.NULL_20695, - NullObjectID.NULL_20696, ObjectID.DOOR_20697, NullObjectID.NULL_20700, NullObjectID.NULL_20701, NullObjectID.NULL_20702, NullObjectID.NULL_20703, NullObjectID.NULL_20704, NullObjectID.NULL_20705, - NullObjectID.NULL_20706, NullObjectID.NULL_20707, NullObjectID.NULL_20708, NullObjectID.NULL_20709, NullObjectID.NULL_20710, NullObjectID.NULL_20711, NullObjectID.NULL_20712, NullObjectID.NULL_20713, - NullObjectID.NULL_20714, NullObjectID.NULL_20715, NullObjectID.NULL_20728, NullObjectID.NULL_20730 - ); + ( + ObjectID.DOOR_20678, NullObjectID.NULL_20681, NullObjectID.NULL_20682, NullObjectID.NULL_20683, NullObjectID.NULL_20684, NullObjectID.NULL_20685, NullObjectID.NULL_20686, NullObjectID.NULL_20687, + NullObjectID.NULL_20688, NullObjectID.NULL_20689, NullObjectID.NULL_20690, NullObjectID.NULL_20691, NullObjectID.NULL_20692, NullObjectID.NULL_20693, NullObjectID.NULL_20694, NullObjectID.NULL_20695, + NullObjectID.NULL_20696, ObjectID.DOOR_20697, NullObjectID.NULL_20700, NullObjectID.NULL_20701, NullObjectID.NULL_20702, NullObjectID.NULL_20703, NullObjectID.NULL_20704, NullObjectID.NULL_20705, + NullObjectID.NULL_20706, NullObjectID.NULL_20707, NullObjectID.NULL_20708, NullObjectID.NULL_20709, NullObjectID.NULL_20710, NullObjectID.NULL_20711, NullObjectID.NULL_20712, NullObjectID.NULL_20713, + NullObjectID.NULL_20714, NullObjectID.NULL_20715, NullObjectID.NULL_20728, NullObjectID.NULL_20730 + ); private static final Set BARROWS_LADDERS = Sets.newHashSet(NullObjectID.NULL_20675, NullObjectID.NULL_20676, NullObjectID.NULL_20677); private static final ImmutableList POSSIBLE_SOLUTIONS = ImmutableList.of( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java index f200ae5272..c3b4b7e5b5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java @@ -31,8 +31,6 @@ import java.time.Duration; import java.time.Instant; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.NPCComposition; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java index a65e8a89fd..5f7980900b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java @@ -63,7 +63,6 @@ import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; @@ -371,10 +370,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener @Subscribe public void onNpcDespawned(NpcDespawned event) { - if (healers.remove(event.getNpc()) != null && healers.isEmpty()) - { - healers.clear(); - } + healers.remove(event.getNpc()); } @Subscribe @@ -450,7 +446,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener { remove(new String[]{"take", "light"}, target, true); } - else//remove "Light" option (and "Take" option if not defender). + else //remove "Light" option (and "Take" option if not defender). { remove("light", target, true); } @@ -466,7 +462,8 @@ public class BAToolsPlugin extends Plugin implements KeyListener List poison = Arrays.asList("poisoned tofu", "poisoned meat", "poisoned worms"); List vials = Arrays.asList("healing vial", "healing vial(1)", "healing vial(2)", "healing vial(3)", "healing vial(4)");//"healing vial(4)" if (poison.contains(item)) - {//if item is a poison item + { + //if item is a poison item int calledPoison = 0; switch (healer.getText())//choose which poison to hide the use/destroy option for { @@ -509,11 +506,13 @@ public class BAToolsPlugin extends Plugin implements KeyListener } } else if (option.equals("attack") && client.getWidget(WidgetInfo.BA_ATK_ROLE_TEXT) == null && !target.equals("queen spawn"))//if not attacker - {//remove attack option from everything but queen spawns + { + //remove attack option from everything but queen spawns remove(option, target, true); } else if ((option.equals("fix") || (option.equals("block") && target.equals("penance cave"))) && client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null)//if not defender - {//the check for option requires checking target as well because defensive attack style option is also called "block". + { + //the check for option requires checking target as well because defensive attack style option is also called "block". remove(option, target, true); } else if ((option.equals("load")) && client.getWidget(WidgetInfo.BA_COLL_ROLE_TEXT) == null)//if not collector, remove hopper options @@ -632,7 +631,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener if (correctEgg != null) { entries.add(correctEgg); - client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()])); + client.setMenuEntries(entries.toArray(new MenuEntry[0])); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java index 581039179d..0fb721d7a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java @@ -24,10 +24,10 @@ */ package net.runelite.client.plugins.batools; -import lombok.Getter; - import java.util.HashMap; import java.util.Map; +import lombok.Getter; + @Getter public enum Calls { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/CycleCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/CycleCounter.java index af7dd4e57f..e6c026fe05 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/CycleCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/CycleCounter.java @@ -24,11 +24,10 @@ */ package net.runelite.client.plugins.batools; +import java.awt.image.BufferedImage; import net.runelite.client.plugins.Plugin; import net.runelite.client.ui.overlay.infobox.Counter; -import java.awt.image.BufferedImage; - class CycleCounter extends Counter { CycleCounter(BufferedImage img, Plugin plugin, int tick) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java index 45078e7772..93382e57c0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java @@ -27,9 +27,7 @@ package net.runelite.client.plugins.batools; import lombok.Getter; import lombok.Setter; - import net.runelite.api.NPC; -import net.runelite.api.Actor; class Healer @@ -75,7 +73,7 @@ class Healer private HealerCode getCode(int wave) { - switch(wave) + switch (wave) { case 1: return HealerCode.WAVEONE; @@ -97,7 +95,8 @@ class Healer return HealerCode.WAVENINE; case 10: return HealerCode.WAVETEN; - default: return null; + default: + return null; } } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java index 7d5211604d..a604239045 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java @@ -30,16 +30,16 @@ import lombok.Getter; enum HealerCode { - WAVEONE(new int[] {1,1}, new int[] {0,0}, new int[] {0,0}), - WAVETWO(new int[] {1,1,2}, new int[] {0,0,0}, new int[] {0,0,21}), - WAVETHREE(new int[] {1,6,2}, new int[] {0,0,0}, new int[] {0,0,0}), - WAVEFOUR(new int[] {2,5,2,0}, new int[] {0,0,7,10}, new int[] {0,0,0,0}), - WAVEFIVE(new int[] {2,5,2,3,0}, new int[] {0,0,0,0,7}, new int[] {0,0,21,30,0}), - WAVESIX(new int[] {3,5,2,2,0,0}, new int[] {0,0,0,2,9,10}, new int[] {12,18,21,0,0,0}), - WAVESEVEN(new int[] {3,7,1,1,0,0,0}, new int[] {2,0,1,1,2,4,10}, new int[] {0,21,0,0,30,45,0}), - WAVEEIGHT(new int[] {1,9,1,1,0,0,0}, new int[] {1,0,1,1,2,2,10}, new int[] {0,0,0,0,33,42,0}), - WAVENINE(new int[] {2,8,1,1,0,0,0,0}, new int[] {1,0,1,1,2,1,1,10}, new int[] {0,21,0,0,0,0,0,0,0}), - WAVETEN(new int[] {2,5,1,1,0,0,0}, new int[] {1,0,1,1,4,4,8}, new int[] {21,33,0,33,30,45,0}); + WAVEONE(new int[]{1, 1}, new int[]{0, 0}, new int[]{0, 0}), + WAVETWO(new int[]{1, 1, 2}, new int[]{0, 0, 0}, new int[]{0, 0, 21}), + WAVETHREE(new int[]{1, 6, 2}, new int[]{0, 0, 0}, new int[]{0, 0, 0}), + WAVEFOUR(new int[]{2, 5, 2, 0}, new int[]{0, 0, 7, 10}, new int[]{0, 0, 0, 0}), + WAVEFIVE(new int[]{2, 5, 2, 3, 0}, new int[]{0, 0, 0, 0, 7}, new int[]{0, 0, 21, 30, 0}), + WAVESIX(new int[]{3, 5, 2, 2, 0, 0}, new int[]{0, 0, 0, 2, 9, 10}, new int[]{12, 18, 21, 0, 0, 0}), + WAVESEVEN(new int[]{3, 7, 1, 1, 0, 0, 0}, new int[]{2, 0, 1, 1, 2, 4, 10}, new int[]{0, 21, 0, 0, 30, 45, 0}), + WAVEEIGHT(new int[]{1, 9, 1, 1, 0, 0, 0}, new int[]{1, 0, 1, 1, 2, 2, 10}, new int[]{0, 0, 0, 0, 33, 42, 0}), + WAVENINE(new int[]{2, 8, 1, 1, 0, 0, 0, 0}, new int[]{1, 0, 1, 1, 2, 1, 1, 10}, new int[]{0, 21, 0, 0, 0, 0, 0, 0, 0}), + WAVETEN(new int[]{2, 5, 1, 1, 0, 0, 0}, new int[]{1, 0, 1, 1, 4, 4, 8}, new int[]{21, 33, 0, 33, 30, 45, 0}); @Getter diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java index e7fdc8848f..8cff73bd55 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMineOreCountOverlay.java @@ -36,7 +36,6 @@ import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.game.ItemManager; import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPosition; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMinePluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMinePluginConfig.java index 76848a66e2..d6a0e9ecf2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMinePluginConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastmine/BlastMinePluginConfig.java @@ -1,101 +1,100 @@ -/* - * Copyright (c) 2018, Unmoon - * 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.blastmine; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -import java.awt.Color; - -@ConfigGroup("blastmine") -public interface BlastMinePluginConfig extends Config -{ - @ConfigItem( - position = 0, - keyName = "showOreOverlay", - name = "Show ore overlay", - description = "Configures whether or not the ore count overlay is displayed" - ) - default boolean showOreOverlay() - { - return true; - } - - @ConfigItem( - position = 1, - keyName = "showRockIconOverlay", - name = "Show icons overlay", - description = "Configures whether or not the icon overlay is displayed" - ) - default boolean showRockIconOverlay() - { - return true; - } - - @ConfigItem( - position = 2, - keyName = "showTimerOverlay", - name = "Show timer overlay", - description = "Configures whether or not the timer overlay is displayed" - ) - default boolean showTimerOverlay() - { - return true; - } - - @ConfigItem( - position = 3, - keyName = "showWarningOverlay", - name = "Show explosion warning", - description = "Configures whether or not the explosion warning overlay is displayed" - ) - default boolean showWarningOverlay() - { - return true; - } - - @ConfigItem( - position = 4, - keyName = "hexTimerColor", - name = "Timer color", - description = "Color of timer overlay" - ) - default Color getTimerColor() - { - return new Color(217, 54, 0); - } - - @ConfigItem( - position = 5, - keyName = "hexWarningColor", - name = "Warning color", - description = "Color of warning overlay" - ) - default Color getWarningColor() - { - return new Color(217, 54, 0); - } -} +/* + * Copyright (c) 2018, Unmoon + * 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.blastmine; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("blastmine") +public interface BlastMinePluginConfig extends Config +{ + @ConfigItem( + position = 0, + keyName = "showOreOverlay", + name = "Show ore overlay", + description = "Configures whether or not the ore count overlay is displayed" + ) + default boolean showOreOverlay() + { + return true; + } + + @ConfigItem( + position = 1, + keyName = "showRockIconOverlay", + name = "Show icons overlay", + description = "Configures whether or not the icon overlay is displayed" + ) + default boolean showRockIconOverlay() + { + return true; + } + + @ConfigItem( + position = 2, + keyName = "showTimerOverlay", + name = "Show timer overlay", + description = "Configures whether or not the timer overlay is displayed" + ) + default boolean showTimerOverlay() + { + return true; + } + + @ConfigItem( + position = 3, + keyName = "showWarningOverlay", + name = "Show explosion warning", + description = "Configures whether or not the explosion warning overlay is displayed" + ) + default boolean showWarningOverlay() + { + return true; + } + + @ConfigItem( + position = 4, + keyName = "hexTimerColor", + name = "Timer color", + description = "Color of timer overlay" + ) + default Color getTimerColor() + { + return new Color(217, 54, 0); + } + + @ConfigItem( + position = 5, + keyName = "hexWarningColor", + name = "Warning color", + description = "Color of warning overlay" + ) + default Color getWarningColor() + { + return new Color(217, 54, 0); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java index eb255b81b9..511359206e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java @@ -356,7 +356,7 @@ public class BoostsPlugin extends Plugin * section it will "activate" adding an additional 15 second section * to the boost timing. If again the preserve prayer is active for that * entire section a second 15 second section will be added. - * + *

* Preserve is only required to be on for the 4th and 5th sections of the boost timer * to gain full effect (seconds 45-75). * @@ -365,8 +365,8 @@ public class BoostsPlugin extends Plugin int getChangeDownTicks() { if (lastChangeDown == -1 || - config.displayNextBuffChange() == BoostsConfig.DisplayChangeMode.NEVER || - (config.displayNextBuffChange() == BoostsConfig.DisplayChangeMode.BOOSTED && !isChangedUp)) + config.displayNextBuffChange() == BoostsConfig.DisplayChangeMode.NEVER || + (config.displayNextBuffChange() == BoostsConfig.DisplayChangeMode.BOOSTED && !isChangedUp)) { return -1; } @@ -393,8 +393,8 @@ public class BoostsPlugin extends Plugin int getChangeUpTicks() { if (lastChangeUp == -1 || - config.displayNextDebuffChange() == BoostsConfig.DisplayChangeMode.NEVER || - (config.displayNextDebuffChange() == BoostsConfig.DisplayChangeMode.BOOSTED && !isChangedDown)) + config.displayNextDebuffChange() == BoostsConfig.DisplayChangeMode.NEVER || + (config.displayNextDebuffChange() == BoostsConfig.DisplayChangeMode.BOOSTED && !isChangedDown)) { return -1; } @@ -406,12 +406,13 @@ public class BoostsPlugin extends Plugin /** * Converts tick-based time to accurate second time + * * @param time tick-based time * @return second-based time */ int getChangeTime(final int time) { final long diff = System.currentTimeMillis() - lastTickMillis; - return time != -1 ? (int)((time * Constants.GAME_TICK_LENGTH - diff) / 1000d) : time; + return time != -1 ? (int) ((time * Constants.GAME_TICK_LENGTH - diff) / 1000d) : time; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java b/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java index 47752f415b..f315956a1b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/Boss.java @@ -77,7 +77,7 @@ enum Boss bosses = builder.build(); } - private Boss(int id, long period, ChronoUnit unit, int itemSpriteId) + Boss(int id, long period, ChronoUnit unit, int itemSpriteId) { this.id = id; this.spawnTime = Duration.of(period, unit); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonOverlay.java index ebee009d3b..591e55908b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonOverlay.java @@ -1,141 +1,142 @@ -/* - * Copyright (c) 2016-2018, Seth - * 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.cannon; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Polygon; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import static net.runelite.api.Perspective.LOCAL_TILE_SIZE; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.TextComponent; - -class CannonOverlay extends Overlay -{ - private static final int MAX_DISTANCE = 2500; - - private final Client client; - private final CannonConfig config; - private final CannonPlugin plugin; - private final TextComponent textComponent = new TextComponent(); - - @Inject - CannonOverlay(Client client, CannonConfig config, CannonPlugin plugin) - { - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.MED); - this.client = client; - this.config = config; - this.plugin = plugin; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isCannonPlaced() || plugin.getCannonPosition() == null) - { - return null; - } - - LocalPoint cannonPoint = LocalPoint.fromWorld(client, plugin.getCannonPosition()); - - if (cannonPoint == null) - { - return null; - } - - LocalPoint localLocation = client.getLocalPlayer().getLocalLocation(); - - if (localLocation.distanceTo(cannonPoint) <= MAX_DISTANCE) - { - Point cannonLoc = Perspective.getCanvasTextLocation(client, - graphics, - cannonPoint, - String.valueOf(plugin.getCballsLeft()), 150); - - if (cannonLoc != null) - { - textComponent.setText(String.valueOf(plugin.getCballsLeft())); - textComponent.setPosition(new java.awt.Point(cannonLoc.getX(), cannonLoc.getY())); - textComponent.setColor(plugin.getStateColor()); - textComponent.render(graphics); - } - - if (config.showDoubleHitSpot()) - { - Color color = config.highlightDoubleHitColor(); - drawDoubleHitSpots(graphics, cannonPoint, color); - } - } - - return null; - } - - - /** - * Draw the double hit spots on a 6 by 6 grid around the cannon - * @param startTile The position of the cannon - */ - private void drawDoubleHitSpots(Graphics2D graphics, LocalPoint startTile, Color color) - { - for (int x = -3; x <= 3; x++) - { - for (int y = -3; y <= 3; y++) - { - if (y != 1 && x != 1 && y != -1 && x != -1) - { - continue; - } - - //Ignore center square - if (y >= -1 && y <= 1 && x >= -1 && x <= 1) - { - continue; - } - - int xPos = startTile.getX() - (x * LOCAL_TILE_SIZE); - int yPos = startTile.getY() - (y * LOCAL_TILE_SIZE); - - LocalPoint marker = new LocalPoint(xPos, yPos); - Polygon poly = Perspective.getCanvasTilePoly(client, marker); - - if (poly == null) - { - continue; - } - - OverlayUtil.renderPolygon(graphics, poly, color); - } - } - } +/* + * Copyright (c) 2016-2018, Seth + * 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.cannon; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import static net.runelite.api.Perspective.LOCAL_TILE_SIZE; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.TextComponent; + +class CannonOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2500; + + private final Client client; + private final CannonConfig config; + private final CannonPlugin plugin; + private final TextComponent textComponent = new TextComponent(); + + @Inject + CannonOverlay(Client client, CannonConfig config, CannonPlugin plugin) + { + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.MED); + this.client = client; + this.config = config; + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isCannonPlaced() || plugin.getCannonPosition() == null) + { + return null; + } + + LocalPoint cannonPoint = LocalPoint.fromWorld(client, plugin.getCannonPosition()); + + if (cannonPoint == null) + { + return null; + } + + LocalPoint localLocation = client.getLocalPlayer().getLocalLocation(); + + if (localLocation.distanceTo(cannonPoint) <= MAX_DISTANCE) + { + Point cannonLoc = Perspective.getCanvasTextLocation(client, + graphics, + cannonPoint, + String.valueOf(plugin.getCballsLeft()), 150); + + if (cannonLoc != null) + { + textComponent.setText(String.valueOf(plugin.getCballsLeft())); + textComponent.setPosition(new java.awt.Point(cannonLoc.getX(), cannonLoc.getY())); + textComponent.setColor(plugin.getStateColor()); + textComponent.render(graphics); + } + + if (config.showDoubleHitSpot()) + { + Color color = config.highlightDoubleHitColor(); + drawDoubleHitSpots(graphics, cannonPoint, color); + } + } + + return null; + } + + + /** + * Draw the double hit spots on a 6 by 6 grid around the cannon + * + * @param startTile The position of the cannon + */ + private void drawDoubleHitSpots(Graphics2D graphics, LocalPoint startTile, Color color) + { + for (int x = -3; x <= 3; x++) + { + for (int y = -3; y <= 3; y++) + { + if (y != 1 && x != 1 && y != -1 && x != -1) + { + continue; + } + + //Ignore center square + if (y >= -1 && y <= 1 && x >= -1 && x <= 1) + { + continue; + } + + int xPos = startTile.getX() - (x * LOCAL_TILE_SIZE); + int yPos = startTile.getY() - (y * LOCAL_TILE_SIZE); + + LocalPoint marker = new LocalPoint(xPos, yPos); + Polygon poly = Perspective.getCanvasTilePoly(client, marker); + + if (poly == null) + { + continue; + } + + OverlayUtil.renderPolygon(graphics, poly, color); + } + } + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java index 744085c9a4..354dd0edf4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusGhost.java @@ -60,6 +60,7 @@ public enum CerberusGhost /** * Try to identify if NPC is ghost + * * @param npc npc * @return optional ghost */ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java index 68018b6c3b..2f384fcd80 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusOverlay.java @@ -63,13 +63,13 @@ public class CerberusOverlay extends Overlay // Ghosts are already sorted plugin.getGhosts().stream() - // Iterate only through the correct amount of ghosts - .limit(CerberusGhost.values().length) - .forEach(npc -> CerberusGhost - .fromNPC(npc) - .ifPresent(ghost -> panelComponent - .getChildren() - .add(new ImageComponent(iconManager.getSkillImage(ghost.getType()))))); + // Iterate only through the correct amount of ghosts + .limit(CerberusGhost.values().length) + .forEach(npc -> CerberusGhost + .fromNPC(npc) + .ifPresent(ghost -> panelComponent + .getChildren() + .add(new ImageComponent(iconManager.getSkillImage(ghost.getType()))))); return panelComponent.render(graphics); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatboxperformance/ChatboxPerformancePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatboxperformance/ChatboxPerformancePlugin.java index aaf6634ead..b19ab92f6f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatboxperformance/ChatboxPerformancePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatboxperformance/ChatboxPerformancePlugin.java @@ -1,158 +1,158 @@ -/* - * Copyright (c) 2018, Woox - * 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.chatboxperformance; - -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.widgets.WidgetType; -import net.runelite.api.events.WidgetPositioned; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.api.widgets.WidgetPositionMode; -import net.runelite.api.widgets.WidgetSizeMode; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; - -@PluginDescriptor( - name = "Chatbox performance", - hidden = true -) -public class ChatboxPerformancePlugin extends Plugin -{ - @Inject - private Client client; - - @Subscribe - public void onWidgetPositioned(WidgetPositioned event) - { - if (!areWidgetsFixed()) - { - fixChatbox(); - } - } - - private boolean areWidgetsFixed() - { - Widget widget = client.getWidget(WidgetInfo.CHATBOX_TRANSPARENT_BACKGROUND); - if (widget == null) - { - return true; - } - - Widget[] widgets = widget.getChildren(); - - if (widgets != null && widgets.length > 0) - { - Widget last = widgets[widgets.length - 1]; - return last != null && last.getOpacity() < 254; - } - - return false; - } - - private void fixChatbox() - { - fixDarkBackground(); - fixWhiteLines(true); - fixWhiteLines(false); - } - - private void fixDarkBackground() - { - int currOpacity = 256; - int prevY = 0; - Widget[] children = client.getWidget(WidgetInfo.CHATBOX_TRANSPARENT_BACKGROUND).getDynamicChildren(); - Widget prev = null; - for (Widget w : children) - { - if (w.getType() != WidgetType.RECTANGLE) - { - continue; - } - - if (prev != null) - { - int relY = w.getRelativeY(); - prev.setHeightMode(WidgetSizeMode.ABSOLUTE); - prev.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - prev.setRelativeY(prevY); - prev.setOriginalY(prev.getRelativeY()); - prev.setHeight(relY - prevY); - prev.setOriginalHeight(prev.getHeight()); - prev.setOpacity(currOpacity); - } - - prevY = w.getRelativeY(); - currOpacity -= 3; // Rough number, can't get exactly the same as Jagex because of rounding - prev = w; - } - if (prev != null) - { - prev.setOpacity(currOpacity); - } - } - - private void fixWhiteLines(boolean upperLine) - { - int currOpacity = 256; - int prevWidth = 0; - Widget[] children = client.getWidget(WidgetInfo.CHATBOX_TRANSPARENT_LINES).getDynamicChildren(); - Widget prev = null; - for (Widget w : children) - { - if (w.getType() != WidgetType.RECTANGLE) - { - continue; - } - - if ((w.getRelativeY() == 0 && !upperLine) || - (w.getRelativeY() != 0 && upperLine)) - { - continue; - } - - if (prev != null) - { - int width = w.getWidth(); - prev.setWidthMode(WidgetSizeMode.ABSOLUTE); - prev.setRelativeX(width); - prev.setOriginalX(width); - prev.setWidth(prevWidth - width); - prev.setOriginalWidth(prev.getWidth()); - prev.setOpacity(currOpacity); - } - - prevWidth = w.getWidth(); - - currOpacity -= upperLine ? 3 : 4; // Rough numbers, can't get exactly the same as Jagex because of rounding - prev = w; - } - if (prev != null) - { - prev.setOpacity(currOpacity); - } - } -} +/* + * Copyright (c) 2018, Woox + * 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.chatboxperformance; + +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.events.WidgetPositioned; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +@PluginDescriptor( + name = "Chatbox performance", + hidden = true +) +public class ChatboxPerformancePlugin extends Plugin +{ + @Inject + private Client client; + + @Subscribe + public void onWidgetPositioned(WidgetPositioned event) + { + if (!areWidgetsFixed()) + { + fixChatbox(); + } + } + + private boolean areWidgetsFixed() + { + Widget widget = client.getWidget(WidgetInfo.CHATBOX_TRANSPARENT_BACKGROUND); + if (widget == null) + { + return true; + } + + Widget[] widgets = widget.getChildren(); + + if (widgets != null && widgets.length > 0) + { + Widget last = widgets[widgets.length - 1]; + return last != null && last.getOpacity() < 254; + } + + return false; + } + + private void fixChatbox() + { + fixDarkBackground(); + fixWhiteLines(true); + fixWhiteLines(false); + } + + private void fixDarkBackground() + { + int currOpacity = 256; + int prevY = 0; + Widget[] children = client.getWidget(WidgetInfo.CHATBOX_TRANSPARENT_BACKGROUND).getDynamicChildren(); + Widget prev = null; + for (Widget w : children) + { + if (w.getType() != WidgetType.RECTANGLE) + { + continue; + } + + if (prev != null) + { + int relY = w.getRelativeY(); + prev.setHeightMode(WidgetSizeMode.ABSOLUTE); + prev.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + prev.setRelativeY(prevY); + prev.setOriginalY(prev.getRelativeY()); + prev.setHeight(relY - prevY); + prev.setOriginalHeight(prev.getHeight()); + prev.setOpacity(currOpacity); + } + + prevY = w.getRelativeY(); + currOpacity -= 3; // Rough number, can't get exactly the same as Jagex because of rounding + prev = w; + } + if (prev != null) + { + prev.setOpacity(currOpacity); + } + } + + private void fixWhiteLines(boolean upperLine) + { + int currOpacity = 256; + int prevWidth = 0; + Widget[] children = client.getWidget(WidgetInfo.CHATBOX_TRANSPARENT_LINES).getDynamicChildren(); + Widget prev = null; + for (Widget w : children) + { + if (w.getType() != WidgetType.RECTANGLE) + { + continue; + } + + if ((w.getRelativeY() == 0 && !upperLine) || + (w.getRelativeY() != 0 && upperLine)) + { + continue; + } + + if (prev != null) + { + int width = w.getWidth(); + prev.setWidthMode(WidgetSizeMode.ABSOLUTE); + prev.setRelativeX(width); + prev.setOriginalX(width); + prev.setWidth(prevWidth - width); + prev.setOriginalWidth(prev.getWidth()); + prev.setOpacity(currOpacity); + } + + prevWidth = w.getWidth(); + + currOpacity -= upperLine ? 3 : 4; // Rough numbers, can't get exactly the same as Jagex because of rounding + prev = w; + } + if (prev != null) + { + prev.setOpacity(currOpacity); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index bd7c941ee1..b926e9528f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -653,7 +653,7 @@ public class ChatCommandsPlugin extends Plugin * response. * * @param chatMessage The chat message containing the command. - * @param message The chat message + * @param message The chat message */ private void itemPriceLookup(ChatMessage chatMessage, String message) { @@ -689,17 +689,17 @@ public class ChatCommandsPlugin extends Plugin int itemPrice = item.getPrice(); final ChatMessageBuilder builder = new ChatMessageBuilder(); - builder.append(ChatColorType.NORMAL); - builder.append(ChatColorType.HIGHLIGHT); - builder.append(item.getName()); - builder.append(ChatColorType.NORMAL); - builder.append(": GE "); - builder.append(ChatColorType.HIGHLIGHT); - builder.append(StackFormatter.formatNumber(itemPrice)); - builder.append(ChatColorType.NORMAL); - builder.append(": OSB "); - builder.append(ChatColorType.HIGHLIGHT); - builder.append(StackFormatter.formatNumber(osbresult.getOverall_average())); + builder.append(ChatColorType.NORMAL); + builder.append(ChatColorType.HIGHLIGHT); + builder.append(item.getName()); + builder.append(ChatColorType.NORMAL); + builder.append(": GE "); + builder.append(ChatColorType.HIGHLIGHT); + builder.append(StackFormatter.formatNumber(itemPrice)); + builder.append(ChatColorType.NORMAL); + builder.append(": OSB "); + builder.append(ChatColorType.HIGHLIGHT); + builder.append(StackFormatter.formatNumber(osbresult.getOverall_average())); ItemComposition itemComposition = itemManager.getItemComposition(itemId); if (itemComposition != null) @@ -726,7 +726,7 @@ public class ChatCommandsPlugin extends Plugin * response. * * @param chatMessage The chat message containing the command. - * @param message The chat message + * @param message The chat message */ private void playerSkillLookup(ChatMessage chatMessage, String message) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java index 03aa7c2110..11e2c98e21 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java @@ -1,262 +1,263 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * 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.chathistory; - -import com.google.common.collect.EvictingQueue; -import com.google.inject.Provides; -import java.awt.event.KeyEvent; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Iterator; -import java.util.Queue; -import javax.inject.Inject; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.ScriptID; -import net.runelite.api.VarClientInt; -import net.runelite.api.VarClientStr; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.MenuOptionClicked; -import net.runelite.api.vars.InputType; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.chat.ChatMessageManager; -import net.runelite.client.chat.QueuedMessage; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.util.Text; - -@PluginDescriptor( - name = "Chat History", - description = "Retain your chat history when logging in/out or world hopping", - tags = {"chat", "history", "retain", "cycle", "pm"} -) -public class ChatHistoryPlugin extends Plugin implements KeyListener -{ - private static final String WELCOME_MESSAGE = "Welcome to Old School RuneScape."; - private static final String CLEAR_HISTORY = "Clear history"; - private static final String CLEAR_PRIVATE = "Private:"; - private static final int CYCLE_HOTKEY = KeyEvent.VK_TAB; - private static final int FRIENDS_MAX_SIZE = 5; - - private Queue messageQueue; - private Deque friends; - - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private ChatHistoryConfig config; - - @Inject - private KeyManager keyManager; - - @Inject - private ChatMessageManager chatMessageManager; - - @Provides - ChatHistoryConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(ChatHistoryConfig.class); - } - - @Override - protected void startUp() - { - messageQueue = EvictingQueue.create(100); - friends = new ArrayDeque<>(FRIENDS_MAX_SIZE + 1); - keyManager.registerKeyListener(this); - } - - @Override - protected void shutDown() - { - messageQueue.clear(); - messageQueue = null; - friends.clear(); - friends = null; - keyManager.unregisterKeyListener(this); - } - - @Subscribe - public void onChatMessage(ChatMessage chatMessage) - { - // Start sending old messages right after the welcome message, as that is most reliable source - // of information that chat history was reset - if (chatMessage.getMessage().equals(WELCOME_MESSAGE)) - { - if (!config.retainChatHistory()) - { - return; - } - - QueuedMessage queuedMessage; - - while ((queuedMessage = messageQueue.poll()) != null) - { - chatMessageManager.queue(queuedMessage); - } - - return; - } - - switch (chatMessage.getType()) - { - case PRIVATECHATOUT: - case PRIVATECHAT: - case MODPRIVATECHAT: - final String name = Text.removeTags(chatMessage.getName()); - // Remove to ensure uniqueness & its place in history - if (!friends.remove(name)) - { - // If the friend didn't previously exist ensure deque capacity doesn't increase by adding them - if (friends.size() >= FRIENDS_MAX_SIZE) - { - friends.remove(); - } - } - friends.add(name); - // intentional fall-through - case PUBLICCHAT: - case MODCHAT: - case FRIENDSCHAT: - case CONSOLE: - final QueuedMessage queuedMessage = QueuedMessage.builder() - .type(chatMessage.getType()) - .name(chatMessage.getName()) - .sender(chatMessage.getSender()) - .value(nbsp(chatMessage.getMessage())) - .runeLiteFormattedMessage(nbsp(chatMessage.getMessageNode().getRuneLiteFormatMessage())) - .timestamp(chatMessage.getTimestamp()) - .build(); - - if (!messageQueue.contains(queuedMessage)) - { - messageQueue.offer(queuedMessage); - } - } - } - - @Subscribe - public void onMenuOptionClicked(MenuOptionClicked event) - { - String menuOption = event.getMenuOption(); - - if (menuOption.contains(CLEAR_HISTORY)) - { - if (menuOption.startsWith(CLEAR_PRIVATE)) - { - messageQueue.removeIf(e -> e.getType() == ChatMessageType.PRIVATECHAT || - e.getType() == ChatMessageType.PRIVATECHATOUT || e.getType() == ChatMessageType.MODPRIVATECHAT); - friends.clear(); - } - else - { - messageQueue.removeIf(e -> e.getType() == ChatMessageType.PUBLICCHAT || e.getType() == ChatMessageType.MODCHAT); - } - } - } - - /** - * Small hack to prevent plugins checking for specific messages to match - * @param message message - * @return message with nbsp - */ - private static String nbsp(final String message) - { - if (message != null) - { - return message.replace(' ', '\u00A0'); - } - - return null; - } - - @Override - public void keyPressed(KeyEvent e) - { - if (e.getKeyCode() != CYCLE_HOTKEY || !config.pmTargetCycling()) - { - return; - } - - if (client.getVar(VarClientInt.INPUT_TYPE) != InputType.PRIVATE_MESSAGE.getType()) - { - return; - } - - clientThread.invoke(() -> - { - final String target = findPreviousFriend(); - if (target == null) - { - return; - } - - final String currentMessage = client.getVar(VarClientStr.INPUT_TEXT); - - client.runScript(ScriptID.OPEN_PRIVATE_MESSAGE_INTERFACE, target); - - client.setVar(VarClientStr.INPUT_TEXT, currentMessage); - client.runScript(ScriptID.CHAT_TEXT_INPUT_REBUILD, ""); - }); - } - - @Override - public void keyTyped(KeyEvent e) - { - } - - @Override - public void keyReleased(KeyEvent e) - { - } - - private String findPreviousFriend() - { - final String currentTarget = client.getVar(VarClientStr.PRIVATE_MESSAGE_TARGET); - if (currentTarget == null || friends.isEmpty()) - { - return null; - } - - for (Iterator it = friends.descendingIterator(); it.hasNext(); ) - { - String friend = it.next(); - if (friend.equals(currentTarget)) - { - return it.hasNext() ? it.next() : friends.getLast(); - } - } - - return friends.getLast(); - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * 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.chathistory; + +import com.google.common.collect.EvictingQueue; +import com.google.inject.Provides; +import java.awt.event.KeyEvent; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.Queue; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.ScriptID; +import net.runelite.api.VarClientInt; +import net.runelite.api.VarClientStr; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.vars.InputType; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.chat.QueuedMessage; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.Text; + +@PluginDescriptor( + name = "Chat History", + description = "Retain your chat history when logging in/out or world hopping", + tags = {"chat", "history", "retain", "cycle", "pm"} +) +public class ChatHistoryPlugin extends Plugin implements KeyListener +{ + private static final String WELCOME_MESSAGE = "Welcome to Old School RuneScape."; + private static final String CLEAR_HISTORY = "Clear history"; + private static final String CLEAR_PRIVATE = "Private:"; + private static final int CYCLE_HOTKEY = KeyEvent.VK_TAB; + private static final int FRIENDS_MAX_SIZE = 5; + + private Queue messageQueue; + private Deque friends; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private ChatHistoryConfig config; + + @Inject + private KeyManager keyManager; + + @Inject + private ChatMessageManager chatMessageManager; + + @Provides + ChatHistoryConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(ChatHistoryConfig.class); + } + + @Override + protected void startUp() + { + messageQueue = EvictingQueue.create(100); + friends = new ArrayDeque<>(FRIENDS_MAX_SIZE + 1); + keyManager.registerKeyListener(this); + } + + @Override + protected void shutDown() + { + messageQueue.clear(); + messageQueue = null; + friends.clear(); + friends = null; + keyManager.unregisterKeyListener(this); + } + + @Subscribe + public void onChatMessage(ChatMessage chatMessage) + { + // Start sending old messages right after the welcome message, as that is most reliable source + // of information that chat history was reset + if (chatMessage.getMessage().equals(WELCOME_MESSAGE)) + { + if (!config.retainChatHistory()) + { + return; + } + + QueuedMessage queuedMessage; + + while ((queuedMessage = messageQueue.poll()) != null) + { + chatMessageManager.queue(queuedMessage); + } + + return; + } + + switch (chatMessage.getType()) + { + case PRIVATECHATOUT: + case PRIVATECHAT: + case MODPRIVATECHAT: + final String name = Text.removeTags(chatMessage.getName()); + // Remove to ensure uniqueness & its place in history + if (!friends.remove(name)) + { + // If the friend didn't previously exist ensure deque capacity doesn't increase by adding them + if (friends.size() >= FRIENDS_MAX_SIZE) + { + friends.remove(); + } + } + friends.add(name); + // intentional fall-through + case PUBLICCHAT: + case MODCHAT: + case FRIENDSCHAT: + case CONSOLE: + final QueuedMessage queuedMessage = QueuedMessage.builder() + .type(chatMessage.getType()) + .name(chatMessage.getName()) + .sender(chatMessage.getSender()) + .value(nbsp(chatMessage.getMessage())) + .runeLiteFormattedMessage(nbsp(chatMessage.getMessageNode().getRuneLiteFormatMessage())) + .timestamp(chatMessage.getTimestamp()) + .build(); + + if (!messageQueue.contains(queuedMessage)) + { + messageQueue.offer(queuedMessage); + } + } + } + + @Subscribe + public void onMenuOptionClicked(MenuOptionClicked event) + { + String menuOption = event.getMenuOption(); + + if (menuOption.contains(CLEAR_HISTORY)) + { + if (menuOption.startsWith(CLEAR_PRIVATE)) + { + messageQueue.removeIf(e -> e.getType() == ChatMessageType.PRIVATECHAT || + e.getType() == ChatMessageType.PRIVATECHATOUT || e.getType() == ChatMessageType.MODPRIVATECHAT); + friends.clear(); + } + else + { + messageQueue.removeIf(e -> e.getType() == ChatMessageType.PUBLICCHAT || e.getType() == ChatMessageType.MODCHAT); + } + } + } + + /** + * Small hack to prevent plugins checking for specific messages to match + * + * @param message message + * @return message with nbsp + */ + private static String nbsp(final String message) + { + if (message != null) + { + return message.replace(' ', '\u00A0'); + } + + return null; + } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() != CYCLE_HOTKEY || !config.pmTargetCycling()) + { + return; + } + + if (client.getVar(VarClientInt.INPUT_TYPE) != InputType.PRIVATE_MESSAGE.getType()) + { + return; + } + + clientThread.invoke(() -> + { + final String target = findPreviousFriend(); + if (target == null) + { + return; + } + + final String currentMessage = client.getVar(VarClientStr.INPUT_TEXT); + + client.runScript(ScriptID.OPEN_PRIVATE_MESSAGE_INTERFACE, target); + + client.setVar(VarClientStr.INPUT_TEXT, currentMessage); + client.runScript(ScriptID.CHAT_TEXT_INPUT_REBUILD, ""); + }); + } + + @Override + public void keyTyped(KeyEvent e) + { + } + + @Override + public void keyReleased(KeyEvent e) + { + } + + private String findPreviousFriend() + { + final String currentTarget = client.getVar(VarClientStr.PRIVATE_MESSAGE_TARGET); + if (currentTarget == null || friends.isEmpty()) + { + return null; + } + + for (Iterator it = friends.descendingIterator(); it.hasNext(); ) + { + String friend = it.next(); + if (friend.equals(currentTarget)) + { + return it.hasNext() ? it.next() : friends.getLast(); + } + } + + return friends.getLast(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java index e2e2699f2a..8b2fc8d652 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java @@ -1,231 +1,231 @@ -/* - * Copyright (c) 2018, Hydrox6 - * Copyright (c) 2018, Adam - * 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.chatnotifications; - -import com.google.common.base.Strings; -import com.google.inject.Provides; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import static java.util.regex.Pattern.quote; -import java.util.stream.Collectors; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.MessageNode; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.client.Notifier; -import net.runelite.client.RuneLiteProperties; -import net.runelite.client.chat.ChatColorType; -import net.runelite.client.chat.ChatMessageManager; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.util.Text; - -@PluginDescriptor( - name = "Chat Notifications", - description = "Highlight and notify you of chat messages", - tags = {"duel", "messages", "notifications", "trade", "username"}, - enabledByDefault = false -) -public class ChatNotificationsPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private ChatNotificationsConfig config; - - @Inject - private ChatMessageManager chatMessageManager; - - @Inject - private Notifier notifier; - - @Inject - private RuneLiteProperties runeLiteProperties; - - //Custom Highlights - private Pattern usernameMatcher = null; - private String usernameReplacer = ""; - private Pattern highlightMatcher = null; - - @Provides - ChatNotificationsConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(ChatNotificationsConfig.class); - } - - @Override - public void startUp() - { - updateHighlights(); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - switch (event.getGameState()) - { - case LOGIN_SCREEN: - case HOPPING: - usernameMatcher = null; - break; - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("chatnotification")) - { - updateHighlights(); - } - } - - private void updateHighlights() - { - highlightMatcher = null; - - if (!config.highlightWordsString().trim().equals("")) - { - List items = Text.fromCSV(config.highlightWordsString()); - String joined = items.stream() - .map(Pattern::quote) - .collect(Collectors.joining("|")); - highlightMatcher = Pattern.compile("\\b(" + joined + ")\\b", Pattern.CASE_INSENSITIVE); - } - } - - @Subscribe - public void onChatMessage(ChatMessage chatMessage) - { - MessageNode messageNode = chatMessage.getMessageNode(); - String nodeValue = Text.removeTags(messageNode.getValue()); - boolean update = false; - - switch (chatMessage.getType()) - { - case TRADEREQ: - if (chatMessage.getMessage().contains("wishes to trade with you.") && config.notifyOnTrade()) - { - notifier.notify(chatMessage.getMessage()); - } - break; - case CHALREQ_TRADE: - if (chatMessage.getMessage().contains("wishes to duel with you.") && config.notifyOnDuel()) - { - notifier.notify(chatMessage.getMessage()); - } - break; - case CONSOLE: - // Don't notify for notification messages - if (chatMessage.getName().equals(runeLiteProperties.getTitle())) - { - return; - } - break; - } - - if (usernameMatcher == null && client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) - { - String username = client.getLocalPlayer().getName(); - usernameMatcher = Pattern.compile("\\b(" + quote(username) + ")\\b", Pattern.CASE_INSENSITIVE); - usernameReplacer = "" + username + ""; - } - - if (config.highlightOwnName() && usernameMatcher != null) - { - Matcher matcher = usernameMatcher.matcher(messageNode.getValue()); - if (matcher.find()) - { - messageNode.setValue(matcher.replaceAll(usernameReplacer)); - update = true; - - if (config.notifyOnOwnName()) - { - sendNotification(chatMessage); - } - } - } - - if (highlightMatcher != null) - { - Matcher matcher = highlightMatcher.matcher(nodeValue); - boolean found = false; - StringBuffer stringBuffer = new StringBuffer(); - - while (matcher.find()) - { - String value = matcher.group(); - matcher.appendReplacement(stringBuffer, "" + value + ""); - update = true; - found = true; - } - - if (found) - { - matcher.appendTail(stringBuffer); - messageNode.setValue(stringBuffer.toString()); - - if (config.notifyOnHighlight()) - { - sendNotification(chatMessage); - } - } - } - - if (update) - { - messageNode.setRuneLiteFormatMessage(messageNode.getValue()); - chatMessageManager.update(messageNode); - } - } - - private void sendNotification(ChatMessage message) - { - String name = Text.removeTags(message.getName()); - String sender = message.getSender(); - StringBuilder stringBuilder = new StringBuilder(); - - if (!Strings.isNullOrEmpty(sender)) - { - stringBuilder.append('[').append(sender).append("] "); - } - - if (!Strings.isNullOrEmpty(name)) - { - stringBuilder.append(name).append(": "); - } - - stringBuilder.append(Text.removeTags(message.getMessage())); - String notification = stringBuilder.toString(); - notifier.notify(notification); - } -} +/* + * Copyright (c) 2018, Hydrox6 + * Copyright (c) 2018, Adam + * 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.chatnotifications; + +import com.google.common.base.Strings; +import com.google.inject.Provides; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import static java.util.regex.Pattern.quote; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.MessageNode; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.client.Notifier; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.chat.ChatColorType; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.Text; + +@PluginDescriptor( + name = "Chat Notifications", + description = "Highlight and notify you of chat messages", + tags = {"duel", "messages", "notifications", "trade", "username"}, + enabledByDefault = false +) +public class ChatNotificationsPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ChatNotificationsConfig config; + + @Inject + private ChatMessageManager chatMessageManager; + + @Inject + private Notifier notifier; + + @Inject + private RuneLiteProperties runeLiteProperties; + + //Custom Highlights + private Pattern usernameMatcher = null; + private String usernameReplacer = ""; + private Pattern highlightMatcher = null; + + @Provides + ChatNotificationsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(ChatNotificationsConfig.class); + } + + @Override + public void startUp() + { + updateHighlights(); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + switch (event.getGameState()) + { + case LOGIN_SCREEN: + case HOPPING: + usernameMatcher = null; + break; + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("chatnotification")) + { + updateHighlights(); + } + } + + private void updateHighlights() + { + highlightMatcher = null; + + if (!config.highlightWordsString().trim().equals("")) + { + List items = Text.fromCSV(config.highlightWordsString()); + String joined = items.stream() + .map(Pattern::quote) + .collect(Collectors.joining("|")); + highlightMatcher = Pattern.compile("\\b(" + joined + ")\\b", Pattern.CASE_INSENSITIVE); + } + } + + @Subscribe + public void onChatMessage(ChatMessage chatMessage) + { + MessageNode messageNode = chatMessage.getMessageNode(); + String nodeValue = Text.removeTags(messageNode.getValue()); + boolean update = false; + + switch (chatMessage.getType()) + { + case TRADEREQ: + if (chatMessage.getMessage().contains("wishes to trade with you.") && config.notifyOnTrade()) + { + notifier.notify(chatMessage.getMessage()); + } + break; + case CHALREQ_TRADE: + if (chatMessage.getMessage().contains("wishes to duel with you.") && config.notifyOnDuel()) + { + notifier.notify(chatMessage.getMessage()); + } + break; + case CONSOLE: + // Don't notify for notification messages + if (chatMessage.getName().equals(runeLiteProperties.getTitle())) + { + return; + } + break; + } + + if (usernameMatcher == null && client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) + { + String username = client.getLocalPlayer().getName(); + usernameMatcher = Pattern.compile("\\b(" + quote(username) + ")\\b", Pattern.CASE_INSENSITIVE); + usernameReplacer = "" + username + ""; + } + + if (config.highlightOwnName() && usernameMatcher != null) + { + Matcher matcher = usernameMatcher.matcher(messageNode.getValue()); + if (matcher.find()) + { + messageNode.setValue(matcher.replaceAll(usernameReplacer)); + update = true; + + if (config.notifyOnOwnName()) + { + sendNotification(chatMessage); + } + } + } + + if (highlightMatcher != null) + { + Matcher matcher = highlightMatcher.matcher(nodeValue); + boolean found = false; + StringBuffer stringBuffer = new StringBuffer(); + + while (matcher.find()) + { + String value = matcher.group(); + matcher.appendReplacement(stringBuffer, "" + value + ""); + update = true; + found = true; + } + + if (found) + { + matcher.appendTail(stringBuffer); + messageNode.setValue(stringBuffer.toString()); + + if (config.notifyOnHighlight()) + { + sendNotification(chatMessage); + } + } + } + + if (update) + { + messageNode.setRuneLiteFormatMessage(messageNode.getValue()); + chatMessageManager.update(messageNode); + } + } + + private void sendNotification(ChatMessage message) + { + String name = Text.removeTags(message.getName()); + String sender = message.getSender(); + StringBuilder stringBuilder = new StringBuilder(); + + if (!Strings.isNullOrEmpty(sender)) + { + stringBuilder.append('[').append(sender).append("] "); + } + + if (!Strings.isNullOrEmpty(name)) + { + stringBuilder.append(name).append(": "); + } + + stringBuilder.append(Text.removeTags(message.getMessage())); + String notification = stringBuilder.toString(); + notifier.notify(notification); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java index 8e2f32f2ba..a8403c65d5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java @@ -33,13 +33,11 @@ import java.awt.Color; import java.awt.image.BufferedImage; import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Arrays; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import javax.inject.Inject; import net.runelite.api.ChatLineBuffer; @@ -49,9 +47,7 @@ import net.runelite.api.ClanMemberRank; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.MessageNode; -import net.runelite.api.Opcodes; import net.runelite.api.Player; -import net.runelite.api.Script; import net.runelite.api.ScriptID; import net.runelite.api.SpriteID; import net.runelite.api.VarClientStr; @@ -65,10 +61,7 @@ import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.PlayerDespawned; import net.runelite.api.events.PlayerSpawned; -import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.VarClientStrChanged; -import net.runelite.api.events.WidgetMenuOptionClicked; -import net.runelite.api.widgets.JavaScriptCallback; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetType; @@ -78,8 +71,6 @@ import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ClanManager; import net.runelite.client.game.SpriteManager; -import net.runelite.client.menus.MenuManager; -import net.runelite.client.menus.WidgetMenuOption; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import static net.runelite.client.ui.JagexColors.CHAT_CLAN_NAME_OPAQUE_BACKGROUND; @@ -120,16 +111,13 @@ public class ClanChatPlugin extends Plugin @Inject private ClientThread clientThread; - @Inject - private MenuManager menuManager; - private List chats = new ArrayList<>(); - + public static CopyOnWriteArrayList getClanMembers() { return (CopyOnWriteArrayList) clanMembers.clone(); } - + private static CopyOnWriteArrayList clanMembers = new CopyOnWriteArrayList<>(); private ClanChatIndicator clanMemberCounter; /** @@ -139,8 +127,6 @@ public class ClanChatPlugin extends Plugin private Map activityBuffer = new HashMap<>(); private int clanJoinedTick; - private ConcurrentHashMap ccWidgetMap = new ConcurrentHashMap(); - @Provides ClanChatConfig getConfig(ConfigManager configManager) { @@ -561,13 +547,14 @@ public class ClanChatPlugin extends Plugin private void loadClanChats() { Widget clanChatList = client.getWidget(WidgetInfo.CLAN_CHAT_LIST); - clanChatList.setScrollHeight( 14 * chats.size()); - clanChatList.revalidateScroll(); if (clanChatList == null) { return; } + clanChatList.setScrollHeight(14 * chats.size()); + clanChatList.revalidateScroll(); + int y = 2; clanChatList.setChildren(null); for (String chat : Lists.reverse(chats)) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModeOverlay.java index 28ebb3fe29..4cfc1cd6ad 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModeOverlay.java @@ -7,7 +7,6 @@ import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Player; import net.runelite.api.Point; -import net.runelite.client.game.ClanManager; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; @@ -49,7 +48,8 @@ public class ClanManModeOverlay extends Overlay if (textLocation != null) { - if (config.getClanAttackableColor().equals(color) && config.ShowBold()) { + if (config.getClanAttackableColor().equals(color) && config.ShowBold()) + { graphics.setFont(FontManager.getRunescapeBoldFont()); } OverlayUtil.renderTextLocation(graphics, textLocation, name, color); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModePlugin.java index 9c597bafe3..63d0c6c37d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanmanmode/ClanManModePlugin.java @@ -70,14 +70,16 @@ public class ClanManModePlugin extends Plugin Map clan = new HashMap<>(); @Override - protected void startUp() throws Exception { + protected void startUp() throws Exception + { overlayManager.add(ClanManModeOverlay); overlayManager.add(ClanManModeTileOverlay); overlayManager.add(ClanManModeMinimapOverlay); } @Override - protected void shutDown() throws Exception { + protected void shutDown() throws Exception + { overlayManager.remove(ClanManModeOverlay); overlayManager.remove(ClanManModeTileOverlay); overlayManager.remove(ClanManModeMinimapOverlay); @@ -90,17 +92,21 @@ public class ClanManModePlugin extends Plugin } @Subscribe - public void onGameStateChanged(GameStateChanged gameStateChanged) { - if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN || gameStateChanged.getGameState() == GameState.HOPPING) { + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN || gameStateChanged.getGameState() == GameState.HOPPING) + { ticks = 0; } } @Subscribe - public void onGameTick(GameTick event) { + public void onGameTick(GameTick event) + { ticks++; final Player localPlayer = client.getLocalPlayer(); - if (!clan.containsKey(localPlayer.getName())) { + if (!clan.containsKey(localPlayer.getName())) + { clan.put(localPlayer.getName(), localPlayer.getCombatLevel()); } WorldPoint a = localPlayer.getWorldLocation(); @@ -108,30 +114,38 @@ public class ClanManModePlugin extends Plugin int upperLevel = ((a.getY() - 3520) / 8) + 1; wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel; inwildy = client.getVar(Varbits.IN_WILDERNESS); - if (clan.size() > 0) { + if (clan.size() > 0) + { clanmin = Collections.min(clan.values()); clanmax = Collections.max(clan.values()); } } @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) { - if (!config.hideAtkOpt()) { + public void onMenuEntryAdded(MenuEntryAdded event) + { + if (!config.hideAtkOpt()) + { return; } - if (client.getGameState() != GameState.LOGGED_IN) { + if (client.getGameState() != GameState.LOGGED_IN) + { return; } final String option = Text.removeTags(event.getOption()).toLowerCase(); - if (option.equals("attack")) { + if (option.equals("attack")) + { final Pattern ppattern = Pattern.compile("(.+?) 6400 ? underLevel : upperLevel; int wildydiff = plugin.wildernessLevel - wildernessLevel; - if (wildydiff < 0) { + if (wildydiff < 0) + { wildydiff = 0; } - if (config.CalcSelfCB()) { - if (interacting.getCombatLevel() <= selfmax && interacting.getCombatLevel() - wildydiff >= selfmin && !interactor.isClanMember()) { + if (config.CalcSelfCB()) + { + if (interacting.getCombatLevel() <= selfmax && interacting.getCombatLevel() - wildydiff >= selfmin && !interactor.isClanMember()) + { interactors.put(interactor.getName(), player.getName()); consumer.accept(interactor, config.getClanAttackableColor()); } - } else { - if (interacting.getCombatLevel() <= maxatk && interacting.getCombatLevel() - wildydiff >= minatk && !interactor.isClanMember()) { + } + else + { + if (interacting.getCombatLevel() <= maxatk && interacting.getCombatLevel() - wildydiff >= minatk && !interactor.isClanMember()) + { interactors.put(interactor.getName(), player.getName()); consumer.accept(interactor, config.getClanAttackableColor()); } @@ -92,43 +110,61 @@ public class ClanManModeService } } } - } else { - if (config.PersistentClan()) { - if (plugin.clan.containsKey(player.getName())) { + } + else + { + if (config.PersistentClan()) + { + if (plugin.clan.containsKey(player.getName())) + { consumer.accept(player, config.getClanMemberColor()); } } - if (config.highlightAttacked()) { - if (interactors.containsKey(player.getName())) { + if (config.highlightAttacked()) + { + if (interactors.containsKey(player.getName())) + { String attackername = interactors.get(player.getName()); boolean found = false; - for (Player attacker : client.getPlayers()) { - if (attacker == null || attacker.getName() == null) { + for (Player attacker : client.getPlayers()) + { + if (attacker == null || attacker.getName() == null) + { continue; } - if (attacker.getName().equals(attackername)) { + if (attacker.getName().equals(attackername)) + { found = true; Actor ainteract = attacker.getInteracting(); - if (ainteract != null) { - if (ainteract.getName().equals(player.getName())) { + if (ainteract != null) + { + if (ainteract.getName().equals(player.getName())) + { consumer.accept(player, config.getClanAttackableColor()); - } else { + } + else + { interactors.remove(player.getName()); } - } else { + } + else + { interactors.remove(player.getName()); } break; } } - if (!found) { + if (!found) + { interactors.remove(player.getName()); } continue; } } - if (config.highlightAttackable()) { - if ((config.hideAttackable() && plugin.ticks >= config.hideTime()) || plugin.clan.containsKey(player.getName())) { + if (config.highlightAttackable()) + { + if ((config.hideAttackable() && plugin.ticks >= config.hideTime()) || plugin.clan.containsKey(player.getName())) + { continue; } WorldPoint a = player.getWorldLocation(); @@ -136,15 +172,21 @@ public class ClanManModeService int upperLevel = ((a.getY() - 3520) / 8) + 1; int wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel; int wildydiff = plugin.wildernessLevel - wildernessLevel; - if (wildydiff < 0) { + if (wildydiff < 0) + { wildydiff = 0; } - if (config.CalcSelfCB()) { - if (player.getCombatLevel() <= selfmax && player.getCombatLevel() - wildydiff >= selfmin) { + if (config.CalcSelfCB()) + { + if (player.getCombatLevel() <= selfmax && player.getCombatLevel() - wildydiff >= selfmin) + { consumer.accept(player, config.getAttackableColor()); } - } else { - if (player.getCombatLevel() <= maxatk && player.getCombatLevel() - wildydiff >= minatk) { + } + else + { + if (player.getCombatLevel() <= maxatk && player.getCombatLevel() - wildydiff >= minatk) + { consumer.accept(player, config.getAttackableColor()); } } 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 d060f1a3e4..6dc32fde32 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 @@ -749,7 +749,7 @@ public class ClueScrollPlugin extends Plugin textComponent.render(graphics); } - void scrollToWidget(WidgetInfo list, WidgetInfo scrollbar, Widget ... toHighlight) + void scrollToWidget(WidgetInfo list, WidgetInfo scrollbar, Widget... toHighlight) { final Widget parent = client.getWidget(list); int averageCentralY = 0; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java index c59a79728c..a343f49357 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java @@ -267,12 +267,12 @@ public class AnagramClue extends ClueScroll implements TextClueScroll, NpcClueSc @Override public String[] getNpcs() { - return new String[] {npc}; + return new String[]{npc}; } @Override public int[] getObjectIds() { - return new int[] {objectId}; + return new int[]{objectId}; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java index 404ce70eae..a4aa491c32 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CipherClue.java @@ -133,6 +133,6 @@ public class CipherClue extends ClueScroll implements TextClueScroll, NpcClueScr public String[] getNpcs() { - return new String[] {npc}; + return new String[]{npc}; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java index f8582fe1c0..888458197e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java @@ -32,7 +32,56 @@ import lombok.Getter; import net.runelite.api.NPC; import static net.runelite.api.NullObjectID.NULL_1293; import net.runelite.api.ObjectComposition; -import static net.runelite.api.ObjectID.*; +import static net.runelite.api.ObjectID.BOOKCASE_12539; +import static net.runelite.api.ObjectID.BOOKCASE_380; +import static net.runelite.api.ObjectID.BOOKCASE_394; +import static net.runelite.api.ObjectID.BOOKCASE_9523; +import static net.runelite.api.ObjectID.BOXES; +import static net.runelite.api.ObjectID.BOXES_360; +import static net.runelite.api.ObjectID.BOXES_361; +import static net.runelite.api.ObjectID.BOXES_3686; +import static net.runelite.api.ObjectID.BOXES_5111; +import static net.runelite.api.ObjectID.BOXES_6176; +import static net.runelite.api.ObjectID.BUCKET_9568; +import static net.runelite.api.ObjectID.BUSH_2357; +import static net.runelite.api.ObjectID.CLOSED_CHEST_25592; +import static net.runelite.api.ObjectID.CLOSED_CHEST_375; +import static net.runelite.api.ObjectID.CLOSED_CHEST_5108; +import static net.runelite.api.ObjectID.COFFIN; +import static net.runelite.api.ObjectID.CRATES_11600; +import static net.runelite.api.ObjectID.CRATES_24088; +import static net.runelite.api.ObjectID.CRATE_11485; +import static net.runelite.api.ObjectID.CRATE_12963; +import static net.runelite.api.ObjectID.CRATE_18204; +import static net.runelite.api.ObjectID.CRATE_18506; +import static net.runelite.api.ObjectID.CRATE_18889; +import static net.runelite.api.ObjectID.CRATE_24344; +import static net.runelite.api.ObjectID.CRATE_25775; +import static net.runelite.api.ObjectID.CRATE_26635; +import static net.runelite.api.ObjectID.CRATE_27532; +import static net.runelite.api.ObjectID.CRATE_27533; +import static net.runelite.api.ObjectID.CRATE_354; +import static net.runelite.api.ObjectID.CRATE_355; +import static net.runelite.api.ObjectID.CRATE_356; +import static net.runelite.api.ObjectID.CRATE_357; +import static net.runelite.api.ObjectID.CRATE_358; +import static net.runelite.api.ObjectID.CRATE_366; +import static net.runelite.api.ObjectID.CRATE_5106; +import static net.runelite.api.ObjectID.CRATE_5107; +import static net.runelite.api.ObjectID.CRATE_5113; +import static net.runelite.api.ObjectID.CRATE_9534; +import static net.runelite.api.ObjectID.DRAWERS; +import static net.runelite.api.ObjectID.DRAWERS_25766; +import static net.runelite.api.ObjectID.DRAWERS_350; +import static net.runelite.api.ObjectID.DRAWERS_352; +import static net.runelite.api.ObjectID.DRAWERS_5618; +import static net.runelite.api.ObjectID.DRAWERS_7194; +import static net.runelite.api.ObjectID.HAYSTACK; +import static net.runelite.api.ObjectID.JUNA; +import static net.runelite.api.ObjectID.MINE_CART_6045; +import static net.runelite.api.ObjectID.STONES_26633; +import static net.runelite.api.ObjectID.WARDROBE_5622; +import static net.runelite.api.ObjectID.WHEELBARROW_9625; import net.runelite.api.TileObject; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; @@ -116,7 +165,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("Probably filled with wizards socks.", "Wizard", DRAWERS_350, new WorldPoint(3116, 9562, 0), "Search the drawers in the basement of the Wizard's Tower south of Draynor Village. Kill one of the Wizards for the key. Fairy ring DIS"), new CrypticClue("Even the seers say this clue goes right over their heads.", CRATE_26635, new WorldPoint(2707, 3488, 2), "Search the crate on the Seers Agility Course in Seers Village"), new CrypticClue("Speak to a Wyse man.", "Wyson the gardener", new WorldPoint(3026, 3378, 0), "Talk to Wyson the gardener at Falador Park."), - new CrypticClue("You'll need to look for a town with a central fountain. Look for a locked chest in the town's chapel.", "Monk" , CLOSED_CHEST_5108, new WorldPoint(3256, 3487, 0), "Search the chest by the stairs in the Varrock church. Kill a Monk in Ardougne Monastery to obtain the key."), + new CrypticClue("You'll need to look for a town with a central fountain. Look for a locked chest in the town's chapel.", "Monk", CLOSED_CHEST_5108, new WorldPoint(3256, 3487, 0), "Search the chest by the stairs in the Varrock church. Kill a Monk in Ardougne Monastery to obtain the key."), new CrypticClue("Talk to Ambassador Spanfipple in the White Knights Castle.", "Ambassador Spanfipple", new WorldPoint(2979, 3340, 0), "Ambassador Spanfipple can be found roaming on the first floor of the White Knights Castle."), new CrypticClue("Mine was the strangest birth under the sun. I left the crimson sack, yet life had not begun. Entered the world, and yet was seen by none.", new WorldPoint(2832, 9586, 0), "Inside Karamja Volcano, dig directly underneath the Red spiders' eggs respawn."), new CrypticClue("Search for a crate in Varrock Castle.", CRATE_5113, new WorldPoint(3224, 3492, 0), "Search the crate in the corner of the kitchen in Varrock Castle."), @@ -196,13 +245,13 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("Search a bookcase in Lumbridge swamp.", BOOKCASE_9523, new WorldPoint(3146, 3177, 0), "Located in Father Urhney's house."), new CrypticClue("Surround my bones in fire, ontop the wooden pyre. Finally lay me to rest, before my one last test.", null, "Kill a confused/lost barbarian to receive mangled bones. Construct and burn a pyre ship. Kill the ferocious barbarian spirit that spawns to receive a clue casket."), new CrypticClue("Fiendish cooks probably won't dig the dirty dishes.", new WorldPoint(3043, 4974, 1), "Dig by the fire in the Rogues' Den."), - new CrypticClue("My life was spared but these voices remain, now guarding these iron gates is my bane.", "Key Master", new WorldPoint(1310, 1251, 0), "Speak to the Key Master in Cerberus' Lair."), + new CrypticClue("My life was spared but these voices remain, now guarding these iron gates is my bane.", "Key Master", new WorldPoint(1310, 1251, 0), "Speak to the Key Master in Cerberus' Lair."), new CrypticClue("Search the boxes in one of the tents in Al Kharid.", BOXES_361, new WorldPoint(3308, 3206, 0), "Search the boxes in the tent east of the Silk trader."), - new CrypticClue("One of several rhyming brothers, in business attire with an obsession for paper work.", "Piles", new WorldPoint(3186, 3936, 0), "Speak to Piles in the Wilderness Resource Area. An entry fee of 7,500 coins is required, or less if Wilderness Diaries have been completed."), + new CrypticClue("One of several rhyming brothers, in business attire with an obsession for paper work.", "Piles", new WorldPoint(3186, 3936, 0), "Speak to Piles in the Wilderness Resource Area. An entry fee of 7,500 coins is required, or less if Wilderness Diaries have been completed."), new CrypticClue("Search the drawers on the first floor of a building overlooking Ardougne's Market.", DRAWERS_352, new WorldPoint(2657, 3322, 1), "Climb the ladder in the house north of the market."), new CrypticClue("'A bag belt only?', he asked his balding brothers.", "Abbot Langley", new WorldPoint(3058, 3487, 0), "Talk-to Abbot Langley in Monastery west of Edgeville"), new CrypticClue("Search the drawers upstairs in Falador's shield shop.", DRAWERS, new WorldPoint(2971, 3386, 1), "Cassie's Shield Shop at the northern Falador entrance."), - new CrypticClue("Go to this building to be illuminated, and check the drawers while you are there.", "Market Guard", DRAWERS_350 , new WorldPoint(2512, 3641, 1), "Search the drawers in the first floor of the Lighthouse. Kill a Rellekka marketplace guard to obtain the key."), + new CrypticClue("Go to this building to be illuminated, and check the drawers while you are there.", "Market Guard", DRAWERS_350, new WorldPoint(2512, 3641, 1), "Search the drawers in the first floor of the Lighthouse. Kill a Rellekka marketplace guard to obtain the key."), new CrypticClue("Dig near some giant mushrooms, behind the Grand Tree.", new WorldPoint(2458, 3504, 0), "Dig near the red mushrooms northwest of the Grand Tree."), new CrypticClue("Pentagrams and demons, burnt bones and remains, I wonder what the blood contains.", new WorldPoint(3297, 3890, 0), "Dig under the blood rune spawn next the the Demonic Ruins."), new CrypticClue("Search the drawers above Varrock's shops.", DRAWERS_7194, new WorldPoint(3206, 3419, 1), "Located upstairs in Thessalia's Fine Clothes shop in Varrock."), @@ -276,7 +325,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("Ghommal wishes to be impressed by how strong your equipment is.", "Ghommal", new WorldPoint(2878, 3546, 0), "Speak to Ghommal at the Warriors' Guild with a total Melee Strength bonus of over 100."), new CrypticClue("Shhhh!", "Logosia", new WorldPoint(1633, 3808, 0), "Speak to Logosia in the Arceuus Library's ground floor."), new CrypticClue("Salty peter.", "Konoo", new WorldPoint(1703, 3524, 0), "Talk to Konoo who is digging saltpetre in Hosidius, south of the bank."), - new CrypticClue("Talk to Zeke in Al Kharid.", "Zeke", new WorldPoint(3287, 3190, 0), "Zeke is the owner of the scimitar shop in Al Kharid."), + new CrypticClue("Talk to Zeke in Al Kharid.", "Zeke", new WorldPoint(3287, 3190, 0), "Zeke is the owner of the scimitar shop in Al Kharid."), new CrypticClue("Guthix left his mark in a fiery lake, dig at the tip of it.", new WorldPoint(3069, 3935, 0), "Dig at the tip of the lava lake that is shaped like a Guthixian symbol, west of the Mage Arena."), new CrypticClue("Search the drawers in the upstairs of a house in Catherby.", DRAWERS_350, new WorldPoint(2809, 3451, 1), "Perdu's house in Catherby."), new CrypticClue("Search a crate in the Haymaker's arms.", CRATE_27532, new WorldPoint(1720, 3652, 1), "Search the crate in the north-east corner of The Haymaker's Arms tavern east of Kourend Castle."), @@ -294,9 +343,9 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("Dig in the centre of a great kingdom of 5 cities.", new WorldPoint(1639, 3673, 0), "Dig in front of the large statue in the centre of Great Kourend."), new CrypticClue("Hopefully this set of armour will help you to keep surviving.", "Sir Vyvin", new WorldPoint(2982, 3336, 2), "Speak to Sir Vyvin while wearing a white platebody, and platelegs."), new CrypticClue("The beasts retreat, for their Queen is gone; the song of this town still plays on. Dig near the birthplace of a blade, be careful not to melt your spade.", new WorldPoint(2342, 3677, 0), "Dig in front of the small furnace in the Piscatoris Fishing Colony."), - new CrypticClue("Darkness wanders around me, but fills my mind with knowledge.", "Biblia", new WorldPoint(1633, 3825, 2), "Speak to Biblia on the Arceuus Library's top floor."), + new CrypticClue("Darkness wanders around me, but fills my mind with knowledge.", "Biblia", new WorldPoint(1633, 3825, 2), "Speak to Biblia on the Arceuus Library's top floor."), new CrypticClue("I would make a chemistry joke, but I'm afraid I wouldn't get a reaction.", "Chemist", new WorldPoint(2932, 3212, 0), "Talk to the Chemist in Rimmington"), - new CrypticClue("Show this to Hazelmere.", "Hazelmere", new WorldPoint(2677, 3088, 1), "Hazelmere is found upstairs on the island located just east of Yanille."), + new CrypticClue("Show this to Hazelmere.", "Hazelmere", new WorldPoint(2677, 3088, 1), "Hazelmere is found upstairs on the island located just east of Yanille."), new CrypticClue("Does one really need a fire to stay warm here?", new WorldPoint(3816, 3810, 0), "Dig next to the fire near the Volcanic Mine entrance."), new CrypticClue("Search the open crate found in a small farmhouse in Hosidius. Cabbages grow outside.", CRATE_27533, new WorldPoint(1687, 3628, 0), "The house is north-east of the general store in Hosidius."), new CrypticClue("Dig under Ithoi's cabin.", new WorldPoint(2529, 2838, 0), "Dig under Ithoi's cabin in the Corsair Cove."), @@ -428,7 +477,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc for (TileObject gameObject : plugin.getObjectsToMark()) { OverlayUtil.renderHoverableArea(graphics, gameObject.getClickbox(), mousePosition, - CLICKBOX_FILL_COLOR, CLICKBOX_BORDER_COLOR, CLICKBOX_HOVER_BORDER_COLOR); + CLICKBOX_FILL_COLOR, CLICKBOX_BORDER_COLOR, CLICKBOX_HOVER_BORDER_COLOR); OverlayUtil.renderImageLocation(plugin.getClient(), graphics, gameObject.getLocalLocation(), plugin.getClueScrollImage(), IMAGE_Z_OFFSET); } @@ -452,12 +501,12 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc @Override public int[] getObjectIds() { - return new int[] {objectId}; + return new int[]{objectId}; } @Override public String[] getNpcs() { - return new String[] {npc}; + return new String[]{npc}; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index eb4e89cef0..15352c56b2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -1,312 +1,827 @@ -/* - * Copyright (c) 2018, Lotto - * 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.cluescrolls.clues; - -import com.google.common.collect.ImmutableSet; -import java.awt.Color; -import java.awt.Graphics2D; -import java.util.Set; -import javax.annotation.Nonnull; -import lombok.Getter; -import net.runelite.api.EquipmentInventorySlot; -import static net.runelite.api.EquipmentInventorySlot.*; -import static net.runelite.api.EquipmentInventorySlot.LEGS; -import net.runelite.api.Item; -import net.runelite.api.ItemID; -import static net.runelite.api.ItemID.*; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; -import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; -import net.runelite.client.plugins.cluescrolls.clues.emote.AllRequirementsCollection; -import net.runelite.client.plugins.cluescrolls.clues.emote.AnyRequirementCollection; -import net.runelite.client.plugins.cluescrolls.clues.emote.Emote; -import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.*; -import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER; -import net.runelite.client.plugins.cluescrolls.clues.emote.ItemRequirement; -import net.runelite.client.plugins.cluescrolls.clues.emote.RangeItemRequirement; -import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.*; -import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS; -import net.runelite.client.plugins.cluescrolls.clues.emote.SingleItemRequirement; -import net.runelite.client.plugins.cluescrolls.clues.emote.SlotLimitationRequirement; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -@Getter -public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClueScroll -{ - private static final Set CLUES = ImmutableSet.of( - new EmoteClue("Beckon on the east coast of the Kharazi Jungle. Beware of double agents! Equip any vestment stole and a heraldic rune shield.", NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE, new WorldPoint(2954, 2933, 0), BECKON, any("Any stole", item(GUTHIX_STOLE), item(SARADOMIN_STOLE), item(ZAMORAK_STOLE), item(ARMADYL_STOLE), item(BANDOS_STOLE), item(ANCIENT_STOLE)), any("Any heraldic rune shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))), - new EmoteClue("Cheer in the Barbarian Agility Arena. Headbang before you talk to me. Equip a steel platebody, maple shortbow and a Wilderness cape.", BARBARIAN_OUTPOST_OBSTACLE_COURSE, new WorldPoint(2552, 3556, 0), CHEER, HEADBANG, item(STEEL_PLATEBODY), item(MAPLE_SHORTBOW), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)), - new EmoteClue("Bow upstairs in the Edgeville Monastery. Equip a completed prayer book.", SOUTHEAST_CORNER_OF_THE_MONASTERY, new WorldPoint(3056, 3484, 1), BOW, any("Any god book", item(HOLY_BOOK), item(BOOK_OF_BALANCE), item(UNHOLY_BOOK), item(BOOK_OF_LAW), item(BOOK_OF_WAR), item(BOOK_OF_DARKNESS))), - new EmoteClue("Cheer in the Shadow dungeon. Equip a rune crossbow, climbing boots and any mitre.", ENTRANCE_OF_THE_CAVE_OF_DAMIS, new WorldPoint(2629, 5071, 0), CHEER, any("Any mitre", item(GUTHIX_MITRE), item(SARADOMIN_MITRE), item(ZAMORAK_MITRE), item(ANCIENT_MITRE), item(BANDOS_MITRE), item(ARMADYL_MITRE)), item(RUNE_CROSSBOW), item(CLIMBING_BOOTS), item(RING_OF_VISIBILITY)), - new EmoteClue("Cheer at the top of the agility pyramid. Beware of double agents! Equip a blue mystic robe top, and any rune heraldic shield.", AGILITY_PYRAMID, new WorldPoint(3043, 4697, 3), CHEER, item(MYSTIC_ROBE_TOP), any("Any rune heraldic shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))), - new EmoteClue("Dance in Iban's temple. Beware of double agents! Equip Iban's staff, a black mystic top and a black mystic bottom.", WELL_OF_VOYAGE, new WorldPoint(2011, 4712, 0), DANCE, any("Any iban's staff", item(IBANS_STAFF), item(IBANS_STAFF_U)), item(MYSTIC_ROBE_TOP_DARK), item(MYSTIC_ROBE_BOTTOM_DARK)), - new EmoteClue("Dance on the Fishing Platform. Equip barrows gloves, an amulet of glory and a dragon med helm.", SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM, new WorldPoint(2782, 3273, 0), DANCE, any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6)), item(BARROWS_GLOVES), item(DRAGON_MED_HELM)), - new EmoteClue("Flap at the death altar. Beware of double agents! Equip a death tiara, a legend's cape and any ring of wealth.", DEATH_ALTAR, new WorldPoint(2205, 4838, 0), FLAP, any("Any ring of wealth", item(RING_OF_WEALTH), item(RING_OF_WEALTH_1), item(RING_OF_WEALTH_2), item(RING_OF_WEALTH_3), item(RING_OF_WEALTH_4), item(RING_OF_WEALTH_5), item(RING_OF_WEALTH_I), item(RING_OF_WEALTH_I1), item(RING_OF_WEALTH_I2), item(RING_OF_WEALTH_I3), item(RING_OF_WEALTH_I4), item(RING_OF_WEALTH_I5)), item(DEATH_TIARA), item(CAPE_OF_LEGENDS)), - new EmoteClue("Headbang in the Fight Arena pub. Equip a pirate bandana, a dragonstone necklace and and a magic longbow.", OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA, new WorldPoint(2568, 3149, 0), HEADBANG, any("Any pirate bandana", item(PIRATE_BANDANA), item(PIRATE_BANDANA_7124), item(PIRATE_BANDANA_7130), item(PIRATE_BANDANA_7136)), item(DRAGON_NECKLACE), item(MAGIC_LONGBOW)), - new EmoteClue("Do a jig at the barrow's chest. Beware of double agents! Equip any full barrows set.", BARROWS_CHEST, new WorldPoint(3551, 9694, 0), JIG, any("Any full barrows set", all(range(AHRIMS_HOOD_100, AHRIMS_HOOD_0), range(AHRIMS_STAFF_100, AHRIMS_STAFF_0), range(AHRIMS_ROBETOP_100, AHRIMS_ROBETOP_0), range(AHRIMS_ROBESKIRT_100, AHRIMS_ROBESKIRT_0)), all(range(DHAROKS_HELM_100, DHAROKS_HELM_0), range(DHAROKS_GREATAXE_100, DHAROKS_GREATAXE_0), range(DHAROKS_PLATEBODY_100, DHAROKS_PLATEBODY_0), range(DHAROKS_PLATELEGS_100, DHAROKS_PLATELEGS_0)), all(range(GUTHANS_HELM_100, GUTHANS_HELM_0), range(GUTHANS_WARSPEAR_100, GUTHANS_WARSPEAR_0), range(GUTHANS_PLATEBODY_100, GUTHANS_PLATEBODY_0), range(GUTHANS_CHAINSKIRT_100, GUTHANS_CHAINSKIRT_0)), all(range(KARILS_COIF_100, KARILS_COIF_0), range(KARILS_CROSSBOW_100, KARILS_CROSSBOW_0), range(KARILS_LEATHERTOP_100, KARILS_LEATHERTOP_0), range(KARILS_LEATHERSKIRT_100, KARILS_LEATHERSKIRT_0)), all(range(TORAGS_HELM_100, TORAGS_HELM_0), range(TORAGS_HAMMERS_100, TORAGS_HAMMERS_0), range(TORAGS_PLATEBODY_100, TORAGS_PLATEBODY_0), range(TORAGS_PLATELEGS_100, TORAGS_PLATELEGS_0)), all(range(VERACS_HELM_100, VERACS_HELM_0), range(VERACS_FLAIL_100, VERACS_FLAIL_0), range(VERACS_BRASSARD_100, VERACS_BRASSARD_0), range(VERACS_PLATESKIRT_100, VERACS_PLATESKIRT_0)))), - new EmoteClue("Jig at Jiggig. Beware of double agents! Equip a Rune spear, rune platelegs and any rune heraldic helm.", IN_THE_MIDDLE_OF_JIGGIG, new WorldPoint(2477, 3047, 0), JIG, range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5), item(RUNE_SPEAR), item(RUNE_PLATELEGS)), - new EmoteClue("Cheer at the games room. Have nothing equipped at all when you do.", null, new WorldPoint(2207, 4952, 0), CHEER, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), - new EmoteClue("Panic on the pier where you catch the Fishing trawler. Have nothing equipped at all when you do.", null, new WorldPoint(2676, 3169, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), - new EmoteClue("Panic in the heart of the Haunted Woods. Beware of double agents! Have no items equipped when you do.", null, new WorldPoint(3611, 3492, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), - new EmoteClue("Show your anger towards the Statue of Saradomin in Ellamaria's garden. Beware of double agents! Equip a zamorak godsword.", BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS, new WorldPoint(3230, 3478, 0), ANGRY, item(ZAMORAK_GODSWORD)), - new EmoteClue("Show your anger at the Wise old man. Beware of double agents! Equip an abyssal whip, a legend's cape and some spined chaps.", BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE, new WorldPoint(3088, 3254, 0), ANGRY, any("Abyssal whip", item(ABYSSAL_WHIP), item(VOLCANIC_ABYSSAL_WHIP), item(FROZEN_ABYSSAL_WHIP)), item(CAPE_OF_LEGENDS), item(SPINED_CHAPS)), - new EmoteClue("Beckon in the Digsite, near the eastern winch. Bow before you talk to me. Equip a green gnome hat, snakeskin boots and an iron pickaxe.", DIGSITE, new WorldPoint(3370, 3425, 0), BECKON, BOW, item(GREEN_HAT), item(SNAKESKIN_BOOTS), item(IRON_PICKAXE)), - new EmoteClue("Beckon in Tai Bwo Wannai. Clap before you talk to me. Equip green dragonhide chaps, a ring of dueling and a mithril medium helmet.", SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE, new WorldPoint(2803, 3073, 0), BECKON, CLAP, item(GREEN_DHIDE_CHAPS), any("Ring of dueling", item(RING_OF_DUELING1), item(RING_OF_DUELING2), item(RING_OF_DUELING3), item(RING_OF_DUELING4), item(RING_OF_DUELING5), item(RING_OF_DUELING6), item(RING_OF_DUELING7), item(RING_OF_DUELING8)), item(MITHRIL_MED_HELM)), - new EmoteClue("Beckon in the combat ring of Shayzien. Show your anger before you talk to me. Equip an adamant platebody, adamant full helm and adamant platelegs.", WEST_OF_THE_SHAYZIEN_COMBAT_RING, new WorldPoint(1545, 3594, 0), BECKON, ANGRY, item(ADAMANT_PLATELEGS), item(ADAMANT_PLATEBODY), item(ADAMANT_FULL_HELM)), - new EmoteClue("Bow near Lord Iorwerth. Beware of double agents! Equip a new imbued crystal bow.", TENT_IN_LORD_IORWERTHS_ENCAMPMENT, new WorldPoint(2205, 3252, 0), BOW, any("Imbued crystal bow", item(NEW_CRYSTAL_BOW_I), item(CRYSTAL_BOW_FULL_I), item(CRYSTAL_BOW_910_I), item(CRYSTAL_BOW_810_I), item(CRYSTAL_BOW_710_I), item(CRYSTAL_BOW_610_I), item(CRYSTAL_BOW_510_I), item(CRYSTAL_BOW_410_I), item(CRYSTAL_BOW_310_I), item(CRYSTAL_BOW_210_I), item(CRYSTAL_BOW_110_I))), - new EmoteClue("Bow outside the entrance to the Legends' Guild. Equip iron platelegs, an emerald amulet and an oak longbow.", OUTSIDE_THE_LEGENDS_GUILD_GATES, new WorldPoint(2729, 3349, 0), BOW, item(IRON_PLATELEGS), item(OAK_LONGBOW), item(EMERALD_AMULET)), - new EmoteClue("Bow on the ground floor of the Legend's guild. Equip Legend's cape, a dragon battleaxe and an amulet of glory.", OUTSIDE_THE_LEGENDS_GUILD_DOOR, new WorldPoint(2728, 3377, 0), BOW, item(CAPE_OF_LEGENDS), item(DRAGON_BATTLEAXE), any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6))), - new EmoteClue("Bow in the ticket office of the Duel Arena. Equip an iron chain body, leather chaps and coif.", MUBARIZS_ROOM_AT_THE_DUEL_ARENA, new WorldPoint(3314, 3241, 0), BOW, item(IRON_CHAINBODY), item(LEATHER_CHAPS), item(COIF)), - new EmoteClue("Bow at the top of the lighthouse. Beware of double agents! Equip a blue dragonhide body, blue dragonhide vambraces and no jewelry.", TOP_FLOOR_OF_THE_LIGHTHOUSE, new WorldPoint(2511, 3641, 2), BOW, item(BLUE_DHIDE_BODY), item(BLUE_DHIDE_VAMB), emptySlot("No jewelry", AMULET, RING)), - new EmoteClue("Blow a kiss between the tables in Shilo Village bank. Beware of double agents! Equip a blue mystic hat, bone spear and rune platebody.", SHILO_VILLAGE_BANK, new WorldPoint(2851, 2954, 0), BLOW_KISS, item(MYSTIC_HAT), item(BONE_SPEAR), item(RUNE_PLATEBODY)), - new EmoteClue("Blow a kiss in the heart of the lava maze. Equip black dragonhide chaps, a spotted cape and a rolling pin.", NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE, new WorldPoint(3069, 3861, 0), BLOW_KISS, item(BLACK_DHIDE_CHAPS), any("Spotted cape", item(SPOTTED_CAPE), item(SPOTTED_CAPE_10073)), item(ROLLING_PIN)), - new EmoteClue("Blow a kiss outside K'ril Tsutsaroth's chamber. Beware of double agents! Equip a zamorak full helm and the shadow sword.", OUTSIDE_KRIL_TSUTSAROTHS_ROOM, new WorldPoint(2925, 5333, 0), BLOW_KISS, item(ZAMORAK_FULL_HELM), item(SHADOW_SWORD)), - new EmoteClue("Cheer at the Druids' Circle. Equip a blue wizard hat, a bronze two-handed sword and HAM boots.", TAVERLEY_STONE_CIRCLE, new WorldPoint(2924, 3478, 0), CHEER, item(BLUE_WIZARD_HAT), item(BRONZE_2H_SWORD), item(HAM_BOOTS)), - new EmoteClue("Cheer in the Edgeville general store. Dance before you talk to me. Equip a brown apron, leather boots and leather gloves.", NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE, new WorldPoint(3080, 3509, 0), CHEER, DANCE, item(BROWN_APRON), item(LEATHER_BOOTS), item(LEATHER_GLOVES)), - new EmoteClue("Cheer in the Ogre Pen in the Training Camp. Show you are angry before you talk to me. Equip a green dragonhide body and chaps and a steel square shield.", OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP, new WorldPoint(2527, 3375, 0), CHEER, ANGRY, item(GREEN_DHIDE_BODY), item(GREEN_DHIDE_CHAPS), item(STEEL_SQ_SHIELD)), - new EmoteClue("Cheer in the Entrana church. Beware of double agents! Equip a full set of black dragonhide armour.", ENTRANA_CHAPEL, new WorldPoint(2852, 3349, 0), CHEER, item(BLACK_DHIDE_VAMB), item(BLACK_DHIDE_CHAPS), item(BLACK_DHIDE_BODY)), - new EmoteClue("Cheer for the monks at Port Sarim. Equip a coif, steel plateskirt and a sapphire necklace.", NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM, new WorldPoint(3047, 3237, 0), CHEER, item(COIF), item(STEEL_PLATESKIRT), item(SAPPHIRE_NECKLACE)), - new EmoteClue("Clap in the main exam room in the Exam Centre. Equip a white apron, green gnome boots and leather gloves.", INSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3361, 3339, 0), CLAP, item(WHITE_APRON), item(GREEN_BOOTS), item(LEATHER_GLOVES)), - new EmoteClue("Clap on the causeway to the Wizards' Tower. Equip an iron medium helmet, emerald ring and a white apron.", ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER, new WorldPoint(3113, 3196, 0), CLAP, item(IRON_MED_HELM), item(EMERALD_RING), item(WHITE_APRON)), - new EmoteClue("Clap on the top level of the mill, north of East Ardougne. Equip a blue gnome robe top, HAM robe bottom and an unenchanted tiara.", UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL, new WorldPoint(2635, 3385, 3), CLAP, item(BLUE_ROBE_TOP), item(HAM_ROBE), item(TIARA)), - new EmoteClue("Clap in Seers court house. Spin before you talk to me. Equip an adamant halberd, blue mystic robe bottom and a diamond ring.", OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE, new WorldPoint(2735, 3469, 0), CLAP, SPIN, item(ADAMANT_HALBERD), item(MYSTIC_ROBE_BOTTOM), item(DIAMOND_RING)), - new EmoteClue("Clap in the magic axe hut. Beware of double agents! Equip only some flared trousers.", OUTSIDE_THE_WILDERNESS_AXE_HUT, new WorldPoint(3191, 3960, 0), CLAP, item(FLARED_TROUSERS), item(LOCKPICK), emptySlot("Nothing else", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, GLOVES, BOOTS, RING, AMMO)), - new EmoteClue("Clap your hands north of Mount Karuulm Spin before you talk to me. Equip an adamant warhammer, a ring of life and a pair of mithril boots.", NORTH_OF_MOUNT_KARUULM, new WorldPoint(1306, 3839, 0), CLAP, SPIN, item(ADAMANT_WARHAMMER), item(RING_OF_LIFE), item(MITHRIL_BOOTS)), - new EmoteClue("Cry in the Catherby Ranging shop. Bow before you talk to me. Equip blue gnome boots, a hard leather body and an unblessed silver sickle.", HICKTONS_ARCHERY_EMPORIUM, new WorldPoint(2823, 3443, 0), CRY, BOW, item(BLUE_BOOTS), item(HARDLEATHER_BODY), item(SILVER_SICKLE)), - new EmoteClue("Cry on the shore of Catherby beach. Laugh before you talk to me, equip an adamant sq shield, a bone dagger and mithril platebody.", OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY, new WorldPoint(2852, 3429, 0), CRY, LAUGH, item(ADAMANT_SQ_SHIELD), item(BONE_DAGGER), item(MITHRIL_PLATEBODY)), - new EmoteClue("Cry on top of the western tree in the Gnome Agility Arena. Indicate 'no' before you talk to me. Equip a steel kiteshield, ring of forging and green dragonhide chaps.", GNOME_STRONGHOLD_BALANCING_ROPE, new WorldPoint(2473, 3420, 2), CRY, NO, item(STEEL_KITESHIELD), item(RING_OF_FORGING), item(GREEN_DHIDE_CHAPS)), - new EmoteClue("Cry in the TzHaar gem store. Beware of double agents! Equip a fire cape and TokTz-Xil-Ul.", TZHAAR_GEM_STORE, new WorldPoint(2463, 5149, 0), CRY, any("Fire cape", item(FIRE_CAPE), item(FIRE_MAX_CAPE)), item(TOKTZXILUL)), - new EmoteClue("Cry in the Draynor Village jail. Jump for joy before you talk to me. Equip an adamant sword, a sapphire amulet and an adamant plateskirt.", OUTSIDE_DRAYNOR_VILLAGE_JAIL, new WorldPoint(3128, 3245, 0), CRY, JUMP_FOR_JOY, item(ADAMANT_SWORD), item(SAPPHIRE_AMULET), item(ADAMANT_PLATESKIRT)), - new EmoteClue("Dance at the crossroads north of Draynor. Equip an iron chain body, a sapphire ring and a longbow.", CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE, new WorldPoint(3109, 3294, 0), DANCE, item(IRON_CHAINBODY), item(SAPPHIRE_RING), item(LONGBOW)), - new EmoteClue("Dance in the Party Room. Equip a steel full helmet, steel platebody and an iron plateskirt.", OUTSIDE_THE_FALADOR_PARTY_ROOM, new WorldPoint(3045, 3376, 0), DANCE, item(STEEL_FULL_HELM), item(STEEL_PLATEBODY), item(IRON_PLATESKIRT)), - new EmoteClue("Dance in the shack in Lumbridge Swamp. Equip a bronze dagger, iron full helmet and a gold ring.", NEAR_A_SHED_IN_LUMBRIDGE_SWAMP, new WorldPoint(3203, 3169, 0), DANCE, item(BRONZE_DAGGER), item(IRON_FULL_HELM), item(GOLD_RING)), - new EmoteClue("Dance in the dark caves beneath Lumbridge Swamp. Blow a kiss before you talk to me. Equip an air staff, Bronze full helm and an amulet of power.", LUMBRIDGE_SWAMP_CAVES, new WorldPoint(3168, 9571, 0), DANCE, BLOW_KISS, item(STAFF_OF_AIR), item(BRONZE_FULL_HELM), item(AMULET_OF_POWER)), - new EmoteClue("Dance at the cat-doored pyramid in Sophanem. Beware of double agents! Equip a ring of life, an uncharged amulet of glory and an adamant two-handed sword.", OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM, new WorldPoint(3294, 2781, 0), DANCE, item(RING_OF_LIFE), item(AMULET_OF_GLORY), item(ADAMANT_2H_SWORD)), - new EmoteClue("Dance in the centre of Canifis. Bow before you talk to me. Equip a green gnome robe top, mithril plate legs and an iron two-handed sword.", CENTRE_OF_CANIFIS, new WorldPoint(3492, 3488, 0), DANCE, BOW, item(GREEN_ROBE_TOP), item(MITHRIL_PLATELEGS), item(IRON_2H_SWORD)), - new EmoteClue("Dance in the King Black Dragon's lair. Beware of double agents! Equip a black dragonhide body, black dragonhide vambs and a black dragon mask.", KING_BLACK_DRAGONS_LAIR, new WorldPoint(2271, 4680, 0), DANCE, item(BLACK_DHIDE_BODY), item(BLACK_DHIDE_VAMB), item(BLACK_DRAGON_MASK)), - new EmoteClue("Dance at the entrance to the Grand Exchange. Equip a pink skirt, pink robe top and a body tiara.", SOUTH_OF_THE_GRAND_EXCHANGE, new WorldPoint(3165, 3467, 0), DANCE, item(PINK_SKIRT), item(PINK_ROBE_TOP), item(BODY_TIARA)), - new EmoteClue("Goblin Salute in the Goblin Village. Beware of double agents! Equip a bandos godsword, a bandos cloak and a bandos platebody.", OUTSIDE_MUDKNUCKLES_HUT, new WorldPoint(2956, 3505, 0), GOBLIN_SALUTE, item(BANDOS_PLATEBODY), item(BANDOS_CLOAK), item(BANDOS_GODSWORD)), - new EmoteClue("Headbang in the mine north of Al Kharid. Equip a desert shirt, leather gloves and leather boots.", AL_KHARID_SCORPION_MINE, new WorldPoint(3299, 3289, 0), HEADBANG, item(DESERT_SHIRT), item(LEATHER_GLOVES), item(LEATHER_BOOTS)), - new EmoteClue("Headbang at the exam center. Beware of double agents! Equip a mystic fire staff, a diamond bracelet and rune boots.", OUTSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3362, 3340, 0), HEADBANG, item(MYSTIC_FIRE_STAFF), item(DIAMOND_BRACELET), item(RUNE_BOOTS)), - new EmoteClue("Headbang at the top of Slayer Tower. Equip a seercull, a combat bracelet and helm of Neitiznot.", OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM, new WorldPoint(3421, 3537, 2), HEADBANG, item(SEERCULL), range("Combat bracelet", COMBAT_BRACELET4, COMBAT_BRACELET), item(HELM_OF_NEITIZNOT)), - new EmoteClue("Dance a jig by the entrance to the Fishing Guild. Equip an emerald ring, a sapphire amulet, and a bronze chain body.", OUTSIDE_THE_FISHING_GUILD, new WorldPoint(2610, 3391, 0), JIG, item(EMERALD_RING), item(SAPPHIRE_AMULET), item(BRONZE_CHAINBODY)), - new EmoteClue("Dance a jig under Shantay's Awning. Bow before you talk to me. Equip a pointed blue snail helmet, an air staff and a bronze square shield.", SHANTAY_PASS, new WorldPoint(3304, 3124, 0), JIG, BOW, any("Bruise blue snelm (pointed)", item(BRUISE_BLUE_SNELM_3343)), item(STAFF_OF_AIR), item(BRONZE_SQ_SHIELD)), - new EmoteClue("Do a jig in Varrock's rune store. Equip an air tiara and a staff of water.", AUBURYS_SHOP_IN_VARROCK, new WorldPoint(3253, 3401, 0), JIG, item(AIR_TIARA), item(STAFF_OF_WATER)), - new EmoteClue("Jump for joy at the beehives. Equip a desert shirt, green gnome robe bottoms and a steel axe.", CATHERBY_BEEHIVE_FIELD, new WorldPoint(2759, 3445, 0), JUMP_FOR_JOY, item(DESERT_SHIRT), item(GREEN_ROBE_BOTTOMS), item(STEEL_AXE)), - new EmoteClue("Jump for joy in Yanille bank. Dance a jig before you talk to me. Equip a brown apron, adamantite medium helmet and snakeskin chaps.", OUTSIDE_YANILLE_BANK, new WorldPoint(2610, 3092, 0), JUMP_FOR_JOY, JIG, item(BROWN_APRON), item(ADAMANT_MED_HELM), item(SNAKESKIN_CHAPS)), - new EmoteClue("Jump for joy in the TzHaar sword shop. Shrug before you talk to me. Equip a Steel longsword, Blue D'hide body and blue mystic gloves.", TZHAAR_WEAPONS_STORE, new WorldPoint(2477, 5146, 0), JUMP_FOR_JOY, SHRUG, item(STEEL_LONGSWORD), item(BLUE_DHIDE_BODY), item(MYSTIC_GLOVES)), - new EmoteClue("Jump for joy in the Ancient Cavern. Equip a granite shield, splitbark body and any rune heraldic helm.", ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL, new WorldPoint(1768, 5366, 1), JUMP_FOR_JOY, item(GRANITE_SHIELD), item(SPLITBARK_BODY), range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5)), - new EmoteClue("Jump for joy at the Neitiznot rune rock. Equip Rune boots, a proselyte hauberk and a dragonstone ring.", NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES, new WorldPoint(2375, 3850, 0), JUMP_FOR_JOY, item(RUNE_BOOTS), item(PROSELYTE_HAUBERK), item(DRAGONSTONE_RING)), - new EmoteClue("Jump for joy in the centre of Zul-Andra. Beware of double agents! Equip a dragon 2h sword, bandos boots and an obsidian cape.", NEAR_THE_PIER_IN_ZULANDRA, new WorldPoint(2199, 3056, 0), JUMP_FOR_JOY, item(DRAGON_2H_SWORD), item(BANDOS_BOOTS), item(OBSIDIAN_CAPE)), - new EmoteClue("Laugh by the fountain of heroes. Equip splitbark legs, dragon boots and a Rune longsword.", FOUNTAIN_OF_HEROES, new WorldPoint(2920, 9893, 0), LAUGH, item(SPLITBARK_LEGS), item(DRAGON_BOOTS), item(RUNE_LONGSWORD)), - new EmoteClue("Laugh in Jokul's tent in the Mountain Camp. Beware of double agents! Equip a rune full helmet, blue dragonhide chaps and a fire battlestaff.", MOUNTAIN_CAMP_GOAT_ENCLOSURE, new WorldPoint(2812, 3681, 0), LAUGH, item(RUNE_FULL_HELM), item(BLUE_DHIDE_CHAPS), item(FIRE_BATTLESTAFF)), - new EmoteClue("Laugh at the crossroads south of the Sinclair Mansion. Equip a cowl, a blue wizard robe top and an iron scimitar.", ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION, new WorldPoint(2741, 3536, 0), LAUGH, item(LEATHER_COWL), item(BLUE_WIZARD_ROBE), item(IRON_SCIMITAR)), - new EmoteClue("Laugh in front of the gem store in Ardougne market. Equip a Castlewars bracelet, a dragonstone amulet and a ring of forging.", NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET, new WorldPoint(2666, 3304, 0), LAUGH, any("Castle wars bracelet", range(CASTLE_WARS_BRACELET3, CASTLE_WARS_BRACELET1)), item(DRAGONSTONE_AMULET), item(RING_OF_FORGING)), - new EmoteClue("Panic in the Limestone Mine. Equip bronze platelegs, a steel pickaxe and a steel medium helmet.", LIMESTONE_MINE, new WorldPoint(3372, 3498, 0), PANIC, item(BRONZE_PLATELEGS), item(STEEL_PICKAXE), item(STEEL_MED_HELM)), - new EmoteClue("Panic by the mausoleum in Morytania. Wave before you speak to me. Equip a mithril plate skirt, a maple longbow and no boots.", MAUSOLEUM_OFF_THE_MORYTANIA_COAST, new WorldPoint(3504, 3576, 0), PANIC, WAVE, item(MITHRIL_PLATESKIRT), item(MAPLE_LONGBOW), emptySlot("No boots", BOOTS)), - new EmoteClue("Panic on the Wilderness volcano bridge. Beware of double agents! Equip any headband and crozier.", VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS, new WorldPoint(3368, 3935, 0), PANIC, any("Any headband", range(RED_HEADBAND, BROWN_HEADBAND), range(WHITE_HEADBAND, GREEN_HEADBAND)), any("Any crozier", item(ANCIENT_CROZIER), item(ARMADYL_CROZIER), item(BANDOS_CROZIER), range(SARADOMIN_CROZIER, ZAMORAK_CROZIER))), - new EmoteClue("Panic by the pilot on White Wolf Mountain. Beware of double agents! Equip mithril platelegs, a ring of life and a rune axe.", GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN, new WorldPoint(2847, 3499, 0), PANIC, item(MITHRIL_PLATELEGS), item(RING_OF_LIFE), item(RUNE_AXE)), - new EmoteClue("Panic by the big egg where no one dare goes and the ground is burnt. Beware of double agents! Equip a dragon med helm, a TokTz-Ket-Xil, a brine sabre, rune platebody and an uncharged amulet of glory.", SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE, new WorldPoint(3227, 3831, 0), PANIC, item(DRAGON_MED_HELM), item(TOKTZKETXIL), item(BRINE_SABRE), item(RUNE_PLATEBODY), item(AMULET_OF_GLORY)), - new EmoteClue("Panic at the area flowers meet snow. Equip Blue D'hide vambs, a dragon spear and a rune plateskirt.", HALFWAY_DOWN_TROLLWEISS_MOUNTAIN, new WorldPoint(2776, 3781, 0), PANIC, item(BLUE_DHIDE_VAMB), item(DRAGON_SPEAR), item(RUNE_PLATESKIRT), item(SLED_4084)), - new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), - new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), - new EmoteClue("Blow a raspberry at the monkey cage in Ardougne Zoo. Equip a studded leather body, bronze platelegs and a normal staff with no orb.", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)), - new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)), - new EmoteClue("Blow a raspberry in the Fishing Guild bank. Beware of double agents! Equip an elemental shield, blue dragonhide chaps and a rune warhammer.", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)), - new EmoteClue("Salute in the banana plantation. Beware of double agents! Equip a diamond ring, amulet of power, and nothing on your chest and legs.", WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION, new WorldPoint(2914, 3168, 0), SALUTE, item(DIAMOND_RING), item(AMULET_OF_POWER), emptySlot("Nothing on chest & legs", BODY, LEGS)), - new EmoteClue("Salute in the Warriors' guild bank. Equip only a black salamander.", WARRIORS_GUILD_BANK, new WorldPoint(2844, 3542, 0), SALUTE, item(BLACK_SALAMANDER), emptySlot("Nothing else", HEAD, CAPE, AMULET, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), - new EmoteClue("Salute in the centre of the mess hall. Beware of double agents! Equip a rune halberd rune platebody, and an amulet of strength.", HOSIDIUS_MESS, new WorldPoint(1646, 3632, 0), SALUTE, item(RUNE_HALBERD), item(RUNE_PLATEBODY), item(AMULET_OF_STRENGTH)), - new EmoteClue("Shrug in the mine near Rimmington. Equip a gold necklace, a gold ring and a bronze spear.", RIMMINGTON_MINE, new WorldPoint(2976, 3238, 0), SHRUG, item(GOLD_NECKLACE), item(GOLD_RING), item(BRONZE_SPEAR)), - new EmoteClue("Shrug in Catherby bank. Yawn before you talk to me. Equip a maple longbow, green d'hide chaps and an iron med helm.", OUTSIDE_CATHERBY_BANK, new WorldPoint(2808, 3440, 0), SHRUG, YAWN, item(MAPLE_LONGBOW), item(GREEN_DHIDE_CHAPS), item(IRON_MED_HELM)), - new EmoteClue("Shrug in the Zamorak temple found in the Eastern Wilderness. Beware of double agents! Equip rune platelegs, an iron platebody and blue dragonhide vambraces.", CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS, new WorldPoint(3239, 3611, 0), SHRUG, item(RUNE_PLATELEGS), item(IRON_PLATEBODY), item(BLUE_DHIDE_VAMB)), - new EmoteClue("Shrug in the Shayzien command tent. Equip a blue mystic robe bottom, a rune kiteshield and any bob shirt.", SHAYZIEN_WAR_TENT, new WorldPoint(1555, 3537, 0), SHRUG, item(MYSTIC_ROBE_BOTTOM), item(RUNE_KITESHIELD), range("Any bob shirt", BOBS_RED_SHIRT, BOBS_PURPLE_SHIRT)), - new EmoteClue("Slap your head in the centre of the Kourend catacombs. Beware of double agents! Equip the arclight and the amulet of the damned.", CENTRE_OF_THE_CATACOMBS_OF_KOUREND, new WorldPoint(1663, 10045, 0), SLAP_HEAD, item(ARCLIGHT), any("Amulet of the damned", item(AMULET_OF_THE_DAMNED), item(AMULET_OF_THE_DAMNED_FULL))), - new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", ROAD_JUNCTION_NORTH_OF_RIMMINGTON, new WorldPoint(2981, 3276, 0), SPIN, item(GREEN_HAT), item(CREAM_ROBE_TOP), item(LEATHER_CHAPS)), - new EmoteClue("Spin in Draynor Manor by the fountain. Equip an iron platebody, studded leather chaps and a bronze full helmet.", DRAYNOR_MANOR_BY_THE_FOUNTAIN, new WorldPoint(3088, 3336, 0), SPIN, item(IRON_PLATEBODY), item(STUDDED_CHAPS), item(BRONZE_FULL_HELM)), - new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), - new EmoteClue("Spin in the Varrock Castle courtyard. Equip a black axe, a coif and a ruby ring.", OUTSIDE_VARROCK_PALACE_COURTYARD, new WorldPoint(3213, 3463, 0), SPIN, item(BLACK_AXE), item(COIF), item(RUBY_RING)), - new EmoteClue("Spin in West Ardougne Church. Equip a dragon spear and red dragonhide chaps.", CHAPEL_IN_WEST_ARDOUGNE, new WorldPoint(2530, 3290, 0), SPIN, item(DRAGON_SPEAR), item(RED_DHIDE_CHAPS)), - new EmoteClue("Spin on the bridge by the Barbarian Village. Salute before you talk to me. Equip purple gloves, a steel kiteshield and a mithril full helmet.", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)), - new EmoteClue("Stamp in the Enchanted valley west of the waterfall. Beware of double agents! Equip a dragon axe.", NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY, new WorldPoint(3030, 4522, 0), STOMP, item(DRAGON_AXE)), - new EmoteClue("Think in middle of the wheat field by the Lumbridge mill. Equip a blue gnome robetop, a turquoise gnome robe bottom and an oak shortbow.", WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL, new WorldPoint(3159, 3298, 0), THINK, item(BLUE_ROBE_TOP), item(TURQUOISE_ROBE_BOTTOMS), item(OAK_SHORTBOW)), - new EmoteClue("Think in the centre of the Observatory. Spin before you talk to me. Equip a mithril chain body, green dragonhide chaps and a ruby amulet.", OBSERVATORY, new WorldPoint(2439, 3161, 0), THINK, SPIN, item(MITHRIL_CHAINBODY), item(GREEN_DHIDE_CHAPS), item(RUBY_AMULET)), - new EmoteClue("Wave along the south fence of the Lumber Yard. Equip a hard leather body, leather chaps and a bronze axe.", NEAR_THE_SAWMILL_OPERATORS_BOOTH, new WorldPoint(3307, 3491, 0), WAVE, item(HARDLEATHER_BODY), item(LEATHER_CHAPS), item(BRONZE_AXE)), - new EmoteClue("Wave in the Falador gem store. Equip a Mithril pickaxe, Black platebody and an Iron Kiteshield.", NEAR_HERQUINS_SHOP_IN_FALADOR, new WorldPoint(2945, 3335, 0), WAVE, item(MITHRIL_PICKAXE), item(BLACK_PLATEBODY), item(IRON_KITESHIELD)), - new EmoteClue("Wave on Mudskipper Point. Equip a black cape, leather chaps and a steel mace.", MUDSKIPPER_POINT, new WorldPoint(2989, 3110, 0), WAVE, item(BLACK_CAPE), item(LEATHER_CHAPS), item(STEEL_MACE)), - new EmoteClue("Wave on the northern wall of Castle Drakan. Beware of double agents! Wear a dragon sq shield, splitbark body and any boater.", NORTHERN_WALL_OF_CASTLE_DRAKAN, new WorldPoint(3560, 3385, 0), WAVE, item(DRAGON_SQ_SHIELD), item(SPLITBARK_BODY), any("Any boater", item(RED_BOATER), item(ORANGE_BOATER), item(GREEN_BOATER), item(BLUE_BOATER), item(BLACK_BOATER), item(PINK_BOATER), item(PURPLE_BOATER), item(WHITE_BOATER))), - new EmoteClue("Yawn in the 7th room of Pyramid Plunder. Beware of double agents! Equip a pharaoh sceptre and a full set of menaphite robes.", _7TH_CHAMBER_OF_JALSAVRAH, new WorldPoint(1944, 4427, 0), YAWN, any("Pharaoh's sceptre", item(PHARAOHS_SCEPTRE), item(PHARAOHS_SCEPTRE_1), item(PHARAOHS_SCEPTRE_2), item(PHARAOHS_SCEPTRE_3), item(PHARAOHS_SCEPTRE_4), item(PHARAOHS_SCEPTRE_5), item(PHARAOHS_SCEPTRE_6), item(PHARAOHS_SCEPTRE_7), item(PHARAOHS_SCEPTRE_8)), any("Full set of menaphite robes", all(item(MENAPHITE_PURPLE_HAT), item(MENAPHITE_PURPLE_TOP), range(MENAPHITE_PURPLE_ROBE, MENAPHITE_PURPLE_KILT)), all(item(MENAPHITE_RED_HAT), item(MENAPHITE_RED_TOP), range(MENAPHITE_RED_ROBE, MENAPHITE_RED_KILT)))), - new EmoteClue("Yawn in the Varrock library. Equip a green gnome robe top, HAM robe bottom and an iron warhammer.", VARROCK_PALACE_LIBRARY, new WorldPoint(3209, 3492, 0), YAWN, item(GREEN_ROBE_TOP), item(HAM_ROBE), item(IRON_WARHAMMER)), - new EmoteClue("Yawn in Draynor Marketplace. Equip studded leather chaps, an iron kiteshield and a steel longsword.", DRAYNOR_VILLAGE_MARKET, new WorldPoint(3083, 3253, 0), YAWN, item(STUDDED_CHAPS), item(IRON_KITESHIELD), item(STEEL_LONGSWORD)), - new EmoteClue("Yawn in the Castle Wars lobby. Shrug before you talk to me. Equip a ruby amulet, a mithril scimitar and a Wilderness cape.", CASTLE_WARS_BANK, new WorldPoint(2440, 3092, 0), YAWN, SHRUG, item(RUBY_AMULET), item(MITHRIL_SCIMITAR), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)), - new EmoteClue("Yawn in the rogues' general store. Beware of double agents! Equip an adamant square shield, blue dragon vambraces and a rune pickaxe.", NOTERAZZOS_SHOP_IN_THE_WILDERNESS, new WorldPoint(3026, 3701, 0), YAWN, item(ADAMANT_SQ_SHIELD), item(BLUE_DHIDE_VAMB), item(RUNE_PICKAXE)), - new EmoteClue("Yawn at the top of Trollheim. Equip a lava battlestaff, black dragonhide vambraces and a mind shield.", ON_TOP_OF_TROLLHEIM_MOUNTAIN, new WorldPoint(2887, 3676, 0), YAWN, item(LAVA_BATTLESTAFF), item(BLACK_DHIDE_VAMB), item(MIND_SHIELD)), - new EmoteClue("Yawn in the centre of Arceuus library. Nod your head before you talk to me. Equip blue dragonhide vambraces, adamant boots and an adamant dagger.", ENTRANCE_OF_THE_ARCEUUS_LIBRARY, new WorldPoint(1632, 3807, 0), YAWN, YES, item(BLUE_DHIDE_VAMB), item(ADAMANT_BOOTS), item(ADAMANT_DAGGER)), - new EmoteClue("Swing a bullroarer at the top of the watchtower. Beware of double agents! Equip a dragon plateskirt, climbing boots and a dragon chainbody.", TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER, new WorldPoint(2932, 4712, 0), BULL_ROARER, item(DRAGON_PLATESKIRT), item(CLIMBING_BOOTS), item(DRAGON_CHAINBODY_3140), item(ItemID.BULL_ROARER)), - new EmoteClue("Blow a raspberry at Gypsy Aris in her tent. Equip a gold ring and a gold necklace.", GYPSY_TENT_ENTRANCE, new WorldPoint(3203, 3424, 0), RASPBERRY, item(GOLD_RING), item(GOLD_NECKLACE)), - new EmoteClue("Bow to Brugsen Bursen at the Grand Exchange.", null, new WorldPoint(3164, 3477, 0), BOW), - new EmoteClue("Cheer at Iffie Nitter. Equip a chef hat and a red cape.", FINE_CLOTHES_ENTRANCE, new WorldPoint(3205, 3416, 0), CHEER, item(CHEFS_HAT), item(RED_CAPE)), - new EmoteClue("Clap at Bob's Brilliant Axes. Equip a bronze axe and leather boots.", BOB_AXES_ENTRANCE, new WorldPoint(3231, 3203, 0), CLAP, item(BRONZE_AXE), item(LEATHER_BOOTS)), - new EmoteClue("Panic at Al Kharid mine.", null, new WorldPoint(3300, 3314, 0), PANIC), - new EmoteClue("Spin at Flynn's Mace Shop.", null, new WorldPoint(2950, 3387, 0), SPIN)); - - private static SingleItemRequirement item(int itemId) - { - return new SingleItemRequirement(itemId); - } - - private static RangeItemRequirement range(int startItemId, int endItemId) - { - return range(null, startItemId, endItemId); - } - - private static RangeItemRequirement range(String name, int startItemId, int endItemId) - { - return new RangeItemRequirement(name, startItemId, endItemId); - } - - private static AnyRequirementCollection any(String name, ItemRequirement... requirements) - { - return new AnyRequirementCollection(name, requirements); - } - - private static AllRequirementsCollection all(ItemRequirement... requirements) - { - return new AllRequirementsCollection(requirements); - } - - private static SlotLimitationRequirement emptySlot(String description, EquipmentInventorySlot... slots) - { - return new SlotLimitationRequirement(description, slots); - } - - private final String text; - private final Integer stashUnit; - private final WorldPoint location; - private final Emote firstEmote; - private final Emote secondEmote; - @Nonnull - private final ItemRequirement[] itemRequirements; - - private EmoteClue(String text, Integer stashUnit, WorldPoint location, Emote firstEmote, @Nonnull ItemRequirement... itemRequirements) - { - this(text, stashUnit, location, firstEmote, null, itemRequirements); - } - - private EmoteClue(String text, Integer stashUnit, WorldPoint location, Emote firstEmote, Emote secondEmote, @Nonnull ItemRequirement... itemRequirements) - { - this.text = text; - this.stashUnit = stashUnit; - this.location = location; - this.firstEmote = firstEmote; - this.secondEmote = secondEmote; - this.itemRequirements = itemRequirements; - } - - @Override - public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) - { - panelComponent.getChildren().add(TitleComponent.builder().text("Emote Clue").build()); - panelComponent.getChildren().add(LineComponent.builder().left("Emotes:").build()); - panelComponent.getChildren().add(LineComponent.builder() - .left(getFirstEmote().getName()) - .leftColor(TITLED_CONTENT_COLOR) - .build()); - - if (getSecondEmote() != null) - { - panelComponent.getChildren().add(LineComponent.builder() - .left(getSecondEmote().getName()) - .leftColor(TITLED_CONTENT_COLOR) - .build()); - } - - if (itemRequirements.length > 0) - { - panelComponent.getChildren().add(LineComponent.builder().left("Equip:").build()); - - Item[] equipment = plugin.getEquippedItems(); - Item[] inventory = plugin.getInventoryItems(); - - // If equipment is null, the player is wearing nothing - if (equipment == null) - { - equipment = new Item[0]; - } - - // If inventory is null, the player has nothing in their inventory - if (inventory == null) - { - inventory = new Item[0]; - } - - Item[] combined = new Item[equipment.length + inventory.length]; - System.arraycopy(equipment, 0, combined, 0, equipment.length); - System.arraycopy(inventory, 0, combined, equipment.length, inventory.length); - - for (ItemRequirement requirement : itemRequirements) - { - boolean equipmentFulfilled = requirement.fulfilledBy(equipment); - boolean combinedFulfilled = requirement.fulfilledBy(combined); - - panelComponent.getChildren().add(LineComponent.builder() - .left(requirement.getCollectiveName(plugin.getClient())) - .leftColor(TITLED_CONTENT_COLOR) - .right(combinedFulfilled ? "\u2713" : "\u2717") - .rightColor(equipmentFulfilled ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED)) - .build()); - } - } - } - - @Override - public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) - { - LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation()); - - if (localLocation == null) - { - return; - } - - OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getEmoteImage(), Color.ORANGE); - } - - public static EmoteClue forText(String text) - { - for (EmoteClue clue : CLUES) - { - if (clue.getText().equalsIgnoreCase(text)) - { - return clue; - } - } - - return null; - } -} +/* + * Copyright (c) 2018, Lotto + * 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.cluescrolls.clues; + +import com.google.common.collect.ImmutableSet; +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.Set; +import javax.annotation.Nonnull; +import lombok.Getter; +import net.runelite.api.EquipmentInventorySlot; +import static net.runelite.api.EquipmentInventorySlot.AMMO; +import static net.runelite.api.EquipmentInventorySlot.AMULET; +import static net.runelite.api.EquipmentInventorySlot.BODY; +import static net.runelite.api.EquipmentInventorySlot.BOOTS; +import static net.runelite.api.EquipmentInventorySlot.CAPE; +import static net.runelite.api.EquipmentInventorySlot.GLOVES; +import static net.runelite.api.EquipmentInventorySlot.HEAD; +import static net.runelite.api.EquipmentInventorySlot.LEGS; +import static net.runelite.api.EquipmentInventorySlot.RING; +import static net.runelite.api.EquipmentInventorySlot.SHIELD; +import static net.runelite.api.EquipmentInventorySlot.WEAPON; +import net.runelite.api.Item; +import net.runelite.api.ItemID; +import static net.runelite.api.ItemID.ABYSSAL_WHIP; +import static net.runelite.api.ItemID.ADAMANT_2H_SWORD; +import static net.runelite.api.ItemID.ADAMANT_BOOTS; +import static net.runelite.api.ItemID.ADAMANT_DAGGER; +import static net.runelite.api.ItemID.ADAMANT_FULL_HELM; +import static net.runelite.api.ItemID.ADAMANT_HALBERD; +import static net.runelite.api.ItemID.ADAMANT_MED_HELM; +import static net.runelite.api.ItemID.ADAMANT_PLATEBODY; +import static net.runelite.api.ItemID.ADAMANT_PLATELEGS; +import static net.runelite.api.ItemID.ADAMANT_PLATESKIRT; +import static net.runelite.api.ItemID.ADAMANT_SQ_SHIELD; +import static net.runelite.api.ItemID.ADAMANT_SWORD; +import static net.runelite.api.ItemID.ADAMANT_WARHAMMER; +import static net.runelite.api.ItemID.AHRIMS_HOOD_0; +import static net.runelite.api.ItemID.AHRIMS_HOOD_100; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_0; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_100; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_0; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_100; +import static net.runelite.api.ItemID.AHRIMS_STAFF_0; +import static net.runelite.api.ItemID.AHRIMS_STAFF_100; +import static net.runelite.api.ItemID.AIR_TIARA; +import static net.runelite.api.ItemID.AMULET_OF_GLORY; +import static net.runelite.api.ItemID.AMULET_OF_GLORY1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY4; +import static net.runelite.api.ItemID.AMULET_OF_GLORY5; +import static net.runelite.api.ItemID.AMULET_OF_GLORY6; +import static net.runelite.api.ItemID.AMULET_OF_POWER; +import static net.runelite.api.ItemID.AMULET_OF_STRENGTH; +import static net.runelite.api.ItemID.AMULET_OF_THE_DAMNED; +import static net.runelite.api.ItemID.AMULET_OF_THE_DAMNED_FULL; +import static net.runelite.api.ItemID.ANCIENT_CROZIER; +import static net.runelite.api.ItemID.ANCIENT_MITRE; +import static net.runelite.api.ItemID.ANCIENT_STOLE; +import static net.runelite.api.ItemID.ARCLIGHT; +import static net.runelite.api.ItemID.ARMADYL_CROZIER; +import static net.runelite.api.ItemID.ARMADYL_MITRE; +import static net.runelite.api.ItemID.ARMADYL_STOLE; +import static net.runelite.api.ItemID.BANDOS_BOOTS; +import static net.runelite.api.ItemID.BANDOS_CLOAK; +import static net.runelite.api.ItemID.BANDOS_CROZIER; +import static net.runelite.api.ItemID.BANDOS_GODSWORD; +import static net.runelite.api.ItemID.BANDOS_MITRE; +import static net.runelite.api.ItemID.BANDOS_PLATEBODY; +import static net.runelite.api.ItemID.BANDOS_STOLE; +import static net.runelite.api.ItemID.BARROWS_GLOVES; +import static net.runelite.api.ItemID.BLACK_AXE; +import static net.runelite.api.ItemID.BLACK_BOATER; +import static net.runelite.api.ItemID.BLACK_CAPE; +import static net.runelite.api.ItemID.BLACK_DHIDE_BODY; +import static net.runelite.api.ItemID.BLACK_DHIDE_CHAPS; +import static net.runelite.api.ItemID.BLACK_DHIDE_VAMB; +import static net.runelite.api.ItemID.BLACK_DRAGON_MASK; +import static net.runelite.api.ItemID.BLACK_PLATEBODY; +import static net.runelite.api.ItemID.BLACK_SALAMANDER; +import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET; +import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.BLUE_BOATER; +import static net.runelite.api.ItemID.BLUE_BOOTS; +import static net.runelite.api.ItemID.BLUE_DHIDE_BODY; +import static net.runelite.api.ItemID.BLUE_DHIDE_CHAPS; +import static net.runelite.api.ItemID.BLUE_DHIDE_VAMB; +import static net.runelite.api.ItemID.BLUE_ROBE_TOP; +import static net.runelite.api.ItemID.BLUE_WIZARD_HAT; +import static net.runelite.api.ItemID.BLUE_WIZARD_ROBE; +import static net.runelite.api.ItemID.BOBS_PURPLE_SHIRT; +import static net.runelite.api.ItemID.BOBS_RED_SHIRT; +import static net.runelite.api.ItemID.BODY_TIARA; +import static net.runelite.api.ItemID.BONE_DAGGER; +import static net.runelite.api.ItemID.BONE_SPEAR; +import static net.runelite.api.ItemID.BOOK_OF_BALANCE; +import static net.runelite.api.ItemID.BOOK_OF_DARKNESS; +import static net.runelite.api.ItemID.BOOK_OF_LAW; +import static net.runelite.api.ItemID.BOOK_OF_WAR; +import static net.runelite.api.ItemID.BRINE_SABRE; +import static net.runelite.api.ItemID.BRONZE_2H_SWORD; +import static net.runelite.api.ItemID.BRONZE_AXE; +import static net.runelite.api.ItemID.BRONZE_CHAINBODY; +import static net.runelite.api.ItemID.BRONZE_DAGGER; +import static net.runelite.api.ItemID.BRONZE_FULL_HELM; +import static net.runelite.api.ItemID.BRONZE_PLATELEGS; +import static net.runelite.api.ItemID.BRONZE_SPEAR; +import static net.runelite.api.ItemID.BRONZE_SQ_SHIELD; +import static net.runelite.api.ItemID.BROWN_APRON; +import static net.runelite.api.ItemID.BROWN_HEADBAND; +import static net.runelite.api.ItemID.BRUISE_BLUE_SNELM_3343; +import static net.runelite.api.ItemID.CAPE_OF_LEGENDS; +import static net.runelite.api.ItemID.CASTLE_WARS_BRACELET1; +import static net.runelite.api.ItemID.CASTLE_WARS_BRACELET3; +import static net.runelite.api.ItemID.CHEFS_HAT; +import static net.runelite.api.ItemID.CLIMBING_BOOTS; +import static net.runelite.api.ItemID.COIF; +import static net.runelite.api.ItemID.COMBAT_BRACELET; +import static net.runelite.api.ItemID.COMBAT_BRACELET4; +import static net.runelite.api.ItemID.CREAM_ROBE_TOP; +import static net.runelite.api.ItemID.CRYSTAL_BOW_110_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_210_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_310_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_410_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_510_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_610_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_710_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_810_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_910_I; +import static net.runelite.api.ItemID.CRYSTAL_BOW_FULL_I; +import static net.runelite.api.ItemID.DEATH_TIARA; +import static net.runelite.api.ItemID.DESERT_SHIRT; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_0; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_100; +import static net.runelite.api.ItemID.DHAROKS_HELM_0; +import static net.runelite.api.ItemID.DHAROKS_HELM_100; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_0; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_100; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_0; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_100; +import static net.runelite.api.ItemID.DIAMOND_BRACELET; +import static net.runelite.api.ItemID.DIAMOND_RING; +import static net.runelite.api.ItemID.DRAGONSTONE_AMULET; +import static net.runelite.api.ItemID.DRAGONSTONE_RING; +import static net.runelite.api.ItemID.DRAGON_2H_SWORD; +import static net.runelite.api.ItemID.DRAGON_AXE; +import static net.runelite.api.ItemID.DRAGON_BATTLEAXE; +import static net.runelite.api.ItemID.DRAGON_BOOTS; +import static net.runelite.api.ItemID.DRAGON_CHAINBODY_3140; +import static net.runelite.api.ItemID.DRAGON_DEFENDER; +import static net.runelite.api.ItemID.DRAGON_MED_HELM; +import static net.runelite.api.ItemID.DRAGON_NECKLACE; +import static net.runelite.api.ItemID.DRAGON_PICKAXE; +import static net.runelite.api.ItemID.DRAGON_PICKAXE_12797; +import static net.runelite.api.ItemID.DRAGON_PLATESKIRT; +import static net.runelite.api.ItemID.DRAGON_SPEAR; +import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD; +import static net.runelite.api.ItemID.ELEMENTAL_SHIELD; +import static net.runelite.api.ItemID.EMERALD_AMULET; +import static net.runelite.api.ItemID.EMERALD_RING; +import static net.runelite.api.ItemID.FIRE_BATTLESTAFF; +import static net.runelite.api.ItemID.FIRE_CAPE; +import static net.runelite.api.ItemID.FIRE_MAX_CAPE; +import static net.runelite.api.ItemID.FLARED_TROUSERS; +import static net.runelite.api.ItemID.FROZEN_ABYSSAL_WHIP; +import static net.runelite.api.ItemID.GOLD_NECKLACE; +import static net.runelite.api.ItemID.GOLD_RING; +import static net.runelite.api.ItemID.GRANITE_SHIELD; +import static net.runelite.api.ItemID.GREEN_BOATER; +import static net.runelite.api.ItemID.GREEN_BOOTS; +import static net.runelite.api.ItemID.GREEN_DHIDE_BODY; +import static net.runelite.api.ItemID.GREEN_DHIDE_CHAPS; +import static net.runelite.api.ItemID.GREEN_HAT; +import static net.runelite.api.ItemID.GREEN_HEADBAND; +import static net.runelite.api.ItemID.GREEN_ROBE_BOTTOMS; +import static net.runelite.api.ItemID.GREEN_ROBE_TOP; +import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET; +import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_0; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_100; +import static net.runelite.api.ItemID.GUTHANS_HELM_0; +import static net.runelite.api.ItemID.GUTHANS_HELM_100; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_0; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_100; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_0; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_100; +import static net.runelite.api.ItemID.GUTHIX_MITRE; +import static net.runelite.api.ItemID.GUTHIX_STOLE; +import static net.runelite.api.ItemID.HAM_BOOTS; +import static net.runelite.api.ItemID.HAM_ROBE; +import static net.runelite.api.ItemID.HARDLEATHER_BODY; +import static net.runelite.api.ItemID.HELM_OF_NEITIZNOT; +import static net.runelite.api.ItemID.HOLY_BOOK; +import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET; +import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.IBANS_STAFF; +import static net.runelite.api.ItemID.IBANS_STAFF_U; +import static net.runelite.api.ItemID.INFERNAL_PICKAXE; +import static net.runelite.api.ItemID.INFERNAL_PICKAXE_UNCHARGED; +import static net.runelite.api.ItemID.IRON_2H_SWORD; +import static net.runelite.api.ItemID.IRON_CHAINBODY; +import static net.runelite.api.ItemID.IRON_FULL_HELM; +import static net.runelite.api.ItemID.IRON_KITESHIELD; +import static net.runelite.api.ItemID.IRON_MED_HELM; +import static net.runelite.api.ItemID.IRON_PICKAXE; +import static net.runelite.api.ItemID.IRON_PLATEBODY; +import static net.runelite.api.ItemID.IRON_PLATELEGS; +import static net.runelite.api.ItemID.IRON_PLATESKIRT; +import static net.runelite.api.ItemID.IRON_SCIMITAR; +import static net.runelite.api.ItemID.IRON_WARHAMMER; +import static net.runelite.api.ItemID.KARILS_COIF_0; +import static net.runelite.api.ItemID.KARILS_COIF_100; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_0; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_100; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_0; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_100; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_0; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_100; +import static net.runelite.api.ItemID.LAVA_BATTLESTAFF; +import static net.runelite.api.ItemID.LEATHER_BOOTS; +import static net.runelite.api.ItemID.LEATHER_CHAPS; +import static net.runelite.api.ItemID.LEATHER_COWL; +import static net.runelite.api.ItemID.LEATHER_GLOVES; +import static net.runelite.api.ItemID.LOCKPICK; +import static net.runelite.api.ItemID.LONGBOW; +import static net.runelite.api.ItemID.MAGIC_LONGBOW; +import static net.runelite.api.ItemID.MAPLE_LONGBOW; +import static net.runelite.api.ItemID.MAPLE_SHORTBOW; +import static net.runelite.api.ItemID.MENAPHITE_PURPLE_HAT; +import static net.runelite.api.ItemID.MENAPHITE_PURPLE_KILT; +import static net.runelite.api.ItemID.MENAPHITE_PURPLE_ROBE; +import static net.runelite.api.ItemID.MENAPHITE_PURPLE_TOP; +import static net.runelite.api.ItemID.MENAPHITE_RED_HAT; +import static net.runelite.api.ItemID.MENAPHITE_RED_KILT; +import static net.runelite.api.ItemID.MENAPHITE_RED_ROBE; +import static net.runelite.api.ItemID.MENAPHITE_RED_TOP; +import static net.runelite.api.ItemID.MIND_SHIELD; +import static net.runelite.api.ItemID.MITHRIL_BOOTS; +import static net.runelite.api.ItemID.MITHRIL_CHAINBODY; +import static net.runelite.api.ItemID.MITHRIL_FULL_HELM; +import static net.runelite.api.ItemID.MITHRIL_MED_HELM; +import static net.runelite.api.ItemID.MITHRIL_PICKAXE; +import static net.runelite.api.ItemID.MITHRIL_PLATEBODY; +import static net.runelite.api.ItemID.MITHRIL_PLATELEGS; +import static net.runelite.api.ItemID.MITHRIL_PLATESKIRT; +import static net.runelite.api.ItemID.MITHRIL_SCIMITAR; +import static net.runelite.api.ItemID.MYSTIC_FIRE_STAFF; +import static net.runelite.api.ItemID.MYSTIC_GLOVES; +import static net.runelite.api.ItemID.MYSTIC_HAT; +import static net.runelite.api.ItemID.MYSTIC_ROBE_BOTTOM; +import static net.runelite.api.ItemID.MYSTIC_ROBE_BOTTOM_DARK; +import static net.runelite.api.ItemID.MYSTIC_ROBE_TOP; +import static net.runelite.api.ItemID.MYSTIC_ROBE_TOP_DARK; +import static net.runelite.api.ItemID.NEW_CRYSTAL_BOW_I; +import static net.runelite.api.ItemID.OAK_LONGBOW; +import static net.runelite.api.ItemID.OAK_SHORTBOW; +import static net.runelite.api.ItemID.OBSIDIAN_CAPE; +import static net.runelite.api.ItemID.ORANGE_BOATER; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_1; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_2; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_3; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_4; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_5; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_6; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_7; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_8; +import static net.runelite.api.ItemID.PINK_BOATER; +import static net.runelite.api.ItemID.PINK_ROBE_TOP; +import static net.runelite.api.ItemID.PINK_SKIRT; +import static net.runelite.api.ItemID.PIRATE_BANDANA; +import static net.runelite.api.ItemID.PIRATE_BANDANA_7124; +import static net.runelite.api.ItemID.PIRATE_BANDANA_7130; +import static net.runelite.api.ItemID.PIRATE_BANDANA_7136; +import static net.runelite.api.ItemID.PROSELYTE_HAUBERK; +import static net.runelite.api.ItemID.PURPLE_BOATER; +import static net.runelite.api.ItemID.PURPLE_GLOVES; +import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET; +import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.RED_BOATER; +import static net.runelite.api.ItemID.RED_CAPE; +import static net.runelite.api.ItemID.RED_DHIDE_CHAPS; +import static net.runelite.api.ItemID.RED_HEADBAND; +import static net.runelite.api.ItemID.RED_SLAYER_HELMET; +import static net.runelite.api.ItemID.RED_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.RING_OF_DUELING1; +import static net.runelite.api.ItemID.RING_OF_DUELING2; +import static net.runelite.api.ItemID.RING_OF_DUELING3; +import static net.runelite.api.ItemID.RING_OF_DUELING4; +import static net.runelite.api.ItemID.RING_OF_DUELING5; +import static net.runelite.api.ItemID.RING_OF_DUELING6; +import static net.runelite.api.ItemID.RING_OF_DUELING7; +import static net.runelite.api.ItemID.RING_OF_DUELING8; +import static net.runelite.api.ItemID.RING_OF_FORGING; +import static net.runelite.api.ItemID.RING_OF_LIFE; +import static net.runelite.api.ItemID.RING_OF_VISIBILITY; +import static net.runelite.api.ItemID.RING_OF_WEALTH; +import static net.runelite.api.ItemID.RING_OF_WEALTH_1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_5; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I5; +import static net.runelite.api.ItemID.ROLLING_PIN; +import static net.runelite.api.ItemID.RUBY_AMULET; +import static net.runelite.api.ItemID.RUBY_RING; +import static net.runelite.api.ItemID.RUNE_AXE; +import static net.runelite.api.ItemID.RUNE_BOOTS; +import static net.runelite.api.ItemID.RUNE_CROSSBOW; +import static net.runelite.api.ItemID.RUNE_FULL_HELM; +import static net.runelite.api.ItemID.RUNE_HALBERD; +import static net.runelite.api.ItemID.RUNE_HELM_H1; +import static net.runelite.api.ItemID.RUNE_HELM_H5; +import static net.runelite.api.ItemID.RUNE_KITESHIELD; +import static net.runelite.api.ItemID.RUNE_LONGSWORD; +import static net.runelite.api.ItemID.RUNE_PICKAXE; +import static net.runelite.api.ItemID.RUNE_PLATEBODY; +import static net.runelite.api.ItemID.RUNE_PLATELEGS; +import static net.runelite.api.ItemID.RUNE_PLATESKIRT; +import static net.runelite.api.ItemID.RUNE_SHIELD_H1; +import static net.runelite.api.ItemID.RUNE_SHIELD_H2; +import static net.runelite.api.ItemID.RUNE_SHIELD_H3; +import static net.runelite.api.ItemID.RUNE_SHIELD_H4; +import static net.runelite.api.ItemID.RUNE_SHIELD_H5; +import static net.runelite.api.ItemID.RUNE_SPEAR; +import static net.runelite.api.ItemID.RUNE_WARHAMMER; +import static net.runelite.api.ItemID.SAPPHIRE_AMULET; +import static net.runelite.api.ItemID.SAPPHIRE_NECKLACE; +import static net.runelite.api.ItemID.SAPPHIRE_RING; +import static net.runelite.api.ItemID.SARADOMIN_CROZIER; +import static net.runelite.api.ItemID.SARADOMIN_MITRE; +import static net.runelite.api.ItemID.SARADOMIN_STOLE; +import static net.runelite.api.ItemID.SEERCULL; +import static net.runelite.api.ItemID.SHADOW_SWORD; +import static net.runelite.api.ItemID.SILVER_SICKLE; +import static net.runelite.api.ItemID.SLAYER_HELMET; +import static net.runelite.api.ItemID.SLAYER_HELMET_I; +import static net.runelite.api.ItemID.SLED_4084; +import static net.runelite.api.ItemID.SNAKESKIN_BOOTS; +import static net.runelite.api.ItemID.SNAKESKIN_CHAPS; +import static net.runelite.api.ItemID.SPINED_CHAPS; +import static net.runelite.api.ItemID.SPLITBARK_BODY; +import static net.runelite.api.ItemID.SPLITBARK_LEGS; +import static net.runelite.api.ItemID.SPOTTED_CAPE; +import static net.runelite.api.ItemID.SPOTTED_CAPE_10073; +import static net.runelite.api.ItemID.STAFF; +import static net.runelite.api.ItemID.STAFF_OF_AIR; +import static net.runelite.api.ItemID.STAFF_OF_WATER; +import static net.runelite.api.ItemID.STEEL_AXE; +import static net.runelite.api.ItemID.STEEL_FULL_HELM; +import static net.runelite.api.ItemID.STEEL_KITESHIELD; +import static net.runelite.api.ItemID.STEEL_LONGSWORD; +import static net.runelite.api.ItemID.STEEL_MACE; +import static net.runelite.api.ItemID.STEEL_MED_HELM; +import static net.runelite.api.ItemID.STEEL_PICKAXE; +import static net.runelite.api.ItemID.STEEL_PLATEBODY; +import static net.runelite.api.ItemID.STEEL_PLATESKIRT; +import static net.runelite.api.ItemID.STEEL_SQ_SHIELD; +import static net.runelite.api.ItemID.STUDDED_BODY; +import static net.runelite.api.ItemID.STUDDED_CHAPS; +import static net.runelite.api.ItemID.TEAM1_CAPE; +import static net.runelite.api.ItemID.TEAM50_CAPE; +import static net.runelite.api.ItemID.TIARA; +import static net.runelite.api.ItemID.TOKTZKETXIL; +import static net.runelite.api.ItemID.TOKTZXILUL; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_0; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_100; +import static net.runelite.api.ItemID.TORAGS_HELM_0; +import static net.runelite.api.ItemID.TORAGS_HELM_100; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_0; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_100; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_0; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_100; +import static net.runelite.api.ItemID.TURQUOISE_ROBE_BOTTOMS; +import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET; +import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.UNHOLY_BOOK; +import static net.runelite.api.ItemID.VERACS_BRASSARD_0; +import static net.runelite.api.ItemID.VERACS_BRASSARD_100; +import static net.runelite.api.ItemID.VERACS_FLAIL_0; +import static net.runelite.api.ItemID.VERACS_FLAIL_100; +import static net.runelite.api.ItemID.VERACS_HELM_0; +import static net.runelite.api.ItemID.VERACS_HELM_100; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_0; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_100; +import static net.runelite.api.ItemID.VOLCANIC_ABYSSAL_WHIP; +import static net.runelite.api.ItemID.WHITE_APRON; +import static net.runelite.api.ItemID.WHITE_BOATER; +import static net.runelite.api.ItemID.WHITE_HEADBAND; +import static net.runelite.api.ItemID.ZAMORAK_CROZIER; +import static net.runelite.api.ItemID.ZAMORAK_FULL_HELM; +import static net.runelite.api.ItemID.ZAMORAK_GODSWORD; +import static net.runelite.api.ItemID.ZAMORAK_MITRE; +import static net.runelite.api.ItemID.ZAMORAK_STOLE; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; +import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; +import net.runelite.client.plugins.cluescrolls.clues.emote.AllRequirementsCollection; +import net.runelite.client.plugins.cluescrolls.clues.emote.AnyRequirementCollection; +import net.runelite.client.plugins.cluescrolls.clues.emote.Emote; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.ANGRY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BECKON; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BLOW_KISS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BOW; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.CHEER; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.CLAP; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.CRY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.DANCE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.FLAP; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.GOBLIN_SALUTE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.HEADBANG; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.JIG; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.JUMP_FOR_JOY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.LAUGH; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.NO; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.PANIC; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.PUSH_UP; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.RASPBERRY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SALUTE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SHRUG; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SLAP_HEAD; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SPIN; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.STOMP; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.THINK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.WAVE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.YAWN; +import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.YES; +import net.runelite.client.plugins.cluescrolls.clues.emote.ItemRequirement; +import net.runelite.client.plugins.cluescrolls.clues.emote.RangeItemRequirement; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.AGILITY_PYRAMID; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.AL_KHARID_SCORPION_MINE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.AUBURYS_SHOP_IN_VARROCK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BARBARIAN_OUTPOST_OBSTACLE_COURSE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BARROWS_CHEST; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BOB_AXES_ENTRANCE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CASTLE_WARS_BANK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CATHERBY_BEEHIVE_FIELD; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CENTRE_OF_CANIFIS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CENTRE_OF_THE_CATACOMBS_OF_KOUREND; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CHAPEL_IN_WEST_ARDOUGNE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DEATH_ALTAR; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DIGSITE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DRAYNOR_MANOR_BY_THE_FOUNTAIN; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DRAYNOR_VILLAGE_MARKET; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANA_CHAPEL; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANCE_OF_THE_ARCEUUS_LIBRARY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANCE_OF_THE_CAVE_OF_DAMIS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.FINE_CLOTHES_ENTRANCE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.FISHING_GUILD_BANK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.FOUNTAIN_OF_HEROES; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.GNOME_STRONGHOLD_BALANCING_ROPE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.GYPSY_TENT_ENTRANCE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.HALFWAY_DOWN_TROLLWEISS_MOUNTAIN; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.HICKTONS_ARCHERY_EMPORIUM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.HOSIDIUS_MESS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.INSIDE_THE_DIGSITE_EXAM_CENTRE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.IN_THE_MIDDLE_OF_JIGGIG; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.KING_BLACK_DRAGONS_LAIR; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.LIMESTONE_MINE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.LUMBRIDGE_SWAMP_CAVES; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MAUSOLEUM_OFF_THE_MORYTANIA_COAST; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MOUNTAIN_CAMP_GOAT_ENCLOSURE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MUBARIZS_ROOM_AT_THE_DUEL_ARENA; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MUDSKIPPER_POINT; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_A_SHED_IN_LUMBRIDGE_SWAMP; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_HERQUINS_SHOP_IN_FALADOR; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_PIER_IN_ZULANDRA; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_SAWMILL_OPERATORS_BOOTH; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTHERN_WALL_OF_CASTLE_DRAKAN; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTH_OF_MOUNT_KARUULM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NOTERAZZOS_SHOP_IN_THE_WILDERNESS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OBSERVATORY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ON_TOP_OF_TROLLHEIM_MOUNTAIN; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_CATHERBY_BANK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_DRAYNOR_VILLAGE_JAIL; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_KEEP_LE_FAYE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_KRIL_TSUTSAROTHS_ROOM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_MUDKNUCKLES_HUT; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_DIGSITE_EXAM_CENTRE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_FALADOR_PARTY_ROOM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_FISHING_GUILD; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_LEGENDS_GUILD_DOOR; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_LEGENDS_GUILD_GATES; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_WILDERNESS_AXE_HUT; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_VARROCK_PALACE_COURTYARD; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_YANILLE_BANK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.RIMMINGTON_MINE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ROAD_JUNCTION_NORTH_OF_RIMMINGTON; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHAYZIEN_WAR_TENT; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHILO_VILLAGE_BANK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUL_ALTAR; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTHEAST_CORNER_OF_THE_MONASTERY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTH_OF_THE_GRAND_EXCHANGE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TAVERLEY_STONE_CIRCLE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TENT_IN_LORD_IORWERTHS_ENCAMPMENT; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TOP_FLOOR_OF_THE_LIGHTHOUSE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TZHAAR_GEM_STORE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TZHAAR_WEAPONS_STORE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.VARROCK_PALACE_LIBRARY; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WARRIORS_GUILD_BANK; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WARRIORS_GUILD_BANK_29047; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WELL_OF_VOYAGE; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WEST_OF_THE_SHAYZIEN_COMBAT_RING; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL; +import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit._7TH_CHAMBER_OF_JALSAVRAH; +import net.runelite.client.plugins.cluescrolls.clues.emote.SingleItemRequirement; +import net.runelite.client.plugins.cluescrolls.clues.emote.SlotLimitationRequirement; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +@Getter +public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClueScroll +{ + private static final Set CLUES = ImmutableSet.of( + new EmoteClue("Beckon on the east coast of the Kharazi Jungle. Beware of double agents! Equip any vestment stole and a heraldic rune shield.", NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE, new WorldPoint(2954, 2933, 0), BECKON, any("Any stole", item(GUTHIX_STOLE), item(SARADOMIN_STOLE), item(ZAMORAK_STOLE), item(ARMADYL_STOLE), item(BANDOS_STOLE), item(ANCIENT_STOLE)), any("Any heraldic rune shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))), + new EmoteClue("Cheer in the Barbarian Agility Arena. Headbang before you talk to me. Equip a steel platebody, maple shortbow and a Wilderness cape.", BARBARIAN_OUTPOST_OBSTACLE_COURSE, new WorldPoint(2552, 3556, 0), CHEER, HEADBANG, item(STEEL_PLATEBODY), item(MAPLE_SHORTBOW), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)), + new EmoteClue("Bow upstairs in the Edgeville Monastery. Equip a completed prayer book.", SOUTHEAST_CORNER_OF_THE_MONASTERY, new WorldPoint(3056, 3484, 1), BOW, any("Any god book", item(HOLY_BOOK), item(BOOK_OF_BALANCE), item(UNHOLY_BOOK), item(BOOK_OF_LAW), item(BOOK_OF_WAR), item(BOOK_OF_DARKNESS))), + new EmoteClue("Cheer in the Shadow dungeon. Equip a rune crossbow, climbing boots and any mitre.", ENTRANCE_OF_THE_CAVE_OF_DAMIS, new WorldPoint(2629, 5071, 0), CHEER, any("Any mitre", item(GUTHIX_MITRE), item(SARADOMIN_MITRE), item(ZAMORAK_MITRE), item(ANCIENT_MITRE), item(BANDOS_MITRE), item(ARMADYL_MITRE)), item(RUNE_CROSSBOW), item(CLIMBING_BOOTS), item(RING_OF_VISIBILITY)), + new EmoteClue("Cheer at the top of the agility pyramid. Beware of double agents! Equip a blue mystic robe top, and any rune heraldic shield.", AGILITY_PYRAMID, new WorldPoint(3043, 4697, 3), CHEER, item(MYSTIC_ROBE_TOP), any("Any rune heraldic shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))), + new EmoteClue("Dance in Iban's temple. Beware of double agents! Equip Iban's staff, a black mystic top and a black mystic bottom.", WELL_OF_VOYAGE, new WorldPoint(2011, 4712, 0), DANCE, any("Any iban's staff", item(IBANS_STAFF), item(IBANS_STAFF_U)), item(MYSTIC_ROBE_TOP_DARK), item(MYSTIC_ROBE_BOTTOM_DARK)), + new EmoteClue("Dance on the Fishing Platform. Equip barrows gloves, an amulet of glory and a dragon med helm.", SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM, new WorldPoint(2782, 3273, 0), DANCE, any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6)), item(BARROWS_GLOVES), item(DRAGON_MED_HELM)), + new EmoteClue("Flap at the death altar. Beware of double agents! Equip a death tiara, a legend's cape and any ring of wealth.", DEATH_ALTAR, new WorldPoint(2205, 4838, 0), FLAP, any("Any ring of wealth", item(RING_OF_WEALTH), item(RING_OF_WEALTH_1), item(RING_OF_WEALTH_2), item(RING_OF_WEALTH_3), item(RING_OF_WEALTH_4), item(RING_OF_WEALTH_5), item(RING_OF_WEALTH_I), item(RING_OF_WEALTH_I1), item(RING_OF_WEALTH_I2), item(RING_OF_WEALTH_I3), item(RING_OF_WEALTH_I4), item(RING_OF_WEALTH_I5)), item(DEATH_TIARA), item(CAPE_OF_LEGENDS)), + new EmoteClue("Headbang in the Fight Arena pub. Equip a pirate bandana, a dragonstone necklace and and a magic longbow.", OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA, new WorldPoint(2568, 3149, 0), HEADBANG, any("Any pirate bandana", item(PIRATE_BANDANA), item(PIRATE_BANDANA_7124), item(PIRATE_BANDANA_7130), item(PIRATE_BANDANA_7136)), item(DRAGON_NECKLACE), item(MAGIC_LONGBOW)), + new EmoteClue("Do a jig at the barrow's chest. Beware of double agents! Equip any full barrows set.", BARROWS_CHEST, new WorldPoint(3551, 9694, 0), JIG, any("Any full barrows set", all(range(AHRIMS_HOOD_100, AHRIMS_HOOD_0), range(AHRIMS_STAFF_100, AHRIMS_STAFF_0), range(AHRIMS_ROBETOP_100, AHRIMS_ROBETOP_0), range(AHRIMS_ROBESKIRT_100, AHRIMS_ROBESKIRT_0)), all(range(DHAROKS_HELM_100, DHAROKS_HELM_0), range(DHAROKS_GREATAXE_100, DHAROKS_GREATAXE_0), range(DHAROKS_PLATEBODY_100, DHAROKS_PLATEBODY_0), range(DHAROKS_PLATELEGS_100, DHAROKS_PLATELEGS_0)), all(range(GUTHANS_HELM_100, GUTHANS_HELM_0), range(GUTHANS_WARSPEAR_100, GUTHANS_WARSPEAR_0), range(GUTHANS_PLATEBODY_100, GUTHANS_PLATEBODY_0), range(GUTHANS_CHAINSKIRT_100, GUTHANS_CHAINSKIRT_0)), all(range(KARILS_COIF_100, KARILS_COIF_0), range(KARILS_CROSSBOW_100, KARILS_CROSSBOW_0), range(KARILS_LEATHERTOP_100, KARILS_LEATHERTOP_0), range(KARILS_LEATHERSKIRT_100, KARILS_LEATHERSKIRT_0)), all(range(TORAGS_HELM_100, TORAGS_HELM_0), range(TORAGS_HAMMERS_100, TORAGS_HAMMERS_0), range(TORAGS_PLATEBODY_100, TORAGS_PLATEBODY_0), range(TORAGS_PLATELEGS_100, TORAGS_PLATELEGS_0)), all(range(VERACS_HELM_100, VERACS_HELM_0), range(VERACS_FLAIL_100, VERACS_FLAIL_0), range(VERACS_BRASSARD_100, VERACS_BRASSARD_0), range(VERACS_PLATESKIRT_100, VERACS_PLATESKIRT_0)))), + new EmoteClue("Jig at Jiggig. Beware of double agents! Equip a Rune spear, rune platelegs and any rune heraldic helm.", IN_THE_MIDDLE_OF_JIGGIG, new WorldPoint(2477, 3047, 0), JIG, range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5), item(RUNE_SPEAR), item(RUNE_PLATELEGS)), + new EmoteClue("Cheer at the games room. Have nothing equipped at all when you do.", null, new WorldPoint(2207, 4952, 0), CHEER, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), + new EmoteClue("Panic on the pier where you catch the Fishing trawler. Have nothing equipped at all when you do.", null, new WorldPoint(2676, 3169, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), + new EmoteClue("Panic in the heart of the Haunted Woods. Beware of double agents! Have no items equipped when you do.", null, new WorldPoint(3611, 3492, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), + new EmoteClue("Show your anger towards the Statue of Saradomin in Ellamaria's garden. Beware of double agents! Equip a zamorak godsword.", BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS, new WorldPoint(3230, 3478, 0), ANGRY, item(ZAMORAK_GODSWORD)), + new EmoteClue("Show your anger at the Wise old man. Beware of double agents! Equip an abyssal whip, a legend's cape and some spined chaps.", BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE, new WorldPoint(3088, 3254, 0), ANGRY, any("Abyssal whip", item(ABYSSAL_WHIP), item(VOLCANIC_ABYSSAL_WHIP), item(FROZEN_ABYSSAL_WHIP)), item(CAPE_OF_LEGENDS), item(SPINED_CHAPS)), + new EmoteClue("Beckon in the Digsite, near the eastern winch. Bow before you talk to me. Equip a green gnome hat, snakeskin boots and an iron pickaxe.", DIGSITE, new WorldPoint(3370, 3425, 0), BECKON, BOW, item(GREEN_HAT), item(SNAKESKIN_BOOTS), item(IRON_PICKAXE)), + new EmoteClue("Beckon in Tai Bwo Wannai. Clap before you talk to me. Equip green dragonhide chaps, a ring of dueling and a mithril medium helmet.", SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE, new WorldPoint(2803, 3073, 0), BECKON, CLAP, item(GREEN_DHIDE_CHAPS), any("Ring of dueling", item(RING_OF_DUELING1), item(RING_OF_DUELING2), item(RING_OF_DUELING3), item(RING_OF_DUELING4), item(RING_OF_DUELING5), item(RING_OF_DUELING6), item(RING_OF_DUELING7), item(RING_OF_DUELING8)), item(MITHRIL_MED_HELM)), + new EmoteClue("Beckon in the combat ring of Shayzien. Show your anger before you talk to me. Equip an adamant platebody, adamant full helm and adamant platelegs.", WEST_OF_THE_SHAYZIEN_COMBAT_RING, new WorldPoint(1545, 3594, 0), BECKON, ANGRY, item(ADAMANT_PLATELEGS), item(ADAMANT_PLATEBODY), item(ADAMANT_FULL_HELM)), + new EmoteClue("Bow near Lord Iorwerth. Beware of double agents! Equip a new imbued crystal bow.", TENT_IN_LORD_IORWERTHS_ENCAMPMENT, new WorldPoint(2205, 3252, 0), BOW, any("Imbued crystal bow", item(NEW_CRYSTAL_BOW_I), item(CRYSTAL_BOW_FULL_I), item(CRYSTAL_BOW_910_I), item(CRYSTAL_BOW_810_I), item(CRYSTAL_BOW_710_I), item(CRYSTAL_BOW_610_I), item(CRYSTAL_BOW_510_I), item(CRYSTAL_BOW_410_I), item(CRYSTAL_BOW_310_I), item(CRYSTAL_BOW_210_I), item(CRYSTAL_BOW_110_I))), + new EmoteClue("Bow outside the entrance to the Legends' Guild. Equip iron platelegs, an emerald amulet and an oak longbow.", OUTSIDE_THE_LEGENDS_GUILD_GATES, new WorldPoint(2729, 3349, 0), BOW, item(IRON_PLATELEGS), item(OAK_LONGBOW), item(EMERALD_AMULET)), + new EmoteClue("Bow on the ground floor of the Legend's guild. Equip Legend's cape, a dragon battleaxe and an amulet of glory.", OUTSIDE_THE_LEGENDS_GUILD_DOOR, new WorldPoint(2728, 3377, 0), BOW, item(CAPE_OF_LEGENDS), item(DRAGON_BATTLEAXE), any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6))), + new EmoteClue("Bow in the ticket office of the Duel Arena. Equip an iron chain body, leather chaps and coif.", MUBARIZS_ROOM_AT_THE_DUEL_ARENA, new WorldPoint(3314, 3241, 0), BOW, item(IRON_CHAINBODY), item(LEATHER_CHAPS), item(COIF)), + new EmoteClue("Bow at the top of the lighthouse. Beware of double agents! Equip a blue dragonhide body, blue dragonhide vambraces and no jewelry.", TOP_FLOOR_OF_THE_LIGHTHOUSE, new WorldPoint(2511, 3641, 2), BOW, item(BLUE_DHIDE_BODY), item(BLUE_DHIDE_VAMB), emptySlot("No jewelry", AMULET, RING)), + new EmoteClue("Blow a kiss between the tables in Shilo Village bank. Beware of double agents! Equip a blue mystic hat, bone spear and rune platebody.", SHILO_VILLAGE_BANK, new WorldPoint(2851, 2954, 0), BLOW_KISS, item(MYSTIC_HAT), item(BONE_SPEAR), item(RUNE_PLATEBODY)), + new EmoteClue("Blow a kiss in the heart of the lava maze. Equip black dragonhide chaps, a spotted cape and a rolling pin.", NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE, new WorldPoint(3069, 3861, 0), BLOW_KISS, item(BLACK_DHIDE_CHAPS), any("Spotted cape", item(SPOTTED_CAPE), item(SPOTTED_CAPE_10073)), item(ROLLING_PIN)), + new EmoteClue("Blow a kiss outside K'ril Tsutsaroth's chamber. Beware of double agents! Equip a zamorak full helm and the shadow sword.", OUTSIDE_KRIL_TSUTSAROTHS_ROOM, new WorldPoint(2925, 5333, 0), BLOW_KISS, item(ZAMORAK_FULL_HELM), item(SHADOW_SWORD)), + new EmoteClue("Cheer at the Druids' Circle. Equip a blue wizard hat, a bronze two-handed sword and HAM boots.", TAVERLEY_STONE_CIRCLE, new WorldPoint(2924, 3478, 0), CHEER, item(BLUE_WIZARD_HAT), item(BRONZE_2H_SWORD), item(HAM_BOOTS)), + new EmoteClue("Cheer in the Edgeville general store. Dance before you talk to me. Equip a brown apron, leather boots and leather gloves.", NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE, new WorldPoint(3080, 3509, 0), CHEER, DANCE, item(BROWN_APRON), item(LEATHER_BOOTS), item(LEATHER_GLOVES)), + new EmoteClue("Cheer in the Ogre Pen in the Training Camp. Show you are angry before you talk to me. Equip a green dragonhide body and chaps and a steel square shield.", OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP, new WorldPoint(2527, 3375, 0), CHEER, ANGRY, item(GREEN_DHIDE_BODY), item(GREEN_DHIDE_CHAPS), item(STEEL_SQ_SHIELD)), + new EmoteClue("Cheer in the Entrana church. Beware of double agents! Equip a full set of black dragonhide armour.", ENTRANA_CHAPEL, new WorldPoint(2852, 3349, 0), CHEER, item(BLACK_DHIDE_VAMB), item(BLACK_DHIDE_CHAPS), item(BLACK_DHIDE_BODY)), + new EmoteClue("Cheer for the monks at Port Sarim. Equip a coif, steel plateskirt and a sapphire necklace.", NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM, new WorldPoint(3047, 3237, 0), CHEER, item(COIF), item(STEEL_PLATESKIRT), item(SAPPHIRE_NECKLACE)), + new EmoteClue("Clap in the main exam room in the Exam Centre. Equip a white apron, green gnome boots and leather gloves.", INSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3361, 3339, 0), CLAP, item(WHITE_APRON), item(GREEN_BOOTS), item(LEATHER_GLOVES)), + new EmoteClue("Clap on the causeway to the Wizards' Tower. Equip an iron medium helmet, emerald ring and a white apron.", ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER, new WorldPoint(3113, 3196, 0), CLAP, item(IRON_MED_HELM), item(EMERALD_RING), item(WHITE_APRON)), + new EmoteClue("Clap on the top level of the mill, north of East Ardougne. Equip a blue gnome robe top, HAM robe bottom and an unenchanted tiara.", UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL, new WorldPoint(2635, 3385, 3), CLAP, item(BLUE_ROBE_TOP), item(HAM_ROBE), item(TIARA)), + new EmoteClue("Clap in Seers court house. Spin before you talk to me. Equip an adamant halberd, blue mystic robe bottom and a diamond ring.", OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE, new WorldPoint(2735, 3469, 0), CLAP, SPIN, item(ADAMANT_HALBERD), item(MYSTIC_ROBE_BOTTOM), item(DIAMOND_RING)), + new EmoteClue("Clap in the magic axe hut. Beware of double agents! Equip only some flared trousers.", OUTSIDE_THE_WILDERNESS_AXE_HUT, new WorldPoint(3191, 3960, 0), CLAP, item(FLARED_TROUSERS), item(LOCKPICK), emptySlot("Nothing else", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, GLOVES, BOOTS, RING, AMMO)), + new EmoteClue("Clap your hands north of Mount Karuulm Spin before you talk to me. Equip an adamant warhammer, a ring of life and a pair of mithril boots.", NORTH_OF_MOUNT_KARUULM, new WorldPoint(1306, 3839, 0), CLAP, SPIN, item(ADAMANT_WARHAMMER), item(RING_OF_LIFE), item(MITHRIL_BOOTS)), + new EmoteClue("Cry in the Catherby Ranging shop. Bow before you talk to me. Equip blue gnome boots, a hard leather body and an unblessed silver sickle.", HICKTONS_ARCHERY_EMPORIUM, new WorldPoint(2823, 3443, 0), CRY, BOW, item(BLUE_BOOTS), item(HARDLEATHER_BODY), item(SILVER_SICKLE)), + new EmoteClue("Cry on the shore of Catherby beach. Laugh before you talk to me, equip an adamant sq shield, a bone dagger and mithril platebody.", OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY, new WorldPoint(2852, 3429, 0), CRY, LAUGH, item(ADAMANT_SQ_SHIELD), item(BONE_DAGGER), item(MITHRIL_PLATEBODY)), + new EmoteClue("Cry on top of the western tree in the Gnome Agility Arena. Indicate 'no' before you talk to me. Equip a steel kiteshield, ring of forging and green dragonhide chaps.", GNOME_STRONGHOLD_BALANCING_ROPE, new WorldPoint(2473, 3420, 2), CRY, NO, item(STEEL_KITESHIELD), item(RING_OF_FORGING), item(GREEN_DHIDE_CHAPS)), + new EmoteClue("Cry in the TzHaar gem store. Beware of double agents! Equip a fire cape and TokTz-Xil-Ul.", TZHAAR_GEM_STORE, new WorldPoint(2463, 5149, 0), CRY, any("Fire cape", item(FIRE_CAPE), item(FIRE_MAX_CAPE)), item(TOKTZXILUL)), + new EmoteClue("Cry in the Draynor Village jail. Jump for joy before you talk to me. Equip an adamant sword, a sapphire amulet and an adamant plateskirt.", OUTSIDE_DRAYNOR_VILLAGE_JAIL, new WorldPoint(3128, 3245, 0), CRY, JUMP_FOR_JOY, item(ADAMANT_SWORD), item(SAPPHIRE_AMULET), item(ADAMANT_PLATESKIRT)), + new EmoteClue("Dance at the crossroads north of Draynor. Equip an iron chain body, a sapphire ring and a longbow.", CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE, new WorldPoint(3109, 3294, 0), DANCE, item(IRON_CHAINBODY), item(SAPPHIRE_RING), item(LONGBOW)), + new EmoteClue("Dance in the Party Room. Equip a steel full helmet, steel platebody and an iron plateskirt.", OUTSIDE_THE_FALADOR_PARTY_ROOM, new WorldPoint(3045, 3376, 0), DANCE, item(STEEL_FULL_HELM), item(STEEL_PLATEBODY), item(IRON_PLATESKIRT)), + new EmoteClue("Dance in the shack in Lumbridge Swamp. Equip a bronze dagger, iron full helmet and a gold ring.", NEAR_A_SHED_IN_LUMBRIDGE_SWAMP, new WorldPoint(3203, 3169, 0), DANCE, item(BRONZE_DAGGER), item(IRON_FULL_HELM), item(GOLD_RING)), + new EmoteClue("Dance in the dark caves beneath Lumbridge Swamp. Blow a kiss before you talk to me. Equip an air staff, Bronze full helm and an amulet of power.", LUMBRIDGE_SWAMP_CAVES, new WorldPoint(3168, 9571, 0), DANCE, BLOW_KISS, item(STAFF_OF_AIR), item(BRONZE_FULL_HELM), item(AMULET_OF_POWER)), + new EmoteClue("Dance at the cat-doored pyramid in Sophanem. Beware of double agents! Equip a ring of life, an uncharged amulet of glory and an adamant two-handed sword.", OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM, new WorldPoint(3294, 2781, 0), DANCE, item(RING_OF_LIFE), item(AMULET_OF_GLORY), item(ADAMANT_2H_SWORD)), + new EmoteClue("Dance in the centre of Canifis. Bow before you talk to me. Equip a green gnome robe top, mithril plate legs and an iron two-handed sword.", CENTRE_OF_CANIFIS, new WorldPoint(3492, 3488, 0), DANCE, BOW, item(GREEN_ROBE_TOP), item(MITHRIL_PLATELEGS), item(IRON_2H_SWORD)), + new EmoteClue("Dance in the King Black Dragon's lair. Beware of double agents! Equip a black dragonhide body, black dragonhide vambs and a black dragon mask.", KING_BLACK_DRAGONS_LAIR, new WorldPoint(2271, 4680, 0), DANCE, item(BLACK_DHIDE_BODY), item(BLACK_DHIDE_VAMB), item(BLACK_DRAGON_MASK)), + new EmoteClue("Dance at the entrance to the Grand Exchange. Equip a pink skirt, pink robe top and a body tiara.", SOUTH_OF_THE_GRAND_EXCHANGE, new WorldPoint(3165, 3467, 0), DANCE, item(PINK_SKIRT), item(PINK_ROBE_TOP), item(BODY_TIARA)), + new EmoteClue("Goblin Salute in the Goblin Village. Beware of double agents! Equip a bandos godsword, a bandos cloak and a bandos platebody.", OUTSIDE_MUDKNUCKLES_HUT, new WorldPoint(2956, 3505, 0), GOBLIN_SALUTE, item(BANDOS_PLATEBODY), item(BANDOS_CLOAK), item(BANDOS_GODSWORD)), + new EmoteClue("Headbang in the mine north of Al Kharid. Equip a desert shirt, leather gloves and leather boots.", AL_KHARID_SCORPION_MINE, new WorldPoint(3299, 3289, 0), HEADBANG, item(DESERT_SHIRT), item(LEATHER_GLOVES), item(LEATHER_BOOTS)), + new EmoteClue("Headbang at the exam center. Beware of double agents! Equip a mystic fire staff, a diamond bracelet and rune boots.", OUTSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3362, 3340, 0), HEADBANG, item(MYSTIC_FIRE_STAFF), item(DIAMOND_BRACELET), item(RUNE_BOOTS)), + new EmoteClue("Headbang at the top of Slayer Tower. Equip a seercull, a combat bracelet and helm of Neitiznot.", OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM, new WorldPoint(3421, 3537, 2), HEADBANG, item(SEERCULL), range("Combat bracelet", COMBAT_BRACELET4, COMBAT_BRACELET), item(HELM_OF_NEITIZNOT)), + new EmoteClue("Dance a jig by the entrance to the Fishing Guild. Equip an emerald ring, a sapphire amulet, and a bronze chain body.", OUTSIDE_THE_FISHING_GUILD, new WorldPoint(2610, 3391, 0), JIG, item(EMERALD_RING), item(SAPPHIRE_AMULET), item(BRONZE_CHAINBODY)), + new EmoteClue("Dance a jig under Shantay's Awning. Bow before you talk to me. Equip a pointed blue snail helmet, an air staff and a bronze square shield.", SHANTAY_PASS, new WorldPoint(3304, 3124, 0), JIG, BOW, any("Bruise blue snelm (pointed)", item(BRUISE_BLUE_SNELM_3343)), item(STAFF_OF_AIR), item(BRONZE_SQ_SHIELD)), + new EmoteClue("Do a jig in Varrock's rune store. Equip an air tiara and a staff of water.", AUBURYS_SHOP_IN_VARROCK, new WorldPoint(3253, 3401, 0), JIG, item(AIR_TIARA), item(STAFF_OF_WATER)), + new EmoteClue("Jump for joy at the beehives. Equip a desert shirt, green gnome robe bottoms and a steel axe.", CATHERBY_BEEHIVE_FIELD, new WorldPoint(2759, 3445, 0), JUMP_FOR_JOY, item(DESERT_SHIRT), item(GREEN_ROBE_BOTTOMS), item(STEEL_AXE)), + new EmoteClue("Jump for joy in Yanille bank. Dance a jig before you talk to me. Equip a brown apron, adamantite medium helmet and snakeskin chaps.", OUTSIDE_YANILLE_BANK, new WorldPoint(2610, 3092, 0), JUMP_FOR_JOY, JIG, item(BROWN_APRON), item(ADAMANT_MED_HELM), item(SNAKESKIN_CHAPS)), + new EmoteClue("Jump for joy in the TzHaar sword shop. Shrug before you talk to me. Equip a Steel longsword, Blue D'hide body and blue mystic gloves.", TZHAAR_WEAPONS_STORE, new WorldPoint(2477, 5146, 0), JUMP_FOR_JOY, SHRUG, item(STEEL_LONGSWORD), item(BLUE_DHIDE_BODY), item(MYSTIC_GLOVES)), + new EmoteClue("Jump for joy in the Ancient Cavern. Equip a granite shield, splitbark body and any rune heraldic helm.", ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL, new WorldPoint(1768, 5366, 1), JUMP_FOR_JOY, item(GRANITE_SHIELD), item(SPLITBARK_BODY), range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5)), + new EmoteClue("Jump for joy at the Neitiznot rune rock. Equip Rune boots, a proselyte hauberk and a dragonstone ring.", NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES, new WorldPoint(2375, 3850, 0), JUMP_FOR_JOY, item(RUNE_BOOTS), item(PROSELYTE_HAUBERK), item(DRAGONSTONE_RING)), + new EmoteClue("Jump for joy in the centre of Zul-Andra. Beware of double agents! Equip a dragon 2h sword, bandos boots and an obsidian cape.", NEAR_THE_PIER_IN_ZULANDRA, new WorldPoint(2199, 3056, 0), JUMP_FOR_JOY, item(DRAGON_2H_SWORD), item(BANDOS_BOOTS), item(OBSIDIAN_CAPE)), + new EmoteClue("Laugh by the fountain of heroes. Equip splitbark legs, dragon boots and a Rune longsword.", FOUNTAIN_OF_HEROES, new WorldPoint(2920, 9893, 0), LAUGH, item(SPLITBARK_LEGS), item(DRAGON_BOOTS), item(RUNE_LONGSWORD)), + new EmoteClue("Laugh in Jokul's tent in the Mountain Camp. Beware of double agents! Equip a rune full helmet, blue dragonhide chaps and a fire battlestaff.", MOUNTAIN_CAMP_GOAT_ENCLOSURE, new WorldPoint(2812, 3681, 0), LAUGH, item(RUNE_FULL_HELM), item(BLUE_DHIDE_CHAPS), item(FIRE_BATTLESTAFF)), + new EmoteClue("Laugh at the crossroads south of the Sinclair Mansion. Equip a cowl, a blue wizard robe top and an iron scimitar.", ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION, new WorldPoint(2741, 3536, 0), LAUGH, item(LEATHER_COWL), item(BLUE_WIZARD_ROBE), item(IRON_SCIMITAR)), + new EmoteClue("Laugh in front of the gem store in Ardougne market. Equip a Castlewars bracelet, a dragonstone amulet and a ring of forging.", NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET, new WorldPoint(2666, 3304, 0), LAUGH, any("Castle wars bracelet", range(CASTLE_WARS_BRACELET3, CASTLE_WARS_BRACELET1)), item(DRAGONSTONE_AMULET), item(RING_OF_FORGING)), + new EmoteClue("Panic in the Limestone Mine. Equip bronze platelegs, a steel pickaxe and a steel medium helmet.", LIMESTONE_MINE, new WorldPoint(3372, 3498, 0), PANIC, item(BRONZE_PLATELEGS), item(STEEL_PICKAXE), item(STEEL_MED_HELM)), + new EmoteClue("Panic by the mausoleum in Morytania. Wave before you speak to me. Equip a mithril plate skirt, a maple longbow and no boots.", MAUSOLEUM_OFF_THE_MORYTANIA_COAST, new WorldPoint(3504, 3576, 0), PANIC, WAVE, item(MITHRIL_PLATESKIRT), item(MAPLE_LONGBOW), emptySlot("No boots", BOOTS)), + new EmoteClue("Panic on the Wilderness volcano bridge. Beware of double agents! Equip any headband and crozier.", VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS, new WorldPoint(3368, 3935, 0), PANIC, any("Any headband", range(RED_HEADBAND, BROWN_HEADBAND), range(WHITE_HEADBAND, GREEN_HEADBAND)), any("Any crozier", item(ANCIENT_CROZIER), item(ARMADYL_CROZIER), item(BANDOS_CROZIER), range(SARADOMIN_CROZIER, ZAMORAK_CROZIER))), + new EmoteClue("Panic by the pilot on White Wolf Mountain. Beware of double agents! Equip mithril platelegs, a ring of life and a rune axe.", GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN, new WorldPoint(2847, 3499, 0), PANIC, item(MITHRIL_PLATELEGS), item(RING_OF_LIFE), item(RUNE_AXE)), + new EmoteClue("Panic by the big egg where no one dare goes and the ground is burnt. Beware of double agents! Equip a dragon med helm, a TokTz-Ket-Xil, a brine sabre, rune platebody and an uncharged amulet of glory.", SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE, new WorldPoint(3227, 3831, 0), PANIC, item(DRAGON_MED_HELM), item(TOKTZKETXIL), item(BRINE_SABRE), item(RUNE_PLATEBODY), item(AMULET_OF_GLORY)), + new EmoteClue("Panic at the area flowers meet snow. Equip Blue D'hide vambs, a dragon spear and a rune plateskirt.", HALFWAY_DOWN_TROLLWEISS_MOUNTAIN, new WorldPoint(2776, 3781, 0), PANIC, item(BLUE_DHIDE_VAMB), item(DRAGON_SPEAR), item(RUNE_PLATESKIRT), item(SLED_4084)), + new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), + new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), + new EmoteClue("Blow a raspberry at the monkey cage in Ardougne Zoo. Equip a studded leather body, bronze platelegs and a normal staff with no orb.", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)), + new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)), + new EmoteClue("Blow a raspberry in the Fishing Guild bank. Beware of double agents! Equip an elemental shield, blue dragonhide chaps and a rune warhammer.", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)), + new EmoteClue("Salute in the banana plantation. Beware of double agents! Equip a diamond ring, amulet of power, and nothing on your chest and legs.", WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION, new WorldPoint(2914, 3168, 0), SALUTE, item(DIAMOND_RING), item(AMULET_OF_POWER), emptySlot("Nothing on chest & legs", BODY, LEGS)), + new EmoteClue("Salute in the Warriors' guild bank. Equip only a black salamander.", WARRIORS_GUILD_BANK, new WorldPoint(2844, 3542, 0), SALUTE, item(BLACK_SALAMANDER), emptySlot("Nothing else", HEAD, CAPE, AMULET, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), + new EmoteClue("Salute in the centre of the mess hall. Beware of double agents! Equip a rune halberd rune platebody, and an amulet of strength.", HOSIDIUS_MESS, new WorldPoint(1646, 3632, 0), SALUTE, item(RUNE_HALBERD), item(RUNE_PLATEBODY), item(AMULET_OF_STRENGTH)), + new EmoteClue("Shrug in the mine near Rimmington. Equip a gold necklace, a gold ring and a bronze spear.", RIMMINGTON_MINE, new WorldPoint(2976, 3238, 0), SHRUG, item(GOLD_NECKLACE), item(GOLD_RING), item(BRONZE_SPEAR)), + new EmoteClue("Shrug in Catherby bank. Yawn before you talk to me. Equip a maple longbow, green d'hide chaps and an iron med helm.", OUTSIDE_CATHERBY_BANK, new WorldPoint(2808, 3440, 0), SHRUG, YAWN, item(MAPLE_LONGBOW), item(GREEN_DHIDE_CHAPS), item(IRON_MED_HELM)), + new EmoteClue("Shrug in the Zamorak temple found in the Eastern Wilderness. Beware of double agents! Equip rune platelegs, an iron platebody and blue dragonhide vambraces.", CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS, new WorldPoint(3239, 3611, 0), SHRUG, item(RUNE_PLATELEGS), item(IRON_PLATEBODY), item(BLUE_DHIDE_VAMB)), + new EmoteClue("Shrug in the Shayzien command tent. Equip a blue mystic robe bottom, a rune kiteshield and any bob shirt.", SHAYZIEN_WAR_TENT, new WorldPoint(1555, 3537, 0), SHRUG, item(MYSTIC_ROBE_BOTTOM), item(RUNE_KITESHIELD), range("Any bob shirt", BOBS_RED_SHIRT, BOBS_PURPLE_SHIRT)), + new EmoteClue("Slap your head in the centre of the Kourend catacombs. Beware of double agents! Equip the arclight and the amulet of the damned.", CENTRE_OF_THE_CATACOMBS_OF_KOUREND, new WorldPoint(1663, 10045, 0), SLAP_HEAD, item(ARCLIGHT), any("Amulet of the damned", item(AMULET_OF_THE_DAMNED), item(AMULET_OF_THE_DAMNED_FULL))), + new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", ROAD_JUNCTION_NORTH_OF_RIMMINGTON, new WorldPoint(2981, 3276, 0), SPIN, item(GREEN_HAT), item(CREAM_ROBE_TOP), item(LEATHER_CHAPS)), + new EmoteClue("Spin in Draynor Manor by the fountain. Equip an iron platebody, studded leather chaps and a bronze full helmet.", DRAYNOR_MANOR_BY_THE_FOUNTAIN, new WorldPoint(3088, 3336, 0), SPIN, item(IRON_PLATEBODY), item(STUDDED_CHAPS), item(BRONZE_FULL_HELM)), + new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), + new EmoteClue("Spin in the Varrock Castle courtyard. Equip a black axe, a coif and a ruby ring.", OUTSIDE_VARROCK_PALACE_COURTYARD, new WorldPoint(3213, 3463, 0), SPIN, item(BLACK_AXE), item(COIF), item(RUBY_RING)), + new EmoteClue("Spin in West Ardougne Church. Equip a dragon spear and red dragonhide chaps.", CHAPEL_IN_WEST_ARDOUGNE, new WorldPoint(2530, 3290, 0), SPIN, item(DRAGON_SPEAR), item(RED_DHIDE_CHAPS)), + new EmoteClue("Spin on the bridge by the Barbarian Village. Salute before you talk to me. Equip purple gloves, a steel kiteshield and a mithril full helmet.", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)), + new EmoteClue("Stamp in the Enchanted valley west of the waterfall. Beware of double agents! Equip a dragon axe.", NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY, new WorldPoint(3030, 4522, 0), STOMP, item(DRAGON_AXE)), + new EmoteClue("Think in middle of the wheat field by the Lumbridge mill. Equip a blue gnome robetop, a turquoise gnome robe bottom and an oak shortbow.", WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL, new WorldPoint(3159, 3298, 0), THINK, item(BLUE_ROBE_TOP), item(TURQUOISE_ROBE_BOTTOMS), item(OAK_SHORTBOW)), + new EmoteClue("Think in the centre of the Observatory. Spin before you talk to me. Equip a mithril chain body, green dragonhide chaps and a ruby amulet.", OBSERVATORY, new WorldPoint(2439, 3161, 0), THINK, SPIN, item(MITHRIL_CHAINBODY), item(GREEN_DHIDE_CHAPS), item(RUBY_AMULET)), + new EmoteClue("Wave along the south fence of the Lumber Yard. Equip a hard leather body, leather chaps and a bronze axe.", NEAR_THE_SAWMILL_OPERATORS_BOOTH, new WorldPoint(3307, 3491, 0), WAVE, item(HARDLEATHER_BODY), item(LEATHER_CHAPS), item(BRONZE_AXE)), + new EmoteClue("Wave in the Falador gem store. Equip a Mithril pickaxe, Black platebody and an Iron Kiteshield.", NEAR_HERQUINS_SHOP_IN_FALADOR, new WorldPoint(2945, 3335, 0), WAVE, item(MITHRIL_PICKAXE), item(BLACK_PLATEBODY), item(IRON_KITESHIELD)), + new EmoteClue("Wave on Mudskipper Point. Equip a black cape, leather chaps and a steel mace.", MUDSKIPPER_POINT, new WorldPoint(2989, 3110, 0), WAVE, item(BLACK_CAPE), item(LEATHER_CHAPS), item(STEEL_MACE)), + new EmoteClue("Wave on the northern wall of Castle Drakan. Beware of double agents! Wear a dragon sq shield, splitbark body and any boater.", NORTHERN_WALL_OF_CASTLE_DRAKAN, new WorldPoint(3560, 3385, 0), WAVE, item(DRAGON_SQ_SHIELD), item(SPLITBARK_BODY), any("Any boater", item(RED_BOATER), item(ORANGE_BOATER), item(GREEN_BOATER), item(BLUE_BOATER), item(BLACK_BOATER), item(PINK_BOATER), item(PURPLE_BOATER), item(WHITE_BOATER))), + new EmoteClue("Yawn in the 7th room of Pyramid Plunder. Beware of double agents! Equip a pharaoh sceptre and a full set of menaphite robes.", _7TH_CHAMBER_OF_JALSAVRAH, new WorldPoint(1944, 4427, 0), YAWN, any("Pharaoh's sceptre", item(PHARAOHS_SCEPTRE), item(PHARAOHS_SCEPTRE_1), item(PHARAOHS_SCEPTRE_2), item(PHARAOHS_SCEPTRE_3), item(PHARAOHS_SCEPTRE_4), item(PHARAOHS_SCEPTRE_5), item(PHARAOHS_SCEPTRE_6), item(PHARAOHS_SCEPTRE_7), item(PHARAOHS_SCEPTRE_8)), any("Full set of menaphite robes", all(item(MENAPHITE_PURPLE_HAT), item(MENAPHITE_PURPLE_TOP), range(MENAPHITE_PURPLE_ROBE, MENAPHITE_PURPLE_KILT)), all(item(MENAPHITE_RED_HAT), item(MENAPHITE_RED_TOP), range(MENAPHITE_RED_ROBE, MENAPHITE_RED_KILT)))), + new EmoteClue("Yawn in the Varrock library. Equip a green gnome robe top, HAM robe bottom and an iron warhammer.", VARROCK_PALACE_LIBRARY, new WorldPoint(3209, 3492, 0), YAWN, item(GREEN_ROBE_TOP), item(HAM_ROBE), item(IRON_WARHAMMER)), + new EmoteClue("Yawn in Draynor Marketplace. Equip studded leather chaps, an iron kiteshield and a steel longsword.", DRAYNOR_VILLAGE_MARKET, new WorldPoint(3083, 3253, 0), YAWN, item(STUDDED_CHAPS), item(IRON_KITESHIELD), item(STEEL_LONGSWORD)), + new EmoteClue("Yawn in the Castle Wars lobby. Shrug before you talk to me. Equip a ruby amulet, a mithril scimitar and a Wilderness cape.", CASTLE_WARS_BANK, new WorldPoint(2440, 3092, 0), YAWN, SHRUG, item(RUBY_AMULET), item(MITHRIL_SCIMITAR), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)), + new EmoteClue("Yawn in the rogues' general store. Beware of double agents! Equip an adamant square shield, blue dragon vambraces and a rune pickaxe.", NOTERAZZOS_SHOP_IN_THE_WILDERNESS, new WorldPoint(3026, 3701, 0), YAWN, item(ADAMANT_SQ_SHIELD), item(BLUE_DHIDE_VAMB), item(RUNE_PICKAXE)), + new EmoteClue("Yawn at the top of Trollheim. Equip a lava battlestaff, black dragonhide vambraces and a mind shield.", ON_TOP_OF_TROLLHEIM_MOUNTAIN, new WorldPoint(2887, 3676, 0), YAWN, item(LAVA_BATTLESTAFF), item(BLACK_DHIDE_VAMB), item(MIND_SHIELD)), + new EmoteClue("Yawn in the centre of Arceuus library. Nod your head before you talk to me. Equip blue dragonhide vambraces, adamant boots and an adamant dagger.", ENTRANCE_OF_THE_ARCEUUS_LIBRARY, new WorldPoint(1632, 3807, 0), YAWN, YES, item(BLUE_DHIDE_VAMB), item(ADAMANT_BOOTS), item(ADAMANT_DAGGER)), + new EmoteClue("Swing a bullroarer at the top of the watchtower. Beware of double agents! Equip a dragon plateskirt, climbing boots and a dragon chainbody.", TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER, new WorldPoint(2932, 4712, 0), BULL_ROARER, item(DRAGON_PLATESKIRT), item(CLIMBING_BOOTS), item(DRAGON_CHAINBODY_3140), item(ItemID.BULL_ROARER)), + new EmoteClue("Blow a raspberry at Gypsy Aris in her tent. Equip a gold ring and a gold necklace.", GYPSY_TENT_ENTRANCE, new WorldPoint(3203, 3424, 0), RASPBERRY, item(GOLD_RING), item(GOLD_NECKLACE)), + new EmoteClue("Bow to Brugsen Bursen at the Grand Exchange.", null, new WorldPoint(3164, 3477, 0), BOW), + new EmoteClue("Cheer at Iffie Nitter. Equip a chef hat and a red cape.", FINE_CLOTHES_ENTRANCE, new WorldPoint(3205, 3416, 0), CHEER, item(CHEFS_HAT), item(RED_CAPE)), + new EmoteClue("Clap at Bob's Brilliant Axes. Equip a bronze axe and leather boots.", BOB_AXES_ENTRANCE, new WorldPoint(3231, 3203, 0), CLAP, item(BRONZE_AXE), item(LEATHER_BOOTS)), + new EmoteClue("Panic at Al Kharid mine.", null, new WorldPoint(3300, 3314, 0), PANIC), + new EmoteClue("Spin at Flynn's Mace Shop.", null, new WorldPoint(2950, 3387, 0), SPIN)); + + private static SingleItemRequirement item(int itemId) + { + return new SingleItemRequirement(itemId); + } + + private static RangeItemRequirement range(int startItemId, int endItemId) + { + return range(null, startItemId, endItemId); + } + + private static RangeItemRequirement range(String name, int startItemId, int endItemId) + { + return new RangeItemRequirement(name, startItemId, endItemId); + } + + private static AnyRequirementCollection any(String name, ItemRequirement... requirements) + { + return new AnyRequirementCollection(name, requirements); + } + + private static AllRequirementsCollection all(ItemRequirement... requirements) + { + return new AllRequirementsCollection(requirements); + } + + private static SlotLimitationRequirement emptySlot(String description, EquipmentInventorySlot... slots) + { + return new SlotLimitationRequirement(description, slots); + } + + private final String text; + private final Integer stashUnit; + private final WorldPoint location; + private final Emote firstEmote; + private final Emote secondEmote; + @Nonnull + private final ItemRequirement[] itemRequirements; + + private EmoteClue(String text, Integer stashUnit, WorldPoint location, Emote firstEmote, @Nonnull ItemRequirement... itemRequirements) + { + this(text, stashUnit, location, firstEmote, null, itemRequirements); + } + + private EmoteClue(String text, Integer stashUnit, WorldPoint location, Emote firstEmote, Emote secondEmote, @Nonnull ItemRequirement... itemRequirements) + { + this.text = text; + this.stashUnit = stashUnit; + this.location = location; + this.firstEmote = firstEmote; + this.secondEmote = secondEmote; + this.itemRequirements = itemRequirements; + } + + @Override + public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) + { + panelComponent.getChildren().add(TitleComponent.builder().text("Emote Clue").build()); + panelComponent.getChildren().add(LineComponent.builder().left("Emotes:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(getFirstEmote().getName()) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + + if (getSecondEmote() != null) + { + panelComponent.getChildren().add(LineComponent.builder() + .left(getSecondEmote().getName()) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + } + + if (itemRequirements.length > 0) + { + panelComponent.getChildren().add(LineComponent.builder().left("Equip:").build()); + + Item[] equipment = plugin.getEquippedItems(); + Item[] inventory = plugin.getInventoryItems(); + + // If equipment is null, the player is wearing nothing + if (equipment == null) + { + equipment = new Item[0]; + } + + // If inventory is null, the player has nothing in their inventory + if (inventory == null) + { + inventory = new Item[0]; + } + + Item[] combined = new Item[equipment.length + inventory.length]; + System.arraycopy(equipment, 0, combined, 0, equipment.length); + System.arraycopy(inventory, 0, combined, equipment.length, inventory.length); + + for (ItemRequirement requirement : itemRequirements) + { + boolean equipmentFulfilled = requirement.fulfilledBy(equipment); + boolean combinedFulfilled = requirement.fulfilledBy(combined); + + panelComponent.getChildren().add(LineComponent.builder() + .left(requirement.getCollectiveName(plugin.getClient())) + .leftColor(TITLED_CONTENT_COLOR) + .right(combinedFulfilled ? "\u2713" : "\u2717") + .rightColor(equipmentFulfilled ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED)) + .build()); + } + } + } + + @Override + public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) + { + LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation()); + + if (localLocation == null) + { + return; + } + + OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getEmoteImage(), Color.ORANGE); + } + + public static EmoteClue forText(String text) + { + for (EmoteClue clue : CLUES) + { + if (clue.getText().equalsIgnoreCase(text)) + { + return clue; + } + } + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java index 68ad2e0af8..00162a541f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java @@ -184,7 +184,7 @@ public class FaloTheBardClue extends ClueScroll implements TextClueScroll, NpcCl @Override public String[] getNpcs() { - return new String[] {FALO_THE_BARD}; + return new String[]{FALO_THE_BARD}; } public static FaloTheBardClue forText(String text) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/HotColdClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/HotColdClue.java index 826017744f..af5deae6cf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/HotColdClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/HotColdClue.java @@ -1,411 +1,411 @@ -/* - * Copyright (c) 2018, Eadgars Ruse - * 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.cluescrolls.clues; - -import com.google.common.collect.Lists; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.Getter; -import net.runelite.api.NPC; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; -import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; -import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdArea; -import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -@Getter -public class HotColdClue extends ClueScroll implements LocationClueScroll, LocationsClueScroll, TextClueScroll, NpcClueScroll -{ - private static final Pattern INITIAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*)"); - private static final Pattern STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*), (.*) last time\\."); - private static final Pattern FINAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is visibly shaking.*"); - private static final HotColdClue CLUE = - new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Jorral may have a clue.", - "Jorral", - "Speak to Jorral to receive a strange device."); - - // list of potential places to dig - private List digLocations = new ArrayList<>(); - private final String text; - private final String npc; - private final String solution; - private WorldPoint location; - private WorldPoint lastWorldPoint; - - public static HotColdClue forText(String text) - { - if (CLUE.text.equalsIgnoreCase(text)) - { - return CLUE; - } - - return null; - } - - private HotColdClue(String text, String npc, String solution) - { - this.text = text; - this.npc = npc; - this.solution = solution; - setRequiresSpade(true); - } - - @Override - public WorldPoint[] getLocations() - { - return Lists.transform(digLocations, HotColdLocation::getWorldPoint).toArray(new WorldPoint[0]); - } - - @Override - public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) - { - panelComponent.getChildren().add(TitleComponent.builder() - .text("Hot/Cold Clue") - .build()); - panelComponent.setPreferredSize(new Dimension(200, 0)); - - // strange device has not been tested yet, show how to get it - if (lastWorldPoint == null && location == null) - { - if (getNpc() != null) - { - panelComponent.getChildren().add(LineComponent.builder() - .left("NPC:") - .build()); - panelComponent.getChildren().add(LineComponent.builder() - .left(getNpc()) - .leftColor(TITLED_CONTENT_COLOR) - .build()); - } - - panelComponent.getChildren().add(LineComponent.builder() - .left("Solution:") - .build()); - panelComponent.getChildren().add(LineComponent.builder() - .left(getSolution()) - .leftColor(TITLED_CONTENT_COLOR) - .build()); - } - // strange device has been tested, show possible locations for final dig spot - else - { - panelComponent.getChildren().add(LineComponent.builder() - .left("Possible areas:") - .build()); - Map locationCounts = new HashMap<>(); - - for (HotColdLocation hotColdLocation : digLocations) - { - HotColdArea hotColdArea = hotColdLocation.getHotColdArea(); - - if (locationCounts.containsKey(hotColdArea)) - { - locationCounts.put(hotColdArea, locationCounts.get(hotColdArea) + 1); - } - else - { - locationCounts.put(hotColdArea, 1); - } - } - - if (digLocations.size() > 10) - { - for (HotColdArea area : locationCounts.keySet()) - { - panelComponent.getChildren().add(LineComponent.builder() - .left(area.getName()) - .right(Integer.toString(locationCounts.get(area))) - .build()); - } - } - else - { - for (HotColdArea s : locationCounts.keySet()) - { - panelComponent.getChildren().add(LineComponent.builder() - .left(s.getName() + ":") - .build()); - - for (HotColdLocation hotColdLocation : digLocations) - { - if (hotColdLocation.getHotColdArea() == s) - { - Rectangle2D r = hotColdLocation.getRect(); - panelComponent.getChildren().add(LineComponent.builder() - .left("- " + hotColdLocation.getArea()) - .leftColor(Color.LIGHT_GRAY) - .build()); - } - } - } - } - } - } - - @Override - public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) - { - // when final location has been found - if (this.location != null) - { - LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation()); - - if (localLocation != null) - { - OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getSpadeImage(), Color.ORANGE); - } - - return; - } - - // when strange device hasn't been activated yet, show Jorral - if (lastWorldPoint == null) - { - // Mark NPC - if (plugin.getNpcsToMark() != null) - { - for (NPC npc : plugin.getNpcsToMark()) - { - OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET); - } - } - } - - // once the number of possible dig locations is below 10, show the dig spots - if (digLocations.size() < 10) - { - // Mark potential dig locations - for (HotColdLocation hotColdLocation : digLocations) - { - WorldPoint wp = hotColdLocation.getWorldPoint(); - LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), wp.getX(), wp.getY()); - - if (localLocation == null) - { - return; - } - - OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getSpadeImage(), Color.ORANGE); - } - } - } - - public boolean update(final String message, final ClueScrollPlugin plugin) - { - if (!message.startsWith("The device is")) - { - return false; - } - - Matcher m1 = FINAL_STRANGE_DEVICE_MESSAGE.matcher(message); - Matcher m2 = STRANGE_DEVICE_MESSAGE.matcher(message); - Matcher m3 = INITIAL_STRANGE_DEVICE_MESSAGE.matcher(message); - - // the order that these pattern matchers are checked is important - if (m1.find()) - { - // final location for hot cold clue has been found - WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation(); - - if (localWorld != null) - { - markFinalSpot(localWorld); - return true; - } - } - else if (m2.find()) - { - String temperature = m2.group(1); - String difference = m2.group(2); - WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation(); - - if (localWorld != null) - { - updatePossibleArea(localWorld, temperature, difference); - return true; - } - } - else if (m3.find()) - { - String temperature = m3.group(1); - WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation(); - - if (localWorld != null) - { - updatePossibleArea(localWorld, temperature, ""); - return true; - } - } - - return false; - } - - @Override - public void reset() - { - this.lastWorldPoint = null; - digLocations.clear(); - } - - private void updatePossibleArea(WorldPoint currentWp, String temperature, String difference) - { - this.location = null; - - if (digLocations.isEmpty()) - { - digLocations.addAll(Arrays.asList(HotColdLocation.values())); - } - - int maxSquaresAway = 5000; - int minSquaresAway = 0; - - switch (temperature) - { - // when the strange device reads a temperature, that means that the center of the final dig location - // is a range of squares away from the player's current location (Chebyshev AKA Chess-board distance) - case "ice cold": - maxSquaresAway = 5000; - minSquaresAway = 500; - break; - case "very cold": - maxSquaresAway = 499; - minSquaresAway = 200; - break; - case "cold": - maxSquaresAway = 199; - minSquaresAway = 150; - break; - case "warm": - maxSquaresAway = 149; - minSquaresAway = 100; - break; - case "hot": - maxSquaresAway = 99; - minSquaresAway = 70; - break; - case "very hot": - maxSquaresAway = 69; - minSquaresAway = 30; - break; - case "incredibly hot": - maxSquaresAway = 29; - minSquaresAway = 5; - break; - } - - // rectangle r1 encompasses all of the points that are within the max possible distance from the player - Point p1 = new Point(currentWp.getX() - maxSquaresAway, currentWp.getY() - maxSquaresAway); - Rectangle r1 = new Rectangle((int) p1.getX(), (int) p1.getY(), 2 * maxSquaresAway + 1, 2 * maxSquaresAway + 1); - // rectangle r2 encompasses all of the points that are within the min possible distance from the player - Point p2 = new Point(currentWp.getX() - minSquaresAway, currentWp.getY() - minSquaresAway); - Rectangle r2 = new Rectangle((int) p2.getX(), (int) p2.getY(), 2 * minSquaresAway + 1, 2 * minSquaresAway + 1); - - // eliminate from consideration dig spots that lie entirely within the min range or entirely outside of the max range - digLocations.removeIf(entry -> r2.contains(entry.getRect()) || !r1.intersects(entry.getRect())); - - // if a previous world point has been recorded, we can consider the warmer/colder result from the strange device - if (lastWorldPoint != null) - { - switch (difference) - { - case "but colder than": - // eliminate spots that are absolutely warmer - digLocations.removeIf(entry -> isFirstPointCloserRect(currentWp, lastWorldPoint, entry.getRect())); - break; - case "and warmer than": - // eliminate spots that are absolutely colder - digLocations.removeIf(entry -> isFirstPointCloserRect(lastWorldPoint, currentWp, entry.getRect())); - break; - case "and the same temperature as": - // I couldn't figure out a clean implementation for this case - // not necessary for quickly determining final location - } - } - - lastWorldPoint = currentWp; - } - - private boolean isFirstPointCloserRect(WorldPoint firstWp, WorldPoint secondWp, Rectangle2D r) - { - WorldPoint p1 = new WorldPoint((int) r.getMaxX(), (int) r.getMaxY(), 0); - - if (!isFirstPointCloser(firstWp, secondWp, p1)) - { - return false; - } - - WorldPoint p2 = new WorldPoint((int) r.getMaxX(), (int) r.getMinY(), 0); - - if (!isFirstPointCloser(firstWp, secondWp, p2)) - { - return false; - } - - WorldPoint p3 = new WorldPoint((int) r.getMinX(), (int)r.getMaxY(), 0); - - if (!isFirstPointCloser(firstWp, secondWp, p3)) - { - return false; - } - - WorldPoint p4 = new WorldPoint((int) r.getMinX(), (int) r.getMinY(), 0); - return (isFirstPointCloser(firstWp, secondWp, p4)); - } - - private boolean isFirstPointCloser(WorldPoint firstWp, WorldPoint secondWp, WorldPoint wp) - { - int firstDistance = firstWp.distanceTo2D(wp); - int secondDistance = secondWp.distanceTo2D(wp); - return (firstDistance < secondDistance); - } - - private void markFinalSpot(WorldPoint wp) - { - this.location = wp; - reset(); - } - - public String[] getNpcs() - { - return new String[] {npc}; - } +/* + * Copyright (c) 2018, Eadgars Ruse + * 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.cluescrolls.clues; + +import com.google.common.collect.Lists; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.Getter; +import net.runelite.api.NPC; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; +import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; +import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdArea; +import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +@Getter +public class HotColdClue extends ClueScroll implements LocationClueScroll, LocationsClueScroll, TextClueScroll, NpcClueScroll +{ + private static final Pattern INITIAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*)"); + private static final Pattern STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*), (.*) last time\\."); + private static final Pattern FINAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is visibly shaking.*"); + private static final HotColdClue CLUE = + new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Jorral may have a clue.", + "Jorral", + "Speak to Jorral to receive a strange device."); + + // list of potential places to dig + private List digLocations = new ArrayList<>(); + private final String text; + private final String npc; + private final String solution; + private WorldPoint location; + private WorldPoint lastWorldPoint; + + public static HotColdClue forText(String text) + { + if (CLUE.text.equalsIgnoreCase(text)) + { + return CLUE; + } + + return null; + } + + private HotColdClue(String text, String npc, String solution) + { + this.text = text; + this.npc = npc; + this.solution = solution; + setRequiresSpade(true); + } + + @Override + public WorldPoint[] getLocations() + { + return Lists.transform(digLocations, HotColdLocation::getWorldPoint).toArray(new WorldPoint[0]); + } + + @Override + public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("Hot/Cold Clue") + .build()); + panelComponent.setPreferredSize(new Dimension(200, 0)); + + // strange device has not been tested yet, show how to get it + if (lastWorldPoint == null && location == null) + { + if (getNpc() != null) + { + panelComponent.getChildren().add(LineComponent.builder() + .left("NPC:") + .build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(getNpc()) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + } + + panelComponent.getChildren().add(LineComponent.builder() + .left("Solution:") + .build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(getSolution()) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + } + // strange device has been tested, show possible locations for final dig spot + else + { + panelComponent.getChildren().add(LineComponent.builder() + .left("Possible areas:") + .build()); + Map locationCounts = new HashMap<>(); + + for (HotColdLocation hotColdLocation : digLocations) + { + HotColdArea hotColdArea = hotColdLocation.getHotColdArea(); + + if (locationCounts.containsKey(hotColdArea)) + { + locationCounts.put(hotColdArea, locationCounts.get(hotColdArea) + 1); + } + else + { + locationCounts.put(hotColdArea, 1); + } + } + + if (digLocations.size() > 10) + { + for (HotColdArea area : locationCounts.keySet()) + { + panelComponent.getChildren().add(LineComponent.builder() + .left(area.getName()) + .right(Integer.toString(locationCounts.get(area))) + .build()); + } + } + else + { + for (HotColdArea s : locationCounts.keySet()) + { + panelComponent.getChildren().add(LineComponent.builder() + .left(s.getName() + ":") + .build()); + + for (HotColdLocation hotColdLocation : digLocations) + { + if (hotColdLocation.getHotColdArea() == s) + { + Rectangle2D r = hotColdLocation.getRect(); + panelComponent.getChildren().add(LineComponent.builder() + .left("- " + hotColdLocation.getArea()) + .leftColor(Color.LIGHT_GRAY) + .build()); + } + } + } + } + } + } + + @Override + public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) + { + // when final location has been found + if (this.location != null) + { + LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation()); + + if (localLocation != null) + { + OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getSpadeImage(), Color.ORANGE); + } + + return; + } + + // when strange device hasn't been activated yet, show Jorral + if (lastWorldPoint == null) + { + // Mark NPC + if (plugin.getNpcsToMark() != null) + { + for (NPC npc : plugin.getNpcsToMark()) + { + OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET); + } + } + } + + // once the number of possible dig locations is below 10, show the dig spots + if (digLocations.size() < 10) + { + // Mark potential dig locations + for (HotColdLocation hotColdLocation : digLocations) + { + WorldPoint wp = hotColdLocation.getWorldPoint(); + LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), wp.getX(), wp.getY()); + + if (localLocation == null) + { + return; + } + + OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getSpadeImage(), Color.ORANGE); + } + } + } + + public boolean update(final String message, final ClueScrollPlugin plugin) + { + if (!message.startsWith("The device is")) + { + return false; + } + + Matcher m1 = FINAL_STRANGE_DEVICE_MESSAGE.matcher(message); + Matcher m2 = STRANGE_DEVICE_MESSAGE.matcher(message); + Matcher m3 = INITIAL_STRANGE_DEVICE_MESSAGE.matcher(message); + + // the order that these pattern matchers are checked is important + if (m1.find()) + { + // final location for hot cold clue has been found + WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation(); + + if (localWorld != null) + { + markFinalSpot(localWorld); + return true; + } + } + else if (m2.find()) + { + String temperature = m2.group(1); + String difference = m2.group(2); + WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation(); + + if (localWorld != null) + { + updatePossibleArea(localWorld, temperature, difference); + return true; + } + } + else if (m3.find()) + { + String temperature = m3.group(1); + WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation(); + + if (localWorld != null) + { + updatePossibleArea(localWorld, temperature, ""); + return true; + } + } + + return false; + } + + @Override + public void reset() + { + this.lastWorldPoint = null; + digLocations.clear(); + } + + private void updatePossibleArea(WorldPoint currentWp, String temperature, String difference) + { + this.location = null; + + if (digLocations.isEmpty()) + { + digLocations.addAll(Arrays.asList(HotColdLocation.values())); + } + + int maxSquaresAway = 5000; + int minSquaresAway = 0; + + switch (temperature) + { + // when the strange device reads a temperature, that means that the center of the final dig location + // is a range of squares away from the player's current location (Chebyshev AKA Chess-board distance) + case "ice cold": + maxSquaresAway = 5000; + minSquaresAway = 500; + break; + case "very cold": + maxSquaresAway = 499; + minSquaresAway = 200; + break; + case "cold": + maxSquaresAway = 199; + minSquaresAway = 150; + break; + case "warm": + maxSquaresAway = 149; + minSquaresAway = 100; + break; + case "hot": + maxSquaresAway = 99; + minSquaresAway = 70; + break; + case "very hot": + maxSquaresAway = 69; + minSquaresAway = 30; + break; + case "incredibly hot": + maxSquaresAway = 29; + minSquaresAway = 5; + break; + } + + // rectangle r1 encompasses all of the points that are within the max possible distance from the player + Point p1 = new Point(currentWp.getX() - maxSquaresAway, currentWp.getY() - maxSquaresAway); + Rectangle r1 = new Rectangle((int) p1.getX(), (int) p1.getY(), 2 * maxSquaresAway + 1, 2 * maxSquaresAway + 1); + // rectangle r2 encompasses all of the points that are within the min possible distance from the player + Point p2 = new Point(currentWp.getX() - minSquaresAway, currentWp.getY() - minSquaresAway); + Rectangle r2 = new Rectangle((int) p2.getX(), (int) p2.getY(), 2 * minSquaresAway + 1, 2 * minSquaresAway + 1); + + // eliminate from consideration dig spots that lie entirely within the min range or entirely outside of the max range + digLocations.removeIf(entry -> r2.contains(entry.getRect()) || !r1.intersects(entry.getRect())); + + // if a previous world point has been recorded, we can consider the warmer/colder result from the strange device + if (lastWorldPoint != null) + { + switch (difference) + { + case "but colder than": + // eliminate spots that are absolutely warmer + digLocations.removeIf(entry -> isFirstPointCloserRect(currentWp, lastWorldPoint, entry.getRect())); + break; + case "and warmer than": + // eliminate spots that are absolutely colder + digLocations.removeIf(entry -> isFirstPointCloserRect(lastWorldPoint, currentWp, entry.getRect())); + break; + case "and the same temperature as": + // I couldn't figure out a clean implementation for this case + // not necessary for quickly determining final location + } + } + + lastWorldPoint = currentWp; + } + + private boolean isFirstPointCloserRect(WorldPoint firstWp, WorldPoint secondWp, Rectangle2D r) + { + WorldPoint p1 = new WorldPoint((int) r.getMaxX(), (int) r.getMaxY(), 0); + + if (!isFirstPointCloser(firstWp, secondWp, p1)) + { + return false; + } + + WorldPoint p2 = new WorldPoint((int) r.getMaxX(), (int) r.getMinY(), 0); + + if (!isFirstPointCloser(firstWp, secondWp, p2)) + { + return false; + } + + WorldPoint p3 = new WorldPoint((int) r.getMinX(), (int) r.getMaxY(), 0); + + if (!isFirstPointCloser(firstWp, secondWp, p3)) + { + return false; + } + + WorldPoint p4 = new WorldPoint((int) r.getMinX(), (int) r.getMinY(), 0); + return (isFirstPointCloser(firstWp, secondWp, p4)); + } + + private boolean isFirstPointCloser(WorldPoint firstWp, WorldPoint secondWp, WorldPoint wp) + { + int firstDistance = firstWp.distanceTo2D(wp); + int secondDistance = secondWp.distanceTo2D(wp); + return (firstDistance < secondDistance); + } + + private void markFinalSpot(WorldPoint wp) + { + this.location = wp; + reset(); + } + + public String[] getNpcs() + { + return new String[]{npc}; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java index 99b1eef058..8e27090ddb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java @@ -1,209 +1,240 @@ -/* - * Copyright (c) 2018, Lotto - * 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.cluescrolls.clues; - -import com.google.common.collect.ImmutableSet; -import java.awt.Color; -import java.awt.Graphics2D; -import java.util.Set; -import lombok.Getter; -import static net.runelite.api.ItemID.*; -import net.runelite.api.ObjectComposition; -import static net.runelite.api.ObjectID.CRATE_18506; -import static net.runelite.api.ObjectID.CRATE_2620; -import static net.runelite.api.ObjectID.CRATE_354; -import static net.runelite.api.ObjectID.CRATE_357; -import static net.runelite.api.ObjectID.CRATE_6616; -import net.runelite.api.TileObject; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_BORDER_COLOR; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_FILL_COLOR; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_HOVER_BORDER_COLOR; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -@Getter -public class MapClue extends ClueScroll implements ObjectClueScroll -{ - private static final Set CLUES = ImmutableSet.of( - new MapClue(CLUE_SCROLL_EASY_12179, new WorldPoint(3300, 3291, 0)), - new MapClue(CLUE_SCROLL_EASY_2713, new WorldPoint(3166, 3361, 0)), - new MapClue(CLUE_SCROLL_EASY_2716, new WorldPoint(3290, 3374, 0)), - new MapClue(CLUE_SCROLL_EASY_2719, new WorldPoint(3043, 3398, 0)), - new MapClue(CLUE_SCROLL_EASY_3516, new WorldPoint(2612, 3482, 0)), - new MapClue(CLUE_SCROLL_EASY_3518, new WorldPoint(3110, 3152, 0)), - new MapClue(CLUE_SCROLL_EASY_7236, new WorldPoint(2970, 3415, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_2827, new WorldPoint(3091, 3227, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_3596, new WorldPoint(2907, 3295, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_3598, new WorldPoint(2658, 3488, 0), CRATE_357), - new MapClue(CLUE_SCROLL_MEDIUM_3599, new WorldPoint(2651, 3231, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_3601, new WorldPoint(2565, 3248, 0), CRATE_354), - new MapClue(CLUE_SCROLL_MEDIUM_3602, new WorldPoint(2924, 3210, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_7286, new WorldPoint(2536, 3865, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_7288, new WorldPoint(3434, 3265, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_7290, new WorldPoint(2454, 3230, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_7292, new WorldPoint(2578, 3597, 0)), - new MapClue(CLUE_SCROLL_MEDIUM_7294, new WorldPoint(2666, 3562, 0)), - new MapClue(CLUE_SCROLL_HARD, new WorldPoint(3309, 3503, 0), CRATE_2620), - new MapClue(CLUE_SCROLL_HARD_2729, new WorldPoint(3190, 3963, 0)), - new MapClue(CLUE_SCROLL_HARD_3520, new WorldPoint(2615, 3078, 0)), - new MapClue(CLUE_SCROLL_HARD_3522, new WorldPoint(2488, 3308, 0)), - new MapClue(CLUE_SCROLL_HARD_3524, new WorldPoint(2457, 3182, 0), CRATE_18506), - new MapClue(CLUE_SCROLL_HARD_3525, new WorldPoint(3026, 3628, 0), CRATE_354), - new MapClue(CLUE_SCROLL_HARD_7239, new WorldPoint(3021, 3912, 0)), - new MapClue(CLUE_SCROLL_HARD_7241, new WorldPoint(2722, 3338, 0)), - new MapClue(CLUE_SCROLL_ELITE_12130, new WorldPoint(2449, 3130, 0)), - new MapClue(CLUE_SCROLL_ELITE_19782, new WorldPoint(2953, 9523, 1), "In the Mogre Camp, near Port Khazard. You require a Diving Apparatus and a Fishbowl Helmet"), - new MapClue(CLUE_SCROLL_ELITE_19783, new WorldPoint(2202, 3062, 0)), - new MapClue(CLUE_SCROLL_ELITE_19784, new WorldPoint(1815, 3852, 0)), - new MapClue(CLUE_SCROLL_ELITE_19785, new WorldPoint(3538, 3208, 0)), - new MapClue(CLUE_SCROLL_ELITE_19786, new WorldPoint(2703, 2716, 0), CRATE_6616) - ); - - private final int itemId; - private final WorldPoint location; - private final int objectId; - private final String description; - - private MapClue(int itemId, WorldPoint location) - { - this(itemId, location, -1); - } - - private MapClue(int itemId, WorldPoint location, int objectId) - { - this(itemId, location, objectId, null); - } - - private MapClue(int itemId, WorldPoint location, String description) - { - this(itemId, location, -1, description); - } - - private MapClue(int itemId, WorldPoint location, int objectId, String description) - { - this.itemId = itemId; - this.location = location; - this.objectId = objectId; - this.description = description; - setRequiresSpade(objectId == -1); - } - - @Override - public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) - { - panelComponent.getChildren().add(TitleComponent.builder().text("Map Clue").build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Click the clue scroll along the edge of your world map to see your destination.") - .build()); - - if (objectId != -1) - { - ObjectComposition objectToClick = plugin.getClient().getObjectDefinition(getObjectId()); - - String objectName = "N/A"; - - if (objectToClick != null) - { - objectName = objectToClick.getName(); - } - - panelComponent.getChildren().add(LineComponent.builder() - .left("Travel to the destination and click the " + objectName + ".") - .build()); - } - else - { - panelComponent.getChildren().add(LineComponent.builder() - .left("Travel to the destination and dig on the marked tile.") - .build()); - } - - if (description != null) - { - panelComponent.getChildren().add(LineComponent.builder().build()); - panelComponent.getChildren().add(LineComponent.builder() - .left(description) - .build()); - } - } - - @Override - public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) - { - LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation()); - - if (localLocation == null) - { - return; - } - - // Mark game object - if (objectId != -1) - { - net.runelite.api.Point mousePosition = plugin.getClient().getMouseCanvasPosition(); - - if (plugin.getObjectsToMark() != null) - { - for (TileObject gameObject : plugin.getObjectsToMark()) - { - OverlayUtil.renderHoverableArea(graphics, gameObject.getClickbox(), mousePosition, - CLICKBOX_FILL_COLOR, CLICKBOX_BORDER_COLOR, CLICKBOX_HOVER_BORDER_COLOR); - - OverlayUtil.renderImageLocation(plugin.getClient(), graphics, gameObject.getLocalLocation(), plugin.getClueScrollImage(), IMAGE_Z_OFFSET); - } - } - } - // Mark tile - else - { - OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getSpadeImage(), Color.ORANGE); - } - } - - public static MapClue forItemId(int itemId) - { - for (MapClue clue : CLUES) - { - if (clue.itemId == itemId) - { - return clue; - } - } - - return null; - } - - public int[] getObjectIds() - { - return new int[] {objectId}; - } -} +/* + * Copyright (c) 2018, Lotto + * 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.cluescrolls.clues; + +import com.google.common.collect.ImmutableSet; +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.Set; +import lombok.Getter; +import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_12179; +import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_2713; +import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_2716; +import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_2719; +import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_3516; +import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_3518; +import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_7236; +import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_12130; +import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19782; +import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19783; +import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19784; +import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19785; +import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19786; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_2729; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3520; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3522; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3524; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3525; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_7239; +import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_7241; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_2827; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3596; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3598; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3599; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3601; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3602; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7286; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7288; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7290; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7292; +import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7294; +import net.runelite.api.ObjectComposition; +import static net.runelite.api.ObjectID.CRATE_18506; +import static net.runelite.api.ObjectID.CRATE_2620; +import static net.runelite.api.ObjectID.CRATE_354; +import static net.runelite.api.ObjectID.CRATE_357; +import static net.runelite.api.ObjectID.CRATE_6616; +import net.runelite.api.TileObject; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_BORDER_COLOR; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_FILL_COLOR; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_HOVER_BORDER_COLOR; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +@Getter +public class MapClue extends ClueScroll implements ObjectClueScroll +{ + private static final Set CLUES = ImmutableSet.of( + new MapClue(CLUE_SCROLL_EASY_12179, new WorldPoint(3300, 3291, 0)), + new MapClue(CLUE_SCROLL_EASY_2713, new WorldPoint(3166, 3361, 0)), + new MapClue(CLUE_SCROLL_EASY_2716, new WorldPoint(3290, 3374, 0)), + new MapClue(CLUE_SCROLL_EASY_2719, new WorldPoint(3043, 3398, 0)), + new MapClue(CLUE_SCROLL_EASY_3516, new WorldPoint(2612, 3482, 0)), + new MapClue(CLUE_SCROLL_EASY_3518, new WorldPoint(3110, 3152, 0)), + new MapClue(CLUE_SCROLL_EASY_7236, new WorldPoint(2970, 3415, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_2827, new WorldPoint(3091, 3227, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_3596, new WorldPoint(2907, 3295, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_3598, new WorldPoint(2658, 3488, 0), CRATE_357), + new MapClue(CLUE_SCROLL_MEDIUM_3599, new WorldPoint(2651, 3231, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_3601, new WorldPoint(2565, 3248, 0), CRATE_354), + new MapClue(CLUE_SCROLL_MEDIUM_3602, new WorldPoint(2924, 3210, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_7286, new WorldPoint(2536, 3865, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_7288, new WorldPoint(3434, 3265, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_7290, new WorldPoint(2454, 3230, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_7292, new WorldPoint(2578, 3597, 0)), + new MapClue(CLUE_SCROLL_MEDIUM_7294, new WorldPoint(2666, 3562, 0)), + new MapClue(CLUE_SCROLL_HARD, new WorldPoint(3309, 3503, 0), CRATE_2620), + new MapClue(CLUE_SCROLL_HARD_2729, new WorldPoint(3190, 3963, 0)), + new MapClue(CLUE_SCROLL_HARD_3520, new WorldPoint(2615, 3078, 0)), + new MapClue(CLUE_SCROLL_HARD_3522, new WorldPoint(2488, 3308, 0)), + new MapClue(CLUE_SCROLL_HARD_3524, new WorldPoint(2457, 3182, 0), CRATE_18506), + new MapClue(CLUE_SCROLL_HARD_3525, new WorldPoint(3026, 3628, 0), CRATE_354), + new MapClue(CLUE_SCROLL_HARD_7239, new WorldPoint(3021, 3912, 0)), + new MapClue(CLUE_SCROLL_HARD_7241, new WorldPoint(2722, 3338, 0)), + new MapClue(CLUE_SCROLL_ELITE_12130, new WorldPoint(2449, 3130, 0)), + new MapClue(CLUE_SCROLL_ELITE_19782, new WorldPoint(2953, 9523, 1), "In the Mogre Camp, near Port Khazard. You require a Diving Apparatus and a Fishbowl Helmet"), + new MapClue(CLUE_SCROLL_ELITE_19783, new WorldPoint(2202, 3062, 0)), + new MapClue(CLUE_SCROLL_ELITE_19784, new WorldPoint(1815, 3852, 0)), + new MapClue(CLUE_SCROLL_ELITE_19785, new WorldPoint(3538, 3208, 0)), + new MapClue(CLUE_SCROLL_ELITE_19786, new WorldPoint(2703, 2716, 0), CRATE_6616) + ); + + private final int itemId; + private final WorldPoint location; + private final int objectId; + private final String description; + + private MapClue(int itemId, WorldPoint location) + { + this(itemId, location, -1); + } + + private MapClue(int itemId, WorldPoint location, int objectId) + { + this(itemId, location, objectId, null); + } + + private MapClue(int itemId, WorldPoint location, String description) + { + this(itemId, location, -1, description); + } + + private MapClue(int itemId, WorldPoint location, int objectId, String description) + { + this.itemId = itemId; + this.location = location; + this.objectId = objectId; + this.description = description; + setRequiresSpade(objectId == -1); + } + + @Override + public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) + { + panelComponent.getChildren().add(TitleComponent.builder().text("Map Clue").build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Click the clue scroll along the edge of your world map to see your destination.") + .build()); + + if (objectId != -1) + { + ObjectComposition objectToClick = plugin.getClient().getObjectDefinition(getObjectId()); + + String objectName = "N/A"; + + if (objectToClick != null) + { + objectName = objectToClick.getName(); + } + + panelComponent.getChildren().add(LineComponent.builder() + .left("Travel to the destination and click the " + objectName + ".") + .build()); + } + else + { + panelComponent.getChildren().add(LineComponent.builder() + .left("Travel to the destination and dig on the marked tile.") + .build()); + } + + if (description != null) + { + panelComponent.getChildren().add(LineComponent.builder().build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(description) + .build()); + } + } + + @Override + public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) + { + LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation()); + + if (localLocation == null) + { + return; + } + + // Mark game object + if (objectId != -1) + { + net.runelite.api.Point mousePosition = plugin.getClient().getMouseCanvasPosition(); + + if (plugin.getObjectsToMark() != null) + { + for (TileObject gameObject : plugin.getObjectsToMark()) + { + OverlayUtil.renderHoverableArea(graphics, gameObject.getClickbox(), mousePosition, + CLICKBOX_FILL_COLOR, CLICKBOX_BORDER_COLOR, CLICKBOX_HOVER_BORDER_COLOR); + + OverlayUtil.renderImageLocation(plugin.getClient(), graphics, gameObject.getLocalLocation(), plugin.getClueScrollImage(), IMAGE_Z_OFFSET); + } + } + } + // Mark tile + else + { + OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getSpadeImage(), Color.ORANGE); + } + } + + public static MapClue forItemId(int itemId) + { + for (MapClue clue : CLUES) + { + if (clue.itemId == itemId) + { + return clue; + } + } + + return null; + } + + public int[] getObjectIds() + { + return new int[]{objectId}; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java index 6ed7ce176f..a2e7d8696b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java @@ -1,107 +1,107 @@ -/* - * Copyright (c) 2019, Hydrox6 - * 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.cluescrolls.clues; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import net.runelite.api.NPC; -import net.runelite.api.coords.WorldPoint; -import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; -import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -@AllArgsConstructor(access = AccessLevel.PRIVATE) -@Getter -public class MusicClue extends ClueScroll implements NpcClueScroll -{ - private static final WorldPoint LOCATION = new WorldPoint(2990, 3384, 0); - private static final String CECILIA = "Cecilia"; - private static final Pattern SONG_PATTERN = Pattern.compile("([A-Za-z !&',.]+)"); - - private final String song; - - @Override - public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) - { - panelComponent.getChildren().add(TitleComponent.builder().text("Music Clue").build()); - panelComponent.getChildren().add(LineComponent.builder().left("NPC:").build()); - panelComponent.getChildren().add(LineComponent.builder() - .left(CECILIA) - .leftColor(TITLED_CONTENT_COLOR) - .build()); - - panelComponent.getChildren().add(LineComponent.builder().left("Area:").build()); - panelComponent.getChildren().add(LineComponent.builder() - .left("Falador Park") - .leftColor(TITLED_CONTENT_COLOR) - .build()); - - panelComponent.getChildren().add(LineComponent.builder().left("Song:").build()); - panelComponent.getChildren().add(LineComponent.builder() - .left(song) - .leftColor(TITLED_CONTENT_COLOR) - .build()); - } - - @Override - public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) - { - if (!LOCATION.isInScene(plugin.getClient())) - { - return; - } - - for (NPC npc : plugin.getNpcsToMark()) - { - OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET); - } - } - - @Override - public String[] getNpcs() - { - return new String[] {CECILIA}; - } - - public static MusicClue forText(String text) - { - final Matcher m = SONG_PATTERN.matcher(text); - if (m.find()) - { - final String song = m.group(1); - return new MusicClue(song); - } - return null; - } -} +/* + * Copyright (c) 2019, Hydrox6 + * 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.cluescrolls.clues; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.runelite.api.NPC; +import net.runelite.api.coords.WorldPoint; +import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; +import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public class MusicClue extends ClueScroll implements NpcClueScroll +{ + private static final WorldPoint LOCATION = new WorldPoint(2990, 3384, 0); + private static final String CECILIA = "Cecilia"; + private static final Pattern SONG_PATTERN = Pattern.compile("([A-Za-z !&',.]+)"); + + private final String song; + + @Override + public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) + { + panelComponent.getChildren().add(TitleComponent.builder().text("Music Clue").build()); + panelComponent.getChildren().add(LineComponent.builder().left("NPC:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(CECILIA) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + + panelComponent.getChildren().add(LineComponent.builder().left("Area:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left("Falador Park") + .leftColor(TITLED_CONTENT_COLOR) + .build()); + + panelComponent.getChildren().add(LineComponent.builder().left("Song:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(song) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + } + + @Override + public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) + { + if (!LOCATION.isInScene(plugin.getClient())) + { + return; + } + + for (NPC npc : plugin.getNpcsToMark()) + { + OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET); + } + } + + @Override + public String[] getNpcs() + { + return new String[]{CECILIA}; + } + + public static MusicClue forText(String text) + { + final Matcher m = SONG_PATTERN.matcher(text); + if (m.find()) + { + final String song = m.group(1); + return new MusicClue(song); + } + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/emote/Emote.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/emote/Emote.java index 67019d58d0..10ecc5793c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/emote/Emote.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/emote/Emote.java @@ -1,75 +1,101 @@ -/* - * Copyright (c) 2018, Lotto - * 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.cluescrolls.clues.emote; - -import lombok.Getter; -import static net.runelite.api.SpriteID.*; - -@Getter -public enum Emote -{ - BULL_ROARER("Bull Roarer", -1), - YES("Yes", EMOTE_YES), - NO("No", EMOTE_NO), - THINK("Think", EMOTE_THINK), - BOW("Bow", EMOTE_BOW), - ANGRY("Angry", EMOTE_ANGRY), - CRY("Cry", EMOTE_CRY), - LAUGH("Laugh", EMOTE_LAUGH), - CHEER("Cheer", EMOTE_CHEER), - WAVE("Wave", EMOTE_WAVE), - BECKON("Beckon", EMOTE_BECKON), - DANCE("Dance", EMOTE_DANCE), - CLAP("Clap", EMOTE_CLAP), - PANIC("Panic", EMOTE_PANIC), - JIG("Jig", EMOTE_JIG), - SPIN("Spin", EMOTE_SPIN), - HEADBANG("Headbang", EMOTE_HEADBANG), - JUMP_FOR_JOY("Jump for Joy", EMOTE_JUMP_FOR_JOY), - RASPBERRY("Raspberry", EMOTE_RASPBERRY), - YAWN("Yawn", EMOTE_YAWN), - SALUTE("Salute", EMOTE_SALUTE), - SHRUG("Shrug", EMOTE_SHRUG), - BLOW_KISS("Blow Kiss", EMOTE_BLOW_KISS), - GOBLIN_SALUTE("Goblin Salute", EMOTE_GOBLIN_SALUTE), - SLAP_HEAD("Slap Head", EMOTE_SLAP_HEAD), - STOMP("Stomp", EMOTE_STOMP), - FLAP("Flap", EMOTE_FLAP), - PUSH_UP("Push up", EMOTE_PUSH_UP); - - private String name; - private int spriteId; - - Emote(String name, int spriteId) - { - this.name = name; - this.spriteId = spriteId; - } - - public boolean hasSprite() - { - return spriteId != -1; - } -} +/* + * Copyright (c) 2018, Lotto + * 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.cluescrolls.clues.emote; + +import lombok.Getter; +import static net.runelite.api.SpriteID.EMOTE_ANGRY; +import static net.runelite.api.SpriteID.EMOTE_BECKON; +import static net.runelite.api.SpriteID.EMOTE_BLOW_KISS; +import static net.runelite.api.SpriteID.EMOTE_BOW; +import static net.runelite.api.SpriteID.EMOTE_CHEER; +import static net.runelite.api.SpriteID.EMOTE_CLAP; +import static net.runelite.api.SpriteID.EMOTE_CRY; +import static net.runelite.api.SpriteID.EMOTE_DANCE; +import static net.runelite.api.SpriteID.EMOTE_FLAP; +import static net.runelite.api.SpriteID.EMOTE_GOBLIN_SALUTE; +import static net.runelite.api.SpriteID.EMOTE_HEADBANG; +import static net.runelite.api.SpriteID.EMOTE_JIG; +import static net.runelite.api.SpriteID.EMOTE_JUMP_FOR_JOY; +import static net.runelite.api.SpriteID.EMOTE_LAUGH; +import static net.runelite.api.SpriteID.EMOTE_NO; +import static net.runelite.api.SpriteID.EMOTE_PANIC; +import static net.runelite.api.SpriteID.EMOTE_PUSH_UP; +import static net.runelite.api.SpriteID.EMOTE_RASPBERRY; +import static net.runelite.api.SpriteID.EMOTE_SALUTE; +import static net.runelite.api.SpriteID.EMOTE_SHRUG; +import static net.runelite.api.SpriteID.EMOTE_SLAP_HEAD; +import static net.runelite.api.SpriteID.EMOTE_SPIN; +import static net.runelite.api.SpriteID.EMOTE_STOMP; +import static net.runelite.api.SpriteID.EMOTE_THINK; +import static net.runelite.api.SpriteID.EMOTE_WAVE; +import static net.runelite.api.SpriteID.EMOTE_YAWN; +import static net.runelite.api.SpriteID.EMOTE_YES; + +@Getter +public enum Emote +{ + BULL_ROARER("Bull Roarer", -1), + YES("Yes", EMOTE_YES), + NO("No", EMOTE_NO), + THINK("Think", EMOTE_THINK), + BOW("Bow", EMOTE_BOW), + ANGRY("Angry", EMOTE_ANGRY), + CRY("Cry", EMOTE_CRY), + LAUGH("Laugh", EMOTE_LAUGH), + CHEER("Cheer", EMOTE_CHEER), + WAVE("Wave", EMOTE_WAVE), + BECKON("Beckon", EMOTE_BECKON), + DANCE("Dance", EMOTE_DANCE), + CLAP("Clap", EMOTE_CLAP), + PANIC("Panic", EMOTE_PANIC), + JIG("Jig", EMOTE_JIG), + SPIN("Spin", EMOTE_SPIN), + HEADBANG("Headbang", EMOTE_HEADBANG), + JUMP_FOR_JOY("Jump for Joy", EMOTE_JUMP_FOR_JOY), + RASPBERRY("Raspberry", EMOTE_RASPBERRY), + YAWN("Yawn", EMOTE_YAWN), + SALUTE("Salute", EMOTE_SALUTE), + SHRUG("Shrug", EMOTE_SHRUG), + BLOW_KISS("Blow Kiss", EMOTE_BLOW_KISS), + GOBLIN_SALUTE("Goblin Salute", EMOTE_GOBLIN_SALUTE), + SLAP_HEAD("Slap Head", EMOTE_SLAP_HEAD), + STOMP("Stomp", EMOTE_STOMP), + FLAP("Flap", EMOTE_FLAP), + PUSH_UP("Push up", EMOTE_PUSH_UP); + + private String name; + private int spriteId; + + Emote(String name, int spriteId) + { + this.name = name; + this.spriteId = spriteId; + } + + public boolean hasSprite() + { + return spriteId != -1; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java index 6e81a7a983..3e811a60d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java @@ -25,6 +25,11 @@ package net.runelite.client.plugins.combatlevel; import com.google.common.annotations.VisibleForTesting; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.Experience; import net.runelite.api.Skill; @@ -34,11 +39,6 @@ import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.tooltip.Tooltip; import net.runelite.client.ui.overlay.tooltip.TooltipManager; import net.runelite.client.util.ColorUtil; -import javax.inject.Inject; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; class CombatLevelOverlay extends Overlay { @@ -143,10 +143,11 @@ class CombatLevelOverlay extends Overlay /** * Calculate skill levels required for increasing combat level, meant * for all combat skills besides prayer, ranged, and magic. - * @param start initial value - * @param end ending value (combat level + 1) - * @param multiple how much adding one skill level will change combat - * @return levels required for a specific skill to level up combat + * + * @param start initial value + * @param end ending value (combat level + 1) + * @param multiple how much adding one skill level will change combat + * @return levels required for a specific skill to level up combat */ @VisibleForTesting static int calcLevels(double start, int end, double multiple) @@ -158,8 +159,9 @@ class CombatLevelOverlay extends Overlay * Calculate skill levels for increasing combat level, meant ONLY for the Prayer skill. *

* Note: Prayer is a special case, only leveling up upon even level numbers. This is accounted - * for in this function. + * for in this function. *

+ * * @param start current combat level * @param end ending value (combat level + 1) * @param prayerLevel the player's current prayer level @@ -191,10 +193,11 @@ class CombatLevelOverlay extends Overlay /** * Calculate skill levels required for increasing combat level, meant * ONLY for Ranged and Magic skills. - * @param start either the current ranged or magic level - * @param end ending value (combat level + 1) - * @param dhp defence, hitpoints, and prayer; this is the initial calculated "base" value - * @return levels required for a specific skill to level up combat + * + * @param start either the current ranged or magic level + * @param end ending value (combat level + 1) + * @param dhp defence, hitpoints, and prayer; this is the initial calculated "base" value + * @return levels required for a specific skill to level up combat */ @VisibleForTesting static int calcLevelsRM(double start, int end, double dhp) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java index bbde15c2e0..eb7c318320 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java @@ -1,244 +1,244 @@ -/* - * Copyright (c) 2017, Devin French - * Copyright (c) 2019, Jordan Atwood - * 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.combatlevel; - -import com.google.inject.Provides; -import java.text.DecimalFormat; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Experience; -import net.runelite.api.GameState; -import net.runelite.api.Skill; -import net.runelite.api.WorldType; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "Combat Level", - description = "Show a more accurate combat level in Combat Options panel and other combat level functions", - tags = {"wilderness", "attack", "range"} -) -public class CombatLevelPlugin extends Plugin -{ - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.###"); - private static final String CONFIG_GROUP = "combatlevel"; - private static final String ATTACK_RANGE_CONFIG_KEY = "wildernessAttackLevelRange"; - private static final Pattern WILDERNESS_LEVEL_PATTERN = Pattern.compile("^Level: (\\d+)$"); - private static final int SKULL_CONTAINER_ADJUSTED_ORIGINAL_Y = 6; - private static final int WILDERNESS_LEVEL_TEXT_ADJUSTED_ORIGINAL_Y = 3; - private static final int MIN_COMBAT_LEVEL = 3; - - private int originalWildernessLevelTextPosition = -1; - private int originalSkullContainerPosition = -1; - - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private CombatLevelConfig config; - - @Inject - private CombatLevelOverlay overlay; - - @Inject - private OverlayManager overlayManager; - - @Provides - CombatLevelConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(CombatLevelConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - - if (config.wildernessAttackLevelRange()) - { - appendAttackLevelRangeText(); - } - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - Widget combatLevelWidget = client.getWidget(WidgetInfo.COMBAT_LEVEL); - - if (combatLevelWidget != null) - { - String widgetText = combatLevelWidget.getText(); - - if (widgetText.contains(".")) - { - combatLevelWidget.setText(widgetText.substring(0, widgetText.indexOf("."))); - } - } - - shutDownAttackLevelRange(); - } - - @Subscribe - public void onGameTick(GameTick event) - { - if (client.getGameState() != GameState.LOGGED_IN) - { - return; - } - - Widget combatLevelWidget = client.getWidget(WidgetInfo.COMBAT_LEVEL); - if (combatLevelWidget == null) - { - return; - } - - double combatLevelPrecise = Experience.getCombatLevelPrecise( - client.getRealSkillLevel(Skill.ATTACK), - client.getRealSkillLevel(Skill.STRENGTH), - client.getRealSkillLevel(Skill.DEFENCE), - client.getRealSkillLevel(Skill.HITPOINTS), - client.getRealSkillLevel(Skill.MAGIC), - client.getRealSkillLevel(Skill.RANGED), - client.getRealSkillLevel(Skill.PRAYER) - ); - - combatLevelWidget.setText("Combat Lvl: " + DECIMAL_FORMAT.format(combatLevelPrecise)); - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (!CONFIG_GROUP.equals(event.getGroup()) || !ATTACK_RANGE_CONFIG_KEY.equals(event.getKey())) - { - return; - } - - if (config.wildernessAttackLevelRange()) - { - appendAttackLevelRangeText(); - } - else - { - shutDownAttackLevelRange(); - } - } - - @Subscribe - public void onScriptCallbackEvent(ScriptCallbackEvent event) - { - if (config.wildernessAttackLevelRange() - && "wildernessWidgetTextSet".equals(event.getEventName())) - { - appendAttackLevelRangeText(); - } - } - - private void appendAttackLevelRangeText() - { - final Widget wildernessLevelWidget = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL); - if (wildernessLevelWidget == null) - { - return; - } - - final String wildernessLevelText = wildernessLevelWidget.getText(); - final Matcher m = WILDERNESS_LEVEL_PATTERN.matcher(wildernessLevelText); - if (!m.matches() - || WorldType.isPvpWorld(client.getWorldType())) - { - return; - } - - final Widget skullContainer = client.getWidget(WidgetInfo.PVP_SKULL_CONTAINER); - if (originalWildernessLevelTextPosition == -1) - { - originalWildernessLevelTextPosition = wildernessLevelWidget.getOriginalY(); - } - if (originalSkullContainerPosition == -1) - { - originalSkullContainerPosition = skullContainer.getRelativeY(); - } - - final int wildernessLevel = Integer.parseInt(m.group(1)); - final int combatLevel = client.getLocalPlayer().getCombatLevel(); - - wildernessLevelWidget.setText(wildernessLevelText + "
" + combatAttackRange(combatLevel, wildernessLevel)); - wildernessLevelWidget.setOriginalY(WILDERNESS_LEVEL_TEXT_ADJUSTED_ORIGINAL_Y); - skullContainer.setOriginalY(SKULL_CONTAINER_ADJUSTED_ORIGINAL_Y); - - clientThread.invoke(wildernessLevelWidget::revalidate); - clientThread.invoke(skullContainer::revalidate); - } - - private void shutDownAttackLevelRange() - { - if (WorldType.isPvpWorld(client.getWorldType())) - { - return; - } - - final Widget wildernessLevelWidget = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL); - if (wildernessLevelWidget != null) - { - String wildernessLevelText = wildernessLevelWidget.getText(); - if (wildernessLevelText.contains("
")) - { - wildernessLevelWidget.setText(wildernessLevelText.substring(0, wildernessLevelText.indexOf("
"))); - } - wildernessLevelWidget.setOriginalY(originalWildernessLevelTextPosition); - clientThread.invoke(wildernessLevelWidget::revalidate); - } - originalWildernessLevelTextPosition = -1; - - final Widget skullContainer = client.getWidget(WidgetInfo.PVP_SKULL_CONTAINER); - if (skullContainer != null) - { - skullContainer.setOriginalY(originalSkullContainerPosition); - clientThread.invoke(skullContainer::revalidate); - } - originalSkullContainerPosition = -1; - } - - private static String combatAttackRange(final int combatLevel, final int wildernessLevel) - { - return Math.max(MIN_COMBAT_LEVEL, combatLevel - wildernessLevel) + "-" + Math.min(Experience.MAX_COMBAT_LEVEL, combatLevel + wildernessLevel); - } -} +/* + * Copyright (c) 2017, Devin French + * Copyright (c) 2019, Jordan Atwood + * 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.combatlevel; + +import com.google.inject.Provides; +import java.text.DecimalFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Experience; +import net.runelite.api.GameState; +import net.runelite.api.Skill; +import net.runelite.api.WorldType; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Combat Level", + description = "Show a more accurate combat level in Combat Options panel and other combat level functions", + tags = {"wilderness", "attack", "range"} +) +public class CombatLevelPlugin extends Plugin +{ + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.###"); + private static final String CONFIG_GROUP = "combatlevel"; + private static final String ATTACK_RANGE_CONFIG_KEY = "wildernessAttackLevelRange"; + private static final Pattern WILDERNESS_LEVEL_PATTERN = Pattern.compile("^Level: (\\d+)$"); + private static final int SKULL_CONTAINER_ADJUSTED_ORIGINAL_Y = 6; + private static final int WILDERNESS_LEVEL_TEXT_ADJUSTED_ORIGINAL_Y = 3; + private static final int MIN_COMBAT_LEVEL = 3; + + private int originalWildernessLevelTextPosition = -1; + private int originalSkullContainerPosition = -1; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private CombatLevelConfig config; + + @Inject + private CombatLevelOverlay overlay; + + @Inject + private OverlayManager overlayManager; + + @Provides + CombatLevelConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(CombatLevelConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + + if (config.wildernessAttackLevelRange()) + { + appendAttackLevelRangeText(); + } + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + Widget combatLevelWidget = client.getWidget(WidgetInfo.COMBAT_LEVEL); + + if (combatLevelWidget != null) + { + String widgetText = combatLevelWidget.getText(); + + if (widgetText.contains(".")) + { + combatLevelWidget.setText(widgetText.substring(0, widgetText.indexOf("."))); + } + } + + shutDownAttackLevelRange(); + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + Widget combatLevelWidget = client.getWidget(WidgetInfo.COMBAT_LEVEL); + if (combatLevelWidget == null) + { + return; + } + + double combatLevelPrecise = Experience.getCombatLevelPrecise( + client.getRealSkillLevel(Skill.ATTACK), + client.getRealSkillLevel(Skill.STRENGTH), + client.getRealSkillLevel(Skill.DEFENCE), + client.getRealSkillLevel(Skill.HITPOINTS), + client.getRealSkillLevel(Skill.MAGIC), + client.getRealSkillLevel(Skill.RANGED), + client.getRealSkillLevel(Skill.PRAYER) + ); + + combatLevelWidget.setText("Combat Lvl: " + DECIMAL_FORMAT.format(combatLevelPrecise)); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!CONFIG_GROUP.equals(event.getGroup()) || !ATTACK_RANGE_CONFIG_KEY.equals(event.getKey())) + { + return; + } + + if (config.wildernessAttackLevelRange()) + { + appendAttackLevelRangeText(); + } + else + { + shutDownAttackLevelRange(); + } + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent event) + { + if (config.wildernessAttackLevelRange() + && "wildernessWidgetTextSet".equals(event.getEventName())) + { + appendAttackLevelRangeText(); + } + } + + private void appendAttackLevelRangeText() + { + final Widget wildernessLevelWidget = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL); + if (wildernessLevelWidget == null) + { + return; + } + + final String wildernessLevelText = wildernessLevelWidget.getText(); + final Matcher m = WILDERNESS_LEVEL_PATTERN.matcher(wildernessLevelText); + if (!m.matches() + || WorldType.isPvpWorld(client.getWorldType())) + { + return; + } + + final Widget skullContainer = client.getWidget(WidgetInfo.PVP_SKULL_CONTAINER); + if (originalWildernessLevelTextPosition == -1) + { + originalWildernessLevelTextPosition = wildernessLevelWidget.getOriginalY(); + } + if (originalSkullContainerPosition == -1) + { + originalSkullContainerPosition = skullContainer.getRelativeY(); + } + + final int wildernessLevel = Integer.parseInt(m.group(1)); + final int combatLevel = client.getLocalPlayer().getCombatLevel(); + + wildernessLevelWidget.setText(wildernessLevelText + "
" + combatAttackRange(combatLevel, wildernessLevel)); + wildernessLevelWidget.setOriginalY(WILDERNESS_LEVEL_TEXT_ADJUSTED_ORIGINAL_Y); + skullContainer.setOriginalY(SKULL_CONTAINER_ADJUSTED_ORIGINAL_Y); + + clientThread.invoke(wildernessLevelWidget::revalidate); + clientThread.invoke(skullContainer::revalidate); + } + + private void shutDownAttackLevelRange() + { + if (WorldType.isPvpWorld(client.getWorldType())) + { + return; + } + + final Widget wildernessLevelWidget = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL); + if (wildernessLevelWidget != null) + { + String wildernessLevelText = wildernessLevelWidget.getText(); + if (wildernessLevelText.contains("
")) + { + wildernessLevelWidget.setText(wildernessLevelText.substring(0, wildernessLevelText.indexOf("
"))); + } + wildernessLevelWidget.setOriginalY(originalWildernessLevelTextPosition); + clientThread.invoke(wildernessLevelWidget::revalidate); + } + originalWildernessLevelTextPosition = -1; + + final Widget skullContainer = client.getWidget(WidgetInfo.PVP_SKULL_CONTAINER); + if (skullContainer != null) + { + skullContainer.setOriginalY(originalSkullContainerPosition); + clientThread.invoke(skullContainer::revalidate); + } + originalSkullContainerPosition = -1; + } + + private static String combatAttackRange(final int combatLevel, final int wildernessLevel) + { + return Math.max(MIN_COMBAT_LEVEL, combatLevel - wildernessLevel) + "-" + Math.min(Experience.MAX_COMBAT_LEVEL, combatLevel + wildernessLevel); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 6f6d469c0b..152458de73 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -83,7 +83,6 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginInstantiationException; import net.runelite.client.plugins.PluginManager; import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.pluginsorter.PluginSorterPlugin; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.DynamicGridLayout; import net.runelite.client.ui.PluginPanel; @@ -197,8 +196,8 @@ public class ConfigPanel extends PluginPanel // set RuneLite config on top, as it should always have been final PluginListItem runeLite = new PluginListItem(this, configManager, runeLiteConfig, - configManager.getConfigDescriptor(runeLiteConfig), - RUNELITE_PLUGIN, "RuneLite client settings", "client"); + configManager.getConfigDescriptor(runeLiteConfig), + RUNELITE_PLUGIN, "RuneLite client settings", "client"); runeLite.setPinned(pinnedPlugins.contains(RUNELITE_PLUGIN)); runeLite.nameLabel.setForeground(Color.WHITE); pluginList.add(runeLite); @@ -279,13 +278,13 @@ public class ConfigPanel extends PluginPanel // populate pluginList with all vanilla RL plugins List vanillaPlugins = new ArrayList<>(); pluginManager.getPlugins().stream() - .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).hidden()) - .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.PVM)) - .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.PVP)) - .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.UTILITY)) - .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.PLUGIN_ORGANIZER)) - .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.EXTERNAL)) - .forEach(plugin -> + .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).hidden()) + .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.PVM)) + .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.PVP)) + .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.UTILITY)) + .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.PLUGIN_ORGANIZER)) + .filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).type().equals(PluginType.EXTERNAL)) + .forEach(plugin -> { final PluginDescriptor descriptor = plugin.getClass().getAnnotation(PluginDescriptor.class); final Config config = pluginManager.getPluginConfigProxy(plugin); @@ -295,11 +294,11 @@ public class ConfigPanel extends PluginPanel listItem.setPinned(pinnedPlugins.contains(listItem.getName())); vanillaPlugins.add(listItem); } - ); + ); final PluginListItem chatColor = new PluginListItem(this, configManager, chatColorConfig, - configManager.getConfigDescriptor(chatColorConfig), - CHAT_COLOR_PLUGIN, "Recolor chat text", "colour", "messages"); + configManager.getConfigDescriptor(chatColorConfig), + CHAT_COLOR_PLUGIN, "Recolor chat text", "colour", "messages"); chatColor.setPinned(pinnedPlugins.contains(CHAT_COLOR_PLUGIN)); chatColor.nameLabel.setForeground(Color.WHITE); vanillaPlugins.add(chatColor); @@ -404,7 +403,9 @@ public class ConfigPanel extends PluginPanel topPanel.add(topPanelBackButton, BorderLayout.WEST); if (!listItem.getName().equals("RuneLitePlus")) - topPanel.add(listItem.createToggleButton(), BorderLayout.EAST); + { + topPanel.add(listItem.createToggleButton(), BorderLayout.EAST); + } String name = listItem.getName(); JLabel title = new JLabel(name); @@ -520,7 +521,7 @@ public class ConfigPanel extends PluginPanel public void mouseClicked(MouseEvent e) { RuneliteColorPicker colorPicker = new RuneliteColorPicker(SwingUtilities.windowForComponent(ConfigPanel.this), - colorPickerBtn.getBackground(), cid.getItem().name(), cid.getAlpha() == null); + colorPickerBtn.getBackground(), cid.getItem().name(), cid.getAlpha() == null); colorPicker.setLocation(getLocationOnScreen()); colorPicker.setOnColorChange(c -> { @@ -566,7 +567,7 @@ public class ConfigPanel extends PluginPanel heightSpinnerTextField.setColumns(4); ChangeListener listener = e -> - configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue()); + configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue()); widthSpinner.addChangeListener(listener); heightSpinner.addChangeListener(listener); @@ -611,8 +612,8 @@ public class ConfigPanel extends PluginPanel if (cid.getType() == Keybind.class || cid.getType() == ModifierlessKeybind.class) { Keybind startingValue = configManager.getConfiguration(cd.getGroup().value(), - cid.getItem().keyName(), - (Class) cid.getType()); + cid.getItem().keyName(), + (Class) cid.getType()); HotkeyButton button = new HotkeyButton(startingValue, cid.getType() == ModifierlessKeybind.class); @@ -635,8 +636,8 @@ public class ConfigPanel extends PluginPanel resetButton.addActionListener((e) -> { final int result = JOptionPane.showOptionDialog(resetButton, "Are you sure you want to reset this plugin's configuration?", - "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, - null, new String[]{"Yes", "No"}, "No"); + "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, new String[]{"Yes", "No"}, "No"); if (result == JOptionPane.YES_OPTION) { @@ -663,8 +664,8 @@ public class ConfigPanel extends PluginPanel if (!Strings.isNullOrEmpty(configItem.warning())) { final int result = JOptionPane.showOptionDialog(component, configItem.warning(), - "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, - null, new String[]{"Yes", "No"}, "No"); + "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, new String[]{"Yes", "No"}, "No"); if (result != JOptionPane.YES_OPTION) { @@ -758,9 +759,9 @@ public class ConfigPanel extends PluginPanel void savePinnedPlugins() { final String value = pluginList.stream() - .filter(PluginListItem::isPinned) - .map(PluginListItem::getName) - .collect(Collectors.joining(",")); + .filter(PluginListItem::isPinned) + .map(PluginListItem::getName) + .collect(Collectors.joining(",")); configManager.setConfiguration(RUNELITE_GROUP_NAME, PINNED_PLUGINS_CONFIG_KEY, value); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java index 6daab8d582..9481a9f1f6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java @@ -25,7 +25,6 @@ package net.runelite.client.plugins.config; import java.awt.BorderLayout; -import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.image.BufferedImage; @@ -33,7 +32,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.annotation.Nullable; -import javax.inject.Inject; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; @@ -41,13 +39,11 @@ import lombok.AccessLevel; import lombok.Getter; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigDescriptor; -import net.runelite.client.config.ConfigItemDescriptor; import net.runelite.client.config.ConfigManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.components.IconButton; -import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ImageUtil; import org.apache.commons.text.similarity.JaroWinklerDistance; @@ -105,17 +101,17 @@ public class PluginListItem extends JPanel ON_STAR = new ImageIcon(onStar); CONFIG_ICON_HOVER = new ImageIcon(ImageUtil.grayscaleOffset(configIcon, -100)); BufferedImage offSwitcherImage = ImageUtil.flipImage( - ImageUtil.grayscaleOffset( - ImageUtil.grayscaleImage(onSwitcher), - 0.61f - ), - true, - false + ImageUtil.grayscaleOffset( + ImageUtil.grayscaleImage(onSwitcher), + 0.61f + ), + true, + false ); OFF_SWITCHER = new ImageIcon(offSwitcherImage); BufferedImage offStar = ImageUtil.grayscaleOffset( - ImageUtil.grayscaleImage(onStar), - 0.77f + ImageUtil.grayscaleImage(onStar), + 0.77f ); OFF_STAR = new ImageIcon(offStar); } @@ -130,7 +126,7 @@ public class PluginListItem extends JPanel @Nullable Config config, @Nullable ConfigDescriptor configDescriptor) { this(configPanel, configManager, plugin, config, configDescriptor, - descriptor.name(), descriptor.description(), descriptor.tags()); + descriptor.name(), descriptor.description(), descriptor.tags()); } /** @@ -179,27 +175,28 @@ public class PluginListItem extends JPanel }); - final JPanel buttonPanel = new JPanel(); - buttonPanel.setLayout(new GridLayout(1, 2)); - add(buttonPanel, BorderLayout.LINE_END); + final JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new GridLayout(1, 2)); + add(buttonPanel, BorderLayout.LINE_END); - configButton.setPreferredSize(new Dimension(25, 0)); - configButton.setVisible(false); - buttonPanel.add(configButton); + configButton.setPreferredSize(new Dimension(25, 0)); + configButton.setVisible(false); + buttonPanel.add(configButton); - // add a listener to configButton only if there are config items to show - if (config != null && !configDescriptor.getItems().stream().allMatch(item -> item.getItem().hidden())) + // add a listener to configButton only if there are config items to show + if (config != null && !configDescriptor.getItems().stream().allMatch(item -> item.getItem().hidden())) + { + configButton.addActionListener(e -> { - configButton.addActionListener(e -> - { - configButton.setIcon(CONFIG_ICON); - configPanel.openGroupConfigPanel(PluginListItem.this, config, configDescriptor); - }); + configButton.setIcon(CONFIG_ICON); + configPanel.openGroupConfigPanel(PluginListItem.this, config, configDescriptor); + }); - configButton.setVisible(true); - configButton.setToolTipText("Edit plugin configuration"); - } - if (!name.equals("RuneLitePlus")) { + configButton.setVisible(true); + configButton.setToolTipText("Edit plugin configuration"); + } + if (!name.equals("RuneLitePlus")) + { toggleButton.setPreferredSize(new Dimension(25, 0)); attachToggleButtonListener(toggleButton); buttonPanel.add(toggleButton); @@ -261,6 +258,7 @@ public class PluginListItem extends JPanel /** * Checks if all the search terms in the given list matches at least one keyword. + * * @return true if all search terms matches at least one keyword, or false if otherwise. */ boolean matchesSearchTerms(String[] searchTerms) @@ -268,7 +266,7 @@ public class PluginListItem extends JPanel for (String term : searchTerms) { if (keywords.stream().noneMatch((t) -> t.contains(term) || - DISTANCE.apply(t, term) > 0.9)) + DISTANCE.apply(t, term) > 0.9)) { return false; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dailytaskindicators/DailyTasksPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/dailytaskindicators/DailyTasksPlugin.java index 82f1624f1d..fe0ce2cdad 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/dailytaskindicators/DailyTasksPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dailytaskindicators/DailyTasksPlugin.java @@ -251,7 +251,7 @@ public class DailyTasksPlugin extends Plugin max += BONEMEAL_PER_DIARY; } } - if (dailyReset || collected < max) + if (dailyReset || collected < max) { sendChatMessage(BONEMEAL_MESSAGE); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java index d68791d289..7bcd26fd8b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java @@ -1,152 +1,152 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * 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.defaultworld; - -import com.google.inject.Provides; -import java.io.IOException; -import javax.inject.Inject; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.events.GameStateChanged; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.util.WorldUtil; -import net.runelite.http.api.worlds.World; -import net.runelite.http.api.worlds.WorldClient; -import net.runelite.http.api.worlds.WorldResult; - -@PluginDescriptor( - name = "Default World", - description = "Enable a default world to be selected when launching the client", - tags = {"home"} -) -@Slf4j -public class DefaultWorldPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private DefaultWorldConfig config; - - private final WorldClient worldClient = new WorldClient(); - private int worldCache; - private boolean worldChangeRequired; - - @Override - protected void startUp() throws Exception - { - worldChangeRequired = true; - applyWorld(); - } - - @Override - protected void shutDown() throws Exception - { - worldChangeRequired = true; - changeWorld(worldCache); - } - - @Provides - DefaultWorldConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(DefaultWorldConfig.class); - } - - @Subscribe - public void onSessionOpen(SessionOpen event) - { - worldChangeRequired = true; - applyWorld(); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - applyWorld(); - } - - private void changeWorld(int newWorld) - { - if (!worldChangeRequired || client.getGameState() != GameState.LOGIN_SCREEN) - { - return; - } - - worldChangeRequired = false; - int correctedWorld = newWorld < 300 ? newWorld + 300 : newWorld; - - // Old School RuneScape worlds start on 301 so don't even bother trying to find lower id ones - // and also do not try to set world if we are already on it - if (correctedWorld <= 300 || client.getWorld() == correctedWorld) - { - return; - } - - try - { - final WorldResult worldResult = worldClient.lookupWorlds(); - final World world = worldResult.findWorld(correctedWorld); - - if (world != null) - { - final net.runelite.api.World rsWorld = client.createWorld(); - rsWorld.setActivity(world.getActivity()); - rsWorld.setAddress(world.getAddress()); - rsWorld.setId(world.getId()); - rsWorld.setPlayerCount(world.getPlayers()); - rsWorld.setLocation(world.getLocation()); - rsWorld.setTypes(WorldUtil.toWorldTypes(world.getTypes())); - - client.changeWorld(rsWorld); - log.debug("Applied new world {}", correctedWorld); - } - else - { - log.warn("World {} not found.", correctedWorld); - } - } - catch (IOException e) - { - log.warn("Error looking up world {}. Error: {}", correctedWorld, e); - } - } - - private void applyWorld() - { - if (worldCache == 0) - { - worldCache = client.getWorld(); - log.debug("Stored old world {}", worldCache); - } - - final int newWorld = config.getWorld(); - changeWorld(newWorld); - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * 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.defaultworld; + +import com.google.inject.Provides; +import java.io.IOException; +import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.events.GameStateChanged; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.WorldUtil; +import net.runelite.http.api.worlds.World; +import net.runelite.http.api.worlds.WorldClient; +import net.runelite.http.api.worlds.WorldResult; + +@PluginDescriptor( + name = "Default World", + description = "Enable a default world to be selected when launching the client", + tags = {"home"} +) +@Slf4j +public class DefaultWorldPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private DefaultWorldConfig config; + + private final WorldClient worldClient = new WorldClient(); + private int worldCache; + private boolean worldChangeRequired; + + @Override + protected void startUp() throws Exception + { + worldChangeRequired = true; + applyWorld(); + } + + @Override + protected void shutDown() throws Exception + { + worldChangeRequired = true; + changeWorld(worldCache); + } + + @Provides + DefaultWorldConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(DefaultWorldConfig.class); + } + + @Subscribe + public void onSessionOpen(SessionOpen event) + { + worldChangeRequired = true; + applyWorld(); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + applyWorld(); + } + + private void changeWorld(int newWorld) + { + if (!worldChangeRequired || client.getGameState() != GameState.LOGIN_SCREEN) + { + return; + } + + worldChangeRequired = false; + int correctedWorld = newWorld < 300 ? newWorld + 300 : newWorld; + + // Old School RuneScape worlds start on 301 so don't even bother trying to find lower id ones + // and also do not try to set world if we are already on it + if (correctedWorld <= 300 || client.getWorld() == correctedWorld) + { + return; + } + + try + { + final WorldResult worldResult = worldClient.lookupWorlds(); + final World world = worldResult.findWorld(correctedWorld); + + if (world != null) + { + final net.runelite.api.World rsWorld = client.createWorld(); + rsWorld.setActivity(world.getActivity()); + rsWorld.setAddress(world.getAddress()); + rsWorld.setId(world.getId()); + rsWorld.setPlayerCount(world.getPlayers()); + rsWorld.setLocation(world.getLocation()); + rsWorld.setTypes(WorldUtil.toWorldTypes(world.getTypes())); + + client.changeWorld(rsWorld); + log.debug("Applied new world {}", correctedWorld); + } + else + { + log.warn("World {} not found.", correctedWorld); + } + } + catch (IOException e) + { + log.warn("Error looking up world {}. Error: {}", correctedWorld, e); + } + } + + private void applyWorld() + { + if (worldCache == 0) + { + worldCache = client.getWorld(); + log.debug("Stored old world {}", worldCache); + } + + final int newWorld = config.getWorld(); + changeWorld(newWorld); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java index 2fa191d5ba..4396c71d73 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java @@ -1,154 +1,157 @@ -/* - * Copyright (c) 2018, Woox - * 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.demonicgorilla; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.geom.Arc2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.Skill; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -public class DemonicGorillaOverlay extends Overlay -{ - private static final Color COLOR_ICON_BACKGROUND = new Color(0, 0, 0, 128); - private static final Color COLOR_ICON_BORDER = new Color(0, 0, 0, 255); - private static final Color COLOR_ICON_BORDER_FILL = new Color(219, 175, 0, 255); - private static final int OVERLAY_ICON_DISTANCE = 50; - private static final int OVERLAY_ICON_MARGIN = 8; - - private Client client; - private DemonicGorillaPlugin plugin; - - @Inject - private SkillIconManager iconManager; - - @Inject - public DemonicGorillaOverlay(Client client, DemonicGorillaPlugin plugin) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.client = client; - this.plugin = plugin; - } - - private BufferedImage getIcon(DemonicGorilla.AttackStyle attackStyle) - { - switch (attackStyle) - { - case MELEE: return iconManager.getSkillImage(Skill.ATTACK); - case RANGED: return iconManager.getSkillImage(Skill.RANGED); - case MAGIC: return iconManager.getSkillImage(Skill.MAGIC); - } - return null; - } - - @Override - public Dimension render(Graphics2D graphics) - { - for (DemonicGorilla gorilla : plugin.getGorillas().values()) - { - if (gorilla.getNpc().getInteracting() == null) - { - continue; - } - - LocalPoint lp = gorilla.getNpc().getLocalLocation(); - if (lp != null) - { - Point point = Perspective.localToCanvas(client, lp, client.getPlane(), - gorilla.getNpc().getLogicalHeight() + 16); - if (point != null) - { - point = new Point(point.getX(), point.getY()); - - List attackStyles = gorilla.getNextPosibleAttackStyles(); - List icons = new ArrayList<>(); - int totalWidth = (attackStyles.size() - 1) * OVERLAY_ICON_MARGIN; - for (DemonicGorilla.AttackStyle attackStyle : attackStyles) - { - BufferedImage icon = getIcon(attackStyle); - icons.add(icon); - totalWidth += icon.getWidth(); - } - - int bgPadding = 4; - int currentPosX = 0; - for (BufferedImage icon : icons) - { - graphics.setStroke(new BasicStroke(2)); - graphics.setColor(COLOR_ICON_BACKGROUND); - graphics.fillOval( - point.getX() - totalWidth / 2 + currentPosX - bgPadding, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, - icon.getWidth() + bgPadding * 2, - icon.getHeight() + bgPadding * 2); - - graphics.setColor(COLOR_ICON_BORDER); - graphics.drawOval( - point.getX() - totalWidth / 2 + currentPosX - bgPadding, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, - icon.getWidth() + bgPadding * 2, - icon.getHeight() + bgPadding * 2); - - graphics.drawImage( - icon, - point.getX() - totalWidth / 2 + currentPosX, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE, - null); - - graphics.setColor(COLOR_ICON_BORDER_FILL); - Arc2D.Double arc = new Arc2D.Double( - point.getX() - totalWidth / 2 + currentPosX - bgPadding, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, - icon.getWidth() + bgPadding * 2, - icon.getHeight() + bgPadding * 2, - 90.0, - -360.0 * (DemonicGorilla.ATTACKS_PER_SWITCH - - gorilla.getAttacksUntilSwitch()) / DemonicGorilla.ATTACKS_PER_SWITCH, - Arc2D.OPEN); - graphics.draw(arc); - - currentPosX += icon.getWidth() + OVERLAY_ICON_MARGIN; - } - } - } - } - - return null; - } +/* + * Copyright (c) 2018, Woox + * 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.demonicgorilla; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Arc2D; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.Skill; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.game.SkillIconManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +public class DemonicGorillaOverlay extends Overlay +{ + private static final Color COLOR_ICON_BACKGROUND = new Color(0, 0, 0, 128); + private static final Color COLOR_ICON_BORDER = new Color(0, 0, 0, 255); + private static final Color COLOR_ICON_BORDER_FILL = new Color(219, 175, 0, 255); + private static final int OVERLAY_ICON_DISTANCE = 50; + private static final int OVERLAY_ICON_MARGIN = 8; + + private Client client; + private DemonicGorillaPlugin plugin; + + @Inject + private SkillIconManager iconManager; + + @Inject + public DemonicGorillaOverlay(Client client, DemonicGorillaPlugin plugin) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.client = client; + this.plugin = plugin; + } + + private BufferedImage getIcon(DemonicGorilla.AttackStyle attackStyle) + { + switch (attackStyle) + { + case MELEE: + return iconManager.getSkillImage(Skill.ATTACK); + case RANGED: + return iconManager.getSkillImage(Skill.RANGED); + case MAGIC: + return iconManager.getSkillImage(Skill.MAGIC); + } + return null; + } + + @Override + public Dimension render(Graphics2D graphics) + { + for (DemonicGorilla gorilla : plugin.getGorillas().values()) + { + if (gorilla.getNpc().getInteracting() == null) + { + continue; + } + + LocalPoint lp = gorilla.getNpc().getLocalLocation(); + if (lp != null) + { + Point point = Perspective.localToCanvas(client, lp, client.getPlane(), + gorilla.getNpc().getLogicalHeight() + 16); + if (point != null) + { + point = new Point(point.getX(), point.getY()); + + List attackStyles = gorilla.getNextPosibleAttackStyles(); + List icons = new ArrayList<>(); + int totalWidth = (attackStyles.size() - 1) * OVERLAY_ICON_MARGIN; + for (DemonicGorilla.AttackStyle attackStyle : attackStyles) + { + BufferedImage icon = getIcon(attackStyle); + icons.add(icon); + totalWidth += icon.getWidth(); + } + + int bgPadding = 4; + int currentPosX = 0; + for (BufferedImage icon : icons) + { + graphics.setStroke(new BasicStroke(2)); + graphics.setColor(COLOR_ICON_BACKGROUND); + graphics.fillOval( + point.getX() - totalWidth / 2 + currentPosX - bgPadding, + point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, + icon.getWidth() + bgPadding * 2, + icon.getHeight() + bgPadding * 2); + + graphics.setColor(COLOR_ICON_BORDER); + graphics.drawOval( + point.getX() - totalWidth / 2 + currentPosX - bgPadding, + point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, + icon.getWidth() + bgPadding * 2, + icon.getHeight() + bgPadding * 2); + + graphics.drawImage( + icon, + point.getX() - totalWidth / 2 + currentPosX, + point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE, + null); + + graphics.setColor(COLOR_ICON_BORDER_FILL); + Arc2D.Double arc = new Arc2D.Double( + point.getX() - totalWidth / 2 + currentPosX - bgPadding, + point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, + icon.getWidth() + bgPadding * 2, + icon.getHeight() + bgPadding * 2, + 90.0, + -360.0 * (DemonicGorilla.ATTACKS_PER_SWITCH - + gorilla.getAttacksUntilSwitch()) / DemonicGorilla.ATTACKS_PER_SWITCH, + Arc2D.OPEN); + graphics.draw(arc); + + currentPosX += icon.getWidth() + OVERLAY_ICON_MARGIN; + } + } + } + } + + return null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java index 0e9660b918..e0bc04dfad 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java @@ -1,716 +1,716 @@ -/* - * Copyright (c) 2018, Woox - * 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.demonicgorilla; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.AnimationID; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.HeadIcon; -import net.runelite.api.Hitsplat; -import net.runelite.api.NPC; -import net.runelite.api.NpcID; -import net.runelite.api.Player; -import net.runelite.api.Projectile; -import net.runelite.api.ProjectileID; -import net.runelite.api.coords.WorldArea; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.HitsplatApplied; -import net.runelite.api.events.NpcDespawned; -import net.runelite.api.events.NpcSpawned; -import net.runelite.api.events.PlayerDespawned; -import net.runelite.api.events.PlayerSpawned; -import net.runelite.api.events.ProjectileMoved; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "Demonic Gorillas", - description = "Count demonic gorilla attacks and display their next possible attack styles", - tags = {"combat", "overlay", "pve", "pvm"} -) -public class DemonicGorillaPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private OverlayManager overlayManager; - - @Inject - private DemonicGorillaOverlay overlay; - - @Inject - private ClientThread clientThread; - - @Getter - private Map gorillas; - - private List recentBoulders; - - private List pendingAttacks; - - private Map memorizedPlayers; - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - gorillas = new HashMap<>(); - recentBoulders = new ArrayList<>(); - pendingAttacks = new ArrayList<>(); - memorizedPlayers = new HashMap<>(); - clientThread.invoke(this::reset); // Updates the list of gorillas and players - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - gorillas = null; - recentBoulders = null; - pendingAttacks = null; - memorizedPlayers = null; - } - - private void clear() - { - recentBoulders.clear(); - pendingAttacks.clear(); - memorizedPlayers.clear(); - gorillas.clear(); - } - - private void reset() - { - recentBoulders.clear(); - pendingAttacks.clear(); - resetGorillas(); - resetPlayers(); - } - - private void resetGorillas() - { - gorillas.clear(); - for (NPC npc : client.getNpcs()) - { - if (isNpcGorilla(npc.getId())) - { - gorillas.put(npc, new DemonicGorilla(npc)); - } - } - } - - private void resetPlayers() - { - memorizedPlayers.clear(); - for (Player player : client.getPlayers()) - { - memorizedPlayers.put(player, new MemorizedPlayer(player)); - } - } - - public static boolean isNpcGorilla(int npcId) - { - return npcId == NpcID.DEMONIC_GORILLA || - npcId == NpcID.DEMONIC_GORILLA_7145 || - npcId == NpcID.DEMONIC_GORILLA_7146 || - npcId == NpcID.DEMONIC_GORILLA_7147 || - npcId == NpcID.DEMONIC_GORILLA_7148 || - npcId == NpcID.DEMONIC_GORILLA_7149; - } - - private void checkGorillaAttackStyleSwitch(DemonicGorilla gorilla, - final DemonicGorilla.AttackStyle... protectedStyles) - { - if (gorilla.getAttacksUntilSwitch() <= 0 || - gorilla.getNextPosibleAttackStyles().isEmpty()) - { - gorilla.setNextPosibleAttackStyles(Arrays - .stream(DemonicGorilla.ALL_REGULAR_ATTACK_STYLES) - .filter(x -> Arrays.stream(protectedStyles).noneMatch(y -> x == y)) - .collect(Collectors.toList())); - gorilla.setAttacksUntilSwitch(DemonicGorilla.ATTACKS_PER_SWITCH); - gorilla.setChangedAttackStyleThisTick(true); - } - } - - private DemonicGorilla.AttackStyle getProtectedStyle(Player player) - { - HeadIcon headIcon = player.getOverheadIcon(); - if (headIcon == null) - { - return null; - } - switch (headIcon) - { - case MELEE: - return DemonicGorilla.AttackStyle.MELEE; - case RANGED: - return DemonicGorilla.AttackStyle.RANGED; - case MAGIC: - return DemonicGorilla.AttackStyle.MAGIC; - default: - return null; - } - } - - private void onGorillaAttack(DemonicGorilla gorilla, final DemonicGorilla.AttackStyle attackStyle) - { - gorilla.setInitiatedCombat(true); - - Player target = (Player)gorilla.getNpc().getInteracting(); - - DemonicGorilla.AttackStyle protectedStyle = null; - if (target != null) - { - protectedStyle = getProtectedStyle(target); - } - boolean correctPrayer = - target == null || // If player is out of memory, assume prayer was correct - attackStyle == protectedStyle; - - if (attackStyle == DemonicGorilla.AttackStyle.BOULDER) - { - // The gorilla can't throw boulders when it's meleeing - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - else - { - if (correctPrayer) - { - gorilla.setAttacksUntilSwitch(gorilla.getAttacksUntilSwitch() - 1); - } - else - { - // We're not sure if the attack will hit a 0 or not, - // so we don't know if we should decrease the counter or not, - // so we keep track of the attack here until the damage splat - // has appeared on the player. - - int damagesOnTick = client.getTickCount(); - if (attackStyle == DemonicGorilla.AttackStyle.MAGIC) - { - MemorizedPlayer mp = memorizedPlayers.get(target); - WorldArea lastPlayerArea = mp.getLastWorldArea(); - if (lastPlayerArea != null) - { - int dist = gorilla.getNpc().getWorldArea().distanceTo(lastPlayerArea); - damagesOnTick += (dist + DemonicGorilla.PROJECTILE_MAGIC_DELAY) / - DemonicGorilla.PROJECTILE_MAGIC_SPEED; - } - } - else if (attackStyle == DemonicGorilla.AttackStyle.RANGED) - { - MemorizedPlayer mp = memorizedPlayers.get(target); - WorldArea lastPlayerArea = mp.getLastWorldArea(); - if (lastPlayerArea != null) - { - int dist = gorilla.getNpc().getWorldArea().distanceTo(lastPlayerArea); - damagesOnTick += (dist + DemonicGorilla.PROJECTILE_RANGED_DELAY) / - DemonicGorilla.PROJECTILE_RANGED_SPEED; - } - } - pendingAttacks.add(new PendingGorillaAttack(gorilla, attackStyle, target, damagesOnTick)); - } - - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x == attackStyle) - .collect(Collectors.toList())); - - if (gorilla.getNextPosibleAttackStyles().isEmpty()) - { - // Sometimes the gorilla can switch attack style before it's supposed to - // if someone was fighting it earlier and then left, so we just - // reset the counter in that case. - - gorilla.setNextPosibleAttackStyles(Arrays - .stream(DemonicGorilla.ALL_REGULAR_ATTACK_STYLES) - .filter(x -> x == attackStyle) - .collect(Collectors.toList())); - gorilla.setAttacksUntilSwitch(DemonicGorilla.ATTACKS_PER_SWITCH - - (correctPrayer ? 1 : 0)); - } - } - - checkGorillaAttackStyleSwitch(gorilla, protectedStyle); - - int tickCounter = client.getTickCount(); - gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE); - } - - private void checkGorillaAttacks() - { - int tickCounter = client.getTickCount(); - for (DemonicGorilla gorilla : gorillas.values()) - { - Player interacting = (Player)gorilla.getNpc().getInteracting(); - MemorizedPlayer mp = memorizedPlayers.get(interacting); - - if (gorilla.getLastTickInteracting() != null && interacting == null) - { - gorilla.setInitiatedCombat(false); - } - else if (mp != null && mp.getLastWorldArea() != null && - !gorilla.isInitiatedCombat() && - tickCounter < gorilla.getNextAttackTick() && - gorilla.getNpc().getWorldArea().isInMeleeDistance(mp.getLastWorldArea())) - { - gorilla.setInitiatedCombat(true); - gorilla.setNextAttackTick(tickCounter + 1); - } - - int animationId = gorilla.getNpc().getAnimation(); - - if (gorilla.isTakenDamageRecently() && - tickCounter >= gorilla.getNextAttackTick() + 4) - { - // The gorilla was flinched, so its next attack gets delayed - gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE / 2); - gorilla.setInitiatedCombat(true); - - if (mp != null && mp.getLastWorldArea() != null && - !gorilla.getNpc().getWorldArea().isInMeleeDistance(mp.getLastWorldArea()) && - !gorilla.getNpc().getWorldArea().intersectsWith(mp.getLastWorldArea())) - { - // Gorillas stop meleeing when they get flinched - // and the target isn't in melee distance - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - checkGorillaAttackStyleSwitch(gorilla, DemonicGorilla.AttackStyle.MELEE, - getProtectedStyle(interacting)); - } - } - else if (animationId != gorilla.getLastTickAnimation()) - { - if (animationId == AnimationID.DEMONIC_GORILLA_MELEE_ATTACK) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MELEE); - } - else if (animationId == AnimationID.DEMONIC_GORILLA_MAGIC_ATTACK) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MAGIC); - } - else if (animationId == AnimationID.DEMONIC_GORILLA_RANGED_ATTACK) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.RANGED); - } - else if (animationId == AnimationID.DEMONIC_GORILLA_AOE_ATTACK && interacting != null) - { - // Note that AoE animation is the same as prayer switch animation - // so we need to check if the prayer was switched or not. - // It also does this animation when it spawns, so - // we need the interacting != null check. - - if (gorilla.getOverheadIcon() == gorilla.getLastTickOverheadIcon()) - { - // Confirmed, the gorilla used the AoE attack - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.BOULDER); - } - else - { - if (tickCounter >= gorilla.getNextAttackTick()) - { - gorilla.setChangedPrayerThisTick(true); - - // This part is more complicated because the gorilla may have - // used an attack, but the prayer switch animation takes - // priority over normal attack animations. - - int projectileId = gorilla.getRecentProjectileId(); - if (projectileId == ProjectileID.DEMONIC_GORILLA_MAGIC) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MAGIC); - } - else if (projectileId == ProjectileID.DEMONIC_GORILLA_RANGED) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.RANGED); - } - else if (mp != null) - { - WorldArea lastPlayerArea = mp.getLastWorldArea(); - if (lastPlayerArea != null && - interacting != null && recentBoulders.stream() - .anyMatch(x -> x.distanceTo(lastPlayerArea) == 0)) - { - // A boulder started falling on the gorillas target, - // so we assume it was the gorilla who shot it - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.BOULDER); - } - else if (!mp.getRecentHitsplats().isEmpty()) - { - // It wasn't any of the three other attacks, - // but the player took damage, so we assume - // it's a melee attack - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MELEE); - } - } - } - - // The next attack tick is always delayed if the - // gorilla switched prayer - gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE); - gorilla.setChangedPrayerThisTick(true); - } - } - } - - if (gorilla.getDisabledMeleeMovementForTicks() > 0) - { - gorilla.setDisabledMeleeMovementForTicks(gorilla.getDisabledMeleeMovementForTicks() - 1); - } - else if (gorilla.isInitiatedCombat() && - gorilla.getNpc().getInteracting() != null && - !gorilla.isChangedAttackStyleThisTick() && - gorilla.getNextPosibleAttackStyles().size() >= 2 && - gorilla.getNextPosibleAttackStyles().stream() - .anyMatch(x -> x == DemonicGorilla.AttackStyle.MELEE)) - { - // If melee is a possibility, we can check if the gorilla - // is or isn't moving toward the player to determine if - // it is actually attempting to melee or not. - // We only run this check if the gorilla is in combat - // because otherwise it attempts to travel to melee - // distance before attacking its target. - - if (mp != null && mp.getLastWorldArea() != null && gorilla.getLastWorldArea() != null) - { - WorldArea predictedNewArea = gorilla.getLastWorldArea().calculateNextTravellingPoint( - client, mp.getLastWorldArea(), true, x -> - { - // Gorillas can't normally walk through other gorillas - // or other players - final WorldArea area1 = new WorldArea(x, 1, 1); - return area1 != null && - gorillas.values().stream().noneMatch(y -> - { - if (y == gorilla) - { - return false; - } - final WorldArea area2 = - y.getNpc().getIndex() < gorilla.getNpc().getIndex() ? - y.getNpc().getWorldArea() : y.getLastWorldArea(); - return area2 != null && area1.intersectsWith(area2); - }) && - memorizedPlayers.values().stream().noneMatch(y -> - { - final WorldArea area2 = y.getLastWorldArea(); - return area2 != null && area1.intersectsWith(area2); - }); - - // There is a special case where if a player walked through - // a gorilla, or a player walked through another player, - // the tiles that were walked through becomes - // walkable, but I didn't feel like it's necessary to handle - // that special case as it should rarely happen. - }); - if (predictedNewArea != null) - { - int distance = gorilla.getNpc().getWorldArea().distanceTo(mp.getLastWorldArea()); - WorldPoint predictedMovement = predictedNewArea.toWorldPoint(); - if (distance <= DemonicGorilla.MAX_ATTACK_RANGE && - mp != null && - mp.getLastWorldArea().hasLineOfSightTo(client, gorilla.getLastWorldArea())) - { - if (predictedMovement.distanceTo(gorilla.getLastWorldArea().toWorldPoint()) != 0) - { - if (predictedMovement.distanceTo(gorilla.getNpc().getWorldLocation()) == 0) - { - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x == DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - else - { - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - } - else if (tickCounter >= gorilla.getNextAttackTick() && - gorilla.getRecentProjectileId() == -1 && - recentBoulders.stream().noneMatch(x -> x.distanceTo(mp.getLastWorldArea()) == 0)) - { - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x == DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - } - } - } - } - - if (gorilla.isTakenDamageRecently()) - { - gorilla.setInitiatedCombat(true); - } - - if (gorilla.getOverheadIcon() != gorilla.getLastTickOverheadIcon()) - { - if (gorilla.isChangedAttackStyleLastTick() || - gorilla.isChangedAttackStyleThisTick()) - { - // Apparently if it changes attack style and changes - // prayer on the same tick or 1 tick apart, it won't - // be able to move for the next 2 ticks if it attempts - // to melee - gorilla.setDisabledMeleeMovementForTicks(2); - } - else - { - // If it didn't change attack style lately, - // it's only for the next 1 tick - gorilla.setDisabledMeleeMovementForTicks(1); - } - } - gorilla.setLastTickAnimation(gorilla.getNpc().getAnimation()); - gorilla.setLastWorldArea(gorilla.getNpc().getWorldArea()); - gorilla.setLastTickInteracting(gorilla.getNpc().getInteracting()); - gorilla.setTakenDamageRecently(false); - gorilla.setChangedPrayerThisTick(false); - gorilla.setChangedAttackStyleLastTick(gorilla.isChangedAttackStyleThisTick()); - gorilla.setChangedAttackStyleThisTick(false); - gorilla.setLastTickOverheadIcon(gorilla.getOverheadIcon()); - gorilla.setRecentProjectileId(-1); - } - } - - @Subscribe - public void onProjectileMoved(ProjectileMoved event) - { - Projectile projectile = event.getProjectile(); - int projectileId = projectile.getId(); - if (projectileId != ProjectileID.DEMONIC_GORILLA_RANGED && - projectileId != ProjectileID.DEMONIC_GORILLA_MAGIC && - projectileId != ProjectileID.DEMONIC_GORILLA_BOULDER) - { - return; - } - - // The event fires once before the projectile starts moving, - // and we only want to check each projectile once - if (client.getGameCycle() >= projectile.getStartMovementCycle()) - { - return; - } - - if (projectileId == ProjectileID.DEMONIC_GORILLA_BOULDER) - { - recentBoulders.add(WorldPoint.fromLocal(client, event.getPosition())); - } - else if (projectileId == ProjectileID.DEMONIC_GORILLA_MAGIC || - projectileId == ProjectileID.DEMONIC_GORILLA_RANGED) - { - WorldPoint projectileSourcePosition = WorldPoint.fromLocal( - client, projectile.getX1(), projectile.getY1(), client.getPlane()); - for (DemonicGorilla gorilla : gorillas.values()) - { - if (gorilla.getNpc().getWorldLocation().distanceTo(projectileSourcePosition) == 0) - { - gorilla.setRecentProjectileId(projectile.getId()); - } - } - } - } - - private void checkPendingAttacks() - { - Iterator it = pendingAttacks.iterator(); - int tickCounter = client.getTickCount(); - while (it.hasNext()) - { - PendingGorillaAttack attack = it.next(); - if (tickCounter >= attack.getFinishesOnTick()) - { - boolean shouldDecreaseCounter = false; - DemonicGorilla gorilla = attack.getAttacker(); - MemorizedPlayer target = memorizedPlayers.get(attack.getTarget()); - if (target == null) - { - // Player went out of memory, so assume the hit was a 0 - shouldDecreaseCounter = true; - } - else if (target.getRecentHitsplats().isEmpty()) - { - // No hitsplats was applied. This may happen in some cases - // where the player was out of memory while the - // projectile was travelling. So we assume the hit was a 0. - shouldDecreaseCounter = true; - } - else if (target.getRecentHitsplats().stream() - .anyMatch(x -> x.getHitsplatType() == Hitsplat.HitsplatType.BLOCK)) - { - // A blue hitsplat appeared, so we assume the gorilla hit a 0 - shouldDecreaseCounter = true; - } - - if (shouldDecreaseCounter) - { - gorilla.setAttacksUntilSwitch(gorilla.getAttacksUntilSwitch() - 1); - checkGorillaAttackStyleSwitch(gorilla); - } - - it.remove(); - } - } - } - - private void updatePlayers() - { - for (MemorizedPlayer mp : memorizedPlayers.values()) - { - mp.setLastWorldArea(mp.getPlayer().getWorldArea()); - mp.getRecentHitsplats().clear(); - } - } - - @Subscribe - public void onHitsplatApplied(HitsplatApplied event) - { - if (gorillas.isEmpty()) - { - return; - } - - if (event.getActor() instanceof Player) - { - Player player = (Player)event.getActor(); - MemorizedPlayer mp = memorizedPlayers.get(player); - if (mp != null) - { - mp.getRecentHitsplats().add(event.getHitsplat()); - } - } - else if (event.getActor() instanceof NPC) - { - DemonicGorilla gorilla = gorillas.get(event.getActor()); - Hitsplat.HitsplatType hitsplatType = event.getHitsplat().getHitsplatType(); - if (gorilla != null && (hitsplatType == Hitsplat.HitsplatType.BLOCK || - hitsplatType == Hitsplat.HitsplatType.DAMAGE)) - { - gorilla.setTakenDamageRecently(true); - } - } - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - GameState gs = event.getGameState(); - if (gs == GameState.LOGGING_IN || - gs == GameState.CONNECTION_LOST || - gs == GameState.HOPPING) - { - reset(); - } - } - - @Subscribe - public void onPlayerSpawned(PlayerSpawned event) - { - if (gorillas.isEmpty()) - { - return; - } - - Player player = event.getPlayer(); - memorizedPlayers.put(player, new MemorizedPlayer(player)); - } - - @Subscribe - public void onPlayerDespawned(PlayerDespawned event) - { - if (gorillas.isEmpty()) - { - return; - } - - memorizedPlayers.remove(event.getPlayer()); - } - - @Subscribe - public void onNpcSpawned(NpcSpawned event) - { - NPC npc = event.getNpc(); - if (isNpcGorilla(npc.getId())) - { - if (gorillas.isEmpty()) - { - // Players are not kept track of when there are no gorillas in - // memory, so we need to add the players that were already in memory. - resetPlayers(); - } - - gorillas.put(npc, new DemonicGorilla(npc)); - } - } - - @Subscribe - public void onNpcDespawned(NpcDespawned event) - { - if (gorillas.remove(event.getNpc()) != null && gorillas.isEmpty()) - { - clear(); - } - } - - @Subscribe - public void onGameTick(GameTick event) - { - checkGorillaAttacks(); - checkPendingAttacks(); - updatePlayers(); - recentBoulders.clear(); - } +/* + * Copyright (c) 2018, Woox + * 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.demonicgorilla; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.AnimationID; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HeadIcon; +import net.runelite.api.Hitsplat; +import net.runelite.api.NPC; +import net.runelite.api.NpcID; +import net.runelite.api.Player; +import net.runelite.api.Projectile; +import net.runelite.api.ProjectileID; +import net.runelite.api.coords.WorldArea; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.HitsplatApplied; +import net.runelite.api.events.NpcDespawned; +import net.runelite.api.events.NpcSpawned; +import net.runelite.api.events.PlayerDespawned; +import net.runelite.api.events.PlayerSpawned; +import net.runelite.api.events.ProjectileMoved; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Demonic Gorillas", + description = "Count demonic gorilla attacks and display their next possible attack styles", + tags = {"combat", "overlay", "pve", "pvm"} +) +public class DemonicGorillaPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private DemonicGorillaOverlay overlay; + + @Inject + private ClientThread clientThread; + + @Getter + private Map gorillas; + + private List recentBoulders; + + private List pendingAttacks; + + private Map memorizedPlayers; + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + gorillas = new HashMap<>(); + recentBoulders = new ArrayList<>(); + pendingAttacks = new ArrayList<>(); + memorizedPlayers = new HashMap<>(); + clientThread.invoke(this::reset); // Updates the list of gorillas and players + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + gorillas = null; + recentBoulders = null; + pendingAttacks = null; + memorizedPlayers = null; + } + + private void clear() + { + recentBoulders.clear(); + pendingAttacks.clear(); + memorizedPlayers.clear(); + gorillas.clear(); + } + + private void reset() + { + recentBoulders.clear(); + pendingAttacks.clear(); + resetGorillas(); + resetPlayers(); + } + + private void resetGorillas() + { + gorillas.clear(); + for (NPC npc : client.getNpcs()) + { + if (isNpcGorilla(npc.getId())) + { + gorillas.put(npc, new DemonicGorilla(npc)); + } + } + } + + private void resetPlayers() + { + memorizedPlayers.clear(); + for (Player player : client.getPlayers()) + { + memorizedPlayers.put(player, new MemorizedPlayer(player)); + } + } + + public static boolean isNpcGorilla(int npcId) + { + return npcId == NpcID.DEMONIC_GORILLA || + npcId == NpcID.DEMONIC_GORILLA_7145 || + npcId == NpcID.DEMONIC_GORILLA_7146 || + npcId == NpcID.DEMONIC_GORILLA_7147 || + npcId == NpcID.DEMONIC_GORILLA_7148 || + npcId == NpcID.DEMONIC_GORILLA_7149; + } + + private void checkGorillaAttackStyleSwitch(DemonicGorilla gorilla, + final DemonicGorilla.AttackStyle... protectedStyles) + { + if (gorilla.getAttacksUntilSwitch() <= 0 || + gorilla.getNextPosibleAttackStyles().isEmpty()) + { + gorilla.setNextPosibleAttackStyles(Arrays + .stream(DemonicGorilla.ALL_REGULAR_ATTACK_STYLES) + .filter(x -> Arrays.stream(protectedStyles).noneMatch(y -> x == y)) + .collect(Collectors.toList())); + gorilla.setAttacksUntilSwitch(DemonicGorilla.ATTACKS_PER_SWITCH); + gorilla.setChangedAttackStyleThisTick(true); + } + } + + private DemonicGorilla.AttackStyle getProtectedStyle(Player player) + { + HeadIcon headIcon = player.getOverheadIcon(); + if (headIcon == null) + { + return null; + } + switch (headIcon) + { + case MELEE: + return DemonicGorilla.AttackStyle.MELEE; + case RANGED: + return DemonicGorilla.AttackStyle.RANGED; + case MAGIC: + return DemonicGorilla.AttackStyle.MAGIC; + default: + return null; + } + } + + private void onGorillaAttack(DemonicGorilla gorilla, final DemonicGorilla.AttackStyle attackStyle) + { + gorilla.setInitiatedCombat(true); + + Player target = (Player) gorilla.getNpc().getInteracting(); + + DemonicGorilla.AttackStyle protectedStyle = null; + if (target != null) + { + protectedStyle = getProtectedStyle(target); + } + boolean correctPrayer = + target == null || // If player is out of memory, assume prayer was correct + attackStyle == protectedStyle; + + if (attackStyle == DemonicGorilla.AttackStyle.BOULDER) + { + // The gorilla can't throw boulders when it's meleeing + gorilla.setNextPosibleAttackStyles(gorilla + .getNextPosibleAttackStyles() + .stream() + .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) + .collect(Collectors.toList())); + } + else + { + if (correctPrayer) + { + gorilla.setAttacksUntilSwitch(gorilla.getAttacksUntilSwitch() - 1); + } + else + { + // We're not sure if the attack will hit a 0 or not, + // so we don't know if we should decrease the counter or not, + // so we keep track of the attack here until the damage splat + // has appeared on the player. + + int damagesOnTick = client.getTickCount(); + if (attackStyle == DemonicGorilla.AttackStyle.MAGIC) + { + MemorizedPlayer mp = memorizedPlayers.get(target); + WorldArea lastPlayerArea = mp.getLastWorldArea(); + if (lastPlayerArea != null) + { + int dist = gorilla.getNpc().getWorldArea().distanceTo(lastPlayerArea); + damagesOnTick += (dist + DemonicGorilla.PROJECTILE_MAGIC_DELAY) / + DemonicGorilla.PROJECTILE_MAGIC_SPEED; + } + } + else if (attackStyle == DemonicGorilla.AttackStyle.RANGED) + { + MemorizedPlayer mp = memorizedPlayers.get(target); + WorldArea lastPlayerArea = mp.getLastWorldArea(); + if (lastPlayerArea != null) + { + int dist = gorilla.getNpc().getWorldArea().distanceTo(lastPlayerArea); + damagesOnTick += (dist + DemonicGorilla.PROJECTILE_RANGED_DELAY) / + DemonicGorilla.PROJECTILE_RANGED_SPEED; + } + } + pendingAttacks.add(new PendingGorillaAttack(gorilla, attackStyle, target, damagesOnTick)); + } + + gorilla.setNextPosibleAttackStyles(gorilla + .getNextPosibleAttackStyles() + .stream() + .filter(x -> x == attackStyle) + .collect(Collectors.toList())); + + if (gorilla.getNextPosibleAttackStyles().isEmpty()) + { + // Sometimes the gorilla can switch attack style before it's supposed to + // if someone was fighting it earlier and then left, so we just + // reset the counter in that case. + + gorilla.setNextPosibleAttackStyles(Arrays + .stream(DemonicGorilla.ALL_REGULAR_ATTACK_STYLES) + .filter(x -> x == attackStyle) + .collect(Collectors.toList())); + gorilla.setAttacksUntilSwitch(DemonicGorilla.ATTACKS_PER_SWITCH - + (correctPrayer ? 1 : 0)); + } + } + + checkGorillaAttackStyleSwitch(gorilla, protectedStyle); + + int tickCounter = client.getTickCount(); + gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE); + } + + private void checkGorillaAttacks() + { + int tickCounter = client.getTickCount(); + for (DemonicGorilla gorilla : gorillas.values()) + { + Player interacting = (Player) gorilla.getNpc().getInteracting(); + MemorizedPlayer mp = memorizedPlayers.get(interacting); + + if (gorilla.getLastTickInteracting() != null && interacting == null) + { + gorilla.setInitiatedCombat(false); + } + else if (mp != null && mp.getLastWorldArea() != null && + !gorilla.isInitiatedCombat() && + tickCounter < gorilla.getNextAttackTick() && + gorilla.getNpc().getWorldArea().isInMeleeDistance(mp.getLastWorldArea())) + { + gorilla.setInitiatedCombat(true); + gorilla.setNextAttackTick(tickCounter + 1); + } + + int animationId = gorilla.getNpc().getAnimation(); + + if (gorilla.isTakenDamageRecently() && + tickCounter >= gorilla.getNextAttackTick() + 4) + { + // The gorilla was flinched, so its next attack gets delayed + gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE / 2); + gorilla.setInitiatedCombat(true); + + if (mp != null && mp.getLastWorldArea() != null && + !gorilla.getNpc().getWorldArea().isInMeleeDistance(mp.getLastWorldArea()) && + !gorilla.getNpc().getWorldArea().intersectsWith(mp.getLastWorldArea())) + { + // Gorillas stop meleeing when they get flinched + // and the target isn't in melee distance + gorilla.setNextPosibleAttackStyles(gorilla + .getNextPosibleAttackStyles() + .stream() + .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) + .collect(Collectors.toList())); + checkGorillaAttackStyleSwitch(gorilla, DemonicGorilla.AttackStyle.MELEE, + getProtectedStyle(interacting)); + } + } + else if (animationId != gorilla.getLastTickAnimation()) + { + if (animationId == AnimationID.DEMONIC_GORILLA_MELEE_ATTACK) + { + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MELEE); + } + else if (animationId == AnimationID.DEMONIC_GORILLA_MAGIC_ATTACK) + { + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MAGIC); + } + else if (animationId == AnimationID.DEMONIC_GORILLA_RANGED_ATTACK) + { + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.RANGED); + } + else if (animationId == AnimationID.DEMONIC_GORILLA_AOE_ATTACK && interacting != null) + { + // Note that AoE animation is the same as prayer switch animation + // so we need to check if the prayer was switched or not. + // It also does this animation when it spawns, so + // we need the interacting != null check. + + if (gorilla.getOverheadIcon() == gorilla.getLastTickOverheadIcon()) + { + // Confirmed, the gorilla used the AoE attack + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.BOULDER); + } + else + { + if (tickCounter >= gorilla.getNextAttackTick()) + { + gorilla.setChangedPrayerThisTick(true); + + // This part is more complicated because the gorilla may have + // used an attack, but the prayer switch animation takes + // priority over normal attack animations. + + int projectileId = gorilla.getRecentProjectileId(); + if (projectileId == ProjectileID.DEMONIC_GORILLA_MAGIC) + { + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MAGIC); + } + else if (projectileId == ProjectileID.DEMONIC_GORILLA_RANGED) + { + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.RANGED); + } + else if (mp != null) + { + WorldArea lastPlayerArea = mp.getLastWorldArea(); + if (lastPlayerArea != null && + interacting != null && recentBoulders.stream() + .anyMatch(x -> x.distanceTo(lastPlayerArea) == 0)) + { + // A boulder started falling on the gorillas target, + // so we assume it was the gorilla who shot it + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.BOULDER); + } + else if (!mp.getRecentHitsplats().isEmpty()) + { + // It wasn't any of the three other attacks, + // but the player took damage, so we assume + // it's a melee attack + onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MELEE); + } + } + } + + // The next attack tick is always delayed if the + // gorilla switched prayer + gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE); + gorilla.setChangedPrayerThisTick(true); + } + } + } + + if (gorilla.getDisabledMeleeMovementForTicks() > 0) + { + gorilla.setDisabledMeleeMovementForTicks(gorilla.getDisabledMeleeMovementForTicks() - 1); + } + else if (gorilla.isInitiatedCombat() && + gorilla.getNpc().getInteracting() != null && + !gorilla.isChangedAttackStyleThisTick() && + gorilla.getNextPosibleAttackStyles().size() >= 2 && + gorilla.getNextPosibleAttackStyles().stream() + .anyMatch(x -> x == DemonicGorilla.AttackStyle.MELEE)) + { + // If melee is a possibility, we can check if the gorilla + // is or isn't moving toward the player to determine if + // it is actually attempting to melee or not. + // We only run this check if the gorilla is in combat + // because otherwise it attempts to travel to melee + // distance before attacking its target. + + if (mp != null && mp.getLastWorldArea() != null && gorilla.getLastWorldArea() != null) + { + WorldArea predictedNewArea = gorilla.getLastWorldArea().calculateNextTravellingPoint( + client, mp.getLastWorldArea(), true, x -> + { + // Gorillas can't normally walk through other gorillas + // or other players + final WorldArea area1 = new WorldArea(x, 1, 1); + return area1 != null && + gorillas.values().stream().noneMatch(y -> + { + if (y == gorilla) + { + return false; + } + final WorldArea area2 = + y.getNpc().getIndex() < gorilla.getNpc().getIndex() ? + y.getNpc().getWorldArea() : y.getLastWorldArea(); + return area2 != null && area1.intersectsWith(area2); + }) && + memorizedPlayers.values().stream().noneMatch(y -> + { + final WorldArea area2 = y.getLastWorldArea(); + return area2 != null && area1.intersectsWith(area2); + }); + + // There is a special case where if a player walked through + // a gorilla, or a player walked through another player, + // the tiles that were walked through becomes + // walkable, but I didn't feel like it's necessary to handle + // that special case as it should rarely happen. + }); + if (predictedNewArea != null) + { + int distance = gorilla.getNpc().getWorldArea().distanceTo(mp.getLastWorldArea()); + WorldPoint predictedMovement = predictedNewArea.toWorldPoint(); + if (distance <= DemonicGorilla.MAX_ATTACK_RANGE && + mp != null && + mp.getLastWorldArea().hasLineOfSightTo(client, gorilla.getLastWorldArea())) + { + if (predictedMovement.distanceTo(gorilla.getLastWorldArea().toWorldPoint()) != 0) + { + if (predictedMovement.distanceTo(gorilla.getNpc().getWorldLocation()) == 0) + { + gorilla.setNextPosibleAttackStyles(gorilla + .getNextPosibleAttackStyles() + .stream() + .filter(x -> x == DemonicGorilla.AttackStyle.MELEE) + .collect(Collectors.toList())); + } + else + { + gorilla.setNextPosibleAttackStyles(gorilla + .getNextPosibleAttackStyles() + .stream() + .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) + .collect(Collectors.toList())); + } + } + else if (tickCounter >= gorilla.getNextAttackTick() && + gorilla.getRecentProjectileId() == -1 && + recentBoulders.stream().noneMatch(x -> x.distanceTo(mp.getLastWorldArea()) == 0)) + { + gorilla.setNextPosibleAttackStyles(gorilla + .getNextPosibleAttackStyles() + .stream() + .filter(x -> x == DemonicGorilla.AttackStyle.MELEE) + .collect(Collectors.toList())); + } + } + } + } + } + + if (gorilla.isTakenDamageRecently()) + { + gorilla.setInitiatedCombat(true); + } + + if (gorilla.getOverheadIcon() != gorilla.getLastTickOverheadIcon()) + { + if (gorilla.isChangedAttackStyleLastTick() || + gorilla.isChangedAttackStyleThisTick()) + { + // Apparently if it changes attack style and changes + // prayer on the same tick or 1 tick apart, it won't + // be able to move for the next 2 ticks if it attempts + // to melee + gorilla.setDisabledMeleeMovementForTicks(2); + } + else + { + // If it didn't change attack style lately, + // it's only for the next 1 tick + gorilla.setDisabledMeleeMovementForTicks(1); + } + } + gorilla.setLastTickAnimation(gorilla.getNpc().getAnimation()); + gorilla.setLastWorldArea(gorilla.getNpc().getWorldArea()); + gorilla.setLastTickInteracting(gorilla.getNpc().getInteracting()); + gorilla.setTakenDamageRecently(false); + gorilla.setChangedPrayerThisTick(false); + gorilla.setChangedAttackStyleLastTick(gorilla.isChangedAttackStyleThisTick()); + gorilla.setChangedAttackStyleThisTick(false); + gorilla.setLastTickOverheadIcon(gorilla.getOverheadIcon()); + gorilla.setRecentProjectileId(-1); + } + } + + @Subscribe + public void onProjectileMoved(ProjectileMoved event) + { + Projectile projectile = event.getProjectile(); + int projectileId = projectile.getId(); + if (projectileId != ProjectileID.DEMONIC_GORILLA_RANGED && + projectileId != ProjectileID.DEMONIC_GORILLA_MAGIC && + projectileId != ProjectileID.DEMONIC_GORILLA_BOULDER) + { + return; + } + + // The event fires once before the projectile starts moving, + // and we only want to check each projectile once + if (client.getGameCycle() >= projectile.getStartMovementCycle()) + { + return; + } + + if (projectileId == ProjectileID.DEMONIC_GORILLA_BOULDER) + { + recentBoulders.add(WorldPoint.fromLocal(client, event.getPosition())); + } + else if (projectileId == ProjectileID.DEMONIC_GORILLA_MAGIC || + projectileId == ProjectileID.DEMONIC_GORILLA_RANGED) + { + WorldPoint projectileSourcePosition = WorldPoint.fromLocal( + client, projectile.getX1(), projectile.getY1(), client.getPlane()); + for (DemonicGorilla gorilla : gorillas.values()) + { + if (gorilla.getNpc().getWorldLocation().distanceTo(projectileSourcePosition) == 0) + { + gorilla.setRecentProjectileId(projectile.getId()); + } + } + } + } + + private void checkPendingAttacks() + { + Iterator it = pendingAttacks.iterator(); + int tickCounter = client.getTickCount(); + while (it.hasNext()) + { + PendingGorillaAttack attack = it.next(); + if (tickCounter >= attack.getFinishesOnTick()) + { + boolean shouldDecreaseCounter = false; + DemonicGorilla gorilla = attack.getAttacker(); + MemorizedPlayer target = memorizedPlayers.get(attack.getTarget()); + if (target == null) + { + // Player went out of memory, so assume the hit was a 0 + shouldDecreaseCounter = true; + } + else if (target.getRecentHitsplats().isEmpty()) + { + // No hitsplats was applied. This may happen in some cases + // where the player was out of memory while the + // projectile was travelling. So we assume the hit was a 0. + shouldDecreaseCounter = true; + } + else if (target.getRecentHitsplats().stream() + .anyMatch(x -> x.getHitsplatType() == Hitsplat.HitsplatType.BLOCK)) + { + // A blue hitsplat appeared, so we assume the gorilla hit a 0 + shouldDecreaseCounter = true; + } + + if (shouldDecreaseCounter) + { + gorilla.setAttacksUntilSwitch(gorilla.getAttacksUntilSwitch() - 1); + checkGorillaAttackStyleSwitch(gorilla); + } + + it.remove(); + } + } + } + + private void updatePlayers() + { + for (MemorizedPlayer mp : memorizedPlayers.values()) + { + mp.setLastWorldArea(mp.getPlayer().getWorldArea()); + mp.getRecentHitsplats().clear(); + } + } + + @Subscribe + public void onHitsplatApplied(HitsplatApplied event) + { + if (gorillas.isEmpty()) + { + return; + } + + if (event.getActor() instanceof Player) + { + Player player = (Player) event.getActor(); + MemorizedPlayer mp = memorizedPlayers.get(player); + if (mp != null) + { + mp.getRecentHitsplats().add(event.getHitsplat()); + } + } + else if (event.getActor() instanceof NPC) + { + DemonicGorilla gorilla = gorillas.get(event.getActor()); + Hitsplat.HitsplatType hitsplatType = event.getHitsplat().getHitsplatType(); + if (gorilla != null && (hitsplatType == Hitsplat.HitsplatType.BLOCK || + hitsplatType == Hitsplat.HitsplatType.DAMAGE)) + { + gorilla.setTakenDamageRecently(true); + } + } + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + GameState gs = event.getGameState(); + if (gs == GameState.LOGGING_IN || + gs == GameState.CONNECTION_LOST || + gs == GameState.HOPPING) + { + reset(); + } + } + + @Subscribe + public void onPlayerSpawned(PlayerSpawned event) + { + if (gorillas.isEmpty()) + { + return; + } + + Player player = event.getPlayer(); + memorizedPlayers.put(player, new MemorizedPlayer(player)); + } + + @Subscribe + public void onPlayerDespawned(PlayerDespawned event) + { + if (gorillas.isEmpty()) + { + return; + } + + memorizedPlayers.remove(event.getPlayer()); + } + + @Subscribe + public void onNpcSpawned(NpcSpawned event) + { + NPC npc = event.getNpc(); + if (isNpcGorilla(npc.getId())) + { + if (gorillas.isEmpty()) + { + // Players are not kept track of when there are no gorillas in + // memory, so we need to add the players that were already in memory. + resetPlayers(); + } + + gorillas.put(npc, new DemonicGorilla(npc)); + } + } + + @Subscribe + public void onNpcDespawned(NpcDespawned event) + { + if (gorillas.remove(event.getNpc()) != null && gorillas.isEmpty()) + { + clear(); + } + } + + @Subscribe + public void onGameTick(GameTick event) + { + checkGorillaAttacks(); + checkPendingAttacks(); + updatePlayers(); + recentBoulders.clear(); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/CameraOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/CameraOverlay.java index 882fe4201c..7a23ae3003 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/CameraOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/CameraOverlay.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2018, Matthew Steglinski - * 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.devtools; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -public class CameraOverlay extends Overlay -{ - private final Client client; - private final DevToolsPlugin plugin; - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - CameraOverlay(Client client, DevToolsPlugin plugin) - { - this.client = client; - this.plugin = plugin; - panelComponent.setPreferredSize(new Dimension(150, 0)); - setPosition(OverlayPosition.TOP_LEFT); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.getCameraPosition().isActive()) - { - return null; - } - - panelComponent.getChildren().clear(); - - panelComponent.getChildren().add(TitleComponent.builder() - .text("Camera") - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("X") - .right("" + client.getCameraX()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Y") - .right("" + client.getCameraY()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Z") - .right("" + client.getCameraZ()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Pitch") - .right("" + client.getCameraPitch()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Yaw") - .right("" + client.getCameraYaw()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Scale") - .right("" + client.getScale()) - .build()); - - return panelComponent.render(graphics); - } -} +/* + * Copyright (c) 2018, Matthew Steglinski + * 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.devtools; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +public class CameraOverlay extends Overlay +{ + private final Client client; + private final DevToolsPlugin plugin; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + CameraOverlay(Client client, DevToolsPlugin plugin) + { + this.client = client; + this.plugin = plugin; + panelComponent.setPreferredSize(new Dimension(150, 0)); + setPosition(OverlayPosition.TOP_LEFT); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.getCameraPosition().isActive()) + { + return null; + } + + panelComponent.getChildren().clear(); + + panelComponent.getChildren().add(TitleComponent.builder() + .text("Camera") + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("X") + .right("" + client.getCameraX()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Y") + .right("" + client.getCameraY()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Z") + .right("" + client.getCameraZ()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Pitch") + .right("" + client.getCameraPitch()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Yaw") + .right("" + client.getCameraYaw()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Scale") + .right("" + client.getScale()) + .build()); + + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java index d9a90b79fe..e3c42445cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java @@ -118,11 +118,11 @@ class DevToolsPanel extends PluginPanel varInspector.open(); } }); - + container.add(plugin.getLogMenuActions()); plugin.getLogMenuActions().addActionListener((ev) -> { - if(plugin.getLogMenuActions().isActive()) + if (plugin.getLogMenuActions().isActive()) { client.setPrintMenuActions(false); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java index 3b540d414d..4f77b25c26 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java @@ -71,7 +71,7 @@ import org.slf4j.LoggerFactory; public class DevToolsPlugin extends Plugin { private static final List EXAMINE_MENU_ACTIONS = ImmutableList.of(MenuAction.EXAMINE_ITEM, - MenuAction.EXAMINE_ITEM_GROUND, MenuAction.EXAMINE_NPC, MenuAction.EXAMINE_OBJECT); + MenuAction.EXAMINE_ITEM_GROUND, MenuAction.EXAMINE_NPC, MenuAction.EXAMINE_OBJECT); @Inject private Client client; @@ -119,7 +119,7 @@ public class DevToolsPlugin extends Plugin private DevToolsButton validMovement; private DevToolsButton lineOfSight; private DevToolsButton cameraPosition; - private DevToolsButton worldMapLocation ; + private DevToolsButton worldMapLocation; private DevToolsButton tileLocation; private DevToolsButton interacting; private DevToolsButton examine; @@ -174,7 +174,7 @@ public class DevToolsPlugin extends Plugin overlayManager.add(cameraOverlay); overlayManager.add(worldMapLocationOverlay); overlayManager.add(mapRegionOverlay); - + logMenuActions = new DevToolsButton("Menu Actions"); final DevToolsPanel panel = injector.getInstance(DevToolsPanel.class); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/LocationOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/LocationOverlay.java index e9f9d2b608..7caa1691fb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/LocationOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/LocationOverlay.java @@ -1,122 +1,122 @@ -/* - * Copyright (c) 2018, Seth - * 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.devtools; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import static net.runelite.api.Constants.CHUNK_SIZE; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; - -public class LocationOverlay extends Overlay -{ - private final Client client; - private final DevToolsPlugin plugin; - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - LocationOverlay(Client client, DevToolsPlugin plugin) - { - this.client = client; - this.plugin = plugin; - panelComponent.setPreferredSize(new Dimension(150, 0)); - setPosition(OverlayPosition.TOP_LEFT); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.getLocation().isActive()) - { - return null; - } - - panelComponent.getChildren().clear(); - WorldPoint localWorld = client.getLocalPlayer().getWorldLocation(); - LocalPoint localPoint = client.getLocalPlayer().getLocalLocation(); - - int regionID = localWorld.getRegionID(); - - if (client.isInInstancedRegion()) - { - panelComponent.getChildren().add(LineComponent.builder() - .left("Instance") - .build()); - - int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); - int z = client.getPlane(); - int chunkData = instanceTemplateChunks[z][localPoint.getSceneX() / CHUNK_SIZE][localPoint.getSceneY() / CHUNK_SIZE]; - - int rotation = chunkData >> 1 & 0x3; - int chunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; - int chunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; - - panelComponent.getChildren().add(LineComponent.builder() - .left("Chunk " + localPoint.getSceneX() / CHUNK_SIZE + "," + localPoint.getSceneY() / CHUNK_SIZE) - .right(rotation + " " + chunkX + " " + chunkY) - .build()); - } - - panelComponent.getChildren().add(LineComponent.builder() - .left("Base") - .right(client.getBaseX() + ", " + client.getBaseY()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Local") - .right(localPoint.getX() + ", " + localPoint.getY()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Scene") - .right(localPoint.getSceneX() + ", " + localPoint.getSceneY()) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Tile") - .right(localWorld.getX() + ", " + localWorld.getY() + ", " + client.getPlane()) - .build()); - - for (int i = 0; i < client.getMapRegions().length; i++) - { - int region = client.getMapRegions()[i]; - - panelComponent.getChildren().add(LineComponent.builder() - .left((i == 0) ? "Map regions" : " ") - .right(String.valueOf(region)) - .rightColor((region == regionID) ? Color.GREEN : Color.WHITE) - .build()); - } - - return panelComponent.render(graphics); - } -} +/* + * Copyright (c) 2018, Seth + * 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.devtools; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import static net.runelite.api.Constants.CHUNK_SIZE; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +public class LocationOverlay extends Overlay +{ + private final Client client; + private final DevToolsPlugin plugin; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + LocationOverlay(Client client, DevToolsPlugin plugin) + { + this.client = client; + this.plugin = plugin; + panelComponent.setPreferredSize(new Dimension(150, 0)); + setPosition(OverlayPosition.TOP_LEFT); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.getLocation().isActive()) + { + return null; + } + + panelComponent.getChildren().clear(); + WorldPoint localWorld = client.getLocalPlayer().getWorldLocation(); + LocalPoint localPoint = client.getLocalPlayer().getLocalLocation(); + + int regionID = localWorld.getRegionID(); + + if (client.isInInstancedRegion()) + { + panelComponent.getChildren().add(LineComponent.builder() + .left("Instance") + .build()); + + int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); + int z = client.getPlane(); + int chunkData = instanceTemplateChunks[z][localPoint.getSceneX() / CHUNK_SIZE][localPoint.getSceneY() / CHUNK_SIZE]; + + int rotation = chunkData >> 1 & 0x3; + int chunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; + int chunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; + + panelComponent.getChildren().add(LineComponent.builder() + .left("Chunk " + localPoint.getSceneX() / CHUNK_SIZE + "," + localPoint.getSceneY() / CHUNK_SIZE) + .right(rotation + " " + chunkX + " " + chunkY) + .build()); + } + + panelComponent.getChildren().add(LineComponent.builder() + .left("Base") + .right(client.getBaseX() + ", " + client.getBaseY()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Local") + .right(localPoint.getX() + ", " + localPoint.getY()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Scene") + .right(localPoint.getSceneX() + ", " + localPoint.getSceneY()) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Tile") + .right(localWorld.getX() + ", " + localWorld.getY() + ", " + client.getPlane()) + .build()); + + for (int i = 0; i < client.getMapRegions().length; i++) + { + int region = client.getMapRegions()[i]; + + panelComponent.getChildren().add(LineComponent.builder() + .left((i == 0) ? "Map regions" : " ") + .right(String.valueOf(region)) + .rightColor((region == regionID) ? Color.GREEN : Color.WHITE) + .build()); + } + + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WorldMapLocationOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WorldMapLocationOverlay.java index b109ef67ad..2d5542c1bc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WorldMapLocationOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WorldMapLocationOverlay.java @@ -1,106 +1,106 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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.devtools; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Point; -import net.runelite.api.RenderOverview; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay; - -public class WorldMapLocationOverlay extends Overlay -{ - private final Client client; - private final WorldMapOverlay worldMapOverlay; - private final DevToolsPlugin plugin; - - @Inject - private WorldMapLocationOverlay(Client client, WorldMapOverlay worldMapOverlay, DevToolsPlugin plugin) - { - this.client = client; - this.worldMapOverlay = worldMapOverlay; - this.plugin = plugin; - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.HIGH); - setLayer(OverlayLayer.ABOVE_MAP); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.getWorldMapLocation().isActive()) - { - return null; - } - - RenderOverview ro = client.getRenderOverview(); - Widget worldMapWidget = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); - - if (ro == null || worldMapWidget == null) - { - return null; - } - - Rectangle worldMapRectangle = worldMapWidget.getBounds(); - - graphics.setClip(worldMapRectangle); - graphics.setColor(Color.CYAN); - - WorldPoint mapCenterPoint = new WorldPoint(ro.getWorldMapPosition().getX(), ro.getWorldMapPosition().getY(), 0); - Point middle = worldMapOverlay.mapWorldPointToGraphicsPoint(mapCenterPoint); - - if (middle == null) - { - return null; - } - - graphics.drawLine(middle.getX(), worldMapRectangle.y, middle.getX(), worldMapRectangle.y + worldMapRectangle.height); - graphics.drawLine(worldMapRectangle.x, middle.getY(), worldMapRectangle.x + worldMapRectangle.width, middle.getY()); - - String output = "Center: " + mapCenterPoint.getX() + ", " + mapCenterPoint.getY(); - graphics.setColor(Color.white); - FontMetrics fm = graphics.getFontMetrics(); - int height = fm.getHeight(); - int width = fm.stringWidth(output); - graphics.fillRect((int)worldMapRectangle.getX(), (int)worldMapRectangle.getY() + worldMapRectangle.height - height, (int)worldMapRectangle.getX() + width, (int)worldMapRectangle.getY() + worldMapRectangle.height); - - graphics.setColor(Color.BLACK); - graphics.drawString(output, (int) worldMapRectangle.getX(), (int) worldMapRectangle.getY() + worldMapRectangle.height); - - return null; - } -} +/* + * Copyright (c) 2018, Morgan Lewis + * 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.devtools; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.RenderOverview; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay; + +public class WorldMapLocationOverlay extends Overlay +{ + private final Client client; + private final WorldMapOverlay worldMapOverlay; + private final DevToolsPlugin plugin; + + @Inject + private WorldMapLocationOverlay(Client client, WorldMapOverlay worldMapOverlay, DevToolsPlugin plugin) + { + this.client = client; + this.worldMapOverlay = worldMapOverlay; + this.plugin = plugin; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGH); + setLayer(OverlayLayer.ABOVE_MAP); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.getWorldMapLocation().isActive()) + { + return null; + } + + RenderOverview ro = client.getRenderOverview(); + Widget worldMapWidget = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); + + if (ro == null || worldMapWidget == null) + { + return null; + } + + Rectangle worldMapRectangle = worldMapWidget.getBounds(); + + graphics.setClip(worldMapRectangle); + graphics.setColor(Color.CYAN); + + WorldPoint mapCenterPoint = new WorldPoint(ro.getWorldMapPosition().getX(), ro.getWorldMapPosition().getY(), 0); + Point middle = worldMapOverlay.mapWorldPointToGraphicsPoint(mapCenterPoint); + + if (middle == null) + { + return null; + } + + graphics.drawLine(middle.getX(), worldMapRectangle.y, middle.getX(), worldMapRectangle.y + worldMapRectangle.height); + graphics.drawLine(worldMapRectangle.x, middle.getY(), worldMapRectangle.x + worldMapRectangle.width, middle.getY()); + + String output = "Center: " + mapCenterPoint.getX() + ", " + mapCenterPoint.getY(); + graphics.setColor(Color.white); + FontMetrics fm = graphics.getFontMetrics(); + int height = fm.getHeight(); + int width = fm.stringWidth(output); + graphics.fillRect((int) worldMapRectangle.getX(), (int) worldMapRectangle.getY() + worldMapRectangle.height - height, (int) worldMapRectangle.getX() + width, (int) worldMapRectangle.getY() + worldMapRectangle.height); + + graphics.setColor(Color.BLACK); + graphics.drawString(output, (int) worldMapRectangle.getX(), (int) worldMapRectangle.getY() + worldMapRectangle.height); + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java index cd05521228..6a6c621f78 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java @@ -86,68 +86,68 @@ enum DiscordGameEventType BOSS_ZULRAH("Zulrah", DiscordAreaType.BOSSES, 9007), // Cities - CITY_AL_KHARID("Al Kharid" , DiscordAreaType.CITIES, 13105, 13106), - CITY_APE_ATOLL("Ape Atoll" , DiscordAreaType.CITIES, 10795, 11051, 10974, 11050), - CITY_ARCEUUS_HOUSE("Arceuus" , DiscordAreaType.CITIES, 6459, 6715, 6458, 6714), - CITY_ARDOUGNE("Ardougne" , DiscordAreaType.CITIES, 10548, 10547, 10292, 10291, 10036, 10035, 9780, 9779), - CITY_BARBARIAN_VILLAGE("Barbarian Village" , DiscordAreaType.CITIES, 12341), - CITY_BANDIT_CAMP("Bandit Camp" , DiscordAreaType.CITIES, 12591), - CITY_BEDABIN_CAMP("Bedabin Camp" , DiscordAreaType.CITIES, 12590), - CITY_BRIMHAVEN("Brimhaven" , DiscordAreaType.CITIES, 11057, 11058), - CITY_BURGH_DE_ROTT("Burgh de Rott" , DiscordAreaType.CITIES, 13874, 13873, 14130, 14129), - CITY_BURTHORPE("Burthorpe" , DiscordAreaType.CITIES, 11319, 11575), - CITY_CANIFIS("Canifis" , DiscordAreaType.CITIES, 13878), - CITY_CATHERBY("Catherby" , DiscordAreaType.CITIES, 11317, 11318, 11061), - CITY_CORSAIR_CAVE("Corsair Cove" , DiscordAreaType.CITIES, 10028, 10284), - CITY_DORGESH_KAAN("Dorgesh-Kaan" , DiscordAreaType.CITIES, 10835, 10834), - CITY_DRAYNOR("Draynor" , DiscordAreaType.CITIES, 12338), - CITY_EDGEVILLE("Edgeville" , DiscordAreaType.CITIES, 12342), - CITY_ENTRANA("Entrana" , DiscordAreaType.CITIES, 11060, 11316), - CITY_FALADOR("Falador" , DiscordAreaType.CITIES, 11828, 11572, 11571, 11827, 12084), - CITY_GOBLIN_VILLAGE("Goblin Village" , DiscordAreaType.CITIES, 11830), - CITY_GUTANOTH("Gu'Tanoth" , DiscordAreaType.CITIES, 10031), - CITY_HOSIDIUS_HOUSE("Hosidius" , DiscordAreaType.CITIES, 6713, 6712, 6455, 6711, 6710, 6965, 6966, 7222, 7223, 6967), - CITY_JATISZO("Jatizso" , DiscordAreaType.CITIES, 9531), - CITY_JIGGIG("Jiggig" , DiscordAreaType.CITIES, 9775), - CITY_KARAMJA("Karamja" , DiscordAreaType.CITIES, 11569, 11568, 11567, 11566, 11313, 11312, 11311), - CITY_KELDAGRIM("Keldagrim" , DiscordAreaType.CITIES, 11423, 11422, 11679, 11678), - CITY_LLETYA("Lletya" , DiscordAreaType.CITIES, 9265), - CITY_LOVAKENGJ_HOUSE("Lovakengj" , DiscordAreaType.CITIES, 5692, 5948, 5691, 5947, 6203, 6202, 5690, 5946), - CITY_LUMBRIDGE("Lumbridge" , DiscordAreaType.CITIES, 12850), - CITY_LUNAR_ISLE("Lunar Isle" , DiscordAreaType.CITIES, 8253, 8252, 8509, 8508), - CITY_MEIYERDITCH("Meiyerditch" , DiscordAreaType.CITIES, 14132, 14388, 14387, 14386, 14385), - CITY_MISCELLANIA("Miscellania" , DiscordAreaType.CITIES, 10044, 10300), - CITY_MOS_LE_HARMLESS("Mos Le'Harmless" , DiscordAreaType.CITIES, 14638), - CITY_MORTTON("Mort'ton" , DiscordAreaType.CITIES, 13875), - CITY_MOR_UI_REK("Mor UI Rek" , DiscordAreaType.CITIES, 9808, 9807, 10064, 10063), + CITY_AL_KHARID("Al Kharid", DiscordAreaType.CITIES, 13105, 13106), + CITY_APE_ATOLL("Ape Atoll", DiscordAreaType.CITIES, 10795, 11051, 10974, 11050), + CITY_ARCEUUS_HOUSE("Arceuus", DiscordAreaType.CITIES, 6459, 6715, 6458, 6714), + CITY_ARDOUGNE("Ardougne", DiscordAreaType.CITIES, 10548, 10547, 10292, 10291, 10036, 10035, 9780, 9779), + CITY_BARBARIAN_VILLAGE("Barbarian Village", DiscordAreaType.CITIES, 12341), + CITY_BANDIT_CAMP("Bandit Camp", DiscordAreaType.CITIES, 12591), + CITY_BEDABIN_CAMP("Bedabin Camp", DiscordAreaType.CITIES, 12590), + CITY_BRIMHAVEN("Brimhaven", DiscordAreaType.CITIES, 11057, 11058), + CITY_BURGH_DE_ROTT("Burgh de Rott", DiscordAreaType.CITIES, 13874, 13873, 14130, 14129), + CITY_BURTHORPE("Burthorpe", DiscordAreaType.CITIES, 11319, 11575), + CITY_CANIFIS("Canifis", DiscordAreaType.CITIES, 13878), + CITY_CATHERBY("Catherby", DiscordAreaType.CITIES, 11317, 11318, 11061), + CITY_CORSAIR_CAVE("Corsair Cove", DiscordAreaType.CITIES, 10028, 10284), + CITY_DORGESH_KAAN("Dorgesh-Kaan", DiscordAreaType.CITIES, 10835, 10834), + CITY_DRAYNOR("Draynor", DiscordAreaType.CITIES, 12338), + CITY_EDGEVILLE("Edgeville", DiscordAreaType.CITIES, 12342), + CITY_ENTRANA("Entrana", DiscordAreaType.CITIES, 11060, 11316), + CITY_FALADOR("Falador", DiscordAreaType.CITIES, 11828, 11572, 11571, 11827, 12084), + CITY_GOBLIN_VILLAGE("Goblin Village", DiscordAreaType.CITIES, 11830), + CITY_GUTANOTH("Gu'Tanoth", DiscordAreaType.CITIES, 10031), + CITY_HOSIDIUS_HOUSE("Hosidius", DiscordAreaType.CITIES, 6713, 6712, 6455, 6711, 6710, 6965, 6966, 7222, 7223, 6967), + CITY_JATISZO("Jatizso", DiscordAreaType.CITIES, 9531), + CITY_JIGGIG("Jiggig", DiscordAreaType.CITIES, 9775), + CITY_KARAMJA("Karamja", DiscordAreaType.CITIES, 11569, 11568, 11567, 11566, 11313, 11312, 11311), + CITY_KELDAGRIM("Keldagrim", DiscordAreaType.CITIES, 11423, 11422, 11679, 11678), + CITY_LLETYA("Lletya", DiscordAreaType.CITIES, 9265), + CITY_LOVAKENGJ_HOUSE("Lovakengj", DiscordAreaType.CITIES, 5692, 5948, 5691, 5947, 6203, 6202, 5690, 5946), + CITY_LUMBRIDGE("Lumbridge", DiscordAreaType.CITIES, 12850), + CITY_LUNAR_ISLE("Lunar Isle", DiscordAreaType.CITIES, 8253, 8252, 8509, 8508), + CITY_MEIYERDITCH("Meiyerditch", DiscordAreaType.CITIES, 14132, 14388, 14387, 14386, 14385), + CITY_MISCELLANIA("Miscellania", DiscordAreaType.CITIES, 10044, 10300), + CITY_MOS_LE_HARMLESS("Mos Le'Harmless", DiscordAreaType.CITIES, 14638), + CITY_MORTTON("Mort'ton", DiscordAreaType.CITIES, 13875), + CITY_MOR_UI_REK("Mor UI Rek", DiscordAreaType.CITIES, 9808, 9807, 10064, 10063), CITY_MOUNT_KARUULM("Mount Karuulm", DiscordAreaType.CITIES, 5179, 4923, 5180), - CITY_NARDAH("Nardah" , DiscordAreaType.CITIES, 13613), - CITY_NEITIZNOT("Neitiznot" , DiscordAreaType.CITIES, 9275), - CITY_PISCATORIS("Piscatoris" , DiscordAreaType.CITIES, 9273), - CITY_POLLNIVNEACH("Pollnivneach" , DiscordAreaType.CITIES, 13358), - CITY_PORT_KHAZARD("Port Khazard" , DiscordAreaType.CITIES, 10545), - CITY_PORT_PHASMATYS("Port Phasmatys" , DiscordAreaType.CITIES, 14646), - CITY_PORT_SARIM("Port Sarim" , DiscordAreaType.CITIES, 12082), - CITY_PISCARILIUS_HOUSE("Port Piscarilius" , DiscordAreaType.CITIES, 6971, 7227, 6970, 7226), - CITY_RELLEKKA("Rellekka" , DiscordAreaType.CITIES, 10553), - CITY_RIMMINGTON("Rimmington" , DiscordAreaType.CITIES, 11826, 11570), - CITY_SEERS_VILLAGE("Seers' Village" , DiscordAreaType.CITIES, 10806), - CITY_SHAYZIEN_HOUSE("Shayzien" , DiscordAreaType.CITIES, 5944, 5943, 6200, 6199, 5688), - CITY_SHILO_VILLAGE("Shilo Village" , DiscordAreaType.CITIES, 11310), - CITY_SOPHANEM("Sophanem" , DiscordAreaType.CITIES, 13099), - CITY_TAI_BWO_WANNAI("Tai Bwo Wannai" , DiscordAreaType.CITIES, 11056, 11055), - CITY_TAVERLEY("Taverley" , DiscordAreaType.CITIES, 11574, 11573), - CITY_TREE_GNOME_STRONGHOLD("Tree Gnome Stronghold" , DiscordAreaType.CITIES, 9782, 9781), - CITY_TREE_GNOME_VILLAGE("Tree Gnome Village" , DiscordAreaType.CITIES, 10033), - CITY_TROLL_STRONGHOLD("Troll Stronghold" , DiscordAreaType.CITIES, 11321), - CITY_TYRAS_CAMP("Tyras Camp" , DiscordAreaType.CITIES, 8753, 8752), - CITY_UZER("Uzer" , DiscordAreaType.CITIES, 13872), - CITY_VARROCK("Varrock" , DiscordAreaType.CITIES, 12596, 12597, 12598, 12852, 12853, 12854, 13108, 13109, 13110), - CITY_WITCHHAVEN("Witchaven" , DiscordAreaType.CITIES, 10803), + CITY_NARDAH("Nardah", DiscordAreaType.CITIES, 13613), + CITY_NEITIZNOT("Neitiznot", DiscordAreaType.CITIES, 9275), + CITY_PISCATORIS("Piscatoris", DiscordAreaType.CITIES, 9273), + CITY_POLLNIVNEACH("Pollnivneach", DiscordAreaType.CITIES, 13358), + CITY_PORT_KHAZARD("Port Khazard", DiscordAreaType.CITIES, 10545), + CITY_PORT_PHASMATYS("Port Phasmatys", DiscordAreaType.CITIES, 14646), + CITY_PORT_SARIM("Port Sarim", DiscordAreaType.CITIES, 12082), + CITY_PISCARILIUS_HOUSE("Port Piscarilius", DiscordAreaType.CITIES, 6971, 7227, 6970, 7226), + CITY_RELLEKKA("Rellekka", DiscordAreaType.CITIES, 10553), + CITY_RIMMINGTON("Rimmington", DiscordAreaType.CITIES, 11826, 11570), + CITY_SEERS_VILLAGE("Seers' Village", DiscordAreaType.CITIES, 10806), + CITY_SHAYZIEN_HOUSE("Shayzien", DiscordAreaType.CITIES, 5944, 5943, 6200, 6199, 5688), + CITY_SHILO_VILLAGE("Shilo Village", DiscordAreaType.CITIES, 11310), + CITY_SOPHANEM("Sophanem", DiscordAreaType.CITIES, 13099), + CITY_TAI_BWO_WANNAI("Tai Bwo Wannai", DiscordAreaType.CITIES, 11056, 11055), + CITY_TAVERLEY("Taverley", DiscordAreaType.CITIES, 11574, 11573), + CITY_TREE_GNOME_STRONGHOLD("Tree Gnome Stronghold", DiscordAreaType.CITIES, 9782, 9781), + CITY_TREE_GNOME_VILLAGE("Tree Gnome Village", DiscordAreaType.CITIES, 10033), + CITY_TROLL_STRONGHOLD("Troll Stronghold", DiscordAreaType.CITIES, 11321), + CITY_TYRAS_CAMP("Tyras Camp", DiscordAreaType.CITIES, 8753, 8752), + CITY_UZER("Uzer", DiscordAreaType.CITIES, 13872), + CITY_VARROCK("Varrock", DiscordAreaType.CITIES, 12596, 12597, 12598, 12852, 12853, 12854, 13108, 13109, 13110), + CITY_WITCHHAVEN("Witchaven", DiscordAreaType.CITIES, 10803), CITY_WOODCUTTING_GUILD("Woodcutting Guild", DiscordAreaType.CITIES, 6454, 6198, 6298), - CITY_YANILLE("Yanille" , DiscordAreaType.CITIES, 10288, 10032), - CITY_ZANARIS("Zanaris" , DiscordAreaType.CITIES, 9285, 9541, 9540, 9797), - CITY_ZULANDRA("Zul-Andra" , DiscordAreaType.CITIES, 8751), + CITY_YANILLE("Yanille", DiscordAreaType.CITIES, 10288, 10032), + CITY_ZANARIS("Zanaris", DiscordAreaType.CITIES, 9285, 9541, 9540, 9797), + CITY_ZULANDRA("Zul-Andra", DiscordAreaType.CITIES, 8751), // Dungeons DUNGEON_ABANDONED_MINE("Abandoned Mine", DiscordAreaType.DUNGEONS, 13718, 11079, 11078, 11077, 10823, 10822, 10821), @@ -358,29 +358,52 @@ enum DiscordGameEventType { switch (skill) { - case ATTACK: return TRAINING_ATTACK; - case DEFENCE: return TRAINING_DEFENCE; - case STRENGTH: return TRAINING_STRENGTH; - case RANGED: return TRAINING_RANGED; - case PRAYER: return TRAINING_PRAYER; - case MAGIC: return TRAINING_MAGIC; - case COOKING: return TRAINING_COOKING; - case WOODCUTTING: return TRAINING_WOODCUTTING; - case FLETCHING: return TRAINING_FLETCHING; - case FISHING: return TRAINING_FISHING; - case FIREMAKING: return TRAINING_FIREMAKING; - case CRAFTING: return TRAINING_CRAFTING; - case SMITHING: return TRAINING_SMITHING; - case MINING: return TRAINING_MINING; - case HERBLORE: return TRAINING_HERBLORE; - case AGILITY: return TRAINING_AGILITY; - case THIEVING: return TRAINING_THIEVING; - case SLAYER: return TRAINING_SLAYER; - case FARMING: return TRAINING_FARMING; - case RUNECRAFT: return TRAINING_RUNECRAFT; - case HUNTER: return TRAINING_HUNTER; - case CONSTRUCTION: return TRAINING_CONSTRUCTION; - default: return null; + case ATTACK: + return TRAINING_ATTACK; + case DEFENCE: + return TRAINING_DEFENCE; + case STRENGTH: + return TRAINING_STRENGTH; + case RANGED: + return TRAINING_RANGED; + case PRAYER: + return TRAINING_PRAYER; + case MAGIC: + return TRAINING_MAGIC; + case COOKING: + return TRAINING_COOKING; + case WOODCUTTING: + return TRAINING_WOODCUTTING; + case FLETCHING: + return TRAINING_FLETCHING; + case FISHING: + return TRAINING_FISHING; + case FIREMAKING: + return TRAINING_FIREMAKING; + case CRAFTING: + return TRAINING_CRAFTING; + case SMITHING: + return TRAINING_SMITHING; + case MINING: + return TRAINING_MINING; + case HERBLORE: + return TRAINING_HERBLORE; + case AGILITY: + return TRAINING_AGILITY; + case THIEVING: + return TRAINING_THIEVING; + case SLAYER: + return TRAINING_SLAYER; + case FARMING: + return TRAINING_FARMING; + case RUNECRAFT: + return TRAINING_RUNECRAFT; + case HUNTER: + return TRAINING_HUNTER; + case CONSTRUCTION: + return TRAINING_CONSTRUCTION; + default: + return null; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java index b14bd00dce..6ad277721e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java @@ -417,10 +417,14 @@ public class DiscordPlugin extends Plugin switch (event.getDiscordAreaType()) { - case BOSSES: return config.showBossActivity(); - case CITIES: return config.showCityActivity(); - case DUNGEONS: return config.showDungeonActivity(); - case MINIGAMES: return config.showMinigameActivity(); + case BOSSES: + return config.showBossActivity(); + case CITIES: + return config.showCityActivity(); + case DUNGEONS: + return config.showDungeonActivity(); + case MINIGAMES: + return config.showMinigameActivity(); } return false; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/DuelingRingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/DuelingRingMode.java index 56b18591d9..1cb3651b5b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/DuelingRingMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/DuelingRingMode.java @@ -1,42 +1,45 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum DuelingRingMode { - DUEL_ARENA("Duel Arena"), - CASTLE_WARS("Castle Wars"), - CLAN_WARS("Clan Wars"); - - private final String name; - - DuelingRingMode(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.easyscape; + +public enum DuelingRingMode +{ + DUEL_ARENA("Duel Arena"), + CASTLE_WARS("Castle Wars"), + CLAN_WARS("Clan Wars"); + + private final String name; + + DuelingRingMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index ef4741434f..6ad12ca97a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -25,10 +25,13 @@ package net.runelite.client.plugins.easyscape; import com.google.inject.Provides; +import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.MenuAction; +import static net.runelite.api.MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET; +import static net.runelite.api.MenuAction.WALK; import net.runelite.api.MenuEntry; import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; @@ -43,322 +46,390 @@ import net.runelite.client.plugins.PluginType; import static net.runelite.client.util.MenuUtil.swap; import net.runelite.client.util.Text; import org.apache.commons.lang3.ArrayUtils; -import javax.inject.Inject; -import static net.runelite.api.MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET; -import static net.runelite.api.MenuAction.WALK; @PluginDescriptor( - name = "Easyscape", - description = "Easyscape.", - tags = {"Easyscape"}, - enabledByDefault = false, - type = PluginType.UTILITY + name = "Easyscape", + description = "Easyscape.", + tags = {"Easyscape"}, + enabledByDefault = false, + type = PluginType.UTILITY ) @Slf4j -public class EasyscapePlugin extends Plugin { +public class EasyscapePlugin extends Plugin +{ - private static final int PURO_PURO_REGION_ID = 10307; - private static final int HOUSE_REGION_ID = 7513; + private static final int PURO_PURO_REGION_ID = 10307; + private static final int HOUSE_REGION_ID = 7513; - private MenuEntry[] entries; + private MenuEntry[] entries; - @Inject - private Client client; + @Inject + private Client client; - @Inject - private EasyscapePluginConfig config; + @Inject + private EasyscapePluginConfig config; - @Provides - EasyscapePluginConfig provideConfig(ConfigManager configManager) { - return configManager.getConfig(EasyscapePluginConfig.class); - } + @Provides + EasyscapePluginConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(EasyscapePluginConfig.class); + } - @Override - public void startUp() { - log.debug("Easyscape Started."); - } + @Override + public void startUp() + { + log.debug("Easyscape Started."); + } - @Override - public void shutDown() { - log.debug("Easyscape Stopped."); - } + @Override + public void shutDown() + { + log.debug("Easyscape Stopped."); + } - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) { + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { - if (client.getGameState() != GameState.LOGGED_IN) { - return; - } + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } - Widget loginScreenOne = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN); - Widget loginScreenTwo = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY); + Widget loginScreenOne = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN); + Widget loginScreenTwo = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY); - if (loginScreenOne != null || loginScreenTwo != null) { - return; - } + if (loginScreenOne != null || loginScreenTwo != null) + { + return; + } - final String option = Text.removeTags(event.getOption()).toLowerCase(); - final String target = Text.removeTags(event.getTarget()).toLowerCase(); + final String option = Text.removeTags(event.getOption()).toLowerCase(); + final String target = Text.removeTags(event.getTarget()).toLowerCase(); - entries = client.getMenuEntries(); + entries = client.getMenuEntries(); - if (config.getRemoveExamine()) { - for (int i = entries.length - 1; i >= 0; i--) { - if (entries[i].getOption().equals("Examine")) { - entries = ArrayUtils.remove(entries, i); - i--; - } - } - client.setMenuEntries(entries); - } + if (config.getRemoveExamine()) + { + for (int i = entries.length - 1; i >= 0; i--) + { + if (entries[i].getOption().equals("Examine")) + { + entries = ArrayUtils.remove(entries, i); + i--; + } + } + client.setMenuEntries(entries); + } - if (config.getRemoveObjects() && !config.getRemovedObjects().equals("")) { - for (String removed : config.getRemovedObjects().split(",")) { - removed = removed.trim(); - if (target.contains("->")) { - String trimmed = target.split("->")[1].trim(); - if (trimmed.length() >= removed.length() && trimmed.substring(0, removed.length()).equalsIgnoreCase(removed)) { - delete(event.getIdentifier()); - break; - } - } - if (target.length() >= removed.length() && target.substring(0, removed.length()).equalsIgnoreCase(removed)) { - delete(event.getIdentifier()); - break; - } - } - } + if (config.getRemoveObjects() && !config.getRemovedObjects().equals("")) + { + for (String removed : config.getRemovedObjects().split(",")) + { + removed = removed.trim(); + if (target.contains("->")) + { + String trimmed = target.split("->")[1].trim(); + if (trimmed.length() >= removed.length() && trimmed.substring(0, removed.length()).equalsIgnoreCase(removed)) + { + delete(event.getIdentifier()); + break; + } + } + if (target.length() >= removed.length() && target.substring(0, removed.length()).equalsIgnoreCase(removed)) + { + delete(event.getIdentifier()); + break; + } + } + } - if (config.getSwapPuro() && isPuroPuro()) { - if (event.getType() == WALK.getId()) { - MenuEntry menuEntry = entries[entries.length - 1]; - menuEntry.setType(MenuAction.WALK.getId() + MENU_ACTION_DEPRIORITIZE_OFFSET); - client.setMenuEntries(entries); - } - else if (option.equalsIgnoreCase("examine")) { - swap(client, "push-through", option, target); - } - else if (option.equalsIgnoreCase("use")) { - swap(client, "escape", option, target); - } - } + if (config.getSwapPuro() && isPuroPuro()) + { + if (event.getType() == WALK.getId()) + { + MenuEntry menuEntry = entries[entries.length - 1]; + menuEntry.setType(MenuAction.WALK.getId() + MENU_ACTION_DEPRIORITIZE_OFFSET); + client.setMenuEntries(entries); + } + else if (option.equalsIgnoreCase("examine")) + { + swap(client, "push-through", option, target); + } + else if (option.equalsIgnoreCase("use")) + { + swap(client, "escape", option, target); + } + } - if (config.getEasyConstruction() && !config.getConstructionItems().equals("")) { - if (event.getType() == WALK.getId()) { - MenuEntry menuEntry = entries[entries.length - 1]; - menuEntry.setType(MenuAction.WALK.getId() + MENU_ACTION_DEPRIORITIZE_OFFSET); - client.setMenuEntries(entries); - } + if (config.getEasyConstruction() && !config.getConstructionItems().equals("")) + { + if (event.getType() == WALK.getId()) + { + MenuEntry menuEntry = entries[entries.length - 1]; + menuEntry.setType(MenuAction.WALK.getId() + MENU_ACTION_DEPRIORITIZE_OFFSET); + client.setMenuEntries(entries); + } - swap(client, "Build", option, target); + swap(client, "Build", option, target); - for (int i = entries.length - 1; i >= 0; i--) { - for (String item : config.getConstructionItems().split(",")) { - if (item.trim().equalsIgnoreCase(Text.removeTags(entries[i].getTarget()))) { - if (!entries[i].getOption().equalsIgnoreCase("remove")) { - entries = ArrayUtils.remove(entries, i); - i--; - } - } - } - } + for (int i = entries.length - 1; i >= 0; i--) + { + for (String item : config.getConstructionItems().split(",")) + { + if (item.trim().equalsIgnoreCase(Text.removeTags(entries[i].getTarget()))) + { + if (!entries[i].getOption().equalsIgnoreCase("remove")) + { + entries = ArrayUtils.remove(entries, i); + i--; + } + } + } + } - client.setMenuEntries(entries); - } + client.setMenuEntries(entries); + } - if (config.getSwapShop() && !config.getSwappedItems().equals("")) { - for (String item : config.getSwappedItems().split(",")) { - if (target.equalsIgnoreCase(item.trim())) { - swap(client, "Buy 50", option, target); - } - } - } + if (config.getSwapShop() && !config.getSwappedItems().equals("")) + { + for (String item : config.getSwappedItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Buy 50", option, target); + } + } + } - if (config.getSwapSmithing()) { - if (option.equalsIgnoreCase("Smith 1")) { - swap(client, "Smith All", option, target); - } else if (option.equalsIgnoreCase("Smith 1 Set")) { - swap(client, "Smith All Sets", option, target); - } - } + if (config.getSwapSmithing()) + { + if (option.equalsIgnoreCase("Smith 1")) + { + swap(client, "Smith All", option, target); + } + else if (option.equalsIgnoreCase("Smith 1 Set")) + { + swap(client, "Smith All Sets", option, target); + } + } - if (config.getSwapTanning() && option.equalsIgnoreCase("Tan 1")) { - swap(client, "Tan All", option, target); - } + if (config.getSwapTanning() && option.equalsIgnoreCase("Tan 1")) + { + swap(client, "Tan All", option, target); + } - if (config.getSwapCrafting() && option.equalsIgnoreCase("Make-1")) { - swap(client, "Make-All", option, target); - } + if (config.getSwapCrafting() && option.equalsIgnoreCase("Make-1")) + { + swap(client, "Make-All", option, target); + } - if (config.getSwapSawmill() && target.equalsIgnoreCase("Sawmill operator")) { - swap(client, "Buy-plank", option, target); - } + if (config.getSwapSawmill() && target.equalsIgnoreCase("Sawmill operator")) + { + swap(client, "Buy-plank", option, target); + } - if (config.getSwapSawmillPlanks() && option.equalsIgnoreCase("Buy 1")) { - swap(client, "Buy All", option, target); - } + if (config.getSwapSawmillPlanks() && option.equalsIgnoreCase("Buy 1")) + { + swap(client, "Buy All", option, target); + } - if (config.getSwapStairs() && option.equalsIgnoreCase("Climb Stairs")) { - swap(client, "Climb Up Stairs", option, target); - } + if (config.getSwapStairs() && option.equalsIgnoreCase("Climb Stairs")) + { + swap(client, "Climb Up Stairs", option, target); + } - if (option.equalsIgnoreCase("Clear-All") && target.equalsIgnoreCase("Bank Filler")) { - swap(client, "Clear", option, target); - } + if (option.equalsIgnoreCase("Clear-All") && target.equalsIgnoreCase("Bank Filler")) + { + swap(client, "Clear", option, target); + } - if (target.toLowerCase().contains("ardougne cloak") && config.getSwapArdougneCape()) { - swap(client, "Kandarin Monastery", option, target); - swap(client, "Monastery Teleport", option, target); - } + if (target.toLowerCase().contains("ardougne cloak") && config.getSwapArdougneCape()) + { + swap(client, "Kandarin Monastery", option, target); + swap(client, "Monastery Teleport", option, target); + } - if (config.getSwapEssencePouch()) { - if (isEssencePouch(target)) { - Widget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR); - switch (config.getEssenceMode()) { - case RUNECRAFTING: - if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) { - swap(client, "Empty", option, target); - } else { - swap(client, "Fill", option, target); - } - break; - case ESSENCE_MINING: - if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) { - swap(client, "Fill", option, target); - } else { - swap(client, "Empty", option, target); - } - break; - default: - break; - } - } - } + if (config.getSwapEssencePouch()) + { + if (isEssencePouch(target)) + { + Widget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR); + switch (config.getEssenceMode()) + { + case RUNECRAFTING: + if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) + { + swap(client, "Empty", option, target); + } + else + { + swap(client, "Fill", option, target); + } + break; + case ESSENCE_MINING: + if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) + { + swap(client, "Fill", option, target); + } + else + { + swap(client, "Empty", option, target); + } + break; + default: + break; + } + } + } - if (config.getGamesNecklace()) { - if (target.toLowerCase().contains("games necklace")) { - switch (config.getGamesNecklaceMode()) { - case BURTHORPE: - swap(client, GamesNecklaceMode.BURTHORPE.toString(), option, target); - break; - case BARBARIAN_OUTPOST: - swap(client, GamesNecklaceMode.BARBARIAN_OUTPOST.toString(), option, target); - break; - case CORPOREAL_BEAST: - swap(client, GamesNecklaceMode.CORPOREAL_BEAST.toString(), option, target); - break; - case TEARS_OF_GUTHIX: - swap(client, GamesNecklaceMode.TEARS_OF_GUTHIX.toString(), option, target); - break; - case WINTERTODT: - swap(client, GamesNecklaceMode.WINTERTODT.toString(), option, target); - break; - default: - break; - } - } - } + if (config.getGamesNecklace()) + { + if (target.toLowerCase().contains("games necklace")) + { + switch (config.getGamesNecklaceMode()) + { + case BURTHORPE: + swap(client, GamesNecklaceMode.BURTHORPE.toString(), option, target); + break; + case BARBARIAN_OUTPOST: + swap(client, GamesNecklaceMode.BARBARIAN_OUTPOST.toString(), option, target); + break; + case CORPOREAL_BEAST: + swap(client, GamesNecklaceMode.CORPOREAL_BEAST.toString(), option, target); + break; + case TEARS_OF_GUTHIX: + swap(client, GamesNecklaceMode.TEARS_OF_GUTHIX.toString(), option, target); + break; + case WINTERTODT: + swap(client, GamesNecklaceMode.WINTERTODT.toString(), option, target); + break; + default: + break; + } + } + } - if (config.getDuelingRing()) { - if (target.toLowerCase().contains("ring of dueling")) { - switch (config.getDuelingRingMode()) { - case DUEL_ARENA: - swap(client, DuelingRingMode.DUEL_ARENA.toString(), option, target); - break; - case CASTLE_WARS: - swap(client, DuelingRingMode.CASTLE_WARS.toString(), option, target); - break; - case CLAN_WARS: - swap(client, DuelingRingMode.CLAN_WARS.toString(), option, target); - break; - default: - break; - } - } - } + if (config.getDuelingRing()) + { + if (target.toLowerCase().contains("ring of dueling")) + { + switch (config.getDuelingRingMode()) + { + case DUEL_ARENA: + swap(client, DuelingRingMode.DUEL_ARENA.toString(), option, target); + break; + case CASTLE_WARS: + swap(client, DuelingRingMode.CASTLE_WARS.toString(), option, target); + break; + case CLAN_WARS: + swap(client, DuelingRingMode.CLAN_WARS.toString(), option, target); + break; + default: + break; + } + } + } - if (config.getWealthRing()) { - if (target.toLowerCase().contains("ring of wealth")) { - switch (config.getWealthRingMode()) { - case MISCELLANIA: - swap(client, WealthRingMode.MISCELLANIA.toString(), option, target); - break; - case GRAND_EXCHANGE: - swap(client, WealthRingMode.GRAND_EXCHANGE.toString(), option, target); - break; - case FALADOR: - swap(client, WealthRingMode.FALADOR.toString(), option, target); - break; + if (config.getWealthRing()) + { + if (target.toLowerCase().contains("ring of wealth")) + { + switch (config.getWealthRingMode()) + { + case MISCELLANIA: + swap(client, WealthRingMode.MISCELLANIA.toString(), option, target); + break; + case GRAND_EXCHANGE: + swap(client, WealthRingMode.GRAND_EXCHANGE.toString(), option, target); + break; + case FALADOR: + swap(client, WealthRingMode.FALADOR.toString(), option, target); + break; case DONDAKAN: - swap(client, WealthRingMode.DONDAKAN.toString(), option, target); - break; - default: - break; - } - } - } + swap(client, WealthRingMode.DONDAKAN.toString(), option, target); + break; + default: + break; + } + } + } - if (config.getGlory()) { - if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) { - switch (config.getGloryMode()) { - case EDGEVILLE: - swap(client, GloryMode.EDGEVILLE.toString(), option, target); - break; - case KARAMJA: - swap(client, GloryMode.KARAMJA.toString(), option, target); - break; - case DRAYNOR_VILLAGE: - swap(client, GloryMode.DRAYNOR_VILLAGE.toString(), option, target); - break; - case AL_KHARID: - swap(client, GloryMode.AL_KHARID.toString(), option, target); - break; - default: - break; - } - } - } + if (config.getGlory()) + { + if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) + { + switch (config.getGloryMode()) + { + case EDGEVILLE: + swap(client, GloryMode.EDGEVILLE.toString(), option, target); + break; + case KARAMJA: + swap(client, GloryMode.KARAMJA.toString(), option, target); + break; + case DRAYNOR_VILLAGE: + swap(client, GloryMode.DRAYNOR_VILLAGE.toString(), option, target); + break; + case AL_KHARID: + swap(client, GloryMode.AL_KHARID.toString(), option, target); + break; + default: + break; + } + } + } - if (target.toLowerCase().contains("crafting cape") && config.getSwapCraftingCape()) { - swap(client, "Teleport", option, target); + if (target.toLowerCase().contains("crafting cape") && config.getSwapCraftingCape()) + { + swap(client, "Teleport", option, target); - } + } - if (target.toLowerCase().contains("construct. cape") && config.getSwapConstructionCape()) { - swap(client, "Tele to poh", option, target); + if (target.toLowerCase().contains("construct. cape") && config.getSwapConstructionCape()) + { + swap(client, "Tele to poh", option, target); - } - } + } + } - private void delete(int target) { - for (int i = entries.length - 1; i >= 0; i--) { - if (entries[i].getIdentifier() == target) { - entries = ArrayUtils.remove(entries, i); - i--; - } - } - client.setMenuEntries(entries); - } + private void delete(int target) + { + for (int i = entries.length - 1; i >= 0; i--) + { + if (entries[i].getIdentifier() == target) + { + entries = ArrayUtils.remove(entries, i); + i--; + } + } + client.setMenuEntries(entries); + } - private boolean isEssencePouch(String target) { - return (target.equalsIgnoreCase("Small Pouch") || target.equalsIgnoreCase("Medium Pouch") || target.equalsIgnoreCase("Large Pouch") || target.equalsIgnoreCase("Giant Pouch")); - } + private boolean isEssencePouch(String target) + { + return (target.equalsIgnoreCase("Small Pouch") || target.equalsIgnoreCase("Medium Pouch") || target.equalsIgnoreCase("Large Pouch") || target.equalsIgnoreCase("Giant Pouch")); + } - private boolean isHouse() { - return client.getMapRegions()[0] == HOUSE_REGION_ID; - } + private boolean isHouse() + { + return client.getMapRegions()[0] == HOUSE_REGION_ID; + } - private boolean isPuroPuro() { - Player player = client.getLocalPlayer(); + private boolean isPuroPuro() + { + Player player = client.getLocalPlayer(); - if (player == null) { - return false; - } else { - WorldPoint location = player.getWorldLocation(); - return location.getRegionID() == PURO_PURO_REGION_ID; - } - } + if (player == null) + { + return false; + } + else + { + WorldPoint location = player.getWorldLocation(); + return location.getRegionID() == PURO_PURO_REGION_ID; + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java index 60e73281fd..ac0f61b361 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java @@ -29,285 +29,313 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; @ConfigGroup("easyscape") -public interface EasyscapePluginConfig extends Config { +public interface EasyscapePluginConfig extends Config +{ - @ConfigItem( - keyName = "removeExamine", - name = "Remove Examine", - description = "", - position = 0 - ) - default boolean getRemoveExamine() { - return true; - } + @ConfigItem( + keyName = "removeExamine", + name = "Remove Examine", + description = "", + position = 0 + ) + default boolean getRemoveExamine() + { + return true; + } - @ConfigItem( - keyName = "swapShop", - name = "Easy Shop", - description = "Enables swapping of items in the shop with their buy-50 option.", - position = 1 - ) - default boolean getSwapShop() { - return true; - } + @ConfigItem( + keyName = "swapShop", + name = "Easy Shop", + description = "Enables swapping of items in the shop with their buy-50 option.", + position = 1 + ) + default boolean getSwapShop() + { + return true; + } - @ConfigItem( - keyName = "swappedItems", - name = "Shop Items", - description = "Items listed here will have their value and buy-50 options swapped.", - position = 2 - ) - default String getSwappedItems() { - return ""; - } + @ConfigItem( + keyName = "swappedItems", + name = "Shop Items", + description = "Items listed here will have their value and buy-50 options swapped.", + position = 2 + ) + default String getSwappedItems() + { + return ""; + } - @ConfigItem( - keyName = "easyConstruction", - name = "Easy Construction", - description = "", - position = 3 - ) + @ConfigItem( + keyName = "easyConstruction", + name = "Easy Construction", + description = "", + position = 3 + ) - default boolean getEasyConstruction() { - return true; - } + default boolean getEasyConstruction() + { + return true; + } - @ConfigItem( - keyName = "constructionItems", - name = "Construction Items", - description = "", - position = 4 - ) + @ConfigItem( + keyName = "constructionItems", + name = "Construction Items", + description = "", + position = 4 + ) - default String getConstructionItems() { - return ""; - } + default String getConstructionItems() + { + return ""; + } - @ConfigItem( - keyName = "removeObjects", - name = "Remove Objects", - description = "", - position = 5 - ) - default boolean getRemoveObjects() { - return true; - } + @ConfigItem( + keyName = "removeObjects", + name = "Remove Objects", + description = "", + position = 5 + ) + default boolean getRemoveObjects() + { + return true; + } - @ConfigItem( - keyName = "removedObjects", - name = "Removed Objects", - description = "", - position = 6 - ) - default String getRemovedObjects() { - return ""; - } + @ConfigItem( + keyName = "removedObjects", + name = "Removed Objects", + description = "", + position = 6 + ) + default String getRemovedObjects() + { + return ""; + } - @ConfigItem( - keyName = "swapSmithing", - name = "Swap Smithing", - description = "Enables swapping of smith-1 and smith-all options.", - position = 7 - ) - default boolean getSwapSmithing() { - return true; - } + @ConfigItem( + keyName = "swapSmithing", + name = "Swap Smithing", + description = "Enables swapping of smith-1 and smith-all options.", + position = 7 + ) + default boolean getSwapSmithing() + { + return true; + } - @ConfigItem( - keyName = "swapTanning", - name = "Swap Tanning", - description = "Enables swapping of tan-1 and tan-all options.", - position = 8 - ) - default boolean getSwapTanning() { - return true; - } + @ConfigItem( + keyName = "swapTanning", + name = "Swap Tanning", + description = "Enables swapping of tan-1 and tan-all options.", + position = 8 + ) + default boolean getSwapTanning() + { + return true; + } - @ConfigItem( - keyName = "swapCrafting", - name = "Swap Crafting", - description = "", - position = 9 - ) - default boolean getSwapCrafting() { - return true; - } + @ConfigItem( + keyName = "swapCrafting", + name = "Swap Crafting", + description = "", + position = 9 + ) + default boolean getSwapCrafting() + { + return true; + } - @ConfigItem( - keyName = "swapArdougneCape", - name = "Swap Ardougne Cape", - description = "Enables swapping of teleport and wear.", - position = 10 - ) - default boolean getSwapArdougneCape() { - return true; - } + @ConfigItem( + keyName = "swapArdougneCape", + name = "Swap Ardougne Cape", + description = "Enables swapping of teleport and wear.", + position = 10 + ) + default boolean getSwapArdougneCape() + { + return true; + } - @ConfigItem( - keyName = "swapStairs", - name = "Swap Stairs", - description = "", - position = 11 - ) + @ConfigItem( + keyName = "swapStairs", + name = "Swap Stairs", + description = "", + position = 11 + ) - default boolean getSwapStairs() { - return true; - } + default boolean getSwapStairs() + { + return true; + } - @ConfigItem( - keyName = "swapSawmill", - name = "Swap Sawmill Operator", - description = "", - position = 12 - ) - default boolean getSwapSawmill() { - return true; - } + @ConfigItem( + keyName = "swapSawmill", + name = "Swap Sawmill Operator", + description = "", + position = 12 + ) + default boolean getSwapSawmill() + { + return true; + } - @ConfigItem( - keyName = "swapSawmillPlanks", - name = "Swap Buy Planks", - description = "", - position = 13 - ) + @ConfigItem( + keyName = "swapSawmillPlanks", + name = "Swap Buy Planks", + description = "", + position = 13 + ) - default boolean getSwapSawmillPlanks() { - return true; - } + default boolean getSwapSawmillPlanks() + { + return true; + } - @ConfigItem( - keyName = "swapPuroPuro", - name = "Swap Puro Puro Wheat", - description = "", - position = 14 - ) - default boolean getSwapPuro() { - return true; - } + @ConfigItem( + keyName = "swapPuroPuro", + name = "Swap Puro Puro Wheat", + description = "", + position = 14 + ) + default boolean getSwapPuro() + { + return true; + } - @ConfigItem( - keyName = "swapEssencePounch", - name = "Swap Essence Pouch", - description = "Enables swapping of fill and empty for essence pounch.", - position = 15 - ) - default boolean getSwapEssencePouch() { - return true; - } + @ConfigItem( + keyName = "swapEssencePounch", + name = "Swap Essence Pouch", + description = "Enables swapping of fill and empty for essence pounch.", + position = 15 + ) + default boolean getSwapEssencePouch() + { + return true; + } - @ConfigItem( - keyName = "essenceMode", - name = "Essence Pouch Mode", - description = "Runecrafting or essence mining mode.", - position = 16 - ) + @ConfigItem( + keyName = "essenceMode", + name = "Essence Pouch Mode", + description = "Runecrafting or essence mining mode.", + position = 16 + ) - default EssenceMode getEssenceMode() { - return EssenceMode.RUNECRAFTING; - } + default EssenceMode getEssenceMode() + { + return EssenceMode.RUNECRAFTING; + } - @ConfigItem( - keyName = "swapGamesNecklace", - name = "Swap Games Necklace", - description = "Enables swapping of games necklace.", - position = 17 - ) - default boolean getGamesNecklace() { - return true; - } + @ConfigItem( + keyName = "swapGamesNecklace", + name = "Swap Games Necklace", + description = "Enables swapping of games necklace.", + position = 17 + ) + default boolean getGamesNecklace() + { + return true; + } - @ConfigItem( - keyName = "gamesNecklaceMode", - name = "Games Necklace Mode", - description = "Teleport location mode.", - position = 18 - ) + @ConfigItem( + keyName = "gamesNecklaceMode", + name = "Games Necklace Mode", + description = "Teleport location mode.", + position = 18 + ) - default GamesNecklaceMode getGamesNecklaceMode() { - return GamesNecklaceMode.BURTHORPE; - } + default GamesNecklaceMode getGamesNecklaceMode() + { + return GamesNecklaceMode.BURTHORPE; + } - @ConfigItem( - keyName = "swapDuelingRing", - name = "Swap Dueling Ring", - description = "Enables swapping of dueling ring.", - position = 19 - ) - default boolean getDuelingRing() { - return true; - } + @ConfigItem( + keyName = "swapDuelingRing", + name = "Swap Dueling Ring", + description = "Enables swapping of dueling ring.", + position = 19 + ) + default boolean getDuelingRing() + { + return true; + } - @ConfigItem( - keyName = "duelingRingMode", - name = "Dueling Ring Mode", - description = "Teleport location mode.", - position = 20 - ) + @ConfigItem( + keyName = "duelingRingMode", + name = "Dueling Ring Mode", + description = "Teleport location mode.", + position = 20 + ) - default DuelingRingMode getDuelingRingMode() { - return DuelingRingMode.DUEL_ARENA; - } + default DuelingRingMode getDuelingRingMode() + { + return DuelingRingMode.DUEL_ARENA; + } - @ConfigItem( - keyName = "swapGlory", - name = "Swap Glory", - description = "Enables swapping of Amulet of Glory.", - position = 21 - ) - default boolean getGlory() { - return true; - } + @ConfigItem( + keyName = "swapGlory", + name = "Swap Glory", + description = "Enables swapping of Amulet of Glory.", + position = 21 + ) + default boolean getGlory() + { + return true; + } - @ConfigItem( - keyName = "gloryMode", - name = "Glory Mode", - description = "Teleport location mode.", - position = 22 - ) + @ConfigItem( + keyName = "gloryMode", + name = "Glory Mode", + description = "Teleport location mode.", + position = 22 + ) - default GloryMode getGloryMode() { - return GloryMode.EDGEVILLE; - } + default GloryMode getGloryMode() + { + return GloryMode.EDGEVILLE; + } - @ConfigItem( - keyName = "swapWealthRing", - name = "Swap Ring of Wealth", - description = "Enables swapping of Ring of Wealth.", - position = 23 - ) - default boolean getWealthRing() { - return true; - } + @ConfigItem( + keyName = "swapWealthRing", + name = "Swap Ring of Wealth", + description = "Enables swapping of Ring of Wealth.", + position = 23 + ) + default boolean getWealthRing() + { + return true; + } - @ConfigItem( - keyName = "WealthRingMode", - name = "Wealth Ring Mode", - description = "Teleport location mode.", - position = 24 - ) + @ConfigItem( + keyName = "WealthRingMode", + name = "Wealth Ring Mode", + description = "Teleport location mode.", + position = 24 + ) - default WealthRingMode getWealthRingMode() { - return WealthRingMode.GRAND_EXCHANGE; - } + default WealthRingMode getWealthRingMode() + { + return WealthRingMode.GRAND_EXCHANGE; + } - @ConfigItem( - keyName = "swapConstructionCape", - name = "Swap Construction Cape", - description = "Enables swapping of teleport and wear.", - position = 25 - ) - default boolean getSwapConstructionCape() { - return true; - } + @ConfigItem( + keyName = "swapConstructionCape", + name = "Swap Construction Cape", + description = "Enables swapping of teleport and wear.", + position = 25 + ) + default boolean getSwapConstructionCape() + { + return true; + } - @ConfigItem( - keyName = "swapCraftingCape", - name = "Swap Crafting Cape", - description = "Enables swapping of teleport and wear.", - position = 26 - ) - default boolean getSwapCraftingCape() { - return true; - } + @ConfigItem( + keyName = "swapCraftingCape", + name = "Swap Crafting Cape", + description = "Enables swapping of teleport and wear.", + position = 26 + ) + default boolean getSwapCraftingCape() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EssenceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EssenceMode.java index e5d21e61fa..fe001dbea4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EssenceMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EssenceMode.java @@ -1,41 +1,44 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum EssenceMode { - RUNECRAFTING("Runecrafting"), - ESSENCE_MINING("Essence Mining"); - - private final String name; - - EssenceMode(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.easyscape; + +public enum EssenceMode +{ + RUNECRAFTING("Runecrafting"), + ESSENCE_MINING("Essence Mining"); + + private final String name; + + EssenceMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GamesNecklaceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GamesNecklaceMode.java index e4e54c4b90..457fc100bc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GamesNecklaceMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GamesNecklaceMode.java @@ -1,44 +1,47 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum GamesNecklaceMode { - BURTHORPE("Burthorpe"), - BARBARIAN_OUTPOST("Barbarian Outpost"), - CORPOREAL_BEAST("Corporeal Beast"), - TEARS_OF_GUTHIX("Tears of Guthix"), - WINTERTODT("Wintertodt Camp"); - - private final String name; - - GamesNecklaceMode(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.easyscape; + +public enum GamesNecklaceMode +{ + BURTHORPE("Burthorpe"), + BARBARIAN_OUTPOST("Barbarian Outpost"), + CORPOREAL_BEAST("Corporeal Beast"), + TEARS_OF_GUTHIX("Tears of Guthix"), + WINTERTODT("Wintertodt Camp"); + + private final String name; + + GamesNecklaceMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GloryMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GloryMode.java index 4d83526dfc..f160c41c56 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GloryMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GloryMode.java @@ -1,43 +1,46 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum GloryMode { - EDGEVILLE("Edgeville"), - KARAMJA("Karamja"), - DRAYNOR_VILLAGE("Draynor Village"), - AL_KHARID("Al Kharid"); - - private final String name; - - GloryMode(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.easyscape; + +public enum GloryMode +{ + EDGEVILLE("Edgeville"), + KARAMJA("Karamja"), + DRAYNOR_VILLAGE("Draynor Village"), + AL_KHARID("Al Kharid"); + + private final String name; + + GloryMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java index f865dd5da9..525aa5ee3c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java @@ -1,43 +1,46 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum WealthRingMode { - MISCELLANIA ("Miscellania"), - GRAND_EXCHANGE ("Grand Exchange"), - FALADOR ("Falador"), - DONDAKAN ("Dondakan"); - - private final String name; - - WealthRingMode(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.easyscape; + +public enum WealthRingMode +{ + MISCELLANIA("Miscellania"), + GRAND_EXCHANGE("Grand Exchange"), + FALADOR("Falador"), + DONDAKAN("Dondakan"); + + private final String name; + + WealthRingMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/ItemPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/ItemPanel.java index b9b10d2531..9a4807a981 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/ItemPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/ItemPanel.java @@ -40,7 +40,7 @@ class ItemPanel extends JPanel ItemPanel(ItemComposition item, KitType kitType, AsyncBufferedImage icon) { - setBorder(new EmptyBorder(3, 3, 3, 3)); + setBorder(new EmptyBorder(3, 3, 3, 3)); setBackground(ColorScheme.DARK_GRAY_COLOR); GroupLayout layout = new GroupLayout(this); @@ -55,20 +55,20 @@ class ItemPanel extends JPanel icon.addTo(imageLabel); layout.setVerticalGroup(layout.createParallelGroup() - .addComponent(imageLabel) - .addGroup(layout.createSequentialGroup() - .addComponent(name) - .addComponent(location) - ) + .addComponent(imageLabel) + .addGroup(layout.createSequentialGroup() + .addComponent(name) + .addComponent(location) + ) ); layout.setHorizontalGroup(layout.createSequentialGroup() - .addComponent(imageLabel) - .addGap(8) - .addGroup(layout.createParallelGroup() - .addComponent(name) - .addComponent(location) - ) + .addComponent(imageLabel) + .addGap(8) + .addGroup(layout.createParallelGroup() + .addComponent(name) + .addComponent(location) + ) ); // AWT's Z order is weird. This put image at the back of the stack diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/examine/CacheKey.java b/runelite-client/src/main/java/net/runelite/client/plugins/examine/CacheKey.java index 135b300979..f38d90d9d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/examine/CacheKey.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/examine/CacheKey.java @@ -1,75 +1,71 @@ -/* - * Copyright (c) 2017, Adam - * 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.examine; - -import java.util.Objects; - -class CacheKey -{ - private final ExamineType type; - private final int id; - - public CacheKey(ExamineType type, int id) - { - this.type = type; - this.id = id; - } - - @Override - public int hashCode() - { - int hash = 3; - hash = 23 * hash + Objects.hashCode(this.type); - hash = 23 * hash + this.id; - return hash; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (getClass() != obj.getClass()) - { - return false; - } - final CacheKey other = (CacheKey) obj; - if (this.id != other.id) - { - return false; - } - if (this.type != other.type) - { - return false; - } - return true; - } -} +/* + * Copyright (c) 2017, Adam + * 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.examine; + +import java.util.Objects; + +class CacheKey +{ + private final ExamineType type; + private final int id; + + public CacheKey(ExamineType type, int id) + { + this.type = type; + this.id = id; + } + + @Override + public int hashCode() + { + int hash = 3; + hash = 23 * hash + Objects.hashCode(this.type); + hash = 23 * hash + this.id; + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final CacheKey other = (CacheKey) obj; + if (this.id != other.id) + { + return false; + } + return this.type == other.type; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExamineType.java b/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExamineType.java index 790d0f1d77..5cda430a50 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExamineType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExamineType.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2017, Adam - * 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.examine; - -public enum ExamineType -{ - ITEM, - ITEM_BANK_EQ, - NPC, - OBJECT; -} +/* + * Copyright (c) 2017, Adam + * 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.examine; + +public enum ExamineType +{ + ITEM, + ITEM_BANK_EQ, + NPC, + OBJECT +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/PrayerType.java b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/PrayerType.java index 4e7efb793c..a47f96283c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/PrayerType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/PrayerType.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2018, Adam - * 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.experiencedrop; - -enum PrayerType -{ - MELEE, - RANGE, - MAGIC; -} +/* + * Copyright (c) 2018, Adam + * 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.experiencedrop; + +enum PrayerType +{ + MELEE, + RANGE, + MAGIC +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java index 0d1beab3e7..fa5aeab690 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java @@ -1,112 +1,112 @@ -/* - * Copyright (c) 2018, Cameron - * 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.experiencedrop; - -import java.awt.Color; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("xpdrop") -public interface XpDropConfig extends Config -{ - @ConfigItem( - keyName = "hideSkillIcons", - name = "Hide skill icons", - description = "Configure if XP drops will show their respective skill icons", - position = 0 - ) - default boolean hideSkillIcons() - { - return false; - } - - @ConfigItem( - keyName = "meleePrayerColor", - name = "Melee Prayer Color", - description = "XP drop color when a melee prayer is active", - position = 1 - ) - default Color getMeleePrayerColor() - { - return new Color(0x15, 0x80, 0xAD); - } - - @ConfigItem( - keyName = "rangePrayerColor", - name = "Range Prayer Color", - description = "XP drop color when a range prayer is active", - position = 2 - ) - default Color getRangePrayerColor() - { - return new Color(0x15, 0x80, 0xAD); - } - - @ConfigItem( - keyName = "magePrayerColor", - name = "Mage Prayer Color", - description = "XP drop color when a mage prayer is active", - position = 3 - ) - default Color getMagePrayerColor() - { - return new Color(0x15, 0x80, 0xAD); - } - - @ConfigItem( - keyName = "fakeXpDropDelay", - name = "Fake Xp Drop delay", - description = "Configures how many ticks should pass between fake XP drops, 0 to disable", - position = 4 - ) - default int fakeXpDropDelay() - { - return 0; - } - - @ConfigItem( - keyName = "showDamage", - name = "Show Damage on XP Drop", - description = "Show what you hit next to the XP drop", - position = 5 - ) - default boolean showDamage() - { - return false; - } - - @ConfigItem( - keyName = "damageColor", - name = "Damage Color", - description = "The color you want the text to be for damage", - position = 6 - ) - default Color getDamageColor() - { - return Color.RED; - } - -} +/* + * Copyright (c) 2018, Cameron + * 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.experiencedrop; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("xpdrop") +public interface XpDropConfig extends Config +{ + @ConfigItem( + keyName = "hideSkillIcons", + name = "Hide skill icons", + description = "Configure if XP drops will show their respective skill icons", + position = 0 + ) + default boolean hideSkillIcons() + { + return false; + } + + @ConfigItem( + keyName = "meleePrayerColor", + name = "Melee Prayer Color", + description = "XP drop color when a melee prayer is active", + position = 1 + ) + default Color getMeleePrayerColor() + { + return new Color(0x15, 0x80, 0xAD); + } + + @ConfigItem( + keyName = "rangePrayerColor", + name = "Range Prayer Color", + description = "XP drop color when a range prayer is active", + position = 2 + ) + default Color getRangePrayerColor() + { + return new Color(0x15, 0x80, 0xAD); + } + + @ConfigItem( + keyName = "magePrayerColor", + name = "Mage Prayer Color", + description = "XP drop color when a mage prayer is active", + position = 3 + ) + default Color getMagePrayerColor() + { + return new Color(0x15, 0x80, 0xAD); + } + + @ConfigItem( + keyName = "fakeXpDropDelay", + name = "Fake Xp Drop delay", + description = "Configures how many ticks should pass between fake XP drops, 0 to disable", + position = 4 + ) + default int fakeXpDropDelay() + { + return 0; + } + + @ConfigItem( + keyName = "showDamage", + name = "Show Damage on XP Drop", + description = "Show what you hit next to the XP drop", + position = 5 + ) + default boolean showDamage() + { + return false; + } + + @ConfigItem( + keyName = "damageColor", + name = "Damage Color", + description = "The color you want the text to be for damage", + position = 6 + ) + default Color getDamageColor() + { + return Color.RED; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropOverlay.java index 119da63597..c3b9bf916b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropOverlay.java @@ -1,73 +1,72 @@ -/* - * Copyright (c) 2017, honeyhoney - * 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.experiencedrop; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; - -import net.runelite.api.Actor; -import net.runelite.api.Point; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.OverlayUtil; - -class XpDropOverlay extends Overlay -{ - private final XpDropPlugin plugin; - private final XpDropConfig config; - - @Inject - private XpDropOverlay(XpDropPlugin plugin, XpDropConfig config) - { - this.plugin = plugin; - this.config = config; - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.MED); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (config.showDamage()) - { - final Actor opponent = plugin.getLastOpponent(); - if (opponent != null) - { - int offset = opponent.getLogicalHeight() + 50; - String damageStr = String.valueOf(this.plugin.getDamage()); - Point textLocation = opponent.getCanvasTextLocation(graphics, damageStr, offset); - - if (textLocation != null && this.plugin.getDamage() != 0) - { - OverlayUtil.renderTextLocation(graphics, textLocation, damageStr, config.getDamageColor()); - } - } - } - - return null; - } -} +/* + * Copyright (c) 2017, honeyhoney + * 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.experiencedrop; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Actor; +import net.runelite.api.Point; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; + +class XpDropOverlay extends Overlay +{ + private final XpDropPlugin plugin; + private final XpDropConfig config; + + @Inject + private XpDropOverlay(XpDropPlugin plugin, XpDropConfig config) + { + this.plugin = plugin; + this.config = config; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.MED); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (config.showDamage()) + { + final Actor opponent = plugin.getLastOpponent(); + if (opponent != null) + { + int offset = opponent.getLogicalHeight() + 50; + String damageStr = String.valueOf(this.plugin.getDamage()); + Point textLocation = opponent.getCanvasTextLocation(graphics, damageStr, offset); + + if (textLocation != null && this.plugin.getDamage() != 0) + { + OverlayUtil.renderTextLocation(graphics, textLocation, damageStr, config.getDamageColor()); + } + } + } + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropPlugin.java index e2344f7929..50e64e1558 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropPlugin.java @@ -1,453 +1,469 @@ -/* - * Copyright (c) 2018, Cameron , SoyChai - * 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.experiencedrop; - -import com.google.inject.Provides; - -import java.time.Duration; -import java.time.Instant; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.Map; -import java.util.stream.IntStream; -import javax.inject.Inject; - -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.*; - -import static net.runelite.api.ScriptID.XPDROP_DISABLED; -import static net.runelite.client.plugins.attackstyles.AttackStyle.*; - -import net.runelite.api.events.*; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetID; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.HiscoreManager; -import net.runelite.client.game.NPCManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.attackstyles.AttackStyle; -import net.runelite.client.plugins.attackstyles.WeaponType; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.Text; -import net.runelite.http.api.hiscore.HiscoreEndpoint; -import net.runelite.http.api.hiscore.HiscoreResult; - -@PluginDescriptor( - name = "XP Drop", - description = "Enable customization of the way XP drops are displayed", - tags = {"experience", "levels", "tick"} -) -public class XpDropPlugin extends Plugin -{ - private static final int XPDROP_PADDING = 2; // space between xp drop icons - private static final Duration WAIT = Duration.ofSeconds(5); - - @Inject - private Client client; - - @Inject - private XpDropConfig config; - - private int tickCounter = 0; - private int previousExpGained; - private boolean hasHit = false; - private boolean hasDropped = false; - private boolean correctPrayer; - private Skill lastSkill = null; - private Map previousSkillExpTable = new EnumMap<>(Skill.class); - private PrayerType currentTickPrayer; - private AttackStyle attackStyle; - private int attackStyleVarbit = -1; - private int equippedWeaponTypeVarbit = -1; - private int castingModeVarbit = -1; - private int opponentHealth = -1; - private int xpGains = 0; - private AttackStyle[] offensiveStyles = {ACCURATE, AGGRESSIVE, DEFENSIVE, CONTROLLED, RANGING, LONGRANGE, CASTING, DEFENSIVE_CASTING}; - - @Getter(AccessLevel.PACKAGE) - private int damage = 0; - - @Getter(AccessLevel.PACKAGE) - private Actor lastOpponent; - - private Instant lastTime; - - @Inject - private OverlayManager overlayManager; - - @Inject - private XpDropOverlay overlay; - - @Inject - private NPCManager npcManager; - - @Inject - private HiscoreManager hiscoreManager; - - @Provides - XpDropConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(XpDropConfig.class); - } - - @Override - protected void startUp() throws Exception - { - lastOpponent = null; - overlayManager.add(overlay); - if (client.getGameState() == GameState.LOGGED_IN) - { - attackStyleVarbit = client.getVar(VarPlayer.ATTACK_STYLE); - equippedWeaponTypeVarbit = client.getVar(Varbits.EQUIPPED_WEAPON_TYPE); - castingModeVarbit = client.getVar(Varbits.DEFENSIVE_CASTING_MODE); - updateAttackStyle( - equippedWeaponTypeVarbit, - attackStyleVarbit, - castingModeVarbit); - } - } - - @Subscribe - public void onWidgetHiddenChanged(WidgetHiddenChanged event) - { - Widget widget = event.getWidget(); - - int group = WidgetInfo.TO_GROUP(widget.getId()); - - if (group != WidgetID.EXPERIENCE_DROP_GROUP_ID) - { - return; - } - - if (widget.isHidden()) - { - return; - } - - if (config.hideSkillIcons()) - { - if (widget.getSpriteId() > 0) - { - widget.setHidden(true); - return; - } - else if (!widget.getText().isEmpty()) - { - // Align text accordingly to take up hidden skill icon space - int width = 0; - for (Widget w : widget.getParent().getDynamicChildren()) - { - if (w.getSpriteId() != -1) - { - if (width > 0) - { - // Add in space between sprites - width += XPDROP_PADDING; - } - width += w.getWidth(); // width of sprite - } - } - - final int xpDropPosition = client.getVar(Varbits.EXPERIENCE_TRACKER_POSITION); - switch (xpDropPosition) - { - case 2: // left - int cur = widget.getRelativeX(); - cur -= width; - widget.setRelativeX(cur); - break; - case 0: // right - break; - case 1: // center - cur = widget.getRelativeX(); - cur -= width / 2; - widget.setRelativeX(cur); - break; - } - } - } - - PrayerType prayer = currentTickPrayer; - if (prayer == null) - { - resetTextColor(widget); - return; - } - - String text = widget.getText(); - final IntStream spriteIDs = - Arrays.stream(widget.getParent().getDynamicChildren()).mapToInt(Widget::getSpriteId); - - if (text != null) - { - int color = widget.getTextColor(); - - switch (prayer) - { - case MELEE: - if (spriteIDs.anyMatch(id -> - id == SpriteID.SKILL_ATTACK || id == SpriteID.SKILL_STRENGTH || id == SpriteID.SKILL_DEFENCE - || correctPrayer)) - { - color = config.getMeleePrayerColor().getRGB(); - correctPrayer = true; - } - break; - case RANGE: - if (spriteIDs.anyMatch(id -> id == SpriteID.SKILL_RANGED || correctPrayer)) - { - color = config.getRangePrayerColor().getRGB(); - correctPrayer = true; - } - break; - case MAGIC: - if (spriteIDs.anyMatch(id -> id == SpriteID.SKILL_MAGIC || correctPrayer)) - { - color = config.getMagePrayerColor().getRGB(); - correctPrayer = true; - } - break; - } - - widget.setTextColor(color); - } - } - - private void resetTextColor(Widget widget) - { - int defaultColorIdx = client.getVar(Varbits.EXPERIENCE_DROP_COLOR); - int defaultColor = DefaultColors.values()[defaultColorIdx].getColor().getRGB(); - widget.setTextColor(defaultColor); - } - - private PrayerType getActivePrayerType() - { - for (XpPrayer prayer : XpPrayer.values()) - { - if (client.isPrayerActive(prayer.getPrayer())) - { - return prayer.getType(); - } - } - return null; - } - - @Subscribe - public void onGameTick(GameTick tick) - { - // Detect hitting a 0 - if (lastOpponent != null) - { - int health = calculateHealth(lastOpponent); - if (health != -1 && opponentHealth != -1 && health == opponentHealth && hasHit) - { - damage = 0; - hasHit = false; - } - } - - // Handle getting XP gains - if (hasDropped) - { - if (xpGains != 0 && attackStyle.getSkills().length > 1 && attackStyle != LONGRANGE) - { - damage = (int) (xpGains / (attackStyle.getSkills().length * 1.3)); - } - else if (xpGains != 0) - { - damage = xpGains / 4; - } - - xpGains = 0; - hasDropped = false; - } - - // Clear opponent - if (lastOpponent != null && lastTime != null && client.getLocalPlayer().getInteracting() == null) - { - if (Duration.between(lastTime, Instant.now()).compareTo(WAIT) > 0) - { - lastOpponent = null; - } - } - - currentTickPrayer = getActivePrayerType(); - correctPrayer = false; - - final int fakeTickDelay = config.fakeXpDropDelay(); - - if (fakeTickDelay == 0 || lastSkill == null) - { - return; - } - - // If an xp drop was created this tick, reset the counter - if (hasDropped) - { - hasDropped = false; - tickCounter = 0; - return; - } - - if (++tickCounter % fakeTickDelay != 0) - { - return; - } - - client.runScript(XPDROP_DISABLED, lastSkill.ordinal(), previousExpGained); - } - - @Subscribe - public void onExperienceChanged(ExperienceChanged event) - { - final Skill skill = event.getSkill(); - final int xp = client.getSkillExperience(skill); - - lastSkill = skill; - - Integer previous = previousSkillExpTable.put(skill, xp); - if (previous != null) - { - opponentHealth = calculateHealth(lastOpponent); - previousExpGained = xp - previous; - if (skill != Skill.HITPOINTS && Arrays.stream(offensiveStyles).anyMatch(attackStyle::equals)) - { - xpGains += previousExpGained; - } - - hasDropped = true; - hasHit = true; - } - } - - private void updateAttackStyle(int equippedWeaponType, int attackStyleIndex, int castingMode) - { - AttackStyle[] attackStyles = WeaponType.getWeaponType(equippedWeaponType).getAttackStyles(); - if (attackStyleIndex < attackStyles.length) - { - attackStyle = attackStyles[attackStyleIndex]; - if (attackStyle == null) - { - attackStyle = OTHER; - } - else if ((attackStyle == CASTING) && (castingMode == 1)) - { - attackStyle = DEFENSIVE_CASTING; - } - } - } - - @Subscribe - public void onInteractingChanged(InteractingChanged event) - { - if (event.getSource() != client.getLocalPlayer()) - { - return; - } - - Actor opponent = event.getTarget(); - - if (opponent == null) - { - lastTime = Instant.now(); - return; - } - else if (opponent.getName().equalsIgnoreCase("fishing spot")) - { - lastTime = Instant.now().minus(WAIT); - return; - } - - damage = 0; - lastOpponent = opponent; - opponentHealth = calculateHealth(opponent); - } - - private int calculateHealth(Actor target) - { - if (target == null || target.getName() == null) - { - return -1; - } - - final int healthScale = target.getHealth(); - final int healthRatio = target.getHealthRatio(); - final String targetName = Text.removeTags(target.getName()); - - Integer maxHealth = -1; - if (target instanceof NPC) - { - maxHealth = npcManager.getHealth(targetName, target.getCombatLevel()); - } - else if (target instanceof Player) - { - final HiscoreResult hiscoreResult = hiscoreManager.lookupAsync(targetName, HiscoreEndpoint.NORMAL); - if (hiscoreResult != null) - { - final int hp = hiscoreResult.getHitpoints().getLevel(); - if (hp > 0) - { - maxHealth = hp; - } - } - } - - if (healthRatio < 0 || healthScale <= 0 || maxHealth == null) - { - return -1; - } - - return (int)((maxHealth * healthRatio / healthScale) + 0.5f); - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - if (attackStyleVarbit == -1 || attackStyleVarbit != client.getVar(VarPlayer.ATTACK_STYLE)) - { - attackStyleVarbit = client.getVar(VarPlayer.ATTACK_STYLE); - updateAttackStyle(client.getVar(Varbits.EQUIPPED_WEAPON_TYPE), attackStyleVarbit, - client.getVar(Varbits.DEFENSIVE_CASTING_MODE)); - } - - if (equippedWeaponTypeVarbit == -1 || equippedWeaponTypeVarbit != client.getVar(Varbits.EQUIPPED_WEAPON_TYPE)) - { - equippedWeaponTypeVarbit = client.getVar(Varbits.EQUIPPED_WEAPON_TYPE); - updateAttackStyle(equippedWeaponTypeVarbit, client.getVar(VarPlayer.ATTACK_STYLE), - client.getVar(Varbits.DEFENSIVE_CASTING_MODE)); - } - - if (castingModeVarbit == -1 || castingModeVarbit != client.getVar(Varbits.DEFENSIVE_CASTING_MODE)) - { - castingModeVarbit = client.getVar(Varbits.DEFENSIVE_CASTING_MODE); - updateAttackStyle(client.getVar(Varbits.EQUIPPED_WEAPON_TYPE), client.getVar(VarPlayer.ATTACK_STYLE), - castingModeVarbit); - } - } -} +/* + * Copyright (c) 2018, Cameron , SoyChai + * 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.experiencedrop; + +import com.google.inject.Provides; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.Map; +import java.util.stream.IntStream; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import static net.runelite.api.ScriptID.XPDROP_DISABLED; +import net.runelite.api.Skill; +import net.runelite.api.SpriteID; +import net.runelite.api.VarPlayer; +import net.runelite.api.Varbits; +import net.runelite.api.events.ExperienceChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.InteractingChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.events.WidgetHiddenChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.HiscoreManager; +import net.runelite.client.game.NPCManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.attackstyles.AttackStyle; +import static net.runelite.client.plugins.attackstyles.AttackStyle.ACCURATE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.AGGRESSIVE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.CASTING; +import static net.runelite.client.plugins.attackstyles.AttackStyle.CONTROLLED; +import static net.runelite.client.plugins.attackstyles.AttackStyle.DEFENSIVE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.DEFENSIVE_CASTING; +import static net.runelite.client.plugins.attackstyles.AttackStyle.LONGRANGE; +import static net.runelite.client.plugins.attackstyles.AttackStyle.OTHER; +import static net.runelite.client.plugins.attackstyles.AttackStyle.RANGING; +import net.runelite.client.plugins.attackstyles.WeaponType; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.Text; +import net.runelite.http.api.hiscore.HiscoreEndpoint; +import net.runelite.http.api.hiscore.HiscoreResult; + +@PluginDescriptor( + name = "XP Drop", + description = "Enable customization of the way XP drops are displayed", + tags = {"experience", "levels", "tick"} +) +public class XpDropPlugin extends Plugin +{ + private static final int XPDROP_PADDING = 2; // space between xp drop icons + private static final Duration WAIT = Duration.ofSeconds(5); + + @Inject + private Client client; + + @Inject + private XpDropConfig config; + + private int tickCounter = 0; + private int previousExpGained; + private boolean hasHit = false; + private boolean hasDropped = false; + private boolean correctPrayer; + private Skill lastSkill = null; + private Map previousSkillExpTable = new EnumMap<>(Skill.class); + private PrayerType currentTickPrayer; + private AttackStyle attackStyle; + private int attackStyleVarbit = -1; + private int equippedWeaponTypeVarbit = -1; + private int castingModeVarbit = -1; + private int opponentHealth = -1; + private int xpGains = 0; + private AttackStyle[] offensiveStyles = {ACCURATE, AGGRESSIVE, DEFENSIVE, CONTROLLED, RANGING, LONGRANGE, CASTING, DEFENSIVE_CASTING}; + + @Getter(AccessLevel.PACKAGE) + private int damage = 0; + + @Getter(AccessLevel.PACKAGE) + private Actor lastOpponent; + + private Instant lastTime; + + @Inject + private OverlayManager overlayManager; + + @Inject + private XpDropOverlay overlay; + + @Inject + private NPCManager npcManager; + + @Inject + private HiscoreManager hiscoreManager; + + @Provides + XpDropConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(XpDropConfig.class); + } + + @Override + protected void startUp() throws Exception + { + lastOpponent = null; + overlayManager.add(overlay); + if (client.getGameState() == GameState.LOGGED_IN) + { + attackStyleVarbit = client.getVar(VarPlayer.ATTACK_STYLE); + equippedWeaponTypeVarbit = client.getVar(Varbits.EQUIPPED_WEAPON_TYPE); + castingModeVarbit = client.getVar(Varbits.DEFENSIVE_CASTING_MODE); + updateAttackStyle( + equippedWeaponTypeVarbit, + attackStyleVarbit, + castingModeVarbit); + } + } + + @Subscribe + public void onWidgetHiddenChanged(WidgetHiddenChanged event) + { + Widget widget = event.getWidget(); + + int group = WidgetInfo.TO_GROUP(widget.getId()); + + if (group != WidgetID.EXPERIENCE_DROP_GROUP_ID) + { + return; + } + + if (widget.isHidden()) + { + return; + } + + if (config.hideSkillIcons()) + { + if (widget.getSpriteId() > 0) + { + widget.setHidden(true); + return; + } + else if (!widget.getText().isEmpty()) + { + // Align text accordingly to take up hidden skill icon space + int width = 0; + for (Widget w : widget.getParent().getDynamicChildren()) + { + if (w.getSpriteId() != -1) + { + if (width > 0) + { + // Add in space between sprites + width += XPDROP_PADDING; + } + width += w.getWidth(); // width of sprite + } + } + + final int xpDropPosition = client.getVar(Varbits.EXPERIENCE_TRACKER_POSITION); + switch (xpDropPosition) + { + case 2: // left + int cur = widget.getRelativeX(); + cur -= width; + widget.setRelativeX(cur); + break; + case 0: // right + break; + case 1: // center + cur = widget.getRelativeX(); + cur -= width / 2; + widget.setRelativeX(cur); + break; + } + } + } + + PrayerType prayer = currentTickPrayer; + if (prayer == null) + { + resetTextColor(widget); + return; + } + + String text = widget.getText(); + final IntStream spriteIDs = + Arrays.stream(widget.getParent().getDynamicChildren()).mapToInt(Widget::getSpriteId); + + if (text != null) + { + int color = widget.getTextColor(); + + switch (prayer) + { + case MELEE: + if (spriteIDs.anyMatch(id -> + id == SpriteID.SKILL_ATTACK || id == SpriteID.SKILL_STRENGTH || id == SpriteID.SKILL_DEFENCE + || correctPrayer)) + { + color = config.getMeleePrayerColor().getRGB(); + correctPrayer = true; + } + break; + case RANGE: + if (spriteIDs.anyMatch(id -> id == SpriteID.SKILL_RANGED || correctPrayer)) + { + color = config.getRangePrayerColor().getRGB(); + correctPrayer = true; + } + break; + case MAGIC: + if (spriteIDs.anyMatch(id -> id == SpriteID.SKILL_MAGIC || correctPrayer)) + { + color = config.getMagePrayerColor().getRGB(); + correctPrayer = true; + } + break; + } + + widget.setTextColor(color); + } + } + + private void resetTextColor(Widget widget) + { + int defaultColorIdx = client.getVar(Varbits.EXPERIENCE_DROP_COLOR); + int defaultColor = DefaultColors.values()[defaultColorIdx].getColor().getRGB(); + widget.setTextColor(defaultColor); + } + + private PrayerType getActivePrayerType() + { + for (XpPrayer prayer : XpPrayer.values()) + { + if (client.isPrayerActive(prayer.getPrayer())) + { + return prayer.getType(); + } + } + return null; + } + + @Subscribe + public void onGameTick(GameTick tick) + { + // Detect hitting a 0 + if (lastOpponent != null) + { + int health = calculateHealth(lastOpponent); + if (health != -1 && opponentHealth != -1 && health == opponentHealth && hasHit) + { + damage = 0; + hasHit = false; + } + } + + // Handle getting XP gains + if (hasDropped) + { + if (xpGains != 0 && attackStyle.getSkills().length > 1 && attackStyle != LONGRANGE) + { + damage = (int) (xpGains / (attackStyle.getSkills().length * 1.3)); + } + else if (xpGains != 0) + { + damage = xpGains / 4; + } + + xpGains = 0; + hasDropped = false; + } + + // Clear opponent + if (lastOpponent != null && lastTime != null && client.getLocalPlayer().getInteracting() == null) + { + if (Duration.between(lastTime, Instant.now()).compareTo(WAIT) > 0) + { + lastOpponent = null; + } + } + + currentTickPrayer = getActivePrayerType(); + correctPrayer = false; + + final int fakeTickDelay = config.fakeXpDropDelay(); + + if (fakeTickDelay == 0 || lastSkill == null) + { + return; + } + + // If an xp drop was created this tick, reset the counter + if (hasDropped) + { + hasDropped = false; + tickCounter = 0; + return; + } + + if (++tickCounter % fakeTickDelay != 0) + { + return; + } + + client.runScript(XPDROP_DISABLED, lastSkill.ordinal(), previousExpGained); + } + + @Subscribe + public void onExperienceChanged(ExperienceChanged event) + { + final Skill skill = event.getSkill(); + final int xp = client.getSkillExperience(skill); + + lastSkill = skill; + + Integer previous = previousSkillExpTable.put(skill, xp); + if (previous != null) + { + opponentHealth = calculateHealth(lastOpponent); + previousExpGained = xp - previous; + if (skill != Skill.HITPOINTS && Arrays.stream(offensiveStyles).anyMatch(attackStyle::equals)) + { + xpGains += previousExpGained; + } + + hasDropped = true; + hasHit = true; + } + } + + private void updateAttackStyle(int equippedWeaponType, int attackStyleIndex, int castingMode) + { + AttackStyle[] attackStyles = WeaponType.getWeaponType(equippedWeaponType).getAttackStyles(); + if (attackStyleIndex < attackStyles.length) + { + attackStyle = attackStyles[attackStyleIndex]; + if (attackStyle == null) + { + attackStyle = OTHER; + } + else if ((attackStyle == CASTING) && (castingMode == 1)) + { + attackStyle = DEFENSIVE_CASTING; + } + } + } + + @Subscribe + public void onInteractingChanged(InteractingChanged event) + { + if (event.getSource() != client.getLocalPlayer()) + { + return; + } + + Actor opponent = event.getTarget(); + + if (opponent == null) + { + lastTime = Instant.now(); + return; + } + else if (opponent.getName().equalsIgnoreCase("fishing spot")) + { + lastTime = Instant.now().minus(WAIT); + return; + } + + damage = 0; + lastOpponent = opponent; + opponentHealth = calculateHealth(opponent); + } + + private int calculateHealth(Actor target) + { + if (target == null || target.getName() == null) + { + return -1; + } + + final int healthScale = target.getHealth(); + final int healthRatio = target.getHealthRatio(); + final String targetName = Text.removeTags(target.getName()); + + Integer maxHealth = -1; + if (target instanceof NPC) + { + maxHealth = npcManager.getHealth(targetName, target.getCombatLevel()); + } + else if (target instanceof Player) + { + final HiscoreResult hiscoreResult = hiscoreManager.lookupAsync(targetName, HiscoreEndpoint.NORMAL); + if (hiscoreResult != null) + { + final int hp = hiscoreResult.getHitpoints().getLevel(); + if (hp > 0) + { + maxHealth = hp; + } + } + } + + if (healthRatio < 0 || healthScale <= 0 || maxHealth == null) + { + return -1; + } + + return (int) ((maxHealth * healthRatio / healthScale) + 0.5f); + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + if (attackStyleVarbit == -1 || attackStyleVarbit != client.getVar(VarPlayer.ATTACK_STYLE)) + { + attackStyleVarbit = client.getVar(VarPlayer.ATTACK_STYLE); + updateAttackStyle(client.getVar(Varbits.EQUIPPED_WEAPON_TYPE), attackStyleVarbit, + client.getVar(Varbits.DEFENSIVE_CASTING_MODE)); + } + + if (equippedWeaponTypeVarbit == -1 || equippedWeaponTypeVarbit != client.getVar(Varbits.EQUIPPED_WEAPON_TYPE)) + { + equippedWeaponTypeVarbit = client.getVar(Varbits.EQUIPPED_WEAPON_TYPE); + updateAttackStyle(equippedWeaponTypeVarbit, client.getVar(VarPlayer.ATTACK_STYLE), + client.getVar(Varbits.DEFENSIVE_CASTING_MODE)); + } + + if (castingModeVarbit == -1 || castingModeVarbit != client.getVar(Varbits.DEFENSIVE_CASTING_MODE)) + { + castingModeVarbit = client.getVar(Varbits.DEFENSIVE_CASTING_MODE); + updateAttackStyle(client.getVar(Varbits.EQUIPPED_WEAPON_TYPE), client.getVar(VarPlayer.ATTACK_STYLE), + castingModeVarbit); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpPrayer.java b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpPrayer.java index 61ff0b088c..b1b80f2509 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpPrayer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpPrayer.java @@ -1,63 +1,78 @@ -/* - * Copyright (c) 2018, Adam - * 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.experiencedrop; - -import lombok.Getter; -import net.runelite.api.Prayer; -import static net.runelite.api.Prayer.*; -import static net.runelite.client.plugins.experiencedrop.PrayerType.MAGIC; -import static net.runelite.client.plugins.experiencedrop.PrayerType.MELEE; -import static net.runelite.client.plugins.experiencedrop.PrayerType.RANGE; - -enum XpPrayer -{ - XP_BURST_OF_STRENGTH(BURST_OF_STRENGTH, MELEE), - XP_CLARITY_OF_THOUGHT(CLARITY_OF_THOUGHT, MELEE), - XP_SHARP_EYE(SHARP_EYE, RANGE), - XP_MYSTIC_WILL(MYSTIC_WILL, MAGIC), - XP_SUPERHUMAN_STRENGTH(SUPERHUMAN_STRENGTH, MELEE), - XP_IMPROVED_REFLEXES(IMPROVED_REFLEXES, MELEE), - XP_HAWK_EYE(HAWK_EYE, RANGE), - XP_MYSTIC_LORE(MYSTIC_LORE, MAGIC), - XP_ULTIMATE_STRENGTH(ULTIMATE_STRENGTH, MELEE), - XP_INCREDIBLE_REFLEXES(INCREDIBLE_REFLEXES, MELEE), - XP_EAGLE_EYE(EAGLE_EYE, RANGE), - XP_MYSTIC_MIGHT(MYSTIC_MIGHT, MAGIC), - XP_CHIVALRY(CHIVALRY, MELEE), - XP_PIETY(PIETY, MELEE), - XP_RIGOUR(RIGOUR, RANGE), - XP_AUGURY(AUGURY, MAGIC); - - @Getter - private final Prayer prayer; - @Getter - private final PrayerType type; - - XpPrayer(Prayer prayer, PrayerType type) - { - this.prayer = prayer; - this.type = type; - } -} +/* + * Copyright (c) 2018, Adam + * 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.experiencedrop; + +import lombok.Getter; +import net.runelite.api.Prayer; +import static net.runelite.api.Prayer.AUGURY; +import static net.runelite.api.Prayer.BURST_OF_STRENGTH; +import static net.runelite.api.Prayer.CHIVALRY; +import static net.runelite.api.Prayer.CLARITY_OF_THOUGHT; +import static net.runelite.api.Prayer.EAGLE_EYE; +import static net.runelite.api.Prayer.HAWK_EYE; +import static net.runelite.api.Prayer.IMPROVED_REFLEXES; +import static net.runelite.api.Prayer.INCREDIBLE_REFLEXES; +import static net.runelite.api.Prayer.MYSTIC_LORE; +import static net.runelite.api.Prayer.MYSTIC_MIGHT; +import static net.runelite.api.Prayer.MYSTIC_WILL; +import static net.runelite.api.Prayer.PIETY; +import static net.runelite.api.Prayer.RIGOUR; +import static net.runelite.api.Prayer.SHARP_EYE; +import static net.runelite.api.Prayer.SUPERHUMAN_STRENGTH; +import static net.runelite.api.Prayer.ULTIMATE_STRENGTH; +import static net.runelite.client.plugins.experiencedrop.PrayerType.MAGIC; +import static net.runelite.client.plugins.experiencedrop.PrayerType.MELEE; +import static net.runelite.client.plugins.experiencedrop.PrayerType.RANGE; + +enum XpPrayer +{ + XP_BURST_OF_STRENGTH(BURST_OF_STRENGTH, MELEE), + XP_CLARITY_OF_THOUGHT(CLARITY_OF_THOUGHT, MELEE), + XP_SHARP_EYE(SHARP_EYE, RANGE), + XP_MYSTIC_WILL(MYSTIC_WILL, MAGIC), + XP_SUPERHUMAN_STRENGTH(SUPERHUMAN_STRENGTH, MELEE), + XP_IMPROVED_REFLEXES(IMPROVED_REFLEXES, MELEE), + XP_HAWK_EYE(HAWK_EYE, RANGE), + XP_MYSTIC_LORE(MYSTIC_LORE, MAGIC), + XP_ULTIMATE_STRENGTH(ULTIMATE_STRENGTH, MELEE), + XP_INCREDIBLE_REFLEXES(INCREDIBLE_REFLEXES, MELEE), + XP_EAGLE_EYE(EAGLE_EYE, RANGE), + XP_MYSTIC_MIGHT(MYSTIC_MIGHT, MAGIC), + XP_CHIVALRY(CHIVALRY, MELEE), + XP_PIETY(PIETY, MELEE), + XP_RIGOUR(RIGOUR, RANGE), + XP_AUGURY(AUGURY, MAGIC); + + @Getter + private final Prayer prayer; + @Getter + private final PrayerType type; + + XpPrayer(Prayer prayer, PrayerType type) + { + this.prayer = prayer; + this.type = type; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fairyring/FairyRingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fairyring/FairyRingPlugin.java index 644c05859b..c0e91cf335 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fairyring/FairyRingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fairyring/FairyRingPlugin.java @@ -1,366 +1,366 @@ -/* - * Copyright (c) 2018 Abex - * Copyright (c) 2017, Tyler - * Copyright (c) 2018, Yoav Ram - * Copyright (c) 2018, Infinitay - * 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.fairyring; - -import com.google.common.base.Strings; -import com.google.inject.Provides; -import java.util.Collection; -import java.util.Map; -import java.util.TreeMap; -import javax.annotation.Nullable; -import javax.inject.Inject; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.ScriptEvent; -import net.runelite.api.ScriptID; -import net.runelite.api.SoundEffectID; -import net.runelite.api.SpriteID; -import net.runelite.api.Varbits; -import net.runelite.api.widgets.WidgetType; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.VarbitChanged; -import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetID; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.chatbox.ChatboxPanelManager; -import net.runelite.client.game.chatbox.ChatboxTextInput; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.util.Text; - -@Slf4j -@PluginDescriptor( - name = "Fairy Rings", - description = "Show the location of the fairy ring teleport", - tags = {"teleportation"} -) -public class FairyRingPlugin extends Plugin -{ - private static final String[] leftDial = new String[]{"A", "D", "C", "B"}; - private static final String[] middleDial = new String[]{"I", "L", "K", "J"}; - private static final String[] rightDial = new String[]{"P", "S", "R", "Q"}; - - private static final int ENTRY_PADDING = 3; - - private static final String MENU_OPEN = "Open"; - private static final String MENU_CLOSE = "Close"; - - @Inject - private Client client; - - @Inject - private FairyRingConfig config; - - @Inject - private ChatboxPanelManager chatboxPanelManager; - - @Inject - private ClientThread clientThread; - - private ChatboxTextInput searchInput = null; - private Widget searchBtn; - private Collection codes = null; - - @Data - private static class CodeWidgets - { - // The fairy hideout has both of these null, because its not the same as the rest of them - @Nullable - private Widget favorite; - - @Nullable - private Widget code; - - private Widget description; - } - - @Provides - FairyRingConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(FairyRingConfig.class); - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - setWidgetTextToDestination(); - } - - @Subscribe - public void onWidgetLoaded(WidgetLoaded widgetLoaded) - { - if (widgetLoaded.getGroupId() == WidgetID.FAIRY_RING_PANEL_GROUP_ID) - { - setWidgetTextToDestination(); - - Widget header = client.getWidget(WidgetInfo.FAIRY_RING_HEADER); - if (header != null) - { - searchBtn = header.createChild(-1, WidgetType.GRAPHIC); - searchBtn.setSpriteId(SpriteID.GE_SEARCH); - searchBtn.setOriginalWidth(17); - searchBtn.setOriginalHeight(17); - searchBtn.setOriginalX(11); - searchBtn.setOriginalY(11); - searchBtn.setHasListener(true); - searchBtn.setAction(1, MENU_OPEN); - searchBtn.setOnOpListener((JavaScriptCallback) this::menuOpen); - searchBtn.setName("Search"); - searchBtn.revalidate(); - - codes = null; - - if (config.autoOpen()) - { - openSearch(); - } - } - } - } - - private void menuOpen(ScriptEvent e) - { - openSearch(); - client.playSoundEffect(SoundEffectID.UI_BOOP); - } - - private void menuClose(ScriptEvent e) - { - updateFilter(""); - chatboxPanelManager.close(); - client.playSoundEffect(SoundEffectID.UI_BOOP); - } - - private void setWidgetTextToDestination() - { - Widget fairyRingTeleportButton = client.getWidget(WidgetInfo.FAIRY_RING_TELEPORT_BUTTON); - if (fairyRingTeleportButton != null && !fairyRingTeleportButton.isHidden()) - { - String destination; - try - { - FairyRings fairyRingDestination = getFairyRingDestination(client.getVar(Varbits.FAIRY_RING_DIAL_ADCB), - client.getVar(Varbits.FAIRY_RIGH_DIAL_ILJK), client.getVar(Varbits.FAIRY_RING_DIAL_PSRQ)); - destination = fairyRingDestination.getDestination(); - } - catch (IllegalArgumentException ex) - { - destination = "Invalid location"; - } - - fairyRingTeleportButton.setText(destination); - } - } - - private FairyRings getFairyRingDestination(int varbitValueDialLeft, int varbitValueDialMiddle, int varbitValueDialRight) - { - return FairyRings.valueOf(leftDial[varbitValueDialLeft] + middleDial[varbitValueDialMiddle] + rightDial[varbitValueDialRight]); - } - - private void openSearch() - { - updateFilter(""); - searchBtn.setAction(1, MENU_CLOSE); - searchBtn.setOnOpListener((JavaScriptCallback) this::menuClose); - searchInput = chatboxPanelManager.openTextInput("Filter fairy rings") - .onChanged(s -> clientThread.invokeLater(() -> updateFilter(s))) - .onClose(() -> - { - clientThread.invokeLater(() -> updateFilter("")); - searchBtn.setOnOpListener((JavaScriptCallback) this::menuOpen); - searchBtn.setAction(1, MENU_OPEN); - }) - .build(); - } - - @Subscribe - public void onGameTick(GameTick t) - { - // This has to happen because the only widget that gets hidden is the tli one - Widget fairyRingTeleportButton = client.getWidget(WidgetInfo.FAIRY_RING_TELEPORT_BUTTON); - boolean fairyRingWidgetOpen = fairyRingTeleportButton != null && !fairyRingTeleportButton.isHidden(); - boolean chatboxOpen = searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput; - - if (!fairyRingWidgetOpen && chatboxOpen) - { - chatboxPanelManager.close(); - } - } - - private void updateFilter(String filter) - { - filter = filter.toLowerCase(); - final Widget list = client.getWidget(WidgetInfo.FAIRY_RING_LIST); - final Widget favorites = client.getWidget(WidgetInfo.FAIRY_RING_FAVORITES); - - if (list == null) - { - return; - } - - if (codes != null) - { - // Check to make sure the list hasn't been rebuild since we were last her - // Do this by making sure the list's dynamic children are the same as when we last saw them - if (codes.stream().noneMatch(w -> - { - Widget codeWidget = w.getCode(); - if (codeWidget == null) - { - return false; - } - return list.getChild(codeWidget.getIndex()) == codeWidget; - })) - { - codes = null; - } - } - - if (codes == null) - { - // Find all of the widgets that we care about, grouping by their Y value - Map codeMap = new TreeMap<>(); - - for (Widget w : list.getStaticChildren()) - { - if (w.isSelfHidden()) - { - continue; - } - - if (w.getSpriteId() != -1) - { - codeMap.computeIfAbsent(w.getRelativeY(), k -> new CodeWidgets()).setFavorite(w); - } - else if (!Strings.isNullOrEmpty(w.getText())) - { - codeMap.computeIfAbsent(w.getRelativeY(), k -> new CodeWidgets()).setDescription(w); - } - } - - for (Widget w : list.getDynamicChildren()) - { - if (w.isSelfHidden()) - { - continue; - } - - CodeWidgets c = codeMap.computeIfAbsent(w.getRelativeY(), k -> new CodeWidgets()); - c.setCode(w); - } - - codes = codeMap.values(); - } - - // Relayout the panel - int y = 0; - - if (favorites != null) - { - boolean hide = !filter.isEmpty(); - favorites.setHidden(hide); - if (!hide) - { - y += favorites.getOriginalHeight() + ENTRY_PADDING; - } - } - - for (CodeWidgets c : codes) - { - String code = Text.removeTags(c.getDescription().getName()).replaceAll(" ", ""); - String tags = null; - - if (!code.isEmpty()) - { - try - { - FairyRings ring = FairyRings.valueOf(code); - tags = ring.getTags(); - } - catch (IllegalArgumentException e) - { - log.warn("Unable to find ring with code '{}'", code, e); - } - } - - boolean hidden = !(filter.isEmpty() - || Text.removeTags(c.getDescription().getText()).toLowerCase().contains(filter) - || code.toLowerCase().contains(filter) - || tags != null && tags.contains(filter)); - - if (c.getCode() != null) - { - c.getCode().setHidden(hidden); - c.getCode().setOriginalY(y); - } - - if (c.getFavorite() != null) - { - c.getFavorite().setHidden(hidden); - c.getFavorite().setOriginalY(y); - } - - c.getDescription().setHidden(hidden); - c.getDescription().setOriginalY(y); - - if (!hidden) - { - y += c.getDescription().getHeight() + ENTRY_PADDING; - } - } - - y -= ENTRY_PADDING; - - if (y < 0) - { - y = 0; - } - - int newHeight = 0; - if (list.getScrollHeight() > 0) - { - newHeight = (list.getScrollY() * y) / list.getScrollHeight(); - } - - list.setScrollHeight(y); - list.revalidateScroll(); - client.runScript( - ScriptID.UPDATE_SCROLLBAR, - WidgetInfo.FAIRY_RING_LIST_SCROLLBAR.getId(), - WidgetInfo.FAIRY_RING_LIST.getId(), - newHeight - ); - } -} +/* + * Copyright (c) 2018 Abex + * Copyright (c) 2017, Tyler + * Copyright (c) 2018, Yoav Ram + * Copyright (c) 2018, Infinitay + * 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.fairyring; + +import com.google.common.base.Strings; +import com.google.inject.Provides; +import java.util.Collection; +import java.util.Map; +import java.util.TreeMap; +import javax.annotation.Nullable; +import javax.inject.Inject; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.ScriptEvent; +import net.runelite.api.ScriptID; +import net.runelite.api.SoundEffectID; +import net.runelite.api.SpriteID; +import net.runelite.api.Varbits; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.chatbox.ChatboxPanelManager; +import net.runelite.client.game.chatbox.ChatboxTextInput; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.Text; + +@Slf4j +@PluginDescriptor( + name = "Fairy Rings", + description = "Show the location of the fairy ring teleport", + tags = {"teleportation"} +) +public class FairyRingPlugin extends Plugin +{ + private static final String[] leftDial = new String[]{"A", "D", "C", "B"}; + private static final String[] middleDial = new String[]{"I", "L", "K", "J"}; + private static final String[] rightDial = new String[]{"P", "S", "R", "Q"}; + + private static final int ENTRY_PADDING = 3; + + private static final String MENU_OPEN = "Open"; + private static final String MENU_CLOSE = "Close"; + + @Inject + private Client client; + + @Inject + private FairyRingConfig config; + + @Inject + private ChatboxPanelManager chatboxPanelManager; + + @Inject + private ClientThread clientThread; + + private ChatboxTextInput searchInput = null; + private Widget searchBtn; + private Collection codes = null; + + @Data + private static class CodeWidgets + { + // The fairy hideout has both of these null, because its not the same as the rest of them + @Nullable + private Widget favorite; + + @Nullable + private Widget code; + + private Widget description; + } + + @Provides + FairyRingConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(FairyRingConfig.class); + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + setWidgetTextToDestination(); + } + + @Subscribe + public void onWidgetLoaded(WidgetLoaded widgetLoaded) + { + if (widgetLoaded.getGroupId() == WidgetID.FAIRY_RING_PANEL_GROUP_ID) + { + setWidgetTextToDestination(); + + Widget header = client.getWidget(WidgetInfo.FAIRY_RING_HEADER); + if (header != null) + { + searchBtn = header.createChild(-1, WidgetType.GRAPHIC); + searchBtn.setSpriteId(SpriteID.GE_SEARCH); + searchBtn.setOriginalWidth(17); + searchBtn.setOriginalHeight(17); + searchBtn.setOriginalX(11); + searchBtn.setOriginalY(11); + searchBtn.setHasListener(true); + searchBtn.setAction(1, MENU_OPEN); + searchBtn.setOnOpListener((JavaScriptCallback) this::menuOpen); + searchBtn.setName("Search"); + searchBtn.revalidate(); + + codes = null; + + if (config.autoOpen()) + { + openSearch(); + } + } + } + } + + private void menuOpen(ScriptEvent e) + { + openSearch(); + client.playSoundEffect(SoundEffectID.UI_BOOP); + } + + private void menuClose(ScriptEvent e) + { + updateFilter(""); + chatboxPanelManager.close(); + client.playSoundEffect(SoundEffectID.UI_BOOP); + } + + private void setWidgetTextToDestination() + { + Widget fairyRingTeleportButton = client.getWidget(WidgetInfo.FAIRY_RING_TELEPORT_BUTTON); + if (fairyRingTeleportButton != null && !fairyRingTeleportButton.isHidden()) + { + String destination; + try + { + FairyRings fairyRingDestination = getFairyRingDestination(client.getVar(Varbits.FAIRY_RING_DIAL_ADCB), + client.getVar(Varbits.FAIRY_RIGH_DIAL_ILJK), client.getVar(Varbits.FAIRY_RING_DIAL_PSRQ)); + destination = fairyRingDestination.getDestination(); + } + catch (IllegalArgumentException ex) + { + destination = "Invalid location"; + } + + fairyRingTeleportButton.setText(destination); + } + } + + private FairyRings getFairyRingDestination(int varbitValueDialLeft, int varbitValueDialMiddle, int varbitValueDialRight) + { + return FairyRings.valueOf(leftDial[varbitValueDialLeft] + middleDial[varbitValueDialMiddle] + rightDial[varbitValueDialRight]); + } + + private void openSearch() + { + updateFilter(""); + searchBtn.setAction(1, MENU_CLOSE); + searchBtn.setOnOpListener((JavaScriptCallback) this::menuClose); + searchInput = chatboxPanelManager.openTextInput("Filter fairy rings") + .onChanged(s -> clientThread.invokeLater(() -> updateFilter(s))) + .onClose(() -> + { + clientThread.invokeLater(() -> updateFilter("")); + searchBtn.setOnOpListener((JavaScriptCallback) this::menuOpen); + searchBtn.setAction(1, MENU_OPEN); + }) + .build(); + } + + @Subscribe + public void onGameTick(GameTick t) + { + // This has to happen because the only widget that gets hidden is the tli one + Widget fairyRingTeleportButton = client.getWidget(WidgetInfo.FAIRY_RING_TELEPORT_BUTTON); + boolean fairyRingWidgetOpen = fairyRingTeleportButton != null && !fairyRingTeleportButton.isHidden(); + boolean chatboxOpen = searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput; + + if (!fairyRingWidgetOpen && chatboxOpen) + { + chatboxPanelManager.close(); + } + } + + private void updateFilter(String filter) + { + filter = filter.toLowerCase(); + final Widget list = client.getWidget(WidgetInfo.FAIRY_RING_LIST); + final Widget favorites = client.getWidget(WidgetInfo.FAIRY_RING_FAVORITES); + + if (list == null) + { + return; + } + + if (codes != null) + { + // Check to make sure the list hasn't been rebuild since we were last her + // Do this by making sure the list's dynamic children are the same as when we last saw them + if (codes.stream().noneMatch(w -> + { + Widget codeWidget = w.getCode(); + if (codeWidget == null) + { + return false; + } + return list.getChild(codeWidget.getIndex()) == codeWidget; + })) + { + codes = null; + } + } + + if (codes == null) + { + // Find all of the widgets that we care about, grouping by their Y value + Map codeMap = new TreeMap<>(); + + for (Widget w : list.getStaticChildren()) + { + if (w.isSelfHidden()) + { + continue; + } + + if (w.getSpriteId() != -1) + { + codeMap.computeIfAbsent(w.getRelativeY(), k -> new CodeWidgets()).setFavorite(w); + } + else if (!Strings.isNullOrEmpty(w.getText())) + { + codeMap.computeIfAbsent(w.getRelativeY(), k -> new CodeWidgets()).setDescription(w); + } + } + + for (Widget w : list.getDynamicChildren()) + { + if (w.isSelfHidden()) + { + continue; + } + + CodeWidgets c = codeMap.computeIfAbsent(w.getRelativeY(), k -> new CodeWidgets()); + c.setCode(w); + } + + codes = codeMap.values(); + } + + // Relayout the panel + int y = 0; + + if (favorites != null) + { + boolean hide = !filter.isEmpty(); + favorites.setHidden(hide); + if (!hide) + { + y += favorites.getOriginalHeight() + ENTRY_PADDING; + } + } + + for (CodeWidgets c : codes) + { + String code = Text.removeTags(c.getDescription().getName()).replaceAll(" ", ""); + String tags = null; + + if (!code.isEmpty()) + { + try + { + FairyRings ring = FairyRings.valueOf(code); + tags = ring.getTags(); + } + catch (IllegalArgumentException e) + { + log.warn("Unable to find ring with code '{}'", code, e); + } + } + + boolean hidden = !(filter.isEmpty() + || Text.removeTags(c.getDescription().getText()).toLowerCase().contains(filter) + || code.toLowerCase().contains(filter) + || tags != null && tags.contains(filter)); + + if (c.getCode() != null) + { + c.getCode().setHidden(hidden); + c.getCode().setOriginalY(y); + } + + if (c.getFavorite() != null) + { + c.getFavorite().setHidden(hidden); + c.getFavorite().setOriginalY(y); + } + + c.getDescription().setHidden(hidden); + c.getDescription().setOriginalY(y); + + if (!hidden) + { + y += c.getDescription().getHeight() + ENTRY_PADDING; + } + } + + y -= ENTRY_PADDING; + + if (y < 0) + { + y = 0; + } + + int newHeight = 0; + if (list.getScrollHeight() > 0) + { + newHeight = (list.getScrollY() * y) / list.getScrollHeight(); + } + + list.setScrollHeight(y); + list.revalidateScroll(); + client.runScript( + ScriptID.UPDATE_SCROLLBAR, + WidgetInfo.FAIRY_RING_LIST_SCROLLBAR.getId(), + WidgetInfo.FAIRY_RING_LIST.getId(), + newHeight + ); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadAttack.java b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadAttack.java index 99f8cd2bb3..3da9f544a3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadAttack.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadAttack.java @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2017, Devin French - * 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.fightcave; - -import net.runelite.api.AnimationID; -import net.runelite.api.Prayer; - -public enum JadAttack -{ - MAGIC(AnimationID.TZTOK_JAD_MAGIC_ATTACK, Prayer.PROTECT_FROM_MAGIC), - RANGE(AnimationID.TZTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES); - - private final int animation; - private final Prayer prayer; - - JadAttack(int animation, Prayer prayer) - { - this.animation = animation; - this.prayer = prayer; - } - - public int getAnimation() - { - return animation; - } - - public Prayer getPrayer() - { - return prayer; - } +/* + * Copyright (c) 2017, Devin French + * 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.fightcave; + +import net.runelite.api.AnimationID; +import net.runelite.api.Prayer; + +public enum JadAttack +{ + MAGIC(AnimationID.TZTOK_JAD_MAGIC_ATTACK, Prayer.PROTECT_FROM_MAGIC), + RANGE(AnimationID.TZTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES); + + private final int animation; + private final Prayer prayer; + + JadAttack(int animation, Prayer prayer) + { + this.animation = animation; + this.prayer = prayer; + } + + public int getAnimation() + { + return animation; + } + + public Prayer getPrayer() + { + return prayer; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadOverlay.java index 0f31a153a4..b5998e2bfa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/JadOverlay.java @@ -1,87 +1,87 @@ -/* - * Copyright (c) 2017, Devin French - * 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.fightcave; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.SpriteID; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.ComponentConstants; -import net.runelite.client.ui.overlay.components.ImageComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; - -public class JadOverlay extends Overlay -{ - private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150); - - private final Client client; - private final FightCavePlugin plugin; - private final SpriteManager spriteManager; - private final PanelComponent imagePanelComponent = new PanelComponent(); - - @Inject - private JadOverlay(Client client, FightCavePlugin plugin, SpriteManager spriteManager) - { - setPosition(OverlayPosition.BOTTOM_RIGHT); - setPriority(OverlayPriority.HIGH); - this.client = client; - this.plugin = plugin; - this.spriteManager = spriteManager; - } - - @Override - public Dimension render(Graphics2D graphics) - { - final JadAttack attack = plugin.getAttack(); - - if (attack == null) - { - return null; - } - - final BufferedImage prayerImage = getPrayerImage(attack); - - imagePanelComponent.getChildren().clear(); - imagePanelComponent.getChildren().add(new ImageComponent(prayerImage)); - imagePanelComponent.setBackgroundColor(client.isPrayerActive(attack.getPrayer()) - ? ComponentConstants.STANDARD_BACKGROUND_COLOR - : NOT_ACTIVATED_BACKGROUND_COLOR); - - return imagePanelComponent.render(graphics); - } - - private BufferedImage getPrayerImage(JadAttack attack) - { - final int prayerSpriteID = attack == JadAttack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES; - return spriteManager.getSprite(prayerSpriteID, 0); - } +/* + * Copyright (c) 2017, Devin French + * 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.fightcave; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.SpriteID; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.ComponentConstants; +import net.runelite.client.ui.overlay.components.ImageComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +public class JadOverlay extends Overlay +{ + private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150); + + private final Client client; + private final FightCavePlugin plugin; + private final SpriteManager spriteManager; + private final PanelComponent imagePanelComponent = new PanelComponent(); + + @Inject + private JadOverlay(Client client, FightCavePlugin plugin, SpriteManager spriteManager) + { + setPosition(OverlayPosition.BOTTOM_RIGHT); + setPriority(OverlayPriority.HIGH); + this.client = client; + this.plugin = plugin; + this.spriteManager = spriteManager; + } + + @Override + public Dimension render(Graphics2D graphics) + { + final JadAttack attack = plugin.getAttack(); + + if (attack == null) + { + return null; + } + + final BufferedImage prayerImage = getPrayerImage(attack); + + imagePanelComponent.getChildren().clear(); + imagePanelComponent.getChildren().add(new ImageComponent(prayerImage)); + imagePanelComponent.setBackgroundColor(client.isPrayerActive(attack.getPrayer()) + ? ComponentConstants.STANDARD_BACKGROUND_COLOR + : NOT_ACTIVATED_BACKGROUND_COLOR); + + return imagePanelComponent.render(graphics); + } + + private BufferedImage getPrayerImage(JadAttack attack) + { + final int prayerSpriteID = attack == JadAttack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES; + return spriteManager.getSprite(prayerSpriteID, 0); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/WaveOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/WaveOverlay.java index e9c5678bcf..8561919254 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/WaveOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/WaveOverlay.java @@ -1,124 +1,125 @@ -/* - * Copyright (c) 2018, Jordan Atwood - * 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.fightcave; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import javax.inject.Inject; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -class WaveOverlay extends Overlay -{ - private static final Color HEADER_COLOR = ColorScheme.BRAND_ORANGE; - - private final FightCaveConfig config; - private final FightCavePlugin plugin; - - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - private WaveOverlay(FightCaveConfig config, FightCavePlugin plugin) - { - setPosition(OverlayPosition.TOP_RIGHT); - this.config = config; - this.plugin = plugin; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.inFightCave() - || plugin.getCurrentWave() < 0) - { - return null; - } - - panelComponent.getChildren().clear(); - - final int currentWave = plugin.getCurrentWave(); - final int waveIndex = currentWave - 1; - - if (config.waveDisplay() == WaveDisplayMode.CURRENT - || config.waveDisplay() == WaveDisplayMode.BOTH) - { - final Map waveContents = FightCavePlugin.getWAVES().get(waveIndex); - - addWaveInfo("Wave " + plugin.getCurrentWave(), waveContents); - } - - if ((config.waveDisplay() == WaveDisplayMode.NEXT - || config.waveDisplay() == WaveDisplayMode.BOTH) - && currentWave != FightCavePlugin.MAX_WAVE) - { - final Map waveContents = FightCavePlugin.getWAVES().get(waveIndex + 1); - - addWaveInfo("Next wave", waveContents); - } - - return panelComponent.render(graphics); - } - private void addWaveInfo(final String headerText, final Map waveContents) - { - panelComponent.getChildren().add(TitleComponent.builder() - .text(headerText) - .color(HEADER_COLOR) - .build()); - - for (LineComponent line : buildWaveLines(waveContents)) - { - panelComponent.getChildren().add(line); - } - } - - private static Collection buildWaveLines(final Map wave) - { - final List> monsters = new ArrayList<>(wave.entrySet()); - monsters.sort(Map.Entry.comparingByKey()); - final List outputLines = new ArrayList<>(); - - for (Map.Entry monsterEntry : monsters) - { - final WaveMonster monster = monsterEntry.getKey(); - final int quantity = monsterEntry.getValue(); - final LineComponent line = LineComponent.builder() - .left(FightCavePlugin.formatMonsterQuantity(monster, quantity)) - .build(); - - outputLines.add(line); - } - - return outputLines; - } -} +/* + * Copyright (c) 2018, Jordan Atwood + * 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.fightcave; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.inject.Inject; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +class WaveOverlay extends Overlay +{ + private static final Color HEADER_COLOR = ColorScheme.BRAND_ORANGE; + + private final FightCaveConfig config; + private final FightCavePlugin plugin; + + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + private WaveOverlay(FightCaveConfig config, FightCavePlugin plugin) + { + setPosition(OverlayPosition.TOP_RIGHT); + this.config = config; + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.inFightCave() + || plugin.getCurrentWave() < 0) + { + return null; + } + + panelComponent.getChildren().clear(); + + final int currentWave = plugin.getCurrentWave(); + final int waveIndex = currentWave - 1; + + if (config.waveDisplay() == WaveDisplayMode.CURRENT + || config.waveDisplay() == WaveDisplayMode.BOTH) + { + final Map waveContents = FightCavePlugin.getWAVES().get(waveIndex); + + addWaveInfo("Wave " + plugin.getCurrentWave(), waveContents); + } + + if ((config.waveDisplay() == WaveDisplayMode.NEXT + || config.waveDisplay() == WaveDisplayMode.BOTH) + && currentWave != FightCavePlugin.MAX_WAVE) + { + final Map waveContents = FightCavePlugin.getWAVES().get(waveIndex + 1); + + addWaveInfo("Next wave", waveContents); + } + + return panelComponent.render(graphics); + } + + private void addWaveInfo(final String headerText, final Map waveContents) + { + panelComponent.getChildren().add(TitleComponent.builder() + .text(headerText) + .color(HEADER_COLOR) + .build()); + + for (LineComponent line : buildWaveLines(waveContents)) + { + panelComponent.getChildren().add(line); + } + } + + private static Collection buildWaveLines(final Map wave) + { + final List> monsters = new ArrayList<>(wave.entrySet()); + monsters.sort(Map.Entry.comparingByKey()); + final List outputLines = new ArrayList<>(); + + for (Map.Entry monsterEntry : monsters) + { + final WaveMonster monster = monsterEntry.getKey(); + final int quantity = monsterEntry.getValue(); + final LineComponent line = LineComponent.builder() + .left(FightCavePlugin.formatMonsterQuantity(monster, quantity)) + .build(); + + outputLines.add(line); + } + + return outputLines; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java index 80cdaec1e4..31b2160b3f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingSpotOverlay.java @@ -1,182 +1,182 @@ -/* - * Copyright (c) 2017, Seth - * 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.fishing; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.image.BufferedImage; -import java.time.Duration; -import java.time.Instant; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Setter; -import net.runelite.api.Client; -import net.runelite.api.GraphicID; -import net.runelite.api.NPC; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.ProgressPieComponent; -import net.runelite.client.util.ImageUtil; - -class FishingSpotOverlay extends Overlay -{ - private static final Duration MINNOW_MOVE = Duration.ofSeconds(15); - private static final Duration MINNOW_WARN = Duration.ofSeconds(3); - private static final int ONE_TICK_AERIAL_FISHING = 3; - - private final FishingPlugin plugin; - private final FishingConfig config; - private final Client client; - private final ItemManager itemManager; - - @Setter(AccessLevel.PACKAGE) - private boolean hidden; - - @Inject - private FishingSpotOverlay(FishingPlugin plugin, FishingConfig config, Client client, ItemManager itemManager) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.plugin = plugin; - this.config = config; - this.client = client; - this.itemManager = itemManager; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (hidden) - { - return null; - } - - for (NPC npc : plugin.getFishingSpots()) - { - FishingSpot spot = FishingSpot.getSPOTS().get(npc.getId()); - - if (spot == null) - { - continue; - } - - if (config.onlyCurrentSpot() && plugin.getCurrentSpot() != null && plugin.getCurrentSpot() != spot) - { - continue; - } - - Color color = npc.getGraphic() == GraphicID.FLYING_FISH ? Color.RED : Color.CYAN; - - if (spot == FishingSpot.MINNOW && config.showMinnowOverlay()) - { - MinnowSpot minnowSpot = plugin.getMinnowSpots().get(npc.getIndex()); - if (minnowSpot != null) - { - long millisLeft = MINNOW_MOVE.toMillis() - Duration.between(minnowSpot.getTime(), Instant.now()).toMillis(); - if (millisLeft < MINNOW_WARN.toMillis()) - { - color = Color.ORANGE; - } - - LocalPoint localPoint = npc.getLocalLocation(); - Point location = Perspective.localToCanvas(client, localPoint, client.getPlane()); - - if (location != null) - { - ProgressPieComponent pie = new ProgressPieComponent(); - pie.setFill(color); - pie.setBorderColor(color); - pie.setPosition(location); - pie.setProgress((float) millisLeft / MINNOW_MOVE.toMillis()); - pie.render(graphics); - } - } - } - - if (config.showSpotTiles()) - { - Polygon poly = npc.getCanvasTilePoly(); - - if (spot == FishingSpot.COMMON_TENCH - && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) - { - color = Color.GREEN; - } - - if (poly != null) - { - OverlayUtil.renderPolygon(graphics, poly, color.darker()); - } - } - - if (config.showSpotIcons()) - { - BufferedImage fishImage = itemManager.getImage(spot.getFishSpriteId());; - - if (spot == FishingSpot.COMMON_TENCH - && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) - { - fishImage = ImageUtil.outlineImage(itemManager.getImage(spot.getFishSpriteId()), Color.GREEN); - } - - if (fishImage != null) - { - Point imageLocation = npc.getCanvasImageLocation(fishImage, npc.getLogicalHeight()); - if (imageLocation != null) - { - OverlayUtil.renderImageLocation(graphics, imageLocation, fishImage); - } - } - } - - if (config.showSpotNames()) - { - String text = spot.getName(); - Point textLocation = npc.getCanvasTextLocation(graphics, text, npc.getLogicalHeight() + 40); - - if (spot == FishingSpot.COMMON_TENCH - && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) - { - color = Color.GREEN; - } - - if (textLocation != null) - { - OverlayUtil.renderTextLocation(graphics, textLocation, text, color.darker()); - } - } - } - - return null; - } -} +/* + * Copyright (c) 2017, Seth + * 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.fishing; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.image.BufferedImage; +import java.time.Duration; +import java.time.Instant; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Setter; +import net.runelite.api.Client; +import net.runelite.api.GraphicID; +import net.runelite.api.NPC; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.ProgressPieComponent; +import net.runelite.client.util.ImageUtil; + +class FishingSpotOverlay extends Overlay +{ + private static final Duration MINNOW_MOVE = Duration.ofSeconds(15); + private static final Duration MINNOW_WARN = Duration.ofSeconds(3); + private static final int ONE_TICK_AERIAL_FISHING = 3; + + private final FishingPlugin plugin; + private final FishingConfig config; + private final Client client; + private final ItemManager itemManager; + + @Setter(AccessLevel.PACKAGE) + private boolean hidden; + + @Inject + private FishingSpotOverlay(FishingPlugin plugin, FishingConfig config, Client client, ItemManager itemManager) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.plugin = plugin; + this.config = config; + this.client = client; + this.itemManager = itemManager; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (hidden) + { + return null; + } + + for (NPC npc : plugin.getFishingSpots()) + { + FishingSpot spot = FishingSpot.getSPOTS().get(npc.getId()); + + if (spot == null) + { + continue; + } + + if (config.onlyCurrentSpot() && plugin.getCurrentSpot() != null && plugin.getCurrentSpot() != spot) + { + continue; + } + + Color color = npc.getGraphic() == GraphicID.FLYING_FISH ? Color.RED : Color.CYAN; + + if (spot == FishingSpot.MINNOW && config.showMinnowOverlay()) + { + MinnowSpot minnowSpot = plugin.getMinnowSpots().get(npc.getIndex()); + if (minnowSpot != null) + { + long millisLeft = MINNOW_MOVE.toMillis() - Duration.between(minnowSpot.getTime(), Instant.now()).toMillis(); + if (millisLeft < MINNOW_WARN.toMillis()) + { + color = Color.ORANGE; + } + + LocalPoint localPoint = npc.getLocalLocation(); + Point location = Perspective.localToCanvas(client, localPoint, client.getPlane()); + + if (location != null) + { + ProgressPieComponent pie = new ProgressPieComponent(); + pie.setFill(color); + pie.setBorderColor(color); + pie.setPosition(location); + pie.setProgress((float) millisLeft / MINNOW_MOVE.toMillis()); + pie.render(graphics); + } + } + } + + if (config.showSpotTiles()) + { + Polygon poly = npc.getCanvasTilePoly(); + + if (spot == FishingSpot.COMMON_TENCH + && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) + { + color = Color.GREEN; + } + + if (poly != null) + { + OverlayUtil.renderPolygon(graphics, poly, color.darker()); + } + } + + if (config.showSpotIcons()) + { + BufferedImage fishImage = itemManager.getImage(spot.getFishSpriteId()); + + if (spot == FishingSpot.COMMON_TENCH + && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) + { + fishImage = ImageUtil.outlineImage(itemManager.getImage(spot.getFishSpriteId()), Color.GREEN); + } + + if (fishImage != null) + { + Point imageLocation = npc.getCanvasImageLocation(fishImage, npc.getLogicalHeight()); + if (imageLocation != null) + { + OverlayUtil.renderImageLocation(graphics, imageLocation, fishImage); + } + } + } + + if (config.showSpotNames()) + { + String text = spot.getName(); + Point textLocation = npc.getCanvasTextLocation(graphics, text, npc.getLogicalHeight() + 40); + + if (spot == FishingSpot.COMMON_TENCH + && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING) + { + color = Color.GREEN; + } + + if (textLocation != null) + { + OverlayUtil.renderTextLocation(graphics, textLocation, text, color.darker()); + } + } + } + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/flexo/FlexoOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/flexo/FlexoOverlay.java index daf2d69c67..4c145ae303 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/flexo/FlexoOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/flexo/FlexoOverlay.java @@ -34,9 +34,7 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.Line2D; import java.util.ArrayList; -import javax.annotation.Nullable; import javax.inject.Inject; -import net.runelite.api.Client; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java index 3be17f5577..2ee44ed9ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java @@ -36,7 +36,7 @@ import net.runelite.api.events.FocusChanged; * For low powered computers, the RS client is often throttled by the hardware or OS and draws at 25-30 fps. * The nano timer is not used in this scenario. * Instead to catch up the RS client runs several cycles before drawing, thus maintaining 50 cycles / second. - * + *

* Enforcing FPS in the draw code does not impact the client engine's ability to run including its audio, * even when forced to 1 FPS with this plugin. */ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java index 41df487ee8..3f83335d19 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PlayerSpellEffect.java @@ -57,10 +57,12 @@ public enum PlayerSpellEffect public static PlayerSpellEffect getFromSpotAnim(int spotAnim) { - for(PlayerSpellEffect effect : values()) + for (PlayerSpellEffect effect : values()) { - if(effect.getSpotAnimId() == spotAnim) + if (effect.getSpotAnimId() == spotAnim) + { return effect; + } } return NONE; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java index 1352b351bb..896363e681 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java @@ -11,8 +11,7 @@ package net.runelite.client.plugins.friendtagging; import com.google.common.base.Strings; import com.google.common.collect.ObjectArrays; - -import java.awt.*; +import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.util.Arrays; import java.util.HashSet; @@ -21,8 +20,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import net.runelite.api.*; -import net.runelite.api.events.*; +import net.runelite.api.Client; +import net.runelite.api.Friend; +import net.runelite.api.Ignore; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.Nameable; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.NameableNameChanged; +import net.runelite.api.events.RemovedFriend; +import net.runelite.api.events.WidgetMenuOptionClicked; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; @@ -40,8 +48,8 @@ import org.apache.commons.lang3.ArrayUtils; @PluginDescriptor( name = "Friend Tagging", description = "Tag people on your friends list.", - tags = {"PVP", "friend", "finder", "pk", "pklite"}, - type = PluginType.UTILITY + tags = {"PVP", "friend", "finder", "pk", "pklite"}, + type = PluginType.UTILITY ) public class FriendTaggingPlugin extends Plugin { @@ -267,8 +275,8 @@ public class FriendTaggingPlugin extends Plugin } /** - * This method combines the list of usernames on local players friend/ignore list into a comma delimited string - * and then copies it to the clipboard. + * This method combines the list of usernames on local players friend/ignore list into a comma delimited string + * and then copies it to the clipboard. */ private void friendIgnoreToClipboard() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index 80d37e7566..449f1b5441 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -74,7 +74,18 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginInstantiationException; import net.runelite.client.plugins.PluginManager; -import static net.runelite.client.plugins.gpu.GLUtil.*; +import static net.runelite.client.plugins.gpu.GLUtil.glDeleteBuffer; +import static net.runelite.client.plugins.gpu.GLUtil.glDeleteFrameBuffer; +import static net.runelite.client.plugins.gpu.GLUtil.glDeleteRenderbuffers; +import static net.runelite.client.plugins.gpu.GLUtil.glDeleteTexture; +import static net.runelite.client.plugins.gpu.GLUtil.glDeleteVertexArrays; +import static net.runelite.client.plugins.gpu.GLUtil.glGenBuffers; +import static net.runelite.client.plugins.gpu.GLUtil.glGenFrameBuffer; +import static net.runelite.client.plugins.gpu.GLUtil.glGenRenderbuffer; +import static net.runelite.client.plugins.gpu.GLUtil.glGenTexture; +import static net.runelite.client.plugins.gpu.GLUtil.glGenVertexArrays; +import static net.runelite.client.plugins.gpu.GLUtil.glGetInteger; +import static net.runelite.client.plugins.gpu.GLUtil.inputStreamToString; import net.runelite.client.plugins.gpu.config.AntiAliasingMode; import net.runelite.client.plugins.gpu.template.Template; import net.runelite.client.ui.DrawManager; @@ -414,8 +425,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks { glVersionHeader = "#version 420\n" + - "#extension GL_ARB_compute_shader : require\n" + - "#extension GL_ARB_shader_storage_buffer_object : require\n"; + "#extension GL_ARB_compute_shader : require\n" + + "#extension GL_ARB_shader_storage_buffer_object : require\n"; } else { @@ -707,8 +718,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } public void drawScenePaint(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, - SceneTilePaint paint, int tileZ, int tileX, int tileY, - int zoom, int centerX, int centerY) + SceneTilePaint paint, int tileZ, int tileX, int tileY, + int zoom, int centerX, int centerY) { if (paint.getBufferLen() > 0) { @@ -733,8 +744,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } public void drawSceneModel(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, - SceneTileModel model, int tileZ, int tileX, int tileY, - int zoom, int centerX, int centerY) + SceneTileModel model, int tileZ, int tileX, int tileY, + int zoom, int centerX, int centerY) { if (model.getBufferLen() > 0) { @@ -980,18 +991,18 @@ public class GpuPlugin extends Plugin implements DrawCallbacks renderCanvasHeight = dim.height; double scaleFactorY = dim.getHeight() / canvasHeight; - double scaleFactorX = dim.getWidth() / canvasWidth; + double scaleFactorX = dim.getWidth() / canvasWidth; // Pad the viewport a little because having ints for our viewport dimensions can introduce off-by-one errors. final int padding = 1; // Ceil the sizes because even if the size is 599.1 we want to treat it as size 600 (i.e. render to the x=599 pixel). renderViewportHeight = (int) Math.ceil(scaleFactorY * (renderViewportHeight)) + padding * 2; - renderViewportWidth = (int) Math.ceil(scaleFactorX * (renderViewportWidth )) + padding * 2; + renderViewportWidth = (int) Math.ceil(scaleFactorX * (renderViewportWidth)) + padding * 2; // Floor the offsets because even if the offset is 4.9, we want to render to the x=4 pixel anyway. - renderHeightOff = (int) Math.floor(scaleFactorY * (renderHeightOff)) - padding; - renderWidthOff = (int) Math.floor(scaleFactorX * (renderWidthOff )) - padding; + renderHeightOff = (int) Math.floor(scaleFactorY * (renderHeightOff)) - padding; + renderWidthOff = (int) Math.floor(scaleFactorX * (renderWidthOff)) - padding; } glDpiAwareViewport(renderWidthOff, renderCanvasHeight - renderViewportHeight - renderHeightOff, renderViewportWidth, renderViewportHeight); @@ -1169,13 +1180,13 @@ public class GpuPlugin extends Plugin implements DrawCallbacks */ private Image screenshot() { - int width = client.getCanvasWidth(); + int width = client.getCanvasWidth(); int height = client.getCanvasHeight(); if (client.isStretchedEnabled()) { Dimension dim = client.getStretchedDimensions(); - width = dim.width; + width = dim.width; height = dim.height; } @@ -1295,10 +1306,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks { int var21 = (pitchCos * modelHeight >> 16) + var19; int var22 = (var18 - var21) * zoom; - if (var22 / var14 < Rasterizer3D_clipMidY2) - { - return true; - } + return var22 / var14 < Rasterizer3D_clipMidY2; } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java index 94878c69dc..4d8c2b1801 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java @@ -1,87 +1,87 @@ -/* - * Copyright (c) 2018, Adam - * 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.gpu; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.Range; -import static net.runelite.client.plugins.gpu.GpuPlugin.MAX_FOG_DEPTH; -import net.runelite.client.plugins.gpu.config.AntiAliasingMode; -import static net.runelite.client.plugins.gpu.GpuPlugin.MAX_DISTANCE; - -@ConfigGroup("gpu") -public interface GpuPluginConfig extends Config -{ - @Range( - max = MAX_DISTANCE - ) - @ConfigItem( - keyName = "drawDistance", - name = "Draw Distance", - description = "Draw distance", - position = 1 - ) - default int drawDistance() - { - return 25; - } - - @ConfigItem( - keyName = "smoothBanding", - name = "Remove Color Banding", - description = "Smooths out the color banding that is present in the CPU renderer", - position = 2 - ) - default boolean smoothBanding() - { - return false; - } - - @ConfigItem( - keyName = "antiAliasingMode", - name = "Anti Aliasing", - description = "Configures the anti-aliasing mode", - position = 3 - ) - default AntiAliasingMode antiAliasingMode() - { - return AntiAliasingMode.DISABLED; - } - - @Range( - max = MAX_FOG_DEPTH - ) - @ConfigItem( - keyName = "fogDepth", - name = "Fog depth", - description = "Distance from the scene edge the fog starts", - position = 4 - ) - default int fogDepth() - { - return 0; - } -} +/* + * Copyright (c) 2018, Adam + * 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.gpu; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; +import static net.runelite.client.plugins.gpu.GpuPlugin.MAX_DISTANCE; +import static net.runelite.client.plugins.gpu.GpuPlugin.MAX_FOG_DEPTH; +import net.runelite.client.plugins.gpu.config.AntiAliasingMode; + +@ConfigGroup("gpu") +public interface GpuPluginConfig extends Config +{ + @Range( + max = MAX_DISTANCE + ) + @ConfigItem( + keyName = "drawDistance", + name = "Draw Distance", + description = "Draw distance", + position = 1 + ) + default int drawDistance() + { + return 25; + } + + @ConfigItem( + keyName = "smoothBanding", + name = "Remove Color Banding", + description = "Smooths out the color banding that is present in the CPU renderer", + position = 2 + ) + default boolean smoothBanding() + { + return false; + } + + @ConfigItem( + keyName = "antiAliasingMode", + name = "Anti Aliasing", + description = "Configures the anti-aliasing mode", + position = 3 + ) + default AntiAliasingMode antiAliasingMode() + { + return AntiAliasingMode.DISABLED; + } + + @Range( + max = MAX_FOG_DEPTH + ) + @ConfigItem( + keyName = "fogDepth", + name = "Fog depth", + description = "Distance from the scene edge the fog starts", + position = 4 + ) + default int fogDepth() + { + return 0; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeOfferSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeOfferSlot.java index 14090170fe..1b7c3d2f76 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeOfferSlot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeOfferSlot.java @@ -1,277 +1,277 @@ -/* - * Copyright (c) 2018, SomeoneWithAnInternetConnection - * Copyright (c) 2018, Psikoi - * 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.grandexchange; - -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.image.BufferedImage; -import javax.annotation.Nullable; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.border.EmptyBorder; -import net.runelite.api.GrandExchangeOffer; -import net.runelite.api.GrandExchangeOfferState; -import static net.runelite.api.GrandExchangeOfferState.CANCELLED_BUY; -import static net.runelite.api.GrandExchangeOfferState.CANCELLED_SELL; -import static net.runelite.api.GrandExchangeOfferState.EMPTY; -import net.runelite.api.ItemComposition; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.components.ThinProgressBar; -import net.runelite.client.util.ColorUtil; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.StackFormatter; - -public class GrandExchangeOfferSlot extends JPanel -{ - private static final String FACE_CARD = "FACE_CARD"; - private static final String DETAILS_CARD = "DETAILS_CARD"; - - private static final ImageIcon RIGHT_ARROW_ICON; - private static final ImageIcon LEFT_ARROW_ICON; - - private final JPanel container = new JPanel(); - private final CardLayout cardLayout = new CardLayout(); - - private final JLabel itemIcon = new JLabel(); - private final JLabel itemName = new JLabel(); - private final JLabel offerInfo = new JLabel(); - - private final JLabel itemPrice = new JLabel(); - private final JLabel offerSpent = new JLabel(); - - private final ThinProgressBar progressBar = new ThinProgressBar(); - - private boolean showingFace = true; - - static - { - final BufferedImage rightArrow = ImageUtil.alphaOffset(ImageUtil.getResourceStreamFromClass(GrandExchangeOfferSlot.class, "/util/arrow_right.png"), 0.25f); - RIGHT_ARROW_ICON = new ImageIcon(rightArrow); - LEFT_ARROW_ICON = new ImageIcon(ImageUtil.flipImage(rightArrow, true, false)); - } - - /** - * This (sub)panel is used for each GE slot displayed - * in the sidebar - */ - GrandExchangeOfferSlot() - { - setLayout(new BorderLayout()); - setBackground(ColorScheme.DARK_GRAY_COLOR); - setBorder(new EmptyBorder(7, 0, 0, 0)); - - final MouseListener ml = new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - super.mousePressed(mouseEvent); - switchPanel(); - } - - @Override - public void mouseEntered(MouseEvent mouseEvent) - { - super.mouseEntered(mouseEvent); - container.setBackground(ColorScheme.DARKER_GRAY_HOVER_COLOR); - } - - @Override - public void mouseExited(MouseEvent mouseEvent) - { - super.mouseExited(mouseEvent); - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - } - }; - - container.setLayout(cardLayout); - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - JPanel faceCard = new JPanel(); - faceCard.setBackground(ColorScheme.DARKER_GRAY_COLOR); - faceCard.setLayout(new BorderLayout()); - faceCard.addMouseListener(ml); - - itemIcon.setVerticalAlignment(JLabel.CENTER); - itemIcon.setHorizontalAlignment(JLabel.CENTER); - itemIcon.setPreferredSize(new Dimension(45, 45)); - - itemName.setForeground(Color.WHITE); - itemName.setVerticalAlignment(JLabel.BOTTOM); - itemName.setFont(FontManager.getRunescapeSmallFont()); - - offerInfo.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - offerInfo.setVerticalAlignment(JLabel.TOP); - offerInfo.setFont(FontManager.getRunescapeSmallFont()); - - JLabel switchFaceViewIcon = new JLabel(); - switchFaceViewIcon.setIcon(RIGHT_ARROW_ICON); - switchFaceViewIcon.setVerticalAlignment(JLabel.CENTER); - switchFaceViewIcon.setHorizontalAlignment(JLabel.CENTER); - switchFaceViewIcon.setPreferredSize(new Dimension(30, 45)); - - JPanel offerFaceDetails = new JPanel(); - offerFaceDetails.setBackground(ColorScheme.DARKER_GRAY_COLOR); - offerFaceDetails.setLayout(new GridLayout(2, 1, 0, 2)); - - offerFaceDetails.add(itemName); - offerFaceDetails.add(offerInfo); - - faceCard.add(offerFaceDetails, BorderLayout.CENTER); - faceCard.add(itemIcon, BorderLayout.WEST); - faceCard.add(switchFaceViewIcon, BorderLayout.EAST); - - JPanel detailsCard = new JPanel(); - detailsCard.setBackground(ColorScheme.DARKER_GRAY_COLOR); - detailsCard.setLayout(new BorderLayout()); - detailsCard.setBorder(new EmptyBorder(0, 15, 0, 0)); - detailsCard.addMouseListener(ml); - - itemPrice.setForeground(Color.WHITE); - itemPrice.setVerticalAlignment(JLabel.BOTTOM); - itemPrice.setFont(FontManager.getRunescapeSmallFont()); - - offerSpent.setForeground(Color.WHITE); - offerSpent.setVerticalAlignment(JLabel.TOP); - offerSpent.setFont(FontManager.getRunescapeSmallFont()); - - JLabel switchDetailsViewIcon = new JLabel(); - switchDetailsViewIcon.setIcon(LEFT_ARROW_ICON); - switchDetailsViewIcon.setVerticalAlignment(JLabel.CENTER); - switchDetailsViewIcon.setHorizontalAlignment(JLabel.CENTER); - switchDetailsViewIcon.setPreferredSize(new Dimension(30, 45)); - - JPanel offerDetails = new JPanel(); - offerDetails.setBackground(ColorScheme.DARKER_GRAY_COLOR); - offerDetails.setLayout(new GridLayout(2, 1)); - - offerDetails.add(itemPrice); - offerDetails.add(offerSpent); - - detailsCard.add(offerDetails, BorderLayout.CENTER); - detailsCard.add(switchDetailsViewIcon, BorderLayout.EAST); - - container.add(faceCard, FACE_CARD); - container.add(detailsCard, DETAILS_CARD); - - cardLayout.show(container, FACE_CARD); - - add(container, BorderLayout.CENTER); - add(progressBar, BorderLayout.SOUTH); - } - - void updateOffer(ItemComposition offerItem, BufferedImage itemImage, @Nullable GrandExchangeOffer newOffer) - { - if (newOffer == null || newOffer.getState() == EMPTY) - { - return; - } - else - { - cardLayout.show(container, FACE_CARD); - - itemName.setText(offerItem.getName()); - itemIcon.setIcon(new ImageIcon(itemImage)); - - boolean buying = newOffer.getState() == GrandExchangeOfferState.BOUGHT - || newOffer.getState() == GrandExchangeOfferState.BUYING - || newOffer.getState() == GrandExchangeOfferState.CANCELLED_BUY; - - String offerState = (buying ? "Bought " : "Sold ") - + StackFormatter.quantityToRSDecimalStack(newOffer.getQuantitySold()) + " / " - + StackFormatter.quantityToRSDecimalStack(newOffer.getTotalQuantity()); - - offerInfo.setText(offerState); - - itemPrice.setText(htmlLabel("Price each: ", StackFormatter.formatNumber(newOffer.getPrice()))); - - String action = buying ? "Spent: " : "Received: "; - - offerSpent.setText(htmlLabel(action, StackFormatter.formatNumber(newOffer.getSpent()) + " / " - + StackFormatter.formatNumber(newOffer.getPrice() * newOffer.getTotalQuantity()))); - - progressBar.setForeground(getProgressColor(newOffer)); - progressBar.setMaximumValue(newOffer.getTotalQuantity()); - progressBar.setValue(newOffer.getQuantitySold()); - - /* Couldn't set the tooltip for the container panel as the children override it, so I'm setting - * the tooltips on the children instead. */ - for (Component c : container.getComponents()) - { - if (c instanceof JPanel) - { - JPanel panel = (JPanel) c; - panel.setToolTipText(htmlTooltip(((int) progressBar.getPercentage()) + "%")); - } - } - } - - revalidate(); - repaint(); - } - - private String htmlTooltip(String value) - { - return "Progress: " + value + ""; - } - - private String htmlLabel(String key, String value) - { - return "" + key + "" + value + ""; - } - - private void switchPanel() - { - this.showingFace = !this.showingFace; - cardLayout.show(container, showingFace ? FACE_CARD : DETAILS_CARD); - } - - private Color getProgressColor(GrandExchangeOffer offer) - { - if (offer.getState() == CANCELLED_BUY || offer.getState() == CANCELLED_SELL) - { - return ColorScheme.PROGRESS_ERROR_COLOR; - } - - if (offer.getQuantitySold() == offer.getTotalQuantity()) - { - return ColorScheme.PROGRESS_COMPLETE_COLOR; - } - - return ColorScheme.PROGRESS_INPROGRESS_COLOR; - } -} - +/* + * Copyright (c) 2018, SomeoneWithAnInternetConnection + * Copyright (c) 2018, Psikoi + * 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.grandexchange; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.image.BufferedImage; +import javax.annotation.Nullable; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import net.runelite.api.GrandExchangeOffer; +import net.runelite.api.GrandExchangeOfferState; +import static net.runelite.api.GrandExchangeOfferState.CANCELLED_BUY; +import static net.runelite.api.GrandExchangeOfferState.CANCELLED_SELL; +import static net.runelite.api.GrandExchangeOfferState.EMPTY; +import net.runelite.api.ItemComposition; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.components.ThinProgressBar; +import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.StackFormatter; + +public class GrandExchangeOfferSlot extends JPanel +{ + private static final String FACE_CARD = "FACE_CARD"; + private static final String DETAILS_CARD = "DETAILS_CARD"; + + private static final ImageIcon RIGHT_ARROW_ICON; + private static final ImageIcon LEFT_ARROW_ICON; + + private final JPanel container = new JPanel(); + private final CardLayout cardLayout = new CardLayout(); + + private final JLabel itemIcon = new JLabel(); + private final JLabel itemName = new JLabel(); + private final JLabel offerInfo = new JLabel(); + + private final JLabel itemPrice = new JLabel(); + private final JLabel offerSpent = new JLabel(); + + private final ThinProgressBar progressBar = new ThinProgressBar(); + + private boolean showingFace = true; + + static + { + final BufferedImage rightArrow = ImageUtil.alphaOffset(ImageUtil.getResourceStreamFromClass(GrandExchangeOfferSlot.class, "/util/arrow_right.png"), 0.25f); + RIGHT_ARROW_ICON = new ImageIcon(rightArrow); + LEFT_ARROW_ICON = new ImageIcon(ImageUtil.flipImage(rightArrow, true, false)); + } + + /** + * This (sub)panel is used for each GE slot displayed + * in the sidebar + */ + GrandExchangeOfferSlot() + { + setLayout(new BorderLayout()); + setBackground(ColorScheme.DARK_GRAY_COLOR); + setBorder(new EmptyBorder(7, 0, 0, 0)); + + final MouseListener ml = new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + super.mousePressed(mouseEvent); + switchPanel(); + } + + @Override + public void mouseEntered(MouseEvent mouseEvent) + { + super.mouseEntered(mouseEvent); + container.setBackground(ColorScheme.DARKER_GRAY_HOVER_COLOR); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) + { + super.mouseExited(mouseEvent); + container.setBackground(ColorScheme.DARKER_GRAY_COLOR); + } + }; + + container.setLayout(cardLayout); + container.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + JPanel faceCard = new JPanel(); + faceCard.setBackground(ColorScheme.DARKER_GRAY_COLOR); + faceCard.setLayout(new BorderLayout()); + faceCard.addMouseListener(ml); + + itemIcon.setVerticalAlignment(JLabel.CENTER); + itemIcon.setHorizontalAlignment(JLabel.CENTER); + itemIcon.setPreferredSize(new Dimension(45, 45)); + + itemName.setForeground(Color.WHITE); + itemName.setVerticalAlignment(JLabel.BOTTOM); + itemName.setFont(FontManager.getRunescapeSmallFont()); + + offerInfo.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + offerInfo.setVerticalAlignment(JLabel.TOP); + offerInfo.setFont(FontManager.getRunescapeSmallFont()); + + JLabel switchFaceViewIcon = new JLabel(); + switchFaceViewIcon.setIcon(RIGHT_ARROW_ICON); + switchFaceViewIcon.setVerticalAlignment(JLabel.CENTER); + switchFaceViewIcon.setHorizontalAlignment(JLabel.CENTER); + switchFaceViewIcon.setPreferredSize(new Dimension(30, 45)); + + JPanel offerFaceDetails = new JPanel(); + offerFaceDetails.setBackground(ColorScheme.DARKER_GRAY_COLOR); + offerFaceDetails.setLayout(new GridLayout(2, 1, 0, 2)); + + offerFaceDetails.add(itemName); + offerFaceDetails.add(offerInfo); + + faceCard.add(offerFaceDetails, BorderLayout.CENTER); + faceCard.add(itemIcon, BorderLayout.WEST); + faceCard.add(switchFaceViewIcon, BorderLayout.EAST); + + JPanel detailsCard = new JPanel(); + detailsCard.setBackground(ColorScheme.DARKER_GRAY_COLOR); + detailsCard.setLayout(new BorderLayout()); + detailsCard.setBorder(new EmptyBorder(0, 15, 0, 0)); + detailsCard.addMouseListener(ml); + + itemPrice.setForeground(Color.WHITE); + itemPrice.setVerticalAlignment(JLabel.BOTTOM); + itemPrice.setFont(FontManager.getRunescapeSmallFont()); + + offerSpent.setForeground(Color.WHITE); + offerSpent.setVerticalAlignment(JLabel.TOP); + offerSpent.setFont(FontManager.getRunescapeSmallFont()); + + JLabel switchDetailsViewIcon = new JLabel(); + switchDetailsViewIcon.setIcon(LEFT_ARROW_ICON); + switchDetailsViewIcon.setVerticalAlignment(JLabel.CENTER); + switchDetailsViewIcon.setHorizontalAlignment(JLabel.CENTER); + switchDetailsViewIcon.setPreferredSize(new Dimension(30, 45)); + + JPanel offerDetails = new JPanel(); + offerDetails.setBackground(ColorScheme.DARKER_GRAY_COLOR); + offerDetails.setLayout(new GridLayout(2, 1)); + + offerDetails.add(itemPrice); + offerDetails.add(offerSpent); + + detailsCard.add(offerDetails, BorderLayout.CENTER); + detailsCard.add(switchDetailsViewIcon, BorderLayout.EAST); + + container.add(faceCard, FACE_CARD); + container.add(detailsCard, DETAILS_CARD); + + cardLayout.show(container, FACE_CARD); + + add(container, BorderLayout.CENTER); + add(progressBar, BorderLayout.SOUTH); + } + + void updateOffer(ItemComposition offerItem, BufferedImage itemImage, @Nullable GrandExchangeOffer newOffer) + { + if (newOffer == null || newOffer.getState() == EMPTY) + { + return; + } + else + { + cardLayout.show(container, FACE_CARD); + + itemName.setText(offerItem.getName()); + itemIcon.setIcon(new ImageIcon(itemImage)); + + boolean buying = newOffer.getState() == GrandExchangeOfferState.BOUGHT + || newOffer.getState() == GrandExchangeOfferState.BUYING + || newOffer.getState() == GrandExchangeOfferState.CANCELLED_BUY; + + String offerState = (buying ? "Bought " : "Sold ") + + StackFormatter.quantityToRSDecimalStack(newOffer.getQuantitySold()) + " / " + + StackFormatter.quantityToRSDecimalStack(newOffer.getTotalQuantity()); + + offerInfo.setText(offerState); + + itemPrice.setText(htmlLabel("Price each: ", StackFormatter.formatNumber(newOffer.getPrice()))); + + String action = buying ? "Spent: " : "Received: "; + + offerSpent.setText(htmlLabel(action, StackFormatter.formatNumber(newOffer.getSpent()) + " / " + + StackFormatter.formatNumber(newOffer.getPrice() * newOffer.getTotalQuantity()))); + + progressBar.setForeground(getProgressColor(newOffer)); + progressBar.setMaximumValue(newOffer.getTotalQuantity()); + progressBar.setValue(newOffer.getQuantitySold()); + + /* Couldn't set the tooltip for the container panel as the children override it, so I'm setting + * the tooltips on the children instead. */ + for (Component c : container.getComponents()) + { + if (c instanceof JPanel) + { + JPanel panel = (JPanel) c; + panel.setToolTipText(htmlTooltip(((int) progressBar.getPercentage()) + "%")); + } + } + } + + revalidate(); + repaint(); + } + + private String htmlTooltip(String value) + { + return "Progress: " + value + ""; + } + + private String htmlLabel(String key, String value) + { + return "" + key + "" + value + ""; + } + + private void switchPanel() + { + this.showingFace = !this.showingFace; + cardLayout.show(container, showingFace ? FACE_CARD : DETAILS_CARD); + } + + private Color getProgressColor(GrandExchangeOffer offer) + { + if (offer.getState() == CANCELLED_BUY || offer.getState() == CANCELLED_SELL) + { + return ColorScheme.PROGRESS_ERROR_COLOR; + } + + if (offer.getQuantitySold() == offer.getTotalQuantity()) + { + return ColorScheme.PROGRESS_COMPLETE_COLOR; + } + + return ColorScheme.PROGRESS_INPROGRESS_COLOR; + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index 01fde6181d..d6ed26161e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -1,497 +1,497 @@ -/* - * Copyright (c) 2019, Adam - * Copyright (c) 2017, Robbie - * Copyright (c) 2018, SomeoneWithAnInternetConnection - * 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.grandexchange; - -import com.google.common.reflect.TypeToken; -import com.google.gson.Gson; -import com.google.inject.Provides; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; -import javax.inject.Inject; -import javax.swing.SwingUtilities; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.GrandExchangeOffer; -import net.runelite.api.GrandExchangeOfferState; -import net.runelite.api.ItemComposition; -import net.runelite.api.MenuAction; -import net.runelite.api.MenuEntry; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.FocusChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.GrandExchangeOfferChanged; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; -import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetID; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.Notifier; -import net.runelite.client.account.AccountSession; -import net.runelite.client.account.SessionManager; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.ItemManager; -import net.runelite.client.input.KeyManager; -import net.runelite.client.input.MouseManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.StackFormatter; -import net.runelite.client.util.Text; -import net.runelite.http.api.ge.GrandExchangeClient; -import net.runelite.http.api.ge.GrandExchangeTrade; -import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; -import net.runelite.http.api.osbuddy.OSBGrandExchangeResult; - -@PluginDescriptor( - name = "Grand Exchange", - description = "Provide additional and/or easier access to Grand Exchange information", - tags = {"external", "integration", "notifications", "panel", "prices", "trade"} -) -@Slf4j -public class GrandExchangePlugin extends Plugin -{ - private static final int OFFER_CONTAINER_ITEM = 21; - private static final int OFFER_DEFAULT_ITEM_ID = 6512; - private static final OSBGrandExchangeClient CLIENT = new OSBGrandExchangeClient(); - private static final String OSB_GE_TEXT = "
OSBuddy Actively traded price: "; - - private static final String BUY_LIMIT_GE_TEXT = "
Buy limit: "; - private static final Gson GSON = new Gson(); - private static final TypeToken> BUY_LIMIT_TOKEN = new TypeToken>() - { - }; - - static final String SEARCH_GRAND_EXCHANGE = "Search Grand Exchange"; - - @Getter(AccessLevel.PACKAGE) - private NavigationButton button; - - @Getter(AccessLevel.PACKAGE) - private GrandExchangePanel panel; - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private boolean hotKeyPressed; - - @Inject - private GrandExchangeInputListener inputListener; - - @Inject - private ItemManager itemManager; - - @Inject - private MouseManager mouseManager; - - @Inject - private KeyManager keyManager; - - @Inject - private Client client; - - @Inject - private ClientToolbar clientToolbar; - - @Inject - private GrandExchangeConfig config; - - @Inject - private Notifier notifier; - - @Inject - private ScheduledExecutorService executorService; - - @Inject - private SessionManager sessionManager; - - @Inject - private ConfigManager configManager; - - private Widget grandExchangeText; - private Widget grandExchangeItem; - private Map itemGELimits; - - private GrandExchangeClient grandExchangeClient; - - private SavedOffer getOffer(int slot) - { - String offer = configManager.getConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot)); - if (offer == null) - { - return null; - } - return GSON.fromJson(offer, SavedOffer.class); - } - - private void setOffer(int slot, SavedOffer offer) - { - configManager.setConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot), GSON.toJson(offer)); - } - - private void deleteOffer(int slot) - { - configManager.unsetConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot)); - } - - @Provides - GrandExchangeConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(GrandExchangeConfig.class); - } - - @Override - protected void startUp() - { - itemGELimits = loadGELimits(); - panel = injector.getInstance(GrandExchangePanel.class); - panel.setGELimits(itemGELimits); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "ge_icon.png"); - - button = NavigationButton.builder() - .tooltip("Grand Exchange") - .icon(icon) - .priority(3) - .panel(panel) - .build(); - - clientToolbar.addNavigation(button); - - if (config.quickLookup()) - { - mouseManager.registerMouseListener(inputListener); - keyManager.registerKeyListener(inputListener); - } - - AccountSession accountSession = sessionManager.getAccountSession(); - if (accountSession != null) - { - grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); - } - } - - @Override - protected void shutDown() - { - clientToolbar.removeNavigation(button); - mouseManager.unregisterMouseListener(inputListener); - keyManager.unregisterKeyListener(inputListener); - grandExchangeText = null; - grandExchangeItem = null; - itemGELimits = null; - grandExchangeClient = null; - } - - @Subscribe - public void onSessionOpen(SessionOpen sessionOpen) - { - AccountSession accountSession = sessionManager.getAccountSession(); - if (accountSession.getUuid() != null) - { - grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); - } - else - { - grandExchangeClient = null; - } - } - - @Subscribe - public void onSessionClose(SessionClose sessionClose) - { - grandExchangeClient = null; - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("grandexchange")) - { - if (event.getKey().equals("quickLookup")) - { - if (config.quickLookup()) - { - mouseManager.registerMouseListener(inputListener); - keyManager.registerKeyListener(inputListener); - } - else - { - mouseManager.unregisterMouseListener(inputListener); - keyManager.unregisterKeyListener(inputListener); - } - } - } - } - - @Subscribe - public void onGrandExchangeOfferChanged(GrandExchangeOfferChanged offerEvent) - { - final int slot = offerEvent.getSlot(); - final GrandExchangeOffer offer = offerEvent.getOffer(); - - ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId()); - boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1; - BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack); - SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offer, slot)); - - submitTrades(slot, offer); - - updateConfig(slot, offer); - } - - private void submitTrades(int slot, GrandExchangeOffer offer) - { - if (grandExchangeClient == null) - { - return; - } - - // Only interested in offers which are fully bought/sold - if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD) - { - return; - } - - SavedOffer savedOffer = getOffer(slot); - if (!shouldUpdate(savedOffer, offer)) - { - return; - } - - // getPrice() is the price of the offer, not necessarily what the item bought at - int priceEach = offer.getSpent() / offer.getTotalQuantity(); - - GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); - grandExchangeTrade.setBuy(offer.getState() == GrandExchangeOfferState.BOUGHT); - grandExchangeTrade.setItemId(offer.getItemId()); - grandExchangeTrade.setQuantity(offer.getTotalQuantity()); - grandExchangeTrade.setPrice(priceEach); - - log.debug("Submitting trade: {}", grandExchangeTrade); - grandExchangeClient.submit(grandExchangeTrade); - } - - private void updateConfig(int slot, GrandExchangeOffer offer) - { - if (offer.getState() == GrandExchangeOfferState.EMPTY) - { - deleteOffer(slot); - } - else - { - SavedOffer savedOffer = new SavedOffer(); - savedOffer.setItemId(offer.getItemId()); - savedOffer.setQuantitySold(offer.getQuantitySold()); - savedOffer.setTotalQuantity(offer.getTotalQuantity()); - savedOffer.setPrice(offer.getPrice()); - savedOffer.setSpent(offer.getSpent()); - savedOffer.setState(offer.getState()); - setOffer(slot, savedOffer); - } - } - - private boolean shouldUpdate(SavedOffer savedOffer, GrandExchangeOffer grandExchangeOffer) - { - if (savedOffer == null) - { - return false; - } - - // Only update offer if state has changed - return savedOffer.getState() != grandExchangeOffer.getState(); - } - - @Subscribe - public void onChatMessage(ChatMessage event) - { - if (!this.config.enableNotifications() || event.getType() != ChatMessageType.GAMEMESSAGE) - { - return; - } - - String message = Text.removeTags(event.getMessage()); - - if (message.startsWith("Grand Exchange:")) - { - this.notifier.notify(message); - } - } - - @Subscribe - public void onGameStateChanged(GameStateChanged gameStateChanged) - { - if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN) - { - panel.getOffersPanel().resetOffers(); - } - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) - { - // At the moment, if the user disables quick lookup, the input listener gets disabled. Thus, isHotKeyPressed() - // should always return false when quick lookup is disabled. - // Replace the default option with "Search ..." when holding alt - if (client.getGameState() != GameState.LOGGED_IN || !hotKeyPressed) - { - return; - } - - final MenuEntry[] entries = client.getMenuEntries(); - final MenuEntry menuEntry = entries[entries.length - 1]; - final int widgetId = menuEntry.getParam1(); - final int groupId = WidgetInfo.TO_GROUP(widgetId); - - switch (groupId) - { - case WidgetID.BANK_GROUP_ID: - // Don't show for view tabs and such - if (WidgetInfo.TO_CHILD(widgetId) != WidgetInfo.BANK_ITEM_CONTAINER.getChildId()) - { - break; - } - case WidgetID.INVENTORY_GROUP_ID: - case WidgetID.BANK_INVENTORY_GROUP_ID: - case WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID: - case WidgetID.SHOP_INVENTORY_GROUP_ID: - menuEntry.setOption(SEARCH_GRAND_EXCHANGE); - menuEntry.setType(MenuAction.RUNELITE.getId()); - client.setMenuEntries(entries); - } - } - - @Subscribe - public void onFocusChanged(FocusChanged focusChanged) - { - if (!focusChanged.isFocused()) - { - setHotKeyPressed(false); - } - } - - @Subscribe - public void onWidgetLoaded(WidgetLoaded event) - { - switch (event.getGroupId()) - { - // Grand exchange was opened. - case WidgetID.GRAND_EXCHANGE_GROUP_ID: - Widget grandExchangeOffer = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_CONTAINER); - grandExchangeText = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_TEXT); - grandExchangeItem = grandExchangeOffer.getDynamicChildren()[OFFER_CONTAINER_ITEM]; - break; - // Grand exchange was closed (if it was open before). - case WidgetID.INVENTORY_GROUP_ID: - grandExchangeText = null; - grandExchangeItem = null; - break; - } - } - - @Subscribe - public void onGameTick(GameTick event) - { - if (grandExchangeText == null || grandExchangeItem == null || grandExchangeItem.isHidden()) - { - return; - } - - final Widget geText = grandExchangeText; - final String geTextString = geText.getText(); - final int itemId = grandExchangeItem.getItemId(); - - if (itemId == OFFER_DEFAULT_ITEM_ID || itemId == -1) - { - // This item is invalid/nothing has been searched for - return; - } - - if (config.enableGELimits() && itemGELimits != null && !geTextString.contains(BUY_LIMIT_GE_TEXT)) - { - final Integer itemLimit = itemGELimits.get(itemId); - - // If we have item buy limit, append it - if (itemLimit != null) - { - final String text = geText.getText() + BUY_LIMIT_GE_TEXT + StackFormatter.formatNumber(itemLimit); - geText.setText(text); - } - } - - if (!config.enableOsbPrices() || geTextString.contains(OSB_GE_TEXT)) - { - // OSB prices are disabled or price was already looked up, so no need to set it again - return; - } - - log.debug("Looking up OSB item price {}", itemId); - - executorService.submit(() -> - { - if (geText.getText().contains(OSB_GE_TEXT)) - { - // If there are multiple tasks queued and one of them have already added the price - return; - } - - try - { - final OSBGrandExchangeResult result = CLIENT.lookupItem(itemId); - final String text = geText.getText() + OSB_GE_TEXT + StackFormatter.formatNumber(result.getOverall_average()); - geText.setText(text); - } - catch (IOException e) - { - log.debug("Error getting price of item {}", itemId, e); - } - }); - } - - private static Map loadGELimits() - { - final InputStream geLimitData = GrandExchangePlugin.class.getResourceAsStream("ge_limits.json"); - final Map itemGELimits = GSON.fromJson(new InputStreamReader(geLimitData), BUY_LIMIT_TOKEN.getType()); - log.debug("Loaded {} limits", itemGELimits.size()); - return itemGELimits; - } -} +/* + * Copyright (c) 2019, Adam + * Copyright (c) 2017, Robbie + * Copyright (c) 2018, SomeoneWithAnInternetConnection + * 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.grandexchange; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +import javax.swing.SwingUtilities; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.GrandExchangeOffer; +import net.runelite.api.GrandExchangeOfferState; +import net.runelite.api.ItemComposition; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.GrandExchangeOfferChanged; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.Notifier; +import net.runelite.client.account.AccountSession; +import net.runelite.client.account.SessionManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.game.ItemManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.StackFormatter; +import net.runelite.client.util.Text; +import net.runelite.http.api.ge.GrandExchangeClient; +import net.runelite.http.api.ge.GrandExchangeTrade; +import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; +import net.runelite.http.api.osbuddy.OSBGrandExchangeResult; + +@PluginDescriptor( + name = "Grand Exchange", + description = "Provide additional and/or easier access to Grand Exchange information", + tags = {"external", "integration", "notifications", "panel", "prices", "trade"} +) +@Slf4j +public class GrandExchangePlugin extends Plugin +{ + private static final int OFFER_CONTAINER_ITEM = 21; + private static final int OFFER_DEFAULT_ITEM_ID = 6512; + private static final OSBGrandExchangeClient CLIENT = new OSBGrandExchangeClient(); + private static final String OSB_GE_TEXT = "
OSBuddy Actively traded price: "; + + private static final String BUY_LIMIT_GE_TEXT = "
Buy limit: "; + private static final Gson GSON = new Gson(); + private static final TypeToken> BUY_LIMIT_TOKEN = new TypeToken>() + { + }; + + static final String SEARCH_GRAND_EXCHANGE = "Search Grand Exchange"; + + @Getter(AccessLevel.PACKAGE) + private NavigationButton button; + + @Getter(AccessLevel.PACKAGE) + private GrandExchangePanel panel; + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean hotKeyPressed; + + @Inject + private GrandExchangeInputListener inputListener; + + @Inject + private ItemManager itemManager; + + @Inject + private MouseManager mouseManager; + + @Inject + private KeyManager keyManager; + + @Inject + private Client client; + + @Inject + private ClientToolbar clientToolbar; + + @Inject + private GrandExchangeConfig config; + + @Inject + private Notifier notifier; + + @Inject + private ScheduledExecutorService executorService; + + @Inject + private SessionManager sessionManager; + + @Inject + private ConfigManager configManager; + + private Widget grandExchangeText; + private Widget grandExchangeItem; + private Map itemGELimits; + + private GrandExchangeClient grandExchangeClient; + + private SavedOffer getOffer(int slot) + { + String offer = configManager.getConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot)); + if (offer == null) + { + return null; + } + return GSON.fromJson(offer, SavedOffer.class); + } + + private void setOffer(int slot, SavedOffer offer) + { + configManager.setConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot), GSON.toJson(offer)); + } + + private void deleteOffer(int slot) + { + configManager.unsetConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot)); + } + + @Provides + GrandExchangeConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(GrandExchangeConfig.class); + } + + @Override + protected void startUp() + { + itemGELimits = loadGELimits(); + panel = injector.getInstance(GrandExchangePanel.class); + panel.setGELimits(itemGELimits); + + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "ge_icon.png"); + + button = NavigationButton.builder() + .tooltip("Grand Exchange") + .icon(icon) + .priority(3) + .panel(panel) + .build(); + + clientToolbar.addNavigation(button); + + if (config.quickLookup()) + { + mouseManager.registerMouseListener(inputListener); + keyManager.registerKeyListener(inputListener); + } + + AccountSession accountSession = sessionManager.getAccountSession(); + if (accountSession != null) + { + grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); + } + } + + @Override + protected void shutDown() + { + clientToolbar.removeNavigation(button); + mouseManager.unregisterMouseListener(inputListener); + keyManager.unregisterKeyListener(inputListener); + grandExchangeText = null; + grandExchangeItem = null; + itemGELimits = null; + grandExchangeClient = null; + } + + @Subscribe + public void onSessionOpen(SessionOpen sessionOpen) + { + AccountSession accountSession = sessionManager.getAccountSession(); + if (accountSession.getUuid() != null) + { + grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); + } + else + { + grandExchangeClient = null; + } + } + + @Subscribe + public void onSessionClose(SessionClose sessionClose) + { + grandExchangeClient = null; + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("grandexchange")) + { + if (event.getKey().equals("quickLookup")) + { + if (config.quickLookup()) + { + mouseManager.registerMouseListener(inputListener); + keyManager.registerKeyListener(inputListener); + } + else + { + mouseManager.unregisterMouseListener(inputListener); + keyManager.unregisterKeyListener(inputListener); + } + } + } + } + + @Subscribe + public void onGrandExchangeOfferChanged(GrandExchangeOfferChanged offerEvent) + { + final int slot = offerEvent.getSlot(); + final GrandExchangeOffer offer = offerEvent.getOffer(); + + ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId()); + boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1; + BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack); + SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offer, slot)); + + submitTrades(slot, offer); + + updateConfig(slot, offer); + } + + private void submitTrades(int slot, GrandExchangeOffer offer) + { + if (grandExchangeClient == null) + { + return; + } + + // Only interested in offers which are fully bought/sold + if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD) + { + return; + } + + SavedOffer savedOffer = getOffer(slot); + if (!shouldUpdate(savedOffer, offer)) + { + return; + } + + // getPrice() is the price of the offer, not necessarily what the item bought at + int priceEach = offer.getSpent() / offer.getTotalQuantity(); + + GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); + grandExchangeTrade.setBuy(offer.getState() == GrandExchangeOfferState.BOUGHT); + grandExchangeTrade.setItemId(offer.getItemId()); + grandExchangeTrade.setQuantity(offer.getTotalQuantity()); + grandExchangeTrade.setPrice(priceEach); + + log.debug("Submitting trade: {}", grandExchangeTrade); + grandExchangeClient.submit(grandExchangeTrade); + } + + private void updateConfig(int slot, GrandExchangeOffer offer) + { + if (offer.getState() == GrandExchangeOfferState.EMPTY) + { + deleteOffer(slot); + } + else + { + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(offer.getItemId()); + savedOffer.setQuantitySold(offer.getQuantitySold()); + savedOffer.setTotalQuantity(offer.getTotalQuantity()); + savedOffer.setPrice(offer.getPrice()); + savedOffer.setSpent(offer.getSpent()); + savedOffer.setState(offer.getState()); + setOffer(slot, savedOffer); + } + } + + private boolean shouldUpdate(SavedOffer savedOffer, GrandExchangeOffer grandExchangeOffer) + { + if (savedOffer == null) + { + return false; + } + + // Only update offer if state has changed + return savedOffer.getState() != grandExchangeOffer.getState(); + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (!this.config.enableNotifications() || event.getType() != ChatMessageType.GAMEMESSAGE) + { + return; + } + + String message = Text.removeTags(event.getMessage()); + + if (message.startsWith("Grand Exchange:")) + { + this.notifier.notify(message); + } + } + + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN) + { + panel.getOffersPanel().resetOffers(); + } + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + // At the moment, if the user disables quick lookup, the input listener gets disabled. Thus, isHotKeyPressed() + // should always return false when quick lookup is disabled. + // Replace the default option with "Search ..." when holding alt + if (client.getGameState() != GameState.LOGGED_IN || !hotKeyPressed) + { + return; + } + + final MenuEntry[] entries = client.getMenuEntries(); + final MenuEntry menuEntry = entries[entries.length - 1]; + final int widgetId = menuEntry.getParam1(); + final int groupId = WidgetInfo.TO_GROUP(widgetId); + + switch (groupId) + { + case WidgetID.BANK_GROUP_ID: + // Don't show for view tabs and such + if (WidgetInfo.TO_CHILD(widgetId) != WidgetInfo.BANK_ITEM_CONTAINER.getChildId()) + { + break; + } + case WidgetID.INVENTORY_GROUP_ID: + case WidgetID.BANK_INVENTORY_GROUP_ID: + case WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID: + case WidgetID.SHOP_INVENTORY_GROUP_ID: + menuEntry.setOption(SEARCH_GRAND_EXCHANGE); + menuEntry.setType(MenuAction.RUNELITE.getId()); + client.setMenuEntries(entries); + } + } + + @Subscribe + public void onFocusChanged(FocusChanged focusChanged) + { + if (!focusChanged.isFocused()) + { + setHotKeyPressed(false); + } + } + + @Subscribe + public void onWidgetLoaded(WidgetLoaded event) + { + switch (event.getGroupId()) + { + // Grand exchange was opened. + case WidgetID.GRAND_EXCHANGE_GROUP_ID: + Widget grandExchangeOffer = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_CONTAINER); + grandExchangeText = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_TEXT); + grandExchangeItem = grandExchangeOffer.getDynamicChildren()[OFFER_CONTAINER_ITEM]; + break; + // Grand exchange was closed (if it was open before). + case WidgetID.INVENTORY_GROUP_ID: + grandExchangeText = null; + grandExchangeItem = null; + break; + } + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (grandExchangeText == null || grandExchangeItem == null || grandExchangeItem.isHidden()) + { + return; + } + + final Widget geText = grandExchangeText; + final String geTextString = geText.getText(); + final int itemId = grandExchangeItem.getItemId(); + + if (itemId == OFFER_DEFAULT_ITEM_ID || itemId == -1) + { + // This item is invalid/nothing has been searched for + return; + } + + if (config.enableGELimits() && itemGELimits != null && !geTextString.contains(BUY_LIMIT_GE_TEXT)) + { + final Integer itemLimit = itemGELimits.get(itemId); + + // If we have item buy limit, append it + if (itemLimit != null) + { + final String text = geText.getText() + BUY_LIMIT_GE_TEXT + StackFormatter.formatNumber(itemLimit); + geText.setText(text); + } + } + + if (!config.enableOsbPrices() || geTextString.contains(OSB_GE_TEXT)) + { + // OSB prices are disabled or price was already looked up, so no need to set it again + return; + } + + log.debug("Looking up OSB item price {}", itemId); + + executorService.submit(() -> + { + if (geText.getText().contains(OSB_GE_TEXT)) + { + // If there are multiple tasks queued and one of them have already added the price + return; + } + + try + { + final OSBGrandExchangeResult result = CLIENT.lookupItem(itemId); + final String text = geText.getText() + OSB_GE_TEXT + StackFormatter.formatNumber(result.getOverall_average()); + geText.setText(text); + } + catch (IOException e) + { + log.debug("Error getting price of item {}", itemId, e); + } + }); + } + + private static Map loadGELimits() + { + final InputStream geLimitData = GrandExchangePlugin.class.getResourceAsStream("ge_limits.json"); + final Map itemGELimits = GSON.fromJson(new InputStreamReader(geLimitData), BUY_LIMIT_TOKEN.getType()); + log.debug("Loaded {} limits", itemGELimits.size()); + return itemGELimits; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grotesqueguardians/GrotesqueGuardiansPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grotesqueguardians/GrotesqueGuardiansPlugin.java index e41c1a4b47..7d461f8cfd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grotesqueguardians/GrotesqueGuardiansPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grotesqueguardians/GrotesqueGuardiansPlugin.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2018, Damen - * 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.grotesqueguardians; - -import javax.inject.Inject; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "Grotesque Guardians", - description = "Display tile indicators for the Grotesque Guardian special attacks", - tags = {"grotesque", "guardians", "gargoyle", "garg"}, - type = PluginType.PVM -) -public class GrotesqueGuardiansPlugin extends Plugin -{ - @Inject - private OverlayManager overlayManager; - - @Inject - private GrotesqueGuardiansOverlay overlay; - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - } -} +/* + * Copyright (c) 2018, Damen + * 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.grotesqueguardians; + +import javax.inject.Inject; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Grotesque Guardians", + description = "Display tile indicators for the Grotesque Guardian special attacks", + tags = {"grotesque", "guardians", "gargoyle", "garg"}, + type = PluginType.PVM +) +public class GrotesqueGuardiansPlugin extends Plugin +{ + @Inject + private OverlayManager overlayManager; + + @Inject + private GrotesqueGuardiansOverlay overlay; + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java index 008429abf1..c722b202f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java @@ -1,383 +1,383 @@ -/* - * Copyright (c) 2017, Aria - * 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.grounditems; - -import java.awt.Color; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; -import net.runelite.client.plugins.grounditems.config.ItemHighlightMode; -import net.runelite.client.plugins.grounditems.config.MenuHighlightMode; -import net.runelite.client.plugins.grounditems.config.PriceDisplayMode; -import net.runelite.client.plugins.grounditems.config.ValueCalculationMode; - -@ConfigGroup("grounditems") -public interface GroundItemsConfig extends Config -{ - @ConfigItem( - keyName = "highlightedItems", - name = "Highlighted Items", - description = "Configures specifically highlighted ground items. Format: (item), (item)", - position = 0 - ) - default String getHighlightItems() - { - return ""; - } - - @ConfigItem( - keyName = "highlightedItems", - name = "", - description = "" - ) - void setHighlightedItem(String key); - - @ConfigItem( - keyName = "hiddenItems", - name = "Hidden Items", - description = "Configures hidden ground items. Format: (item), (item)", - position = 1 - ) - default String getHiddenItems() - { - return "Vial, Ashes, Coins, Bones, Bucket, Jug, Seaweed"; - } - - @ConfigItem( - keyName = "hiddenItems", - name = "", - description = "" - ) - void setHiddenItems(String key); - - @ConfigItem( - keyName = "showHighlightedOnly", - name = "Show Highlighted items only", - description = "Configures whether or not to draw items only on your highlighted list", - position = 2 - ) - default boolean showHighlightedOnly() - { - return false; - } - - @ConfigItem( - keyName = "dontHideUntradeables", - name = "Do not hide untradeables", - description = "Configures whether or not untradeable items ignore hiding under settings", - position = 3 - ) - default boolean dontHideUntradeables() - { - return true; - } - - @ConfigItem( - keyName = "showMenuItemQuantities", - name = "Show Menu Item Quantities", - description = "Configures whether or not to show the item quantities in the menu", - position = 4 - ) - default boolean showMenuItemQuantities() - { - return true; - } - - @ConfigItem( - keyName = "recolorMenuHiddenItems", - name = "Recolor Menu Hidden Items", - description = "Configures whether or not hidden items in right click menu will be recolored", - position = 5 - ) - default boolean recolorMenuHiddenItems() - { - return false; - } - - @ConfigItem( - keyName = "highlightTiles", - name = "Highlight Tiles", - description = "Configures whether or not to highlight tiles containing ground items", - position = 6 - ) - default boolean highlightTiles() - { - return false; - } - - @ConfigItem( - keyName = "notifyHighlightedDrops", - name = "Notify for Highlighted drops", - description = "Configures whether or not to notify for drops on your highlighted list", - position = 7 - ) - default boolean notifyHighlightedDrops() - { - return false; - } - - @ConfigItem( - keyName = "priceDisplayMode", - name = "Price Display Mode", - description = "Configures what price types are shown alongside of ground item name", - position = 8 - ) - default PriceDisplayMode priceDisplayMode() - { - return PriceDisplayMode.BOTH; - } - - @ConfigItem( - keyName = "itemHighlightMode", - name = "Item Highlight Mode", - description = "Configures how ground items will be highlighted", - position = 9 - ) - default ItemHighlightMode itemHighlightMode() - { - return ItemHighlightMode.BOTH; - } - - @ConfigItem( - keyName = "menuHighlightMode", - name = "Menu Highlight Mode", - description = "Configures what to highlight in right-click menu", - position = 10 - ) - default MenuHighlightMode menuHighlightMode() - { - return MenuHighlightMode.NAME; - } - - @ConfigItem( - keyName = "highlightValueCalculation", - name = "Highlight Value Calculation", - description = "Configures which coin value is used to determine highlight color", - position = 11 - ) - default ValueCalculationMode valueCalculationMode() - { - return ValueCalculationMode.HIGHEST; - } - - @ConfigItem( - keyName = "highlightOverValue2", - name = "Highlight > Value", - description = "Configures highlighted ground items over either GE or HA value", - position = 12 - ) - default int getHighlightOverValue() - { - return 0; - } - - @ConfigItem( - keyName = "hideUnderValue", - name = "Hide < Value", - description = "Configures hidden ground items under both GE and HA value", - position = 13 - ) - default int getHideUnderValue() - { - return 0; - } - - @ConfigItem( - keyName = "defaultColor", - name = "Default items color", - description = "Configures the color for default, non-highlighted items", - position = 14 - ) - default Color defaultColor() - { - return Color.WHITE; - } - - @ConfigItem( - keyName = "highlightedColor", - name = "Highlighted items color", - description = "Configures the color for highlighted items", - position = 15 - ) - default Color highlightedColor() - { - return Color.decode("#AA00FF"); - } - - @ConfigItem( - keyName = "hiddenColor", - name = "Hidden items color", - description = "Configures the color for hidden items in right-click menu and when holding ALT", - position = 16 - ) - default Color hiddenColor() - { - return Color.GRAY; - } - - @ConfigItem( - keyName = "lowValueColor", - name = "Low value items color", - description = "Configures the color for low value items", - position = 17 - ) - default Color lowValueColor() - { - return Color.decode("#66B2FF"); - } - - @ConfigItem( - keyName = "lowValuePrice", - name = "Low value price", - description = "Configures the start price for low value items", - position = 18 - ) - default int lowValuePrice() - { - return 20000; - } - - @ConfigItem( - keyName = "mediumValueColor", - name = "Medium value items color", - description = "Configures the color for medium value items", - position = 19 - ) - default Color mediumValueColor() - { - return Color.decode("#99FF99"); - } - - @ConfigItem( - keyName = "mediumValuePrice", - name = "Medium value price", - description = "Configures the start price for medium value items", - position = 20 - ) - default int mediumValuePrice() - { - return 100000; - } - - @ConfigItem( - keyName = "highValueColor", - name = "High value items color", - description = "Configures the color for high value items", - position = 21 - ) - default Color highValueColor() - { - return Color.decode("#FF9600"); - } - - @ConfigItem( - keyName = "highValuePrice", - name = "High value price", - description = "Configures the start price for high value items", - position = 22 - ) - default int highValuePrice() - { - return 1000000; - } - - @ConfigItem( - keyName = "insaneValueColor", - name = "Insane value items color", - description = "Configures the color for insane value items", - position = 23 - ) - default Color insaneValueColor() - { - return Color.decode("#FF66B2"); - } - - @ConfigItem( - keyName = "insaneValuePrice", - name = "Insane value price", - description = "Configures the start price for insane value items", - position = 24 - ) - default int insaneValuePrice() - { - return 10000000; - } - - @ConfigItem( - keyName = "onlyShowLoot", - name = "Only show loot", - description = "Only shows drops from NPCs and players", - position = 25 - ) - default boolean onlyShowLoot() - { - return false; - } - - @ConfigItem( - keyName = "doubleTapDelay", - name = "Delay for double-tap ALT to hide", - description = "Decrease this number if you accidentally hide ground items often. (0 = Disabled)", - position = 26 - ) - default int doubleTapDelay() - { - return 250; - } - - @ConfigItem( - keyName = "collapseEntries", - name = "Collapse ground item menu entries", - description = "Collapses ground item menu entries together and appends count", - position = 27 - ) - default boolean collapseEntries() - { - return false; - } - - @ConfigItem( - position = 27, - keyName = "removeIgnored", - name = "Hide Ignored", - description = "Remove take option for items that are on the hidden items list." - ) - default boolean removeIgnored() - { - return false; - } - - @ConfigItem( - keyName = "toggleOutline", - name = "Text Outline", - description = "Use an outline around text instead of a text shadow", - position = 29 - ) - default boolean toggleOutline() - { - return false; - } -} +/* + * Copyright (c) 2017, Aria + * 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.grounditems; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.plugins.grounditems.config.ItemHighlightMode; +import net.runelite.client.plugins.grounditems.config.MenuHighlightMode; +import net.runelite.client.plugins.grounditems.config.PriceDisplayMode; +import net.runelite.client.plugins.grounditems.config.ValueCalculationMode; + +@ConfigGroup("grounditems") +public interface GroundItemsConfig extends Config +{ + @ConfigItem( + keyName = "highlightedItems", + name = "Highlighted Items", + description = "Configures specifically highlighted ground items. Format: (item), (item)", + position = 0 + ) + default String getHighlightItems() + { + return ""; + } + + @ConfigItem( + keyName = "highlightedItems", + name = "", + description = "" + ) + void setHighlightedItem(String key); + + @ConfigItem( + keyName = "hiddenItems", + name = "Hidden Items", + description = "Configures hidden ground items. Format: (item), (item)", + position = 1 + ) + default String getHiddenItems() + { + return "Vial, Ashes, Coins, Bones, Bucket, Jug, Seaweed"; + } + + @ConfigItem( + keyName = "hiddenItems", + name = "", + description = "" + ) + void setHiddenItems(String key); + + @ConfigItem( + keyName = "showHighlightedOnly", + name = "Show Highlighted items only", + description = "Configures whether or not to draw items only on your highlighted list", + position = 2 + ) + default boolean showHighlightedOnly() + { + return false; + } + + @ConfigItem( + keyName = "dontHideUntradeables", + name = "Do not hide untradeables", + description = "Configures whether or not untradeable items ignore hiding under settings", + position = 3 + ) + default boolean dontHideUntradeables() + { + return true; + } + + @ConfigItem( + keyName = "showMenuItemQuantities", + name = "Show Menu Item Quantities", + description = "Configures whether or not to show the item quantities in the menu", + position = 4 + ) + default boolean showMenuItemQuantities() + { + return true; + } + + @ConfigItem( + keyName = "recolorMenuHiddenItems", + name = "Recolor Menu Hidden Items", + description = "Configures whether or not hidden items in right click menu will be recolored", + position = 5 + ) + default boolean recolorMenuHiddenItems() + { + return false; + } + + @ConfigItem( + keyName = "highlightTiles", + name = "Highlight Tiles", + description = "Configures whether or not to highlight tiles containing ground items", + position = 6 + ) + default boolean highlightTiles() + { + return false; + } + + @ConfigItem( + keyName = "notifyHighlightedDrops", + name = "Notify for Highlighted drops", + description = "Configures whether or not to notify for drops on your highlighted list", + position = 7 + ) + default boolean notifyHighlightedDrops() + { + return false; + } + + @ConfigItem( + keyName = "priceDisplayMode", + name = "Price Display Mode", + description = "Configures what price types are shown alongside of ground item name", + position = 8 + ) + default PriceDisplayMode priceDisplayMode() + { + return PriceDisplayMode.BOTH; + } + + @ConfigItem( + keyName = "itemHighlightMode", + name = "Item Highlight Mode", + description = "Configures how ground items will be highlighted", + position = 9 + ) + default ItemHighlightMode itemHighlightMode() + { + return ItemHighlightMode.BOTH; + } + + @ConfigItem( + keyName = "menuHighlightMode", + name = "Menu Highlight Mode", + description = "Configures what to highlight in right-click menu", + position = 10 + ) + default MenuHighlightMode menuHighlightMode() + { + return MenuHighlightMode.NAME; + } + + @ConfigItem( + keyName = "highlightValueCalculation", + name = "Highlight Value Calculation", + description = "Configures which coin value is used to determine highlight color", + position = 11 + ) + default ValueCalculationMode valueCalculationMode() + { + return ValueCalculationMode.HIGHEST; + } + + @ConfigItem( + keyName = "highlightOverValue2", + name = "Highlight > Value", + description = "Configures highlighted ground items over either GE or HA value", + position = 12 + ) + default int getHighlightOverValue() + { + return 0; + } + + @ConfigItem( + keyName = "hideUnderValue", + name = "Hide < Value", + description = "Configures hidden ground items under both GE and HA value", + position = 13 + ) + default int getHideUnderValue() + { + return 0; + } + + @ConfigItem( + keyName = "defaultColor", + name = "Default items color", + description = "Configures the color for default, non-highlighted items", + position = 14 + ) + default Color defaultColor() + { + return Color.WHITE; + } + + @ConfigItem( + keyName = "highlightedColor", + name = "Highlighted items color", + description = "Configures the color for highlighted items", + position = 15 + ) + default Color highlightedColor() + { + return Color.decode("#AA00FF"); + } + + @ConfigItem( + keyName = "hiddenColor", + name = "Hidden items color", + description = "Configures the color for hidden items in right-click menu and when holding ALT", + position = 16 + ) + default Color hiddenColor() + { + return Color.GRAY; + } + + @ConfigItem( + keyName = "lowValueColor", + name = "Low value items color", + description = "Configures the color for low value items", + position = 17 + ) + default Color lowValueColor() + { + return Color.decode("#66B2FF"); + } + + @ConfigItem( + keyName = "lowValuePrice", + name = "Low value price", + description = "Configures the start price for low value items", + position = 18 + ) + default int lowValuePrice() + { + return 20000; + } + + @ConfigItem( + keyName = "mediumValueColor", + name = "Medium value items color", + description = "Configures the color for medium value items", + position = 19 + ) + default Color mediumValueColor() + { + return Color.decode("#99FF99"); + } + + @ConfigItem( + keyName = "mediumValuePrice", + name = "Medium value price", + description = "Configures the start price for medium value items", + position = 20 + ) + default int mediumValuePrice() + { + return 100000; + } + + @ConfigItem( + keyName = "highValueColor", + name = "High value items color", + description = "Configures the color for high value items", + position = 21 + ) + default Color highValueColor() + { + return Color.decode("#FF9600"); + } + + @ConfigItem( + keyName = "highValuePrice", + name = "High value price", + description = "Configures the start price for high value items", + position = 22 + ) + default int highValuePrice() + { + return 1000000; + } + + @ConfigItem( + keyName = "insaneValueColor", + name = "Insane value items color", + description = "Configures the color for insane value items", + position = 23 + ) + default Color insaneValueColor() + { + return Color.decode("#FF66B2"); + } + + @ConfigItem( + keyName = "insaneValuePrice", + name = "Insane value price", + description = "Configures the start price for insane value items", + position = 24 + ) + default int insaneValuePrice() + { + return 10000000; + } + + @ConfigItem( + keyName = "onlyShowLoot", + name = "Only show loot", + description = "Only shows drops from NPCs and players", + position = 25 + ) + default boolean onlyShowLoot() + { + return false; + } + + @ConfigItem( + keyName = "doubleTapDelay", + name = "Delay for double-tap ALT to hide", + description = "Decrease this number if you accidentally hide ground items often. (0 = Disabled)", + position = 26 + ) + default int doubleTapDelay() + { + return 250; + } + + @ConfigItem( + keyName = "collapseEntries", + name = "Collapse ground item menu entries", + description = "Collapses ground item menu entries together and appends count", + position = 27 + ) + default boolean collapseEntries() + { + return false; + } + + @ConfigItem( + position = 27, + keyName = "removeIgnored", + name = "Hide Ignored", + description = "Remove take option for items that are on the hidden items list." + ) + default boolean removeIgnored() + { + return false; + } + + @ConfigItem( + keyName = "toggleOutline", + name = "Text Outline", + description = "Use an outline around text instead of a text shadow", + position = 29 + ) + default boolean toggleOutline() + { + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java index 17c0151ae7..4d7e2601cd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java @@ -1,391 +1,391 @@ -/* - * Copyright (c) 2017, Aria - * Copyright (c) 2018, Adam - * 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.grounditems; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.util.AbstractMap.SimpleEntry; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Player; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.MENU; -import net.runelite.client.plugins.grounditems.config.PriceDisplayMode; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.BackgroundComponent; -import net.runelite.client.ui.overlay.components.TextComponent; -import net.runelite.client.util.StackFormatter; - -public class GroundItemsOverlay extends Overlay -{ - private static final int MAX_DISTANCE = 2500; - // We must offset the text on the z-axis such that - // it doesn't obscure the ground items below it. - private static final int OFFSET_Z = 20; - // The game won't send anything higher than this value to the plugin - - // so we replace any item quantity higher with "Lots" instead. - private static final int MAX_QUANTITY = 65535; - // The 15 pixel gap between each drawn ground item. - private static final int STRING_GAP = 15; - // Size of the hidden/highlight boxes - private static final int RECTANGLE_SIZE = 8; - - private final Client client; - private final GroundItemsPlugin plugin; - private final GroundItemsConfig config; - private final StringBuilder itemStringBuilder = new StringBuilder(); - private final BackgroundComponent backgroundComponent = new BackgroundComponent(); - private final TextComponent textComponent = new TextComponent(); - private final Map offsetMap = new HashMap<>(); - - @Inject - private GroundItemsOverlay(Client client, GroundItemsPlugin plugin, GroundItemsConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.client = client; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D graphics) - { - final boolean dontShowOverlay = (config.itemHighlightMode() == MENU || plugin.isHideAll()) && !plugin.isHotKeyPressed(); - - if (dontShowOverlay && !config.highlightTiles()) - { - return null; - } - - final FontMetrics fm = graphics.getFontMetrics(); - final Player player = client.getLocalPlayer(); - - if (player == null || client.getViewportWidget() == null) - { - return null; - } - - offsetMap.clear(); - final LocalPoint localLocation = player.getLocalLocation(); - final Point mousePos = client.getMouseCanvasPosition(); - Collection groundItemList = plugin.getCollectedGroundItems().values(); - GroundItem topGroundItem = null; - - if (plugin.isHotKeyPressed()) - { - // Make copy of ground items because we are going to modify them here, and the array list supports our - // desired behaviour here - groundItemList = new ArrayList<>(groundItemList); - final java.awt.Point awtMousePos = new java.awt.Point(mousePos.getX(), mousePos.getY()); - GroundItem groundItem = null; - - for (GroundItem item : groundItemList) - { - item.setOffset(offsetMap.compute(item.getLocation(), (k, v) -> v != null ? v + 1 : 0)); - - if (groundItem != null) - { - continue; - } - - if (plugin.getTextBoxBounds() != null - && item.equals(plugin.getTextBoxBounds().getValue()) - && plugin.getTextBoxBounds().getKey().contains(awtMousePos)) - { - groundItem = item; - continue; - } - - if (plugin.getHiddenBoxBounds() != null - && item.equals(plugin.getHiddenBoxBounds().getValue()) - && plugin.getHiddenBoxBounds().getKey().contains(awtMousePos)) - { - groundItem = item; - continue; - } - - if (plugin.getHighlightBoxBounds() != null - && item.equals(plugin.getHighlightBoxBounds().getValue()) - && plugin.getHighlightBoxBounds().getKey().contains(awtMousePos)) - { - groundItem = item; - } - } - - if (groundItem != null) - { - groundItemList.remove(groundItem); - groundItemList.add(groundItem); - topGroundItem = groundItem; - } - } - - plugin.setTextBoxBounds(null); - plugin.setHiddenBoxBounds(null); - plugin.setHighlightBoxBounds(null); - - final boolean onlyShowLoot = config.onlyShowLoot(); - - for (GroundItem item : groundItemList) - { - final LocalPoint groundPoint = LocalPoint.fromWorld(client, item.getLocation()); - - if (groundPoint == null || localLocation.distanceTo(groundPoint) > MAX_DISTANCE - || (onlyShowLoot && !item.isMine())) - { - continue; - } - - final Color highlighted = plugin.getHighlighted(item.getName(), item.getGePrice(), item.getHaPrice()); - final Color hidden = plugin.getHidden(item.getName(), item.getGePrice(), item.getHaPrice(), item.isTradeable()); - - if (highlighted == null && !plugin.isHotKeyPressed()) - { - // Do not display hidden items - if (hidden != null) - { - continue; - } - - // Do not display non-highlighted items - if (config.showHighlightedOnly()) - { - continue; - } - } - - final Color color = plugin.getItemColor(highlighted, hidden); - - if (config.highlightTiles()) - { - final Polygon poly = Perspective.getCanvasTilePoly(client, groundPoint); - - if (poly != null) - { - OverlayUtil.renderPolygon(graphics, poly, color); - } - } - - if (dontShowOverlay) - { - continue; - } - - itemStringBuilder.append(item.getName()); - - if (item.getQuantity() > 1) - { - if (item.getQuantity() >= MAX_QUANTITY) - { - itemStringBuilder.append(" (Lots!)"); - } - else - { - itemStringBuilder.append(" (") - .append(StackFormatter.quantityToStackSize(item.getQuantity())) - .append(")"); - } - } - - if (config.priceDisplayMode() == PriceDisplayMode.BOTH) - { - if (item.getGePrice() > 0) - { - itemStringBuilder.append(" (EX: ") - .append(StackFormatter.quantityToStackSize(item.getGePrice())) - .append(" gp)"); - } - - if (item.getHaPrice() > 0) - { - itemStringBuilder.append(" (HA: ") - .append(StackFormatter.quantityToStackSize(item.getHaPrice())) - .append(" gp)"); - } - } - else if (config.priceDisplayMode() != PriceDisplayMode.OFF) - { - final int price = config.priceDisplayMode() == PriceDisplayMode.GE - ? item.getGePrice() - : item.getHaPrice(); - - if (price > 0) - { - itemStringBuilder - .append(" (") - .append(StackFormatter.quantityToStackSize(price)) - .append(" gp)"); - } - } - - final String itemString = itemStringBuilder.toString(); - itemStringBuilder.setLength(0); - - final Point textPoint = Perspective.getCanvasTextLocation(client, - graphics, - groundPoint, - itemString, - item.getHeight() + OFFSET_Z); - - if (textPoint == null) - { - continue; - } - - final int offset = plugin.isHotKeyPressed() - ? item.getOffset() - : offsetMap.compute(item.getLocation(), (k, v) -> v != null ? v + 1 : 0); - - final int textX = textPoint.getX(); - final int textY = textPoint.getY() - (STRING_GAP * offset); - - if (plugin.isHotKeyPressed()) - { - final int stringWidth = fm.stringWidth(itemString); - final int stringHeight = fm.getHeight(); - - // Item bounds - int x = textX - 2; - int y = textY - stringHeight - 2; - int width = stringWidth + 4; - int height = stringHeight + 4; - final Rectangle itemBounds = new Rectangle(x, y, width, height); - - // Hidden box - x += width + 2; - y = textY - (RECTANGLE_SIZE + stringHeight) / 2; - width = height = RECTANGLE_SIZE; - final Rectangle itemHiddenBox = new Rectangle(x, y, width, height); - - // Highlight box - x += width + 2; - final Rectangle itemHighlightBox = new Rectangle(x, y, width, height); - - boolean mouseInBox = itemBounds.contains(mousePos.getX(), mousePos.getY()); - boolean mouseInHiddenBox = itemHiddenBox.contains(mousePos.getX(), mousePos.getY()); - boolean mouseInHighlightBox = itemHighlightBox.contains(mousePos.getX(), mousePos.getY()); - - if (mouseInBox) - { - plugin.setTextBoxBounds(new SimpleEntry<>(itemBounds, item)); - } - else if (mouseInHiddenBox) - { - plugin.setHiddenBoxBounds(new SimpleEntry<>(itemHiddenBox, item)); - - } - else if (mouseInHighlightBox) - { - plugin.setHighlightBoxBounds(new SimpleEntry<>(itemHighlightBox, item)); - } - - boolean topItem = topGroundItem == item; - - // Draw background if hovering - if (topItem && (mouseInBox || mouseInHiddenBox || mouseInHighlightBox)) - { - backgroundComponent.setRectangle(itemBounds); - backgroundComponent.render(graphics); - } - - // Draw hidden box - drawRectangle(graphics, itemHiddenBox, topItem && mouseInHiddenBox ? Color.RED : color, hidden != null, true); - - // Draw highlight box - drawRectangle(graphics, itemHighlightBox, topItem && mouseInHighlightBox ? Color.GREEN : color, highlighted != null, false); - } - - if (config.toggleOutline()) - { - graphics.setColor(Color.BLACK); - graphics.drawString(itemString, textX + 1, textY + 1); - graphics.drawString(itemString, textX - 1, textY - 1); - graphics.drawString(itemString, textX - 1, textY + 1); - graphics.drawString(itemString, textX + 1, textY - 1); - } - - textComponent.setText(itemString); - textComponent.setColor(color); - textComponent.setPosition(new java.awt.Point(textX, textY)); - textComponent.render(graphics); - } - - return null; - } - - private void drawRectangle(Graphics2D graphics, Rectangle rect, Color color, boolean inList, boolean hiddenBox) - { - graphics.setColor(Color.BLACK); - graphics.drawRect(rect.x + 1, rect.y + 1, rect.width, rect.height); - - graphics.setColor(color); - graphics.draw(rect); - - if (inList) - { - graphics.fill(rect); - } - - graphics.setColor(Color.WHITE); - // Minus symbol - graphics.drawLine - ( - rect.x + 2, - rect.y + (rect.height / 2), - rect.x + rect.width - 2, - rect.y + (rect.height / 2) - ); - - if (!hiddenBox) - { - // Plus symbol - graphics.drawLine - ( - rect.x + (rect.width / 2), - rect.y + 2, - rect.x + (rect.width / 2), - rect.y + rect.height - 2 - ); - } - - } - -} +/* + * Copyright (c) 2017, Aria + * Copyright (c) 2018, Adam + * 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.grounditems; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Player; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.MENU; +import net.runelite.client.plugins.grounditems.config.PriceDisplayMode; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.BackgroundComponent; +import net.runelite.client.ui.overlay.components.TextComponent; +import net.runelite.client.util.StackFormatter; + +public class GroundItemsOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2500; + // We must offset the text on the z-axis such that + // it doesn't obscure the ground items below it. + private static final int OFFSET_Z = 20; + // The game won't send anything higher than this value to the plugin - + // so we replace any item quantity higher with "Lots" instead. + private static final int MAX_QUANTITY = 65535; + // The 15 pixel gap between each drawn ground item. + private static final int STRING_GAP = 15; + // Size of the hidden/highlight boxes + private static final int RECTANGLE_SIZE = 8; + + private final Client client; + private final GroundItemsPlugin plugin; + private final GroundItemsConfig config; + private final StringBuilder itemStringBuilder = new StringBuilder(); + private final BackgroundComponent backgroundComponent = new BackgroundComponent(); + private final TextComponent textComponent = new TextComponent(); + private final Map offsetMap = new HashMap<>(); + + @Inject + private GroundItemsOverlay(Client client, GroundItemsPlugin plugin, GroundItemsConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + final boolean dontShowOverlay = (config.itemHighlightMode() == MENU || plugin.isHideAll()) && !plugin.isHotKeyPressed(); + + if (dontShowOverlay && !config.highlightTiles()) + { + return null; + } + + final FontMetrics fm = graphics.getFontMetrics(); + final Player player = client.getLocalPlayer(); + + if (player == null || client.getViewportWidget() == null) + { + return null; + } + + offsetMap.clear(); + final LocalPoint localLocation = player.getLocalLocation(); + final Point mousePos = client.getMouseCanvasPosition(); + Collection groundItemList = GroundItemsPlugin.getCollectedGroundItems().values(); + GroundItem topGroundItem = null; + + if (plugin.isHotKeyPressed()) + { + // Make copy of ground items because we are going to modify them here, and the array list supports our + // desired behaviour here + groundItemList = new ArrayList<>(groundItemList); + final java.awt.Point awtMousePos = new java.awt.Point(mousePos.getX(), mousePos.getY()); + GroundItem groundItem = null; + + for (GroundItem item : groundItemList) + { + item.setOffset(offsetMap.compute(item.getLocation(), (k, v) -> v != null ? v + 1 : 0)); + + if (groundItem != null) + { + continue; + } + + if (plugin.getTextBoxBounds() != null + && item.equals(plugin.getTextBoxBounds().getValue()) + && plugin.getTextBoxBounds().getKey().contains(awtMousePos)) + { + groundItem = item; + continue; + } + + if (plugin.getHiddenBoxBounds() != null + && item.equals(plugin.getHiddenBoxBounds().getValue()) + && plugin.getHiddenBoxBounds().getKey().contains(awtMousePos)) + { + groundItem = item; + continue; + } + + if (plugin.getHighlightBoxBounds() != null + && item.equals(plugin.getHighlightBoxBounds().getValue()) + && plugin.getHighlightBoxBounds().getKey().contains(awtMousePos)) + { + groundItem = item; + } + } + + if (groundItem != null) + { + groundItemList.remove(groundItem); + groundItemList.add(groundItem); + topGroundItem = groundItem; + } + } + + plugin.setTextBoxBounds(null); + plugin.setHiddenBoxBounds(null); + plugin.setHighlightBoxBounds(null); + + final boolean onlyShowLoot = config.onlyShowLoot(); + + for (GroundItem item : groundItemList) + { + final LocalPoint groundPoint = LocalPoint.fromWorld(client, item.getLocation()); + + if (groundPoint == null || localLocation.distanceTo(groundPoint) > MAX_DISTANCE + || (onlyShowLoot && !item.isMine())) + { + continue; + } + + final Color highlighted = plugin.getHighlighted(item.getName(), item.getGePrice(), item.getHaPrice()); + final Color hidden = plugin.getHidden(item.getName(), item.getGePrice(), item.getHaPrice(), item.isTradeable()); + + if (highlighted == null && !plugin.isHotKeyPressed()) + { + // Do not display hidden items + if (hidden != null) + { + continue; + } + + // Do not display non-highlighted items + if (config.showHighlightedOnly()) + { + continue; + } + } + + final Color color = plugin.getItemColor(highlighted, hidden); + + if (config.highlightTiles()) + { + final Polygon poly = Perspective.getCanvasTilePoly(client, groundPoint); + + if (poly != null) + { + OverlayUtil.renderPolygon(graphics, poly, color); + } + } + + if (dontShowOverlay) + { + continue; + } + + itemStringBuilder.append(item.getName()); + + if (item.getQuantity() > 1) + { + if (item.getQuantity() >= MAX_QUANTITY) + { + itemStringBuilder.append(" (Lots!)"); + } + else + { + itemStringBuilder.append(" (") + .append(StackFormatter.quantityToStackSize(item.getQuantity())) + .append(")"); + } + } + + if (config.priceDisplayMode() == PriceDisplayMode.BOTH) + { + if (item.getGePrice() > 0) + { + itemStringBuilder.append(" (EX: ") + .append(StackFormatter.quantityToStackSize(item.getGePrice())) + .append(" gp)"); + } + + if (item.getHaPrice() > 0) + { + itemStringBuilder.append(" (HA: ") + .append(StackFormatter.quantityToStackSize(item.getHaPrice())) + .append(" gp)"); + } + } + else if (config.priceDisplayMode() != PriceDisplayMode.OFF) + { + final int price = config.priceDisplayMode() == PriceDisplayMode.GE + ? item.getGePrice() + : item.getHaPrice(); + + if (price > 0) + { + itemStringBuilder + .append(" (") + .append(StackFormatter.quantityToStackSize(price)) + .append(" gp)"); + } + } + + final String itemString = itemStringBuilder.toString(); + itemStringBuilder.setLength(0); + + final Point textPoint = Perspective.getCanvasTextLocation(client, + graphics, + groundPoint, + itemString, + item.getHeight() + OFFSET_Z); + + if (textPoint == null) + { + continue; + } + + final int offset = plugin.isHotKeyPressed() + ? item.getOffset() + : offsetMap.compute(item.getLocation(), (k, v) -> v != null ? v + 1 : 0); + + final int textX = textPoint.getX(); + final int textY = textPoint.getY() - (STRING_GAP * offset); + + if (plugin.isHotKeyPressed()) + { + final int stringWidth = fm.stringWidth(itemString); + final int stringHeight = fm.getHeight(); + + // Item bounds + int x = textX - 2; + int y = textY - stringHeight - 2; + int width = stringWidth + 4; + int height = stringHeight + 4; + final Rectangle itemBounds = new Rectangle(x, y, width, height); + + // Hidden box + x += width + 2; + y = textY - (RECTANGLE_SIZE + stringHeight) / 2; + width = height = RECTANGLE_SIZE; + final Rectangle itemHiddenBox = new Rectangle(x, y, width, height); + + // Highlight box + x += width + 2; + final Rectangle itemHighlightBox = new Rectangle(x, y, width, height); + + boolean mouseInBox = itemBounds.contains(mousePos.getX(), mousePos.getY()); + boolean mouseInHiddenBox = itemHiddenBox.contains(mousePos.getX(), mousePos.getY()); + boolean mouseInHighlightBox = itemHighlightBox.contains(mousePos.getX(), mousePos.getY()); + + if (mouseInBox) + { + plugin.setTextBoxBounds(new SimpleEntry<>(itemBounds, item)); + } + else if (mouseInHiddenBox) + { + plugin.setHiddenBoxBounds(new SimpleEntry<>(itemHiddenBox, item)); + + } + else if (mouseInHighlightBox) + { + plugin.setHighlightBoxBounds(new SimpleEntry<>(itemHighlightBox, item)); + } + + boolean topItem = topGroundItem == item; + + // Draw background if hovering + if (topItem && (mouseInBox || mouseInHiddenBox || mouseInHighlightBox)) + { + backgroundComponent.setRectangle(itemBounds); + backgroundComponent.render(graphics); + } + + // Draw hidden box + drawRectangle(graphics, itemHiddenBox, topItem && mouseInHiddenBox ? Color.RED : color, hidden != null, true); + + // Draw highlight box + drawRectangle(graphics, itemHighlightBox, topItem && mouseInHighlightBox ? Color.GREEN : color, highlighted != null, false); + } + + if (config.toggleOutline()) + { + graphics.setColor(Color.BLACK); + graphics.drawString(itemString, textX + 1, textY + 1); + graphics.drawString(itemString, textX - 1, textY - 1); + graphics.drawString(itemString, textX - 1, textY + 1); + graphics.drawString(itemString, textX + 1, textY - 1); + } + + textComponent.setText(itemString); + textComponent.setColor(color); + textComponent.setPosition(new java.awt.Point(textX, textY)); + textComponent.render(graphics); + } + + return null; + } + + private void drawRectangle(Graphics2D graphics, Rectangle rect, Color color, boolean inList, boolean hiddenBox) + { + graphics.setColor(Color.BLACK); + graphics.drawRect(rect.x + 1, rect.y + 1, rect.width, rect.height); + + graphics.setColor(color); + graphics.draw(rect); + + if (inList) + { + graphics.fill(rect); + } + + graphics.setColor(Color.WHITE); + // Minus symbol + graphics.drawLine + ( + rect.x + 2, + rect.y + (rect.height / 2), + rect.x + rect.width - 2, + rect.y + (rect.height / 2) + ); + + if (!hiddenBox) + { + // Plus symbol + graphics.drawLine + ( + rect.x + (rect.width / 2), + rect.y + 2, + rect.x + (rect.width / 2), + rect.y + rect.height - 2 + ); + } + + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java index a3bf0f37ea..35ee979085 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java @@ -1,680 +1,680 @@ -/* - * Copyright (c) 2017, Aria - * Copyright (c) 2018, Adam - * 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.grounditems; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.LoadingCache; -import com.google.inject.Provides; -import java.awt.Color; -import java.awt.Rectangle; -import static java.lang.Boolean.TRUE; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.Item; -import net.runelite.api.ItemComposition; -import net.runelite.api.ItemID; -import net.runelite.api.ItemLayer; -import net.runelite.api.MenuAction; -import net.runelite.api.MenuEntry; -import net.runelite.api.Node; -import net.runelite.api.Player; -import net.runelite.api.Scene; -import net.runelite.api.Tile; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.ClientTick; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.FocusChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.ItemDespawned; -import net.runelite.api.events.ItemQuantityChanged; -import net.runelite.api.events.ItemSpawned; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.client.Notifier; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.events.NpcLootReceived; -import net.runelite.client.events.PlayerLootReceived; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemStack; -import net.runelite.client.input.KeyManager; -import net.runelite.client.input.MouseManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.OVERLAY; -import net.runelite.client.plugins.grounditems.config.MenuHighlightMode; -import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.BOTH; -import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.NAME; -import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.OPTION; -import net.runelite.client.plugins.grounditems.config.ValueCalculationMode; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.ColorUtil; -import net.runelite.client.util.StackFormatter; -import net.runelite.client.util.Text; - -@PluginDescriptor( - name = "Ground Items", - description = "Highlight ground items and/or show price information", - tags = {"grand", "exchange", "high", "alchemy", "prices", "highlight", "overlay"} -) -public class GroundItemsPlugin extends Plugin -{ - // Used when getting High Alchemy value - multiplied by general store price. - private static final float HIGH_ALCHEMY_CONSTANT = 0.6f; - // ItemID for coins - private static final int COINS = ItemID.COINS_995; - // Ground item menu options - private static final int FIRST_OPTION = MenuAction.GROUND_ITEM_FIRST_OPTION.getId(); - private static final int SECOND_OPTION = MenuAction.GROUND_ITEM_SECOND_OPTION.getId(); - private static final int THIRD_OPTION = MenuAction.GROUND_ITEM_THIRD_OPTION.getId(); // this is Take - private static final int FOURTH_OPTION = MenuAction.GROUND_ITEM_FOURTH_OPTION.getId(); - private static final int FIFTH_OPTION = MenuAction.GROUND_ITEM_FIFTH_OPTION.getId(); - private static final int EXAMINE_ITEM = MenuAction.EXAMINE_ITEM_GROUND.getId(); - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private Map.Entry textBoxBounds; - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private Map.Entry hiddenBoxBounds; - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private Map.Entry highlightBoxBounds; - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private boolean hotKeyPressed; - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private boolean hideAll; - - private List hiddenItemList = new CopyOnWriteArrayList<>(); - private List highlightedItemsList = new CopyOnWriteArrayList<>(); - - @Inject - private GroundItemInputListener inputListener; - - @Inject - private MouseManager mouseManager; - - @Inject - private KeyManager keyManager; - - @Inject - private Client client; - - @Inject - private ItemManager itemManager; - - @Inject - private OverlayManager overlayManager; - - @Inject - private GroundItemsConfig config; - - @Inject - private GroundItemsOverlay overlay; - - @Inject - private Notifier notifier; - - @Getter - public static final Map collectedGroundItems = new LinkedHashMap<>(); - private final Map priceChecks = new LinkedHashMap<>(); - private LoadingCache highlightedItems; - private LoadingCache hiddenItems; - - @Provides - GroundItemsConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(GroundItemsConfig.class); - } - - @Override - protected void startUp() - { - overlayManager.add(overlay); - reset(); - mouseManager.registerMouseListener(inputListener); - keyManager.registerKeyListener(inputListener); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - mouseManager.unregisterMouseListener(inputListener); - keyManager.unregisterKeyListener(inputListener); - highlightedItems.invalidateAll(); - highlightedItems = null; - hiddenItems.invalidateAll(); - hiddenItems = null; - hiddenItemList = null; - highlightedItemsList = null; - collectedGroundItems.clear(); - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("grounditems")) - { - reset(); - } - } - - @Subscribe - public void onGameStateChanged(final GameStateChanged event) - { - if (event.getGameState() == GameState.LOADING) - { - collectedGroundItems.clear(); - } - } - - @Subscribe - public void onItemSpawned(ItemSpawned itemSpawned) - { - Item item = itemSpawned.getItem(); - Tile tile = itemSpawned.getTile(); - - GroundItem groundItem = buildGroundItem(tile, item); - - GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation()); - GroundItem existing = collectedGroundItems.putIfAbsent(groundItemKey, groundItem); - if (existing != null) - { - existing.setQuantity(existing.getQuantity() + groundItem.getQuantity()); - } - - boolean shouldNotify = !config.onlyShowLoot() && config.highlightedColor().equals(getHighlighted( - groundItem.getName(), - groundItem.getGePrice(), - groundItem.getHaPrice())); - - if (config.notifyHighlightedDrops() && shouldNotify) - { - notifyHighlightedItem(groundItem); - } - } - - @Subscribe - public void onItemDespawned(ItemDespawned itemDespawned) - { - Item item = itemDespawned.getItem(); - Tile tile = itemDespawned.getTile(); - - GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation()); - GroundItem groundItem = collectedGroundItems.get(groundItemKey); - if (groundItem == null) - { - return; - } - - if (groundItem.getQuantity() <= item.getQuantity()) - { - collectedGroundItems.remove(groundItemKey); - } - else - { - groundItem.setQuantity(groundItem.getQuantity() - item.getQuantity()); - } - } - - @Subscribe - public void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged) - { - Item item = itemQuantityChanged.getItem(); - Tile tile = itemQuantityChanged.getTile(); - int oldQuantity = itemQuantityChanged.getOldQuantity(); - int newQuantity = itemQuantityChanged.getNewQuantity(); - - int diff = newQuantity - oldQuantity; - GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation()); - GroundItem groundItem = collectedGroundItems.get(groundItemKey); - if (groundItem != null) - { - groundItem.setQuantity(groundItem.getQuantity() + diff); - } - } - - @Subscribe - public void onNpcLootReceived(NpcLootReceived npcLootReceived) - { - Collection items = npcLootReceived.getItems(); - lootReceived(items); - } - - @Subscribe - public void onPlayerLootReceived(PlayerLootReceived playerLootReceived) - { - Collection items = playerLootReceived.getItems(); - lootReceived(items); - } - - @Subscribe - public void onClientTick(ClientTick event) - { - if (!config.collapseEntries()) - { - return; - } - - final MenuEntry[] menuEntries = client.getMenuEntries(); - final List newEntries = new ArrayList<>(menuEntries.length); - - outer: - for (int i = menuEntries.length - 1; i >= 0; i--) - { - MenuEntry menuEntry = menuEntries[i]; - - int menuType = menuEntry.getType(); - if (menuType == FIRST_OPTION || menuType == SECOND_OPTION || menuType == THIRD_OPTION - || menuType == FOURTH_OPTION || menuType == FIFTH_OPTION || menuType == EXAMINE_ITEM) - { - for (MenuEntryWithCount entryWCount : newEntries) - { - if (entryWCount.getEntry().equals(menuEntry)) - { - entryWCount.increment(); - continue outer; - } - } - } - - newEntries.add(new MenuEntryWithCount(menuEntry)); - } - - Collections.reverse(newEntries); - - client.setMenuEntries(newEntries.stream().map(e -> - { - final MenuEntry entry = e.getEntry(); - final int count = e.getCount(); - if (count > 1) - { - entry.setTarget(entry.getTarget() + " x " + count); - } - - return entry; - }).toArray(MenuEntry[]::new)); - } - - private void lootReceived(Collection items) - { - for (ItemStack itemStack : items) - { - WorldPoint location = WorldPoint.fromLocal(client, itemStack.getLocation()); - GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(itemStack.getId(), location); - GroundItem groundItem = collectedGroundItems.get(groundItemKey); - if (groundItem != null) - { - groundItem.setMine(true); - - boolean shouldNotify = config.onlyShowLoot() && config.highlightedColor().equals(getHighlighted( - groundItem.getName(), - groundItem.getGePrice(), - groundItem.getHaPrice())); - - if (config.notifyHighlightedDrops() && shouldNotify) - { - notifyHighlightedItem(groundItem); - } - } - } - } - - private GroundItem buildGroundItem(final Tile tile, final Item item) - { - // Collect the data for the item - final int itemId = item.getId(); - final ItemComposition itemComposition = itemManager.getItemComposition(itemId); - final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId; - final int alchPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT); - - final GroundItem groundItem = GroundItem.builder() - .id(itemId) - .location(tile.getWorldLocation()) - .itemId(realItemId) - .quantity(item.getQuantity()) - .name(itemComposition.getName()) - .haPrice(alchPrice) - .height(tile.getItemLayer().getHeight()) - .tradeable(itemComposition.isTradeable()) - .build(); - - - // Update item price in case it is coins - if (realItemId == COINS) - { - groundItem.setHaPrice(1); - groundItem.setGePrice(1); - } - else - { - groundItem.setGePrice(itemManager.getItemPrice(realItemId)); - } - - return groundItem; - } - - private void reset() - { - // gets the hidden items from the text box in the config - hiddenItemList = Text.fromCSV(config.getHiddenItems()); - - // gets the highlighted items from the text box in the config - highlightedItemsList = Text.fromCSV(config.getHighlightItems()); - - highlightedItems = CacheBuilder.newBuilder() - .maximumSize(512L) - .expireAfterAccess(10, TimeUnit.MINUTES) - .build(new WildcardMatchLoader(highlightedItemsList)); - - hiddenItems = CacheBuilder.newBuilder() - .maximumSize(512L) - .expireAfterAccess(10, TimeUnit.MINUTES) - .build(new WildcardMatchLoader(hiddenItemList)); - - // Cache colors - priceChecks.clear(); - - if (config.insaneValuePrice() > 0) - { - priceChecks.put(config.insaneValuePrice(), config.insaneValueColor()); - } - - if (config.highValuePrice() > 0) - { - priceChecks.put(config.highValuePrice(), config.highValueColor()); - } - - if (config.mediumValuePrice() > 0) - { - priceChecks.put(config.mediumValuePrice(), config.mediumValueColor()); - } - - if (config.lowValuePrice() > 0) - { - priceChecks.put(config.lowValuePrice(), config.lowValueColor()); - } - - if (config.getHighlightOverValue() > 0) - { - priceChecks.put(config.getHighlightOverValue(), config.highlightedColor()); - } - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) - { - if (config.itemHighlightMode() != OVERLAY - && event.getOption().equals("Take") - && event.getType() == THIRD_OPTION) - { - int itemId = event.getIdentifier(); - Scene scene = client.getScene(); - Tile tile = scene.getTiles()[client.getPlane()][event.getActionParam0()][event.getActionParam1()]; - ItemLayer itemLayer = tile.getItemLayer(); - - if (itemLayer == null) - { - return; - } - - MenuEntry[] menuEntries = client.getMenuEntries(); - MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; - - int quantity = 1; - Node current = itemLayer.getBottom(); - - while (current instanceof Item) - { - Item item = (Item) current; - if (item.getId() == itemId) - { - quantity = item.getQuantity(); - } - current = current.getNext(); - } - - final ItemComposition itemComposition = itemManager.getItemComposition(itemId); - final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemComposition.getId(); - final int itemPrice = itemManager.getItemPrice(realItemId); - final int price = itemPrice <= 0 ? itemComposition.getPrice() : itemPrice; - final int haPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT) * quantity; - final int gePrice = quantity * price; - final Color hidden = getHidden(itemComposition.getName(), gePrice, haPrice, itemComposition.isTradeable()); - final Color highlighted = getHighlighted(itemComposition.getName(), gePrice, haPrice); - final Color color = getItemColor(highlighted, hidden); - final boolean canBeRecolored = highlighted != null || (hidden != null && config.recolorMenuHiddenItems()); - - if (color != null && canBeRecolored && !color.equals(config.defaultColor())) - { - final MenuHighlightMode mode = config.menuHighlightMode(); - - if (mode == BOTH || mode == OPTION) - { - lastEntry.setOption(ColorUtil.prependColorTag("Take", color)); - } - - if (mode == BOTH || mode == NAME) - { - String target = lastEntry.getTarget().substring(lastEntry.getTarget().indexOf(">") + 1); - lastEntry.setTarget(ColorUtil.prependColorTag(target, color)); - } - } - - if (config.showMenuItemQuantities() && itemComposition.isStackable() && quantity > 1) - { - lastEntry.setTarget(lastEntry.getTarget() + " (" + quantity + ")"); - } - - if(config.removeIgnored() && event.getOption().equals("Take") && hiddenItemList.contains(Text.removeTags(event.getTarget()))) - { - menuEntries = removeOption(event.getOption(), event.getTarget()); - } - - client.setMenuEntries(menuEntries); - } - } - - private MenuEntry[] removeOption(String option, String target) - { - MenuEntry[] entries = client.getMenuEntries(); - int j = 0; - if(entries.length > 1) - { - MenuEntry[] newEntries = new MenuEntry[entries.length - 1]; - for (int i = 0; i < entries.length; ++i) - { - if (!(entries[i].getOption().equals(option) && entries[i].getTarget().equals(target))) - { - newEntries[j++] = entries[i]; - } - } - - return newEntries; - } - else - { - return entries; - } - - - } - - void updateList(String item, boolean hiddenList) - { - final Set hiddenItemSet = new HashSet<>(hiddenItemList); - final Set highlightedItemSet = new HashSet<>(highlightedItemsList); - - if (hiddenList) - { - highlightedItemSet.removeIf(item::equalsIgnoreCase); - } - else - { - hiddenItemSet.removeIf(item::equalsIgnoreCase); - } - - final Set items = hiddenList ? hiddenItemSet : highlightedItemSet; - - if (!items.removeIf(item::equalsIgnoreCase)) - { - items.add(item); - } - - config.setHiddenItems(Text.toCSV(hiddenItemSet)); - config.setHighlightedItem(Text.toCSV(highlightedItemSet)); - } - - Color getHighlighted(String item, int gePrice, int haPrice) - { - if (TRUE.equals(highlightedItems.getUnchecked(item))) - { - return config.highlightedColor(); - } - - // Explicit hide takes priority over implicit highlight - if (TRUE.equals(hiddenItems.getUnchecked(item))) - { - return null; - } - - ValueCalculationMode mode = config.valueCalculationMode(); - for (Map.Entry entry : priceChecks.entrySet()) - { - switch (mode) - { - case GE: - if (gePrice > entry.getKey()) - { - return entry.getValue(); - } - break; - case HA: - if (haPrice > entry.getKey()) - { - return entry.getValue(); - } - break; - default: // case HIGHEST - if (gePrice > entry.getKey() || haPrice > entry.getKey()) - { - return entry.getValue(); - } - break; - } - } - - return null; - } - - Color getHidden(String item, int gePrice, int haPrice, boolean isTradeable) - { - final boolean isExplicitHidden = TRUE.equals(hiddenItems.getUnchecked(item)); - final boolean isExplicitHighlight = TRUE.equals(highlightedItems.getUnchecked(item)); - final boolean canBeHidden = gePrice > 0 || isTradeable || !config.dontHideUntradeables(); - final boolean underGe = gePrice < config.getHideUnderValue(); - final boolean underHa = haPrice < config.getHideUnderValue(); - - // Explicit highlight takes priority over implicit hide - return isExplicitHidden || (!isExplicitHighlight && canBeHidden && underGe && underHa) - ? config.hiddenColor() - : null; - } - - Color getItemColor(Color highlighted, Color hidden) - { - if (highlighted != null) - { - return highlighted; - } - - if (hidden != null) - { - return hidden; - } - - return config.defaultColor(); - } - - @Subscribe - public void onFocusChanged(FocusChanged focusChanged) - { - if (!focusChanged.isFocused()) - { - setHotKeyPressed(false); - } - } - - private void notifyHighlightedItem(GroundItem item) - { - final Player local = client.getLocalPlayer(); - final StringBuilder notificationStringBuilder = new StringBuilder() - .append("[") - .append(local.getName()) - .append("] received a highlighted drop: ") - .append(item.getName()); - - if (item.getQuantity() > 1) - { - notificationStringBuilder.append(" x ").append(item.getQuantity()); - - - if (item.getQuantity() > (int) Character.MAX_VALUE) - { - notificationStringBuilder.append(" (Lots!)"); - } - else - { - notificationStringBuilder.append(" (") - .append(StackFormatter.quantityToStackSize(item.getQuantity())) - .append(")"); - } - } - - notificationStringBuilder.append("!"); - notifier.notify(notificationStringBuilder.toString()); - } -} +/* + * Copyright (c) 2017, Aria + * Copyright (c) 2018, Adam + * 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.grounditems; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.LoadingCache; +import com.google.inject.Provides; +import java.awt.Color; +import java.awt.Rectangle; +import static java.lang.Boolean.TRUE; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Item; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemID; +import net.runelite.api.ItemLayer; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.Node; +import net.runelite.api.Player; +import net.runelite.api.Scene; +import net.runelite.api.Tile; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ClientTick; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.ItemDespawned; +import net.runelite.api.events.ItemQuantityChanged; +import net.runelite.api.events.ItemSpawned; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.NpcLootReceived; +import net.runelite.client.events.PlayerLootReceived; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemStack; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.OVERLAY; +import net.runelite.client.plugins.grounditems.config.MenuHighlightMode; +import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.BOTH; +import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.NAME; +import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.OPTION; +import net.runelite.client.plugins.grounditems.config.ValueCalculationMode; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.StackFormatter; +import net.runelite.client.util.Text; + +@PluginDescriptor( + name = "Ground Items", + description = "Highlight ground items and/or show price information", + tags = {"grand", "exchange", "high", "alchemy", "prices", "highlight", "overlay"} +) +public class GroundItemsPlugin extends Plugin +{ + // Used when getting High Alchemy value - multiplied by general store price. + private static final float HIGH_ALCHEMY_CONSTANT = 0.6f; + // ItemID for coins + private static final int COINS = ItemID.COINS_995; + // Ground item menu options + private static final int FIRST_OPTION = MenuAction.GROUND_ITEM_FIRST_OPTION.getId(); + private static final int SECOND_OPTION = MenuAction.GROUND_ITEM_SECOND_OPTION.getId(); + private static final int THIRD_OPTION = MenuAction.GROUND_ITEM_THIRD_OPTION.getId(); // this is Take + private static final int FOURTH_OPTION = MenuAction.GROUND_ITEM_FOURTH_OPTION.getId(); + private static final int FIFTH_OPTION = MenuAction.GROUND_ITEM_FIFTH_OPTION.getId(); + private static final int EXAMINE_ITEM = MenuAction.EXAMINE_ITEM_GROUND.getId(); + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private Map.Entry textBoxBounds; + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private Map.Entry hiddenBoxBounds; + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private Map.Entry highlightBoxBounds; + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean hotKeyPressed; + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean hideAll; + + private List hiddenItemList = new CopyOnWriteArrayList<>(); + private List highlightedItemsList = new CopyOnWriteArrayList<>(); + + @Inject + private GroundItemInputListener inputListener; + + @Inject + private MouseManager mouseManager; + + @Inject + private KeyManager keyManager; + + @Inject + private Client client; + + @Inject + private ItemManager itemManager; + + @Inject + private OverlayManager overlayManager; + + @Inject + private GroundItemsConfig config; + + @Inject + private GroundItemsOverlay overlay; + + @Inject + private Notifier notifier; + + @Getter + public static final Map collectedGroundItems = new LinkedHashMap<>(); + private final Map priceChecks = new LinkedHashMap<>(); + private LoadingCache highlightedItems; + private LoadingCache hiddenItems; + + @Provides + GroundItemsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(GroundItemsConfig.class); + } + + @Override + protected void startUp() + { + overlayManager.add(overlay); + reset(); + mouseManager.registerMouseListener(inputListener); + keyManager.registerKeyListener(inputListener); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + mouseManager.unregisterMouseListener(inputListener); + keyManager.unregisterKeyListener(inputListener); + highlightedItems.invalidateAll(); + highlightedItems = null; + hiddenItems.invalidateAll(); + hiddenItems = null; + hiddenItemList = null; + highlightedItemsList = null; + collectedGroundItems.clear(); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("grounditems")) + { + reset(); + } + } + + @Subscribe + public void onGameStateChanged(final GameStateChanged event) + { + if (event.getGameState() == GameState.LOADING) + { + collectedGroundItems.clear(); + } + } + + @Subscribe + public void onItemSpawned(ItemSpawned itemSpawned) + { + Item item = itemSpawned.getItem(); + Tile tile = itemSpawned.getTile(); + + GroundItem groundItem = buildGroundItem(tile, item); + + GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation()); + GroundItem existing = collectedGroundItems.putIfAbsent(groundItemKey, groundItem); + if (existing != null) + { + existing.setQuantity(existing.getQuantity() + groundItem.getQuantity()); + } + + boolean shouldNotify = !config.onlyShowLoot() && config.highlightedColor().equals(getHighlighted( + groundItem.getName(), + groundItem.getGePrice(), + groundItem.getHaPrice())); + + if (config.notifyHighlightedDrops() && shouldNotify) + { + notifyHighlightedItem(groundItem); + } + } + + @Subscribe + public void onItemDespawned(ItemDespawned itemDespawned) + { + Item item = itemDespawned.getItem(); + Tile tile = itemDespawned.getTile(); + + GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation()); + GroundItem groundItem = collectedGroundItems.get(groundItemKey); + if (groundItem == null) + { + return; + } + + if (groundItem.getQuantity() <= item.getQuantity()) + { + collectedGroundItems.remove(groundItemKey); + } + else + { + groundItem.setQuantity(groundItem.getQuantity() - item.getQuantity()); + } + } + + @Subscribe + public void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged) + { + Item item = itemQuantityChanged.getItem(); + Tile tile = itemQuantityChanged.getTile(); + int oldQuantity = itemQuantityChanged.getOldQuantity(); + int newQuantity = itemQuantityChanged.getNewQuantity(); + + int diff = newQuantity - oldQuantity; + GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation()); + GroundItem groundItem = collectedGroundItems.get(groundItemKey); + if (groundItem != null) + { + groundItem.setQuantity(groundItem.getQuantity() + diff); + } + } + + @Subscribe + public void onNpcLootReceived(NpcLootReceived npcLootReceived) + { + Collection items = npcLootReceived.getItems(); + lootReceived(items); + } + + @Subscribe + public void onPlayerLootReceived(PlayerLootReceived playerLootReceived) + { + Collection items = playerLootReceived.getItems(); + lootReceived(items); + } + + @Subscribe + public void onClientTick(ClientTick event) + { + if (!config.collapseEntries()) + { + return; + } + + final MenuEntry[] menuEntries = client.getMenuEntries(); + final List newEntries = new ArrayList<>(menuEntries.length); + + outer: + for (int i = menuEntries.length - 1; i >= 0; i--) + { + MenuEntry menuEntry = menuEntries[i]; + + int menuType = menuEntry.getType(); + if (menuType == FIRST_OPTION || menuType == SECOND_OPTION || menuType == THIRD_OPTION + || menuType == FOURTH_OPTION || menuType == FIFTH_OPTION || menuType == EXAMINE_ITEM) + { + for (MenuEntryWithCount entryWCount : newEntries) + { + if (entryWCount.getEntry().equals(menuEntry)) + { + entryWCount.increment(); + continue outer; + } + } + } + + newEntries.add(new MenuEntryWithCount(menuEntry)); + } + + Collections.reverse(newEntries); + + client.setMenuEntries(newEntries.stream().map(e -> + { + final MenuEntry entry = e.getEntry(); + final int count = e.getCount(); + if (count > 1) + { + entry.setTarget(entry.getTarget() + " x " + count); + } + + return entry; + }).toArray(MenuEntry[]::new)); + } + + private void lootReceived(Collection items) + { + for (ItemStack itemStack : items) + { + WorldPoint location = WorldPoint.fromLocal(client, itemStack.getLocation()); + GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(itemStack.getId(), location); + GroundItem groundItem = collectedGroundItems.get(groundItemKey); + if (groundItem != null) + { + groundItem.setMine(true); + + boolean shouldNotify = config.onlyShowLoot() && config.highlightedColor().equals(getHighlighted( + groundItem.getName(), + groundItem.getGePrice(), + groundItem.getHaPrice())); + + if (config.notifyHighlightedDrops() && shouldNotify) + { + notifyHighlightedItem(groundItem); + } + } + } + } + + private GroundItem buildGroundItem(final Tile tile, final Item item) + { + // Collect the data for the item + final int itemId = item.getId(); + final ItemComposition itemComposition = itemManager.getItemComposition(itemId); + final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId; + final int alchPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT); + + final GroundItem groundItem = GroundItem.builder() + .id(itemId) + .location(tile.getWorldLocation()) + .itemId(realItemId) + .quantity(item.getQuantity()) + .name(itemComposition.getName()) + .haPrice(alchPrice) + .height(tile.getItemLayer().getHeight()) + .tradeable(itemComposition.isTradeable()) + .build(); + + + // Update item price in case it is coins + if (realItemId == COINS) + { + groundItem.setHaPrice(1); + groundItem.setGePrice(1); + } + else + { + groundItem.setGePrice(itemManager.getItemPrice(realItemId)); + } + + return groundItem; + } + + private void reset() + { + // gets the hidden items from the text box in the config + hiddenItemList = Text.fromCSV(config.getHiddenItems()); + + // gets the highlighted items from the text box in the config + highlightedItemsList = Text.fromCSV(config.getHighlightItems()); + + highlightedItems = CacheBuilder.newBuilder() + .maximumSize(512L) + .expireAfterAccess(10, TimeUnit.MINUTES) + .build(new WildcardMatchLoader(highlightedItemsList)); + + hiddenItems = CacheBuilder.newBuilder() + .maximumSize(512L) + .expireAfterAccess(10, TimeUnit.MINUTES) + .build(new WildcardMatchLoader(hiddenItemList)); + + // Cache colors + priceChecks.clear(); + + if (config.insaneValuePrice() > 0) + { + priceChecks.put(config.insaneValuePrice(), config.insaneValueColor()); + } + + if (config.highValuePrice() > 0) + { + priceChecks.put(config.highValuePrice(), config.highValueColor()); + } + + if (config.mediumValuePrice() > 0) + { + priceChecks.put(config.mediumValuePrice(), config.mediumValueColor()); + } + + if (config.lowValuePrice() > 0) + { + priceChecks.put(config.lowValuePrice(), config.lowValueColor()); + } + + if (config.getHighlightOverValue() > 0) + { + priceChecks.put(config.getHighlightOverValue(), config.highlightedColor()); + } + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + if (config.itemHighlightMode() != OVERLAY + && event.getOption().equals("Take") + && event.getType() == THIRD_OPTION) + { + int itemId = event.getIdentifier(); + Scene scene = client.getScene(); + Tile tile = scene.getTiles()[client.getPlane()][event.getActionParam0()][event.getActionParam1()]; + ItemLayer itemLayer = tile.getItemLayer(); + + if (itemLayer == null) + { + return; + } + + MenuEntry[] menuEntries = client.getMenuEntries(); + MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; + + int quantity = 1; + Node current = itemLayer.getBottom(); + + while (current instanceof Item) + { + Item item = (Item) current; + if (item.getId() == itemId) + { + quantity = item.getQuantity(); + } + current = current.getNext(); + } + + final ItemComposition itemComposition = itemManager.getItemComposition(itemId); + final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemComposition.getId(); + final int itemPrice = itemManager.getItemPrice(realItemId); + final int price = itemPrice <= 0 ? itemComposition.getPrice() : itemPrice; + final int haPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT) * quantity; + final int gePrice = quantity * price; + final Color hidden = getHidden(itemComposition.getName(), gePrice, haPrice, itemComposition.isTradeable()); + final Color highlighted = getHighlighted(itemComposition.getName(), gePrice, haPrice); + final Color color = getItemColor(highlighted, hidden); + final boolean canBeRecolored = highlighted != null || (hidden != null && config.recolorMenuHiddenItems()); + + if (color != null && canBeRecolored && !color.equals(config.defaultColor())) + { + final MenuHighlightMode mode = config.menuHighlightMode(); + + if (mode == BOTH || mode == OPTION) + { + lastEntry.setOption(ColorUtil.prependColorTag("Take", color)); + } + + if (mode == BOTH || mode == NAME) + { + String target = lastEntry.getTarget().substring(lastEntry.getTarget().indexOf(">") + 1); + lastEntry.setTarget(ColorUtil.prependColorTag(target, color)); + } + } + + if (config.showMenuItemQuantities() && itemComposition.isStackable() && quantity > 1) + { + lastEntry.setTarget(lastEntry.getTarget() + " (" + quantity + ")"); + } + + if (config.removeIgnored() && event.getOption().equals("Take") && hiddenItemList.contains(Text.removeTags(event.getTarget()))) + { + menuEntries = removeOption(event.getOption(), event.getTarget()); + } + + client.setMenuEntries(menuEntries); + } + } + + private MenuEntry[] removeOption(String option, String target) + { + MenuEntry[] entries = client.getMenuEntries(); + int j = 0; + if (entries.length > 1) + { + MenuEntry[] newEntries = new MenuEntry[entries.length - 1]; + for (int i = 0; i < entries.length; ++i) + { + if (!(entries[i].getOption().equals(option) && entries[i].getTarget().equals(target))) + { + newEntries[j++] = entries[i]; + } + } + + return newEntries; + } + else + { + return entries; + } + + + } + + void updateList(String item, boolean hiddenList) + { + final Set hiddenItemSet = new HashSet<>(hiddenItemList); + final Set highlightedItemSet = new HashSet<>(highlightedItemsList); + + if (hiddenList) + { + highlightedItemSet.removeIf(item::equalsIgnoreCase); + } + else + { + hiddenItemSet.removeIf(item::equalsIgnoreCase); + } + + final Set items = hiddenList ? hiddenItemSet : highlightedItemSet; + + if (!items.removeIf(item::equalsIgnoreCase)) + { + items.add(item); + } + + config.setHiddenItems(Text.toCSV(hiddenItemSet)); + config.setHighlightedItem(Text.toCSV(highlightedItemSet)); + } + + Color getHighlighted(String item, int gePrice, int haPrice) + { + if (TRUE.equals(highlightedItems.getUnchecked(item))) + { + return config.highlightedColor(); + } + + // Explicit hide takes priority over implicit highlight + if (TRUE.equals(hiddenItems.getUnchecked(item))) + { + return null; + } + + ValueCalculationMode mode = config.valueCalculationMode(); + for (Map.Entry entry : priceChecks.entrySet()) + { + switch (mode) + { + case GE: + if (gePrice > entry.getKey()) + { + return entry.getValue(); + } + break; + case HA: + if (haPrice > entry.getKey()) + { + return entry.getValue(); + } + break; + default: // case HIGHEST + if (gePrice > entry.getKey() || haPrice > entry.getKey()) + { + return entry.getValue(); + } + break; + } + } + + return null; + } + + Color getHidden(String item, int gePrice, int haPrice, boolean isTradeable) + { + final boolean isExplicitHidden = TRUE.equals(hiddenItems.getUnchecked(item)); + final boolean isExplicitHighlight = TRUE.equals(highlightedItems.getUnchecked(item)); + final boolean canBeHidden = gePrice > 0 || isTradeable || !config.dontHideUntradeables(); + final boolean underGe = gePrice < config.getHideUnderValue(); + final boolean underHa = haPrice < config.getHideUnderValue(); + + // Explicit highlight takes priority over implicit hide + return isExplicitHidden || (!isExplicitHighlight && canBeHidden && underGe && underHa) + ? config.hiddenColor() + : null; + } + + Color getItemColor(Color highlighted, Color hidden) + { + if (highlighted != null) + { + return highlighted; + } + + if (hidden != null) + { + return hidden; + } + + return config.defaultColor(); + } + + @Subscribe + public void onFocusChanged(FocusChanged focusChanged) + { + if (!focusChanged.isFocused()) + { + setHotKeyPressed(false); + } + } + + private void notifyHighlightedItem(GroundItem item) + { + final Player local = client.getLocalPlayer(); + final StringBuilder notificationStringBuilder = new StringBuilder() + .append("[") + .append(local.getName()) + .append("] received a highlighted drop: ") + .append(item.getName()); + + if (item.getQuantity() > 1) + { + notificationStringBuilder.append(" x ").append(item.getQuantity()); + + + if (item.getQuantity() > (int) Character.MAX_VALUE) + { + notificationStringBuilder.append(" (Lots!)"); + } + else + { + notificationStringBuilder.append(" (") + .append(StackFormatter.quantityToStackSize(item.getQuantity())) + .append(")"); + } + } + + notificationStringBuilder.append("!"); + notifier.notify(notificationStringBuilder.toString()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index 88f88560a5..02ccf85756 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -1,285 +1,287 @@ -/* - * Copyright (c) 2018, TheLonelyDev - * Copyright (c) 2018, Adam - * 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.groundmarkers; - -import com.google.common.base.Strings; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.google.inject.Provides; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.MenuAction; -import net.runelite.api.MenuEntry; -import net.runelite.api.Tile; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.FocusChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.events.MenuOptionClicked; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -@Slf4j -@PluginDescriptor( - name = "Ground Markers", - description = "Enable marking of tiles using the Shift key", - tags = {"overlay", "tiles"} -) -public class GroundMarkerPlugin extends Plugin -{ - private static final String CONFIG_GROUP = "groundMarker"; - private static final String MARK = "Mark tile"; - private static final String WALK_HERE = "Walk here"; - private static final String REGION_PREFIX = "region_"; - - private static final Gson GSON = new Gson(); - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private boolean hotKeyPressed; - - @Getter(AccessLevel.PACKAGE) - private final List points = new ArrayList<>(); - - @Inject - private Client client; - - @Inject - private GroundMarkerConfig config; - - @Inject - private GroundMarkerInputListener inputListener; - - @Inject - private ConfigManager configManager; - - @Inject - private OverlayManager overlayManager; - - @Inject - private GroundMarkerOverlay overlay; - - @Inject - private GroundMarkerMinimapOverlay minimapOverlay; - - @Inject - private KeyManager keyManager; - - private void savePoints(int regionId, Collection points) - { - if (points == null || points.isEmpty()) - { - configManager.unsetConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId); - return; - } - - String json = GSON.toJson(points); - configManager.setConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId, json); - } - - private Collection getPoints(int regionId) - { - String json = configManager.getConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId); - if (Strings.isNullOrEmpty(json)) - { - return Collections.emptyList(); - } - - // CHECKSTYLE:OFF - return GSON.fromJson(json, new TypeToken>(){}.getType()); - // CHECKSTYLE:ON - } - - @Provides - GroundMarkerConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(GroundMarkerConfig.class); - } - - private void loadPoints() - { - points.clear(); - - int[] regions = client.getMapRegions(); - - if (regions == null) - { - return; - } - - for (int regionId : regions) - { - // load points for region - log.debug("Loading points for region {}", regionId); - Collection regionPoints = getPoints(regionId); - Collection colorTileMarkers = translateToColorTileMarker(regionPoints); - points.addAll(colorTileMarkers); - } - } - - /** - * Translate a collection of ground marker points to color tile markers, accounting for instances - * - * @param points {@link GroundMarkerPoint}s to be converted to {@link ColorTileMarker}s - * @return A collection of color tile markers, converted from the passed ground marker points, accounting for local - * instance points. See {@link WorldPoint#toLocalInstance(Client, WorldPoint)} - */ - private Collection translateToColorTileMarker(Collection points) - { - if (points.isEmpty()) - { - return Collections.emptyList(); - } - - return points.stream() - .map(point -> new ColorTileMarker( - WorldPoint.fromRegion(point.getRegionId(), point.getRegionX(), point.getRegionY(), point.getZ()), - point.getColor())) - .flatMap(colorTile -> - { - final Collection localWorldPoints = WorldPoint.toLocalInstance(client, colorTile.getWorldPoint()); - return localWorldPoints.stream().map(wp -> new ColorTileMarker(wp, colorTile.getColor())); - }) - .collect(Collectors.toList()); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged gameStateChanged) - { - if (gameStateChanged.getGameState() != GameState.LOGGED_IN) - { - return; - } - - // map region has just been updated - loadPoints(); - } - - @Subscribe - public void onFocusChanged(FocusChanged focusChanged) - { - if (!focusChanged.isFocused()) - { - hotKeyPressed = false; - } - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) - { - if (hotKeyPressed && event.getOption().equals(WALK_HERE)) - { - MenuEntry[] menuEntries = client.getMenuEntries(); - menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); - - MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - - menuEntry.setOption(MARK); - menuEntry.setTarget(event.getTarget()); - menuEntry.setType(MenuAction.CANCEL.getId()); - - client.setMenuEntries(menuEntries); - } - } - - @Subscribe - public void onMenuOptionClicked(MenuOptionClicked event) - { - if (!event.getMenuOption().equals(MARK)) - { - return; - } - - Tile target = client.getSelectedSceneTile(); - if (target == null) - { - return; - } - markTile(target.getLocalLocation()); - } - - @Override - protected void startUp() - { - overlayManager.add(overlay); - overlayManager.add(minimapOverlay); - keyManager.registerKeyListener(inputListener); - loadPoints(); - } - - @Override - protected void shutDown() - { - overlayManager.remove(overlay); - overlayManager.remove(minimapOverlay); - keyManager.unregisterKeyListener(inputListener); - points.clear(); - } - - private void markTile(LocalPoint localPoint) - { - if (localPoint == null) - { - return; - } - - WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, localPoint); - - int regionId = worldPoint.getRegionID(); - GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), config.markerColor()); - log.debug("Updating point: {} - {}", point, worldPoint); - - List groundMarkerPoints = new ArrayList<>(getPoints(regionId)); - if (groundMarkerPoints.contains(point)) - { - groundMarkerPoints.remove(point); - } - else - { - groundMarkerPoints.add(point); - } - - savePoints(regionId, groundMarkerPoints); - - loadPoints(); - } -} +/* + * Copyright (c) 2018, TheLonelyDev + * Copyright (c) 2018, Adam + * 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.groundmarkers; + +import com.google.common.base.Strings; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.inject.Provides; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.Tile; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +@Slf4j +@PluginDescriptor( + name = "Ground Markers", + description = "Enable marking of tiles using the Shift key", + tags = {"overlay", "tiles"} +) +public class GroundMarkerPlugin extends Plugin +{ + private static final String CONFIG_GROUP = "groundMarker"; + private static final String MARK = "Mark tile"; + private static final String WALK_HERE = "Walk here"; + private static final String REGION_PREFIX = "region_"; + + private static final Gson GSON = new Gson(); + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean hotKeyPressed; + + @Getter(AccessLevel.PACKAGE) + private final List points = new ArrayList<>(); + + @Inject + private Client client; + + @Inject + private GroundMarkerConfig config; + + @Inject + private GroundMarkerInputListener inputListener; + + @Inject + private ConfigManager configManager; + + @Inject + private OverlayManager overlayManager; + + @Inject + private GroundMarkerOverlay overlay; + + @Inject + private GroundMarkerMinimapOverlay minimapOverlay; + + @Inject + private KeyManager keyManager; + + private void savePoints(int regionId, Collection points) + { + if (points == null || points.isEmpty()) + { + configManager.unsetConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId); + return; + } + + String json = GSON.toJson(points); + configManager.setConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId, json); + } + + private Collection getPoints(int regionId) + { + String json = configManager.getConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId); + if (Strings.isNullOrEmpty(json)) + { + return Collections.emptyList(); + } + + // CHECKSTYLE:OFF + return GSON.fromJson(json, new TypeToken>() + { + }.getType()); + // CHECKSTYLE:ON + } + + @Provides + GroundMarkerConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(GroundMarkerConfig.class); + } + + private void loadPoints() + { + points.clear(); + + int[] regions = client.getMapRegions(); + + if (regions == null) + { + return; + } + + for (int regionId : regions) + { + // load points for region + log.debug("Loading points for region {}", regionId); + Collection regionPoints = getPoints(regionId); + Collection colorTileMarkers = translateToColorTileMarker(regionPoints); + points.addAll(colorTileMarkers); + } + } + + /** + * Translate a collection of ground marker points to color tile markers, accounting for instances + * + * @param points {@link GroundMarkerPoint}s to be converted to {@link ColorTileMarker}s + * @return A collection of color tile markers, converted from the passed ground marker points, accounting for local + * instance points. See {@link WorldPoint#toLocalInstance(Client, WorldPoint)} + */ + private Collection translateToColorTileMarker(Collection points) + { + if (points.isEmpty()) + { + return Collections.emptyList(); + } + + return points.stream() + .map(point -> new ColorTileMarker( + WorldPoint.fromRegion(point.getRegionId(), point.getRegionX(), point.getRegionY(), point.getZ()), + point.getColor())) + .flatMap(colorTile -> + { + final Collection localWorldPoints = WorldPoint.toLocalInstance(client, colorTile.getWorldPoint()); + return localWorldPoints.stream().map(wp -> new ColorTileMarker(wp, colorTile.getColor())); + }) + .collect(Collectors.toList()); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + if (gameStateChanged.getGameState() != GameState.LOGGED_IN) + { + return; + } + + // map region has just been updated + loadPoints(); + } + + @Subscribe + public void onFocusChanged(FocusChanged focusChanged) + { + if (!focusChanged.isFocused()) + { + hotKeyPressed = false; + } + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + if (hotKeyPressed && event.getOption().equals(WALK_HERE)) + { + MenuEntry[] menuEntries = client.getMenuEntries(); + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); + + MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); + + menuEntry.setOption(MARK); + menuEntry.setTarget(event.getTarget()); + menuEntry.setType(MenuAction.CANCEL.getId()); + + client.setMenuEntries(menuEntries); + } + } + + @Subscribe + public void onMenuOptionClicked(MenuOptionClicked event) + { + if (!event.getMenuOption().equals(MARK)) + { + return; + } + + Tile target = client.getSelectedSceneTile(); + if (target == null) + { + return; + } + markTile(target.getLocalLocation()); + } + + @Override + protected void startUp() + { + overlayManager.add(overlay); + overlayManager.add(minimapOverlay); + keyManager.registerKeyListener(inputListener); + loadPoints(); + } + + @Override + protected void shutDown() + { + overlayManager.remove(overlay); + overlayManager.remove(minimapOverlay); + keyManager.unregisterKeyListener(inputListener); + points.clear(); + } + + private void markTile(LocalPoint localPoint) + { + if (localPoint == null) + { + return; + } + + WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, localPoint); + + int regionId = worldPoint.getRegionID(); + GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), config.markerColor()); + log.debug("Updating point: {} - {}", point, worldPoint); + + List groundMarkerPoints = new ArrayList<>(getPoints(regionId)); + if (groundMarkerPoints.contains(point)) + { + groundMarkerPoints.remove(point); + } + else + { + groundMarkerPoints.add(point); + } + + savePoints(regionId, groundMarkerPoints); + + loadPoints(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java index 3e10a654c0..53dce275ff 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2018, TheLonelyDev - * Copyright (c) 2018, Adam - * 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.groundmarkers; - -import java.awt.Color; -import lombok.EqualsAndHashCode; -import lombok.Value; - -/** - * Used for serialization of ground marker points. - */ -@Value -@EqualsAndHashCode(exclude = { "color" }) -class GroundMarkerPoint -{ - private int regionId; - private int regionX; - private int regionY; - private int z; - private Color color; -} +/* + * Copyright (c) 2018, TheLonelyDev + * Copyright (c) 2018, Adam + * 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.groundmarkers; + +import java.awt.Color; +import lombok.EqualsAndHashCode; +import lombok.Value; + +/** + * Used for serialization of ground marker points. + */ +@Value +@EqualsAndHashCode(exclude = {"color"}) +class GroundMarkerPoint +{ + private int regionId; + private int regionX; + private int regionY; + private int z; + private Color color; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java index 83e59c19a4..a5d6e40fb1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarPlugin.java @@ -1,355 +1,355 @@ -/* - * Copyright (c) 2017, Tyler - * 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.herbiboars; - -import com.google.inject.Provides; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.inject.Inject; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.Client; -import static net.runelite.api.ObjectID.DRIFTWOOD_30523; -import static net.runelite.api.ObjectID.MUSHROOM_30520; -import static net.runelite.api.ObjectID.ROCK_30519; -import static net.runelite.api.ObjectID.ROCK_30521; -import static net.runelite.api.ObjectID.ROCK_30522; -import net.runelite.api.Tile; -import net.runelite.api.TileObject; -import net.runelite.api.Varbits; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.GameObjectChanged; -import net.runelite.api.events.GameObjectDespawned; -import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GroundObjectChanged; -import net.runelite.api.events.GroundObjectDespawned; -import net.runelite.api.events.GroundObjectSpawned; -import net.runelite.api.events.VarbitChanged; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "Herbiboar", - description = "Highlight starting rocks, trails, and the objects to search at the end of each trail", - tags = {"herblore", "hunter", "skilling", "overlay"} -) -public class HerbiboarPlugin extends Plugin -{ - private static final List END_LOCATIONS = Arrays.asList( - new WorldPoint(3693, 3798, 0), - new WorldPoint(3702, 3808, 0), - new WorldPoint(3703, 3826, 0), - new WorldPoint(3710, 3881, 0), - new WorldPoint(3700, 3877, 0), - new WorldPoint(3715, 3840, 0), - new WorldPoint(3751, 3849, 0), - new WorldPoint(3685, 3869, 0), - new WorldPoint(3681, 3863, 0) - ); - - private static final List START_OBJECT_IDS = Arrays.asList( - ROCK_30519, - MUSHROOM_30520, - ROCK_30521, - ROCK_30522, - DRIFTWOOD_30523 - ); - - private static final int[] HERBIBOAR_REGIONS = { - 14652, - 14651, - 14908, - 14907 - }; - - @Inject - private Client client; - - @Inject - private OverlayManager overlayManager; - - @Inject - private HerbiboarOverlay overlay; - - @Inject - private HerbiboarMinimapOverlay minimapOverlay; - - @Getter - private boolean inHerbiboarArea; - - @Getter - private Map trails = new HashMap<>(); - - @Getter - private Map tunnels = new HashMap<>(); - - @Getter - private Map starts = new HashMap<>(); - - @Getter - private Map trailObjects = new HashMap<>(); - - @Getter - @Setter - private Set shownTrails = new HashSet<>(); - - @Getter - @Setter - private HerbiboarTrail currentTrail; - - @Getter - @Setter - private int currentPath; - - @Getter - @Setter - private int finishId; - - @Provides - HerbiboarConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(HerbiboarConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - overlayManager.add(minimapOverlay); - inHerbiboarArea = checkArea(); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - overlayManager.remove(minimapOverlay); - } - - private void updateTrailData() - { - currentTrail = null; - currentPath = -1; - - // Get trail data - for (HerbiboarTrail trail : HerbiboarTrail.values()) - { - int trailId = trail.getTrailId(); - int value = client.getVar(trail.getVarbit()); - - if (value > 0) - { - shownTrails.add(trailId); - shownTrails.add(trailId + 1); - } - if (value == 1 || value == 2) - { - currentTrail = trail; - currentPath = value; - } - } - - // Get finish data - finishId = client.getVar(Varbits.HB_FINISH); - if (finishId > 0 && currentTrail != null) - { - shownTrails.add(currentTrail.getTrailId()); - shownTrails.add(currentTrail.getTrailId() + 1); - currentTrail = null; - currentPath = -1; - } - - int started = client.getVar(Varbits.HB_STARTED); - if (currentPath == -1 && finishId == 0 && started == 0) - { - resetTrailData(); - } - } - - private void resetTrailData() - { - currentPath = 0; - currentTrail = null; - finishId = 0; - shownTrails.clear(); - } - - private void clearCache() - { - starts.clear(); - trailObjects.clear(); - trails.clear(); - tunnels.clear(); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - switch (event.getGameState()) - { - case HOPPING: - case LOGGING_IN: - resetTrailData(); - break; - case LOADING: - clearCache(); - inHerbiboarArea = checkArea(); - break; - default: - break; - } - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - if (isInHerbiboarArea()) - { - updateTrailData(); - } - } - - @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) - { - onGameObject(event.getTile(), null, event.getGameObject()); - } - - @Subscribe - public void onGameObjectChanged(GameObjectChanged event) - { - onGameObject(event.getTile(), event.getPrevious(), event.getGameObject()); - } - - @Subscribe - public void onGameObjectDespawned(GameObjectDespawned event) - { - onGameObject(event.getTile(), event.getGameObject(), null); - } - - @Subscribe - public void onGroundObjectSpawned(GroundObjectSpawned event) - { - onGroundObject(event.getTile(), null, event.getGroundObject()); - } - - @Subscribe - public void onGroundObjectChanged(GroundObjectChanged event) - { - onGroundObject(event.getTile(), event.getPrevious(), event.getGroundObject()); - } - - @Subscribe - public void onGroundObjectDespawned(GroundObjectDespawned event) - { - onGroundObject(event.getTile(), event.getGroundObject(), null); - } - - // Store relevant GameObjects (starts, objects used to trigger next trails, and some tunnels) - private void onGameObject(Tile tile, TileObject oldObject, TileObject newObject) - { - if (oldObject != null) - { - WorldPoint oldLocation = oldObject.getWorldLocation(); - trailObjects.remove(oldLocation); - tunnels.remove(oldLocation); - starts.remove(oldLocation); - } - - if (newObject == null) - { - return; - } - - // Starts - if (START_OBJECT_IDS.contains(newObject.getId())) - { - starts.put(newObject.getWorldLocation(), newObject); - return; - } - - // GameObject to trigger next trail (mushrooms, mud, seaweed, etc) - if (HerbiboarTrail.getAllObjectLocs().contains(newObject.getWorldLocation())) - { - trailObjects.put(newObject.getWorldLocation(), newObject); - return; - } - - // Herbiboar tunnel - if (END_LOCATIONS.contains(newObject.getWorldLocation())) - { - tunnels.put(newObject.getWorldLocation(), newObject); - } - } - - // Store relevant GroundObjects (tracks on trails, and some tunnels) - private void onGroundObject(Tile tile, TileObject oldObject, TileObject newObject) - { - if (oldObject != null) - { - WorldPoint oldLocation = oldObject.getWorldLocation(); - trails.remove(oldLocation); - tunnels.remove(oldLocation); - } - - if (newObject == null) - { - return; - } - - //Trails - if (HerbiboarTrail.getTrailIds().contains(newObject.getId())) - { - trails.put(newObject.getWorldLocation(), newObject); - return; - } - - //Herbiboar tunnel - if (END_LOCATIONS.contains(newObject.getWorldLocation())) - { - tunnels.put(newObject.getWorldLocation(), newObject); - } - } - - private boolean checkArea() - { - return client.getMapRegions() != null && Arrays.stream(client.getMapRegions()) - .filter(x -> Arrays.stream(HERBIBOAR_REGIONS).anyMatch(y -> y == x)) - .toArray().length > 0; - } - - public List getEndLocations() - { - return END_LOCATIONS; - } -} +/* + * Copyright (c) 2017, Tyler + * 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.herbiboars; + +import com.google.inject.Provides; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.inject.Inject; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Client; +import static net.runelite.api.ObjectID.DRIFTWOOD_30523; +import static net.runelite.api.ObjectID.MUSHROOM_30520; +import static net.runelite.api.ObjectID.ROCK_30519; +import static net.runelite.api.ObjectID.ROCK_30521; +import static net.runelite.api.ObjectID.ROCK_30522; +import net.runelite.api.Tile; +import net.runelite.api.TileObject; +import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameObjectChanged; +import net.runelite.api.events.GameObjectDespawned; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GroundObjectChanged; +import net.runelite.api.events.GroundObjectDespawned; +import net.runelite.api.events.GroundObjectSpawned; +import net.runelite.api.events.VarbitChanged; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Herbiboar", + description = "Highlight starting rocks, trails, and the objects to search at the end of each trail", + tags = {"herblore", "hunter", "skilling", "overlay"} +) +public class HerbiboarPlugin extends Plugin +{ + private static final List END_LOCATIONS = Arrays.asList( + new WorldPoint(3693, 3798, 0), + new WorldPoint(3702, 3808, 0), + new WorldPoint(3703, 3826, 0), + new WorldPoint(3710, 3881, 0), + new WorldPoint(3700, 3877, 0), + new WorldPoint(3715, 3840, 0), + new WorldPoint(3751, 3849, 0), + new WorldPoint(3685, 3869, 0), + new WorldPoint(3681, 3863, 0) + ); + + private static final List START_OBJECT_IDS = Arrays.asList( + ROCK_30519, + MUSHROOM_30520, + ROCK_30521, + ROCK_30522, + DRIFTWOOD_30523 + ); + + private static final int[] HERBIBOAR_REGIONS = { + 14652, + 14651, + 14908, + 14907 + }; + + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private HerbiboarOverlay overlay; + + @Inject + private HerbiboarMinimapOverlay minimapOverlay; + + @Getter + private boolean inHerbiboarArea; + + @Getter + private Map trails = new HashMap<>(); + + @Getter + private Map tunnels = new HashMap<>(); + + @Getter + private Map starts = new HashMap<>(); + + @Getter + private Map trailObjects = new HashMap<>(); + + @Getter + @Setter + private Set shownTrails = new HashSet<>(); + + @Getter + @Setter + private HerbiboarTrail currentTrail; + + @Getter + @Setter + private int currentPath; + + @Getter + @Setter + private int finishId; + + @Provides + HerbiboarConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(HerbiboarConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + overlayManager.add(minimapOverlay); + inHerbiboarArea = checkArea(); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + overlayManager.remove(minimapOverlay); + } + + private void updateTrailData() + { + currentTrail = null; + currentPath = -1; + + // Get trail data + for (HerbiboarTrail trail : HerbiboarTrail.values()) + { + int trailId = trail.getTrailId(); + int value = client.getVar(trail.getVarbit()); + + if (value > 0) + { + shownTrails.add(trailId); + shownTrails.add(trailId + 1); + } + if (value == 1 || value == 2) + { + currentTrail = trail; + currentPath = value; + } + } + + // Get finish data + finishId = client.getVar(Varbits.HB_FINISH); + if (finishId > 0 && currentTrail != null) + { + shownTrails.add(currentTrail.getTrailId()); + shownTrails.add(currentTrail.getTrailId() + 1); + currentTrail = null; + currentPath = -1; + } + + int started = client.getVar(Varbits.HB_STARTED); + if (currentPath == -1 && finishId == 0 && started == 0) + { + resetTrailData(); + } + } + + private void resetTrailData() + { + currentPath = 0; + currentTrail = null; + finishId = 0; + shownTrails.clear(); + } + + private void clearCache() + { + starts.clear(); + trailObjects.clear(); + trails.clear(); + tunnels.clear(); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + switch (event.getGameState()) + { + case HOPPING: + case LOGGING_IN: + resetTrailData(); + break; + case LOADING: + clearCache(); + inHerbiboarArea = checkArea(); + break; + default: + break; + } + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + if (isInHerbiboarArea()) + { + updateTrailData(); + } + } + + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) + { + onGameObject(event.getTile(), null, event.getGameObject()); + } + + @Subscribe + public void onGameObjectChanged(GameObjectChanged event) + { + onGameObject(event.getTile(), event.getPrevious(), event.getGameObject()); + } + + @Subscribe + public void onGameObjectDespawned(GameObjectDespawned event) + { + onGameObject(event.getTile(), event.getGameObject(), null); + } + + @Subscribe + public void onGroundObjectSpawned(GroundObjectSpawned event) + { + onGroundObject(event.getTile(), null, event.getGroundObject()); + } + + @Subscribe + public void onGroundObjectChanged(GroundObjectChanged event) + { + onGroundObject(event.getTile(), event.getPrevious(), event.getGroundObject()); + } + + @Subscribe + public void onGroundObjectDespawned(GroundObjectDespawned event) + { + onGroundObject(event.getTile(), event.getGroundObject(), null); + } + + // Store relevant GameObjects (starts, objects used to trigger next trails, and some tunnels) + private void onGameObject(Tile tile, TileObject oldObject, TileObject newObject) + { + if (oldObject != null) + { + WorldPoint oldLocation = oldObject.getWorldLocation(); + trailObjects.remove(oldLocation); + tunnels.remove(oldLocation); + starts.remove(oldLocation); + } + + if (newObject == null) + { + return; + } + + // Starts + if (START_OBJECT_IDS.contains(newObject.getId())) + { + starts.put(newObject.getWorldLocation(), newObject); + return; + } + + // GameObject to trigger next trail (mushrooms, mud, seaweed, etc) + if (HerbiboarTrail.getAllObjectLocs().contains(newObject.getWorldLocation())) + { + trailObjects.put(newObject.getWorldLocation(), newObject); + return; + } + + // Herbiboar tunnel + if (END_LOCATIONS.contains(newObject.getWorldLocation())) + { + tunnels.put(newObject.getWorldLocation(), newObject); + } + } + + // Store relevant GroundObjects (tracks on trails, and some tunnels) + private void onGroundObject(Tile tile, TileObject oldObject, TileObject newObject) + { + if (oldObject != null) + { + WorldPoint oldLocation = oldObject.getWorldLocation(); + trails.remove(oldLocation); + tunnels.remove(oldLocation); + } + + if (newObject == null) + { + return; + } + + //Trails + if (HerbiboarTrail.getTrailIds().contains(newObject.getId())) + { + trails.put(newObject.getWorldLocation(), newObject); + return; + } + + //Herbiboar tunnel + if (END_LOCATIONS.contains(newObject.getWorldLocation())) + { + tunnels.put(newObject.getWorldLocation(), newObject); + } + } + + private boolean checkArea() + { + return client.getMapRegions() != null && Arrays.stream(client.getMapRegions()) + .filter(x -> Arrays.stream(HERBIBOAR_REGIONS).anyMatch(y -> y == x)) + .toArray().length > 0; + } + + public List getEndLocations() + { + return END_LOCATIONS; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALConfig.java index a93d794548..e8589c866e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALConfig.java @@ -35,361 +35,362 @@ import net.runelite.client.config.ConfigItem; public interface HidePrayersINDIVIDUALConfig extends Config { @ConfigItem - ( - position = 0, - keyName = "pk prayers", - name = "Hide Prayers", - description = "Hide/Show Prayers." - ) - default boolean showINDIVIDUALPrayers() - { - return false; + ( + position = 0, + keyName = "pk prayers", + name = "Hide Prayers", + description = "Hide/Show Prayers." + ) + default boolean showINDIVIDUALPrayers() + { + return false; } @ConfigItem - ( - position = 1, - keyName = "thickskin", - name = "Hide Thick Skin", - description = "Hide/Show Thick Skin" - ) + ( + position = 1, + keyName = "thickskin", + name = "Hide Thick Skin", + description = "Hide/Show Thick Skin" + ) default boolean HideTHICK_SKIN() - { - return false; - } + { + return false; + } @ConfigItem - ( - position = 2, - keyName = "burstofstrength", - name = "Hide Burst of Strength", - description = "Hide/Show Burst of Strength" - ) + ( + position = 2, + keyName = "burstofstrength", + name = "Hide Burst of Strength", + description = "Hide/Show Burst of Strength" + ) default boolean HideBURST_OF_STRENGTH() - { - return false; - } + { + return false; + } @ConfigItem - ( - position = 3, - keyName = "clarityofthought", - name = "Hide Clarity of Thought", - description = "Hide/Show Clarity of Thought" - ) + ( + position = 3, + keyName = "clarityofthought", + name = "Hide Clarity of Thought", + description = "Hide/Show Clarity of Thought" + ) default boolean HideCLARITY_OF_THOUGHT() - { - return false; - } - + { + return false; + } + @ConfigItem - ( - position = 4, - keyName = "sharpeye", - name = "Hide Sharp Eye", - description = "Hide/Show Sharp Eye" - ) + ( + position = 4, + keyName = "sharpeye", + name = "Hide Sharp Eye", + description = "Hide/Show Sharp Eye" + ) default boolean HideSHARP_EYE() - { - return false; - } - + { + return false; + } + @ConfigItem - ( - position = 5, - keyName = "mysticwill", - name = "Hide Mystic Will", - description = "Hide/Show Mystic Will" - ) + ( + position = 5, + keyName = "mysticwill", + name = "Hide Mystic Will", + description = "Hide/Show Mystic Will" + ) default boolean HideMYSTIC_WILL() - { - return false; - } - + { + return false; + } + @ConfigItem - ( - position = 6, - keyName = "rockskin", - name = "Hide Rock Skin", - description = "Hide/Show Rock Skin" - ) + ( + position = 6, + keyName = "rockskin", + name = "Hide Rock Skin", + description = "Hide/Show Rock Skin" + ) default boolean HideROCK_SKIN() - { - return false; - } - + { + return false; + } + @ConfigItem - ( - position = 7, - keyName = "superhumanstrength", - name = "Hide Super Human Strength", - description = "Hide/Show Super Human Strength" - ) + ( + position = 7, + keyName = "superhumanstrength", + name = "Hide Super Human Strength", + description = "Hide/Show Super Human Strength" + ) default boolean HideSUPERHUMAN_STRENGTH() - { - return false; - } - + { + return false; + } + @ConfigItem - ( - position = 8, - keyName = "improvedreflexes", - name = "Hide Improved_Reflexes", - description = "Hide/Show Improved_Reflexes" - ) + ( + position = 8, + keyName = "improvedreflexes", + name = "Hide Improved_Reflexes", + description = "Hide/Show Improved_Reflexes" + ) default boolean HideIMPROVED_REFLEXES() - { - return false; - } - + { + return false; + } + @ConfigItem - ( - position = 9, - keyName = "rapidrestore", - name = "Hide Rapid Restore", - description = "Hide/Show Rapid Restore" - ) + ( + position = 9, + keyName = "rapidrestore", + name = "Hide Rapid Restore", + description = "Hide/Show Rapid Restore" + ) default boolean HideRapidRestore() - { - return false; + { + return false; } @ConfigItem - ( - position = 10, - keyName = "rapidheal", - name = "Hide Rapid Heal", - description = "Hide/Show Rapid Heal" - ) - default boolean HideRapidHeal() - { - return false; - } - @ConfigItem - ( - position = 11, - keyName = "protectitem", - name = "Hide Protect Item", - description = "Hide/Show Protect Item" - ) - default boolean HideProtectItem() - { - return false; - } - - @ConfigItem - ( - position = 12, - keyName = "hawkeye", - name = "Hide Hawk Eye", - description = "Hide/Show Hawk Eye" - ) - default boolean HideHAWK_EYE() - { - return false; + ( + position = 10, + keyName = "rapidheal", + name = "Hide Rapid Heal", + description = "Hide/Show Rapid Heal" + ) + default boolean HideRapidHeal() + { + return false; } @ConfigItem - ( - position = 13, - keyName = "mysticlore", - name = "Hide Mystic Lore", - description = "Hide/Show Mystic Lore" - ) + ( + position = 11, + keyName = "protectitem", + name = "Hide Protect Item", + description = "Hide/Show Protect Item" + ) + default boolean HideProtectItem() + { + return false; + } + + @ConfigItem + ( + position = 12, + keyName = "hawkeye", + name = "Hide Hawk Eye", + description = "Hide/Show Hawk Eye" + ) + default boolean HideHAWK_EYE() + { + return false; + } + + @ConfigItem + ( + position = 13, + keyName = "mysticlore", + name = "Hide Mystic Lore", + description = "Hide/Show Mystic Lore" + ) default boolean HideMYSTIC_LORE() - { - return false; + { + return false; } - + @ConfigItem - ( - position = 14, - keyName = "steelskin", - name = "Hide Steel Skin", - description = "Hide/Show Steel skin" - ) - default boolean HideSteelSkin() - { - return false; + ( + position = 14, + keyName = "steelskin", + name = "Hide Steel Skin", + description = "Hide/Show Steel skin" + ) + default boolean HideSteelSkin() + { + return false; } @ConfigItem - ( - position = 15, - keyName = "ultimatestrength", - name = "Hide Ultimate Strength", - description = "Hide/Show Ultimate strength" - ) - default boolean HideUltimateStrength() - { - return false; + ( + position = 15, + keyName = "ultimatestrength", + name = "Hide Ultimate Strength", + description = "Hide/Show Ultimate strength" + ) + default boolean HideUltimateStrength() + { + return false; } @ConfigItem - ( - position = 16, - keyName = "incrediblereflex", - name = "Hide Incredible Reflex", - description = "Hide/Show Incredible Reflex" - ) - default boolean HideIncredibleReflex() - { - return false; + ( + position = 16, + keyName = "incrediblereflex", + name = "Hide Incredible Reflex", + description = "Hide/Show Incredible Reflex" + ) + default boolean HideIncredibleReflex() + { + return false; } @ConfigItem - ( - position = 17, - keyName = "PTFMagic", - name = "Hide Protect From Magic", - description = "Hide/Show Protect From Magic" - ) - default boolean HidePTFMagic() - { - return false; + ( + position = 17, + keyName = "PTFMagic", + name = "Hide Protect From Magic", + description = "Hide/Show Protect From Magic" + ) + default boolean HidePTFMagic() + { + return false; } @ConfigItem - ( - position = 18, - keyName = "PTFRange", - name = "Hide Protect From Range", - description = "Hide/Show Protect from Range" - ) - default boolean HidePTFRange() - { - return false; + ( + position = 18, + keyName = "PTFRange", + name = "Hide Protect From Range", + description = "Hide/Show Protect from Range" + ) + default boolean HidePTFRange() + { + return false; } @ConfigItem - ( - position = 19, - keyName = "PTFMelee", - name = "Hide Protect From Melee", - description = "Hide/Show Protect From Melee" - ) - default boolean HidePTFMelee() - { - return false; + ( + position = 19, + keyName = "PTFMelee", + name = "Hide Protect From Melee", + description = "Hide/Show Protect From Melee" + ) + default boolean HidePTFMelee() + { + return false; } @ConfigItem - ( - position = 20, - keyName = "eagle", - name = "Hide Eagle Eye", - description = "Hide/Show Eagle Eye" - ) - default boolean HideEagle() - { - return false; + ( + position = 20, + keyName = "eagle", + name = "Hide Eagle Eye", + description = "Hide/Show Eagle Eye" + ) + default boolean HideEagle() + { + return false; } @ConfigItem - ( - position = 19, - keyName = "mystic", - name = "Hide Mystic Might", - description = "Hide/Show Mystic Might" - ) - default boolean HideMystic() - { - return false; - } - - @ConfigItem - ( - position = 21, - keyName = "Retribution", - name = "Hide Retribution", - description = "Hide/Show Retribution" - ) - default boolean HideRETRIBUTION() - { - return false; + ( + position = 19, + keyName = "mystic", + name = "Hide Mystic Might", + description = "Hide/Show Mystic Might" + ) + default boolean HideMystic() + { + return false; } @ConfigItem - ( - position = 22, - keyName = "redemption", - name = "Hide Redemption", - description = "Hide/Show Redemption" - ) - default boolean HideRedemption() - { - return false; + ( + position = 21, + keyName = "Retribution", + name = "Hide Retribution", + description = "Hide/Show Retribution" + ) + default boolean HideRETRIBUTION() + { + return false; } @ConfigItem - ( - position = 23, - keyName = "smite", - name = "Hide Smite", - description = "Hide/Show Smite" - ) - default boolean HideSmite() - { - return false; + ( + position = 22, + keyName = "redemption", + name = "Hide Redemption", + description = "Hide/Show Redemption" + ) + default boolean HideRedemption() + { + return false; } @ConfigItem - ( - position = 24, - keyName = "preserve", - name = "Hide Preserve", - description = "Hide/Show Preserve" - ) - default boolean HidePreserve() - { - return false; + ( + position = 23, + keyName = "smite", + name = "Hide Smite", + description = "Hide/Show Smite" + ) + default boolean HideSmite() + { + return false; } @ConfigItem - ( - position = 25, - keyName = "Chivalry", - name = "Hide Chivalry", - description = "Hide/Show Chivalry" - ) - default boolean HideChivalry() - { - return false; + ( + position = 24, + keyName = "preserve", + name = "Hide Preserve", + description = "Hide/Show Preserve" + ) + default boolean HidePreserve() + { + return false; } @ConfigItem - ( - position = 26, - keyName = "Piety", - name = "Hide Piety", - description = "Hide/Show Piety" - ) - default boolean HidePiety() - { - return false; + ( + position = 25, + keyName = "Chivalry", + name = "Hide Chivalry", + description = "Hide/Show Chivalry" + ) + default boolean HideChivalry() + { + return false; } @ConfigItem - ( - position = 27, - keyName = "Rigour", - name = "Hide Rigour", - description = "Hide/Show Rigour" - ) - default boolean HideRigour() - { - return false; + ( + position = 26, + keyName = "Piety", + name = "Hide Piety", + description = "Hide/Show Piety" + ) + default boolean HidePiety() + { + return false; } @ConfigItem - ( - position = 28, - keyName = "Augury", - name = "Hide Augury", - description = "Hide/Show Augury" - ) - default boolean HideAugury() + ( + position = 27, + keyName = "Rigour", + name = "Hide Rigour", + description = "Hide/Show Rigour" + ) + default boolean HideRigour() + { + return false; + } + + @ConfigItem + ( + position = 28, + keyName = "Augury", + name = "Hide Augury", + description = "Hide/Show Augury" + ) + default boolean HideAugury() { return false; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALPlugin.java index 902e028d24..53a16515f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/INDIVIDUAL/HidePrayersINDIVIDUALPlugin.java @@ -29,7 +29,15 @@ package net.runelite.client.plugins.hideprayers.INDIVIDUAL; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; -import net.runelite.api.*; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HashTable; +import net.runelite.api.Prayer; +import net.runelite.api.WidgetNode; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.WidgetLoaded; @@ -40,15 +48,10 @@ import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginManager; import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.hideprayers.util.PrayerTabStates; -import javax.inject.Inject; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -@PluginDescriptor +@PluginDescriptor ( name = "Show/Hide INDIVIDUAL Prayers", description = "Hides specific Prayers in the Prayer tab individually.", @@ -61,37 +64,37 @@ public class HidePrayersINDIVIDUALPlugin extends Plugin private static final int PRAYER_COUNT = Prayer.values().length; private static final List PRAYER_WIDGET_INFO_LIST = ImmutableList.of - ( - WidgetInfo.PRAYER_THICK_SKIN, //0 - WidgetInfo.PRAYER_BURST_OF_STRENGTH, //1 - WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, //2 - WidgetInfo.PRAYER_SHARP_EYE, //3 - WidgetInfo.PRAYER_MYSTIC_WILL, //4 - WidgetInfo.PRAYER_ROCK_SKIN, //5 - WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, //6 - WidgetInfo.PRAYER_IMPROVED_REFLEXES, //7 - WidgetInfo.PRAYER_RAPID_RESTORE, //8 - WidgetInfo.PRAYER_RAPID_HEAL, //9 - WidgetInfo.PRAYER_PROTECT_ITEM, //10 - WidgetInfo.PRAYER_HAWK_EYE, //11 - WidgetInfo.PRAYER_MYSTIC_LORE, //12 - WidgetInfo.PRAYER_STEEL_SKIN, //13 - WidgetInfo.PRAYER_ULTIMATE_STRENGTH, //14 - WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, //15 - WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, //16 - WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, //17 - WidgetInfo.PRAYER_PROTECT_FROM_MELEE, //18 - WidgetInfo.PRAYER_EAGLE_EYE, //19 - WidgetInfo.PRAYER_MYSTIC_MIGHT, //20 - WidgetInfo.PRAYER_RETRIBUTION, //21 - WidgetInfo.PRAYER_REDEMPTION, //22 - WidgetInfo.PRAYER_SMITE, //23 - WidgetInfo.PRAYER_PRESERVE, //24 - WidgetInfo.PRAYER_CHIVALRY, //25 - WidgetInfo.PRAYER_PIETY, //26 - WidgetInfo.PRAYER_RIGOUR, //27 - WidgetInfo.PRAYER_AUGURY //28 - ); + ( + WidgetInfo.PRAYER_THICK_SKIN, //0 + WidgetInfo.PRAYER_BURST_OF_STRENGTH, //1 + WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, //2 + WidgetInfo.PRAYER_SHARP_EYE, //3 + WidgetInfo.PRAYER_MYSTIC_WILL, //4 + WidgetInfo.PRAYER_ROCK_SKIN, //5 + WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, //6 + WidgetInfo.PRAYER_IMPROVED_REFLEXES, //7 + WidgetInfo.PRAYER_RAPID_RESTORE, //8 + WidgetInfo.PRAYER_RAPID_HEAL, //9 + WidgetInfo.PRAYER_PROTECT_ITEM, //10 + WidgetInfo.PRAYER_HAWK_EYE, //11 + WidgetInfo.PRAYER_MYSTIC_LORE, //12 + WidgetInfo.PRAYER_STEEL_SKIN, //13 + WidgetInfo.PRAYER_ULTIMATE_STRENGTH, //14 + WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, //15 + WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, //16 + WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, //17 + WidgetInfo.PRAYER_PROTECT_FROM_MELEE, //18 + WidgetInfo.PRAYER_EAGLE_EYE, //19 + WidgetInfo.PRAYER_MYSTIC_MIGHT, //20 + WidgetInfo.PRAYER_RETRIBUTION, //21 + WidgetInfo.PRAYER_REDEMPTION, //22 + WidgetInfo.PRAYER_SMITE, //23 + WidgetInfo.PRAYER_PRESERVE, //24 + WidgetInfo.PRAYER_CHIVALRY, //25 + WidgetInfo.PRAYER_PIETY, //26 + WidgetInfo.PRAYER_RIGOUR, //27 + WidgetInfo.PRAYER_AUGURY //28 + ); @Inject private Client client; @@ -157,7 +160,8 @@ public class HidePrayersINDIVIDUALPlugin extends Plugin if (widgetNode.getId() == WidgetID.PRAYER_GROUP_ID) { return PrayerTabStates.PRAYERS; - } else if (widgetNode.getId() == WidgetID.QUICK_PRAYERS_GROUP_ID) + } + else if (widgetNode.getId() == WidgetID.QUICK_PRAYERS_GROUP_ID) { return PrayerTabStates.QUICK_PRAYERS; } @@ -168,36 +172,47 @@ public class HidePrayersINDIVIDUALPlugin extends Plugin private void restorePrayers() { if (client.getGameState() != GameState.LOGGED_IN) + { return; - - PrayerTabStates prayerTabState = getPrayerTabState(); - - if (prayerTabState == PrayerTabStates.PRAYERS) { - List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget) - .filter(Objects::nonNull).collect(Collectors.toList()); - - if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) - return; - - for (int index = 0; index < PRAYER_COUNT; index++) - prayerWidgets.get(Prayer.values()[index].ordinal()).setHidden(false); } - } - - private void hidePrayers() - { - if (client.getGameState() != GameState.LOGGED_IN) - return; PrayerTabStates prayerTabState = getPrayerTabState(); if (prayerTabState == PrayerTabStates.PRAYERS) { List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget) - .filter(Objects::nonNull).collect(Collectors.toList()); + .filter(Objects::nonNull).collect(Collectors.toList()); if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { return; + } + + for (int index = 0; index < PRAYER_COUNT; index++) + { + prayerWidgets.get(Prayer.values()[index].ordinal()).setHidden(false); + } + } + } + + private void hidePrayers() + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + PrayerTabStates prayerTabState = getPrayerTabState(); + + if (prayerTabState == PrayerTabStates.PRAYERS) + { + List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget) + .filter(Objects::nonNull).collect(Collectors.toList()); + + if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { + return; + } for (int index = 0; index < PRAYER_COUNT; index++) { @@ -205,213 +220,215 @@ public class HidePrayersINDIVIDUALPlugin extends Plugin Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); if (!config.showINDIVIDUALPrayers() - && !config.HideTHICK_SKIN() - && !config.HideBURST_OF_STRENGTH() - && !config.HideCLARITY_OF_THOUGHT() - && !config.HideSHARP_EYE() - && !config.HideMYSTIC_WILL() - && !config.HideROCK_SKIN() - && !config.HideSUPERHUMAN_STRENGTH() - && !config.HideIMPROVED_REFLEXES() - && !config.HideRapidRestore() - && !config.HideRapidHeal() - && !config.HideProtectItem() - && !config.HideHAWK_EYE() - && !config.HideMYSTIC_LORE() - && !config.HideSteelSkin() - && !config.HideUltimateStrength() - && !config.HideIncredibleReflex() - && !config.HidePTFMagic() - && !config.HidePTFRange() - && !config.HidePTFMelee() - && !config.HideEagle() - && !config.HideMystic() - && !config.HideRETRIBUTION() - && !config.HideRedemption() - && !config.HideSmite() - && !config.HidePreserve() - && !config.HideChivalry() - && !config.HidePiety() - && !config.HideRigour() - && !config.HideAugury()) - prayerWidget.setHidden(false); + && !config.HideTHICK_SKIN() + && !config.HideBURST_OF_STRENGTH() + && !config.HideCLARITY_OF_THOUGHT() + && !config.HideSHARP_EYE() + && !config.HideMYSTIC_WILL() + && !config.HideROCK_SKIN() + && !config.HideSUPERHUMAN_STRENGTH() + && !config.HideIMPROVED_REFLEXES() + && !config.HideRapidRestore() + && !config.HideRapidHeal() + && !config.HideProtectItem() + && !config.HideHAWK_EYE() + && !config.HideMYSTIC_LORE() + && !config.HideSteelSkin() + && !config.HideUltimateStrength() + && !config.HideIncredibleReflex() + && !config.HidePTFMagic() + && !config.HidePTFRange() + && !config.HidePTFMelee() + && !config.HideEagle() + && !config.HideMystic() + && !config.HideRETRIBUTION() + && !config.HideRedemption() + && !config.HideSmite() + && !config.HidePreserve() + && !config.HideChivalry() + && !config.HidePiety() + && !config.HideRigour() + && !config.HideAugury()) + { + prayerWidget.setHidden(false); + } if (config.showINDIVIDUALPrayers()) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin - prayerWidgets.get(Prayer.values()[1].ordinal()).setHidden(false); // Burst of Strength - prayerWidgets.get(Prayer.values()[2].ordinal()).setHidden(false); // Clarity of Thought - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[21].ordinal()).setHidden(false); // Retribution - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(false); // Chivalry - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour - prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false); // Augury + prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin + prayerWidgets.get(Prayer.values()[1].ordinal()).setHidden(false); // Burst of Strength + prayerWidgets.get(Prayer.values()[2].ordinal()).setHidden(false); // Clarity of Thought + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[21].ordinal()).setHidden(false); // Retribution + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(false); // Chivalry + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour + prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false); // Augury if (config.HideTHICK_SKIN()) { - prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(true); // Thick Skin + prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(true); // Thick Skin } - + if (config.HideBURST_OF_STRENGTH()) { - prayerWidgets.get(Prayer.values()[1].ordinal()).setHidden(true); // Burst of Strength + prayerWidgets.get(Prayer.values()[1].ordinal()).setHidden(true); // Burst of Strength } - + if (config.HideCLARITY_OF_THOUGHT()) { - prayerWidgets.get(Prayer.values()[2].ordinal()).setHidden(true); // Clarity of Thought + prayerWidgets.get(Prayer.values()[2].ordinal()).setHidden(true); // Clarity of Thought } - + if (config.HideSHARP_EYE()) { - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(true); // Thick Skin + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(true); // Thick Skin } - + if (config.HideMYSTIC_WILL()) { - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(true); // Mystic Will + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(true); // Mystic Will } - + if (config.HideROCK_SKIN()) { - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(true); // Rock Skin - } - + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(true); // Rock Skin + } + if (config.HideSUPERHUMAN_STRENGTH()) { - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(true); // Super Human Strength + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(true); // Super Human Strength } - + if (config.HideIMPROVED_REFLEXES()) { - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(true); // Improved_Reflexes + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(true); // Improved_Reflexes } if (config.HideRapidRestore()) { - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(true); // Rapid Restore + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(true); // Rapid Restore } if (config.HideRapidHeal()) { - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(true); // Rapid Heal + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(true); // Rapid Heal } if (config.HideProtectItem()) { - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(true); // Protect Item + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(true); // Protect Item } if (config.HideHAWK_EYE()) { - prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(true); // Hawk Eye + prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(true); // Hawk Eye } if (config.HideMYSTIC_LORE()) { - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(true); // Mystic Lore + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(true); // Mystic Lore } - + if (config.HideSteelSkin()) { - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(true); // Steel Skin + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(true); // Steel Skin } if (config.HideUltimateStrength()) { - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(true); // Ultimate Strength + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(true); // Ultimate Strength } if (config.HideIncredibleReflex()) { - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(true); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(true); // Incredible Reflexes } if (config.HidePTFMagic()) { - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(true); // Protect from Magic + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(true); // Protect from Magic } if (config.HidePTFRange()) { - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(true); // Protect from Range + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(true); // Protect from Range } if (config.HidePTFMelee()) { - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(true); // Protect from Melee + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(true); // Protect from Melee } if (config.HideEagle()) { - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(true); // eagle eye + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(true); // eagle eye } if (config.HideMystic()) { - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(true); // Mystic Might + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(true); // Mystic Might } - + if (config.HideRETRIBUTION()) { - prayerWidgets.get(Prayer.values()[21].ordinal()).setHidden(true); // Retribution + prayerWidgets.get(Prayer.values()[21].ordinal()).setHidden(true); // Retribution } if (config.HideRedemption()) { - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(true); // Redemption + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(true); // Redemption } if (config.HideSmite()) { - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(true); // Smite + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(true); // Smite } if (config.HidePreserve()) { - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(true); // Preserve + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(true); // Preserve } if (config.HideChivalry()) { - prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(true); // Chivalry + prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(true); // Chivalry } if (config.HidePiety()) { - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(true); // Piety + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(true); // Piety } if (config.HideRigour()) { - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(true); // Rigour + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(true); // Rigour } if (config.HideAugury()) { - prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(true); // Augury + prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(true); // Augury } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java index b4fac7e63f..a66461482c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java @@ -35,74 +35,98 @@ import net.runelite.client.config.ConfigItem; public interface HidePrayersPVMConfig extends Config { @ConfigItem - ( - position = 0, - keyName = "Barrows", - name = "Barrows", - description = "Shows prayers for Barrows" - ) - default Barrows Barrows() {return Barrows.DISABLED;} + ( + position = 0, + keyName = "Barrows", + name = "Barrows", + description = "Shows prayers for Barrows" + ) + default Barrows Barrows() + { + return Barrows.DISABLED; + } @ConfigItem - ( - position = 1, - keyName = "Cerberus", - name = "Cerberus", - description = "Shows prayers for Cerberus" - ) - default Cerberus Cerberus() {return Cerberus.DISABLED;} + ( + position = 1, + keyName = "Cerberus", + name = "Cerberus", + description = "Shows prayers for Cerberus" + ) + default Cerberus Cerberus() + { + return Cerberus.DISABLED; + } @ConfigItem - ( - position = 2, - keyName = "Vorkath", - name = "Vorkath", - description = "Shows prayers for Vorkath" - ) - default Vorkath Vorkath() {return Vorkath.DISABLED;} + ( + position = 2, + keyName = "Vorkath", + name = "Vorkath", + description = "Shows prayers for Vorkath" + ) + default Vorkath Vorkath() + { + return Vorkath.DISABLED; + } @ConfigItem - ( - position = 3, - keyName = "Zulrah", - name = "Zulrah", - description = "Shows prayers for Zulrah" - ) - default Zulrah Zulrah() {return Zulrah.DISABLED;} + ( + position = 3, + keyName = "Zulrah", + name = "Zulrah", + description = "Shows prayers for Zulrah" + ) + default Zulrah Zulrah() + { + return Zulrah.DISABLED; + } @ConfigItem - ( - position = 4, - keyName = "Armadyl", - name = "Armadyl", - description = "Shows prayers for Armadyl" - ) - default Armadyl Armadyl() {return Armadyl.DISABLED;} + ( + position = 4, + keyName = "Armadyl", + name = "Armadyl", + description = "Shows prayers for Armadyl" + ) + default Armadyl Armadyl() + { + return Armadyl.DISABLED; + } @ConfigItem - ( - position = 5, - keyName = "Bandos", - name = "Bandos", - description = "Shows prayers for Bandos" - ) - default Bandos Bandos() {return Bandos.DISABLED;} + ( + position = 5, + keyName = "Bandos", + name = "Bandos", + description = "Shows prayers for Bandos" + ) + default Bandos Bandos() + { + return Bandos.DISABLED; + } @ConfigItem - ( - position = 6, - keyName = "Saradomin", - name = "Saradomin", - description = "Shows prayers for Saradomin" - ) - default Saradomin Saradomin() {return Saradomin.DISABLED;} + ( + position = 6, + keyName = "Saradomin", + name = "Saradomin", + description = "Shows prayers for Saradomin" + ) + default Saradomin Saradomin() + { + return Saradomin.DISABLED; + } @ConfigItem - ( - position = 7, - keyName = "Zamorak", - name = "Zamorak", - description = "Shows prayers for Zamorak" - ) - default Zamorak Zamorak() {return Zamorak.DISABLED;} + ( + position = 7, + keyName = "Zamorak", + name = "Zamorak", + description = "Shows prayers for Zamorak" + ) + default Zamorak Zamorak() + { + return Zamorak.DISABLED; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java index 49f7fd0a1b..fc4b75684a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java @@ -24,12 +24,20 @@ * (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.hideprayers.PVM; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; -import net.runelite.api.*; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HashTable; +import net.runelite.api.Prayer; +import net.runelite.api.WidgetNode; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.WidgetLoaded; @@ -42,12 +50,8 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.hideprayers.util.PrayerTabStates; -import javax.inject.Inject; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -@PluginDescriptor +@PluginDescriptor ( name = "Show/Hide PVM Prayers", description = "Hides specific Prayers in the Prayer tab for PVM.", @@ -60,37 +64,37 @@ public class HidePrayersPVMPlugin extends Plugin private static final int PRAYER_COUNT = Prayer.values().length; private static final List PRAYER_WIDGET_INFO_LIST = ImmutableList.of - ( - WidgetInfo.PRAYER_THICK_SKIN, //0 - WidgetInfo.PRAYER_BURST_OF_STRENGTH, //1 - WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, //2 - WidgetInfo.PRAYER_SHARP_EYE, //3 - WidgetInfo.PRAYER_MYSTIC_WILL, //4 - WidgetInfo.PRAYER_ROCK_SKIN, //5 - WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, //6 - WidgetInfo.PRAYER_IMPROVED_REFLEXES, //7 - WidgetInfo.PRAYER_RAPID_RESTORE, //8 - WidgetInfo.PRAYER_RAPID_HEAL, //9 - WidgetInfo.PRAYER_PROTECT_ITEM, //10 - WidgetInfo.PRAYER_HAWK_EYE, //11 - WidgetInfo.PRAYER_MYSTIC_LORE, //12 - WidgetInfo.PRAYER_STEEL_SKIN, //13 - WidgetInfo.PRAYER_ULTIMATE_STRENGTH, //14 - WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, //15 - WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, //16 - WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, //17 - WidgetInfo.PRAYER_PROTECT_FROM_MELEE, //18 - WidgetInfo.PRAYER_EAGLE_EYE, //19 - WidgetInfo.PRAYER_MYSTIC_MIGHT, //20 - WidgetInfo.PRAYER_RETRIBUTION, //21 - WidgetInfo.PRAYER_REDEMPTION, //22 - WidgetInfo.PRAYER_SMITE, //23 - WidgetInfo.PRAYER_PRESERVE, //24 - WidgetInfo.PRAYER_CHIVALRY, //25 - WidgetInfo.PRAYER_PIETY, //26 - WidgetInfo.PRAYER_RIGOUR, //27 - WidgetInfo.PRAYER_AUGURY //28 - ); + ( + WidgetInfo.PRAYER_THICK_SKIN, //0 + WidgetInfo.PRAYER_BURST_OF_STRENGTH, //1 + WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, //2 + WidgetInfo.PRAYER_SHARP_EYE, //3 + WidgetInfo.PRAYER_MYSTIC_WILL, //4 + WidgetInfo.PRAYER_ROCK_SKIN, //5 + WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, //6 + WidgetInfo.PRAYER_IMPROVED_REFLEXES, //7 + WidgetInfo.PRAYER_RAPID_RESTORE, //8 + WidgetInfo.PRAYER_RAPID_HEAL, //9 + WidgetInfo.PRAYER_PROTECT_ITEM, //10 + WidgetInfo.PRAYER_HAWK_EYE, //11 + WidgetInfo.PRAYER_MYSTIC_LORE, //12 + WidgetInfo.PRAYER_STEEL_SKIN, //13 + WidgetInfo.PRAYER_ULTIMATE_STRENGTH, //14 + WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, //15 + WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, //16 + WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, //17 + WidgetInfo.PRAYER_PROTECT_FROM_MELEE, //18 + WidgetInfo.PRAYER_EAGLE_EYE, //19 + WidgetInfo.PRAYER_MYSTIC_MIGHT, //20 + WidgetInfo.PRAYER_RETRIBUTION, //21 + WidgetInfo.PRAYER_REDEMPTION, //22 + WidgetInfo.PRAYER_SMITE, //23 + WidgetInfo.PRAYER_PRESERVE, //24 + WidgetInfo.PRAYER_CHIVALRY, //25 + WidgetInfo.PRAYER_PIETY, //26 + WidgetInfo.PRAYER_RIGOUR, //27 + WidgetInfo.PRAYER_AUGURY //28 + ); @Inject private Client client; @@ -108,7 +112,7 @@ public class HidePrayersPVMPlugin extends Plugin } @Override - protected void startUp() throws Exception + protected void startUp() throws Exception { hidePrayers(); configManager.setConfiguration("runelite", "hideprayerspvmplugin", false); @@ -116,22 +120,22 @@ public class HidePrayersPVMPlugin extends Plugin } @Override - protected void shutDown() throws Exception + protected void shutDown() throws Exception { restorePrayers(); } @Subscribe - public void onGameStateChanged(GameStateChanged event) + public void onGameStateChanged(GameStateChanged event) { - if (event.getGameState() == GameState.LOGGED_IN) + if (event.getGameState() == GameState.LOGGED_IN) { hidePrayers(); } } @Subscribe - public void onConfigChanged(ConfigChanged event) + public void onConfigChanged(ConfigChanged event) { if (event.getGroup().equals("hideprayersPVM")) { @@ -140,9 +144,9 @@ public class HidePrayersPVMPlugin extends Plugin } @Subscribe - public void onWidgetLoaded(WidgetLoaded event) + public void onWidgetLoaded(WidgetLoaded event) { - if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) + if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) { hidePrayers(); } @@ -168,39 +172,49 @@ public class HidePrayersPVMPlugin extends Plugin private void restorePrayers() { if (client.getGameState() != GameState.LOGGED_IN) + { return; + } PrayerTabStates prayerTabState = getPrayerTabState(); if (prayerTabState == PrayerTabStates.PRAYERS) { List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget) - .filter(Objects::nonNull).collect(Collectors.toList()); + .filter(Objects::nonNull).collect(Collectors.toList()); if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { return; + } for (int index = 0; index < PRAYER_COUNT; index++) + { prayerWidgets.get(Prayer.values()[index].ordinal()).setHidden(false); + } } } private void hidePrayers() { if (client.getGameState() != GameState.LOGGED_IN) + { return; + } PrayerTabStates prayerTabState = getPrayerTabState(); if (prayerTabState == PrayerTabStates.PRAYERS) { List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget) - .filter(Objects::nonNull).collect(Collectors.toList()); + .filter(Objects::nonNull).collect(Collectors.toList()); if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { return; + } - for (int index = 0; index < PRAYER_COUNT; index++) + for (int index = 0; index < PRAYER_COUNT; index++) { Prayer prayer = Prayer.values()[index]; Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); @@ -214,7 +228,9 @@ public class HidePrayersPVMPlugin extends Plugin && config.Zamorak() == Zamorak.DISABLED && config.Zulrah() == Zulrah.DISABLED ) - prayerWidget.setHidden(false); + { + prayerWidget.setHidden(false); + } if (config.Zulrah() == Zulrah.ZULRAH_CHEAP) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/CombatPrayers.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/CombatPrayers.java index 208c0e22b4..e40dd3218e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/CombatPrayers.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/CombatPrayers.java @@ -40,7 +40,7 @@ public enum CombatPrayers PRAY25("25 prayer build"), PRAY31("31 prayer build"), PRAY43("43 prayer build"), - PRAY44("44 prayer build"), + PRAY44("44 prayer build"), PRAY45("45 prayer build"), PRAY52("52 prayer build"), PRAY55("55 prayer build"), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java index 078870726a..30e482d489 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java @@ -35,11 +35,14 @@ import net.runelite.client.config.ConfigItem; public interface HidePrayersPVPConfig extends Config { @ConfigItem - ( - position = 0, - keyName = "CombatPrayers", - name = "Combat Prayers", - description = "Shows prayers based on prayer build" - ) - default CombatPrayers CombatPrayers() {return CombatPrayers.DISABLED;} + ( + position = 0, + keyName = "CombatPrayers", + name = "Combat Prayers", + description = "Shows prayers based on prayer build" + ) + default CombatPrayers CombatPrayers() + { + return CombatPrayers.DISABLED; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java index 1bfd4238d7..0fc21ec4a8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java @@ -24,12 +24,20 @@ * (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.hideprayers.PVP; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; -import net.runelite.api.*; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HashTable; +import net.runelite.api.Prayer; +import net.runelite.api.WidgetNode; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.WidgetLoaded; @@ -42,12 +50,8 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.hideprayers.util.PrayerTabStates; -import javax.inject.Inject; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -@PluginDescriptor +@PluginDescriptor ( name = "Show/Hide PVP Prayers", description = "Hides specific Prayers in the Prayer tab for PVP.", @@ -60,37 +64,37 @@ public class HidePrayersPVPPlugin extends Plugin private static final int PRAYER_COUNT = Prayer.values().length; private static final List PRAYER_WIDGET_INFO_LIST = ImmutableList.of - ( - WidgetInfo.PRAYER_THICK_SKIN, //0 - WidgetInfo.PRAYER_BURST_OF_STRENGTH, //1 - WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, //2 - WidgetInfo.PRAYER_SHARP_EYE, //3 - WidgetInfo.PRAYER_MYSTIC_WILL, //4 - WidgetInfo.PRAYER_ROCK_SKIN, //5 - WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, //6 - WidgetInfo.PRAYER_IMPROVED_REFLEXES, //7 - WidgetInfo.PRAYER_RAPID_RESTORE, //8 - WidgetInfo.PRAYER_RAPID_HEAL, //9 - WidgetInfo.PRAYER_PROTECT_ITEM, //10 - WidgetInfo.PRAYER_HAWK_EYE, //11 - WidgetInfo.PRAYER_MYSTIC_LORE, //12 - WidgetInfo.PRAYER_STEEL_SKIN, //13 - WidgetInfo.PRAYER_ULTIMATE_STRENGTH, //14 - WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, //15 - WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, //16 - WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, //17 - WidgetInfo.PRAYER_PROTECT_FROM_MELEE, //18 - WidgetInfo.PRAYER_EAGLE_EYE, //19 - WidgetInfo.PRAYER_MYSTIC_MIGHT, //20 - WidgetInfo.PRAYER_RETRIBUTION, //21 - WidgetInfo.PRAYER_REDEMPTION, //22 - WidgetInfo.PRAYER_SMITE, //23 - WidgetInfo.PRAYER_PRESERVE, //24 - WidgetInfo.PRAYER_CHIVALRY, //25 - WidgetInfo.PRAYER_PIETY, //26 - WidgetInfo.PRAYER_RIGOUR, //27 - WidgetInfo.PRAYER_AUGURY //28 - ); + ( + WidgetInfo.PRAYER_THICK_SKIN, //0 + WidgetInfo.PRAYER_BURST_OF_STRENGTH, //1 + WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, //2 + WidgetInfo.PRAYER_SHARP_EYE, //3 + WidgetInfo.PRAYER_MYSTIC_WILL, //4 + WidgetInfo.PRAYER_ROCK_SKIN, //5 + WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, //6 + WidgetInfo.PRAYER_IMPROVED_REFLEXES, //7 + WidgetInfo.PRAYER_RAPID_RESTORE, //8 + WidgetInfo.PRAYER_RAPID_HEAL, //9 + WidgetInfo.PRAYER_PROTECT_ITEM, //10 + WidgetInfo.PRAYER_HAWK_EYE, //11 + WidgetInfo.PRAYER_MYSTIC_LORE, //12 + WidgetInfo.PRAYER_STEEL_SKIN, //13 + WidgetInfo.PRAYER_ULTIMATE_STRENGTH, //14 + WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, //15 + WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, //16 + WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, //17 + WidgetInfo.PRAYER_PROTECT_FROM_MELEE, //18 + WidgetInfo.PRAYER_EAGLE_EYE, //19 + WidgetInfo.PRAYER_MYSTIC_MIGHT, //20 + WidgetInfo.PRAYER_RETRIBUTION, //21 + WidgetInfo.PRAYER_REDEMPTION, //22 + WidgetInfo.PRAYER_SMITE, //23 + WidgetInfo.PRAYER_PRESERVE, //24 + WidgetInfo.PRAYER_CHIVALRY, //25 + WidgetInfo.PRAYER_PIETY, //26 + WidgetInfo.PRAYER_RIGOUR, //27 + WidgetInfo.PRAYER_AUGURY //28 + ); @Inject private Client client; @@ -108,7 +112,7 @@ public class HidePrayersPVPPlugin extends Plugin } @Override - protected void startUp() throws Exception + protected void startUp() throws Exception { hidePrayers(); configManager.setConfiguration("runelite", "hideprayerspvmplugin", false); @@ -116,22 +120,22 @@ public class HidePrayersPVPPlugin extends Plugin } @Override - protected void shutDown() throws Exception + protected void shutDown() throws Exception { restorePrayers(); } @Subscribe - public void onGameStateChanged(GameStateChanged event) + public void onGameStateChanged(GameStateChanged event) { - if (event.getGameState() == GameState.LOGGED_IN) + if (event.getGameState() == GameState.LOGGED_IN) { hidePrayers(); } } @Subscribe - public void onConfigChanged(ConfigChanged event) + public void onConfigChanged(ConfigChanged event) { if (event.getGroup().equals("hideprayersPVP")) { @@ -140,9 +144,9 @@ public class HidePrayersPVPPlugin extends Plugin } @Subscribe - public void onWidgetLoaded(WidgetLoaded event) + public void onWidgetLoaded(WidgetLoaded event) { - if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) + if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) { hidePrayers(); } @@ -168,250 +172,262 @@ public class HidePrayersPVPPlugin extends Plugin private void restorePrayers() { if (client.getGameState() != GameState.LOGGED_IN) + { return; + } PrayerTabStates prayerTabState = getPrayerTabState(); if (prayerTabState == PrayerTabStates.PRAYERS) { List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget) - .filter(Objects::nonNull).collect(Collectors.toList()); + .filter(Objects::nonNull).collect(Collectors.toList()); if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { return; + } for (int index = 0; index < PRAYER_COUNT; index++) + { prayerWidgets.get(Prayer.values()[index].ordinal()).setHidden(false); + } } } private void hidePrayers() { if (client.getGameState() != GameState.LOGGED_IN) + { return; + } PrayerTabStates prayerTabState = getPrayerTabState(); if (prayerTabState == PrayerTabStates.PRAYERS) { List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget) - .filter(Objects::nonNull).collect(Collectors.toList()); + .filter(Objects::nonNull).collect(Collectors.toList()); if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { return; + } - for (int index = 0; index < PRAYER_COUNT; index++) + for (int index = 0; index < PRAYER_COUNT; index++) { Prayer prayer = Prayer.values()[index]; Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); if (config.CombatPrayers() == CombatPrayers.DISABLED) - prayerWidget.setHidden(false); + { + prayerWidget.setHidden(false); + } if (config.CombatPrayers() == CombatPrayers.PRAY1) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin + prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin } - + if (config.CombatPrayers() == CombatPrayers.PRAY13) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength + prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength } - + if (config.CombatPrayers() == CombatPrayers.PRAY16) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed } if (config.CombatPrayers() == CombatPrayers.PRAY25) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item } - + if (config.CombatPrayers() == CombatPrayers.PRAY31) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength } if (config.CombatPrayers() == CombatPrayers.PRAY43) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - } - + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + } + if (config.CombatPrayers() == CombatPrayers.PRAY44) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye } - + if (config.CombatPrayers() == CombatPrayers.PRAY45) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - } - + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + } + if (config.CombatPrayers() == CombatPrayers.PRAY52) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite } if (config.CombatPrayers() == CombatPrayers.PRAY55) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve } if (config.CombatPrayers() == CombatPrayers.PRAY60) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(false); // Chivalry + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(false); // Chivalry } - + if (config.CombatPrayers() == CombatPrayers.PRAY70) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety } if (config.CombatPrayers() == CombatPrayers.PRAY74) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour - } - + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour + } + if (config.CombatPrayers() == CombatPrayers.PRAY77) { prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour - prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false); // Augury + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour + prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false); // Augury } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/util/PrayerTabStates.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/util/PrayerTabStates.java index e02efad33f..cf036f1fb7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/util/PrayerTabStates.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/util/PrayerTabStates.java @@ -24,12 +24,12 @@ * (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.hideprayers.util; public enum PrayerTabStates { - NONE, - PRAYERS, - QUICK_PRAYERS + NONE, + PRAYERS, + QUICK_PRAYERS } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyOverlay.java index dfaf0be2e6..7a7fc07394 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyOverlay.java @@ -32,8 +32,6 @@ import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; -import java.util.HashSet; -import java.util.Set; import javax.inject.Inject; import net.runelite.api.ItemComposition; import net.runelite.api.ItemID; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyPlugin.java index af43bb3f77..61439c985f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/highalchemy/HighAlchemyPlugin.java @@ -113,7 +113,7 @@ public class HighAlchemyPlugin extends Plugin if (config.showInventory()) { Arrays.stream( - new int[] { + new int[]{ DEPOSIT_BOX_GROUP_ID, BANK_INVENTORY_GROUP_ID, SHOP_INVENTORY_GROUP_ID, diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java index 5ecd24ae1b..65b978a0b5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java @@ -1,256 +1,256 @@ -/* - * Copyright (c) 2017, Adam - * 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.hiscore; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ObjectArrays; -import com.google.inject.Provides; -import java.awt.image.BufferedImage; -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.annotation.Nullable; -import javax.inject.Inject; -import javax.inject.Provider; -import javax.swing.SwingUtilities; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.MenuAction; -import net.runelite.api.MenuEntry; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.events.PlayerMenuOptionClicked; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.menus.MenuManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.Text; -import org.apache.commons.lang3.ArrayUtils; - -@PluginDescriptor( - name = "HiScore", - description = "Enable the HiScore panel and an optional Lookup option on players", - tags = {"panel", "players"}, - loadWhenOutdated = true -) -public class HiscorePlugin extends Plugin -{ - private static final String LOOKUP = "Lookup"; - private static final String KICK_OPTION = "Kick"; - private static final ImmutableList AFTER_OPTIONS = ImmutableList.of("Message", "Add ignore", "Remove friend", KICK_OPTION); - private static final Pattern BOUNTY_PATTERN = Pattern.compile("You've been assigned a target: (.*)"); - - @Inject - @Nullable - private Client client; - - @Inject - private Provider menuManager; - - @Inject - private ClientToolbar clientToolbar; - - @Inject - private ScheduledExecutorService executor; - - @Inject - private HiscoreConfig config; - - private NavigationButton navButton; - private HiscorePanel hiscorePanel; - - @Inject - private NameAutocompleter autocompleter; - - @Provides - HiscoreConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(HiscoreConfig.class); - } - - @Override - protected void startUp() throws Exception - { - hiscorePanel = injector.getInstance(HiscorePanel.class); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "normal.png"); - - navButton = NavigationButton.builder() - .tooltip("Hiscore") - .icon(icon) - .priority(5) - .panel(hiscorePanel) - .build(); - - clientToolbar.addNavigation(navButton); - - if (config.playerOption() && client != null) - { - menuManager.get().addPlayerMenuItem(LOOKUP); - } - if (config.autocomplete()) - { - hiscorePanel.addInputKeyListener(autocompleter); - } - } - - @Override - protected void shutDown() throws Exception - { - hiscorePanel.removeInputKeyListener(autocompleter); - clientToolbar.removeNavigation(navButton); - - if (client != null) - { - menuManager.get().removePlayerMenuItem(LOOKUP); - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("hiscore")) - { - if (client != null) - { - menuManager.get().removePlayerMenuItem(LOOKUP); - - if (config.playerOption()) - { - menuManager.get().addPlayerMenuItem(LOOKUP); - } - } - - if (event.getKey().equals("autocomplete")) - { - if (config.autocomplete()) - { - hiscorePanel.addInputKeyListener(autocompleter); - } - else - { - hiscorePanel.removeInputKeyListener(autocompleter); - } - } - } - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) - { - if (!config.menuOption()) - { - return; - } - - int groupId = WidgetInfo.TO_GROUP(event.getActionParam1()); - String option = event.getOption(); - - if (groupId == WidgetInfo.FRIENDS_LIST.getGroupId() || groupId == WidgetInfo.CLAN_CHAT.getGroupId() || - groupId == WidgetInfo.CHATBOX.getGroupId() && !KICK_OPTION.equals(option) || //prevent from adding for Kick option (interferes with the raiding party one) - groupId == WidgetInfo.RAIDING_PARTY.getGroupId() || groupId == WidgetInfo.PRIVATE_CHAT_MESSAGE.getGroupId()) - { - boolean after; - - if (!AFTER_OPTIONS.contains(option)) - { - return; - } - - final MenuEntry lookup = new MenuEntry(); - lookup.setOption(LOOKUP); - lookup.setTarget(event.getTarget()); - lookup.setType(MenuAction.RUNELITE.getId()); - lookup.setParam0(event.getActionParam0()); - lookup.setParam1(event.getActionParam1()); - lookup.setIdentifier(event.getIdentifier()); - - insertMenuEntry(lookup, client.getMenuEntries()); - } - } - - @Subscribe - public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event) - { - if (event.getMenuOption().equals(LOOKUP)) - { - lookupPlayer(Text.removeTags(event.getMenuTarget())); - } - } - - @Subscribe - public void onChatMessage(ChatMessage event) - { - if (!config.bountylookup() || !event.getType().equals(ChatMessageType.GAMEMESSAGE)) - { - return; - } - - String message = event.getMessage(); - Matcher m = BOUNTY_PATTERN.matcher(message); - if (m.matches()) - { - lookupPlayer(m.group(1)); - } - } - - private void insertMenuEntry(MenuEntry newEntry, MenuEntry[] entries) - { - MenuEntry[] newMenu = ObjectArrays.concat(entries, newEntry); - int menuEntryCount = newMenu.length; - ArrayUtils.swap(newMenu, menuEntryCount - 1, menuEntryCount - 2); - client.setMenuEntries(newMenu); - } - - private void lookupPlayer(String playerName) - { - executor.execute(() -> - { - try - { - SwingUtilities.invokeAndWait(() -> - { - if (!navButton.isSelected()) - { - navButton.getOnSelect().run(); - } - }); - } - catch (InterruptedException | InvocationTargetException e) - { - throw new RuntimeException(e); - } - - hiscorePanel.lookup(playerName); - }); - } -} +/* + * Copyright (c) 2017, Adam + * 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.hiscore; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ObjectArrays; +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Provider; +import javax.swing.SwingUtilities; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.PlayerMenuOptionClicked; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.menus.MenuManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.Text; +import org.apache.commons.lang3.ArrayUtils; + +@PluginDescriptor( + name = "HiScore", + description = "Enable the HiScore panel and an optional Lookup option on players", + tags = {"panel", "players"}, + loadWhenOutdated = true +) +public class HiscorePlugin extends Plugin +{ + private static final String LOOKUP = "Lookup"; + private static final String KICK_OPTION = "Kick"; + private static final ImmutableList AFTER_OPTIONS = ImmutableList.of("Message", "Add ignore", "Remove friend", KICK_OPTION); + private static final Pattern BOUNTY_PATTERN = Pattern.compile("You've been assigned a target: (.*)"); + + @Inject + @Nullable + private Client client; + + @Inject + private Provider menuManager; + + @Inject + private ClientToolbar clientToolbar; + + @Inject + private ScheduledExecutorService executor; + + @Inject + private HiscoreConfig config; + + private NavigationButton navButton; + private HiscorePanel hiscorePanel; + + @Inject + private NameAutocompleter autocompleter; + + @Provides + HiscoreConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(HiscoreConfig.class); + } + + @Override + protected void startUp() throws Exception + { + hiscorePanel = injector.getInstance(HiscorePanel.class); + + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "normal.png"); + + navButton = NavigationButton.builder() + .tooltip("Hiscore") + .icon(icon) + .priority(5) + .panel(hiscorePanel) + .build(); + + clientToolbar.addNavigation(navButton); + + if (config.playerOption() && client != null) + { + menuManager.get().addPlayerMenuItem(LOOKUP); + } + if (config.autocomplete()) + { + hiscorePanel.addInputKeyListener(autocompleter); + } + } + + @Override + protected void shutDown() throws Exception + { + hiscorePanel.removeInputKeyListener(autocompleter); + clientToolbar.removeNavigation(navButton); + + if (client != null) + { + menuManager.get().removePlayerMenuItem(LOOKUP); + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("hiscore")) + { + if (client != null) + { + menuManager.get().removePlayerMenuItem(LOOKUP); + + if (config.playerOption()) + { + menuManager.get().addPlayerMenuItem(LOOKUP); + } + } + + if (event.getKey().equals("autocomplete")) + { + if (config.autocomplete()) + { + hiscorePanel.addInputKeyListener(autocompleter); + } + else + { + hiscorePanel.removeInputKeyListener(autocompleter); + } + } + } + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + if (!config.menuOption()) + { + return; + } + + int groupId = WidgetInfo.TO_GROUP(event.getActionParam1()); + String option = event.getOption(); + + if (groupId == WidgetInfo.FRIENDS_LIST.getGroupId() || groupId == WidgetInfo.CLAN_CHAT.getGroupId() || + groupId == WidgetInfo.CHATBOX.getGroupId() && !KICK_OPTION.equals(option) || //prevent from adding for Kick option (interferes with the raiding party one) + groupId == WidgetInfo.RAIDING_PARTY.getGroupId() || groupId == WidgetInfo.PRIVATE_CHAT_MESSAGE.getGroupId()) + { + boolean after; + + if (!AFTER_OPTIONS.contains(option)) + { + return; + } + + final MenuEntry lookup = new MenuEntry(); + lookup.setOption(LOOKUP); + lookup.setTarget(event.getTarget()); + lookup.setType(MenuAction.RUNELITE.getId()); + lookup.setParam0(event.getActionParam0()); + lookup.setParam1(event.getActionParam1()); + lookup.setIdentifier(event.getIdentifier()); + + insertMenuEntry(lookup, client.getMenuEntries()); + } + } + + @Subscribe + public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event) + { + if (event.getMenuOption().equals(LOOKUP)) + { + lookupPlayer(Text.removeTags(event.getMenuTarget())); + } + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (!config.bountylookup() || !event.getType().equals(ChatMessageType.GAMEMESSAGE)) + { + return; + } + + String message = event.getMessage(); + Matcher m = BOUNTY_PATTERN.matcher(message); + if (m.matches()) + { + lookupPlayer(m.group(1)); + } + } + + private void insertMenuEntry(MenuEntry newEntry, MenuEntry[] entries) + { + MenuEntry[] newMenu = ObjectArrays.concat(entries, newEntry); + int menuEntryCount = newMenu.length; + ArrayUtils.swap(newMenu, menuEntryCount - 1, menuEntryCount - 2); + client.setMenuEntries(newMenu); + } + + private void lookupPlayer(String playerName) + { + executor.execute(() -> + { + try + { + SwingUtilities.invokeAndWait(() -> + { + if (!navButton.isSelected()) + { + navButton.getOnSelect().run(); + } + }); + } + catch (InterruptedException | InvocationTargetException e) + { + throw new RuntimeException(e); + } + + hiscorePanel.lookup(playerName); + }); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java index 6dcaaecf83..2926be7001 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java @@ -1,265 +1,265 @@ -/* - * Copyright (c) 2018, John Pettenger - * 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.hiscore; - -import com.google.inject.Inject; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; -import java.util.regex.Pattern; -import javax.annotation.Nullable; -import javax.swing.SwingUtilities; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.JTextComponent; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ClanMember; -import net.runelite.api.Client; -import net.runelite.api.Friend; -import net.runelite.api.Player; - -@Slf4j -class NameAutocompleter implements KeyListener -{ - /** - * Non-breaking space character. - */ - private static final String NBSP = Character.toString((char)160); - - /** - * Character class for characters that cannot be in an RSN. - */ - private static final Pattern INVALID_CHARS = Pattern.compile("[^a-zA-Z0-9_ -]"); - - private final Client client; - - /** - * The name currently being autocompleted. - */ - private String autocompleteName; - - /** - * Pattern for the name currently being autocompleted. - */ - private Pattern autocompleteNamePattern; - - @Inject - private NameAutocompleter(@Nullable Client client) - { - this.client = client; - } - - @Override - public void keyPressed(KeyEvent e) - { - - } - - @Override - public void keyReleased(KeyEvent e) - { - - } - - @Override - public void keyTyped(KeyEvent e) - { - final JTextComponent input = (JTextComponent)e.getSource(); - final String inputText = input.getText(); - - // Only autocomplete if the selection end is at the end of the text. - if (input.getSelectionEnd() != inputText.length()) - { - return; - } - - // Character to be inserted at the selection start. - final String charToInsert = Character.toString(e.getKeyChar()); - - // Don't attempt to autocomplete if the name is invalid. - // This condition is also true when the user presses a key like backspace. - if (INVALID_CHARS.matcher(charToInsert).find() - || INVALID_CHARS.matcher(inputText).find()) - { - return; - } - - // Check if we are already autocompleting. - if (autocompleteName != null && autocompleteNamePattern.matcher(inputText).matches()) - { - if (isExpectedNext(input, charToInsert)) - { - try - { - // Insert the character and move the selection. - final int insertIndex = input.getSelectionStart(); - Document doc = input.getDocument(); - doc.remove(insertIndex, 1); - doc.insertString(insertIndex, charToInsert, null); - input.select(insertIndex + 1, input.getSelectionEnd()); - } - catch (BadLocationException ex) - { - log.warn("Could not insert character.", ex); - } - - // Prevent default behavior. - e.consume(); - } - else // Character to insert does not match current autocompletion. Look for another name. - { - newAutocomplete(e); - } - } - else // Search for a name to autocomplete - { - newAutocomplete(e); - } - } - - private void newAutocomplete(KeyEvent e) - { - final JTextComponent input = (JTextComponent)e.getSource(); - final String inputText = input.getText(); - final String nameStart = inputText.substring(0, input.getSelectionStart()) + e.getKeyChar(); - - if (findAutocompleteName(nameStart)) - { - // Assert this.autocompleteName != null - final String name = this.autocompleteName; - SwingUtilities.invokeLater(() -> - { - try - { - input.getDocument().insertString( - nameStart.length(), - name.substring(nameStart.length()), - null); - input.select(nameStart.length(), name.length()); - } - catch (BadLocationException ex) - { - log.warn("Could not autocomplete name.", ex); - } - }); - } - } - - private boolean findAutocompleteName(String nameStart) - { - final Pattern pattern; - Optional autocompleteName; - - // Pattern to match names that start with nameStart. - // Allows spaces to be represented as common whitespaces, underscores, - // hyphens, or non-breaking spaces. - // Matching non-breaking spaces is necessary because the API - // returns non-breaking spaces when a name has whitespace. - pattern = Pattern.compile( - "(?i)^" + nameStart.replaceAll("[ _-]", "[ _" + NBSP + "-]") + ".+?"); - - if (client == null) - { - return false; - } - - autocompleteName = Optional.empty(); - - // TODO: Search lookup history - - Friend[] friends = client.getFriends(); - if (friends != null) - { - autocompleteName = Arrays.stream(friends) - .filter(Objects::nonNull) - .map(Friend::getName) - .filter(n -> pattern.matcher(n).matches()) - .findFirst(); - } - - // Search clan if a friend wasn't found - if (!autocompleteName.isPresent()) - { - final ClanMember[] clannies = client.getClanMembers(); - if (clannies != null) - { - autocompleteName = Arrays.stream(clannies) - .filter(Objects::nonNull) - .map(ClanMember::getUsername) - .filter(n -> pattern.matcher(n).matches()) - .findFirst(); - } - } - - // Search cached players if a clannie wasn't found. - if (!autocompleteName.isPresent()) - { - final Player[] cachedPlayers = client.getCachedPlayers(); - autocompleteName = Arrays.stream(cachedPlayers) - .filter(Objects::nonNull) - .map(Player::getName) - .filter(n -> pattern.matcher(n).matches()) - .findFirst(); - } - - if (autocompleteName.isPresent()) - { - this.autocompleteName = autocompleteName.get().replace(NBSP, " "); - this.autocompleteNamePattern = Pattern.compile( - "(?i)^" + this.autocompleteName.replaceAll("[ _-]", "[ _-]") + "$"); - } - else - { - this.autocompleteName = null; - this.autocompleteNamePattern = null; - } - - return autocompleteName.isPresent(); - } - - private boolean isExpectedNext(JTextComponent input, String nextChar) - { - String expected; - if (input.getSelectionStart() < input.getSelectionEnd()) - { - try - { - expected = input.getText(input.getSelectionStart(), 1); - } - catch (BadLocationException ex) - { - log.warn("Could not get first character from input selection.", ex); - return false; - } - } - else - { - expected = ""; - } - return nextChar.equalsIgnoreCase(expected); - } +/* + * Copyright (c) 2018, John Pettenger + * 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.hiscore; + +import com.google.inject.Inject; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Pattern; +import javax.annotation.Nullable; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ClanMember; +import net.runelite.api.Client; +import net.runelite.api.Friend; +import net.runelite.api.Player; + +@Slf4j +class NameAutocompleter implements KeyListener +{ + /** + * Non-breaking space character. + */ + private static final String NBSP = Character.toString((char) 160); + + /** + * Character class for characters that cannot be in an RSN. + */ + private static final Pattern INVALID_CHARS = Pattern.compile("[^a-zA-Z0-9_ -]"); + + private final Client client; + + /** + * The name currently being autocompleted. + */ + private String autocompleteName; + + /** + * Pattern for the name currently being autocompleted. + */ + private Pattern autocompleteNamePattern; + + @Inject + private NameAutocompleter(@Nullable Client client) + { + this.client = client; + } + + @Override + public void keyPressed(KeyEvent e) + { + + } + + @Override + public void keyReleased(KeyEvent e) + { + + } + + @Override + public void keyTyped(KeyEvent e) + { + final JTextComponent input = (JTextComponent) e.getSource(); + final String inputText = input.getText(); + + // Only autocomplete if the selection end is at the end of the text. + if (input.getSelectionEnd() != inputText.length()) + { + return; + } + + // Character to be inserted at the selection start. + final String charToInsert = Character.toString(e.getKeyChar()); + + // Don't attempt to autocomplete if the name is invalid. + // This condition is also true when the user presses a key like backspace. + if (INVALID_CHARS.matcher(charToInsert).find() + || INVALID_CHARS.matcher(inputText).find()) + { + return; + } + + // Check if we are already autocompleting. + if (autocompleteName != null && autocompleteNamePattern.matcher(inputText).matches()) + { + if (isExpectedNext(input, charToInsert)) + { + try + { + // Insert the character and move the selection. + final int insertIndex = input.getSelectionStart(); + Document doc = input.getDocument(); + doc.remove(insertIndex, 1); + doc.insertString(insertIndex, charToInsert, null); + input.select(insertIndex + 1, input.getSelectionEnd()); + } + catch (BadLocationException ex) + { + log.warn("Could not insert character.", ex); + } + + // Prevent default behavior. + e.consume(); + } + else // Character to insert does not match current autocompletion. Look for another name. + { + newAutocomplete(e); + } + } + else // Search for a name to autocomplete + { + newAutocomplete(e); + } + } + + private void newAutocomplete(KeyEvent e) + { + final JTextComponent input = (JTextComponent) e.getSource(); + final String inputText = input.getText(); + final String nameStart = inputText.substring(0, input.getSelectionStart()) + e.getKeyChar(); + + if (findAutocompleteName(nameStart)) + { + // Assert this.autocompleteName != null + final String name = this.autocompleteName; + SwingUtilities.invokeLater(() -> + { + try + { + input.getDocument().insertString( + nameStart.length(), + name.substring(nameStart.length()), + null); + input.select(nameStart.length(), name.length()); + } + catch (BadLocationException ex) + { + log.warn("Could not autocomplete name.", ex); + } + }); + } + } + + private boolean findAutocompleteName(String nameStart) + { + final Pattern pattern; + Optional autocompleteName; + + // Pattern to match names that start with nameStart. + // Allows spaces to be represented as common whitespaces, underscores, + // hyphens, or non-breaking spaces. + // Matching non-breaking spaces is necessary because the API + // returns non-breaking spaces when a name has whitespace. + pattern = Pattern.compile( + "(?i)^" + nameStart.replaceAll("[ _-]", "[ _" + NBSP + "-]") + ".+?"); + + if (client == null) + { + return false; + } + + autocompleteName = Optional.empty(); + + // TODO: Search lookup history + + Friend[] friends = client.getFriends(); + if (friends != null) + { + autocompleteName = Arrays.stream(friends) + .filter(Objects::nonNull) + .map(Friend::getName) + .filter(n -> pattern.matcher(n).matches()) + .findFirst(); + } + + // Search clan if a friend wasn't found + if (!autocompleteName.isPresent()) + { + final ClanMember[] clannies = client.getClanMembers(); + if (clannies != null) + { + autocompleteName = Arrays.stream(clannies) + .filter(Objects::nonNull) + .map(ClanMember::getUsername) + .filter(n -> pattern.matcher(n).matches()) + .findFirst(); + } + } + + // Search cached players if a clannie wasn't found. + if (!autocompleteName.isPresent()) + { + final Player[] cachedPlayers = client.getCachedPlayers(); + autocompleteName = Arrays.stream(cachedPlayers) + .filter(Objects::nonNull) + .map(Player::getName) + .filter(n -> pattern.matcher(n).matches()) + .findFirst(); + } + + if (autocompleteName.isPresent()) + { + this.autocompleteName = autocompleteName.get().replace(NBSP, " "); + this.autocompleteNamePattern = Pattern.compile( + "(?i)^" + this.autocompleteName.replaceAll("[ _-]", "[ _-]") + "$"); + } + else + { + this.autocompleteName = null; + this.autocompleteNamePattern = null; + } + + return autocompleteName.isPresent(); + } + + private boolean isExpectedNext(JTextComponent input, String nextChar) + { + String expected; + if (input.getSelectionStart() < input.getSelectionEnd()) + { + try + { + expected = input.getText(input.getSelectionStart(), 1); + } + catch (BadLocationException ex) + { + log.warn("Could not get first character from input selection.", ex); + return false; + } + } + else + { + expected = ""; + } + return nextChar.equalsIgnoreCase(expected); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hunter/HunterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hunter/HunterPlugin.java index 1d7c876386..7349352220 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hunter/HunterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hunter/HunterPlugin.java @@ -1,390 +1,390 @@ -/* - * Copyright (c) 2017, Robin Weymans - * 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.hunter; - -import com.google.inject.Provides; -import java.time.Instant; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import javax.inject.Inject; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.GameObject; -import net.runelite.api.ObjectID; -import net.runelite.api.Player; -import net.runelite.api.Tile; -import net.runelite.api.coords.Direction; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GameTick; -import net.runelite.client.Notifier; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -@Slf4j -@PluginDescriptor( - name = "Hunter", - description = "Show the state of your traps", - tags = {"overlay", "skilling", "timers"} -) -public class HunterPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private OverlayManager overlayManager; - - @Inject - private TrapOverlay overlay; - - @Inject - private Notifier notifier; - - @Inject - private HunterConfig config; - - @Getter - private final Map traps = new HashMap<>(); - - @Getter - private Instant lastActionTime = Instant.ofEpochMilli(0); - - private WorldPoint lastTickLocalPlayerLocation; - - @Provides - HunterConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(HunterConfig.class); - } - - @Override - protected void startUp() - { - overlayManager.add(overlay); - overlay.updateConfig(); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - lastActionTime = Instant.ofEpochMilli(0); - traps.clear(); - } - - @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) - { - final GameObject gameObject = event.getGameObject(); - final WorldPoint trapLocation = gameObject.getWorldLocation(); - final HunterTrap myTrap = traps.get(trapLocation); - final Player localPlayer = client.getLocalPlayer(); - - switch (gameObject.getId()) - { - /* - * ------------------------------------------------------------------------------ - * Placing traps - * ------------------------------------------------------------------------------ - */ - case ObjectID.DEADFALL: // Deadfall trap placed - if (localPlayer.getWorldLocation().distanceTo(trapLocation) <= 2) - { - log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), trapLocation); - traps.put(trapLocation, new HunterTrap(gameObject)); - lastActionTime = Instant.now(); - } - break; - - case ObjectID.MONKEY_TRAP: // Maniacal monkey trap placed - // If player is right next to "object" trap assume that player placed the trap - if (localPlayer.getWorldLocation().distanceTo(trapLocation) <= 2) - { - log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), trapLocation); - traps.put(trapLocation, new HunterTrap(gameObject)); - lastActionTime = Instant.now(); - } - break; - - case ObjectID.MAGIC_BOX: // Imp box placed - case ObjectID.BOX_TRAP_9380: // Box trap placed - case ObjectID.BIRD_SNARE_9345: // Bird snare placed - // If the player is on that tile, assume he is the one that placed the trap - // Note that a player can move and set up a trap in the same tick, and this - // event runs after the player movement has been updated, so we need to - // compare to the trap location to the last location of the player. - if (lastTickLocalPlayerLocation != null - && trapLocation.distanceTo(lastTickLocalPlayerLocation) == 0) - { - log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), localPlayer.getWorldLocation()); - traps.put(trapLocation, new HunterTrap(gameObject)); - lastActionTime = Instant.now(); - } - break; - - case ObjectID.NET_TRAP_9343: // Net trap placed at green sallys - case ObjectID.NET_TRAP: // Net trap placed at orange sallys - case ObjectID.NET_TRAP_8992: // Net trap placed at red sallys - case ObjectID.NET_TRAP_9002: // Net trap placed at black sallys - if (lastTickLocalPlayerLocation != null - && trapLocation.distanceTo(lastTickLocalPlayerLocation) == 0) - { - // Net traps facing to the north and east must have their tile translated. - // As otherwise, the wrong tile is stored. - Direction trapOrientation = gameObject.getOrientation().getNearestDirection(); - WorldPoint translatedTrapLocation = trapLocation; - - switch (trapOrientation) - { - case NORTH: - translatedTrapLocation = trapLocation.dy(1); - break; - case EAST: - translatedTrapLocation = trapLocation.dx(1); - break; - } - - log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), translatedTrapLocation); - traps.put(translatedTrapLocation, new HunterTrap(gameObject)); - lastActionTime = Instant.now(); - } - break; - - /* - * ------------------------------------------------------------------------------ - * Catching stuff - * ------------------------------------------------------------------------------ - */ - case ObjectID.MAGIC_BOX_19226: // Imp caught - case ObjectID.SHAKING_BOX: // Black chinchompa caught - case ObjectID.SHAKING_BOX_9382: // Grey chinchompa caught - case ObjectID.SHAKING_BOX_9383: // Red chinchompa caught - case ObjectID.BOULDER_20648: // Prickly kebbit caught - case ObjectID.BOULDER_20649: // Sabre-tooth kebbit caught - case ObjectID.BOULDER_20650: // Barb-tailed kebbit caught - case ObjectID.BOULDER_20651: // Wild kebbit caught - case ObjectID.BIRD_SNARE_9373: // Crimson swift caught - case ObjectID.BIRD_SNARE_9375: // Cerulean twitch caught - case ObjectID.BIRD_SNARE_9377: // Golden warbler caught - case ObjectID.BIRD_SNARE_9379: // Copper longtail caught - case ObjectID.BIRD_SNARE_9348: // Tropical wagtail caught - case ObjectID.NET_TRAP_9004: // Green sally caught - case ObjectID.NET_TRAP_8986: // Red sally caught - case ObjectID.NET_TRAP_8734: // Orange sally caught - case ObjectID.NET_TRAP_8996: // Black sally caught - case ObjectID.LARGE_BOULDER_28830: // Maniacal monkey tail obtained - case ObjectID.LARGE_BOULDER_28831: // Maniacal monkey tail obtained - if (myTrap != null) - { - myTrap.setState(HunterTrap.State.FULL); - myTrap.resetTimer(); - lastActionTime = Instant.now(); - - if (config.maniacalMonkeyNotify() && myTrap.getObjectId() == ObjectID.MONKEY_TRAP) - { - notifier.notify("You've caught part of a monkey's tail."); - } - } - - break; - /* - * ------------------------------------------------------------------------------ - * Failed catch - * ------------------------------------------------------------------------------ - */ - case ObjectID.MAGIC_BOX_FAILED: //Empty imp box - case ObjectID.BOX_TRAP_9385: //Empty box trap - case ObjectID.BIRD_SNARE: //Empty box trap - if (myTrap != null) - { - myTrap.setState(HunterTrap.State.EMPTY); - myTrap.resetTimer(); - lastActionTime = Instant.now(); - } - - break; - /* - * ------------------------------------------------------------------------------ - * Transitions - * ------------------------------------------------------------------------------ - */ - // Imp entering box - case ObjectID.MAGIC_BOX_19225: - - // Black chin shaking box - case ObjectID.BOX_TRAP: - case ObjectID.BOX_TRAP_2026: - case ObjectID.BOX_TRAP_2028: - case ObjectID.BOX_TRAP_2029: - - // Red chin shaking box - case ObjectID.BOX_TRAP_9381: - case ObjectID.BOX_TRAP_9390: - case ObjectID.BOX_TRAP_9391: - case ObjectID.BOX_TRAP_9392: - case ObjectID.BOX_TRAP_9393: - - // Grey chin shaking box - case ObjectID.BOX_TRAP_9386: - case ObjectID.BOX_TRAP_9387: - case ObjectID.BOX_TRAP_9388: - - // Bird traps - case ObjectID.BIRD_SNARE_9346: - case ObjectID.BIRD_SNARE_9347: - case ObjectID.BIRD_SNARE_9349: - case ObjectID.BIRD_SNARE_9374: - case ObjectID.BIRD_SNARE_9376: - case ObjectID.BIRD_SNARE_9378: - - // Deadfall trap - case ObjectID.DEADFALL_19218: - case ObjectID.DEADFALL_19851: - case ObjectID.DEADFALL_20128: - case ObjectID.DEADFALL_20129: - case ObjectID.DEADFALL_20130: - case ObjectID.DEADFALL_20131: - - // Net trap - case ObjectID.NET_TRAP_9003: - case ObjectID.NET_TRAP_9005: - case ObjectID.NET_TRAP_8972: - case ObjectID.NET_TRAP_8974: - case ObjectID.NET_TRAP_8985: - case ObjectID.NET_TRAP_8987: - case ObjectID.NET_TRAP_8993: - case ObjectID.NET_TRAP_8997: - - // Maniacal monkey boulder trap - case ObjectID.MONKEY_TRAP_28828: - case ObjectID.MONKEY_TRAP_28829: - if (myTrap != null) - { - myTrap.setState(HunterTrap.State.TRANSITION); - } - break; - } - } - - /** - * Iterates over all the traps that were placed by the local player and - * checks if the trap is still there. If the trap is gone, it removes - * the trap from the local players trap collection. - */ - @Subscribe - public void onGameTick(GameTick event) - { - // Check if all traps are still there, and remove the ones that are not. - Iterator> it = traps.entrySet().iterator(); - Tile[][][] tiles = client.getScene().getTiles(); - - Instant expire = Instant.now().minus(HunterTrap.TRAP_TIME.multipliedBy(2)); - - while (it.hasNext()) - { - Map.Entry entry = it.next(); - HunterTrap trap = entry.getValue(); - WorldPoint world = entry.getKey(); - LocalPoint local = LocalPoint.fromWorld(client, world); - - // Not within the client's viewport - if (local == null) - { - // Cull very old traps - if (trap.getPlacedOn().isBefore(expire)) - { - log.debug("Trap removed from personal trap collection due to timeout, {} left", traps.size()); - it.remove(); - continue; - } - continue; - } - - Tile tile = tiles[world.getPlane()][local.getSceneX()][local.getSceneY()]; - GameObject[] objects = tile.getGameObjects(); - - boolean containsBoulder = false; - boolean containsAnything = false; - boolean containsYoungTree = false; - for (GameObject object : objects) - { - if (object != null) - { - containsAnything = true; - if (object.getId() == ObjectID.BOULDER_19215 || object.getId() == ObjectID.LARGE_BOULDER) - { - containsBoulder = true; - break; - } - - // Check for young trees (used while catching salamanders) in the tile. - // Otherwise, hunter timers will never disappear after a trap is dismantled - if (object.getId() == ObjectID.YOUNG_TREE_8732 || object.getId() == ObjectID.YOUNG_TREE_8990 || - object.getId() == ObjectID.YOUNG_TREE_9000 || object.getId() == ObjectID.YOUNG_TREE_9341) - { - containsYoungTree = true; - } - } - } - - if (!containsAnything || containsYoungTree) - { - it.remove(); - log.debug("Trap removed from personal trap collection, {} left", traps.size()); - } - else if (containsBoulder) // For traps like deadfalls. This is different because when the trap is gone, there is still a GameObject (boulder) - { - it.remove(); - log.debug("Special trap removed from personal trap collection, {} left", traps.size()); - - // Case we have notifications enabled and the action was not manual, throw notification - if (config.maniacalMonkeyNotify() && trap.getObjectId() == ObjectID.MONKEY_TRAP && - !trap.getState().equals(HunterTrap.State.FULL) && !trap.getState().equals(HunterTrap.State.OPEN)) - { - notifier.notify("The monkey escaped."); - } - } - } - - lastTickLocalPlayerLocation = client.getLocalPlayer().getWorldLocation(); - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("hunterplugin")) - { - overlay.updateConfig(); - } - } -} +/* + * Copyright (c) 2017, Robin Weymans + * 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.hunter; + +import com.google.inject.Provides; +import java.time.Instant; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import javax.inject.Inject; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.ObjectID; +import net.runelite.api.Player; +import net.runelite.api.Tile; +import net.runelite.api.coords.Direction; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GameTick; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +@Slf4j +@PluginDescriptor( + name = "Hunter", + description = "Show the state of your traps", + tags = {"overlay", "skilling", "timers"} +) +public class HunterPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private TrapOverlay overlay; + + @Inject + private Notifier notifier; + + @Inject + private HunterConfig config; + + @Getter + private final Map traps = new HashMap<>(); + + @Getter + private Instant lastActionTime = Instant.ofEpochMilli(0); + + private WorldPoint lastTickLocalPlayerLocation; + + @Provides + HunterConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(HunterConfig.class); + } + + @Override + protected void startUp() + { + overlayManager.add(overlay); + overlay.updateConfig(); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + lastActionTime = Instant.ofEpochMilli(0); + traps.clear(); + } + + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) + { + final GameObject gameObject = event.getGameObject(); + final WorldPoint trapLocation = gameObject.getWorldLocation(); + final HunterTrap myTrap = traps.get(trapLocation); + final Player localPlayer = client.getLocalPlayer(); + + switch (gameObject.getId()) + { + /* + * ------------------------------------------------------------------------------ + * Placing traps + * ------------------------------------------------------------------------------ + */ + case ObjectID.DEADFALL: // Deadfall trap placed + if (localPlayer.getWorldLocation().distanceTo(trapLocation) <= 2) + { + log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), trapLocation); + traps.put(trapLocation, new HunterTrap(gameObject)); + lastActionTime = Instant.now(); + } + break; + + case ObjectID.MONKEY_TRAP: // Maniacal monkey trap placed + // If player is right next to "object" trap assume that player placed the trap + if (localPlayer.getWorldLocation().distanceTo(trapLocation) <= 2) + { + log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), trapLocation); + traps.put(trapLocation, new HunterTrap(gameObject)); + lastActionTime = Instant.now(); + } + break; + + case ObjectID.MAGIC_BOX: // Imp box placed + case ObjectID.BOX_TRAP_9380: // Box trap placed + case ObjectID.BIRD_SNARE_9345: // Bird snare placed + // If the player is on that tile, assume he is the one that placed the trap + // Note that a player can move and set up a trap in the same tick, and this + // event runs after the player movement has been updated, so we need to + // compare to the trap location to the last location of the player. + if (lastTickLocalPlayerLocation != null + && trapLocation.distanceTo(lastTickLocalPlayerLocation) == 0) + { + log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), localPlayer.getWorldLocation()); + traps.put(trapLocation, new HunterTrap(gameObject)); + lastActionTime = Instant.now(); + } + break; + + case ObjectID.NET_TRAP_9343: // Net trap placed at green sallys + case ObjectID.NET_TRAP: // Net trap placed at orange sallys + case ObjectID.NET_TRAP_8992: // Net trap placed at red sallys + case ObjectID.NET_TRAP_9002: // Net trap placed at black sallys + if (lastTickLocalPlayerLocation != null + && trapLocation.distanceTo(lastTickLocalPlayerLocation) == 0) + { + // Net traps facing to the north and east must have their tile translated. + // As otherwise, the wrong tile is stored. + Direction trapOrientation = gameObject.getOrientation().getNearestDirection(); + WorldPoint translatedTrapLocation = trapLocation; + + switch (trapOrientation) + { + case NORTH: + translatedTrapLocation = trapLocation.dy(1); + break; + case EAST: + translatedTrapLocation = trapLocation.dx(1); + break; + } + + log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), translatedTrapLocation); + traps.put(translatedTrapLocation, new HunterTrap(gameObject)); + lastActionTime = Instant.now(); + } + break; + + /* + * ------------------------------------------------------------------------------ + * Catching stuff + * ------------------------------------------------------------------------------ + */ + case ObjectID.MAGIC_BOX_19226: // Imp caught + case ObjectID.SHAKING_BOX: // Black chinchompa caught + case ObjectID.SHAKING_BOX_9382: // Grey chinchompa caught + case ObjectID.SHAKING_BOX_9383: // Red chinchompa caught + case ObjectID.BOULDER_20648: // Prickly kebbit caught + case ObjectID.BOULDER_20649: // Sabre-tooth kebbit caught + case ObjectID.BOULDER_20650: // Barb-tailed kebbit caught + case ObjectID.BOULDER_20651: // Wild kebbit caught + case ObjectID.BIRD_SNARE_9373: // Crimson swift caught + case ObjectID.BIRD_SNARE_9375: // Cerulean twitch caught + case ObjectID.BIRD_SNARE_9377: // Golden warbler caught + case ObjectID.BIRD_SNARE_9379: // Copper longtail caught + case ObjectID.BIRD_SNARE_9348: // Tropical wagtail caught + case ObjectID.NET_TRAP_9004: // Green sally caught + case ObjectID.NET_TRAP_8986: // Red sally caught + case ObjectID.NET_TRAP_8734: // Orange sally caught + case ObjectID.NET_TRAP_8996: // Black sally caught + case ObjectID.LARGE_BOULDER_28830: // Maniacal monkey tail obtained + case ObjectID.LARGE_BOULDER_28831: // Maniacal monkey tail obtained + if (myTrap != null) + { + myTrap.setState(HunterTrap.State.FULL); + myTrap.resetTimer(); + lastActionTime = Instant.now(); + + if (config.maniacalMonkeyNotify() && myTrap.getObjectId() == ObjectID.MONKEY_TRAP) + { + notifier.notify("You've caught part of a monkey's tail."); + } + } + + break; + /* + * ------------------------------------------------------------------------------ + * Failed catch + * ------------------------------------------------------------------------------ + */ + case ObjectID.MAGIC_BOX_FAILED: //Empty imp box + case ObjectID.BOX_TRAP_9385: //Empty box trap + case ObjectID.BIRD_SNARE: //Empty box trap + if (myTrap != null) + { + myTrap.setState(HunterTrap.State.EMPTY); + myTrap.resetTimer(); + lastActionTime = Instant.now(); + } + + break; + /* + * ------------------------------------------------------------------------------ + * Transitions + * ------------------------------------------------------------------------------ + */ + // Imp entering box + case ObjectID.MAGIC_BOX_19225: + + // Black chin shaking box + case ObjectID.BOX_TRAP: + case ObjectID.BOX_TRAP_2026: + case ObjectID.BOX_TRAP_2028: + case ObjectID.BOX_TRAP_2029: + + // Red chin shaking box + case ObjectID.BOX_TRAP_9381: + case ObjectID.BOX_TRAP_9390: + case ObjectID.BOX_TRAP_9391: + case ObjectID.BOX_TRAP_9392: + case ObjectID.BOX_TRAP_9393: + + // Grey chin shaking box + case ObjectID.BOX_TRAP_9386: + case ObjectID.BOX_TRAP_9387: + case ObjectID.BOX_TRAP_9388: + + // Bird traps + case ObjectID.BIRD_SNARE_9346: + case ObjectID.BIRD_SNARE_9347: + case ObjectID.BIRD_SNARE_9349: + case ObjectID.BIRD_SNARE_9374: + case ObjectID.BIRD_SNARE_9376: + case ObjectID.BIRD_SNARE_9378: + + // Deadfall trap + case ObjectID.DEADFALL_19218: + case ObjectID.DEADFALL_19851: + case ObjectID.DEADFALL_20128: + case ObjectID.DEADFALL_20129: + case ObjectID.DEADFALL_20130: + case ObjectID.DEADFALL_20131: + + // Net trap + case ObjectID.NET_TRAP_9003: + case ObjectID.NET_TRAP_9005: + case ObjectID.NET_TRAP_8972: + case ObjectID.NET_TRAP_8974: + case ObjectID.NET_TRAP_8985: + case ObjectID.NET_TRAP_8987: + case ObjectID.NET_TRAP_8993: + case ObjectID.NET_TRAP_8997: + + // Maniacal monkey boulder trap + case ObjectID.MONKEY_TRAP_28828: + case ObjectID.MONKEY_TRAP_28829: + if (myTrap != null) + { + myTrap.setState(HunterTrap.State.TRANSITION); + } + break; + } + } + + /** + * Iterates over all the traps that were placed by the local player and + * checks if the trap is still there. If the trap is gone, it removes + * the trap from the local players trap collection. + */ + @Subscribe + public void onGameTick(GameTick event) + { + // Check if all traps are still there, and remove the ones that are not. + Iterator> it = traps.entrySet().iterator(); + Tile[][][] tiles = client.getScene().getTiles(); + + Instant expire = Instant.now().minus(HunterTrap.TRAP_TIME.multipliedBy(2)); + + while (it.hasNext()) + { + Map.Entry entry = it.next(); + HunterTrap trap = entry.getValue(); + WorldPoint world = entry.getKey(); + LocalPoint local = LocalPoint.fromWorld(client, world); + + // Not within the client's viewport + if (local == null) + { + // Cull very old traps + if (trap.getPlacedOn().isBefore(expire)) + { + log.debug("Trap removed from personal trap collection due to timeout, {} left", traps.size()); + it.remove(); + continue; + } + continue; + } + + Tile tile = tiles[world.getPlane()][local.getSceneX()][local.getSceneY()]; + GameObject[] objects = tile.getGameObjects(); + + boolean containsBoulder = false; + boolean containsAnything = false; + boolean containsYoungTree = false; + for (GameObject object : objects) + { + if (object != null) + { + containsAnything = true; + if (object.getId() == ObjectID.BOULDER_19215 || object.getId() == ObjectID.LARGE_BOULDER) + { + containsBoulder = true; + break; + } + + // Check for young trees (used while catching salamanders) in the tile. + // Otherwise, hunter timers will never disappear after a trap is dismantled + if (object.getId() == ObjectID.YOUNG_TREE_8732 || object.getId() == ObjectID.YOUNG_TREE_8990 || + object.getId() == ObjectID.YOUNG_TREE_9000 || object.getId() == ObjectID.YOUNG_TREE_9341) + { + containsYoungTree = true; + } + } + } + + if (!containsAnything || containsYoungTree) + { + it.remove(); + log.debug("Trap removed from personal trap collection, {} left", traps.size()); + } + else if (containsBoulder) // For traps like deadfalls. This is different because when the trap is gone, there is still a GameObject (boulder) + { + it.remove(); + log.debug("Special trap removed from personal trap collection, {} left", traps.size()); + + // Case we have notifications enabled and the action was not manual, throw notification + if (config.maniacalMonkeyNotify() && trap.getObjectId() == ObjectID.MONKEY_TRAP && + !trap.getState().equals(HunterTrap.State.FULL) && !trap.getState().equals(HunterTrap.State.OPEN)) + { + notifier.notify("The monkey escaped."); + } + } + } + + lastTickLocalPlayerLocation = client.getLocalPlayer().getWorldLocation(); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("hunterplugin")) + { + overlay.updateConfig(); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hunter/TrapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/hunter/TrapOverlay.java index 1e0f23b358..ed9038693d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hunter/TrapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hunter/TrapOverlay.java @@ -1,189 +1,189 @@ -/* - * Copyright (c) 2017, Robin Weymans - * 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.hunter; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.util.Map; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.ProgressPieComponent; - -/** - * Represents the overlay that shows timers on traps that are placed by the - * player. - */ -public class TrapOverlay extends Overlay -{ - /** - * The timer is low when only 25% is left. - */ - private static final double TIMER_LOW = 0.25; // When the timer is under a quarter left, if turns red. - - private final Client client; - private final HunterPlugin plugin; - private final HunterConfig config; - - private Color colorOpen, colorOpenBorder; - private Color colorEmpty, colorEmptyBorder; - private Color colorFull, colorFullBorder; - private Color colorTrans, colorTransBorder; - - @Inject - TrapOverlay(Client client, HunterPlugin plugin, HunterConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.plugin = plugin; - this.config = config; - this.client = client; - } - - @Override - public Dimension render(Graphics2D graphics) - { - drawTraps(graphics); - return null; - } - - /** - * Updates the timer colors. - */ - public void updateConfig() - { - colorEmptyBorder = config.getEmptyTrapColor(); - colorEmpty = new Color(colorEmptyBorder.getRed(), colorEmptyBorder.getGreen(), colorEmptyBorder.getBlue(), 100); - colorFullBorder = config.getFullTrapColor(); - colorFull = new Color(colorFullBorder.getRed(), colorFullBorder.getGreen(), colorFullBorder.getBlue(), 100); - colorOpenBorder = config.getOpenTrapColor(); - colorOpen = new Color(colorOpenBorder.getRed(), colorOpenBorder.getGreen(), colorOpenBorder.getBlue(), 100); - colorTransBorder = config.getTransTrapColor(); - colorTrans = new Color(colorTransBorder.getRed(), colorTransBorder.getGreen(), colorTransBorder.getBlue(), 100); - } - - /** - * Iterates over all the traps that were placed by the local player, and - * draws a circle or a timer on the trap, depending on the trap state. - * - * @param graphics - */ - private void drawTraps(Graphics2D graphics) - { - for (Map.Entry entry : plugin.getTraps().entrySet()) - { - HunterTrap trap = entry.getValue(); - - switch (trap.getState()) - { - case OPEN: - drawTimerOnTrap(graphics, trap, colorOpen, colorOpenBorder, colorEmpty, colorOpenBorder); - break; - case EMPTY: - drawTimerOnTrap(graphics, trap, colorEmpty, colorEmptyBorder, colorEmpty, colorEmptyBorder); - break; - case FULL: - drawTimerOnTrap(graphics, trap, colorFull, colorFullBorder, colorFull, colorFullBorder); - break; - case TRANSITION: - drawCircleOnTrap(graphics, trap, colorTrans, colorTransBorder); - break; - } - } - } - - /** - * Draws a timer on a given trap. - * - * @param graphics - * @param trap The trap on which the timer needs to be drawn - * @param fill The fill color of the timer - * @param border The border color of the timer - * @param fillTimeLow The fill color of the timer when it is low - * @param borderTimeLow The border color of the timer when it is low - */ - private void drawTimerOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border, Color fillTimeLow, Color borderTimeLow) - { - if (trap.getWorldLocation().getPlane() != client.getPlane()) - { - return; - } - LocalPoint localLoc = LocalPoint.fromWorld(client, trap.getWorldLocation()); - if (localLoc == null) - { - return; - } - net.runelite.api.Point loc = Perspective.localToCanvas(client, localLoc, client.getPlane()); - - if (loc == null) - { - return; - } - - double timeLeft = 1 - trap.getTrapTimeRelative(); - - ProgressPieComponent pie = new ProgressPieComponent(); - pie.setFill(timeLeft > TIMER_LOW ? fill : fillTimeLow); - pie.setBorderColor(timeLeft > TIMER_LOW ? border : borderTimeLow); - pie.setPosition(loc); - pie.setProgress(timeLeft); - pie.render(graphics); - } - - /** - * Draws a timer on a given trap. - * - * @param graphics - * @param trap The trap on which the timer needs to be drawn - * @param fill The fill color of the timer - * @param border The border color of the timer - */ - private void drawCircleOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border) - { - if (trap.getWorldLocation().getPlane() != client.getPlane()) - { - return; - } - LocalPoint localLoc = LocalPoint.fromWorld(client, trap.getWorldLocation()); - if (localLoc == null) - { - return; - } - net.runelite.api.Point loc = Perspective.localToCanvas(client, localLoc, client.getPlane()); - - ProgressPieComponent pie = new ProgressPieComponent(); - pie.setFill(fill); - pie.setBorderColor(border); - pie.setPosition(loc); - pie.setProgress(1); - pie.render(graphics); - } -} +/* + * Copyright (c) 2017, Robin Weymans + * 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.hunter; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.util.Map; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ProgressPieComponent; + +/** + * Represents the overlay that shows timers on traps that are placed by the + * player. + */ +public class TrapOverlay extends Overlay +{ + /** + * The timer is low when only 25% is left. + */ + private static final double TIMER_LOW = 0.25; // When the timer is under a quarter left, if turns red. + + private final Client client; + private final HunterPlugin plugin; + private final HunterConfig config; + + private Color colorOpen, colorOpenBorder; + private Color colorEmpty, colorEmptyBorder; + private Color colorFull, colorFullBorder; + private Color colorTrans, colorTransBorder; + + @Inject + TrapOverlay(Client client, HunterPlugin plugin, HunterConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.plugin = plugin; + this.config = config; + this.client = client; + } + + @Override + public Dimension render(Graphics2D graphics) + { + drawTraps(graphics); + return null; + } + + /** + * Updates the timer colors. + */ + public void updateConfig() + { + colorEmptyBorder = config.getEmptyTrapColor(); + colorEmpty = new Color(colorEmptyBorder.getRed(), colorEmptyBorder.getGreen(), colorEmptyBorder.getBlue(), 100); + colorFullBorder = config.getFullTrapColor(); + colorFull = new Color(colorFullBorder.getRed(), colorFullBorder.getGreen(), colorFullBorder.getBlue(), 100); + colorOpenBorder = config.getOpenTrapColor(); + colorOpen = new Color(colorOpenBorder.getRed(), colorOpenBorder.getGreen(), colorOpenBorder.getBlue(), 100); + colorTransBorder = config.getTransTrapColor(); + colorTrans = new Color(colorTransBorder.getRed(), colorTransBorder.getGreen(), colorTransBorder.getBlue(), 100); + } + + /** + * Iterates over all the traps that were placed by the local player, and + * draws a circle or a timer on the trap, depending on the trap state. + * + * @param graphics + */ + private void drawTraps(Graphics2D graphics) + { + for (Map.Entry entry : plugin.getTraps().entrySet()) + { + HunterTrap trap = entry.getValue(); + + switch (trap.getState()) + { + case OPEN: + drawTimerOnTrap(graphics, trap, colorOpen, colorOpenBorder, colorEmpty, colorOpenBorder); + break; + case EMPTY: + drawTimerOnTrap(graphics, trap, colorEmpty, colorEmptyBorder, colorEmpty, colorEmptyBorder); + break; + case FULL: + drawTimerOnTrap(graphics, trap, colorFull, colorFullBorder, colorFull, colorFullBorder); + break; + case TRANSITION: + drawCircleOnTrap(graphics, trap, colorTrans, colorTransBorder); + break; + } + } + } + + /** + * Draws a timer on a given trap. + * + * @param graphics + * @param trap The trap on which the timer needs to be drawn + * @param fill The fill color of the timer + * @param border The border color of the timer + * @param fillTimeLow The fill color of the timer when it is low + * @param borderTimeLow The border color of the timer when it is low + */ + private void drawTimerOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border, Color fillTimeLow, Color borderTimeLow) + { + if (trap.getWorldLocation().getPlane() != client.getPlane()) + { + return; + } + LocalPoint localLoc = LocalPoint.fromWorld(client, trap.getWorldLocation()); + if (localLoc == null) + { + return; + } + net.runelite.api.Point loc = Perspective.localToCanvas(client, localLoc, client.getPlane()); + + if (loc == null) + { + return; + } + + double timeLeft = 1 - trap.getTrapTimeRelative(); + + ProgressPieComponent pie = new ProgressPieComponent(); + pie.setFill(timeLeft > TIMER_LOW ? fill : fillTimeLow); + pie.setBorderColor(timeLeft > TIMER_LOW ? border : borderTimeLow); + pie.setPosition(loc); + pie.setProgress(timeLeft); + pie.render(graphics); + } + + /** + * Draws a timer on a given trap. + * + * @param graphics + * @param trap The trap on which the timer needs to be drawn + * @param fill The fill color of the timer + * @param border The border color of the timer + */ + private void drawCircleOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border) + { + if (trap.getWorldLocation().getPlane() != client.getPlane()) + { + return; + } + LocalPoint localLoc = LocalPoint.fromWorld(client, trap.getWorldLocation()); + if (localLoc == null) + { + return; + } + net.runelite.api.Point loc = Perspective.localToCanvas(client, localLoc, client.getPlane()); + + ProgressPieComponent pie = new ProgressPieComponent(); + pie.setFill(fill); + pie.setBorderColor(border); + pie.setPosition(loc); + pie.setProgress(1); + pie.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java index 49c94a2fa1..d290452237 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java @@ -36,7 +36,6 @@ import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; 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 38b56f8505..accdc1d1d2 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 @@ -26,8 +26,7 @@ package net.runelite.client.plugins.idlenotifier; import com.google.inject.Provides; - -import java.awt.*; +import java.awt.TrayIcon; import java.time.Duration; import java.time.Instant; import java.util.Arrays; @@ -36,7 +35,93 @@ import java.util.List; import javax.inject.Inject; import net.runelite.api.Actor; import net.runelite.api.AnimationID; -import static net.runelite.api.AnimationID.*; +import static net.runelite.api.AnimationID.COOKING_FIRE; +import static net.runelite.api.AnimationID.COOKING_RANGE; +import static net.runelite.api.AnimationID.COOKING_WINE; +import static net.runelite.api.AnimationID.CRAFTING_BATTLESTAVES; +import static net.runelite.api.AnimationID.CRAFTING_GLASSBLOWING; +import static net.runelite.api.AnimationID.CRAFTING_LEATHER; +import static net.runelite.api.AnimationID.CRAFTING_POTTERS_WHEEL; +import static net.runelite.api.AnimationID.CRAFTING_POTTERY_OVEN; +import static net.runelite.api.AnimationID.CRAFTING_SPINNING; +import static net.runelite.api.AnimationID.DENSE_ESSENCE_CHIPPING; +import static net.runelite.api.AnimationID.DENSE_ESSENCE_CHISELING; +import static net.runelite.api.AnimationID.FARMING_MIX_ULTRACOMPOST; +import static net.runelite.api.AnimationID.FISHING_CRUSHING_INFERNAL_EELS; +import static net.runelite.api.AnimationID.FISHING_CUTTING_SACRED_EELS; +import static net.runelite.api.AnimationID.FLETCHING_BOW_CUTTING; +import static net.runelite.api.AnimationID.FLETCHING_STRING_MAGIC_LONGBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_MAGIC_SHORTBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_MAPLE_LONGBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_MAPLE_SHORTBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_NORMAL_LONGBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_NORMAL_SHORTBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_OAK_LONGBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_OAK_SHORTBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_WILLOW_LONGBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_WILLOW_SHORTBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_YEW_LONGBOW; +import static net.runelite.api.AnimationID.FLETCHING_STRING_YEW_SHORTBOW; +import static net.runelite.api.AnimationID.GEM_CUTTING_AMETHYST; +import static net.runelite.api.AnimationID.GEM_CUTTING_DIAMOND; +import static net.runelite.api.AnimationID.GEM_CUTTING_EMERALD; +import static net.runelite.api.AnimationID.GEM_CUTTING_JADE; +import static net.runelite.api.AnimationID.GEM_CUTTING_OPAL; +import static net.runelite.api.AnimationID.GEM_CUTTING_REDTOPAZ; +import static net.runelite.api.AnimationID.GEM_CUTTING_RUBY; +import static net.runelite.api.AnimationID.GEM_CUTTING_SAPPHIRE; +import static net.runelite.api.AnimationID.HERBLORE_MAKE_TAR; +import static net.runelite.api.AnimationID.HERBLORE_PESTLE_AND_MORTAR; +import static net.runelite.api.AnimationID.HERBLORE_POTIONMAKING; +import static net.runelite.api.AnimationID.HOME_MAKE_TABLET; +import static net.runelite.api.AnimationID.IDLE; +import static net.runelite.api.AnimationID.MAGIC_CHARGING_ORBS; +import static net.runelite.api.AnimationID.MAGIC_ENCHANTING_AMULET_1; +import static net.runelite.api.AnimationID.MAGIC_ENCHANTING_AMULET_2; +import static net.runelite.api.AnimationID.MAGIC_ENCHANTING_AMULET_3; +import static net.runelite.api.AnimationID.MAGIC_ENCHANTING_JEWELRY; +import static net.runelite.api.AnimationID.MAGIC_LUNAR_PLANK_MAKE; +import static net.runelite.api.AnimationID.MAGIC_LUNAR_SHARED; +import static net.runelite.api.AnimationID.MAGIC_LUNAR_STRING_JEWELRY; +import static net.runelite.api.AnimationID.MAGIC_MAKE_TABLET; +import static net.runelite.api.AnimationID.MINING_3A_PICKAXE; +import static net.runelite.api.AnimationID.MINING_ADAMANT_PICKAXE; +import static net.runelite.api.AnimationID.MINING_BLACK_PICKAXE; +import static net.runelite.api.AnimationID.MINING_BRONZE_PICKAXE; +import static net.runelite.api.AnimationID.MINING_DRAGON_PICKAXE; +import static net.runelite.api.AnimationID.MINING_DRAGON_PICKAXE_ORN; +import static net.runelite.api.AnimationID.MINING_INFERNAL_PICKAXE; +import static net.runelite.api.AnimationID.MINING_IRON_PICKAXE; +import static net.runelite.api.AnimationID.MINING_MITHRIL_PICKAXE; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_3A; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_ADAMANT; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BLACK; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BRONZE; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_ORN; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_INFERNAL; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_IRON; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_MITHRIL; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_RUNE; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_STEEL; +import static net.runelite.api.AnimationID.MINING_RUNE_PICKAXE; +import static net.runelite.api.AnimationID.MINING_STEEL_PICKAXE; +import static net.runelite.api.AnimationID.PISCARILIUS_CRANE_REPAIR; +import static net.runelite.api.AnimationID.SAND_COLLECTION; +import static net.runelite.api.AnimationID.SMITHING_ANVIL; +import static net.runelite.api.AnimationID.SMITHING_CANNONBALL; +import static net.runelite.api.AnimationID.SMITHING_SMELTING; +import static net.runelite.api.AnimationID.USING_GILDED_ALTAR; +import static net.runelite.api.AnimationID.WOODCUTTING_3A_AXE; +import static net.runelite.api.AnimationID.WOODCUTTING_ADAMANT; +import static net.runelite.api.AnimationID.WOODCUTTING_BLACK; +import static net.runelite.api.AnimationID.WOODCUTTING_BRONZE; +import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON; +import static net.runelite.api.AnimationID.WOODCUTTING_INFERNAL; +import static net.runelite.api.AnimationID.WOODCUTTING_IRON; +import static net.runelite.api.AnimationID.WOODCUTTING_MITHRIL; +import static net.runelite.api.AnimationID.WOODCUTTING_RUNE; +import static net.runelite.api.AnimationID.WOODCUTTING_STEEL; import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.GameState; @@ -143,11 +228,11 @@ public class IdleNotifierPlugin extends Plugin case WOODCUTTING_DRAGON: case WOODCUTTING_INFERNAL: case WOODCUTTING_3A_AXE: - /* Cooking(Fire, Range) */ + /* Cooking(Fire, Range) */ case COOKING_FIRE: case COOKING_RANGE: case COOKING_WINE: - /* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves, Pottery) */ + /* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves, Pottery) */ case GEM_CUTTING_OPAL: case GEM_CUTTING_JADE: case GEM_CUTTING_REDTOPAZ: @@ -162,7 +247,7 @@ public class IdleNotifierPlugin extends Plugin case CRAFTING_LEATHER: case CRAFTING_POTTERS_WHEEL: case CRAFTING_POTTERY_OVEN: - /* Fletching(Cutting, Stringing) */ + /* Fletching(Cutting, Stringing) */ case FLETCHING_BOW_CUTTING: case FLETCHING_STRING_NORMAL_SHORTBOW: case FLETCHING_STRING_OAK_SHORTBOW: @@ -176,14 +261,14 @@ public class IdleNotifierPlugin extends Plugin case FLETCHING_STRING_MAPLE_LONGBOW: case FLETCHING_STRING_YEW_LONGBOW: case FLETCHING_STRING_MAGIC_LONGBOW: - /* Smithing(Anvil, Furnace, Cannonballs */ + /* Smithing(Anvil, Furnace, Cannonballs */ case SMITHING_ANVIL: case SMITHING_SMELTING: case SMITHING_CANNONBALL: - /* Fishing */ + /* Fishing */ case FISHING_CRUSHING_INFERNAL_EELS: case FISHING_CUTTING_SACRED_EELS: - /* Mining(Normal) */ + /* Mining(Normal) */ case MINING_BRONZE_PICKAXE: case MINING_IRON_PICKAXE: case MINING_STEEL_PICKAXE: @@ -197,7 +282,7 @@ public class IdleNotifierPlugin extends Plugin case MINING_3A_PICKAXE: case DENSE_ESSENCE_CHIPPING: case DENSE_ESSENCE_CHISELING: - /* Mining(Motherlode) */ + /* Mining(Motherlode) */ case MINING_MOTHERLODE_BRONZE: case MINING_MOTHERLODE_IRON: case MINING_MOTHERLODE_STEEL: @@ -209,11 +294,11 @@ public class IdleNotifierPlugin extends Plugin case MINING_MOTHERLODE_DRAGON_ORN: case MINING_MOTHERLODE_INFERNAL: case MINING_MOTHERLODE_3A: - /* Herblore */ + /* Herblore */ case HERBLORE_PESTLE_AND_MORTAR: case HERBLORE_POTIONMAKING: case HERBLORE_MAKE_TAR: - /* Magic */ + /* Magic */ case MAGIC_CHARGING_ORBS: case MAGIC_LUNAR_PLANK_MAKE: case MAGIC_LUNAR_STRING_JEWELRY: @@ -222,11 +307,11 @@ public class IdleNotifierPlugin extends Plugin case MAGIC_ENCHANTING_AMULET_1: case MAGIC_ENCHANTING_AMULET_2: case MAGIC_ENCHANTING_AMULET_3: - /* Prayer */ + /* Prayer */ case USING_GILDED_ALTAR: - /* Farming */ + /* Farming */ case FARMING_MIX_ULTRACOMPOST: - /* Misc */ + /* Misc */ case PISCARILIUS_CRANE_REPAIR: case HOME_MAKE_TABLET: case SAND_COLLECTION: diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java index f2c8352680..386284a874 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java @@ -30,7 +30,6 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; /** - * * @author robin */ @ConfigGroup("implings") @@ -312,10 +311,10 @@ public interface ImplingsConfig extends Config } @ConfigItem( - position = 26, - keyName = "spawnColorDynamic", - name = "Impling dynamic spawn color", - description = "Text color for dynamic impling spawns in Puro Puro" + position = 26, + keyName = "spawnColorDynamic", + name = "Impling dynamic spawn color", + description = "Text color for dynamic impling spawns in Puro Puro" ) default Color getDynamicSpawnColor() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsOverlay.java index aaba9e0851..27df5aef14 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsOverlay.java @@ -35,8 +35,8 @@ import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.NPC; import net.runelite.api.NPCComposition; -import net.runelite.api.Point; import net.runelite.api.Perspective; +import net.runelite.api.Point; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import net.runelite.client.ui.overlay.Overlay; @@ -100,7 +100,7 @@ public class ImplingsOverlay extends Overlay //Draw dynamic spawns Map dynamicSpawns = plugin.getDynamicSpawns(); - for (Map.Entry dynamicSpawn : dynamicSpawns.entrySet()) + for (Map.Entry dynamicSpawn : dynamicSpawns.entrySet()) { drawDynamicSpawn(graphics, dynamicSpawn.getKey(), dynamicSpawn.getValue(), config.getDynamicSpawnColor()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java index a697f332d2..d9d93d8f23 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java @@ -1,312 +1,311 @@ -/* - * Copyright (c) 2018 Abex - * Copyright (c) 2018, Psikoi - * 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.info; - -import com.google.common.base.MoreObjects; -import com.google.inject.Inject; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.GridLayout; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.Nullable; -import javax.inject.Singleton; -import javax.swing.Box; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.border.EmptyBorder; -import javax.swing.event.HyperlinkEvent; -import net.runelite.api.Client; -import net.runelite.client.RuneLite; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.RuneLiteProperties; -import net.runelite.client.account.SessionManager; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.LinkBrowser; - -@Singleton -public class InfoPanel extends PluginPanel -{ - private static final String RUNELITE_LOGIN = "https://runelite_login/"; - - private static final ImageIcon ARROW_RIGHT_ICON; - private static final ImageIcon GITHUB_ICON; - private static final ImageIcon DISCORD_ICON; - private static final ImageIcon PATREON_ICON; - private static final ImageIcon WIKI_ICON; - private static final ImageIcon IMPORT_ICON; - - private final JLabel loggedLabel = new JLabel(); - private final JRichTextPane emailLabel = new JRichTextPane(); - private JPanel syncPanel; - private JPanel actionsContainer; - - @Inject - @Nullable - private Client client; - - @Inject - private RuneLiteProperties runeLiteProperties; - - @Inject - private EventBus eventBus; - - @Inject - private SessionManager sessionManager; - - @Inject - private ScheduledExecutorService executor; - - @Inject - private ConfigManager configManager; - - static - { - ARROW_RIGHT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/util/arrow_right.png")); - GITHUB_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "github_icon.png")); - DISCORD_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "discord_icon.png")); - PATREON_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "patreon_icon.png")); - WIKI_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "wiki_icon.png")); - IMPORT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "import_icon.png")); - } - - void init() - { - setLayout(new BorderLayout()); - setBackground(ColorScheme.DARK_GRAY_COLOR); - setBorder(new EmptyBorder(10, 10, 10, 10)); - - JPanel versionPanel = new JPanel(); - versionPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - versionPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); - versionPanel.setLayout(new GridLayout(0, 1)); - - final Font smallFont = FontManager.getRunescapeSmallFont(); - - JLabel version = new JLabel(htmlLabel("RuneLite version: ", runeLiteProperties.getVersion())); - version.setFont(smallFont); - - JLabel revision = new JLabel(); - revision.setFont(smallFont); - - String engineVer = "Unknown"; - if (client != null) - { - engineVer = String.format("Rev %d", client.getRevision()); - } - - revision.setText(htmlLabel("Oldschool revision: ", engineVer)); - - JLabel launcher = new JLabel(htmlLabel("Launcher version: ", MoreObjects - .firstNonNull(RuneLiteProperties.getLauncherVersion(), "Unknown"))); - launcher.setFont(smallFont); - - loggedLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - loggedLabel.setFont(smallFont); - - emailLabel.setForeground(Color.WHITE); - emailLabel.setFont(smallFont); - emailLabel.enableAutoLinkHandler(false); - emailLabel.addHyperlinkListener(e -> - { - if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null) - { - if (e.getURL().toString().equals(RUNELITE_LOGIN)) - { - executor.execute(sessionManager::login); - } - } - }); - - versionPanel.add(version); - versionPanel.add(revision); - versionPanel.add(launcher); - versionPanel.add(Box.createGlue()); - versionPanel.add(loggedLabel); - versionPanel.add(emailLabel); - - actionsContainer = new JPanel(); - actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0)); - actionsContainer.setLayout(new GridLayout(0, 1, 0, 10)); - - syncPanel = buildLinkPanel(IMPORT_ICON, "Import local settings", "to remote RuneLite account", () -> - { - final int result = JOptionPane.showOptionDialog(syncPanel, - "This will replace your current RuneLite account settings with settings from your local profile.", - "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, - null, new String[]{"Yes", "No"}, "No"); - - if (result == JOptionPane.YES_OPTION) - { - configManager.importLocal(); - } - }); - - actionsContainer.add(buildLinkPanel(GITHUB_ICON, "License info", "for distribution", "https://github.com/runelite-extended/runelite/blob/master/LICENSE")); - actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", "https://discord.gg/s2fzu5U")); - actionsContainer.add(buildLinkPanel(PATREON_ICON, "Patreon to support", "the RuneLite devs", runeLiteProperties.getPatreonLink())); -/* actionsContainer.add(buildLinkPanel(WIKI_ICON, "Information about", "RuneLite and plugins", runeLiteProperties.getWikiLink()));*/ - - add(versionPanel, BorderLayout.NORTH); - add(actionsContainer, BorderLayout.CENTER); - - updateLoggedIn(); - eventBus.register(this); - } - - /** - * Builds a link panel with a given icon, text and url to redirect to. - */ - private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url) - { - return buildLinkPanel(icon, topText, bottomText, () -> LinkBrowser.browse(url)); - } - - /** - * Builds a link panel with a given icon, text and callable to call. - */ - private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, Runnable callback) - { - JPanel container = new JPanel(); - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - container.setLayout(new BorderLayout()); - container.setBorder(new EmptyBorder(10, 10, 10, 10)); - - final Color hoverColor = ColorScheme.DARKER_GRAY_HOVER_COLOR; - final Color pressedColor = ColorScheme.DARKER_GRAY_COLOR.brighter(); - - JLabel iconLabel = new JLabel(icon); - container.add(iconLabel, BorderLayout.WEST); - - JPanel textContainer = new JPanel(); - textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - textContainer.setLayout(new GridLayout(2, 1)); - textContainer.setBorder(new EmptyBorder(5, 10, 5, 10)); - - container.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - container.setBackground(pressedColor); - textContainer.setBackground(pressedColor); - } - - @Override - public void mouseReleased(MouseEvent e) - { - callback.run(); - container.setBackground(hoverColor); - textContainer.setBackground(hoverColor); - } - - @Override - public void mouseEntered(MouseEvent e) - { - container.setBackground(hoverColor); - textContainer.setBackground(hoverColor); - container.setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - @Override - public void mouseExited(MouseEvent e) - { - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - container.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - JLabel topLine = new JLabel(topText); - topLine.setForeground(Color.WHITE); - topLine.setFont(FontManager.getRunescapeSmallFont()); - - JLabel bottomLine = new JLabel(bottomText); - bottomLine.setForeground(Color.WHITE); - bottomLine.setFont(FontManager.getRunescapeSmallFont()); - - textContainer.add(topLine); - textContainer.add(bottomLine); - - container.add(textContainer, BorderLayout.CENTER); - - JLabel arrowLabel = new JLabel(ARROW_RIGHT_ICON); - container.add(arrowLabel, BorderLayout.EAST); - - return container; - } - - private void updateLoggedIn() - { - final String name = sessionManager.getAccountSession() != null - ? sessionManager.getAccountSession().getUsername() - : null; - - if (name != null) - { - emailLabel.setContentType("text/plain"); - emailLabel.setText(name); - loggedLabel.setText("Logged in as"); - actionsContainer.add(syncPanel, 0); - } - else - { - //emailLabel.setContentType("text/html"); - //emailLabel.setText("Login to sync settings to the cloud."); - //loggedLabel.setText("Not logged in"); - actionsContainer.remove(syncPanel); - } - } - - private static String htmlLabel(String key, String value) - { - return "" + key + "" + value + ""; - } - - @Subscribe - public void onSessionOpen(SessionOpen sessionOpen) - { - updateLoggedIn(); - } - - @Subscribe - public void onSessionClose(SessionClose e) - { - updateLoggedIn(); - } -} +/* + * Copyright (c) 2018 Abex + * Copyright (c) 2018, Psikoi + * 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.info; + +import com.google.common.base.MoreObjects; +import com.google.inject.Inject; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.ScheduledExecutorService; +import javax.annotation.Nullable; +import javax.inject.Singleton; +import javax.swing.Box; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import javax.swing.event.HyperlinkEvent; +import net.runelite.api.Client; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.account.SessionManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.LinkBrowser; + +@Singleton +public class InfoPanel extends PluginPanel +{ + private static final String RUNELITE_LOGIN = "https://runelite_login/"; + + private static final ImageIcon ARROW_RIGHT_ICON; + private static final ImageIcon GITHUB_ICON; + private static final ImageIcon DISCORD_ICON; + private static final ImageIcon PATREON_ICON; + private static final ImageIcon WIKI_ICON; + private static final ImageIcon IMPORT_ICON; + + private final JLabel loggedLabel = new JLabel(); + private final JRichTextPane emailLabel = new JRichTextPane(); + private JPanel syncPanel; + private JPanel actionsContainer; + + @Inject + @Nullable + private Client client; + + @Inject + private RuneLiteProperties runeLiteProperties; + + @Inject + private EventBus eventBus; + + @Inject + private SessionManager sessionManager; + + @Inject + private ScheduledExecutorService executor; + + @Inject + private ConfigManager configManager; + + static + { + ARROW_RIGHT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/util/arrow_right.png")); + GITHUB_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "github_icon.png")); + DISCORD_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "discord_icon.png")); + PATREON_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "patreon_icon.png")); + WIKI_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "wiki_icon.png")); + IMPORT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "import_icon.png")); + } + + void init() + { + setLayout(new BorderLayout()); + setBackground(ColorScheme.DARK_GRAY_COLOR); + setBorder(new EmptyBorder(10, 10, 10, 10)); + + JPanel versionPanel = new JPanel(); + versionPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + versionPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + versionPanel.setLayout(new GridLayout(0, 1)); + + final Font smallFont = FontManager.getRunescapeSmallFont(); + + JLabel version = new JLabel(htmlLabel("RuneLite version: ", runeLiteProperties.getVersion())); + version.setFont(smallFont); + + JLabel revision = new JLabel(); + revision.setFont(smallFont); + + String engineVer = "Unknown"; + if (client != null) + { + engineVer = String.format("Rev %d", client.getRevision()); + } + + revision.setText(htmlLabel("Oldschool revision: ", engineVer)); + + JLabel launcher = new JLabel(htmlLabel("Launcher version: ", MoreObjects + .firstNonNull(RuneLiteProperties.getLauncherVersion(), "Unknown"))); + launcher.setFont(smallFont); + + loggedLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + loggedLabel.setFont(smallFont); + + emailLabel.setForeground(Color.WHITE); + emailLabel.setFont(smallFont); + emailLabel.enableAutoLinkHandler(false); + emailLabel.addHyperlinkListener(e -> + { + if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null) + { + if (e.getURL().toString().equals(RUNELITE_LOGIN)) + { + executor.execute(sessionManager::login); + } + } + }); + + versionPanel.add(version); + versionPanel.add(revision); + versionPanel.add(launcher); + versionPanel.add(Box.createGlue()); + versionPanel.add(loggedLabel); + versionPanel.add(emailLabel); + + actionsContainer = new JPanel(); + actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0)); + actionsContainer.setLayout(new GridLayout(0, 1, 0, 10)); + + syncPanel = buildLinkPanel(IMPORT_ICON, "Import local settings", "to remote RuneLite account", () -> + { + final int result = JOptionPane.showOptionDialog(syncPanel, + "This will replace your current RuneLite account settings with settings from your local profile.", + "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, new String[]{"Yes", "No"}, "No"); + + if (result == JOptionPane.YES_OPTION) + { + configManager.importLocal(); + } + }); + + actionsContainer.add(buildLinkPanel(GITHUB_ICON, "License info", "for distribution", "https://github.com/runelite-extended/runelite/blob/master/LICENSE")); + actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", "https://discord.gg/s2fzu5U")); + actionsContainer.add(buildLinkPanel(PATREON_ICON, "Patreon to support", "the RuneLite devs", runeLiteProperties.getPatreonLink())); + /* actionsContainer.add(buildLinkPanel(WIKI_ICON, "Information about", "RuneLite and plugins", runeLiteProperties.getWikiLink()));*/ + + add(versionPanel, BorderLayout.NORTH); + add(actionsContainer, BorderLayout.CENTER); + + updateLoggedIn(); + eventBus.register(this); + } + + /** + * Builds a link panel with a given icon, text and url to redirect to. + */ + private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url) + { + return buildLinkPanel(icon, topText, bottomText, () -> LinkBrowser.browse(url)); + } + + /** + * Builds a link panel with a given icon, text and callable to call. + */ + private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, Runnable callback) + { + JPanel container = new JPanel(); + container.setBackground(ColorScheme.DARKER_GRAY_COLOR); + container.setLayout(new BorderLayout()); + container.setBorder(new EmptyBorder(10, 10, 10, 10)); + + final Color hoverColor = ColorScheme.DARKER_GRAY_HOVER_COLOR; + final Color pressedColor = ColorScheme.DARKER_GRAY_COLOR.brighter(); + + JLabel iconLabel = new JLabel(icon); + container.add(iconLabel, BorderLayout.WEST); + + JPanel textContainer = new JPanel(); + textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); + textContainer.setLayout(new GridLayout(2, 1)); + textContainer.setBorder(new EmptyBorder(5, 10, 5, 10)); + + container.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + container.setBackground(pressedColor); + textContainer.setBackground(pressedColor); + } + + @Override + public void mouseReleased(MouseEvent e) + { + callback.run(); + container.setBackground(hoverColor); + textContainer.setBackground(hoverColor); + } + + @Override + public void mouseEntered(MouseEvent e) + { + container.setBackground(hoverColor); + textContainer.setBackground(hoverColor); + container.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) + { + container.setBackground(ColorScheme.DARKER_GRAY_COLOR); + textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); + container.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + JLabel topLine = new JLabel(topText); + topLine.setForeground(Color.WHITE); + topLine.setFont(FontManager.getRunescapeSmallFont()); + + JLabel bottomLine = new JLabel(bottomText); + bottomLine.setForeground(Color.WHITE); + bottomLine.setFont(FontManager.getRunescapeSmallFont()); + + textContainer.add(topLine); + textContainer.add(bottomLine); + + container.add(textContainer, BorderLayout.CENTER); + + JLabel arrowLabel = new JLabel(ARROW_RIGHT_ICON); + container.add(arrowLabel, BorderLayout.EAST); + + return container; + } + + private void updateLoggedIn() + { + final String name = sessionManager.getAccountSession() != null + ? sessionManager.getAccountSession().getUsername() + : null; + + if (name != null) + { + emailLabel.setContentType("text/plain"); + emailLabel.setText(name); + loggedLabel.setText("Logged in as"); + actionsContainer.add(syncPanel, 0); + } + else + { + //emailLabel.setContentType("text/html"); + //emailLabel.setText("Login to sync settings to the cloud."); + //loggedLabel.setText("Not logged in"); + actionsContainer.remove(syncPanel); + } + } + + private static String htmlLabel(String key, String value) + { + return "" + key + "" + value + ""; + } + + @Subscribe + public void onSessionOpen(SessionOpen sessionOpen) + { + updateLoggedIn(); + } + + @Subscribe + public void onSessionClose(SessionClose e) + { + updateLoggedIn(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java index f986a28ffa..40c502631c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java @@ -1,70 +1,70 @@ -/* - * Copyright (c) 2018 Abex - * 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.info; - -import java.awt.image.BufferedImage; -import javax.inject.Inject; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.util.ImageUtil; - -@PluginDescriptor( - name = "Info Panel", - description = "Enable the Info panel", - loadWhenOutdated = true -) -public class InfoPlugin extends Plugin -{ - @Inject - private ClientToolbar clientToolbar; - - private NavigationButton navButton; - - @Override - protected void startUp() throws Exception - { - final InfoPanel panel = injector.getInstance(InfoPanel.class); - panel.init(); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "info_icon.png"); - - navButton = NavigationButton.builder() - .tooltip("Info") - .icon(icon) - .priority(9) - .panel(panel) - .build(); - - clientToolbar.addNavigation(navButton); - } - - @Override - protected void shutDown() - { - clientToolbar.removeNavigation(navButton); - } -} +/* + * Copyright (c) 2018 Abex + * 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.info; + +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.ImageUtil; + +@PluginDescriptor( + name = "Info Panel", + description = "Enable the Info panel", + loadWhenOutdated = true +) +public class InfoPlugin extends Plugin +{ + @Inject + private ClientToolbar clientToolbar; + + private NavigationButton navButton; + + @Override + protected void startUp() throws Exception + { + final InfoPanel panel = injector.getInstance(InfoPanel.class); + panel.init(); + + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "info_icon.png"); + + navButton = NavigationButton.builder() + .tooltip("Info") + .icon(icon) + .priority(9) + .panel(panel) + .build(); + + clientToolbar.addNavigation(navButton); + } + + @Override + protected void shutDown() + { + clientToolbar.removeNavigation(navButton); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java index 3e44e6d4b8..c25ecf6771 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java @@ -1,272 +1,272 @@ -/* - * Copyright (c) 2017, Adam - * 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.instancemap; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.Client; -import net.runelite.api.Player; -import net.runelite.api.SpritePixels; -import net.runelite.api.Tile; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.events.GameStateChanged; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.BackgroundComponent; -import static net.runelite.api.SpriteID.WINDOW_CLOSE_BUTTON_RED_X; -import static net.runelite.api.SpriteID.WINDOW_CLOSE_BUTTON_RED_X_HOVERED; - -@Singleton -class InstanceMapOverlay extends Overlay -{ - /** - * The size of tiles on the map. The way the client renders requires - * this value to be 4. Changing this will break the method for rendering - * complex tiles - */ - static final int TILE_SIZE = 4; - - /** - * The size of the player's position marker on the map - */ - private static final int PLAYER_MARKER_SIZE = 4; - - private static final int MAX_PLANE = 3; - private static final int MIN_PLANE = 0; - - /** - * The plane to render on the instance map. When the map is opened this - * defaults to the current plane. The ascend and descend buttons raise - * and lower this This is used to render parts of an instance below or - * above the local player's current plane. - */ - private int viewedPlane = 0; - - private final Client client; - private final SpriteManager spriteManager; - - /** - * Saved image of the scene, no reason to draw the whole thing every - * frame. - */ - private volatile BufferedImage mapImage; - private volatile boolean showMap = false; - private final BackgroundComponent backgroundComponent = new BackgroundComponent(); - - @Setter - private boolean isCloseButtonHovered; - @Getter - private Rectangle closeButtonBounds; - private BufferedImage closeButtonImage; - private BufferedImage closeButtonHoveredImage; - - @Inject - InstanceMapOverlay(Client client, SpriteManager spriteManager) - { - this.client = client; - this.spriteManager = spriteManager; - setPriority(OverlayPriority.HIGH); - setPosition(OverlayPosition.TOP_LEFT); - setLayer(OverlayLayer.ABOVE_WIDGETS); - backgroundComponent.setFill(false); - } - - public boolean isMapShown() - { - return showMap; - } - - /** - * Setter for showing the map. When the map is set to show, the map is - * re-rendered - * - * @param show Whether or not the map should be shown. - */ - public synchronized void setShowMap(boolean show) - { - showMap = show; - if (showMap) - { - //When we open the map show the current plane - viewedPlane = client.getPlane(); - } - mapImage = null; - } - - /** - * Increases the viewed plane. The maximum viewedPlane is 3 - */ - public synchronized void onAscend() - { - if (viewedPlane >= MAX_PLANE) - { - return; - } - - viewedPlane++;//Increment plane - mapImage = null; - } - - /** - * Decreases the viewed plane. The minimum viewedPlane is 0 - */ - public synchronized void onDescend() - { - if (viewedPlane <= MIN_PLANE) - { - return; - } - - viewedPlane--; - mapImage = null; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!showMap) - { - return null; - } - - // avoid locking on fast path by creating a local ref - BufferedImage image = mapImage; - - if (image == null) - { - BufferedImage closeButton = getCloseButtonImage(); - - SpritePixels map = client.drawInstanceMap(viewedPlane); - image = minimapToBufferedImage(map); - synchronized (this) - { - if (showMap) - { - mapImage = image; - } - } - - closeButtonBounds = new Rectangle(image.getWidth() - closeButton.getWidth() - 5, 6, - closeButton.getWidth(), closeButton.getHeight()); - } - - graphics.drawImage(image, 0, 0, null); - backgroundComponent.setRectangle(new Rectangle(0, 0, image.getWidth(), image.getHeight())); - backgroundComponent.render(graphics); - - if (client.getPlane() == viewedPlane)//If we are not viewing the plane we are on, don't show player's position - { - drawPlayerDot(graphics, client.getLocalPlayer(), Color.white, Color.black); - } - - graphics.drawImage(isCloseButtonHovered ? getCloseButtonHoveredImage() : getCloseButtonImage(), - (int) closeButtonBounds.getX(), (int) closeButtonBounds.getY(), null); - - return new Dimension(image.getWidth(), image.getHeight()); - } - - /** - * Get the files for the current viewed plane - * - * @return - */ - private Tile[][] getTiles() - { - Tile[][][] sceneTiles = client.getScene().getTiles(); - return sceneTiles[viewedPlane]; - } - - /** - * Draws the players position as a dot on the map. - * - * @param graphics graphics to be drawn to - */ - private void drawPlayerDot(Graphics2D graphics, Player player, - Color dotColor, Color outlineColor) - { - LocalPoint playerLoc = player.getLocalLocation(); - - Tile[][] tiles = getTiles(); - int tileX = playerLoc.getSceneX(); - int tileY = (tiles[0].length - 1) - playerLoc.getSceneY(); // flip the y value - - int x = tileX * TILE_SIZE; - int y = tileY * TILE_SIZE; - graphics.setColor(dotColor); - graphics.fillRect(x, y, PLAYER_MARKER_SIZE, PLAYER_MARKER_SIZE);//draw the players point on the map - graphics.setColor(outlineColor); - graphics.drawRect(x, y, PLAYER_MARKER_SIZE, PLAYER_MARKER_SIZE);//outline - } - - /** - * Handles game state changes and re-draws the map - * - * @param event The game state change event - */ - public void onGameStateChange(GameStateChanged event) - { - mapImage = null; - } - - private static BufferedImage minimapToBufferedImage(SpritePixels spritePixels) - { - int width = spritePixels.getWidth(); - int height = spritePixels.getHeight(); - int[] pixels = spritePixels.getPixels(); - BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - img.setRGB(0, 0, width, height, pixels, 0, width); - // 24624 / 512 and 24624 % 512 are both 48 - img = img.getSubimage(48, 48, TILE_SIZE * 104, TILE_SIZE * 104); - return img; - } - - private BufferedImage getCloseButtonImage() - { - if (closeButtonImage == null) - { - closeButtonImage = spriteManager.getSprite(WINDOW_CLOSE_BUTTON_RED_X, 0); - } - return closeButtonImage; - } - - private BufferedImage getCloseButtonHoveredImage() - { - if (closeButtonHoveredImage == null) - { - closeButtonHoveredImage = spriteManager.getSprite(WINDOW_CLOSE_BUTTON_RED_X_HOVERED, 0); - } - return closeButtonHoveredImage; - } -} +/* + * Copyright (c) 2017, Adam + * 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.instancemap; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Client; +import net.runelite.api.Player; +import static net.runelite.api.SpriteID.WINDOW_CLOSE_BUTTON_RED_X; +import static net.runelite.api.SpriteID.WINDOW_CLOSE_BUTTON_RED_X_HOVERED; +import net.runelite.api.SpritePixels; +import net.runelite.api.Tile; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.events.GameStateChanged; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.BackgroundComponent; + +@Singleton +class InstanceMapOverlay extends Overlay +{ + /** + * The size of tiles on the map. The way the client renders requires + * this value to be 4. Changing this will break the method for rendering + * complex tiles + */ + static final int TILE_SIZE = 4; + + /** + * The size of the player's position marker on the map + */ + private static final int PLAYER_MARKER_SIZE = 4; + + private static final int MAX_PLANE = 3; + private static final int MIN_PLANE = 0; + + /** + * The plane to render on the instance map. When the map is opened this + * defaults to the current plane. The ascend and descend buttons raise + * and lower this This is used to render parts of an instance below or + * above the local player's current plane. + */ + private int viewedPlane = 0; + + private final Client client; + private final SpriteManager spriteManager; + + /** + * Saved image of the scene, no reason to draw the whole thing every + * frame. + */ + private volatile BufferedImage mapImage; + private volatile boolean showMap = false; + private final BackgroundComponent backgroundComponent = new BackgroundComponent(); + + @Setter + private boolean isCloseButtonHovered; + @Getter + private Rectangle closeButtonBounds; + private BufferedImage closeButtonImage; + private BufferedImage closeButtonHoveredImage; + + @Inject + InstanceMapOverlay(Client client, SpriteManager spriteManager) + { + this.client = client; + this.spriteManager = spriteManager; + setPriority(OverlayPriority.HIGH); + setPosition(OverlayPosition.TOP_LEFT); + setLayer(OverlayLayer.ABOVE_WIDGETS); + backgroundComponent.setFill(false); + } + + public boolean isMapShown() + { + return showMap; + } + + /** + * Setter for showing the map. When the map is set to show, the map is + * re-rendered + * + * @param show Whether or not the map should be shown. + */ + public synchronized void setShowMap(boolean show) + { + showMap = show; + if (showMap) + { + //When we open the map show the current plane + viewedPlane = client.getPlane(); + } + mapImage = null; + } + + /** + * Increases the viewed plane. The maximum viewedPlane is 3 + */ + public synchronized void onAscend() + { + if (viewedPlane >= MAX_PLANE) + { + return; + } + + viewedPlane++;//Increment plane + mapImage = null; + } + + /** + * Decreases the viewed plane. The minimum viewedPlane is 0 + */ + public synchronized void onDescend() + { + if (viewedPlane <= MIN_PLANE) + { + return; + } + + viewedPlane--; + mapImage = null; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!showMap) + { + return null; + } + + // avoid locking on fast path by creating a local ref + BufferedImage image = mapImage; + + if (image == null) + { + BufferedImage closeButton = getCloseButtonImage(); + + SpritePixels map = client.drawInstanceMap(viewedPlane); + image = minimapToBufferedImage(map); + synchronized (this) + { + if (showMap) + { + mapImage = image; + } + } + + closeButtonBounds = new Rectangle(image.getWidth() - closeButton.getWidth() - 5, 6, + closeButton.getWidth(), closeButton.getHeight()); + } + + graphics.drawImage(image, 0, 0, null); + backgroundComponent.setRectangle(new Rectangle(0, 0, image.getWidth(), image.getHeight())); + backgroundComponent.render(graphics); + + if (client.getPlane() == viewedPlane)//If we are not viewing the plane we are on, don't show player's position + { + drawPlayerDot(graphics, client.getLocalPlayer(), Color.white, Color.black); + } + + graphics.drawImage(isCloseButtonHovered ? getCloseButtonHoveredImage() : getCloseButtonImage(), + (int) closeButtonBounds.getX(), (int) closeButtonBounds.getY(), null); + + return new Dimension(image.getWidth(), image.getHeight()); + } + + /** + * Get the files for the current viewed plane + * + * @return + */ + private Tile[][] getTiles() + { + Tile[][][] sceneTiles = client.getScene().getTiles(); + return sceneTiles[viewedPlane]; + } + + /** + * Draws the players position as a dot on the map. + * + * @param graphics graphics to be drawn to + */ + private void drawPlayerDot(Graphics2D graphics, Player player, + Color dotColor, Color outlineColor) + { + LocalPoint playerLoc = player.getLocalLocation(); + + Tile[][] tiles = getTiles(); + int tileX = playerLoc.getSceneX(); + int tileY = (tiles[0].length - 1) - playerLoc.getSceneY(); // flip the y value + + int x = tileX * TILE_SIZE; + int y = tileY * TILE_SIZE; + graphics.setColor(dotColor); + graphics.fillRect(x, y, PLAYER_MARKER_SIZE, PLAYER_MARKER_SIZE);//draw the players point on the map + graphics.setColor(outlineColor); + graphics.drawRect(x, y, PLAYER_MARKER_SIZE, PLAYER_MARKER_SIZE);//outline + } + + /** + * Handles game state changes and re-draws the map + * + * @param event The game state change event + */ + public void onGameStateChange(GameStateChanged event) + { + mapImage = null; + } + + private static BufferedImage minimapToBufferedImage(SpritePixels spritePixels) + { + int width = spritePixels.getWidth(); + int height = spritePixels.getHeight(); + int[] pixels = spritePixels.getPixels(); + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + img.setRGB(0, 0, width, height, pixels, 0, width); + // 24624 / 512 and 24624 % 512 are both 48 + img = img.getSubimage(48, 48, TILE_SIZE * 104, TILE_SIZE * 104); + return img; + } + + private BufferedImage getCloseButtonImage() + { + if (closeButtonImage == null) + { + closeButtonImage = spriteManager.getSprite(WINDOW_CLOSE_BUTTON_RED_X, 0); + } + return closeButtonImage; + } + + private BufferedImage getCloseButtonHoveredImage() + { + if (closeButtonHoveredImage == null) + { + closeButtonHoveredImage = spriteManager.getSprite(WINDOW_CLOSE_BUTTON_RED_X_HOVERED, 0); + } + return closeButtonHoveredImage; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/SpriteOverride.java b/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/SpriteOverride.java index 3907a42e10..1b360aba55 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/SpriteOverride.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/SpriteOverride.java @@ -1,150 +1,150 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.interfacestyles; - -import lombok.Getter; -import net.runelite.api.SpriteID; -import static net.runelite.client.plugins.interfacestyles.Skin.AROUND_2005; -import static net.runelite.client.plugins.interfacestyles.Skin.AROUND_2010; - -@Getter -enum SpriteOverride -{ - TAB_COMBAT(SpriteID.TAB_COMBAT, AROUND_2005, AROUND_2010), - TAB_STATS(SpriteID.TAB_STATS, AROUND_2005, AROUND_2010), - TAB_QUESTS(SpriteID.TAB_QUESTS, AROUND_2005), - TAB_QUESTS_PURPLE_KOUREND_1299(SpriteID.TAB_QUESTS_PURPLE_KOUREND, AROUND_2005), - TAB_QUESTS_RED_MINIGAMES(SpriteID.TAB_QUESTS_RED_MINIGAMES, AROUND_2005), - TAB_QUESTS_GREEN_ACHIEVEMENT_DIARIES(SpriteID.TAB_QUESTS_GREEN_ACHIEVEMENT_DIARIES, AROUND_2005), - TAB_INVENTORY(SpriteID.TAB_INVENTORY, AROUND_2005, AROUND_2010), - TAB_EQUIPMENT(SpriteID.TAB_EQUIPMENT, AROUND_2005, AROUND_2010), - TAB_PRAYER(SpriteID.TAB_PRAYER, AROUND_2005, AROUND_2010), - TAB_MAGIC(SpriteID.TAB_MAGIC, AROUND_2005, AROUND_2010), - TAB_MAGIC_SPELLBOOK_ANCIENT_MAGICKS(SpriteID.TAB_MAGIC_SPELLBOOK_ANCIENT_MAGICKS, AROUND_2005), - TAB_MAGIC_SPELLBOOK_LUNAR(SpriteID.TAB_MAGIC_SPELLBOOK_LUNAR, AROUND_2005), - TAB_MAGIC_SPELLBOOK_ARCEUUS(SpriteID.TAB_MAGIC_SPELLBOOK_ARCEUUS, AROUND_2005), - TAB_CLAN_CHAT(SpriteID.TAB_CLAN_CHAT, AROUND_2005, AROUND_2010), - TAB_FRIENDS(SpriteID.TAB_FRIENDS, AROUND_2005, AROUND_2010), - TAB_IGNORES(SpriteID.TAB_IGNORES, AROUND_2005, AROUND_2010), - TAB_LOGOUT(SpriteID.TAB_LOGOUT, AROUND_2005, AROUND_2010), - TAB_OPTIONS(SpriteID.TAB_OPTIONS, AROUND_2005, AROUND_2010), - TAB_EMOTES(SpriteID.TAB_EMOTES, AROUND_2005, AROUND_2010), - TAB_MUSIC(SpriteID.TAB_MUSIC, AROUND_2005, AROUND_2010), - TAB_CHATBOX(SpriteID.CHATBOX, AROUND_2005), - - SKILL_ATTACK(SpriteID.SKILL_ATTACK, AROUND_2010), - SKILL_STRENGTH(SpriteID.SKILL_STRENGTH, AROUND_2010), - SKILL_DEFENCE(SpriteID.SKILL_DEFENCE, AROUND_2010), - SKILL_RANGED(SpriteID.SKILL_RANGED, AROUND_2010), - SKILL_PRAYER(SpriteID.SKILL_PRAYER, AROUND_2005, AROUND_2010), - SKILL_MAGIC(SpriteID.SKILL_MAGIC, AROUND_2010), - SKILL_HITPOINTS(SpriteID.SKILL_HITPOINTS, AROUND_2010), - SKILL_AGILITY(SpriteID.SKILL_AGILITY, AROUND_2010), - SKILL_HERBLORE(SpriteID.SKILL_HERBLORE, AROUND_2010), - SKILL_THIEVING(SpriteID.SKILL_THIEVING, AROUND_2010), - SKILL_CRAFTING(SpriteID.SKILL_CRAFTING, AROUND_2010), - SKILL_FLETCHING(SpriteID.SKILL_FLETCHING, AROUND_2010), - SKILL_MINING(SpriteID.SKILL_MINING, AROUND_2010), - SKILL_SMITHING(SpriteID.SKILL_SMITHING, AROUND_2010), - SKILL_FISHING(SpriteID.SKILL_FISHING, AROUND_2010), - SKILL_COOKING(SpriteID.SKILL_COOKING, AROUND_2010), - SKILL_FIREMAKING(SpriteID.SKILL_FIREMAKING, AROUND_2010), - SKILL_WOODCUTTING(SpriteID.SKILL_WOODCUTTING, AROUND_2010), - SKILL_RUNECRAFT(SpriteID.SKILL_RUNECRAFT, AROUND_2010), - SKILL_SLAYER(SpriteID.SKILL_SLAYER, AROUND_2010), - SKILL_HUNTER(SpriteID.SKILL_HUNTER, AROUND_2010), - SKILL_CONSTRUCTION(SpriteID.SKILL_CONSTRUCTION, AROUND_2010), - - COMPASS(SpriteID.COMPASS_TEXTURE, AROUND_2005), - WINDOW_CLOSE_BUTTON_RED_X(SpriteID.WINDOW_CLOSE_BUTTON_RED_X, AROUND_2010), - WINDOW_CLOSE_BUTTON_RED_X_HOVERED(SpriteID.WINDOW_CLOSE_BUTTON_RED_X_HOVERED, AROUND_2010), - WINDOW_CLOSE_BUTTON_BROWN_X(SpriteID.WINDOW_CLOSE_BUTTON_BROWN_X, AROUND_2010), - WINDOW_CLOSE_BUTTON_BROWN_X_HOVERED(SpriteID.WINDOW_CLOSE_BUTTON_BROWN_X_HOVERED, AROUND_2010), - MINIMAP_ORB_FRAME(SpriteID.MINIMAP_ORB_FRAME, AROUND_2010), - MINIMAP_ORB_FRAME_HOVERED(SpriteID.MINIMAP_ORB_FRAME_HOVERED, AROUND_2010), - MINIMAP_ORB_XP(SpriteID.MINIMAP_ORB_XP, AROUND_2010), - MINIMAP_ORB_XP_ACTIVATED(SpriteID.MINIMAP_ORB_XP_ACTIVATED, AROUND_2010), - MINIMAP_ORB_XP_HOVERED(SpriteID.MINIMAP_ORB_XP_HOVERED, AROUND_2010), - MINIMAP_ORB_XP_ACTIVATED_HOVERED(SpriteID.MINIMAP_ORB_XP_ACTIVATED_HOVERED, AROUND_2010), - MINIMAP_ORB_WORLD_MAP_FRAME(SpriteID.MINIMAP_ORB_WORLD_MAP_FRAME, AROUND_2010), - MINIMAP_ORB_WORLD_MAP_PLANET(SpriteID.MINIMAP_ORB_WORLD_MAP_PLANET, AROUND_2010), - - //CHATBOX(SpriteID.CHATBOX, AROUND_2005), - CHATBOX_BUTTONS_BACKGROUND_STONES(SpriteID.CHATBOX_BUTTONS_BACKGROUND_STONES, AROUND_2005), - CHATBOX_BUTTON(SpriteID.CHATBOX_BUTTON, AROUND_2005), - CHATBOX_BUTTON_HOVERED(SpriteID.CHATBOX_BUTTON_HOVERED, AROUND_2005), - CHATBOX_BUTTON_NEW_MESSAGES( SpriteID.CHATBOX_BUTTON_NEW_MESSAGES, AROUND_2005), - CHATBOX_BUTTON_SELECTED(SpriteID.CHATBOX_BUTTON_SELECTED, AROUND_2005), - CHATBOX_BUTTON_SELECTED_HOVERED(SpriteID.CHATBOX_BUTTON_SELECTED_HOVERED, AROUND_2005), - CHATBOX_REPORT_BUTTON(SpriteID.CHATBOX_REPORT_BUTTON, AROUND_2005), - CHATBOX_REPORT_BUTTON_HOVERED(SpriteID.CHATBOX_REPORT_BUTTON_HOVERED, AROUND_2005), - - SCROLLBAR_ARROW_UP(SpriteID.SCROLLBAR_ARROW_UP, AROUND_2005), - SCROLLBAR_ARROW_DOWN(SpriteID.SCROLLBAR_ARROW_DOWN, AROUND_2005), - SCROLLBAR_THUMB_TOP(SpriteID.SCROLLBAR_THUMB_TOP, AROUND_2005), - SCROLLBAR_THUMB_MIDDLE(SpriteID.SCROLLBAR_THUMB_MIDDLE, AROUND_2005), - SCROLLBAR_THUMB_BOTTOM(SpriteID.SCROLLBAR_THUMB_BOTTOM, AROUND_2005), - SCROLLBAR_THUMB_MIDDLE_DARK(SpriteID.SCROLLBAR_THUMB_MIDDLE_DARK, AROUND_2005), - - TAB_STONE_TOP_LEFT_SELECTED(SpriteID.TAB_STONE_TOP_LEFT_SELECTED, AROUND_2010), - TAB_STONE_TOP_RIGHT_SELECTED(SpriteID.TAB_STONE_TOP_RIGHT_SELECTED, AROUND_2010), - TAB_STONE_BOTTOM_LEFT_SELECTED(SpriteID.TAB_STONE_BOTTOM_LEFT_SELECTED, AROUND_2010), - TAB_STONE_BOTTOM_RIGHT_SELECTED(SpriteID.TAB_STONE_BOTTOM_RIGHT_SELECTED, AROUND_2010), - TAB_STONE_MIDDLE_SELECTED(SpriteID.TAB_STONE_MIDDLE_SELECTED, AROUND_2010), - - FIXED_MODE_SIDE_PANEL_BACKGROUND(SpriteID.FIXED_MODE_SIDE_PANEL_BACKGROUND, AROUND_2005), - FIXED_MODE_TABS_ROW_BOTTOM(SpriteID.FIXED_MODE_TABS_ROW_BOTTOM, AROUND_2005, AROUND_2010), - - OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_UPPER(SpriteID.OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_UPPER, AROUND_2005, AROUND_2010), - OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_LOWER(SpriteID.OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_LOWER, AROUND_2005, AROUND_2010), - OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_RIGHT(SpriteID.OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_RIGHT, AROUND_2005, AROUND_2010), - - FIXED_MODE_TABS_TOP_ROW(SpriteID.FIXED_MODE_TABS_TOP_ROW, AROUND_2005, AROUND_2010), - FIXED_MODE_MINIMAP_LEFT_EDGE(SpriteID.FIXED_MODE_MINIMAP_LEFT_EDGE, AROUND_2005, AROUND_2010), - FIXED_MODE_MINIMAP_RIGHT_EDGE(SpriteID.FIXED_MODE_MINIMAP_RIGHT_EDGE, AROUND_2005, AROUND_2010), - FIXED_MODE_WINDOW_FRAME_EDGE_TOP(SpriteID.FIXED_MODE_WINDOW_FRAME_EDGE_TOP, AROUND_2005, AROUND_2010), - FIXED_MODE_MINIMAP_AND_COMPASS_FRAME(SpriteID.FIXED_MODE_MINIMAP_AND_COMPASS_FRAME, AROUND_2005, AROUND_2010), - FIXED_MODE_MINIMAP_FRAME_BOTTOM(SpriteID.FIXED_MODE_MINIMAP_FRAME_BOTTOM, AROUND_2005), - FIXED_MODE_TOP_RIGHT_CORNER(SpriteID.FIXED_MODE_TOP_RIGHT_CORNER, AROUND_2005), - - RESIZEABLE_MODE_TABS_TOP_ROW(SpriteID.RESIZEABLE_MODE_TABS_TOP_ROW, AROUND_2010), - RESIZEABLE_MODE_TABS_BOTTOM_ROW(SpriteID.RESIZEABLE_MODE_TABS_BOTTOM_ROW, AROUND_2010), - RESIZEABLE_MODE_SIDE_PANEL_EDGE_LEFT(SpriteID.RESIZEABLE_MODE_SIDE_PANEL_EDGE_LEFT, AROUND_2010), - RESIZEABLE_MODE_SIDE_PANEL_EDGE_RIGHT(SpriteID.RESIZEABLE_MODE_SIDE_PANEL_EDGE_RIGHT, AROUND_2010), - RESIZEABLE_MODE_MINIMAP_AND_COMPASS_FRAME(SpriteID.RESIZEABLE_MODE_MINIMAP_AND_COMPASS_FRAME, AROUND_2010), - RESIZEABLE_MODE_TAB_STONE_MIDDLE(SpriteID.RESIZEABLE_MODE_TAB_STONE_MIDDLE, AROUND_2010), - RESIZEABLE_MODE_TAB_STONE_MIDDLE_SELECTED(SpriteID.RESIZEABLE_MODE_TAB_STONE_MIDDLE_SELECTED, AROUND_2010); - - private int spriteID; - private Skin[] skin; - - SpriteOverride(int spriteID, Skin... skin) - { - this.spriteID = spriteID; - this.skin = skin; - } +/* + * Copyright (c) 2018, Lotto + * Copyright (c) 2018, Raqes + * 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 HOLDER 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.interfacestyles; + +import lombok.Getter; +import net.runelite.api.SpriteID; +import static net.runelite.client.plugins.interfacestyles.Skin.AROUND_2005; +import static net.runelite.client.plugins.interfacestyles.Skin.AROUND_2010; + +@Getter +enum SpriteOverride +{ + TAB_COMBAT(SpriteID.TAB_COMBAT, AROUND_2005, AROUND_2010), + TAB_STATS(SpriteID.TAB_STATS, AROUND_2005, AROUND_2010), + TAB_QUESTS(SpriteID.TAB_QUESTS, AROUND_2005), + TAB_QUESTS_PURPLE_KOUREND_1299(SpriteID.TAB_QUESTS_PURPLE_KOUREND, AROUND_2005), + TAB_QUESTS_RED_MINIGAMES(SpriteID.TAB_QUESTS_RED_MINIGAMES, AROUND_2005), + TAB_QUESTS_GREEN_ACHIEVEMENT_DIARIES(SpriteID.TAB_QUESTS_GREEN_ACHIEVEMENT_DIARIES, AROUND_2005), + TAB_INVENTORY(SpriteID.TAB_INVENTORY, AROUND_2005, AROUND_2010), + TAB_EQUIPMENT(SpriteID.TAB_EQUIPMENT, AROUND_2005, AROUND_2010), + TAB_PRAYER(SpriteID.TAB_PRAYER, AROUND_2005, AROUND_2010), + TAB_MAGIC(SpriteID.TAB_MAGIC, AROUND_2005, AROUND_2010), + TAB_MAGIC_SPELLBOOK_ANCIENT_MAGICKS(SpriteID.TAB_MAGIC_SPELLBOOK_ANCIENT_MAGICKS, AROUND_2005), + TAB_MAGIC_SPELLBOOK_LUNAR(SpriteID.TAB_MAGIC_SPELLBOOK_LUNAR, AROUND_2005), + TAB_MAGIC_SPELLBOOK_ARCEUUS(SpriteID.TAB_MAGIC_SPELLBOOK_ARCEUUS, AROUND_2005), + TAB_CLAN_CHAT(SpriteID.TAB_CLAN_CHAT, AROUND_2005, AROUND_2010), + TAB_FRIENDS(SpriteID.TAB_FRIENDS, AROUND_2005, AROUND_2010), + TAB_IGNORES(SpriteID.TAB_IGNORES, AROUND_2005, AROUND_2010), + TAB_LOGOUT(SpriteID.TAB_LOGOUT, AROUND_2005, AROUND_2010), + TAB_OPTIONS(SpriteID.TAB_OPTIONS, AROUND_2005, AROUND_2010), + TAB_EMOTES(SpriteID.TAB_EMOTES, AROUND_2005, AROUND_2010), + TAB_MUSIC(SpriteID.TAB_MUSIC, AROUND_2005, AROUND_2010), + TAB_CHATBOX(SpriteID.CHATBOX, AROUND_2005), + + SKILL_ATTACK(SpriteID.SKILL_ATTACK, AROUND_2010), + SKILL_STRENGTH(SpriteID.SKILL_STRENGTH, AROUND_2010), + SKILL_DEFENCE(SpriteID.SKILL_DEFENCE, AROUND_2010), + SKILL_RANGED(SpriteID.SKILL_RANGED, AROUND_2010), + SKILL_PRAYER(SpriteID.SKILL_PRAYER, AROUND_2005, AROUND_2010), + SKILL_MAGIC(SpriteID.SKILL_MAGIC, AROUND_2010), + SKILL_HITPOINTS(SpriteID.SKILL_HITPOINTS, AROUND_2010), + SKILL_AGILITY(SpriteID.SKILL_AGILITY, AROUND_2010), + SKILL_HERBLORE(SpriteID.SKILL_HERBLORE, AROUND_2010), + SKILL_THIEVING(SpriteID.SKILL_THIEVING, AROUND_2010), + SKILL_CRAFTING(SpriteID.SKILL_CRAFTING, AROUND_2010), + SKILL_FLETCHING(SpriteID.SKILL_FLETCHING, AROUND_2010), + SKILL_MINING(SpriteID.SKILL_MINING, AROUND_2010), + SKILL_SMITHING(SpriteID.SKILL_SMITHING, AROUND_2010), + SKILL_FISHING(SpriteID.SKILL_FISHING, AROUND_2010), + SKILL_COOKING(SpriteID.SKILL_COOKING, AROUND_2010), + SKILL_FIREMAKING(SpriteID.SKILL_FIREMAKING, AROUND_2010), + SKILL_WOODCUTTING(SpriteID.SKILL_WOODCUTTING, AROUND_2010), + SKILL_RUNECRAFT(SpriteID.SKILL_RUNECRAFT, AROUND_2010), + SKILL_SLAYER(SpriteID.SKILL_SLAYER, AROUND_2010), + SKILL_HUNTER(SpriteID.SKILL_HUNTER, AROUND_2010), + SKILL_CONSTRUCTION(SpriteID.SKILL_CONSTRUCTION, AROUND_2010), + + COMPASS(SpriteID.COMPASS_TEXTURE, AROUND_2005), + WINDOW_CLOSE_BUTTON_RED_X(SpriteID.WINDOW_CLOSE_BUTTON_RED_X, AROUND_2010), + WINDOW_CLOSE_BUTTON_RED_X_HOVERED(SpriteID.WINDOW_CLOSE_BUTTON_RED_X_HOVERED, AROUND_2010), + WINDOW_CLOSE_BUTTON_BROWN_X(SpriteID.WINDOW_CLOSE_BUTTON_BROWN_X, AROUND_2010), + WINDOW_CLOSE_BUTTON_BROWN_X_HOVERED(SpriteID.WINDOW_CLOSE_BUTTON_BROWN_X_HOVERED, AROUND_2010), + MINIMAP_ORB_FRAME(SpriteID.MINIMAP_ORB_FRAME, AROUND_2010), + MINIMAP_ORB_FRAME_HOVERED(SpriteID.MINIMAP_ORB_FRAME_HOVERED, AROUND_2010), + MINIMAP_ORB_XP(SpriteID.MINIMAP_ORB_XP, AROUND_2010), + MINIMAP_ORB_XP_ACTIVATED(SpriteID.MINIMAP_ORB_XP_ACTIVATED, AROUND_2010), + MINIMAP_ORB_XP_HOVERED(SpriteID.MINIMAP_ORB_XP_HOVERED, AROUND_2010), + MINIMAP_ORB_XP_ACTIVATED_HOVERED(SpriteID.MINIMAP_ORB_XP_ACTIVATED_HOVERED, AROUND_2010), + MINIMAP_ORB_WORLD_MAP_FRAME(SpriteID.MINIMAP_ORB_WORLD_MAP_FRAME, AROUND_2010), + MINIMAP_ORB_WORLD_MAP_PLANET(SpriteID.MINIMAP_ORB_WORLD_MAP_PLANET, AROUND_2010), + + //CHATBOX(SpriteID.CHATBOX, AROUND_2005), + CHATBOX_BUTTONS_BACKGROUND_STONES(SpriteID.CHATBOX_BUTTONS_BACKGROUND_STONES, AROUND_2005), + CHATBOX_BUTTON(SpriteID.CHATBOX_BUTTON, AROUND_2005), + CHATBOX_BUTTON_HOVERED(SpriteID.CHATBOX_BUTTON_HOVERED, AROUND_2005), + CHATBOX_BUTTON_NEW_MESSAGES(SpriteID.CHATBOX_BUTTON_NEW_MESSAGES, AROUND_2005), + CHATBOX_BUTTON_SELECTED(SpriteID.CHATBOX_BUTTON_SELECTED, AROUND_2005), + CHATBOX_BUTTON_SELECTED_HOVERED(SpriteID.CHATBOX_BUTTON_SELECTED_HOVERED, AROUND_2005), + CHATBOX_REPORT_BUTTON(SpriteID.CHATBOX_REPORT_BUTTON, AROUND_2005), + CHATBOX_REPORT_BUTTON_HOVERED(SpriteID.CHATBOX_REPORT_BUTTON_HOVERED, AROUND_2005), + + SCROLLBAR_ARROW_UP(SpriteID.SCROLLBAR_ARROW_UP, AROUND_2005), + SCROLLBAR_ARROW_DOWN(SpriteID.SCROLLBAR_ARROW_DOWN, AROUND_2005), + SCROLLBAR_THUMB_TOP(SpriteID.SCROLLBAR_THUMB_TOP, AROUND_2005), + SCROLLBAR_THUMB_MIDDLE(SpriteID.SCROLLBAR_THUMB_MIDDLE, AROUND_2005), + SCROLLBAR_THUMB_BOTTOM(SpriteID.SCROLLBAR_THUMB_BOTTOM, AROUND_2005), + SCROLLBAR_THUMB_MIDDLE_DARK(SpriteID.SCROLLBAR_THUMB_MIDDLE_DARK, AROUND_2005), + + TAB_STONE_TOP_LEFT_SELECTED(SpriteID.TAB_STONE_TOP_LEFT_SELECTED, AROUND_2010), + TAB_STONE_TOP_RIGHT_SELECTED(SpriteID.TAB_STONE_TOP_RIGHT_SELECTED, AROUND_2010), + TAB_STONE_BOTTOM_LEFT_SELECTED(SpriteID.TAB_STONE_BOTTOM_LEFT_SELECTED, AROUND_2010), + TAB_STONE_BOTTOM_RIGHT_SELECTED(SpriteID.TAB_STONE_BOTTOM_RIGHT_SELECTED, AROUND_2010), + TAB_STONE_MIDDLE_SELECTED(SpriteID.TAB_STONE_MIDDLE_SELECTED, AROUND_2010), + + FIXED_MODE_SIDE_PANEL_BACKGROUND(SpriteID.FIXED_MODE_SIDE_PANEL_BACKGROUND, AROUND_2005), + FIXED_MODE_TABS_ROW_BOTTOM(SpriteID.FIXED_MODE_TABS_ROW_BOTTOM, AROUND_2005, AROUND_2010), + + OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_UPPER(SpriteID.OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_UPPER, AROUND_2005, AROUND_2010), + OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_LOWER(SpriteID.OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_LEFT_LOWER, AROUND_2005, AROUND_2010), + OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_RIGHT(SpriteID.OLD_SCHOOl_MODE_SIDE_PANEL_EDGE_RIGHT, AROUND_2005, AROUND_2010), + + FIXED_MODE_TABS_TOP_ROW(SpriteID.FIXED_MODE_TABS_TOP_ROW, AROUND_2005, AROUND_2010), + FIXED_MODE_MINIMAP_LEFT_EDGE(SpriteID.FIXED_MODE_MINIMAP_LEFT_EDGE, AROUND_2005, AROUND_2010), + FIXED_MODE_MINIMAP_RIGHT_EDGE(SpriteID.FIXED_MODE_MINIMAP_RIGHT_EDGE, AROUND_2005, AROUND_2010), + FIXED_MODE_WINDOW_FRAME_EDGE_TOP(SpriteID.FIXED_MODE_WINDOW_FRAME_EDGE_TOP, AROUND_2005, AROUND_2010), + FIXED_MODE_MINIMAP_AND_COMPASS_FRAME(SpriteID.FIXED_MODE_MINIMAP_AND_COMPASS_FRAME, AROUND_2005, AROUND_2010), + FIXED_MODE_MINIMAP_FRAME_BOTTOM(SpriteID.FIXED_MODE_MINIMAP_FRAME_BOTTOM, AROUND_2005), + FIXED_MODE_TOP_RIGHT_CORNER(SpriteID.FIXED_MODE_TOP_RIGHT_CORNER, AROUND_2005), + + RESIZEABLE_MODE_TABS_TOP_ROW(SpriteID.RESIZEABLE_MODE_TABS_TOP_ROW, AROUND_2010), + RESIZEABLE_MODE_TABS_BOTTOM_ROW(SpriteID.RESIZEABLE_MODE_TABS_BOTTOM_ROW, AROUND_2010), + RESIZEABLE_MODE_SIDE_PANEL_EDGE_LEFT(SpriteID.RESIZEABLE_MODE_SIDE_PANEL_EDGE_LEFT, AROUND_2010), + RESIZEABLE_MODE_SIDE_PANEL_EDGE_RIGHT(SpriteID.RESIZEABLE_MODE_SIDE_PANEL_EDGE_RIGHT, AROUND_2010), + RESIZEABLE_MODE_MINIMAP_AND_COMPASS_FRAME(SpriteID.RESIZEABLE_MODE_MINIMAP_AND_COMPASS_FRAME, AROUND_2010), + RESIZEABLE_MODE_TAB_STONE_MIDDLE(SpriteID.RESIZEABLE_MODE_TAB_STONE_MIDDLE, AROUND_2010), + RESIZEABLE_MODE_TAB_STONE_MIDDLE_SELECTED(SpriteID.RESIZEABLE_MODE_TAB_STONE_MIDDLE_SELECTED, AROUND_2010); + + private int spriteID; + private Skin[] skin; + + SpriteOverride(int spriteID, Skin... skin) + { + this.spriteID = spriteID; + this.skin = skin; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/WidgetOverride.java b/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/WidgetOverride.java index 46997704a5..89019477ca 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/WidgetOverride.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/WidgetOverride.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.interfacestyles; - -import lombok.Getter; -import net.runelite.api.widgets.WidgetInfo; - -@Getter -enum WidgetOverride -{ - FIXED_CORNER_TOP_LEFT_2005(Skin.AROUND_2005, "1026", WidgetInfo.FIXED_VIEWPORT_COMBAT_TAB), - FIXED_CORNER_TOP_RIGHT_2005(Skin.AROUND_2005, "1027", WidgetInfo.FIXED_VIEWPORT_MAGIC_TAB), - FIXED_CORNER_BOTTOM_LEFT_2005(Skin.AROUND_2005, "1028", WidgetInfo.FIXED_VIEWPORT_CLAN_CHAT_TAB), - FIXED_CORNER_BOTTOM_RIGHT_2005(Skin.AROUND_2005, "1029", WidgetInfo.FIXED_VIEWPORT_MUSIC_TAB), - FIXED_TOP_LEFT_2005(Skin.AROUND_2005, "1030_top_left", WidgetInfo.FIXED_VIEWPORT_STATS_TAB, WidgetInfo.FIXED_VIEWPORT_QUESTS_TAB), - FIXED_TOP_RIGHT_2005(Skin.AROUND_2005, "1030_top_right", WidgetInfo.FIXED_VIEWPORT_EQUIPMENT_TAB, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB), - FIXED_TOP_MIDDLE_2005(Skin.AROUND_2005, "1030_top_middle", WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB), - FIXED_BOTTOM_LEFT_2005(Skin.AROUND_2005, "1030_bottom_left", WidgetInfo.FIXED_VIEWPORT_FRIENDS_TAB, WidgetInfo.FIXED_VIEWPORT_IGNORES_TAB), - FIXED_BOTTOM_RIGHT_2005(Skin.AROUND_2005, "1030_bottom_middle", WidgetInfo.FIXED_VIEWPORT_LOGOUT_TAB), - FIXED_BOTTOM_MIDDLE_2005(Skin.AROUND_2005, "1030_bottom_right", WidgetInfo.FIXED_VIEWPORT_OPTIONS_TAB, WidgetInfo.FIXED_VIEWPORT_EMOTES_TAB); - - private Skin skin; - private String name; - private WidgetInfo[] widgetInfo; - - WidgetOverride(Skin skin, String name, WidgetInfo... widgetInfo) - { - this.skin = skin; - this.name = name; - this.widgetInfo = widgetInfo; - } +/* + * Copyright (c) 2018, Lotto + * Copyright (c) 2018, Raqes + * 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 HOLDER 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.interfacestyles; + +import lombok.Getter; +import net.runelite.api.widgets.WidgetInfo; + +@Getter +enum WidgetOverride +{ + FIXED_CORNER_TOP_LEFT_2005(Skin.AROUND_2005, "1026", WidgetInfo.FIXED_VIEWPORT_COMBAT_TAB), + FIXED_CORNER_TOP_RIGHT_2005(Skin.AROUND_2005, "1027", WidgetInfo.FIXED_VIEWPORT_MAGIC_TAB), + FIXED_CORNER_BOTTOM_LEFT_2005(Skin.AROUND_2005, "1028", WidgetInfo.FIXED_VIEWPORT_CLAN_CHAT_TAB), + FIXED_CORNER_BOTTOM_RIGHT_2005(Skin.AROUND_2005, "1029", WidgetInfo.FIXED_VIEWPORT_MUSIC_TAB), + FIXED_TOP_LEFT_2005(Skin.AROUND_2005, "1030_top_left", WidgetInfo.FIXED_VIEWPORT_STATS_TAB, WidgetInfo.FIXED_VIEWPORT_QUESTS_TAB), + FIXED_TOP_RIGHT_2005(Skin.AROUND_2005, "1030_top_right", WidgetInfo.FIXED_VIEWPORT_EQUIPMENT_TAB, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB), + FIXED_TOP_MIDDLE_2005(Skin.AROUND_2005, "1030_top_middle", WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB), + FIXED_BOTTOM_LEFT_2005(Skin.AROUND_2005, "1030_bottom_left", WidgetInfo.FIXED_VIEWPORT_FRIENDS_TAB, WidgetInfo.FIXED_VIEWPORT_IGNORES_TAB), + FIXED_BOTTOM_RIGHT_2005(Skin.AROUND_2005, "1030_bottom_middle", WidgetInfo.FIXED_VIEWPORT_LOGOUT_TAB), + FIXED_BOTTOM_MIDDLE_2005(Skin.AROUND_2005, "1030_bottom_right", WidgetInfo.FIXED_VIEWPORT_OPTIONS_TAB, WidgetInfo.FIXED_VIEWPORT_EMOTES_TAB); + + private Skin skin; + private String name; + private WidgetInfo[] widgetInfo; + + WidgetOverride(Skin skin, String name, WidgetInfo... widgetInfo) + { + this.skin = skin; + this.name = name; + this.widgetInfo = widgetInfo; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerConfig.java index 38ff6d6e3d..8cefffc1de 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerConfig.java @@ -1,63 +1,63 @@ -/* - * Copyright (c) 2019 Hydrox6 - * 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.inventoryviewer; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup(InventoryViewerPlugin.CONFIG_GROUP_KEY) -public interface InventoryViewerConfig extends Config -{ - @ConfigItem( - keyName = "viewerMode", - name = "Mode", - description = "The mode to display the inventory viewer with" - ) - default InventoryViewerMode viewerMode() - { - return InventoryViewerMode.FULL; - } - - @ConfigItem( - keyName = "showFreeSlots", - name = "Show Free Slots", - description = "Whether to show a label with the free slots in the inventory" - ) - default boolean showFreeSlots() - { - return false; - } - - @ConfigItem( - keyName = "hideWhenInvOpen", - name = "Hide when inventory is open", - description = "Hide the inventory viewer when the player's inventory is open" - ) - default boolean hideWhenInvOpen() - { - return false; - } -} +/* + * Copyright (c) 2019 Hydrox6 + * 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.inventoryviewer; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup(InventoryViewerPlugin.CONFIG_GROUP_KEY) +public interface InventoryViewerConfig extends Config +{ + @ConfigItem( + keyName = "viewerMode", + name = "Mode", + description = "The mode to display the inventory viewer with" + ) + default InventoryViewerMode viewerMode() + { + return InventoryViewerMode.FULL; + } + + @ConfigItem( + keyName = "showFreeSlots", + name = "Show Free Slots", + description = "Whether to show a label with the free slots in the inventory" + ) + default boolean showFreeSlots() + { + return false; + } + + @ConfigItem( + keyName = "hideWhenInvOpen", + name = "Hide when inventory is open", + description = "Hide the inventory viewer when the player's inventory is open" + ) + default boolean hideWhenInvOpen() + { + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java index 7a2941158a..d5dd3de6eb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventoryviewer/InventoryViewerOverlay.java @@ -73,18 +73,18 @@ class InventoryViewerOverlay extends Overlay inventoryComponent.setOrientation(ComponentOrientation.HORIZONTAL); inventoryComponent.setBackgroundColor(null); inventoryComponent.setBorder(new Rectangle( - 0, - ComponentConstants.STANDARD_BORDER, - 0, - ComponentConstants.STANDARD_BORDER)); + 0, + ComponentConstants.STANDARD_BORDER, + 0, + ComponentConstants.STANDARD_BORDER)); wrapperComponent.setOrientation(ComponentOrientation.HORIZONTAL); wrapperComponent.setWrapping(2); wrapperComponent.setBorder(new Rectangle( - ComponentConstants.STANDARD_BORDER * 2, - ComponentConstants.STANDARD_BORDER, - ComponentConstants.STANDARD_BORDER * 2, - ComponentConstants.STANDARD_BORDER)); + ComponentConstants.STANDARD_BORDER * 2, + ComponentConstants.STANDARD_BORDER, + ComponentConstants.STANDARD_BORDER * 2, + ComponentConstants.STANDARD_BORDER)); this.itemManager = itemManager; this.client = client; @@ -95,7 +95,7 @@ class InventoryViewerOverlay extends Overlay public Dimension render(Graphics2D graphics) { if (config.hideWhenInvOpen() - && client.getVar(VarClientInt.PLAYER_INVENTORY_OPENED) == 3) + && client.getVar(VarClientInt.PLAYER_INVENTORY_OPENED) == 3) { return null; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java index 2e0e61ae8e..823a6678b6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java @@ -647,7 +647,7 @@ public class ItemChargePlugin extends Plugin return false; } - final ItemChargeInfobox i = (ItemChargeInfobox)t; + final ItemChargeInfobox i = (ItemChargeInfobox) t; return i.getItem() == item && i.getSlot() == slot; }); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java index f696097817..2f2fe76469 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java @@ -29,7 +29,133 @@ import java.util.Map; import javax.annotation.Nullable; import lombok.AllArgsConstructor; import lombok.Getter; -import static net.runelite.api.ItemID.*; +import static net.runelite.api.ItemID.ABYSSAL_BRACELET1; +import static net.runelite.api.ItemID.ABYSSAL_BRACELET2; +import static net.runelite.api.ItemID.ABYSSAL_BRACELET3; +import static net.runelite.api.ItemID.ABYSSAL_BRACELET4; +import static net.runelite.api.ItemID.ABYSSAL_BRACELET5; +import static net.runelite.api.ItemID.AMULET_OF_GLORY1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY4; +import static net.runelite.api.ItemID.AMULET_OF_GLORY5; +import static net.runelite.api.ItemID.AMULET_OF_GLORY6; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T4; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T5; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T6; +import static net.runelite.api.ItemID.BURNING_AMULET1; +import static net.runelite.api.ItemID.BURNING_AMULET2; +import static net.runelite.api.ItemID.BURNING_AMULET3; +import static net.runelite.api.ItemID.BURNING_AMULET4; +import static net.runelite.api.ItemID.BURNING_AMULET5; +import static net.runelite.api.ItemID.COMBAT_BRACELET1; +import static net.runelite.api.ItemID.COMBAT_BRACELET2; +import static net.runelite.api.ItemID.COMBAT_BRACELET3; +import static net.runelite.api.ItemID.COMBAT_BRACELET4; +import static net.runelite.api.ItemID.COMBAT_BRACELET5; +import static net.runelite.api.ItemID.COMBAT_BRACELET6; +import static net.runelite.api.ItemID.DIGSITE_PENDANT_1; +import static net.runelite.api.ItemID.DIGSITE_PENDANT_2; +import static net.runelite.api.ItemID.DIGSITE_PENDANT_3; +import static net.runelite.api.ItemID.DIGSITE_PENDANT_4; +import static net.runelite.api.ItemID.DIGSITE_PENDANT_5; +import static net.runelite.api.ItemID.ENCHANTED_LYRE1; +import static net.runelite.api.ItemID.ENCHANTED_LYRE2; +import static net.runelite.api.ItemID.ENCHANTED_LYRE3; +import static net.runelite.api.ItemID.ENCHANTED_LYRE4; +import static net.runelite.api.ItemID.ENCHANTED_LYRE5; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_0; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_1; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_10; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_2; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_3; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_4; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_5; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_6; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_7; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_8; +import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_9; +import static net.runelite.api.ItemID.GAMES_NECKLACE1; +import static net.runelite.api.ItemID.GAMES_NECKLACE2; +import static net.runelite.api.ItemID.GAMES_NECKLACE3; +import static net.runelite.api.ItemID.GAMES_NECKLACE4; +import static net.runelite.api.ItemID.GAMES_NECKLACE5; +import static net.runelite.api.ItemID.GAMES_NECKLACE6; +import static net.runelite.api.ItemID.GAMES_NECKLACE7; +import static net.runelite.api.ItemID.GAMES_NECKLACE8; +import static net.runelite.api.ItemID.IMPINABOX1; +import static net.runelite.api.ItemID.IMPINABOX2; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE1; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE2; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE3; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE4; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE5; +import static net.runelite.api.ItemID.OGRE_BELLOWS; +import static net.runelite.api.ItemID.OGRE_BELLOWS_1; +import static net.runelite.api.ItemID.OGRE_BELLOWS_2; +import static net.runelite.api.ItemID.OGRE_BELLOWS_3; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_1; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_2; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_3; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_4; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_5; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_6; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_7; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_8; +import static net.runelite.api.ItemID.RING_OF_DUELING1; +import static net.runelite.api.ItemID.RING_OF_DUELING2; +import static net.runelite.api.ItemID.RING_OF_DUELING3; +import static net.runelite.api.ItemID.RING_OF_DUELING4; +import static net.runelite.api.ItemID.RING_OF_DUELING5; +import static net.runelite.api.ItemID.RING_OF_DUELING6; +import static net.runelite.api.ItemID.RING_OF_DUELING7; +import static net.runelite.api.ItemID.RING_OF_DUELING8; +import static net.runelite.api.ItemID.RING_OF_RETURNING1; +import static net.runelite.api.ItemID.RING_OF_RETURNING2; +import static net.runelite.api.ItemID.RING_OF_RETURNING3; +import static net.runelite.api.ItemID.RING_OF_RETURNING4; +import static net.runelite.api.ItemID.RING_OF_RETURNING5; +import static net.runelite.api.ItemID.RING_OF_WEALTH_1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_5; +import static net.runelite.api.ItemID.SKILLS_NECKLACE1; +import static net.runelite.api.ItemID.SKILLS_NECKLACE2; +import static net.runelite.api.ItemID.SKILLS_NECKLACE3; +import static net.runelite.api.ItemID.SKILLS_NECKLACE4; +import static net.runelite.api.ItemID.SKILLS_NECKLACE5; +import static net.runelite.api.ItemID.SKILLS_NECKLACE6; +import static net.runelite.api.ItemID.SLAYER_RING_1; +import static net.runelite.api.ItemID.SLAYER_RING_2; +import static net.runelite.api.ItemID.SLAYER_RING_3; +import static net.runelite.api.ItemID.SLAYER_RING_4; +import static net.runelite.api.ItemID.SLAYER_RING_5; +import static net.runelite.api.ItemID.SLAYER_RING_6; +import static net.runelite.api.ItemID.SLAYER_RING_7; +import static net.runelite.api.ItemID.SLAYER_RING_8; +import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_1; +import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_2; +import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_3; +import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_4; +import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_5; +import static net.runelite.api.ItemID.WATERING_CAN; +import static net.runelite.api.ItemID.WATERING_CAN1; +import static net.runelite.api.ItemID.WATERING_CAN2; +import static net.runelite.api.ItemID.WATERING_CAN3; +import static net.runelite.api.ItemID.WATERING_CAN4; +import static net.runelite.api.ItemID.WATERING_CAN5; +import static net.runelite.api.ItemID.WATERING_CAN6; +import static net.runelite.api.ItemID.WATERING_CAN7; +import static net.runelite.api.ItemID.WATERING_CAN8; +import static net.runelite.api.ItemID.WATERSKIN0; +import static net.runelite.api.ItemID.WATERSKIN1; +import static net.runelite.api.ItemID.WATERSKIN2; +import static net.runelite.api.ItemID.WATERSKIN3; +import static net.runelite.api.ItemID.WATERSKIN4; import static net.runelite.client.plugins.itemcharges.ItemChargeType.ABYSSAL_BRACELET; import static net.runelite.client.plugins.itemcharges.ItemChargeType.BELLOWS; import static net.runelite.client.plugins.itemcharges.ItemChargeType.FUNGICIDE_SPRAY; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java index 622ab1c04e..d2e9913bbf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java @@ -46,7 +46,7 @@ enum ItemIdentification DWARF_WEED_SEED(Type.SEED, "Dwarf", "D", ItemID.DWARF_WEED_SEED), TORSTOL_SEED(Type.SEED, "Torstol", "TOR", ItemID.TORSTOL_SEED), POISON_IVY_SEED(Type.SEED, "Ivy", "I", ItemID.POISON_IVY_SEED), - WHITEBERRY_SEED( Type.SEED, "White", "W", ItemID.WHITEBERRY_SEED), + WHITEBERRY_SEED(Type.SEED, "White", "W", ItemID.WHITEBERRY_SEED), //Herbs GUAM(Type.HERB, "Guam", "G", ItemID.GUAM_LEAF, ItemID.GRIMY_GUAM_LEAF), @@ -92,7 +92,7 @@ enum ItemIdentification final String shortName; final int[] itemIDs; - ItemIdentification(Type type, String medName, String shortName, int ... ids) + ItemIdentification(Type type, String medName, String shortName, int... ids) { this.type = type; this.medName = medName; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/BoostedStatBoost.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/BoostedStatBoost.java index e44c2490ac..c6335672ca 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/BoostedStatBoost.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/BoostedStatBoost.java @@ -1,51 +1,51 @@ -/* - * Copyright (c) 2016-2018, Adam - * 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.itemstats; - -import net.runelite.client.plugins.itemstats.delta.DeltaCalculator; -import net.runelite.client.plugins.itemstats.stats.Stat; -import net.runelite.api.Client; - -/** - * A stat boost using the current boosted (or drained) stat. - */ -public class BoostedStatBoost extends StatBoost -{ - private final DeltaCalculator deltaCalculator; - - public BoostedStatBoost(Stat stat, boolean boost, DeltaCalculator deltaCalculator) - { - super(stat, boost); - this.deltaCalculator = deltaCalculator; - } - - @Override - public int heals(Client client) - { - int value = getStat().getValue(client); - return deltaCalculator.calculateDelta(value); - } - -} +/* + * Copyright (c) 2016-2018, Adam + * 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.itemstats; + +import net.runelite.api.Client; +import net.runelite.client.plugins.itemstats.delta.DeltaCalculator; +import net.runelite.client.plugins.itemstats.stats.Stat; + +/** + * A stat boost using the current boosted (or drained) stat. + */ +public class BoostedStatBoost extends StatBoost +{ + private final DeltaCalculator deltaCalculator; + + public BoostedStatBoost(Stat stat, boolean boost, DeltaCalculator deltaCalculator) + { + super(stat, boost); + this.deltaCalculator = deltaCalculator; + } + + @Override + public int heals(Client client) + { + int value = getStat().getValue(client); + return deltaCalculator.calculateDelta(value); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/Food.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/Food.java index ff3f3fb702..57281769c0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/Food.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/Food.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2016-2018, Adam - * 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.itemstats; - -import net.runelite.client.plugins.itemstats.delta.DeltaCalculator; -import net.runelite.api.Client; - -public class Food extends FoodBase -{ - private final DeltaCalculator p; - - public Food(DeltaCalculator p) - { - this.p = p; - } - - @Override - public int heals(Client client) - { - return p.calculateDelta(getStat().getMaximum(client)); - } - -} +/* + * Copyright (c) 2016-2018, Adam + * 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.itemstats; + +import net.runelite.api.Client; +import net.runelite.client.plugins.itemstats.delta.DeltaCalculator; + +public class Food extends FoodBase +{ + private final DeltaCalculator p; + + public Food(DeltaCalculator p) + { + this.p = p; + } + + @Override + public int heals(Client client) + { + return p.calculateDelta(getStat().getMaximum(client)); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java index bcce08ffe5..c03da92e0f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java @@ -30,15 +30,424 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import lombok.extern.slf4j.Slf4j; -import static net.runelite.api.ItemID.*; -import static net.runelite.client.plugins.itemstats.Builders.*; +import static net.runelite.api.ItemID.ADMIRAL_PIE; +import static net.runelite.api.ItemID.AGILITY_POTION1; +import static net.runelite.api.ItemID.AGILITY_POTION2; +import static net.runelite.api.ItemID.AGILITY_POTION3; +import static net.runelite.api.ItemID.AGILITY_POTION4; +import static net.runelite.api.ItemID.ANCHOVIES; +import static net.runelite.api.ItemID.ANCHOVY_PIZZA; +import static net.runelite.api.ItemID.ANGLERFISH; +import static net.runelite.api.ItemID.APPLE_PIE; +import static net.runelite.api.ItemID.ATTACK_POTION1; +import static net.runelite.api.ItemID.ATTACK_POTION2; +import static net.runelite.api.ItemID.ATTACK_POTION3; +import static net.runelite.api.ItemID.ATTACK_POTION4; +import static net.runelite.api.ItemID.AUTUMN_SQIRKJUICE; +import static net.runelite.api.ItemID.BAGUETTE; +import static net.runelite.api.ItemID.BAKED_POTATO; +import static net.runelite.api.ItemID.BANANA; +import static net.runelite.api.ItemID.BANDAGES; +import static net.runelite.api.ItemID.BASS; +import static net.runelite.api.ItemID.BASTION_POTION1; +import static net.runelite.api.ItemID.BASTION_POTION2; +import static net.runelite.api.ItemID.BASTION_POTION3; +import static net.runelite.api.ItemID.BASTION_POTION4; +import static net.runelite.api.ItemID.BATTLEMAGE_POTION1; +import static net.runelite.api.ItemID.BATTLEMAGE_POTION2; +import static net.runelite.api.ItemID.BATTLEMAGE_POTION3; +import static net.runelite.api.ItemID.BATTLEMAGE_POTION4; +import static net.runelite.api.ItemID.BAT_SHISH; +import static net.runelite.api.ItemID.BOTANICAL_PIE; +import static net.runelite.api.ItemID.BOTTLE_OF_WINE; +import static net.runelite.api.ItemID.BRAWK_FISH_3; +import static net.runelite.api.ItemID.BREAD; +import static net.runelite.api.ItemID.CABBAGE; +import static net.runelite.api.ItemID.CABBAGE_1967; +import static net.runelite.api.ItemID.CAKE; +import static net.runelite.api.ItemID.CAVE_EEL; +import static net.runelite.api.ItemID.CAVIAR; +import static net.runelite.api.ItemID.CHEESE; +import static net.runelite.api.ItemID.CHEESETOM_BATTA; +import static net.runelite.api.ItemID.CHILLI_CON_CARNE; +import static net.runelite.api.ItemID.CHILLI_POTATO; +import static net.runelite.api.ItemID.CHOCCHIP_CRUNCHIES; +import static net.runelite.api.ItemID.CHOCICE; +import static net.runelite.api.ItemID.CHOCOLATEY_MILK; +import static net.runelite.api.ItemID.CHOCOLATE_BAR; +import static net.runelite.api.ItemID.CHOCOLATE_BOMB; +import static net.runelite.api.ItemID.CHOCOLATE_CAKE; +import static net.runelite.api.ItemID.CHOCOLATE_SLICE; +import static net.runelite.api.ItemID.CHOC_SATURDAY; +import static net.runelite.api.ItemID.CHOPPED_ONION; +import static net.runelite.api.ItemID.CHOPPED_TOMATO; +import static net.runelite.api.ItemID.CHOPPED_TUNA; +import static net.runelite.api.ItemID.COATED_FROGS_LEGS; +import static net.runelite.api.ItemID.COD; +import static net.runelite.api.ItemID.COMBAT_POTION1; +import static net.runelite.api.ItemID.COMBAT_POTION2; +import static net.runelite.api.ItemID.COMBAT_POTION3; +import static net.runelite.api.ItemID.COMBAT_POTION4; +import static net.runelite.api.ItemID.COOKED_CHICKEN; +import static net.runelite.api.ItemID.COOKED_CHOMPY; +import static net.runelite.api.ItemID.COOKED_CRAB_MEAT; +import static net.runelite.api.ItemID.COOKED_FISHCAKE; +import static net.runelite.api.ItemID.COOKED_JUBBLY; +import static net.runelite.api.ItemID.COOKED_KARAMBWAN; +import static net.runelite.api.ItemID.COOKED_MEAT; +import static net.runelite.api.ItemID.COOKED_RABBIT; +import static net.runelite.api.ItemID.COOKED_SLIMY_EEL; +import static net.runelite.api.ItemID.COOKED_SWEETCORN; +import static net.runelite.api.ItemID.CURRY; +import static net.runelite.api.ItemID.DARK_CRAB; +import static net.runelite.api.ItemID.DEFENCE_POTION1; +import static net.runelite.api.ItemID.DEFENCE_POTION2; +import static net.runelite.api.ItemID.DEFENCE_POTION3; +import static net.runelite.api.ItemID.DEFENCE_POTION4; +import static net.runelite.api.ItemID.DRUNK_DRAGON; +import static net.runelite.api.ItemID.DWELLBERRIES; +import static net.runelite.api.ItemID.EASTER_EGG; +import static net.runelite.api.ItemID.EDIBLE_SEAWEED; +import static net.runelite.api.ItemID.EEL_SUSHI; +import static net.runelite.api.ItemID.EGG_AND_TOMATO; +import static net.runelite.api.ItemID.EGG_POTATO; +import static net.runelite.api.ItemID.ELDER_1; +import static net.runelite.api.ItemID.ELDER_1_20921; +import static net.runelite.api.ItemID.ELDER_2; +import static net.runelite.api.ItemID.ELDER_2_20922; +import static net.runelite.api.ItemID.ELDER_3; +import static net.runelite.api.ItemID.ELDER_3_20923; +import static net.runelite.api.ItemID.ELDER_4; +import static net.runelite.api.ItemID.ELDER_4_20924; +import static net.runelite.api.ItemID.ELDER_POTION_1; +import static net.runelite.api.ItemID.ELDER_POTION_2; +import static net.runelite.api.ItemID.ELDER_POTION_3; +import static net.runelite.api.ItemID.ELDER_POTION_4; +import static net.runelite.api.ItemID.ENERGY_POTION1; +import static net.runelite.api.ItemID.ENERGY_POTION2; +import static net.runelite.api.ItemID.ENERGY_POTION3; +import static net.runelite.api.ItemID.ENERGY_POTION4; +import static net.runelite.api.ItemID.FAT_SNAIL_MEAT; +import static net.runelite.api.ItemID.FIELD_RATION; +import static net.runelite.api.ItemID.FILLETS; +import static net.runelite.api.ItemID.FINGERS; +import static net.runelite.api.ItemID.FISHING_POTION1; +import static net.runelite.api.ItemID.FISHING_POTION2; +import static net.runelite.api.ItemID.FISHING_POTION3; +import static net.runelite.api.ItemID.FISHING_POTION4; +import static net.runelite.api.ItemID.FISH_PIE; +import static net.runelite.api.ItemID.FRIED_MUSHROOMS; +import static net.runelite.api.ItemID.FRIED_ONIONS; +import static net.runelite.api.ItemID.FROGBURGER; +import static net.runelite.api.ItemID.FROGSPAWN_GUMBO; +import static net.runelite.api.ItemID.FROG_SPAWN; +import static net.runelite.api.ItemID.FRUIT_BATTA; +import static net.runelite.api.ItemID.FRUIT_BLAST; +import static net.runelite.api.ItemID.GARDEN_PIE; +import static net.runelite.api.ItemID.GIANT_CARP; +import static net.runelite.api.ItemID.GIRAL_BAT_2; +import static net.runelite.api.ItemID.GOUT_TUBER; +import static net.runelite.api.ItemID.GREEN_GLOOP_SOUP; +import static net.runelite.api.ItemID.GRUBS__LA_MODE; +import static net.runelite.api.ItemID.GUANIC_BAT_0; +import static net.runelite.api.ItemID.GUTHIX_REST1; +import static net.runelite.api.ItemID.GUTHIX_REST2; +import static net.runelite.api.ItemID.GUTHIX_REST3; +import static net.runelite.api.ItemID.GUTHIX_REST4; +import static net.runelite.api.ItemID.HALF_AN_ADMIRAL_PIE; +import static net.runelite.api.ItemID.HALF_AN_APPLE_PIE; +import static net.runelite.api.ItemID.HALF_A_BOTANICAL_PIE; +import static net.runelite.api.ItemID.HALF_A_FISH_PIE; +import static net.runelite.api.ItemID.HALF_A_GARDEN_PIE; +import static net.runelite.api.ItemID.HALF_A_MEAT_PIE; +import static net.runelite.api.ItemID.HALF_A_MUSHROOM_PIE; +import static net.runelite.api.ItemID.HALF_A_REDBERRY_PIE; +import static net.runelite.api.ItemID.HALF_A_SUMMER_PIE; +import static net.runelite.api.ItemID.HALF_A_WILD_PIE; +import static net.runelite.api.ItemID.HERRING; +import static net.runelite.api.ItemID.HUNTER_POTION1; +import static net.runelite.api.ItemID.HUNTER_POTION2; +import static net.runelite.api.ItemID.HUNTER_POTION3; +import static net.runelite.api.ItemID.HUNTER_POTION4; +import static net.runelite.api.ItemID.IMBUED_HEART; +import static net.runelite.api.ItemID.JANGERBERRIES; +import static net.runelite.api.ItemID.JUG_OF_WINE; +import static net.runelite.api.ItemID.KODAI_1; +import static net.runelite.api.ItemID.KODAI_1_20945; +import static net.runelite.api.ItemID.KODAI_2; +import static net.runelite.api.ItemID.KODAI_2_20946; +import static net.runelite.api.ItemID.KODAI_3; +import static net.runelite.api.ItemID.KODAI_3_20947; +import static net.runelite.api.ItemID.KODAI_4; +import static net.runelite.api.ItemID.KODAI_4_20948; +import static net.runelite.api.ItemID.KODAI_POTION_1; +import static net.runelite.api.ItemID.KODAI_POTION_2; +import static net.runelite.api.ItemID.KODAI_POTION_3; +import static net.runelite.api.ItemID.KODAI_POTION_4; +import static net.runelite.api.ItemID.KRYKET_BAT_4; +import static net.runelite.api.ItemID.KYREN_FISH_6; +import static net.runelite.api.ItemID.LAVA_EEL; +import static net.runelite.api.ItemID.LECKISH_FISH_2; +import static net.runelite.api.ItemID.LEMON; +import static net.runelite.api.ItemID.LEMON_CHUNKS; +import static net.runelite.api.ItemID.LEMON_SLICES; +import static net.runelite.api.ItemID.LIME; +import static net.runelite.api.ItemID.LIME_CHUNKS; +import static net.runelite.api.ItemID.LIME_SLICES; +import static net.runelite.api.ItemID.LOACH; +import static net.runelite.api.ItemID.LOBSTER; +import static net.runelite.api.ItemID.MACKEREL; +import static net.runelite.api.ItemID.MAGIC_ESSENCE1; +import static net.runelite.api.ItemID.MAGIC_ESSENCE2; +import static net.runelite.api.ItemID.MAGIC_ESSENCE3; +import static net.runelite.api.ItemID.MAGIC_ESSENCE4; +import static net.runelite.api.ItemID.MAGIC_POTION1; +import static net.runelite.api.ItemID.MAGIC_POTION2; +import static net.runelite.api.ItemID.MAGIC_POTION3; +import static net.runelite.api.ItemID.MAGIC_POTION4; +import static net.runelite.api.ItemID.MANTA_RAY; +import static net.runelite.api.ItemID.MEAT_PIE; +import static net.runelite.api.ItemID.MEAT_PIZZA; +import static net.runelite.api.ItemID.MINT_CAKE; +import static net.runelite.api.ItemID.MONKFISH; +import static net.runelite.api.ItemID.MOONLIGHT_MEAD; +import static net.runelite.api.ItemID.MURNG_BAT_5; +import static net.runelite.api.ItemID.MUSHROOMS; +import static net.runelite.api.ItemID.MUSHROOM_PIE; +import static net.runelite.api.ItemID.MUSHROOM_POTATO; +import static net.runelite.api.ItemID.MUSHROOM__ONION; +import static net.runelite.api.ItemID.MYCIL_FISH_4; +import static net.runelite.api.ItemID.ONION; +import static net.runelite.api.ItemID.ORANGE; +import static net.runelite.api.ItemID.ORANGE_CHUNKS; +import static net.runelite.api.ItemID.ORANGE_SLICES; +import static net.runelite.api.ItemID.OVERLOAD_1; +import static net.runelite.api.ItemID.OVERLOAD_1_20985; +import static net.runelite.api.ItemID.OVERLOAD_1_20989; +import static net.runelite.api.ItemID.OVERLOAD_1_20993; +import static net.runelite.api.ItemID.OVERLOAD_2; +import static net.runelite.api.ItemID.OVERLOAD_2_20986; +import static net.runelite.api.ItemID.OVERLOAD_2_20990; +import static net.runelite.api.ItemID.OVERLOAD_2_20994; +import static net.runelite.api.ItemID.OVERLOAD_3; +import static net.runelite.api.ItemID.OVERLOAD_3_20987; +import static net.runelite.api.ItemID.OVERLOAD_3_20991; +import static net.runelite.api.ItemID.OVERLOAD_3_20995; +import static net.runelite.api.ItemID.OVERLOAD_4; +import static net.runelite.api.ItemID.OVERLOAD_4_20988; +import static net.runelite.api.ItemID.OVERLOAD_4_20992; +import static net.runelite.api.ItemID.OVERLOAD_4_20996; +import static net.runelite.api.ItemID.PAPAYA_FRUIT; +import static net.runelite.api.ItemID.PEACH; +import static net.runelite.api.ItemID.PHLUXIA_BAT_3; +import static net.runelite.api.ItemID.PIKE; +import static net.runelite.api.ItemID.PINEAPPLE_CHUNKS; +import static net.runelite.api.ItemID.PINEAPPLE_PIZZA; +import static net.runelite.api.ItemID.PINEAPPLE_PUNCH; +import static net.runelite.api.ItemID.PINEAPPLE_RING; +import static net.runelite.api.ItemID.PLAIN_PIZZA; +import static net.runelite.api.ItemID.POISON_KARAMBWAN; +import static net.runelite.api.ItemID.POTATO; +import static net.runelite.api.ItemID.POTATO_WITH_BUTTER; +import static net.runelite.api.ItemID.POTATO_WITH_CHEESE; +import static net.runelite.api.ItemID.POT_OF_CREAM; +import static net.runelite.api.ItemID.PRAEL_BAT_1; +import static net.runelite.api.ItemID.PRAYER_POTION1; +import static net.runelite.api.ItemID.PRAYER_POTION2; +import static net.runelite.api.ItemID.PRAYER_POTION3; +import static net.runelite.api.ItemID.PRAYER_POTION4; +import static net.runelite.api.ItemID.PREMADE_CHOC_BOMB; +import static net.runelite.api.ItemID.PREMADE_CHOC_SDY; +import static net.runelite.api.ItemID.PREMADE_CH_CRUNCH; +import static net.runelite.api.ItemID.PREMADE_CT_BATTA; +import static net.runelite.api.ItemID.PREMADE_DR_DRAGON; +import static net.runelite.api.ItemID.PREMADE_FRT_BATTA; +import static net.runelite.api.ItemID.PREMADE_FR_BLAST; +import static net.runelite.api.ItemID.PREMADE_P_PUNCH; +import static net.runelite.api.ItemID.PREMADE_SGG; +import static net.runelite.api.ItemID.PREMADE_SY_CRUNCH; +import static net.runelite.api.ItemID.PREMADE_TD_BATTA; +import static net.runelite.api.ItemID.PREMADE_TD_CRUNCH; +import static net.runelite.api.ItemID.PREMADE_TTL; +import static net.runelite.api.ItemID.PREMADE_VEG_BALL; +import static net.runelite.api.ItemID.PREMADE_VEG_BATTA; +import static net.runelite.api.ItemID.PREMADE_WIZ_BLZD; +import static net.runelite.api.ItemID.PREMADE_WM_BATTA; +import static net.runelite.api.ItemID.PREMADE_WM_CRUN; +import static net.runelite.api.ItemID.PREMADE_WORM_HOLE; +import static net.runelite.api.ItemID.PSYKK_BAT_6; +import static net.runelite.api.ItemID.PUMPKIN; +import static net.runelite.api.ItemID.PURPLE_SWEETS_10476; +import static net.runelite.api.ItemID.PYSK_FISH_0; +import static net.runelite.api.ItemID.RAINBOW_FISH; +import static net.runelite.api.ItemID.RANGING_POTION1; +import static net.runelite.api.ItemID.RANGING_POTION2; +import static net.runelite.api.ItemID.RANGING_POTION3; +import static net.runelite.api.ItemID.RANGING_POTION4; +import static net.runelite.api.ItemID.REDBERRY_PIE; +import static net.runelite.api.ItemID.RESTORE_POTION1; +import static net.runelite.api.ItemID.RESTORE_POTION2; +import static net.runelite.api.ItemID.RESTORE_POTION3; +import static net.runelite.api.ItemID.RESTORE_POTION4; +import static net.runelite.api.ItemID.REVITALISATION_1_20957; +import static net.runelite.api.ItemID.REVITALISATION_2_20958; +import static net.runelite.api.ItemID.REVITALISATION_3_20959; +import static net.runelite.api.ItemID.REVITALISATION_4_20960; +import static net.runelite.api.ItemID.ROAST_BEAST_MEAT; +import static net.runelite.api.ItemID.ROAST_BIRD_MEAT; +import static net.runelite.api.ItemID.ROAST_FROG; +import static net.runelite.api.ItemID.ROAST_RABBIT; +import static net.runelite.api.ItemID.ROE; +import static net.runelite.api.ItemID.ROLL; +import static net.runelite.api.ItemID.ROQED_FISH_5; +import static net.runelite.api.ItemID.SALMON; +import static net.runelite.api.ItemID.SANFEW_SERUM1; +import static net.runelite.api.ItemID.SANFEW_SERUM2; +import static net.runelite.api.ItemID.SANFEW_SERUM3; +import static net.runelite.api.ItemID.SANFEW_SERUM4; +import static net.runelite.api.ItemID.SARADOMIN_BREW1; +import static net.runelite.api.ItemID.SARADOMIN_BREW2; +import static net.runelite.api.ItemID.SARADOMIN_BREW3; +import static net.runelite.api.ItemID.SARADOMIN_BREW4; +import static net.runelite.api.ItemID.SARDINE; +import static net.runelite.api.ItemID.SEA_TURTLE; +import static net.runelite.api.ItemID.SHARK; +import static net.runelite.api.ItemID.SHORT_GREEN_GUY; +import static net.runelite.api.ItemID.SHRIMPS; +import static net.runelite.api.ItemID.SLICED_BANANA; +import static net.runelite.api.ItemID.SLICE_OF_CAKE; +import static net.runelite.api.ItemID.SPICY_CRUNCHIES; +import static net.runelite.api.ItemID.SPICY_SAUCE; +import static net.runelite.api.ItemID.SPICY_STEW; +import static net.runelite.api.ItemID.SPINACH_ROLL; +import static net.runelite.api.ItemID.SPRING_SQIRKJUICE; +import static net.runelite.api.ItemID.SQUARE_SANDWICH; +import static net.runelite.api.ItemID.STAMINA_POTION1; +import static net.runelite.api.ItemID.STAMINA_POTION2; +import static net.runelite.api.ItemID.STAMINA_POTION3; +import static net.runelite.api.ItemID.STAMINA_POTION4; +import static net.runelite.api.ItemID.STEW; +import static net.runelite.api.ItemID.STRANGE_FRUIT; +import static net.runelite.api.ItemID.STRAWBERRY; +import static net.runelite.api.ItemID.STRENGTH_POTION1; +import static net.runelite.api.ItemID.STRENGTH_POTION2; +import static net.runelite.api.ItemID.STRENGTH_POTION3; +import static net.runelite.api.ItemID.STRENGTH_POTION4; +import static net.runelite.api.ItemID.STUFFED_SNAKE; +import static net.runelite.api.ItemID.SUMMER_PIE; +import static net.runelite.api.ItemID.SUMMER_SQIRKJUICE; +import static net.runelite.api.ItemID.SUPER_ATTACK1; +import static net.runelite.api.ItemID.SUPER_ATTACK2; +import static net.runelite.api.ItemID.SUPER_ATTACK3; +import static net.runelite.api.ItemID.SUPER_ATTACK4; +import static net.runelite.api.ItemID.SUPER_COMBAT_POTION1; +import static net.runelite.api.ItemID.SUPER_COMBAT_POTION2; +import static net.runelite.api.ItemID.SUPER_COMBAT_POTION3; +import static net.runelite.api.ItemID.SUPER_COMBAT_POTION4; +import static net.runelite.api.ItemID.SUPER_DEFENCE1; +import static net.runelite.api.ItemID.SUPER_DEFENCE2; +import static net.runelite.api.ItemID.SUPER_DEFENCE3; +import static net.runelite.api.ItemID.SUPER_DEFENCE4; +import static net.runelite.api.ItemID.SUPER_ENERGY1; +import static net.runelite.api.ItemID.SUPER_ENERGY2; +import static net.runelite.api.ItemID.SUPER_ENERGY3; +import static net.runelite.api.ItemID.SUPER_ENERGY4; +import static net.runelite.api.ItemID.SUPER_MAGIC_POTION_1; +import static net.runelite.api.ItemID.SUPER_MAGIC_POTION_2; +import static net.runelite.api.ItemID.SUPER_MAGIC_POTION_3; +import static net.runelite.api.ItemID.SUPER_MAGIC_POTION_4; +import static net.runelite.api.ItemID.SUPER_RANGING_1; +import static net.runelite.api.ItemID.SUPER_RANGING_2; +import static net.runelite.api.ItemID.SUPER_RANGING_3; +import static net.runelite.api.ItemID.SUPER_RANGING_4; +import static net.runelite.api.ItemID.SUPER_RESTORE1; +import static net.runelite.api.ItemID.SUPER_RESTORE2; +import static net.runelite.api.ItemID.SUPER_RESTORE3; +import static net.runelite.api.ItemID.SUPER_RESTORE4; +import static net.runelite.api.ItemID.SUPER_STRENGTH1; +import static net.runelite.api.ItemID.SUPER_STRENGTH2; +import static net.runelite.api.ItemID.SUPER_STRENGTH3; +import static net.runelite.api.ItemID.SUPER_STRENGTH4; +import static net.runelite.api.ItemID.SUPHI_FISH_1; +import static net.runelite.api.ItemID.SWEETCORN_7088; +import static net.runelite.api.ItemID.SWORDFISH; +import static net.runelite.api.ItemID.TANGLED_TOADS_LEGS; +import static net.runelite.api.ItemID.THIN_SNAIL_MEAT; +import static net.runelite.api.ItemID.TOAD_BATTA; +import static net.runelite.api.ItemID.TOAD_CRUNCHIES; +import static net.runelite.api.ItemID.TOMATO; +import static net.runelite.api.ItemID.TRIANGLE_SANDWICH; +import static net.runelite.api.ItemID.TROUT; +import static net.runelite.api.ItemID.TUNA; +import static net.runelite.api.ItemID.TUNA_AND_CORN; +import static net.runelite.api.ItemID.TUNA_POTATO; +import static net.runelite.api.ItemID.TWISTED_1; +import static net.runelite.api.ItemID.TWISTED_1_20933; +import static net.runelite.api.ItemID.TWISTED_2; +import static net.runelite.api.ItemID.TWISTED_2_20934; +import static net.runelite.api.ItemID.TWISTED_3; +import static net.runelite.api.ItemID.TWISTED_3_20935; +import static net.runelite.api.ItemID.TWISTED_4; +import static net.runelite.api.ItemID.TWISTED_4_20936; +import static net.runelite.api.ItemID.TWISTED_POTION_1; +import static net.runelite.api.ItemID.TWISTED_POTION_2; +import static net.runelite.api.ItemID.TWISTED_POTION_3; +import static net.runelite.api.ItemID.TWISTED_POTION_4; +import static net.runelite.api.ItemID.UGTHANKI_KEBAB; +import static net.runelite.api.ItemID.UGTHANKI_KEBAB_1885; +import static net.runelite.api.ItemID.VEGETABLE_BATTA; +import static net.runelite.api.ItemID.VEG_BALL; +import static net.runelite.api.ItemID.WATERMELON_SLICE; +import static net.runelite.api.ItemID.WHITE_TREE_FRUIT; +import static net.runelite.api.ItemID.WILD_PIE; +import static net.runelite.api.ItemID.WINTER_SQIRKJUICE; +import static net.runelite.api.ItemID.WIZARD_BLIZZARD; +import static net.runelite.api.ItemID.WORM_BATTA; +import static net.runelite.api.ItemID.WORM_CRUNCHIES; +import static net.runelite.api.ItemID.WORM_HOLE; +import static net.runelite.api.ItemID.XERICS_AID_1_20981; +import static net.runelite.api.ItemID.XERICS_AID_2_20982; +import static net.runelite.api.ItemID.XERICS_AID_3_20983; +import static net.runelite.api.ItemID.XERICS_AID_4_20984; +import static net.runelite.api.ItemID.ZAMORAK_BREW1; +import static net.runelite.api.ItemID.ZAMORAK_BREW2; +import static net.runelite.api.ItemID.ZAMORAK_BREW3; +import static net.runelite.api.ItemID.ZAMORAK_BREW4; +import static net.runelite.api.ItemID._12_ANCHOVY_PIZZA; +import static net.runelite.api.ItemID._12_MEAT_PIZZA; +import static net.runelite.api.ItemID._12_PINEAPPLE_PIZZA; +import static net.runelite.api.ItemID._12_PLAIN_PIZZA; +import static net.runelite.api.ItemID._23_CAKE; +import static net.runelite.api.ItemID._23_CHOCOLATE_CAKE; +import static net.runelite.client.plugins.itemstats.Builders.boost; +import static net.runelite.client.plugins.itemstats.Builders.combo; +import static net.runelite.client.plugins.itemstats.Builders.dec; +import static net.runelite.client.plugins.itemstats.Builders.food; +import static net.runelite.client.plugins.itemstats.Builders.heal; +import static net.runelite.client.plugins.itemstats.Builders.perc; +import static net.runelite.client.plugins.itemstats.Builders.range; import net.runelite.client.plugins.itemstats.food.Anglerfish; import net.runelite.client.plugins.itemstats.potions.PrayerPotion; import net.runelite.client.plugins.itemstats.potions.SaradominBrew; import net.runelite.client.plugins.itemstats.potions.SuperRestore; import net.runelite.client.plugins.itemstats.special.CastleWarsBandage; import net.runelite.client.plugins.itemstats.special.SpicyStew; -import static net.runelite.client.plugins.itemstats.stats.Stats.*; +import static net.runelite.client.plugins.itemstats.stats.Stats.AGILITY; +import static net.runelite.client.plugins.itemstats.stats.Stats.ATTACK; +import static net.runelite.client.plugins.itemstats.stats.Stats.CRAFTING; +import static net.runelite.client.plugins.itemstats.stats.Stats.DEFENCE; +import static net.runelite.client.plugins.itemstats.stats.Stats.FARMING; +import static net.runelite.client.plugins.itemstats.stats.Stats.FISHING; +import static net.runelite.client.plugins.itemstats.stats.Stats.HERBLORE; +import static net.runelite.client.plugins.itemstats.stats.Stats.HITPOINTS; +import static net.runelite.client.plugins.itemstats.stats.Stats.HUNTER; +import static net.runelite.client.plugins.itemstats.stats.Stats.MAGIC; +import static net.runelite.client.plugins.itemstats.stats.Stats.PRAYER; +import static net.runelite.client.plugins.itemstats.stats.Stats.RANGED; +import static net.runelite.client.plugins.itemstats.stats.Stats.RUN_ENERGY; +import static net.runelite.client.plugins.itemstats.stats.Stats.SLAYER; +import static net.runelite.client.plugins.itemstats.stats.Stats.STRENGTH; +import static net.runelite.client.plugins.itemstats.stats.Stats.THIEVING; @Singleton @Slf4j @@ -54,8 +463,8 @@ public class ItemStatChanges add(food(-5), POISON_KARAMBWAN); add(food(1), POTATO, ONION, CABBAGE, POT_OF_CREAM, CHOPPED_ONION, ANCHOVIES); add(food(2), TOMATO, CHOPPED_TOMATO, BANANA, SLICED_BANANA, ORANGE, ORANGE_SLICES, ORANGE_CHUNKS, - PINEAPPLE_RING, PINEAPPLE_CHUNKS, SPICY_SAUCE, CHEESE, SPINACH_ROLL, LEMON, LEMON_CHUNKS, LEMON_SLICES, - LIME, LIME_CHUNKS, LIME_SLICES, DWELLBERRIES); + PINEAPPLE_RING, PINEAPPLE_CHUNKS, SPICY_SAUCE, CHEESE, SPINACH_ROLL, LEMON, LEMON_CHUNKS, LEMON_SLICES, + LIME, LIME_CHUNKS, LIME_SLICES, DWELLBERRIES); add(food(3), SHRIMPS, COOKED_MEAT, COOKED_CHICKEN, ROE, CHOCOLATE_BAR); add(food(4), SARDINE, CAKE, _23_CAKE, SLICE_OF_CAKE, CHOCOLATEY_MILK, BAKED_POTATO, EDIBLE_SEAWEED, MOONLIGHT_MEAD); add(food(5), BREAD, HERRING, CHOCOLATE_CAKE, _23_CHOCOLATE_CAKE, CHOCOLATE_SLICE, COOKED_RABBIT, CHILLI_CON_CARNE, @@ -95,7 +504,7 @@ public class ItemStatChanges // Dorgeshuun Cuisine add(food(2), BAT_SHISH, COATED_FROGS_LEGS, FILLETS, FINGERS, FROGBURGER, FROGSPAWN_GUMBO, GREEN_GLOOP_SOUP, - GRUBS__LA_MODE, MUSHROOMS, ROAST_FROG); + GRUBS__LA_MODE, MUSHROOMS, ROAST_FROG); add(food(3), LOACH); add(range(food(3), food(6)), FROG_SPAWN); add(range(food(6), food(10)), COOKED_SLIMY_EEL); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatConfig.java index 3c7d586a86..6b99641473 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatConfig.java @@ -1,149 +1,150 @@ -/* - * Copyright (c) 2018 Abex - * 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.itemstats; - -import java.awt.Color; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("itemstat") -public interface ItemStatConfig extends Config -{ - @ConfigItem( - keyName = "consumableStats", - name = "Enable consumable stats", - description = "Enables tooltips for consumable items (food, boosts)" - ) - default boolean consumableStats() - { - return true; - } - - @ConfigItem( - keyName = "equipmentStats", - name = "Enable equipment stats", - description = "Enables tooltips for equipment items (combat bonuses, weight, prayer bonuses)" - ) - default boolean equipmentStats() - { - return true; - } - - @ConfigItem( - keyName = "geStats", - name = "Enable GE item information", - description = "Shows an item information panel when buying items in the GE" - ) - default boolean geStats() - { - return true; - } - - @ConfigItem( - keyName = "relative", - name = "Show Relative", - description = "Show relative stat change in tooltip" - ) - default boolean relative() - { - return true; - } - - @ConfigItem( - keyName = "absolute", - name = "Show Absolute", - description = "Show absolute stat change in tooltip" - ) - default boolean absolute() - { - return true; - } - - @ConfigItem( - keyName = "theoretical", - name = "Show Theoretical", - description = "Show theoretical stat change in tooltip" - ) - default boolean theoretical() - { - return false; - } - - @ConfigItem( - keyName = "colorBetterUncapped", - name = "Better (Uncapped)", - description = "Color to show when the stat change is fully consumed", - position = 10 - ) - default Color colorBetterUncapped() - { - return new Color(0x33EE33); - } - - @ConfigItem( - keyName = "colorBetterSomecapped", - name = "Better (Some capped)", - description = "Color to show when some stat changes are capped, but some ar not", - position = 11 - ) - default Color colorBetterSomeCapped() - { - return new Color(0x9CEE33); - } - - - @ConfigItem( - keyName = "colorBetterCapped", - name = "Better (Capped)", - description = "Color to show when the stat change is positive, but not fully consumed", - position = 12 - ) - default Color colorBetterCapped() - { - return new Color(0xEEEE33); - } - @ConfigItem( - keyName = "colorNoChange", - name = "No change", - description = "Color to show when there is no change", - position = 13 - ) - default Color colorNoChange() - { - return new Color(0xEEEEEE); - } - - @ConfigItem( - keyName = "colorWorse", - name = "Worse", - description = "Color to show when the stat goes down", - position = 14 - ) - default Color colorWorse() - { - return new Color(0xEE3333); - } -} +/* + * Copyright (c) 2018 Abex + * 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.itemstats; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("itemstat") +public interface ItemStatConfig extends Config +{ + @ConfigItem( + keyName = "consumableStats", + name = "Enable consumable stats", + description = "Enables tooltips for consumable items (food, boosts)" + ) + default boolean consumableStats() + { + return true; + } + + @ConfigItem( + keyName = "equipmentStats", + name = "Enable equipment stats", + description = "Enables tooltips for equipment items (combat bonuses, weight, prayer bonuses)" + ) + default boolean equipmentStats() + { + return true; + } + + @ConfigItem( + keyName = "geStats", + name = "Enable GE item information", + description = "Shows an item information panel when buying items in the GE" + ) + default boolean geStats() + { + return true; + } + + @ConfigItem( + keyName = "relative", + name = "Show Relative", + description = "Show relative stat change in tooltip" + ) + default boolean relative() + { + return true; + } + + @ConfigItem( + keyName = "absolute", + name = "Show Absolute", + description = "Show absolute stat change in tooltip" + ) + default boolean absolute() + { + return true; + } + + @ConfigItem( + keyName = "theoretical", + name = "Show Theoretical", + description = "Show theoretical stat change in tooltip" + ) + default boolean theoretical() + { + return false; + } + + @ConfigItem( + keyName = "colorBetterUncapped", + name = "Better (Uncapped)", + description = "Color to show when the stat change is fully consumed", + position = 10 + ) + default Color colorBetterUncapped() + { + return new Color(0x33EE33); + } + + @ConfigItem( + keyName = "colorBetterSomecapped", + name = "Better (Some capped)", + description = "Color to show when some stat changes are capped, but some ar not", + position = 11 + ) + default Color colorBetterSomeCapped() + { + return new Color(0x9CEE33); + } + + + @ConfigItem( + keyName = "colorBetterCapped", + name = "Better (Capped)", + description = "Color to show when the stat change is positive, but not fully consumed", + position = 12 + ) + default Color colorBetterCapped() + { + return new Color(0xEEEE33); + } + + @ConfigItem( + keyName = "colorNoChange", + name = "No change", + description = "Color to show when there is no change", + position = 13 + ) + default Color colorNoChange() + { + return new Color(0xEEEEEE); + } + + @ConfigItem( + keyName = "colorWorse", + name = "Worse", + description = "Color to show when the stat goes down", + position = 14 + ) + default Color colorWorse() + { + return new Color(0xEE3333); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java index 206ab6fc13..c7105b474b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java @@ -1,291 +1,291 @@ -/* - * Copyright (c) 2018 Abex - * 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.itemstats; - -import com.google.inject.Inject; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -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.MenuEntry; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.tooltip.Tooltip; -import net.runelite.client.ui.overlay.tooltip.TooltipManager; -import net.runelite.client.util.ColorUtil; -import net.runelite.http.api.item.ItemEquipmentStats; -import net.runelite.http.api.item.ItemStats; - -public class ItemStatOverlay extends Overlay -{ - // Unarmed attack speed is 6 - private static final ItemStats UNARMED = new ItemStats(false, true, 0, - ItemEquipmentStats.builder() - .aspeed(6) - .build()); - - @Inject - private Client client; - - @Inject - private ItemManager itemManager; - - @Inject - private TooltipManager tooltipManager; - - @Inject - private ItemStatChanges statChanges; - - @Inject - private ItemStatConfig config; - - @Override - public Dimension render(Graphics2D graphics) - { - if (client.isMenuOpen() || (!config.relative() && !config.absolute() && !config.theoretical())) - { - return null; - } - - final MenuEntry[] menu = client.getMenuEntries(); - final int menuSize = menu.length; - - if (menuSize <= 0) - { - return null; - } - - final MenuEntry entry = menu[menuSize - 1]; - final int group = WidgetInfo.TO_GROUP(entry.getParam1()); - final int child = WidgetInfo.TO_CHILD(entry.getParam1()); - final Widget widget = client.getWidget(group, child); - - if (widget == null || (group != WidgetInfo.INVENTORY.getGroupId() && - group != WidgetInfo.EQUIPMENT.getGroupId() && - group != WidgetInfo.EQUIPMENT_INVENTORY_ITEMS_CONTAINER.getGroupId())) - { - return null; - } - - int itemId = entry.getIdentifier(); - - if (group == WidgetInfo.EQUIPMENT.getGroupId()) - { - final Widget widgetItem = widget.getChild(1); - if (widgetItem != null) - { - itemId = widgetItem.getItemId(); - } - } - else if (group == WidgetInfo.EQUIPMENT_INVENTORY_ITEMS_CONTAINER.getGroupId()) - { - final Widget widgetItem = widget.getChild(entry.getParam0()); - if (widgetItem != null) - { - itemId = widgetItem.getItemId(); - } - } - - if (config.consumableStats()) - { - final Effect change = statChanges.get(itemId); - if (change != null) - { - final StringBuilder b = new StringBuilder(); - final StatsChanges statsChanges = change.calculate(client); - - for (final StatChange c : statsChanges.getStatChanges()) - { - b.append(buildStatChangeString(c)); - } - - final String tooltip = b.toString(); - - if (!tooltip.isEmpty()) - { - tooltipManager.add(new Tooltip(tooltip)); - } - } - } - - if (config.equipmentStats()) - { - final ItemStats stats = itemManager.getItemStats(itemId, false); - - if (stats != null) - { - final String tooltip = buildStatBonusString(stats); - - if (!tooltip.isEmpty()) - { - tooltipManager.add(new Tooltip(tooltip)); - } - } - } - - return null; - } - - private String getChangeString( - final String label, - final double value, - final boolean inverse, - final boolean showPercent) - { - final Color plus = Positivity.getColor(config, Positivity.BETTER_UNCAPPED); - final Color minus = Positivity.getColor(config, Positivity.WORSE); - - if (value == 0) - { - return ""; - } - - final Color color; - - if (inverse) - { - color = value > 0 ? minus : plus; - } - else - { - color = value > 0 ? plus : minus; - } - - final String prefix = value > 0 ? "+" : ""; - final String suffix = showPercent ? "%" : ""; - final String valueString = (int)value == value ? String.valueOf((int)value) : String.valueOf(value); - return label + ": " + ColorUtil.wrapWithColorTag(prefix + valueString + suffix, color) + "
"; - } - - private String buildStatBonusString(ItemStats s) - { - final StringBuilder b = new StringBuilder(); - b.append(getChangeString("Weight", s.getWeight(), true, false)); - - ItemStats other = null; - final ItemEquipmentStats currentEquipment = s.getEquipment(); - - ItemContainer c = client.getItemContainer(InventoryID.EQUIPMENT); - if (s.isEquipable() && currentEquipment != null && c != null) - { - final Item[] items = c.getItems(); - final int slot = currentEquipment.getSlot(); - - if (slot != -1 && slot < items.length) - { - final Item item = items[slot]; - if (item != null) - { - other = itemManager.getItemStats(item.getId(), false); - } - } - - if (other == null && slot == EquipmentInventorySlot.WEAPON.getSlotIdx()) - { - // Unarmed - other = UNARMED; - } - } - - final ItemStats subtracted = s.subtract(other); - final ItemEquipmentStats e = subtracted.getEquipment(); - - if (subtracted.isEquipable() && e != null) - { - b.append(getChangeString("Prayer", e.getPrayer(), false, false)); - b.append(getChangeString("Speed", e.getAspeed(), true, false)); - b.append(getChangeString("Melee Str", e.getStr(), false, false)); - b.append(getChangeString("Range Str", e.getRstr(), false, false)); - b.append(getChangeString("Magic Dmg", e.getMdmg(), false, true)); - - if (e.getAstab() != 0 || e.getAslash() != 0 || e.getAcrush() != 0 || e.getAmagic() != 0 || e.getArange() != 0) - { - b.append(ColorUtil.wrapWithColorTag("Attack Bonus
", JagexColors.MENU_TARGET)); - b.append(getChangeString("Stab", e.getAstab(), false, false)); - b.append(getChangeString("Slash", e.getAslash(), false, false)); - b.append(getChangeString("Crush", e.getAcrush(), false, false)); - b.append(getChangeString("Magic", e.getAmagic(), false, false)); - b.append(getChangeString("Range", e.getArange(), false, false)); - } - - if (e.getDstab() != 0 || e.getDslash() != 0 || e.getDcrush() != 0 || e.getDmagic() != 0 || e.getDrange() != 0) - { - b.append(ColorUtil.wrapWithColorTag("Defence Bonus
", JagexColors.MENU_TARGET)); - b.append(getChangeString("Stab", e.getDstab(), false, false)); - b.append(getChangeString("Slash", e.getDslash(), false, false)); - b.append(getChangeString("Crush", e.getDcrush(), false, false)); - b.append(getChangeString("Magic", e.getDmagic(), false, false)); - b.append(getChangeString("Range", e.getDrange(), false, false)); - } - } - - return b.toString(); - } - - private String buildStatChangeString(StatChange c) - { - StringBuilder b = new StringBuilder(); - b.append(ColorUtil.colorTag(Positivity.getColor(config, c.getPositivity()))); - - if (config.relative()) - { - b.append(c.getFormattedRelative()); - } - - if (config.theoretical()) - { - if (config.relative()) - { - b.append("/"); - } - b.append(c.getFormattedTheoretical()); - } - - if (config.absolute() && (config.relative() || config.theoretical())) - { - b.append(" ("); - } - if (config.absolute()) - { - b.append(c.getAbsolute()); - } - - if (config.absolute() && (config.relative() || config.theoretical())) - { - b.append(")"); - } - b.append(" ").append(c.getStat().getName()); - b.append("
"); - - return b.toString(); - } -} +/* + * Copyright (c) 2018 Abex + * 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.itemstats; + +import com.google.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +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.MenuEntry; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.tooltip.Tooltip; +import net.runelite.client.ui.overlay.tooltip.TooltipManager; +import net.runelite.client.util.ColorUtil; +import net.runelite.http.api.item.ItemEquipmentStats; +import net.runelite.http.api.item.ItemStats; + +public class ItemStatOverlay extends Overlay +{ + // Unarmed attack speed is 6 + private static final ItemStats UNARMED = new ItemStats(false, true, 0, + ItemEquipmentStats.builder() + .aspeed(6) + .build()); + + @Inject + private Client client; + + @Inject + private ItemManager itemManager; + + @Inject + private TooltipManager tooltipManager; + + @Inject + private ItemStatChanges statChanges; + + @Inject + private ItemStatConfig config; + + @Override + public Dimension render(Graphics2D graphics) + { + if (client.isMenuOpen() || (!config.relative() && !config.absolute() && !config.theoretical())) + { + return null; + } + + final MenuEntry[] menu = client.getMenuEntries(); + final int menuSize = menu.length; + + if (menuSize <= 0) + { + return null; + } + + final MenuEntry entry = menu[menuSize - 1]; + final int group = WidgetInfo.TO_GROUP(entry.getParam1()); + final int child = WidgetInfo.TO_CHILD(entry.getParam1()); + final Widget widget = client.getWidget(group, child); + + if (widget == null || (group != WidgetInfo.INVENTORY.getGroupId() && + group != WidgetInfo.EQUIPMENT.getGroupId() && + group != WidgetInfo.EQUIPMENT_INVENTORY_ITEMS_CONTAINER.getGroupId())) + { + return null; + } + + int itemId = entry.getIdentifier(); + + if (group == WidgetInfo.EQUIPMENT.getGroupId()) + { + final Widget widgetItem = widget.getChild(1); + if (widgetItem != null) + { + itemId = widgetItem.getItemId(); + } + } + else if (group == WidgetInfo.EQUIPMENT_INVENTORY_ITEMS_CONTAINER.getGroupId()) + { + final Widget widgetItem = widget.getChild(entry.getParam0()); + if (widgetItem != null) + { + itemId = widgetItem.getItemId(); + } + } + + if (config.consumableStats()) + { + final Effect change = statChanges.get(itemId); + if (change != null) + { + final StringBuilder b = new StringBuilder(); + final StatsChanges statsChanges = change.calculate(client); + + for (final StatChange c : statsChanges.getStatChanges()) + { + b.append(buildStatChangeString(c)); + } + + final String tooltip = b.toString(); + + if (!tooltip.isEmpty()) + { + tooltipManager.add(new Tooltip(tooltip)); + } + } + } + + if (config.equipmentStats()) + { + final ItemStats stats = itemManager.getItemStats(itemId, false); + + if (stats != null) + { + final String tooltip = buildStatBonusString(stats); + + if (!tooltip.isEmpty()) + { + tooltipManager.add(new Tooltip(tooltip)); + } + } + } + + return null; + } + + private String getChangeString( + final String label, + final double value, + final boolean inverse, + final boolean showPercent) + { + final Color plus = Positivity.getColor(config, Positivity.BETTER_UNCAPPED); + final Color minus = Positivity.getColor(config, Positivity.WORSE); + + if (value == 0) + { + return ""; + } + + final Color color; + + if (inverse) + { + color = value > 0 ? minus : plus; + } + else + { + color = value > 0 ? plus : minus; + } + + final String prefix = value > 0 ? "+" : ""; + final String suffix = showPercent ? "%" : ""; + final String valueString = (int) value == value ? String.valueOf((int) value) : String.valueOf(value); + return label + ": " + ColorUtil.wrapWithColorTag(prefix + valueString + suffix, color) + "
"; + } + + private String buildStatBonusString(ItemStats s) + { + final StringBuilder b = new StringBuilder(); + b.append(getChangeString("Weight", s.getWeight(), true, false)); + + ItemStats other = null; + final ItemEquipmentStats currentEquipment = s.getEquipment(); + + ItemContainer c = client.getItemContainer(InventoryID.EQUIPMENT); + if (s.isEquipable() && currentEquipment != null && c != null) + { + final Item[] items = c.getItems(); + final int slot = currentEquipment.getSlot(); + + if (slot != -1 && slot < items.length) + { + final Item item = items[slot]; + if (item != null) + { + other = itemManager.getItemStats(item.getId(), false); + } + } + + if (other == null && slot == EquipmentInventorySlot.WEAPON.getSlotIdx()) + { + // Unarmed + other = UNARMED; + } + } + + final ItemStats subtracted = s.subtract(other); + final ItemEquipmentStats e = subtracted.getEquipment(); + + if (subtracted.isEquipable() && e != null) + { + b.append(getChangeString("Prayer", e.getPrayer(), false, false)); + b.append(getChangeString("Speed", e.getAspeed(), true, false)); + b.append(getChangeString("Melee Str", e.getStr(), false, false)); + b.append(getChangeString("Range Str", e.getRstr(), false, false)); + b.append(getChangeString("Magic Dmg", e.getMdmg(), false, true)); + + if (e.getAstab() != 0 || e.getAslash() != 0 || e.getAcrush() != 0 || e.getAmagic() != 0 || e.getArange() != 0) + { + b.append(ColorUtil.wrapWithColorTag("Attack Bonus
", JagexColors.MENU_TARGET)); + b.append(getChangeString("Stab", e.getAstab(), false, false)); + b.append(getChangeString("Slash", e.getAslash(), false, false)); + b.append(getChangeString("Crush", e.getAcrush(), false, false)); + b.append(getChangeString("Magic", e.getAmagic(), false, false)); + b.append(getChangeString("Range", e.getArange(), false, false)); + } + + if (e.getDstab() != 0 || e.getDslash() != 0 || e.getDcrush() != 0 || e.getDmagic() != 0 || e.getDrange() != 0) + { + b.append(ColorUtil.wrapWithColorTag("Defence Bonus
", JagexColors.MENU_TARGET)); + b.append(getChangeString("Stab", e.getDstab(), false, false)); + b.append(getChangeString("Slash", e.getDslash(), false, false)); + b.append(getChangeString("Crush", e.getDcrush(), false, false)); + b.append(getChangeString("Magic", e.getDmagic(), false, false)); + b.append(getChangeString("Range", e.getDrange(), false, false)); + } + } + + return b.toString(); + } + + private String buildStatChangeString(StatChange c) + { + StringBuilder b = new StringBuilder(); + b.append(ColorUtil.colorTag(Positivity.getColor(config, c.getPositivity()))); + + if (config.relative()) + { + b.append(c.getFormattedRelative()); + } + + if (config.theoretical()) + { + if (config.relative()) + { + b.append("/"); + } + b.append(c.getFormattedTheoretical()); + } + + if (config.absolute() && (config.relative() || config.theoretical())) + { + b.append(" ("); + } + if (config.absolute()) + { + b.append(c.getAbsolute()); + } + + if (config.absolute() && (config.relative() || config.theoretical())) + { + b.append(")"); + } + b.append(" ").append(c.getStat().getName()); + b.append("
"); + + return b.toString(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java index d8facce32a..d38b28dccc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java @@ -1,437 +1,437 @@ -/* - * Copyright (c) 2018 Abex - * 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.itemstats; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.inject.Binder; -import com.google.inject.Inject; -import com.google.inject.Provides; -import java.awt.FontMetrics; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.runelite.api.Client; -import net.runelite.api.FontID; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemContainer; -import net.runelite.api.ItemID; -import net.runelite.api.SpriteID; -import net.runelite.api.VarPlayer; -import net.runelite.api.Varbits; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.events.VarbitChanged; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.api.widgets.WidgetTextAlignment; -import net.runelite.api.widgets.WidgetType; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.StackFormatter; -import net.runelite.http.api.item.ItemEquipmentStats; -import net.runelite.http.api.item.ItemStats; - -@PluginDescriptor( - name = "Item Stats", - description = "Show information about food and potion effects", - tags = {"food", "inventory", "overlay", "potion"} -) -public class ItemStatPlugin extends Plugin -{ - private static final int ORANGE_TEXT = JagexColors.DARK_ORANGE_INTERFACE_TEXT.getRGB(); - private static final int YELLOW_TEXT = JagexColors.YELLOW_INTERFACE_TEXT.getRGB(); - private static final int TEXT_HEIGHT = 11; - - @Inject - private OverlayManager overlayManager; - - @Inject - private ItemStatOverlay overlay; - - @Inject - private Client client; - - @Inject - private ItemManager itemManager; - - @Inject - private ItemStatConfig config; - - @Inject - private ClientThread clientThread; - - private Widget itemInformationTitle; - - @Provides - ItemStatConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(ItemStatConfig.class); - } - - @Override - public void configure(Binder binder) - { - binder.bind(ItemStatChangesService.class).to(ItemStatChangesServiceImpl.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - clientThread.invokeLater(this::resetGEInventory); - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getKey().equals("geStats")) - { - clientThread.invokeLater(this::resetGEInventory); - } - } - - @Subscribe - public void onGameTick(GameTick event) - { - if (itemInformationTitle != null && config.geStats() - && (client.getWidget(WidgetInfo.GRAND_EXCHANGE_WINDOW_CONTAINER) == null - || client.getWidget(WidgetInfo.GRAND_EXCHANGE_WINDOW_CONTAINER).isHidden())) - { - resetGEInventory(); - } - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - if (client.getVar(VarPlayer.CURRENT_GE_ITEM) == -1 && config.geStats()) - { - resetGEInventory(); - } - } - - @Subscribe - public void onScriptCallbackEvent(ScriptCallbackEvent event) - { - if (event.getEventName().equals("geBuilt") && config.geStats()) - { - int currentGeItem = client.getVar(VarPlayer.CURRENT_GE_ITEM); - if (currentGeItem != -1 && client.getVar(Varbits.GE_OFFER_CREATION_TYPE) == 0) - { - createItemInformation(currentGeItem); - } - } - } - - private void createItemInformation(int id) - { - final ItemStats itemStats = itemManager.getItemStats(id, false); - - if (itemStats == null || !itemStats.isEquipable()) - { - return; - } - - final ItemEquipmentStats equipmentStats = itemStats.getEquipment(); - - if (equipmentStats == null) - { - return; - } - - final Widget geInv = client.getWidget(WidgetInfo.GRAND_EXCHANGE_INVENTORY_ITEMS_CONTAINER); - - if (geInv == null) - { - return; - } - - final Widget invContainer = getInventoryContainer(); - - if (invContainer == null) - { - return; - } - - invContainer.deleteAllChildren(); - geInv.setHidden(true); - - int yPos = 0; - - final FontMetrics smallFM = client.getCanvas().getFontMetrics(FontManager.getRunescapeSmallFont()); - - // HEADER - - itemInformationTitle = createText(invContainer, "Item Information", FontID.BOLD_12, ORANGE_TEXT, - 8, 8, invContainer.getWidth(), 16); - itemInformationTitle.setYTextAlignment(WidgetTextAlignment.CENTER); - - Widget closeButton = invContainer.createChild(-1, WidgetType.GRAPHIC); - closeButton.setOriginalY(8); - closeButton.setOriginalX(invContainer.getWidth() - 24); - closeButton.setOriginalHeight(16); - closeButton.setOriginalWidth(16); - closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); - closeButton.setAction(0, "Close"); - closeButton.setOnMouseOverListener((JavaScriptCallback) (ev) -> - { - closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL_HOVERED); - }); - closeButton.setOnMouseLeaveListener((JavaScriptCallback) (ev) -> - { - closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); - }); - closeButton.setOnOpListener((JavaScriptCallback) (ev) -> resetGEInventory()); - closeButton.setHasListener(true); - closeButton.revalidate(); - - yPos += 15; - - createSeparator(invContainer, yPos); - - // ICON AND TITLE - - yPos += 25; - - Widget icon = invContainer.createChild(-1, WidgetType.GRAPHIC); - icon.setOriginalX(8); - icon.setOriginalY(yPos); - icon.setOriginalWidth(36); - icon.setOriginalHeight(32); - icon.setItemId(id); - icon.setItemQuantityMode(0); - icon.setBorderType(1); - icon.revalidate(); - - Widget itemName = createText(invContainer, itemManager.getItemComposition(id).getName(), FontID.PLAIN_12, ORANGE_TEXT, - 50, yPos, invContainer.getWidth() - 40, 30); - itemName.setYTextAlignment(WidgetTextAlignment.CENTER); - - yPos += 20; - - createSeparator(invContainer, yPos); - - // STATS HEADER - - yPos += 25; - - createText(invContainer, "Attack", FontID.PLAIN_11, ORANGE_TEXT, 5, yPos, 50, -1); - - int defenceXPos = invContainer.getWidth() - (smallFM.stringWidth("Defence") + 5); - createText(invContainer, "Defence", FontID.PLAIN_11, ORANGE_TEXT, defenceXPos, yPos, 50, -1); - - // STYLE BONUSES - - final Set stats = ImmutableSet.of( - "Stab", - "Slash", - "Crush", - "Magic", - "Ranged" - ); - - final List attackStats = ImmutableList.of( - equipmentStats.getAstab(), - equipmentStats.getAslash(), - equipmentStats.getAcrush(), - equipmentStats.getAmagic(), - equipmentStats.getArange() - ); - - final List defenceStats = ImmutableList.of( - equipmentStats.getDstab(), - equipmentStats.getDslash(), - equipmentStats.getDcrush(), - equipmentStats.getDmagic(), - equipmentStats.getDrange() - ); - - int index = 0; - - for (final String stat : stats) - { - yPos += TEXT_HEIGHT + 2; - - // Style label - final Widget styleText = createText(invContainer, stat, FontID.PLAIN_11, ORANGE_TEXT, - 0, yPos, invContainer.getWidth(), -1); - styleText.setXTextAlignment(WidgetTextAlignment.CENTER); - - // Attack bonus - createText(invContainer, attackStats.get(index).toString(), FontID.PLAIN_11, YELLOW_TEXT, - 5, yPos, 50, -1); - - // Defence bonus - final int defenceX = invContainer.getWidth() - (smallFM.stringWidth(defenceStats.get(index).toString()) + 5); - createText(invContainer, defenceStats.get(index).toString(), FontID.PLAIN_11, YELLOW_TEXT, - defenceX, yPos, 50, -1); - - index++; - } - - // MISC BONUSES - - yPos += TEXT_HEIGHT + 8; - - final Map miscStats = ImmutableMap.of( - "Strength", equipmentStats.getStr(), - "Ranged Strength", equipmentStats.getRstr(), - "Magic Damage", equipmentStats.getMdmg(), - "Prayer Bonus", equipmentStats.getPrayer() - ); - - for (final Map.Entry miscStat : miscStats.entrySet()) - { - final String name = miscStat.getKey(); - final String value = miscStat.getValue().toString(); - - // Stat label - createText(invContainer, name, FontID.PLAIN_11, ORANGE_TEXT, 5, yPos, 50, -1); - - // Stat bonus - int valueXPos = invContainer.getWidth() - (smallFM.stringWidth(value) + 5); - createText(invContainer, value, FontID.PLAIN_11, YELLOW_TEXT, valueXPos, yPos, 50, -1); - - yPos += TEXT_HEIGHT + 2; - } - - // COINS - - createSeparator(invContainer, invContainer.getHeight() - 40); - - final String coinText = "You have " + StackFormatter.quantityToRSStackSize(getCurrentGP()) - + (getCurrentGP() == 1 ? " coin." : " coins."); - - final Widget coinWidget = createText(invContainer, coinText, FontID.PLAIN_12, ORANGE_TEXT, - 0, invContainer.getHeight() - 18, invContainer.getWidth(), -1); - - coinWidget.setXTextAlignment(WidgetTextAlignment.CENTER); - } - - private static Widget createText(Widget parent, String text, int fontId, int textColor, - int x, int y, int width, int height) - { - final Widget widget = parent.createChild(-1, WidgetType.TEXT); - widget.setText(text); - widget.setFontId(fontId); - widget.setTextColor(textColor); - widget.setTextShadowed(true); - widget.setOriginalHeight(height == -1 ? TEXT_HEIGHT : height); - widget.setOriginalWidth(width); - widget.setOriginalY(y); - widget.setOriginalX(x); - widget.revalidate(); - return widget; - } - - private static void createSeparator(Widget parent, int y) - { - Widget separator = parent.createChild(-1, WidgetType.GRAPHIC); - separator.setOriginalWidth(parent.getWidth()); - separator.setOriginalY(y); - separator.setOriginalHeight(32); - separator.setSpriteId(SpriteID.UNKNOWN_BORDER_EDGE_HORIZONTAL_995); - separator.revalidate(); - } - - private void resetGEInventory() - { - final Widget invContainer = getInventoryContainer(); - - if (invContainer == null) - { - return; - } - - if (itemInformationTitle != null && invContainer.getChild(0) == itemInformationTitle) - { - invContainer.deleteAllChildren(); - itemInformationTitle = null; - } - - final Widget geInv = client.getWidget(WidgetInfo.GRAND_EXCHANGE_INVENTORY_ITEMS_CONTAINER); - if (geInv != null) - { - geInv.setHidden(false); - } - } - - private int getCurrentGP() - { - final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); - - if (inventory == null) - { - return 0; - } - - for (final Item item : inventory.getItems()) - { - if (item.getId() == ItemID.COINS_995) - { - return item.getQuantity(); - } - } - - return 0; - } - - private Widget getInventoryContainer() - { - if (client.isResized()) - { - if (client.getVar(Varbits.SIDE_PANELS) == 1) - { - return client.getWidget(WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_CONTAINER); - } - else - { - return client.getWidget(WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_CONTAINER); - } - } - else - { - return client.getWidget(WidgetInfo.FIXED_VIEWPORT_INVENTORY_CONTAINER); - } - } -} +/* + * Copyright (c) 2018 Abex + * 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.itemstats; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Binder; +import com.google.inject.Inject; +import com.google.inject.Provides; +import java.awt.FontMetrics; +import java.util.List; +import java.util.Map; +import java.util.Set; +import net.runelite.api.Client; +import net.runelite.api.FontID; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; +import net.runelite.api.SpriteID; +import net.runelite.api.VarPlayer; +import net.runelite.api.Varbits; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.StackFormatter; +import net.runelite.http.api.item.ItemEquipmentStats; +import net.runelite.http.api.item.ItemStats; + +@PluginDescriptor( + name = "Item Stats", + description = "Show information about food and potion effects", + tags = {"food", "inventory", "overlay", "potion"} +) +public class ItemStatPlugin extends Plugin +{ + private static final int ORANGE_TEXT = JagexColors.DARK_ORANGE_INTERFACE_TEXT.getRGB(); + private static final int YELLOW_TEXT = JagexColors.YELLOW_INTERFACE_TEXT.getRGB(); + private static final int TEXT_HEIGHT = 11; + + @Inject + private OverlayManager overlayManager; + + @Inject + private ItemStatOverlay overlay; + + @Inject + private Client client; + + @Inject + private ItemManager itemManager; + + @Inject + private ItemStatConfig config; + + @Inject + private ClientThread clientThread; + + private Widget itemInformationTitle; + + @Provides + ItemStatConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(ItemStatConfig.class); + } + + @Override + public void configure(Binder binder) + { + binder.bind(ItemStatChangesService.class).to(ItemStatChangesServiceImpl.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + clientThread.invokeLater(this::resetGEInventory); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getKey().equals("geStats")) + { + clientThread.invokeLater(this::resetGEInventory); + } + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (itemInformationTitle != null && config.geStats() + && (client.getWidget(WidgetInfo.GRAND_EXCHANGE_WINDOW_CONTAINER) == null + || client.getWidget(WidgetInfo.GRAND_EXCHANGE_WINDOW_CONTAINER).isHidden())) + { + resetGEInventory(); + } + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + if (client.getVar(VarPlayer.CURRENT_GE_ITEM) == -1 && config.geStats()) + { + resetGEInventory(); + } + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent event) + { + if (event.getEventName().equals("geBuilt") && config.geStats()) + { + int currentGeItem = client.getVar(VarPlayer.CURRENT_GE_ITEM); + if (currentGeItem != -1 && client.getVar(Varbits.GE_OFFER_CREATION_TYPE) == 0) + { + createItemInformation(currentGeItem); + } + } + } + + private void createItemInformation(int id) + { + final ItemStats itemStats = itemManager.getItemStats(id, false); + + if (itemStats == null || !itemStats.isEquipable()) + { + return; + } + + final ItemEquipmentStats equipmentStats = itemStats.getEquipment(); + + if (equipmentStats == null) + { + return; + } + + final Widget geInv = client.getWidget(WidgetInfo.GRAND_EXCHANGE_INVENTORY_ITEMS_CONTAINER); + + if (geInv == null) + { + return; + } + + final Widget invContainer = getInventoryContainer(); + + if (invContainer == null) + { + return; + } + + invContainer.deleteAllChildren(); + geInv.setHidden(true); + + int yPos = 0; + + final FontMetrics smallFM = client.getCanvas().getFontMetrics(FontManager.getRunescapeSmallFont()); + + // HEADER + + itemInformationTitle = createText(invContainer, "Item Information", FontID.BOLD_12, ORANGE_TEXT, + 8, 8, invContainer.getWidth(), 16); + itemInformationTitle.setYTextAlignment(WidgetTextAlignment.CENTER); + + Widget closeButton = invContainer.createChild(-1, WidgetType.GRAPHIC); + closeButton.setOriginalY(8); + closeButton.setOriginalX(invContainer.getWidth() - 24); + closeButton.setOriginalHeight(16); + closeButton.setOriginalWidth(16); + closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); + closeButton.setAction(0, "Close"); + closeButton.setOnMouseOverListener((JavaScriptCallback) (ev) -> + { + closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL_HOVERED); + }); + closeButton.setOnMouseLeaveListener((JavaScriptCallback) (ev) -> + { + closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); + }); + closeButton.setOnOpListener((JavaScriptCallback) (ev) -> resetGEInventory()); + closeButton.setHasListener(true); + closeButton.revalidate(); + + yPos += 15; + + createSeparator(invContainer, yPos); + + // ICON AND TITLE + + yPos += 25; + + Widget icon = invContainer.createChild(-1, WidgetType.GRAPHIC); + icon.setOriginalX(8); + icon.setOriginalY(yPos); + icon.setOriginalWidth(36); + icon.setOriginalHeight(32); + icon.setItemId(id); + icon.setItemQuantityMode(0); + icon.setBorderType(1); + icon.revalidate(); + + Widget itemName = createText(invContainer, itemManager.getItemComposition(id).getName(), FontID.PLAIN_12, ORANGE_TEXT, + 50, yPos, invContainer.getWidth() - 40, 30); + itemName.setYTextAlignment(WidgetTextAlignment.CENTER); + + yPos += 20; + + createSeparator(invContainer, yPos); + + // STATS HEADER + + yPos += 25; + + createText(invContainer, "Attack", FontID.PLAIN_11, ORANGE_TEXT, 5, yPos, 50, -1); + + int defenceXPos = invContainer.getWidth() - (smallFM.stringWidth("Defence") + 5); + createText(invContainer, "Defence", FontID.PLAIN_11, ORANGE_TEXT, defenceXPos, yPos, 50, -1); + + // STYLE BONUSES + + final Set stats = ImmutableSet.of( + "Stab", + "Slash", + "Crush", + "Magic", + "Ranged" + ); + + final List attackStats = ImmutableList.of( + equipmentStats.getAstab(), + equipmentStats.getAslash(), + equipmentStats.getAcrush(), + equipmentStats.getAmagic(), + equipmentStats.getArange() + ); + + final List defenceStats = ImmutableList.of( + equipmentStats.getDstab(), + equipmentStats.getDslash(), + equipmentStats.getDcrush(), + equipmentStats.getDmagic(), + equipmentStats.getDrange() + ); + + int index = 0; + + for (final String stat : stats) + { + yPos += TEXT_HEIGHT + 2; + + // Style label + final Widget styleText = createText(invContainer, stat, FontID.PLAIN_11, ORANGE_TEXT, + 0, yPos, invContainer.getWidth(), -1); + styleText.setXTextAlignment(WidgetTextAlignment.CENTER); + + // Attack bonus + createText(invContainer, attackStats.get(index).toString(), FontID.PLAIN_11, YELLOW_TEXT, + 5, yPos, 50, -1); + + // Defence bonus + final int defenceX = invContainer.getWidth() - (smallFM.stringWidth(defenceStats.get(index).toString()) + 5); + createText(invContainer, defenceStats.get(index).toString(), FontID.PLAIN_11, YELLOW_TEXT, + defenceX, yPos, 50, -1); + + index++; + } + + // MISC BONUSES + + yPos += TEXT_HEIGHT + 8; + + final Map miscStats = ImmutableMap.of( + "Strength", equipmentStats.getStr(), + "Ranged Strength", equipmentStats.getRstr(), + "Magic Damage", equipmentStats.getMdmg(), + "Prayer Bonus", equipmentStats.getPrayer() + ); + + for (final Map.Entry miscStat : miscStats.entrySet()) + { + final String name = miscStat.getKey(); + final String value = miscStat.getValue().toString(); + + // Stat label + createText(invContainer, name, FontID.PLAIN_11, ORANGE_TEXT, 5, yPos, 50, -1); + + // Stat bonus + int valueXPos = invContainer.getWidth() - (smallFM.stringWidth(value) + 5); + createText(invContainer, value, FontID.PLAIN_11, YELLOW_TEXT, valueXPos, yPos, 50, -1); + + yPos += TEXT_HEIGHT + 2; + } + + // COINS + + createSeparator(invContainer, invContainer.getHeight() - 40); + + final String coinText = "You have " + StackFormatter.quantityToRSStackSize(getCurrentGP()) + + (getCurrentGP() == 1 ? " coin." : " coins."); + + final Widget coinWidget = createText(invContainer, coinText, FontID.PLAIN_12, ORANGE_TEXT, + 0, invContainer.getHeight() - 18, invContainer.getWidth(), -1); + + coinWidget.setXTextAlignment(WidgetTextAlignment.CENTER); + } + + private static Widget createText(Widget parent, String text, int fontId, int textColor, + int x, int y, int width, int height) + { + final Widget widget = parent.createChild(-1, WidgetType.TEXT); + widget.setText(text); + widget.setFontId(fontId); + widget.setTextColor(textColor); + widget.setTextShadowed(true); + widget.setOriginalHeight(height == -1 ? TEXT_HEIGHT : height); + widget.setOriginalWidth(width); + widget.setOriginalY(y); + widget.setOriginalX(x); + widget.revalidate(); + return widget; + } + + private static void createSeparator(Widget parent, int y) + { + Widget separator = parent.createChild(-1, WidgetType.GRAPHIC); + separator.setOriginalWidth(parent.getWidth()); + separator.setOriginalY(y); + separator.setOriginalHeight(32); + separator.setSpriteId(SpriteID.UNKNOWN_BORDER_EDGE_HORIZONTAL_995); + separator.revalidate(); + } + + private void resetGEInventory() + { + final Widget invContainer = getInventoryContainer(); + + if (invContainer == null) + { + return; + } + + if (itemInformationTitle != null && invContainer.getChild(0) == itemInformationTitle) + { + invContainer.deleteAllChildren(); + itemInformationTitle = null; + } + + final Widget geInv = client.getWidget(WidgetInfo.GRAND_EXCHANGE_INVENTORY_ITEMS_CONTAINER); + if (geInv != null) + { + geInv.setHidden(false); + } + } + + private int getCurrentGP() + { + final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); + + if (inventory == null) + { + return 0; + } + + for (final Item item : inventory.getItems()) + { + if (item.getId() == ItemID.COINS_995) + { + return item.getQuantity(); + } + } + + return 0; + } + + private Widget getInventoryContainer() + { + if (client.isResized()) + { + if (client.getVar(Varbits.SIDE_PANELS) == 1) + { + return client.getWidget(WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_CONTAINER); + } + else + { + return client.getWidget(WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_CONTAINER); + } + } + else + { + return client.getWidget(WidgetInfo.FIXED_VIEWPORT_INVENTORY_CONTAINER); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/SimpleStatBoost.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/SimpleStatBoost.java index 5eef493983..617f930c95 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/SimpleStatBoost.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/SimpleStatBoost.java @@ -1,51 +1,51 @@ -/* - * Copyright (c) 2016-2018, Adam - * 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.itemstats; - -import net.runelite.client.plugins.itemstats.delta.DeltaCalculator; -import net.runelite.client.plugins.itemstats.stats.Stat; -import net.runelite.api.Client; - -/** - * A stat boost using the real stat level. Eg, non-boosted. - */ -public class SimpleStatBoost extends StatBoost -{ - private final DeltaCalculator deltaCalculator; - - public SimpleStatBoost(Stat stat, boolean boost, DeltaCalculator deltaCalculator) - { - super(stat, boost); - this.deltaCalculator = deltaCalculator; - } - - @Override - public int heals(Client client) - { - int max = getStat().getMaximum(client); - return deltaCalculator.calculateDelta(max); - } - -} +/* + * Copyright (c) 2016-2018, Adam + * 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.itemstats; + +import net.runelite.api.Client; +import net.runelite.client.plugins.itemstats.delta.DeltaCalculator; +import net.runelite.client.plugins.itemstats.stats.Stat; + +/** + * A stat boost using the real stat level. Eg, non-boosted. + */ +public class SimpleStatBoost extends StatBoost +{ + private final DeltaCalculator deltaCalculator; + + public SimpleStatBoost(Stat stat, boolean boost, DeltaCalculator deltaCalculator) + { + super(stat, boost); + this.deltaCalculator = deltaCalculator; + } + + @Override + public int heals(Client client) + { + int max = getStat().getMaximum(client); + return deltaCalculator.calculateDelta(max); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java index cc5f7797f2..f6316dac55 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java @@ -1,96 +1,96 @@ -/* - * Copyright (c) 2016-2018, Adam - * 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.itemstats; - -import lombok.Getter; -import lombok.Setter; -import net.runelite.client.plugins.itemstats.stats.Stat; -import net.runelite.api.Client; - -public abstract class StatBoost extends SingleEffect -{ - @Getter - @Setter - private Stat stat; - @Getter - @Setter - private boolean boost; - - public StatBoost(Stat stat, boolean boost) - { - this.stat = stat; - this.boost = boost; - } - - public abstract int heals(Client client); - - @Override - public StatChange effect(Client client) - { - int value = stat.getValue(client); - int max = stat.getMaximum(client); - - boolean hitCap = false; - - int calcedDelta = heals(client); - if (boost && calcedDelta > 0) - { - max += calcedDelta; - } - if (value > max) - { - max = value; - } - int newValue = value + calcedDelta; - if (newValue > max) - { - newValue = max; - hitCap = true; - } - if (newValue < 0) - { - newValue = 0; - } - int delta = newValue - value; - StatChange out = new StatChange(); - out.setStat(stat); - if (delta > 0) - { - out.setPositivity(hitCap ? Positivity.BETTER_CAPPED : Positivity.BETTER_UNCAPPED); - } - else if (delta == 0) - { - out.setPositivity(Positivity.NO_CHANGE); - } - else - { - out.setPositivity(Positivity.WORSE); - } - out.setAbsolute(newValue); - out.setRelative(delta); - out.setTheoretical(calcedDelta); - return out; - } -} +/* + * Copyright (c) 2016-2018, Adam + * 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.itemstats; + +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Client; +import net.runelite.client.plugins.itemstats.stats.Stat; + +public abstract class StatBoost extends SingleEffect +{ + @Getter + @Setter + private Stat stat; + @Getter + @Setter + private boolean boost; + + public StatBoost(Stat stat, boolean boost) + { + this.stat = stat; + this.boost = boost; + } + + public abstract int heals(Client client); + + @Override + public StatChange effect(Client client) + { + int value = stat.getValue(client); + int max = stat.getMaximum(client); + + boolean hitCap = false; + + int calcedDelta = heals(client); + if (boost && calcedDelta > 0) + { + max += calcedDelta; + } + if (value > max) + { + max = value; + } + int newValue = value + calcedDelta; + if (newValue > max) + { + newValue = max; + hitCap = true; + } + if (newValue < 0) + { + newValue = 0; + } + int delta = newValue - value; + StatChange out = new StatChange(); + out.setStat(stat); + if (delta > 0) + { + out.setPositivity(hitCap ? Positivity.BETTER_CAPPED : Positivity.BETTER_UNCAPPED); + } + else if (delta == 0) + { + out.setPositivity(Positivity.NO_CHANGE); + } + else + { + out.setPositivity(Positivity.WORSE); + } + out.setAbsolute(newValue); + out.setRelative(delta); + out.setTheoretical(calcedDelta); + return out; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SaradominBrew.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SaradominBrew.java index 74a13531f2..ea6f4364fe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SaradominBrew.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SaradominBrew.java @@ -1,79 +1,84 @@ -/* - * Copyright (c) 2016-2018, Adam - * 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.itemstats.potions; - -import java.util.Comparator; -import java.util.stream.Stream; -import lombok.RequiredArgsConstructor; -import net.runelite.api.Client; -import static net.runelite.client.plugins.itemstats.Builders.perc; -import net.runelite.client.plugins.itemstats.Effect; -import net.runelite.client.plugins.itemstats.SimpleStatBoost; -import net.runelite.client.plugins.itemstats.BoostedStatBoost; -import net.runelite.client.plugins.itemstats.stats.Stat; -import net.runelite.client.plugins.itemstats.StatChange; -import static net.runelite.client.plugins.itemstats.stats.Stats.*; -import net.runelite.client.plugins.itemstats.StatsChanges; - -@RequiredArgsConstructor -public class SaradominBrew implements Effect -{ - private static final Stat[] saradominBrewStats = new Stat[] - { - ATTACK, STRENGTH, RANGED, MAGIC - }; - - private final double percH; //percentage heal - private final double percD; //percentage defence boost - private final double percSD; //percentage stat drain - private final int deltaB; //delta boosted - private final int deltaR; //delta reduced - - @Override - public StatsChanges calculate(Client client) - { - StatsChanges changes = new StatsChanges(0); - SimpleStatBoost hitpoints = new SimpleStatBoost(HITPOINTS, true, perc(percH, deltaB)); - SimpleStatBoost defence = new SimpleStatBoost(DEFENCE, true, perc(percD, deltaB)); - BoostedStatBoost calc = new BoostedStatBoost(null, false, perc(percSD, -deltaR)); - changes.setStatChanges(Stream.concat( - Stream.of(hitpoints.effect(client)), - Stream.concat( - Stream.of(defence.effect(client)), - Stream.of(saradominBrewStats) - .filter(stat -> 1 < stat.getValue(client)) - .map(stat -> - { - calc.setStat(stat); - return calc.effect(client); - }) - ) - ).toArray(StatChange[]::new)); - changes.setPositivity(Stream.of(changes.getStatChanges()) - .map(sc -> sc.getPositivity()) - .max(Comparator.comparing(Enum::ordinal)).get()); - return changes; - } +/* + * Copyright (c) 2016-2018, Adam + * 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.itemstats.potions; + +import java.util.Comparator; +import java.util.stream.Stream; +import lombok.RequiredArgsConstructor; +import net.runelite.api.Client; +import net.runelite.client.plugins.itemstats.BoostedStatBoost; +import static net.runelite.client.plugins.itemstats.Builders.perc; +import net.runelite.client.plugins.itemstats.Effect; +import net.runelite.client.plugins.itemstats.SimpleStatBoost; +import net.runelite.client.plugins.itemstats.StatChange; +import net.runelite.client.plugins.itemstats.StatsChanges; +import net.runelite.client.plugins.itemstats.stats.Stat; +import static net.runelite.client.plugins.itemstats.stats.Stats.ATTACK; +import static net.runelite.client.plugins.itemstats.stats.Stats.DEFENCE; +import static net.runelite.client.plugins.itemstats.stats.Stats.HITPOINTS; +import static net.runelite.client.plugins.itemstats.stats.Stats.MAGIC; +import static net.runelite.client.plugins.itemstats.stats.Stats.RANGED; +import static net.runelite.client.plugins.itemstats.stats.Stats.STRENGTH; + +@RequiredArgsConstructor +public class SaradominBrew implements Effect +{ + private static final Stat[] saradominBrewStats = new Stat[] + { + ATTACK, STRENGTH, RANGED, MAGIC + }; + + private final double percH; //percentage heal + private final double percD; //percentage defence boost + private final double percSD; //percentage stat drain + private final int deltaB; //delta boosted + private final int deltaR; //delta reduced + + @Override + public StatsChanges calculate(Client client) + { + StatsChanges changes = new StatsChanges(0); + SimpleStatBoost hitpoints = new SimpleStatBoost(HITPOINTS, true, perc(percH, deltaB)); + SimpleStatBoost defence = new SimpleStatBoost(DEFENCE, true, perc(percD, deltaB)); + BoostedStatBoost calc = new BoostedStatBoost(null, false, perc(percSD, -deltaR)); + changes.setStatChanges(Stream.concat( + Stream.of(hitpoints.effect(client)), + Stream.concat( + Stream.of(defence.effect(client)), + Stream.of(saradominBrewStats) + .filter(stat -> 1 < stat.getValue(client)) + .map(stat -> + { + calc.setStat(stat); + return calc.effect(client); + }) + ) + ).toArray(StatChange[]::new)); + changes.setPositivity(Stream.of(changes.getStatChanges()) + .map(sc -> sc.getPositivity()) + .max(Comparator.comparing(Enum::ordinal)).get()); + return changes; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java index b63cd0c2c9..c3e06e2c28 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java @@ -1,74 +1,94 @@ -/* - * Copyright (c) 2016-2018, Adam - * 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.itemstats.potions; - -import java.util.Comparator; -import java.util.stream.Stream; -import lombok.RequiredArgsConstructor; -import net.runelite.api.Client; -import static net.runelite.client.plugins.itemstats.Builders.perc; -import net.runelite.client.plugins.itemstats.Effect; -import net.runelite.client.plugins.itemstats.SimpleStatBoost; -import net.runelite.client.plugins.itemstats.stats.Stat; -import net.runelite.client.plugins.itemstats.StatChange; -import static net.runelite.client.plugins.itemstats.stats.Stats.*; -import net.runelite.client.plugins.itemstats.StatsChanges; - -@RequiredArgsConstructor -public class SuperRestore implements Effect -{ - private static final Stat[] superRestoreStats = new Stat[] - { - ATTACK, DEFENCE, STRENGTH, RANGED, MAGIC, COOKING, - WOODCUTTING, FLETCHING, FISHING, FIREMAKING, CRAFTING, SMITHING, MINING, - HERBLORE, AGILITY, THIEVING, SLAYER, FARMING, RUNECRAFT, HUNTER, - CONSTRUCTION - }; - - private final double percR; //percentage restored - private final int delta; - - @Override - public StatsChanges calculate(Client client) - { - StatsChanges changes = new StatsChanges(0); - - SimpleStatBoost calc = new SimpleStatBoost(null, false, perc(percR, delta)); - PrayerPotion prayer = new PrayerPotion(delta); - changes.setStatChanges(Stream.concat( - Stream.of(prayer.effect(client)), - Stream.of(superRestoreStats) - .filter(stat -> stat.getValue(client) < stat.getMaximum(client)) - .map(stat -> - { - calc.setStat(stat); - return calc.effect(client); - }) - ).toArray(StatChange[]::new)); - changes.setPositivity(Stream.of(changes.getStatChanges()).map(sc -> sc.getPositivity()).max(Comparator.comparing(Enum::ordinal)).get()); - return changes; - } - -} +/* + * Copyright (c) 2016-2018, Adam + * 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.itemstats.potions; + +import java.util.Comparator; +import java.util.stream.Stream; +import lombok.RequiredArgsConstructor; +import net.runelite.api.Client; +import static net.runelite.client.plugins.itemstats.Builders.perc; +import net.runelite.client.plugins.itemstats.Effect; +import net.runelite.client.plugins.itemstats.SimpleStatBoost; +import net.runelite.client.plugins.itemstats.StatChange; +import net.runelite.client.plugins.itemstats.StatsChanges; +import net.runelite.client.plugins.itemstats.stats.Stat; +import static net.runelite.client.plugins.itemstats.stats.Stats.AGILITY; +import static net.runelite.client.plugins.itemstats.stats.Stats.ATTACK; +import static net.runelite.client.plugins.itemstats.stats.Stats.CONSTRUCTION; +import static net.runelite.client.plugins.itemstats.stats.Stats.COOKING; +import static net.runelite.client.plugins.itemstats.stats.Stats.CRAFTING; +import static net.runelite.client.plugins.itemstats.stats.Stats.DEFENCE; +import static net.runelite.client.plugins.itemstats.stats.Stats.FARMING; +import static net.runelite.client.plugins.itemstats.stats.Stats.FIREMAKING; +import static net.runelite.client.plugins.itemstats.stats.Stats.FISHING; +import static net.runelite.client.plugins.itemstats.stats.Stats.FLETCHING; +import static net.runelite.client.plugins.itemstats.stats.Stats.HERBLORE; +import static net.runelite.client.plugins.itemstats.stats.Stats.HUNTER; +import static net.runelite.client.plugins.itemstats.stats.Stats.MAGIC; +import static net.runelite.client.plugins.itemstats.stats.Stats.MINING; +import static net.runelite.client.plugins.itemstats.stats.Stats.RANGED; +import static net.runelite.client.plugins.itemstats.stats.Stats.RUNECRAFT; +import static net.runelite.client.plugins.itemstats.stats.Stats.SLAYER; +import static net.runelite.client.plugins.itemstats.stats.Stats.SMITHING; +import static net.runelite.client.plugins.itemstats.stats.Stats.STRENGTH; +import static net.runelite.client.plugins.itemstats.stats.Stats.THIEVING; +import static net.runelite.client.plugins.itemstats.stats.Stats.WOODCUTTING; + +@RequiredArgsConstructor +public class SuperRestore implements Effect +{ + private static final Stat[] superRestoreStats = new Stat[] + { + ATTACK, DEFENCE, STRENGTH, RANGED, MAGIC, COOKING, + WOODCUTTING, FLETCHING, FISHING, FIREMAKING, CRAFTING, SMITHING, MINING, + HERBLORE, AGILITY, THIEVING, SLAYER, FARMING, RUNECRAFT, HUNTER, + CONSTRUCTION + }; + + private final double percR; //percentage restored + private final int delta; + + @Override + public StatsChanges calculate(Client client) + { + StatsChanges changes = new StatsChanges(0); + + SimpleStatBoost calc = new SimpleStatBoost(null, false, perc(percR, delta)); + PrayerPotion prayer = new PrayerPotion(delta); + changes.setStatChanges(Stream.concat( + Stream.of(prayer.effect(client)), + Stream.of(superRestoreStats) + .filter(stat -> stat.getValue(client) < stat.getMaximum(client)) + .map(stat -> + { + calc.setStat(stat); + return calc.effect(client); + }) + ).toArray(StatChange[]::new)); + changes.setPositivity(Stream.of(changes.getStatChanges()).map(sc -> sc.getPositivity()).max(Comparator.comparing(Enum::ordinal)).get()); + return changes; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/CastleWarsBandage.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/CastleWarsBandage.java index e66f9ed709..ea7f9e0985 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/CastleWarsBandage.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/CastleWarsBandage.java @@ -1,85 +1,85 @@ -/* - * Copyright (c) 2019, Giovds - * 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.itemstats.special; - -import com.google.common.collect.ImmutableSet; -import java.util.Comparator; -import java.util.stream.Stream; -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 static net.runelite.client.plugins.itemstats.Builders.heal; -import static net.runelite.client.plugins.itemstats.Builders.perc; -import net.runelite.client.plugins.itemstats.Effect; -import net.runelite.client.plugins.itemstats.StatChange; -import net.runelite.client.plugins.itemstats.StatsChanges; -import static net.runelite.client.plugins.itemstats.stats.Stats.HITPOINTS; -import static net.runelite.client.plugins.itemstats.stats.Stats.RUN_ENERGY; - -public class CastleWarsBandage implements Effect -{ - private static final ImmutableSet BRACELETS = ImmutableSet.of( - ItemID.CASTLE_WARS_BRACELET1, ItemID.CASTLE_WARS_BRACELET2, ItemID.CASTLE_WARS_BRACELET3 - ); - - private static final double BASE_HP_PERC = .10; - private static final double BRACELET_HP_PERC = .50; - - @Override - public StatsChanges calculate(Client client) - { - final ItemContainer equipmentContainer = client.getItemContainer(InventoryID.EQUIPMENT); - final double percH = hasBracelet(equipmentContainer) ? BRACELET_HP_PERC : BASE_HP_PERC; - final StatChange hitPoints = heal(HITPOINTS, perc(percH, 0)).effect(client); - final StatChange runEnergy = heal(RUN_ENERGY, 30).effect(client); - final StatsChanges changes = new StatsChanges(2); - changes.setStatChanges(new StatChange[]{hitPoints, runEnergy}); - changes.setPositivity(Stream.of(changes.getStatChanges()) - .map(StatChange::getPositivity) - .max(Comparator.comparing(Enum::ordinal)).get()); - - return changes; - } - - private boolean hasBracelet(ItemContainer equipmentContainer) - { - if (equipmentContainer == null) - { - return false; - } - - final Item[] equipment = equipmentContainer.getItems(); - - if (equipment.length > EquipmentInventorySlot.GLOVES.getSlotIdx()) - { - return BRACELETS.contains(equipment[EquipmentInventorySlot.GLOVES.getSlotIdx()].getId()); - } - - return false; - } +/* + * Copyright (c) 2019, Giovds + * 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.itemstats.special; + +import com.google.common.collect.ImmutableSet; +import java.util.Comparator; +import java.util.stream.Stream; +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 static net.runelite.client.plugins.itemstats.Builders.heal; +import static net.runelite.client.plugins.itemstats.Builders.perc; +import net.runelite.client.plugins.itemstats.Effect; +import net.runelite.client.plugins.itemstats.StatChange; +import net.runelite.client.plugins.itemstats.StatsChanges; +import static net.runelite.client.plugins.itemstats.stats.Stats.HITPOINTS; +import static net.runelite.client.plugins.itemstats.stats.Stats.RUN_ENERGY; + +public class CastleWarsBandage implements Effect +{ + private static final ImmutableSet BRACELETS = ImmutableSet.of( + ItemID.CASTLE_WARS_BRACELET1, ItemID.CASTLE_WARS_BRACELET2, ItemID.CASTLE_WARS_BRACELET3 + ); + + private static final double BASE_HP_PERC = .10; + private static final double BRACELET_HP_PERC = .50; + + @Override + public StatsChanges calculate(Client client) + { + final ItemContainer equipmentContainer = client.getItemContainer(InventoryID.EQUIPMENT); + final double percH = hasBracelet(equipmentContainer) ? BRACELET_HP_PERC : BASE_HP_PERC; + final StatChange hitPoints = heal(HITPOINTS, perc(percH, 0)).effect(client); + final StatChange runEnergy = heal(RUN_ENERGY, 30).effect(client); + final StatsChanges changes = new StatsChanges(2); + changes.setStatChanges(new StatChange[]{hitPoints, runEnergy}); + changes.setPositivity(Stream.of(changes.getStatChanges()) + .map(StatChange::getPositivity) + .max(Comparator.comparing(Enum::ordinal)).get()); + + return changes; + } + + private boolean hasBracelet(ItemContainer equipmentContainer) + { + if (equipmentContainer == null) + { + return false; + } + + final Item[] equipment = equipmentContainer.getItems(); + + if (equipment.length > EquipmentInventorySlot.GLOVES.getSlotIdx()) + { + return BRACELETS.contains(equipment[EquipmentInventorySlot.GLOVES.getSlotIdx()].getId()); + } + + return false; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java index 7eee548751..2a10b63489 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java @@ -1,161 +1,165 @@ -/* - * Copyright (c) 2018, Adam - * 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.itemstats.special; - -import java.util.ArrayList; -import java.util.List; -import net.runelite.api.Client; -import net.runelite.api.Varbits; -import net.runelite.client.plugins.itemstats.*; -import net.runelite.client.plugins.itemstats.stats.Stat; -import net.runelite.client.plugins.itemstats.stats.Stats; - -public class SpicyStew implements Effect -{ - - @Override - public StatsChanges calculate(Client client) - { - /* - * Spice boosts listed in the colour order of [Spicy stew -> Smell] - */ - int redBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_RED_SPICES)); - int yellowBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_YELLOW_SPICES)); - int orangeBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_ORANGE_SPICES)); - int brownBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_BROWN_SPICES)); - - List changes = new ArrayList<>(); - - /* - * Red spices: Attack, Strength, Defence, Ranged, Magic - */ - if (redBoost > 0) - { - changes.add(statChangeOf(Stats.ATTACK, redBoost, client)); - changes.add(statChangeOf(Stats.STRENGTH, redBoost, client)); - changes.add(statChangeOf(Stats.DEFENCE, redBoost, client)); - changes.add(statChangeOf(Stats.RANGED, redBoost, client)); - changes.add(statChangeOf(Stats.MAGIC, redBoost, client)); - } - - /* - * Yellow spices: Prayer, Agility, Thieving, Slayer, Hunter - */ - if (yellowBoost > 0) - { - changes.add(statChangeOf(Stats.PRAYER, yellowBoost, client)); - changes.add(statChangeOf(Stats.AGILITY, yellowBoost, client)); - changes.add(statChangeOf(Stats.THIEVING, yellowBoost, client)); - changes.add(statChangeOf(Stats.SLAYER, yellowBoost, client)); - changes.add(statChangeOf(Stats.HUNTER, yellowBoost, client)); - } - - /* - * Orange spices: Smithing, Cooking, Crafting, Firemaking, Fletching, Runecraft, Construction - */ - if (orangeBoost > 0) - { - changes.add(statChangeOf(Stats.SMITHING, orangeBoost, client)); - changes.add(statChangeOf(Stats.COOKING, orangeBoost, client)); - changes.add(statChangeOf(Stats.CRAFTING, orangeBoost, client)); - changes.add(statChangeOf(Stats.FIREMAKING, orangeBoost, client)); - changes.add(statChangeOf(Stats.FLETCHING, orangeBoost, client)); - changes.add(statChangeOf(Stats.RUNECRAFT, orangeBoost, client)); - changes.add(statChangeOf(Stats.CONSTRUCTION, orangeBoost, client)); - } - - /* - * Brown spices: Mining, Herblore, Fishing, Woodcutting, Farming - */ - if (brownBoost > 0) - { - changes.add(statChangeOf(Stats.MINING, brownBoost, client)); - changes.add(statChangeOf(Stats.HERBLORE, brownBoost, client)); - changes.add(statChangeOf(Stats.FISHING, brownBoost, client)); - changes.add(statChangeOf(Stats.WOODCUTTING, brownBoost, client)); - changes.add(statChangeOf(Stats.FARMING, brownBoost, client)); - } - - StatsChanges changesReturn = new StatsChanges(4); - changesReturn.setStatChanges(changes.toArray(new StatChange[changes.size()])); - - return changesReturn; - } - - /** - * Calculate the potential boost that a spice currently offers, - * based on its number of doses in the stew. - * - * @param spiceDoses Number of doses between 0 and 3. - * @return Either 0, +1, +3, or +5. - */ - private static int spiceBoostOf(int spiceDoses) - { - return Math.max(0, (spiceDoses * 2) - 1); - } - - /** - * Calculate the fields of a stat change tooltip row. - * - * @param stat Stat that the spice boost affects. - * @param spiceBoost Potential spice boost before capping. - * @param client Client API, needed to check current stat values. - * @return StatChange object with all required values. - */ - private static StatChange statChangeOf(Stat stat, int spiceBoost, Client client) - { - int currentValue = stat.getValue(client); - int currentBase = stat.getMaximum(client); - - int currentBoost = currentValue - currentBase; // Can be negative - int spiceBoostCapped = (currentBoost <= 0) ? spiceBoost : Math.max(0, spiceBoost - currentBoost); - - final RangeStatChange change = new RangeStatChange(); - change.setStat(stat); - change.setMinRelative(-spiceBoost); - change.setRelative(spiceBoostCapped); - change.setMinTheoretical(-spiceBoost); - change.setTheoretical(spiceBoost); - change.setMinAbsolute(Math.max(-spiceBoost, -currentValue)); - change.setAbsolute(stat.getValue(client) + spiceBoostCapped); - - Positivity positivity; - if (spiceBoostCapped == 0) - { - positivity = Positivity.NO_CHANGE; - } - else if (spiceBoost > spiceBoostCapped) - { - positivity = Positivity.BETTER_CAPPED; - } - else - { - positivity = Positivity.BETTER_UNCAPPED; - } - change.setPositivity(positivity); - - return change; - } -} +/* + * Copyright (c) 2018, Adam + * 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.itemstats.special; + +import java.util.ArrayList; +import java.util.List; +import net.runelite.api.Client; +import net.runelite.api.Varbits; +import net.runelite.client.plugins.itemstats.Effect; +import net.runelite.client.plugins.itemstats.Positivity; +import net.runelite.client.plugins.itemstats.RangeStatChange; +import net.runelite.client.plugins.itemstats.StatChange; +import net.runelite.client.plugins.itemstats.StatsChanges; +import net.runelite.client.plugins.itemstats.stats.Stat; +import net.runelite.client.plugins.itemstats.stats.Stats; + +public class SpicyStew implements Effect +{ + + @Override + public StatsChanges calculate(Client client) + { + /* + * Spice boosts listed in the colour order of [Spicy stew -> Smell] + */ + int redBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_RED_SPICES)); + int yellowBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_YELLOW_SPICES)); + int orangeBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_ORANGE_SPICES)); + int brownBoost = spiceBoostOf(client.getVar(Varbits.SPICY_STEW_BROWN_SPICES)); + + List changes = new ArrayList<>(); + + /* + * Red spices: Attack, Strength, Defence, Ranged, Magic + */ + if (redBoost > 0) + { + changes.add(statChangeOf(Stats.ATTACK, redBoost, client)); + changes.add(statChangeOf(Stats.STRENGTH, redBoost, client)); + changes.add(statChangeOf(Stats.DEFENCE, redBoost, client)); + changes.add(statChangeOf(Stats.RANGED, redBoost, client)); + changes.add(statChangeOf(Stats.MAGIC, redBoost, client)); + } + + /* + * Yellow spices: Prayer, Agility, Thieving, Slayer, Hunter + */ + if (yellowBoost > 0) + { + changes.add(statChangeOf(Stats.PRAYER, yellowBoost, client)); + changes.add(statChangeOf(Stats.AGILITY, yellowBoost, client)); + changes.add(statChangeOf(Stats.THIEVING, yellowBoost, client)); + changes.add(statChangeOf(Stats.SLAYER, yellowBoost, client)); + changes.add(statChangeOf(Stats.HUNTER, yellowBoost, client)); + } + + /* + * Orange spices: Smithing, Cooking, Crafting, Firemaking, Fletching, Runecraft, Construction + */ + if (orangeBoost > 0) + { + changes.add(statChangeOf(Stats.SMITHING, orangeBoost, client)); + changes.add(statChangeOf(Stats.COOKING, orangeBoost, client)); + changes.add(statChangeOf(Stats.CRAFTING, orangeBoost, client)); + changes.add(statChangeOf(Stats.FIREMAKING, orangeBoost, client)); + changes.add(statChangeOf(Stats.FLETCHING, orangeBoost, client)); + changes.add(statChangeOf(Stats.RUNECRAFT, orangeBoost, client)); + changes.add(statChangeOf(Stats.CONSTRUCTION, orangeBoost, client)); + } + + /* + * Brown spices: Mining, Herblore, Fishing, Woodcutting, Farming + */ + if (brownBoost > 0) + { + changes.add(statChangeOf(Stats.MINING, brownBoost, client)); + changes.add(statChangeOf(Stats.HERBLORE, brownBoost, client)); + changes.add(statChangeOf(Stats.FISHING, brownBoost, client)); + changes.add(statChangeOf(Stats.WOODCUTTING, brownBoost, client)); + changes.add(statChangeOf(Stats.FARMING, brownBoost, client)); + } + + StatsChanges changesReturn = new StatsChanges(4); + changesReturn.setStatChanges(changes.toArray(new StatChange[changes.size()])); + + return changesReturn; + } + + /** + * Calculate the potential boost that a spice currently offers, + * based on its number of doses in the stew. + * + * @param spiceDoses Number of doses between 0 and 3. + * @return Either 0, +1, +3, or +5. + */ + private static int spiceBoostOf(int spiceDoses) + { + return Math.max(0, (spiceDoses * 2) - 1); + } + + /** + * Calculate the fields of a stat change tooltip row. + * + * @param stat Stat that the spice boost affects. + * @param spiceBoost Potential spice boost before capping. + * @param client Client API, needed to check current stat values. + * @return StatChange object with all required values. + */ + private static StatChange statChangeOf(Stat stat, int spiceBoost, Client client) + { + int currentValue = stat.getValue(client); + int currentBase = stat.getMaximum(client); + + int currentBoost = currentValue - currentBase; // Can be negative + int spiceBoostCapped = (currentBoost <= 0) ? spiceBoost : Math.max(0, spiceBoost - currentBoost); + + final RangeStatChange change = new RangeStatChange(); + change.setStat(stat); + change.setMinRelative(-spiceBoost); + change.setRelative(spiceBoostCapped); + change.setMinTheoretical(-spiceBoost); + change.setTheoretical(spiceBoost); + change.setMinAbsolute(Math.max(-spiceBoost, -currentValue)); + change.setAbsolute(stat.getValue(client) + spiceBoostCapped); + + Positivity positivity; + if (spiceBoostCapped == 0) + { + positivity = Positivity.NO_CHANGE; + } + else if (spiceBoost > spiceBoostCapped) + { + positivity = Positivity.BETTER_CAPPED; + } + else + { + positivity = Positivity.BETTER_UNCAPPED; + } + change.setPositivity(positivity); + + return change; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java index be7b2ff4d8..a67ab22d58 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java @@ -1,58 +1,59 @@ -/* - * Copyright (c) 2018 Abex - * 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.itemstats.stats; - -import net.runelite.api.Client; -import net.runelite.api.Skill; - -/** - * Abstract stat of a player. - * This includes {@link Skill}s and other player variables, such as RUN_ENERGY. - * @see Stats - */ -public abstract class Stat -{ - private final String name; - - Stat(String name) - { - this.name = name; - } - - public String getName() - { - return name; - } - - /** - * Get the current stat value including any boosts or damage. - */ - public abstract int getValue(Client client); - - /** - * Get the base stat maximum, ie. the bottom half of the stat fraction. - */ - public abstract int getMaximum(Client client); -} +/* + * Copyright (c) 2018 Abex + * 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.itemstats.stats; + +import net.runelite.api.Client; +import net.runelite.api.Skill; + +/** + * Abstract stat of a player. + * This includes {@link Skill}s and other player variables, such as RUN_ENERGY. + * + * @see Stats + */ +public abstract class Stat +{ + private final String name; + + Stat(String name) + { + this.name = name; + } + + public String getName() + { + return name; + } + + /** + * Get the current stat value including any boosts or damage. + */ + public abstract int getValue(Client client); + + /** + * Get the base stat maximum, ie. the bottom half of the stat fraction. + */ + public abstract int getMaximum(Client client); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/ActuallyTradeableItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/ActuallyTradeableItem.java index 8f9dddd40b..91d4ef671c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/ActuallyTradeableItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/ActuallyTradeableItem.java @@ -1,87 +1,221 @@ -/* - * 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.plugins.keptondeath; - -import java.util.HashSet; -import static net.runelite.api.ItemID.*; - -/** - * Certain items aren't tradeable via the GE but can be traded between players. - * The {@link net.runelite.api.ItemComposition}'s `isTradeable` value is based on GE trade-ability so we need - * to account for these items. These items should only be kept if protected based on item value. - */ -public enum ActuallyTradeableItem -{ - // Item Packs - RUNE_PACKS(AIR_RUNE_PACK, WATER_RUNE_PACK, EARTH_RUNE_PACK, FIRE_RUNE_PACK, CHAOS_RUNE_PACK, MIND_RUNE_PACK), - TZHAAR_PACKS(TZHAAR_AIR_RUNE_PACK, TZHAAR_WATER_RUNE_PACK, TZHAAR_EARTH_RUNE_PACK, TZHAAR_FIRE_RUNE_PACK), - OTHER_PACKS(BASKET_PACK, FEATHER_PACK, PLANT_POT_PACK, SACK_PACK, UNFINISHED_BROAD_BOLT_PACK), - // Equipment - BLACK_MASK(BLACK_MASK_1, BLACK_MASK_2, BLACK_MASK_3, BLACK_MASK_4, BLACK_MASK_5, BLACK_MASK_6, BLACK_MASK_7, BLACK_MASK_8, BLACK_MASK_9), - SATCHELS(BLACK_SATCHEL, GOLD_SATCHEL, GREEN_SATCHEL, PLAIN_SATCHEL, RED_SATCHEL, RUNE_SATCHEL), - FIRE_ARROWS(BRONZE_FIRE_ARROWS, IRON_FIRE_ARROWS, STEEL_FIRE_ARROWS, MITHRIL_FIRE_ARROWS, ADAMANT_FIRE_ARROWS, RUNE_FIRE_ARROWS, AMETHYST_FIRE_ARROWS, DRAGON_FIRE_ARROWS), - FIRE_ARROWS_2(BRONZE_FIRE_ARROWS_942, IRON_FIRE_ARROWS_2533, STEEL_FIRE_ARROWS_2535, MITHRIL_FIRE_ARROWS_2537, ADAMANT_FIRE_ARROWS_2539, RUNE_FIRE_ARROWS_2541, AMETHYST_FIRE_ARROWS_21330, DRAGON_FIRE_ARROWS_11222), - // Food Items - HALF_A(HALF_A_GARDEN_PIE, HALF_A_MEAT_PIE, HALF_A_MUSHROOM_PIE, HALF_A_REDBERRY_PIE, HALF_A_BOTANICAL_PIE, HALF_A_FISH_PIE, HALF_A_SUMMER_PIE, HALF_A_WILD_PIE, HALF_AN_ADMIRAL_PIE, HALF_AN_APPLE_PIE), - PIZZA(_12_ANCHOVY_PIZZA, _12_MEAT_PIZZA, _12_PINEAPPLE_PIZZA, _12_PLAIN_PIZZA), - CAKES(CAKE, _23_CAKE, SLICE_OF_CAKE, CHOCOLATE_CAKE, _23_CHOCOLATE_CAKE, CHOCOLATE_SLICE), - BASKETS(APPLES1, APPLES2, APPLES3, APPLES4, BANANAS1, BANANAS2, BANANAS3, BANANAS4, ORANGES1, ORANGES2, ORANGES3, ORANGES4, STRAWBERRIES1, STRAWBERRIES2, STRAWBERRIES3, STRAWBERRIES4, TOMATOES1, TOMATOES2, TOMATOES3, TOMATOES4), - // Charged Jewelery - BURNING_AMULET(BURNING_AMULET1, BURNING_AMULET2, BURNING_AMULET3, BURNING_AMULET4), - NECKLACE_OF_PASSAGE(NECKLACE_OF_PASSAGE1, NECKLACE_OF_PASSAGE2, NECKLACE_OF_PASSAGE3, NECKLACE_OF_PASSAGE4), - RING_OF_DUELING(RING_OF_DUELING1, RING_OF_DUELING2, RING_OF_DUELING3, RING_OF_DUELING4, RING_OF_DUELING5, RING_OF_DUELING6, RING_OF_DUELING7), - GAMES_NECKLACE(GAMES_NECKLACE1, GAMES_NECKLACE2, GAMES_NECKLACE3, GAMES_NECKLACE4, GAMES_NECKLACE5, GAMES_NECKLACE6, GAMES_NECKLACE7), - COMBAT_BRACELET(COMBAT_BRACELET1, COMBAT_BRACELET2, COMBAT_BRACELET3, COMBAT_BRACELET5), - RING_OF_WEALTH(RING_OF_WEALTH_I, RING_OF_WEALTH_1, RING_OF_WEALTH_I1, RING_OF_WEALTH_2, RING_OF_WEALTH_I2, RING_OF_WEALTH_3, RING_OF_WEALTH_I3, RING_OF_WEALTH_4, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5), - AMULET_OF_GLORY(AMULET_OF_GLORY1, AMULET_OF_GLORY2, AMULET_OF_GLORY3, AMULET_OF_GLORY5), - AMULET_OF_GLORY_T(AMULET_OF_GLORY_T1, AMULET_OF_GLORY_T2, AMULET_OF_GLORY_T3, AMULET_OF_GLORY_T5), - SKILLS_NECKLACE(SKILLS_NECKLACE1, SKILLS_NECKLACE2, SKILLS_NECKLACE3, SKILLS_NECKLACE5), - ; - - private final int[] ids; - - private static final HashSet ID_SET; - static - { - ID_SET = new HashSet<>(); - for (ActuallyTradeableItem p : values()) - { - for (int id : p.ids) - { - ID_SET.add(id); - } - } - } - - ActuallyTradeableItem(int... ids) - { - this.ids = ids; - } - - public static Boolean check(int id) - { - return ID_SET.contains(id); - } -} +/* + * 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.plugins.keptondeath; + +import java.util.HashSet; +import static net.runelite.api.ItemID.ADAMANT_FIRE_ARROWS; +import static net.runelite.api.ItemID.ADAMANT_FIRE_ARROWS_2539; +import static net.runelite.api.ItemID.AIR_RUNE_PACK; +import static net.runelite.api.ItemID.AMETHYST_FIRE_ARROWS; +import static net.runelite.api.ItemID.AMETHYST_FIRE_ARROWS_21330; +import static net.runelite.api.ItemID.AMULET_OF_GLORY1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY5; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T5; +import static net.runelite.api.ItemID.APPLES1; +import static net.runelite.api.ItemID.APPLES2; +import static net.runelite.api.ItemID.APPLES3; +import static net.runelite.api.ItemID.APPLES4; +import static net.runelite.api.ItemID.BANANAS1; +import static net.runelite.api.ItemID.BANANAS2; +import static net.runelite.api.ItemID.BANANAS3; +import static net.runelite.api.ItemID.BANANAS4; +import static net.runelite.api.ItemID.BASKET_PACK; +import static net.runelite.api.ItemID.BLACK_MASK_1; +import static net.runelite.api.ItemID.BLACK_MASK_2; +import static net.runelite.api.ItemID.BLACK_MASK_3; +import static net.runelite.api.ItemID.BLACK_MASK_4; +import static net.runelite.api.ItemID.BLACK_MASK_5; +import static net.runelite.api.ItemID.BLACK_MASK_6; +import static net.runelite.api.ItemID.BLACK_MASK_7; +import static net.runelite.api.ItemID.BLACK_MASK_8; +import static net.runelite.api.ItemID.BLACK_MASK_9; +import static net.runelite.api.ItemID.BLACK_SATCHEL; +import static net.runelite.api.ItemID.BRONZE_FIRE_ARROWS; +import static net.runelite.api.ItemID.BRONZE_FIRE_ARROWS_942; +import static net.runelite.api.ItemID.BURNING_AMULET1; +import static net.runelite.api.ItemID.BURNING_AMULET2; +import static net.runelite.api.ItemID.BURNING_AMULET3; +import static net.runelite.api.ItemID.BURNING_AMULET4; +import static net.runelite.api.ItemID.CAKE; +import static net.runelite.api.ItemID.CHAOS_RUNE_PACK; +import static net.runelite.api.ItemID.CHOCOLATE_CAKE; +import static net.runelite.api.ItemID.CHOCOLATE_SLICE; +import static net.runelite.api.ItemID.COMBAT_BRACELET1; +import static net.runelite.api.ItemID.COMBAT_BRACELET2; +import static net.runelite.api.ItemID.COMBAT_BRACELET3; +import static net.runelite.api.ItemID.COMBAT_BRACELET5; +import static net.runelite.api.ItemID.DRAGON_FIRE_ARROWS; +import static net.runelite.api.ItemID.DRAGON_FIRE_ARROWS_11222; +import static net.runelite.api.ItemID.EARTH_RUNE_PACK; +import static net.runelite.api.ItemID.FEATHER_PACK; +import static net.runelite.api.ItemID.FIRE_RUNE_PACK; +import static net.runelite.api.ItemID.GAMES_NECKLACE1; +import static net.runelite.api.ItemID.GAMES_NECKLACE2; +import static net.runelite.api.ItemID.GAMES_NECKLACE3; +import static net.runelite.api.ItemID.GAMES_NECKLACE4; +import static net.runelite.api.ItemID.GAMES_NECKLACE5; +import static net.runelite.api.ItemID.GAMES_NECKLACE6; +import static net.runelite.api.ItemID.GAMES_NECKLACE7; +import static net.runelite.api.ItemID.GOLD_SATCHEL; +import static net.runelite.api.ItemID.GREEN_SATCHEL; +import static net.runelite.api.ItemID.HALF_AN_ADMIRAL_PIE; +import static net.runelite.api.ItemID.HALF_AN_APPLE_PIE; +import static net.runelite.api.ItemID.HALF_A_BOTANICAL_PIE; +import static net.runelite.api.ItemID.HALF_A_FISH_PIE; +import static net.runelite.api.ItemID.HALF_A_GARDEN_PIE; +import static net.runelite.api.ItemID.HALF_A_MEAT_PIE; +import static net.runelite.api.ItemID.HALF_A_MUSHROOM_PIE; +import static net.runelite.api.ItemID.HALF_A_REDBERRY_PIE; +import static net.runelite.api.ItemID.HALF_A_SUMMER_PIE; +import static net.runelite.api.ItemID.HALF_A_WILD_PIE; +import static net.runelite.api.ItemID.IRON_FIRE_ARROWS; +import static net.runelite.api.ItemID.IRON_FIRE_ARROWS_2533; +import static net.runelite.api.ItemID.MIND_RUNE_PACK; +import static net.runelite.api.ItemID.MITHRIL_FIRE_ARROWS; +import static net.runelite.api.ItemID.MITHRIL_FIRE_ARROWS_2537; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE1; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE2; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE3; +import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE4; +import static net.runelite.api.ItemID.ORANGES1; +import static net.runelite.api.ItemID.ORANGES2; +import static net.runelite.api.ItemID.ORANGES3; +import static net.runelite.api.ItemID.ORANGES4; +import static net.runelite.api.ItemID.PLAIN_SATCHEL; +import static net.runelite.api.ItemID.PLANT_POT_PACK; +import static net.runelite.api.ItemID.RED_SATCHEL; +import static net.runelite.api.ItemID.RING_OF_DUELING1; +import static net.runelite.api.ItemID.RING_OF_DUELING2; +import static net.runelite.api.ItemID.RING_OF_DUELING3; +import static net.runelite.api.ItemID.RING_OF_DUELING4; +import static net.runelite.api.ItemID.RING_OF_DUELING5; +import static net.runelite.api.ItemID.RING_OF_DUELING6; +import static net.runelite.api.ItemID.RING_OF_DUELING7; +import static net.runelite.api.ItemID.RING_OF_WEALTH_1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I5; +import static net.runelite.api.ItemID.RUNE_FIRE_ARROWS; +import static net.runelite.api.ItemID.RUNE_FIRE_ARROWS_2541; +import static net.runelite.api.ItemID.RUNE_SATCHEL; +import static net.runelite.api.ItemID.SACK_PACK; +import static net.runelite.api.ItemID.SKILLS_NECKLACE1; +import static net.runelite.api.ItemID.SKILLS_NECKLACE2; +import static net.runelite.api.ItemID.SKILLS_NECKLACE3; +import static net.runelite.api.ItemID.SKILLS_NECKLACE5; +import static net.runelite.api.ItemID.SLICE_OF_CAKE; +import static net.runelite.api.ItemID.STEEL_FIRE_ARROWS; +import static net.runelite.api.ItemID.STEEL_FIRE_ARROWS_2535; +import static net.runelite.api.ItemID.STRAWBERRIES1; +import static net.runelite.api.ItemID.STRAWBERRIES2; +import static net.runelite.api.ItemID.STRAWBERRIES3; +import static net.runelite.api.ItemID.STRAWBERRIES4; +import static net.runelite.api.ItemID.TOMATOES1; +import static net.runelite.api.ItemID.TOMATOES2; +import static net.runelite.api.ItemID.TOMATOES3; +import static net.runelite.api.ItemID.TOMATOES4; +import static net.runelite.api.ItemID.TZHAAR_AIR_RUNE_PACK; +import static net.runelite.api.ItemID.TZHAAR_EARTH_RUNE_PACK; +import static net.runelite.api.ItemID.TZHAAR_FIRE_RUNE_PACK; +import static net.runelite.api.ItemID.TZHAAR_WATER_RUNE_PACK; +import static net.runelite.api.ItemID.UNFINISHED_BROAD_BOLT_PACK; +import static net.runelite.api.ItemID.WATER_RUNE_PACK; +import static net.runelite.api.ItemID._12_ANCHOVY_PIZZA; +import static net.runelite.api.ItemID._12_MEAT_PIZZA; +import static net.runelite.api.ItemID._12_PINEAPPLE_PIZZA; +import static net.runelite.api.ItemID._12_PLAIN_PIZZA; +import static net.runelite.api.ItemID._23_CAKE; +import static net.runelite.api.ItemID._23_CHOCOLATE_CAKE; + +/** + * Certain items aren't tradeable via the GE but can be traded between players. + * The {@link net.runelite.api.ItemComposition}'s `isTradeable` value is based on GE trade-ability so we need + * to account for these items. These items should only be kept if protected based on item value. + */ +public enum ActuallyTradeableItem +{ + // Item Packs + RUNE_PACKS(AIR_RUNE_PACK, WATER_RUNE_PACK, EARTH_RUNE_PACK, FIRE_RUNE_PACK, CHAOS_RUNE_PACK, MIND_RUNE_PACK), + TZHAAR_PACKS(TZHAAR_AIR_RUNE_PACK, TZHAAR_WATER_RUNE_PACK, TZHAAR_EARTH_RUNE_PACK, TZHAAR_FIRE_RUNE_PACK), + OTHER_PACKS(BASKET_PACK, FEATHER_PACK, PLANT_POT_PACK, SACK_PACK, UNFINISHED_BROAD_BOLT_PACK), + // Equipment + BLACK_MASK(BLACK_MASK_1, BLACK_MASK_2, BLACK_MASK_3, BLACK_MASK_4, BLACK_MASK_5, BLACK_MASK_6, BLACK_MASK_7, BLACK_MASK_8, BLACK_MASK_9), + SATCHELS(BLACK_SATCHEL, GOLD_SATCHEL, GREEN_SATCHEL, PLAIN_SATCHEL, RED_SATCHEL, RUNE_SATCHEL), + FIRE_ARROWS(BRONZE_FIRE_ARROWS, IRON_FIRE_ARROWS, STEEL_FIRE_ARROWS, MITHRIL_FIRE_ARROWS, ADAMANT_FIRE_ARROWS, RUNE_FIRE_ARROWS, AMETHYST_FIRE_ARROWS, DRAGON_FIRE_ARROWS), + FIRE_ARROWS_2(BRONZE_FIRE_ARROWS_942, IRON_FIRE_ARROWS_2533, STEEL_FIRE_ARROWS_2535, MITHRIL_FIRE_ARROWS_2537, ADAMANT_FIRE_ARROWS_2539, RUNE_FIRE_ARROWS_2541, AMETHYST_FIRE_ARROWS_21330, DRAGON_FIRE_ARROWS_11222), + // Food Items + HALF_A(HALF_A_GARDEN_PIE, HALF_A_MEAT_PIE, HALF_A_MUSHROOM_PIE, HALF_A_REDBERRY_PIE, HALF_A_BOTANICAL_PIE, HALF_A_FISH_PIE, HALF_A_SUMMER_PIE, HALF_A_WILD_PIE, HALF_AN_ADMIRAL_PIE, HALF_AN_APPLE_PIE), + PIZZA(_12_ANCHOVY_PIZZA, _12_MEAT_PIZZA, _12_PINEAPPLE_PIZZA, _12_PLAIN_PIZZA), + CAKES(CAKE, _23_CAKE, SLICE_OF_CAKE, CHOCOLATE_CAKE, _23_CHOCOLATE_CAKE, CHOCOLATE_SLICE), + BASKETS(APPLES1, APPLES2, APPLES3, APPLES4, BANANAS1, BANANAS2, BANANAS3, BANANAS4, ORANGES1, ORANGES2, ORANGES3, ORANGES4, STRAWBERRIES1, STRAWBERRIES2, STRAWBERRIES3, STRAWBERRIES4, TOMATOES1, TOMATOES2, TOMATOES3, TOMATOES4), + // Charged Jewelery + BURNING_AMULET(BURNING_AMULET1, BURNING_AMULET2, BURNING_AMULET3, BURNING_AMULET4), + NECKLACE_OF_PASSAGE(NECKLACE_OF_PASSAGE1, NECKLACE_OF_PASSAGE2, NECKLACE_OF_PASSAGE3, NECKLACE_OF_PASSAGE4), + RING_OF_DUELING(RING_OF_DUELING1, RING_OF_DUELING2, RING_OF_DUELING3, RING_OF_DUELING4, RING_OF_DUELING5, RING_OF_DUELING6, RING_OF_DUELING7), + GAMES_NECKLACE(GAMES_NECKLACE1, GAMES_NECKLACE2, GAMES_NECKLACE3, GAMES_NECKLACE4, GAMES_NECKLACE5, GAMES_NECKLACE6, GAMES_NECKLACE7), + COMBAT_BRACELET(COMBAT_BRACELET1, COMBAT_BRACELET2, COMBAT_BRACELET3, COMBAT_BRACELET5), + RING_OF_WEALTH(RING_OF_WEALTH_I, RING_OF_WEALTH_1, RING_OF_WEALTH_I1, RING_OF_WEALTH_2, RING_OF_WEALTH_I2, RING_OF_WEALTH_3, RING_OF_WEALTH_I3, RING_OF_WEALTH_4, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5), + AMULET_OF_GLORY(AMULET_OF_GLORY1, AMULET_OF_GLORY2, AMULET_OF_GLORY3, AMULET_OF_GLORY5), + AMULET_OF_GLORY_T(AMULET_OF_GLORY_T1, AMULET_OF_GLORY_T2, AMULET_OF_GLORY_T3, AMULET_OF_GLORY_T5), + SKILLS_NECKLACE(SKILLS_NECKLACE1, SKILLS_NECKLACE2, SKILLS_NECKLACE3, SKILLS_NECKLACE5), + ; + + private final int[] ids; + + private static final HashSet ID_SET; + + static + { + ID_SET = new HashSet<>(); + for (ActuallyTradeableItem p : values()) + { + for (int id : p.ids) + { + ID_SET.add(id); + } + } + } + + ActuallyTradeableItem(int... ids) + { + this.ids = ids; + } + + public static Boolean check(int id) + { + return ID_SET.contains(id); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/AlwaysLostItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/AlwaysLostItem.java index 02a8e26df0..32c5e568fc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/AlwaysLostItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/AlwaysLostItem.java @@ -1,69 +1,70 @@ -/* - * 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.plugins.keptondeath; - -import com.google.common.collect.ImmutableMap; -import lombok.Getter; -import net.runelite.api.ItemID; - -/** - * Certain Items receive a white outline by Jagex as they are always lost on death. This is sometimes incorrectly - * added to Items by Jagex as the item is actually kept in non-pvp areas of the game, such as the Rune Pouch. - * - * The white outline will be added to these items when they are lost on death. - */ -public enum AlwaysLostItem -{ - RUNE_POUCH(ItemID.RUNE_POUCH, true), - LOOTING_BAG(ItemID.LOOTING_BAG, false), - LOOTING_BAG_22586(ItemID.LOOTING_BAG_22586, false), - CLUE_BOX(ItemID.CLUE_BOX, false); - - private final int itemID; - @Getter - private final boolean kept; - - private static final ImmutableMap ID_MAP; - static - { - ImmutableMap.Builder map = ImmutableMap.builder(); - for (AlwaysLostItem p : values()) - { - map.put(p.itemID, p); - } - ID_MAP = map.build(); - } - - AlwaysLostItem(int itemID, boolean kept) - { - this.itemID = itemID; - this.kept = kept; - } - - public static AlwaysLostItem getByItemID(int itemID) - { - return ID_MAP.get(itemID); - } -} +/* + * 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.plugins.keptondeath; + +import com.google.common.collect.ImmutableMap; +import lombok.Getter; +import net.runelite.api.ItemID; + +/** + * Certain Items receive a white outline by Jagex as they are always lost on death. This is sometimes incorrectly + * added to Items by Jagex as the item is actually kept in non-pvp areas of the game, such as the Rune Pouch. + *

+ * The white outline will be added to these items when they are lost on death. + */ +public enum AlwaysLostItem +{ + RUNE_POUCH(ItemID.RUNE_POUCH, true), + LOOTING_BAG(ItemID.LOOTING_BAG, false), + LOOTING_BAG_22586(ItemID.LOOTING_BAG_22586, false), + CLUE_BOX(ItemID.CLUE_BOX, false); + + private final int itemID; + @Getter + private final boolean kept; + + private static final ImmutableMap ID_MAP; + + static + { + ImmutableMap.Builder map = ImmutableMap.builder(); + for (AlwaysLostItem p : values()) + { + map.put(p.itemID, p); + } + ID_MAP = map.build(); + } + + AlwaysLostItem(int itemID, boolean kept) + { + this.itemID = itemID; + this.kept = kept; + } + + public static AlwaysLostItem getByItemID(int itemID) + { + return ID_MAP.get(itemID); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/BrokenOnDeathItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/BrokenOnDeathItem.java index bcb629f89e..fba75bddb2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/BrokenOnDeathItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/BrokenOnDeathItem.java @@ -1,112 +1,113 @@ -/* - * 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.plugins.keptondeath; - -import java.util.HashSet; -import net.runelite.api.ItemID; - -/** - * Some non tradeable items are kept on death inside low level wilderness (1-20) but are turned into a broken variant. - * - * The non-broken variant will be shown inside the interface. - */ -public enum BrokenOnDeathItem -{ - // Capes - FIRE_CAPE(ItemID.FIRE_CAPE), - FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE), - INFERNAL_CAPE(ItemID.INFERNAL_CAPE), - INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE), - AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER), - ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE), - - // Defenders - BRONZE_DEFENDER(ItemID.BRONZE_DEFENDER), - IRON_DEFENDER(ItemID.IRON_DEFENDER), - STEEL_DEFENDER(ItemID.STEEL_DEFENDER), - BLACK_DEFENDER(ItemID.BLACK_DEFENDER), - MITHRIL_DEFENDER(ItemID.MITHRIL_DEFENDER), - ADAMANT_DEFENDER(ItemID.ADAMANT_DEFENDER), - RUNE_DEFENDER(ItemID.RUNE_DEFENDER), - DRAGON_DEFENDER(ItemID.DRAGON_DEFENDER), - AVERNIC_DEFENDER(ItemID.AVERNIC_DEFENDER), - - // Void - VOID_MAGE_HELM(ItemID.VOID_MAGE_HELM), - VOID_RANGER_HELM(ItemID.VOID_RANGER_HELM), - VOID_MELEE_HELM(ItemID.VOID_MELEE_HELM), - VOID_KNIGHT_TOP(ItemID.VOID_KNIGHT_TOP), - VOID_KNIGHT_ROBE(ItemID.VOID_KNIGHT_ROBE), - VOID_KNIGHT_GLOVES(ItemID.VOID_KNIGHT_GLOVES), - VOID_KNIGHT_MACE(ItemID.VOID_KNIGHT_MACE), - ELITE_VOID_TOP(ItemID.ELITE_VOID_TOP), - ELITE_VOID_ROBE(ItemID.ELITE_VOID_ROBE), - - // Barb Assault - FIGHTER_HAT(ItemID.FIGHTER_HAT), - RANGER_HAT(ItemID.RANGER_HAT), - HEALER_HAT(ItemID.HEALER_HAT), - FIGHTER_TORSO(ItemID.FIGHTER_TORSO), - PENANCE_SKIRT(ItemID.PENANCE_SKIRT), - - // Castle Wars - SARADOMIN_HALO(ItemID.SARADOMIN_HALO), - ZAMORAK_HALO(ItemID.ZAMORAK_HALO), - GUTHIX_HALO(ItemID.GUTHIX_HALO), - DECORATIVE_MAGIC_HAT(ItemID.DECORATIVE_ARMOUR_11898), - DECORATIVE_MAGIC_ROBE_TOP(ItemID.DECORATIVE_ARMOUR_11896), - DECORATIVE_MAGIC_ROBE_LEGS(ItemID.DECORATIVE_ARMOUR_11897), - DECORATIVE_RANGE_TOP(ItemID.DECORATIVE_ARMOUR_11899), - DECORATIVE_RANGE_BOTTOM(ItemID.DECORATIVE_ARMOUR_11900), - DECORATIVE_RANGE_QUIVER(ItemID.DECORATIVE_ARMOUR_11901), - GOLD_DECORATIVE_HELM(ItemID.DECORATIVE_HELM_4511), - GOLD_DECORATIVE_BODY(ItemID.DECORATIVE_ARMOUR_4509), - GOLD_DECORATIVE_LEGS(ItemID.DECORATIVE_ARMOUR_4510), - GOLD_DECORATIVE_SKIRT(ItemID.DECORATIVE_ARMOUR_11895), - GOLD_DECORATIVE_SHIELD(ItemID.DECORATIVE_SHIELD_4512), - GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508); - - private final int itemID; - - private static final HashSet ID_SET; - static - { - ID_SET = new HashSet<>(); - for (BrokenOnDeathItem p : values()) - { - ID_SET.add(p.itemID); - } - } - - BrokenOnDeathItem(int itemID) - { - this.itemID = itemID; - } - - public static boolean check(int itemID) - { - return ID_SET.contains(itemID); - } -} +/* + * 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.plugins.keptondeath; + +import java.util.HashSet; +import net.runelite.api.ItemID; + +/** + * Some non tradeable items are kept on death inside low level wilderness (1-20) but are turned into a broken variant. + *

+ * The non-broken variant will be shown inside the interface. + */ +public enum BrokenOnDeathItem +{ + // Capes + FIRE_CAPE(ItemID.FIRE_CAPE), + FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE), + INFERNAL_CAPE(ItemID.INFERNAL_CAPE), + INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE), + AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER), + ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE), + + // Defenders + BRONZE_DEFENDER(ItemID.BRONZE_DEFENDER), + IRON_DEFENDER(ItemID.IRON_DEFENDER), + STEEL_DEFENDER(ItemID.STEEL_DEFENDER), + BLACK_DEFENDER(ItemID.BLACK_DEFENDER), + MITHRIL_DEFENDER(ItemID.MITHRIL_DEFENDER), + ADAMANT_DEFENDER(ItemID.ADAMANT_DEFENDER), + RUNE_DEFENDER(ItemID.RUNE_DEFENDER), + DRAGON_DEFENDER(ItemID.DRAGON_DEFENDER), + AVERNIC_DEFENDER(ItemID.AVERNIC_DEFENDER), + + // Void + VOID_MAGE_HELM(ItemID.VOID_MAGE_HELM), + VOID_RANGER_HELM(ItemID.VOID_RANGER_HELM), + VOID_MELEE_HELM(ItemID.VOID_MELEE_HELM), + VOID_KNIGHT_TOP(ItemID.VOID_KNIGHT_TOP), + VOID_KNIGHT_ROBE(ItemID.VOID_KNIGHT_ROBE), + VOID_KNIGHT_GLOVES(ItemID.VOID_KNIGHT_GLOVES), + VOID_KNIGHT_MACE(ItemID.VOID_KNIGHT_MACE), + ELITE_VOID_TOP(ItemID.ELITE_VOID_TOP), + ELITE_VOID_ROBE(ItemID.ELITE_VOID_ROBE), + + // Barb Assault + FIGHTER_HAT(ItemID.FIGHTER_HAT), + RANGER_HAT(ItemID.RANGER_HAT), + HEALER_HAT(ItemID.HEALER_HAT), + FIGHTER_TORSO(ItemID.FIGHTER_TORSO), + PENANCE_SKIRT(ItemID.PENANCE_SKIRT), + + // Castle Wars + SARADOMIN_HALO(ItemID.SARADOMIN_HALO), + ZAMORAK_HALO(ItemID.ZAMORAK_HALO), + GUTHIX_HALO(ItemID.GUTHIX_HALO), + DECORATIVE_MAGIC_HAT(ItemID.DECORATIVE_ARMOUR_11898), + DECORATIVE_MAGIC_ROBE_TOP(ItemID.DECORATIVE_ARMOUR_11896), + DECORATIVE_MAGIC_ROBE_LEGS(ItemID.DECORATIVE_ARMOUR_11897), + DECORATIVE_RANGE_TOP(ItemID.DECORATIVE_ARMOUR_11899), + DECORATIVE_RANGE_BOTTOM(ItemID.DECORATIVE_ARMOUR_11900), + DECORATIVE_RANGE_QUIVER(ItemID.DECORATIVE_ARMOUR_11901), + GOLD_DECORATIVE_HELM(ItemID.DECORATIVE_HELM_4511), + GOLD_DECORATIVE_BODY(ItemID.DECORATIVE_ARMOUR_4509), + GOLD_DECORATIVE_LEGS(ItemID.DECORATIVE_ARMOUR_4510), + GOLD_DECORATIVE_SKIRT(ItemID.DECORATIVE_ARMOUR_11895), + GOLD_DECORATIVE_SHIELD(ItemID.DECORATIVE_SHIELD_4512), + GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508); + + private final int itemID; + + private static final HashSet ID_SET; + + static + { + ID_SET = new HashSet<>(); + for (BrokenOnDeathItem p : values()) + { + ID_SET.add(p.itemID); + } + } + + BrokenOnDeathItem(int itemID) + { + this.itemID = itemID; + } + + public static boolean check(int itemID) + { + return ID_SET.contains(itemID); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/KeptOnDeathPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/KeptOnDeathPlugin.java index ba38a6b615..0ffb3f0861 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/KeptOnDeathPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/KeptOnDeathPlugin.java @@ -1,598 +1,599 @@ -/* - * 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.plugins.keptondeath; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.LinkedHashMap; -import java.util.List; -import javax.inject.Inject; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.FontID; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemComposition; -import net.runelite.api.ItemContainer; -import net.runelite.api.ItemID; -import net.runelite.api.ScriptID; -import net.runelite.api.SkullIcon; -import net.runelite.api.SpriteID; -import net.runelite.api.Varbits; -import net.runelite.api.WorldType; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.vars.AccountType; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.api.widgets.WidgetType; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemVariationMapping; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; - -@PluginDescriptor( - name = "Kept on Death", - description = "Reworks the Items Kept on Death interface to be more accurate", - enabledByDefault = false, - type = PluginType.UTILITY -) -@Slf4j -public class KeptOnDeathPlugin extends Plugin -{ - // Handles Clicking on items in Kept on Death Interface - private static final int SCRIPT_ID = ScriptID.KEPT_LOST_ITEM_EXAMINE; - private static final double HIGH_ALCH = 0.6; - - // Item Container helpers - private static final int MAX_ROW_ITEMS = 8; - private static final int STARTING_X = 5; - private static final int STARTING_Y = 25; - private static final int X_INCREMENT = 40; - private static final int Y_INCREMENT = 38; - private static final int ORIGINAL_WIDTH = 36; - private static final int ORIGINAL_HEIGHT = 32; - private static final int ORIGINAL_LOST_HEIGHT = 209; - private static final int ORIGINAL_LOST_Y = 107; - - // Information panel text helpers - private static final DecimalFormat NUMBER_FORMAT = new DecimalFormat("#,###"); - private static final String MAX_KEPT_ITEMS_FORMAT = "Max items kept on death :

~ %s ~"; - private static final String ACTION_TEXT = "Item: %s"; - private static final String DEFAULT = "3 items protected by default"; - private static final String IS_SKULLED = "PK skull -3"; - private static final String PROTECTING_ITEM = "Protect Item prayer +1"; - private static final String ACTUAL = "Actually protecting %s items"; - private static final String WHITE_OUTLINE = "Items with a white outline will always be lost."; - private static final String CHANGED_MECHANICS = "Untradeable items are kept on death in non-pvp scenarios."; - private static final String NON_PVP = "You will have 1 hour to retrieve your lost items."; - private static final String LINE_BREAK = "
"; - private static final String UIM_DEFAULT = "You are an UIM which means 0 items are protected by default"; - private static final int ORIGINAL_INFO_HEIGHT = 183; - private static final int FONT_COLOR = 0xFF981F; - - // Button Names and Images - private static final String PROTECT_ITEM_BUTTON_NAME = "Protect Item Prayer"; - private static final String SKULLED_BUTTON_NAME = "Skulled"; - private static final String LOW_WILDY_BUTTON_NAME = "Low Wildy (1-20)"; - private static final String DEEP_WILDY_BUTTON_NAME = "Deep Wildy (21+)"; - private static final int PROTECT_ITEM_SPRITE_ID = SpriteID.PRAYER_PROTECT_ITEM; - private static final int SKULL_SPRITE_ID = SpriteID.PLAYER_KILLER_SKULL_523; - private static final int SWORD_SPRITE_ID = SpriteID.MULTI_COMBAT_ZONE_CROSSED_SWORDS; - private static final int SKULL_2_SPRITE_ID = SpriteID.FIGHT_PITS_WINNER_SKULL_RED; - - @Inject - private Client client; - - @Inject - private ItemManager itemManager; - - @Getter - private boolean widgetVisible = false; - - private LinkedHashMap buttonMap = new LinkedHashMap<>(); - private boolean isSkulled = false; - private boolean protectingItem = false; - private boolean hasAlwaysLost = false; - private int wildyLevel = -1; - - @Subscribe - protected void onScriptCallbackEvent(ScriptCallbackEvent event) - { - if (event.getEventName().equals("deathKeepBuild")) - { - // The script in charge of building the Items Kept on Death interface has finished running. - // Make all necessary changes now. - - // Players inside Safe Areas (POH/Clan Wars) & playing DMM see the default interface - if (isInSafeArea() || client.getWorldType().contains(WorldType.DEADMAN)) - { - return; - } - - syncSettings(); - createWidgetButtons(); - recreateItemsKeptOnDeathWidget(); - } - } - - // Sync user settings - private void syncSettings() - { - SkullIcon s = client.getLocalPlayer().getSkullIcon(); - // Ultimate iron men deaths are treated like they are always skulled - isSkulled = (s != null && s.equals(SkullIcon.SKULL)) || isUltimateIronman(); - protectingItem = client.getVar(Varbits.PRAYER_PROTECT_ITEM) == 1; - syncCurrentWildyLevel(); - } - - private void syncCurrentWildyLevel() - { - if (client.getVar(Varbits.IN_WILDERNESS) != 1) - { - // if they are in a PvP world and not in a safe zone act like in lvl 1 wildy - if (isInPvpWorld() && !isInPvPSafeZone()) - { - wildyLevel = 1; - return; - } - wildyLevel = -1; - return; - } - - int y = client.getLocalPlayer().getWorldLocation().getY(); - - // Credits to atomicint_#5069 (Discord) - int underLevel = ((y - 9920) / 8) + 1; - int upperLevel = ((y - 3520) / 8) + 1; - wildyLevel = (y > 6400 ? underLevel : upperLevel); - } - - private boolean isInPvpWorld() - { - EnumSet world = client.getWorldType(); - return world.contains(WorldType.PVP) || world.contains(WorldType.HIGH_RISK); - } - - private boolean isInPvPSafeZone() - { - Widget w = client.getWidget(WidgetInfo.PVP_WORLD_SAFE_ZONE); - return w != null && !w.isHidden(); - } - - private boolean isInSafeArea() - { - Widget w = client.getWidget(WidgetInfo.ITEMS_KEPT_SAFE_ZONE_CONTAINER); - return w != null && !w.isHidden(); - } - - private boolean isUltimateIronman() - { - return client.getAccountType().equals(AccountType.ULTIMATE_IRONMAN); - } - - private int getDefaultItemsKept() - { - int count = isSkulled ? 0 : 3; - - if (protectingItem) - { - count++; - } - - return count; - } - - private void recreateItemsKeptOnDeathWidget() - { - // Text flags based on items should be reset everytime the widget is recreated - hasAlwaysLost = false; - - Widget lost = client.getWidget(WidgetInfo.ITEMS_LOST_ON_DEATH_CONTAINER); - Widget kept = client.getWidget(WidgetInfo.ITEMS_KEPT_ON_DEATH_CONTAINER); - if (lost != null && kept != null) - { - // Grab all items on player and sort by price. - List items = new ArrayList<>(); - ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); - Item[] inv = inventory == null ? new Item[0] : inventory.getItems(); - ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); - Item[] equip = equipment == null ? new Item[0] : equipment.getItems(); - Collections.addAll(items, inv); - Collections.addAll(items, equip); - // Sort by item price - items.sort((o1, o2) -> - { - int o1ID = ItemVariationMapping.map(itemManager.canonicalize(o1.getId())); - int o2ID = ItemVariationMapping.map(itemManager.canonicalize(o2.getId())); - ItemComposition c1 = itemManager.getItemComposition(o1ID); - ItemComposition c2 = itemManager.getItemComposition(o2ID); - int exchangePrice1 = c1.isTradeable() ? itemManager.getItemPrice(c1.getId()) : c1.getPrice(); - int exchangePrice2 = c2.isTradeable() ? itemManager.getItemPrice(c2.getId()) : c2.getPrice(); - return exchangePrice2 - exchangePrice1; - }); - - int keepCount = getDefaultItemsKept(); - - List keptItems = new ArrayList<>(); - List lostItems = new ArrayList<>(); - for (Item i : items) - { - int id = i.getId(); - if (id == -1) - { - continue; - } - - ItemComposition c = itemManager.getItemComposition(i.getId()); - Widget itemWidget = createItemWidget(i.getQuantity(), c); - - // Bonds are always kept and do not count towards the limit. - if (id == ItemID.OLD_SCHOOL_BOND || id == ItemID.OLD_SCHOOL_BOND_UNTRADEABLE) - { - keptItems.add(itemWidget); - continue; - } - - // Certain items are always lost on death and have a white outline which we need to readd - AlwaysLostItem item = AlwaysLostItem.getByItemID(i.getId()); - if (item != null) - { - // Some of these items are kept on death (outside wildy), like the Rune pouch. Ignore them - if (!item.isKept() || wildyLevel > 0) - { - itemWidget.setOnOpListener(SCRIPT_ID, 0, i.getQuantity(), c.getName()); - itemWidget.setBorderType(2); - lostItems.add(itemWidget); - hasAlwaysLost = true; - continue; - } - } - - // Keep most valuable items regardless of trade-ability. - if (keepCount > 0) - { - if (i.getQuantity() > keepCount) - { - keptItems.add(createItemWidget(keepCount, c)); - itemWidget.setItemQuantity(i.getQuantity() - keepCount); - keepCount = 0; - } - else - { - keptItems.add(itemWidget); - keepCount -= i.getQuantity(); - continue; - } - } - - - if (!checkTradeable(i.getId(), c) && wildyLevel < 21) - { - // Certain items are turned into broken variants inside the wilderness. - if (BrokenOnDeathItem.check(i.getId())) - { - keptItems.add(itemWidget); - continue; - } - - // Ignore all non tradeables in wildy except for the above case(s). - if (wildyLevel > 0) - { - lostItems.add(itemWidget); - continue; - } - - keptItems.add(itemWidget); - } - else - { - itemWidget.setOnOpListener(SCRIPT_ID, 0, i.getQuantity(), c.getName()); - lostItems.add(itemWidget); - } - } - - int rows = keptItems.size() > MAX_ROW_ITEMS ? keptItems.size() / MAX_ROW_ITEMS : 0; - // Adjust items lost container position if new rows were added to kept items container - lost.setOriginalY(ORIGINAL_LOST_Y + (rows * Y_INCREMENT)); - lost.setOriginalHeight(ORIGINAL_LOST_HEIGHT - (rows * Y_INCREMENT)); - setWidgetChildren(kept, keptItems); - setWidgetChildren(lost, lostItems); - - updateKeptWidgetInfoText(); - } - } - - /** - * Wrapper for widget.setChildren() but updates the child index and original positions - * Used for Items Kept and Lost containers - * - * @param parent Widget to override children - * @param widgets Children to set on parent - */ - private void setWidgetChildren(Widget parent, List widgets) - { - Widget[] children = parent.getChildren(); - if (children == null) - { - // Create a child so we can copy the returned Widget[] and avoid hn casting issues from creating a new Widget[] - parent.createChild(0, WidgetType.GRAPHIC); - children = parent.getChildren(); - } - Widget[] itemsArray = Arrays.copyOf(children, widgets.size()); - - int parentId = parent.getId(); - int startingIndex = 0; - for (Widget w : widgets) - { - int originalX = STARTING_X + ((startingIndex % MAX_ROW_ITEMS) * X_INCREMENT); - int originalY = STARTING_Y + ((startingIndex / MAX_ROW_ITEMS) * Y_INCREMENT); - - w.setParentId(parentId); - w.setId(parentId); - w.setIndex(startingIndex); - - w.setOriginalX(originalX); - w.setOriginalY(originalY); - w.revalidate(); - - itemsArray[startingIndex] = w; - startingIndex++; - } - - parent.setChildren(itemsArray); - parent.revalidate(); - } - - /** - * Creates the text to be displayed in the right side of the interface based on current selections - */ - private String getUpdatedInfoText() - { - String textToAdd = DEFAULT; - - if (isUltimateIronman()) - { - textToAdd = UIM_DEFAULT; - } - else - { - if (isSkulled) - { - textToAdd += LINE_BREAK + IS_SKULLED; - } - - if (protectingItem) - { - textToAdd += LINE_BREAK + PROTECTING_ITEM; - } - - textToAdd += LINE_BREAK + String.format(ACTUAL, getDefaultItemsKept()); - } - - - if (wildyLevel < 1) - { - textToAdd += LINE_BREAK + LINE_BREAK + NON_PVP; - } - - if (hasAlwaysLost) - { - textToAdd += LINE_BREAK + LINE_BREAK + WHITE_OUTLINE; - } - - textToAdd += LINE_BREAK + LINE_BREAK + CHANGED_MECHANICS; - - return textToAdd; - } - - /** - * Corrects the Information panel based on the item containers - */ - private void updateKeptWidgetInfoText() - { - // Add Information text widget - createNewTextWidget(); - - // Update Items lost total value - Widget lost = client.getWidget(WidgetInfo.ITEMS_LOST_ON_DEATH_CONTAINER); - double total = 0; - for (Widget w : lost.getChildren()) - { - if (w.getItemId() == -1) - { - continue; - } - double price = itemManager.getItemPrice(w.getItemId()); - if (price == 0) - { - // Default to alch price - price = itemManager.getItemComposition(w.getItemId()).getPrice() * HIGH_ALCH; - } - total += price; - } - Widget lostValue = client.getWidget(WidgetInfo.ITEMS_LOST_VALUE); - lostValue.setText(NUMBER_FORMAT.format(total) + " gp"); - - // Update Max items kept - Widget kept = client.getWidget(WidgetInfo.ITEMS_KEPT_ON_DEATH_CONTAINER); - Widget max = client.getWidget(WidgetInfo.ITEMS_KEPT_MAX); - max.setText(String.format(MAX_KEPT_ITEMS_FORMAT, kept.getChildren().length)); - } - - // isTradeable checks if they are traded on the grand exchange, some items are trade-able but not via GE - private boolean checkTradeable(int id, ItemComposition c) - { - // If the item is a note check the unnoted variants trade ability - if (c.getNote() != -1) - { - return checkTradeable(c.getLinkedNoteId(), itemManager.getItemComposition(c.getLinkedNoteId())); - } - - switch (id) - { - case ItemID.COINS_995: - case ItemID.PLATINUM_TOKEN: - return true; - default: - if (ActuallyTradeableItem.check(id)) - { - return true; - } - } - - return c.isTradeable(); - } - - private void createNewTextWidget() - { - // The text use to be put inside this container but since we can't create LAYER widgets - // We needed to edit this to be a layer for adding buttons - Widget old = client.getWidget(WidgetInfo.ITEMS_KEPT_INFORMATION_CONTAINER); - - // Update the existing TEXT container if it exists. It should be the last child of the old text widget - // client.getWidget() seems to not find indexed child widgets - Widget[] children = old.getChildren(); - if (children != null && children.length > 0) - { - Widget x = old.getChild(children.length - 1); - if (x.getId() == WidgetInfo.ITEMS_KEPT_CUSTOM_TEXT_CONTAINER.getId()) - { - x.setText(getUpdatedInfoText()); - x.revalidate(); - return; - } - } - - Widget w = old.createChild(-1, WidgetType.TEXT); - // Position under buttons taking remaining space - w.setOriginalWidth(old.getOriginalWidth()); - w.setOriginalHeight(ORIGINAL_INFO_HEIGHT - old.getOriginalHeight()); - w.setOriginalY(old.getOriginalHeight()); - - w.setFontId(FontID.PLAIN_11); - w.setTextShadowed(true); - w.setTextColor(FONT_COLOR); - - w.setText(getUpdatedInfoText()); - w.setId(WidgetInfo.ITEMS_KEPT_CUSTOM_TEXT_CONTAINER.getId()); - w.revalidate(); - - // Need to reset height so text is visible? - old.setOriginalHeight(ORIGINAL_INFO_HEIGHT); - old.revalidate(); - } - - private void createWidgetButtons() - { - buttonMap.clear(); - - // Ultimate Iron men are always skulled and can't use the protect item prayer - if (!isUltimateIronman()) - { - createButton(PROTECT_ITEM_BUTTON_NAME, PROTECT_ITEM_SPRITE_ID, protectingItem); - createButton(SKULLED_BUTTON_NAME, SKULL_SPRITE_ID, isSkulled); - } - createButton(LOW_WILDY_BUTTON_NAME, SWORD_SPRITE_ID, wildyLevel > 0 && wildyLevel <= 20); - createButton(DEEP_WILDY_BUTTON_NAME, SKULL_2_SPRITE_ID, wildyLevel > 20); - - Widget parent = client.getWidget(WidgetInfo.ITEMS_KEPT_INFORMATION_CONTAINER); - parent.setType(WidgetType.LAYER); - parent.revalidate(); - WidgetButton.addButtonsToContainerWidget(parent, buttonMap.values()); - } - - private void createButton(String name, int spriteID, boolean startingFlag) - { - WidgetButton button = new WidgetButton(name, spriteID, startingFlag, this::buttonCallback, client); - buttonMap.put(name, button); - } - - private void buttonCallback(String name, boolean selected) - { - log.debug("Clicked Widget Button {}. New value: {}", name, selected); - switch (name) - { - case PROTECT_ITEM_BUTTON_NAME: - protectingItem = selected; - break; - case SKULLED_BUTTON_NAME: - isSkulled = selected; - break; - case LOW_WILDY_BUTTON_NAME: - if (!selected) - { - syncCurrentWildyLevel(); - break; - } - wildyLevel = 1; - buttonMap.get(DEEP_WILDY_BUTTON_NAME).setSelected(false); - break; - case DEEP_WILDY_BUTTON_NAME: - if (!selected) - { - syncCurrentWildyLevel(); - break; - } - wildyLevel = 21; - buttonMap.get(LOW_WILDY_BUTTON_NAME).setSelected(false); - break; - default: - log.warn("Unhandled Button Name: {}", name); - return; - } - - recreateItemsKeptOnDeathWidget(); - } - - /** - * Creates an Item Widget for use inside the Kept on Death Interface - * @param qty Amount of item - * @param c Items Composition - * @return - */ - private Widget createItemWidget(int qty, ItemComposition c) - { - Widget itemWidget = client.createWidget(); - itemWidget.setType(WidgetType.GRAPHIC); - itemWidget.setItemId(c.getId()); - itemWidget.setItemQuantity(qty); - itemWidget.setHasListener(true); - itemWidget.setIsIf3(true); - itemWidget.setOriginalWidth(ORIGINAL_WIDTH); - itemWidget.setOriginalHeight(ORIGINAL_HEIGHT); - itemWidget.setBorderType(1); - - itemWidget.setAction(1, String.format(ACTION_TEXT, c.getName())); - itemWidget.setOnOpListener(SCRIPT_ID, 1, qty, c.getName()); - - return itemWidget; - } +/* + * 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.plugins.keptondeath; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.List; +import javax.inject.Inject; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.FontID; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; +import net.runelite.api.ScriptID; +import net.runelite.api.SkullIcon; +import net.runelite.api.SpriteID; +import net.runelite.api.Varbits; +import net.runelite.api.WorldType; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.vars.AccountType; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemVariationMapping; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; + +@PluginDescriptor( + name = "Kept on Death", + description = "Reworks the Items Kept on Death interface to be more accurate", + enabledByDefault = false, + type = PluginType.UTILITY +) +@Slf4j +public class KeptOnDeathPlugin extends Plugin +{ + // Handles Clicking on items in Kept on Death Interface + private static final int SCRIPT_ID = ScriptID.KEPT_LOST_ITEM_EXAMINE; + private static final double HIGH_ALCH = 0.6; + + // Item Container helpers + private static final int MAX_ROW_ITEMS = 8; + private static final int STARTING_X = 5; + private static final int STARTING_Y = 25; + private static final int X_INCREMENT = 40; + private static final int Y_INCREMENT = 38; + private static final int ORIGINAL_WIDTH = 36; + private static final int ORIGINAL_HEIGHT = 32; + private static final int ORIGINAL_LOST_HEIGHT = 209; + private static final int ORIGINAL_LOST_Y = 107; + + // Information panel text helpers + private static final DecimalFormat NUMBER_FORMAT = new DecimalFormat("#,###"); + private static final String MAX_KEPT_ITEMS_FORMAT = "Max items kept on death :

~ %s ~"; + private static final String ACTION_TEXT = "Item: %s"; + private static final String DEFAULT = "3 items protected by default"; + private static final String IS_SKULLED = "PK skull -3"; + private static final String PROTECTING_ITEM = "Protect Item prayer +1"; + private static final String ACTUAL = "Actually protecting %s items"; + private static final String WHITE_OUTLINE = "Items with a white outline will always be lost."; + private static final String CHANGED_MECHANICS = "Untradeable items are kept on death in non-pvp scenarios."; + private static final String NON_PVP = "You will have 1 hour to retrieve your lost items."; + private static final String LINE_BREAK = "
"; + private static final String UIM_DEFAULT = "You are an UIM which means 0 items are protected by default"; + private static final int ORIGINAL_INFO_HEIGHT = 183; + private static final int FONT_COLOR = 0xFF981F; + + // Button Names and Images + private static final String PROTECT_ITEM_BUTTON_NAME = "Protect Item Prayer"; + private static final String SKULLED_BUTTON_NAME = "Skulled"; + private static final String LOW_WILDY_BUTTON_NAME = "Low Wildy (1-20)"; + private static final String DEEP_WILDY_BUTTON_NAME = "Deep Wildy (21+)"; + private static final int PROTECT_ITEM_SPRITE_ID = SpriteID.PRAYER_PROTECT_ITEM; + private static final int SKULL_SPRITE_ID = SpriteID.PLAYER_KILLER_SKULL_523; + private static final int SWORD_SPRITE_ID = SpriteID.MULTI_COMBAT_ZONE_CROSSED_SWORDS; + private static final int SKULL_2_SPRITE_ID = SpriteID.FIGHT_PITS_WINNER_SKULL_RED; + + @Inject + private Client client; + + @Inject + private ItemManager itemManager; + + @Getter + private boolean widgetVisible = false; + + private LinkedHashMap buttonMap = new LinkedHashMap<>(); + private boolean isSkulled = false; + private boolean protectingItem = false; + private boolean hasAlwaysLost = false; + private int wildyLevel = -1; + + @Subscribe + protected void onScriptCallbackEvent(ScriptCallbackEvent event) + { + if (event.getEventName().equals("deathKeepBuild")) + { + // The script in charge of building the Items Kept on Death interface has finished running. + // Make all necessary changes now. + + // Players inside Safe Areas (POH/Clan Wars) & playing DMM see the default interface + if (isInSafeArea() || client.getWorldType().contains(WorldType.DEADMAN)) + { + return; + } + + syncSettings(); + createWidgetButtons(); + recreateItemsKeptOnDeathWidget(); + } + } + + // Sync user settings + private void syncSettings() + { + SkullIcon s = client.getLocalPlayer().getSkullIcon(); + // Ultimate iron men deaths are treated like they are always skulled + isSkulled = (s != null && s.equals(SkullIcon.SKULL)) || isUltimateIronman(); + protectingItem = client.getVar(Varbits.PRAYER_PROTECT_ITEM) == 1; + syncCurrentWildyLevel(); + } + + private void syncCurrentWildyLevel() + { + if (client.getVar(Varbits.IN_WILDERNESS) != 1) + { + // if they are in a PvP world and not in a safe zone act like in lvl 1 wildy + if (isInPvpWorld() && !isInPvPSafeZone()) + { + wildyLevel = 1; + return; + } + wildyLevel = -1; + return; + } + + int y = client.getLocalPlayer().getWorldLocation().getY(); + + // Credits to atomicint_#5069 (Discord) + int underLevel = ((y - 9920) / 8) + 1; + int upperLevel = ((y - 3520) / 8) + 1; + wildyLevel = (y > 6400 ? underLevel : upperLevel); + } + + private boolean isInPvpWorld() + { + EnumSet world = client.getWorldType(); + return world.contains(WorldType.PVP) || world.contains(WorldType.HIGH_RISK); + } + + private boolean isInPvPSafeZone() + { + Widget w = client.getWidget(WidgetInfo.PVP_WORLD_SAFE_ZONE); + return w != null && !w.isHidden(); + } + + private boolean isInSafeArea() + { + Widget w = client.getWidget(WidgetInfo.ITEMS_KEPT_SAFE_ZONE_CONTAINER); + return w != null && !w.isHidden(); + } + + private boolean isUltimateIronman() + { + return client.getAccountType().equals(AccountType.ULTIMATE_IRONMAN); + } + + private int getDefaultItemsKept() + { + int count = isSkulled ? 0 : 3; + + if (protectingItem) + { + count++; + } + + return count; + } + + private void recreateItemsKeptOnDeathWidget() + { + // Text flags based on items should be reset everytime the widget is recreated + hasAlwaysLost = false; + + Widget lost = client.getWidget(WidgetInfo.ITEMS_LOST_ON_DEATH_CONTAINER); + Widget kept = client.getWidget(WidgetInfo.ITEMS_KEPT_ON_DEATH_CONTAINER); + if (lost != null && kept != null) + { + // Grab all items on player and sort by price. + List items = new ArrayList<>(); + ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); + Item[] inv = inventory == null ? new Item[0] : inventory.getItems(); + ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); + Item[] equip = equipment == null ? new Item[0] : equipment.getItems(); + Collections.addAll(items, inv); + Collections.addAll(items, equip); + // Sort by item price + items.sort((o1, o2) -> + { + int o1ID = ItemVariationMapping.map(itemManager.canonicalize(o1.getId())); + int o2ID = ItemVariationMapping.map(itemManager.canonicalize(o2.getId())); + ItemComposition c1 = itemManager.getItemComposition(o1ID); + ItemComposition c2 = itemManager.getItemComposition(o2ID); + int exchangePrice1 = c1.isTradeable() ? itemManager.getItemPrice(c1.getId()) : c1.getPrice(); + int exchangePrice2 = c2.isTradeable() ? itemManager.getItemPrice(c2.getId()) : c2.getPrice(); + return exchangePrice2 - exchangePrice1; + }); + + int keepCount = getDefaultItemsKept(); + + List keptItems = new ArrayList<>(); + List lostItems = new ArrayList<>(); + for (Item i : items) + { + int id = i.getId(); + if (id == -1) + { + continue; + } + + ItemComposition c = itemManager.getItemComposition(i.getId()); + Widget itemWidget = createItemWidget(i.getQuantity(), c); + + // Bonds are always kept and do not count towards the limit. + if (id == ItemID.OLD_SCHOOL_BOND || id == ItemID.OLD_SCHOOL_BOND_UNTRADEABLE) + { + keptItems.add(itemWidget); + continue; + } + + // Certain items are always lost on death and have a white outline which we need to readd + AlwaysLostItem item = AlwaysLostItem.getByItemID(i.getId()); + if (item != null) + { + // Some of these items are kept on death (outside wildy), like the Rune pouch. Ignore them + if (!item.isKept() || wildyLevel > 0) + { + itemWidget.setOnOpListener(SCRIPT_ID, 0, i.getQuantity(), c.getName()); + itemWidget.setBorderType(2); + lostItems.add(itemWidget); + hasAlwaysLost = true; + continue; + } + } + + // Keep most valuable items regardless of trade-ability. + if (keepCount > 0) + { + if (i.getQuantity() > keepCount) + { + keptItems.add(createItemWidget(keepCount, c)); + itemWidget.setItemQuantity(i.getQuantity() - keepCount); + keepCount = 0; + } + else + { + keptItems.add(itemWidget); + keepCount -= i.getQuantity(); + continue; + } + } + + + if (!checkTradeable(i.getId(), c) && wildyLevel < 21) + { + // Certain items are turned into broken variants inside the wilderness. + if (BrokenOnDeathItem.check(i.getId())) + { + keptItems.add(itemWidget); + continue; + } + + // Ignore all non tradeables in wildy except for the above case(s). + if (wildyLevel > 0) + { + lostItems.add(itemWidget); + continue; + } + + keptItems.add(itemWidget); + } + else + { + itemWidget.setOnOpListener(SCRIPT_ID, 0, i.getQuantity(), c.getName()); + lostItems.add(itemWidget); + } + } + + int rows = keptItems.size() > MAX_ROW_ITEMS ? keptItems.size() / MAX_ROW_ITEMS : 0; + // Adjust items lost container position if new rows were added to kept items container + lost.setOriginalY(ORIGINAL_LOST_Y + (rows * Y_INCREMENT)); + lost.setOriginalHeight(ORIGINAL_LOST_HEIGHT - (rows * Y_INCREMENT)); + setWidgetChildren(kept, keptItems); + setWidgetChildren(lost, lostItems); + + updateKeptWidgetInfoText(); + } + } + + /** + * Wrapper for widget.setChildren() but updates the child index and original positions + * Used for Items Kept and Lost containers + * + * @param parent Widget to override children + * @param widgets Children to set on parent + */ + private void setWidgetChildren(Widget parent, List widgets) + { + Widget[] children = parent.getChildren(); + if (children == null) + { + // Create a child so we can copy the returned Widget[] and avoid hn casting issues from creating a new Widget[] + parent.createChild(0, WidgetType.GRAPHIC); + children = parent.getChildren(); + } + Widget[] itemsArray = Arrays.copyOf(children, widgets.size()); + + int parentId = parent.getId(); + int startingIndex = 0; + for (Widget w : widgets) + { + int originalX = STARTING_X + ((startingIndex % MAX_ROW_ITEMS) * X_INCREMENT); + int originalY = STARTING_Y + ((startingIndex / MAX_ROW_ITEMS) * Y_INCREMENT); + + w.setParentId(parentId); + w.setId(parentId); + w.setIndex(startingIndex); + + w.setOriginalX(originalX); + w.setOriginalY(originalY); + w.revalidate(); + + itemsArray[startingIndex] = w; + startingIndex++; + } + + parent.setChildren(itemsArray); + parent.revalidate(); + } + + /** + * Creates the text to be displayed in the right side of the interface based on current selections + */ + private String getUpdatedInfoText() + { + String textToAdd = DEFAULT; + + if (isUltimateIronman()) + { + textToAdd = UIM_DEFAULT; + } + else + { + if (isSkulled) + { + textToAdd += LINE_BREAK + IS_SKULLED; + } + + if (protectingItem) + { + textToAdd += LINE_BREAK + PROTECTING_ITEM; + } + + textToAdd += LINE_BREAK + String.format(ACTUAL, getDefaultItemsKept()); + } + + + if (wildyLevel < 1) + { + textToAdd += LINE_BREAK + LINE_BREAK + NON_PVP; + } + + if (hasAlwaysLost) + { + textToAdd += LINE_BREAK + LINE_BREAK + WHITE_OUTLINE; + } + + textToAdd += LINE_BREAK + LINE_BREAK + CHANGED_MECHANICS; + + return textToAdd; + } + + /** + * Corrects the Information panel based on the item containers + */ + private void updateKeptWidgetInfoText() + { + // Add Information text widget + createNewTextWidget(); + + // Update Items lost total value + Widget lost = client.getWidget(WidgetInfo.ITEMS_LOST_ON_DEATH_CONTAINER); + double total = 0; + for (Widget w : lost.getChildren()) + { + if (w.getItemId() == -1) + { + continue; + } + double price = itemManager.getItemPrice(w.getItemId()); + if (price == 0) + { + // Default to alch price + price = itemManager.getItemComposition(w.getItemId()).getPrice() * HIGH_ALCH; + } + total += price; + } + Widget lostValue = client.getWidget(WidgetInfo.ITEMS_LOST_VALUE); + lostValue.setText(NUMBER_FORMAT.format(total) + " gp"); + + // Update Max items kept + Widget kept = client.getWidget(WidgetInfo.ITEMS_KEPT_ON_DEATH_CONTAINER); + Widget max = client.getWidget(WidgetInfo.ITEMS_KEPT_MAX); + max.setText(String.format(MAX_KEPT_ITEMS_FORMAT, kept.getChildren().length)); + } + + // isTradeable checks if they are traded on the grand exchange, some items are trade-able but not via GE + private boolean checkTradeable(int id, ItemComposition c) + { + // If the item is a note check the unnoted variants trade ability + if (c.getNote() != -1) + { + return checkTradeable(c.getLinkedNoteId(), itemManager.getItemComposition(c.getLinkedNoteId())); + } + + switch (id) + { + case ItemID.COINS_995: + case ItemID.PLATINUM_TOKEN: + return true; + default: + if (ActuallyTradeableItem.check(id)) + { + return true; + } + } + + return c.isTradeable(); + } + + private void createNewTextWidget() + { + // The text use to be put inside this container but since we can't create LAYER widgets + // We needed to edit this to be a layer for adding buttons + Widget old = client.getWidget(WidgetInfo.ITEMS_KEPT_INFORMATION_CONTAINER); + + // Update the existing TEXT container if it exists. It should be the last child of the old text widget + // client.getWidget() seems to not find indexed child widgets + Widget[] children = old.getChildren(); + if (children != null && children.length > 0) + { + Widget x = old.getChild(children.length - 1); + if (x.getId() == WidgetInfo.ITEMS_KEPT_CUSTOM_TEXT_CONTAINER.getId()) + { + x.setText(getUpdatedInfoText()); + x.revalidate(); + return; + } + } + + Widget w = old.createChild(-1, WidgetType.TEXT); + // Position under buttons taking remaining space + w.setOriginalWidth(old.getOriginalWidth()); + w.setOriginalHeight(ORIGINAL_INFO_HEIGHT - old.getOriginalHeight()); + w.setOriginalY(old.getOriginalHeight()); + + w.setFontId(FontID.PLAIN_11); + w.setTextShadowed(true); + w.setTextColor(FONT_COLOR); + + w.setText(getUpdatedInfoText()); + w.setId(WidgetInfo.ITEMS_KEPT_CUSTOM_TEXT_CONTAINER.getId()); + w.revalidate(); + + // Need to reset height so text is visible? + old.setOriginalHeight(ORIGINAL_INFO_HEIGHT); + old.revalidate(); + } + + private void createWidgetButtons() + { + buttonMap.clear(); + + // Ultimate Iron men are always skulled and can't use the protect item prayer + if (!isUltimateIronman()) + { + createButton(PROTECT_ITEM_BUTTON_NAME, PROTECT_ITEM_SPRITE_ID, protectingItem); + createButton(SKULLED_BUTTON_NAME, SKULL_SPRITE_ID, isSkulled); + } + createButton(LOW_WILDY_BUTTON_NAME, SWORD_SPRITE_ID, wildyLevel > 0 && wildyLevel <= 20); + createButton(DEEP_WILDY_BUTTON_NAME, SKULL_2_SPRITE_ID, wildyLevel > 20); + + Widget parent = client.getWidget(WidgetInfo.ITEMS_KEPT_INFORMATION_CONTAINER); + parent.setType(WidgetType.LAYER); + parent.revalidate(); + WidgetButton.addButtonsToContainerWidget(parent, buttonMap.values()); + } + + private void createButton(String name, int spriteID, boolean startingFlag) + { + WidgetButton button = new WidgetButton(name, spriteID, startingFlag, this::buttonCallback, client); + buttonMap.put(name, button); + } + + private void buttonCallback(String name, boolean selected) + { + log.debug("Clicked Widget Button {}. New value: {}", name, selected); + switch (name) + { + case PROTECT_ITEM_BUTTON_NAME: + protectingItem = selected; + break; + case SKULLED_BUTTON_NAME: + isSkulled = selected; + break; + case LOW_WILDY_BUTTON_NAME: + if (!selected) + { + syncCurrentWildyLevel(); + break; + } + wildyLevel = 1; + buttonMap.get(DEEP_WILDY_BUTTON_NAME).setSelected(false); + break; + case DEEP_WILDY_BUTTON_NAME: + if (!selected) + { + syncCurrentWildyLevel(); + break; + } + wildyLevel = 21; + buttonMap.get(LOW_WILDY_BUTTON_NAME).setSelected(false); + break; + default: + log.warn("Unhandled Button Name: {}", name); + return; + } + + recreateItemsKeptOnDeathWidget(); + } + + /** + * Creates an Item Widget for use inside the Kept on Death Interface + * + * @param qty Amount of item + * @param c Items Composition + * @return + */ + private Widget createItemWidget(int qty, ItemComposition c) + { + Widget itemWidget = client.createWidget(); + itemWidget.setType(WidgetType.GRAPHIC); + itemWidget.setItemId(c.getId()); + itemWidget.setItemQuantity(qty); + itemWidget.setHasListener(true); + itemWidget.setIsIf3(true); + itemWidget.setOriginalWidth(ORIGINAL_WIDTH); + itemWidget.setOriginalHeight(ORIGINAL_HEIGHT); + itemWidget.setBorderType(1); + + itemWidget.setAction(1, String.format(ACTION_TEXT, c.getName())); + itemWidget.setOnOpListener(SCRIPT_ID, 1, qty, c.getName()); + + return itemWidget; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/WidgetButton.java b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/WidgetButton.java index 6385faf8aa..1a13b233a1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/WidgetButton.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keptondeath/WidgetButton.java @@ -1,175 +1,176 @@ -/* - * 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.plugins.keptondeath; - -import java.util.Arrays; -import java.util.Collection; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.SpriteID; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetType; - -@Slf4j -public class WidgetButton -{ - private static final int ICON_HEIGHT = 26; - private static final int ICON_WIDTH = 26; - private static final int BACKGROUND_HEIGHT = 32; - private static final int BACKGROUND_WIDTH = 32; - private static final int PADDING = 5; - private static final int ICON_PADDING = (BACKGROUND_HEIGHT - ICON_HEIGHT) / 2; - - private static final int BACKGROUND_SPRITE_ID = SpriteID.EQUIPMENT_SLOT_TILE; - private static final int SELECTED_BACKGROUND_SPRITE_ID = SpriteID.EQUIPMENT_SLOT_SELECTED; - - public interface WidgetButtonCallback - { - void run(String name, boolean newState); - } - - private String name; - private int spriteID; - @Getter - private Widget icon; - @Getter - private Widget background; - private boolean selected; - private WidgetButtonCallback callback; - - WidgetButton(String name, int spriteID, boolean selectedStartState, WidgetButtonCallback callback, Client client) - { - this.name = name; - this.spriteID = spriteID; - this.selected = selectedStartState; - this.callback = callback; - createBackgroundWidget(client); - createIconWidget(client); - } - - private void createBackgroundWidget(Client client) - { - background = createWidget(client); - background.setOriginalWidth(BACKGROUND_WIDTH); - background.setOriginalHeight(BACKGROUND_HEIGHT); - syncBackgroundSprite(); - } - - private void createIconWidget(Client client) - { - icon = createWidget(client); - icon.setAction(1, "Toggle:"); - icon.setOnOpListener((JavaScriptCallback) ev -> onButtonClicked()); - icon.setHasListener(true); - icon.setSpriteId(spriteID); - } - - private Widget createWidget(Client client) - { - Widget w = client.createWidget(); - w.setType(WidgetType.GRAPHIC); - w.setOriginalWidth(ICON_WIDTH); - w.setOriginalHeight(ICON_HEIGHT); - w.setName("" + this.name); - w.setIsIf3(true); - return w; - } - - public void setSelected(boolean selected) - { - this.selected = selected; - syncBackgroundSprite(); - } - - private void syncBackgroundSprite() - { - background.setSpriteId(selected ? SELECTED_BACKGROUND_SPRITE_ID : BACKGROUND_SPRITE_ID); - } - - /** - * Adds the collection of WidgetButtons to the container overriding any existing children. - * @param container Widget to add buttons too - * @param buttons buttons to add - */ - static void addButtonsToContainerWidget(Widget container, Collection buttons) - { - Widget[] children = container.getChildren(); - if (children == null) - { - // Create a child so we can copy the returned Widget[] and avoid hn casting issues from creating a new Widget[] - container.createChild(0, WidgetType.GRAPHIC); - children = container.getChildren(); - } - // Each button has two widgets, Icon and Background - Widget[] itemsArray = Arrays.copyOf(children, buttons.size() * 2); - int parentId = container.getId(); - - int xIncrement = BACKGROUND_WIDTH + PADDING; - int yIncrement = BACKGROUND_HEIGHT + PADDING; - int maxRowItems = container.getWidth() / xIncrement; - // Ensure at least 1 button per row - maxRowItems = maxRowItems < 1 ? 1 : maxRowItems; - - int startingIndex = 0; - for (WidgetButton w : buttons) - { - int originalX = (((startingIndex / 2) % maxRowItems) * xIncrement); - int originalY = (((startingIndex / 2) / maxRowItems) * yIncrement); - Widget background = updateWidgetPosition(w.getBackground(), parentId, startingIndex, originalX, originalY); - itemsArray[startingIndex] = background; - startingIndex++; - // Icon must be padded to center inside image - Widget icon = updateWidgetPosition(w.getIcon(), parentId, startingIndex, originalX + ICON_PADDING, originalY + ICON_PADDING); - itemsArray[startingIndex] = icon; - startingIndex++; - } - - int rows = 1 + (buttons.size() > maxRowItems ? buttons.size() / maxRowItems : 0); - container.setOriginalHeight(yIncrement * rows); - container.setChildren(itemsArray); - container.revalidate(); - } - - private static Widget updateWidgetPosition(Widget w, int id, int index, int originalX, int originalY) - { - w.setParentId(id); - w.setId(id); - w.setIndex(index); - - w.setOriginalX(originalX); - w.setOriginalY(originalY); - w.revalidate(); - - return w; - } - - private void onButtonClicked() - { - setSelected(!selected); - callback.run(name, selected); - } -} +/* + * 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.plugins.keptondeath; + +import java.util.Arrays; +import java.util.Collection; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.SpriteID; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetType; + +@Slf4j +public class WidgetButton +{ + private static final int ICON_HEIGHT = 26; + private static final int ICON_WIDTH = 26; + private static final int BACKGROUND_HEIGHT = 32; + private static final int BACKGROUND_WIDTH = 32; + private static final int PADDING = 5; + private static final int ICON_PADDING = (BACKGROUND_HEIGHT - ICON_HEIGHT) / 2; + + private static final int BACKGROUND_SPRITE_ID = SpriteID.EQUIPMENT_SLOT_TILE; + private static final int SELECTED_BACKGROUND_SPRITE_ID = SpriteID.EQUIPMENT_SLOT_SELECTED; + + public interface WidgetButtonCallback + { + void run(String name, boolean newState); + } + + private String name; + private int spriteID; + @Getter + private Widget icon; + @Getter + private Widget background; + private boolean selected; + private WidgetButtonCallback callback; + + WidgetButton(String name, int spriteID, boolean selectedStartState, WidgetButtonCallback callback, Client client) + { + this.name = name; + this.spriteID = spriteID; + this.selected = selectedStartState; + this.callback = callback; + createBackgroundWidget(client); + createIconWidget(client); + } + + private void createBackgroundWidget(Client client) + { + background = createWidget(client); + background.setOriginalWidth(BACKGROUND_WIDTH); + background.setOriginalHeight(BACKGROUND_HEIGHT); + syncBackgroundSprite(); + } + + private void createIconWidget(Client client) + { + icon = createWidget(client); + icon.setAction(1, "Toggle:"); + icon.setOnOpListener((JavaScriptCallback) ev -> onButtonClicked()); + icon.setHasListener(true); + icon.setSpriteId(spriteID); + } + + private Widget createWidget(Client client) + { + Widget w = client.createWidget(); + w.setType(WidgetType.GRAPHIC); + w.setOriginalWidth(ICON_WIDTH); + w.setOriginalHeight(ICON_HEIGHT); + w.setName("" + this.name); + w.setIsIf3(true); + return w; + } + + public void setSelected(boolean selected) + { + this.selected = selected; + syncBackgroundSprite(); + } + + private void syncBackgroundSprite() + { + background.setSpriteId(selected ? SELECTED_BACKGROUND_SPRITE_ID : BACKGROUND_SPRITE_ID); + } + + /** + * Adds the collection of WidgetButtons to the container overriding any existing children. + * + * @param container Widget to add buttons too + * @param buttons buttons to add + */ + static void addButtonsToContainerWidget(Widget container, Collection buttons) + { + Widget[] children = container.getChildren(); + if (children == null) + { + // Create a child so we can copy the returned Widget[] and avoid hn casting issues from creating a new Widget[] + container.createChild(0, WidgetType.GRAPHIC); + children = container.getChildren(); + } + // Each button has two widgets, Icon and Background + Widget[] itemsArray = Arrays.copyOf(children, buttons.size() * 2); + int parentId = container.getId(); + + int xIncrement = BACKGROUND_WIDTH + PADDING; + int yIncrement = BACKGROUND_HEIGHT + PADDING; + int maxRowItems = container.getWidth() / xIncrement; + // Ensure at least 1 button per row + maxRowItems = maxRowItems < 1 ? 1 : maxRowItems; + + int startingIndex = 0; + for (WidgetButton w : buttons) + { + int originalX = (((startingIndex / 2) % maxRowItems) * xIncrement); + int originalY = (((startingIndex / 2) / maxRowItems) * yIncrement); + Widget background = updateWidgetPosition(w.getBackground(), parentId, startingIndex, originalX, originalY); + itemsArray[startingIndex] = background; + startingIndex++; + // Icon must be padded to center inside image + Widget icon = updateWidgetPosition(w.getIcon(), parentId, startingIndex, originalX + ICON_PADDING, originalY + ICON_PADDING); + itemsArray[startingIndex] = icon; + startingIndex++; + } + + int rows = 1 + (buttons.size() > maxRowItems ? buttons.size() / maxRowItems : 0); + container.setOriginalHeight(yIncrement * rows); + container.setChildren(itemsArray); + container.revalidate(); + } + + private static Widget updateWidgetPosition(Widget w, int id, int index, int originalX, int originalY) + { + w.setParentId(id); + w.setId(id); + w.setIndex(index); + + w.setOriginalX(originalX); + w.setOriginalY(originalY); + w.revalidate(); + + return w; + } + + private void onButtonClicked() + { + setSelected(!selected); + callback.run(name, selected); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java index 02618031db..79bd7f4889 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/Library.java @@ -1,800 +1,824 @@ -/* - * Copyright (c) 2018 Abex - * 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.kourendlibrary; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.stream.IntStream; -import javax.inject.Singleton; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.coords.WorldPoint; - -import static net.runelite.client.plugins.kourendlibrary.Book.*; - -/** - * Library represents a instance of the Kourend/Arceuus House library. - *

- * The library changes the locations of it's books every 60-90 minutes. - * Of the 554 bookcases in the library, only 346 of them can ever have books. - * 6 of the bookcases in the south-west corner of the top floor are duplicated. - * These 6 bookcases are not handled 100% correctly due to their low chance - * of being used to train the predictor. - *

- * Each of the 352 bookcase slots "Bookcase"s has an index which is used to - * place the book inside of them. The game chooses one of the 5 sequences and a - * bookcase starting index, then places a book from the sequence into every 13th - * bookcase, by index. Each sequence contains 26 Books, consisting of 16 books - * and 10 dark manuscripts. You can only get one dark manuscript at a time, though - * they are all placed into shelves. - */ -@Singleton -@Slf4j -class Library -{ - private final Map byPoint = new HashMap<>(); - private final Map> byLevel = new HashMap<>(); - private final List byIndex = new ArrayList<>(); - - private final List> sequences = populateSequences(); - - private final int step; - - @Getter - private SolvedState state; - - @Getter - private Book customerBook; - - @Getter - private LibraryCustomer customer; - - Library() - { - populateBooks(); - step = byIndex.size() / Book.values().length; - reset(); - } - - synchronized List getBookcasesOnLevel(int z) - { - return Collections.unmodifiableList(byLevel.get(z)); - } - - synchronized List getBookcases() - { - return Collections.unmodifiableList(byIndex); - } - - void setCustomer(LibraryCustomer customer, Book book) - { - this.customer = customer; - this.customerBook = book; - } - - synchronized void reset() - { - state = SolvedState.NO_DATA; - for (Bookcase b : byIndex) - { - b.clearBook(); - b.getPossibleBooks().clear(); - } - log.info("Library is now reset"); - } - - synchronized void mark(WorldPoint loc, Book book) - { - Bookcase bookcase = byPoint.get(loc); - if (bookcase == null) - { - log.debug("Requested non-existent bookcase at {}", loc); - return; - } - - if (bookcase.isBookSet()) - { - // Bookcase is set from a previous mark - // Check for a mismatch, unless it is now null and had a dark manuscript - if (book != bookcase.getBook() && !(book == null && bookcase.getBook().isDarkManuscript())) - { - reset(); - } - } - else if (state != SolvedState.NO_DATA) - { - // We know all of the possible things in this shelf. - if (book != null) - { - // Check to see if our guess is wrong - if (!bookcase.getPossibleBooks().contains(book)) - { - reset(); - } - } - } - - // Everything is known, nothing to do - if (state == SolvedState.COMPLETE) - { - return; - } - - log.info("Setting bookcase {} to {}", bookcase.getIndex(), book); - for (; ; ) - { - bookcase.setBook(book); - - // Basing the sequences on null is not supported, though possible - if (book == null) - { - return; - } - - // This is one of the 6 bookcases with 2 ids. Not fully supported. - if (bookcase.getIndex().size() != 1) - { - return; - } - - int bookcaseIndex = bookcase.getIndex().get(0); - - state = SolvedState.INCOMPLETE; - - // Map each sequence to the number of bookcases that match the sequence - // return 0 if it is a mismatch. - // Keep in mind that Bookcases with dark manuscripts may be set to null. - int[] certainty = sequences.stream().mapToInt(sequence -> - { - int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book); - - int found = 0; - for (int i = 0; i < byIndex.size(); i++) - { - int ai = (i + zero) % byIndex.size(); - Bookcase iBookcase = byIndex.get(ai); - if (i % step == 0) - { - int seqI = i / step; - if (iBookcase.isBookSet() && seqI < sequence.size()) - { - Book seqBook = sequence.get(seqI); - boolean isSeqManuscript = seqBook == null || seqBook.isDarkManuscript(); - if (!((isSeqManuscript && iBookcase.getBook() == null) || (iBookcase.getBook() == seqBook))) - { - log.debug("Bailing @ i={} ai={} {}; {} != {}", i, ai, iBookcase.getIndex(), iBookcase.getBook(), seqBook); - found = 0; - break; - } - found++; - } - } - else - { - // Only bail if this isn't a double bookcase - if (iBookcase.isBookSet() && iBookcase.getBook() != null && iBookcase.getIndex().size() == 1) - { - log.debug("Bailing @ i={} ai={} {}; {} is set", i, ai, iBookcase.getIndex(), iBookcase.getBook()); - found = 0; - break; - } - } - } - return found; - }).toArray(); - log.info("Certainty is now {}", certainty); - - for (Bookcase b : byIndex) - { - b.getPossibleBooks().clear(); - } - - // Write the most likely sequences onto the bookcases - int max = IntStream.of(certainty).max().getAsInt(); - - // We have books set, but 0 sequences match, Something is wrong, reset. - if (max == 0) - { - reset(); - continue; - } - - IntStream.range(0, sequences.size()) - .filter(i -> certainty[i] == max) - .forEach(isequence -> - { - List sequence = sequences.get(isequence); - int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book); - - for (int i = 0; i < byIndex.size(); i++) - { - int ai = (i + zero) % byIndex.size(); - Bookcase iBookcase = byIndex.get(ai); - if (iBookcase.getBook() == null) - { - int iseq = i / step; - if (i % step == 0 && iseq < sequence.size()) - { - Book seqBook = sequence.get(iseq); - iBookcase.getPossibleBooks().add(seqBook); - } - } - } - }); - if (IntStream.range(0, certainty.length).filter(i -> certainty[i] == max).count() == 1) - { - state = SolvedState.COMPLETE; - } - return; - } - } - - /** - * Find the bookcase index that is index zero in the sequence, identifying by the book in bookcase - */ - private int getBookcaseZeroIndexForSequenceWithBook(List sequences, int bookcaseIndex, Book book) - { - int bookSequence = sequences.indexOf(book); - assert bookSequence >= 0; - - bookcaseIndex -= step * bookSequence; - for (; bookcaseIndex < 0; ) - { - bookcaseIndex += byIndex.size(); - } - return bookcaseIndex; - } - - private List> populateSequences() - { - List> books = Arrays.asList( - Arrays.asList( - DARK_MANUSCRIPT_13516, - KILLING_OF_A_KING, - DARK_MANUSCRIPT_13520, - IDEOLOGY_OF_DARKNESS, - RADAS_JOURNEY, - TRANSVERGENCE_THEORY, - TRISTESSAS_TRAGEDY, - DARK_MANUSCRIPT_13523, - DARK_MANUSCRIPT_13521, - RADAS_CENSUS, - TREACHERY_OF_ROYALTY, - HOSIDIUS_LETTER, - DARK_MANUSCRIPT_13519, - RICKTORS_DIARY_7, - DARK_MANUSCRIPT_13514, - EATHRAM_RADA_EXTRACT, - DARK_MANUSCRIPT_13522, - VARLAMORE_ENVOY, - WINTERTODT_PARABLE, - TWILL_ACCORD, - DARK_MANUSCRIPT_13515, - BYRNES_CORONATION_SPEECH, - DARK_MANUSCRIPT_13517, - SOUL_JOURNEY, - DARK_MANUSCRIPT_13518, - TRANSPORTATION_INCANTATIONS - ), - Arrays.asList( - DARK_MANUSCRIPT_13516, - KILLING_OF_A_KING, - DARK_MANUSCRIPT_13520, - IDEOLOGY_OF_DARKNESS, - RADAS_JOURNEY, - TRANSVERGENCE_THEORY, - TRISTESSAS_TRAGEDY, - DARK_MANUSCRIPT_13523, - DARK_MANUSCRIPT_13521, - RADAS_CENSUS, - TREACHERY_OF_ROYALTY, - HOSIDIUS_LETTER, - VARLAMORE_ENVOY, - DARK_MANUSCRIPT_13519, - RICKTORS_DIARY_7, - DARK_MANUSCRIPT_13514, - EATHRAM_RADA_EXTRACT, - DARK_MANUSCRIPT_13522, - SOUL_JOURNEY, - WINTERTODT_PARABLE, - TWILL_ACCORD, - DARK_MANUSCRIPT_13515, - BYRNES_CORONATION_SPEECH, - DARK_MANUSCRIPT_13517, - DARK_MANUSCRIPT_13518, - TRANSPORTATION_INCANTATIONS - ), - Arrays.asList( - RICKTORS_DIARY_7, - VARLAMORE_ENVOY, - DARK_MANUSCRIPT_13514, - EATHRAM_RADA_EXTRACT, - IDEOLOGY_OF_DARKNESS, - DARK_MANUSCRIPT_13516, - DARK_MANUSCRIPT_13521, - RADAS_CENSUS, - DARK_MANUSCRIPT_13515, - KILLING_OF_A_KING, - DARK_MANUSCRIPT_13520, - TREACHERY_OF_ROYALTY, - HOSIDIUS_LETTER, - DARK_MANUSCRIPT_13519, - BYRNES_CORONATION_SPEECH, - DARK_MANUSCRIPT_13517, - SOUL_JOURNEY, - DARK_MANUSCRIPT_13522, - WINTERTODT_PARABLE, - TWILL_ACCORD, - RADAS_JOURNEY, - TRANSVERGENCE_THEORY, - TRISTESSAS_TRAGEDY, - DARK_MANUSCRIPT_13523, - DARK_MANUSCRIPT_13518, - TRANSPORTATION_INCANTATIONS - ), - Arrays.asList( - RADAS_CENSUS, - DARK_MANUSCRIPT_13522, - RICKTORS_DIARY_7, - DARK_MANUSCRIPT_13514, - EATHRAM_RADA_EXTRACT, - DARK_MANUSCRIPT_13516, - KILLING_OF_A_KING, - DARK_MANUSCRIPT_13520, - HOSIDIUS_LETTER, - DARK_MANUSCRIPT_13519, - DARK_MANUSCRIPT_13521, - WINTERTODT_PARABLE, - TWILL_ACCORD, - DARK_MANUSCRIPT_13515, - BYRNES_CORONATION_SPEECH, - DARK_MANUSCRIPT_13517, - IDEOLOGY_OF_DARKNESS, - RADAS_JOURNEY, - TRANSVERGENCE_THEORY, - TRISTESSAS_TRAGEDY, - DARK_MANUSCRIPT_13523, - TREACHERY_OF_ROYALTY, - DARK_MANUSCRIPT_13518, - TRANSPORTATION_INCANTATIONS, - SOUL_JOURNEY, - VARLAMORE_ENVOY - ), - Arrays.asList( - RADAS_CENSUS, - TRANSVERGENCE_THEORY, - TREACHERY_OF_ROYALTY, - RADAS_JOURNEY, - KILLING_OF_A_KING, - DARK_MANUSCRIPT_13520, - VARLAMORE_ENVOY, - DARK_MANUSCRIPT_13522, - BYRNES_CORONATION_SPEECH, - DARK_MANUSCRIPT_13517, - HOSIDIUS_LETTER, - DARK_MANUSCRIPT_13516, - DARK_MANUSCRIPT_13519, - TRISTESSAS_TRAGEDY, - DARK_MANUSCRIPT_13523, - DARK_MANUSCRIPT_13521, - RICKTORS_DIARY_7, - DARK_MANUSCRIPT_13514, - IDEOLOGY_OF_DARKNESS, - WINTERTODT_PARABLE, - TWILL_ACCORD, - SOUL_JOURNEY, - DARK_MANUSCRIPT_13515, - EATHRAM_RADA_EXTRACT, - DARK_MANUSCRIPT_13518, - TRANSPORTATION_INCANTATIONS - ) - ); - - for (int i = 0; i < books.size(); i++) - { - assert new HashSet<>(books.get(i)).size() == books.get(i).size(); - books.set(i, Collections.unmodifiableList(books.get(i))); - } - return Collections.unmodifiableList(books); - } - - private void add(int x, int y, int z, int i) - { - // 'i' is added as a parameter for readability - WorldPoint p = new WorldPoint(x, y, z); - Bookcase b = byPoint.get(p); - if (b == null) - { - b = new Bookcase(p); - byPoint.put(p, b); - byLevel.computeIfAbsent(z, a -> new ArrayList<>()).add(b); - } - b.getIndex().add(i); - assert i == byIndex.size(); - byIndex.add(b); - } - - private void populateBooks() - { - add(1626, 3795, 0, 0); - add(1625, 3793, 0, 1); - add(1623, 3793, 0, 2); - add(1620, 3792, 0, 3); - add(1624, 3792, 0, 4); - add(1626, 3788, 0, 5); - add(1626, 3787, 0, 6); - add(1624, 3784, 0, 7); - add(1623, 3784, 0, 8); - add(1621, 3784, 0, 9); - add(1615, 3785, 0, 10); - add(1615, 3788, 0, 11); - add(1615, 3790, 0, 12); - add(1614, 3790, 0, 13); - add(1614, 3788, 0, 14); - add(1614, 3786, 0, 15); - add(1612, 3784, 0, 16); - add(1610, 3784, 0, 17); - add(1609, 3784, 0, 18); - add(1607, 3786, 0, 19); - add(1607, 3789, 0, 20); - add(1607, 3795, 0, 21); - add(1607, 3796, 0, 22); - add(1607, 3799, 0, 23); - add(1610, 3801, 0, 24); - add(1612, 3801, 0, 25); - add(1618, 3801, 0, 26); - add(1620, 3801, 0, 27); - add(1620, 3814, 0, 28); - add(1618, 3814, 0, 29); - add(1617, 3814, 0, 30); - add(1615, 3816, 0, 31); - add(1615, 3817, 0, 32); - add(1615, 3820, 0, 33); - add(1614, 3820, 0, 34); - add(1614, 3817, 0, 35); - add(1614, 3816, 0, 36); - add(1612, 3814, 0, 37); - add(1610, 3814, 0, 38); - add(1607, 3816, 0, 39); - add(1607, 3817, 0, 40); - add(1607, 3820, 0, 41); - add(1607, 3826, 0, 42); - add(1607, 3828, 0, 43); - add(1609, 3831, 0, 44); - add(1612, 3831, 0, 45); - add(1614, 3831, 0, 46); - add(1619, 3831, 0, 47); - add(1621, 3831, 0, 48); - add(1624, 3831, 0, 49); - add(1626, 3829, 0, 50); - add(1626, 3827, 0, 51); - add(1624, 3823, 0, 52); - add(1622, 3823, 0, 53); - add(1620, 3823, 0, 54); - add(1621, 3822, 0, 55); - add(1624, 3822, 0, 56); - add(1626, 3820, 0, 57); - add(1639, 3821, 0, 58); - add(1639, 3822, 0, 59); - add(1639, 3827, 0, 60); - add(1639, 3829, 0, 61); - add(1642, 3831, 0, 62); - add(1645, 3831, 0, 63); - add(1646, 3829, 0, 64); - add(1646, 3827, 0, 65); - add(1646, 3826, 0, 66); - add(1647, 3827, 0, 67); - add(1647, 3829, 0, 68); - add(1647, 3830, 0, 69); - add(1652, 3831, 0, 70); - add(1653, 3831, 0, 71); - add(1656, 3831, 0, 72); - add(1658, 3829, 0, 73); - add(1658, 3826, 0, 74); - add(1658, 3825, 0, 75); - add(1658, 3820, 0, 76); - add(1658, 3819, 0, 77); - add(1658, 3816, 0, 78); - add(1655, 3814, 0, 79); - add(1654, 3814, 0, 80); - add(1651, 3817, 0, 81); - add(1651, 3819, 0, 82); - add(1651, 3820, 0, 83); - add(1650, 3821, 0, 84); - add(1650, 3819, 0, 85); - add(1650, 3816, 0, 86); - add(1648, 3814, 0, 87); - add(1646, 3814, 0, 88); - add(1645, 3814, 0, 89); - add(1607, 3820, 1, 90); - add(1607, 3821, 1, 91); - add(1609, 3822, 1, 92); - add(1612, 3823, 1, 93); - add(1611, 3823, 1, 94); - add(1607, 3824, 1, 95); - add(1607, 3825, 1, 96); - add(1607, 3827, 1, 97); - add(1611, 3831, 1, 98); - add(1612, 3831, 1, 99); - add(1613, 3831, 1, 100); - add(1617, 3831, 1, 101); - add(1618, 3831, 1, 102); - add(1620, 3831, 1, 103); - add(1624, 3831, 1, 104); - add(1624, 3829, 1, 105); - add(1624, 3825, 1, 106); - add(1624, 3824, 1, 107); - add(1624, 3819, 1, 108); - add(1624, 3817, 1, 109); - add(1623, 3816, 1, 110); - add(1621, 3816, 1, 111); - add(1617, 3816, 1, 112); - add(1616, 3816, 1, 113); - add(1611, 3816, 1, 114); - add(1609, 3816, 1, 115); - add(1620, 3820, 1, 116); - add(1620, 3822, 1, 117); - add(1620, 3824, 1, 118); - add(1620, 3825, 1, 119); - add(1620, 3827, 1, 120); - add(1621, 3826, 1, 121); - add(1621, 3822, 1, 122); - add(1621, 3820, 1, 123); - add(1607, 3788, 1, 124); - add(1607, 3789, 1, 125); - add(1609, 3790, 1, 126); - add(1611, 3790, 1, 127); - add(1613, 3790, 1, 128); - add(1614, 3789, 1, 129); - add(1615, 3788, 1, 130); - add(1615, 3790, 1, 131); - add(1614, 3791, 1, 132); - add(1613, 3791, 1, 133); - add(1610, 3791, 1, 134); - add(1609, 3791, 1, 135); - add(1608, 3791, 1, 136); - add(1607, 3793, 1, 137); - add(1607, 3794, 1, 138); - add(1608, 3799, 1, 139); - add(1610, 3799, 1, 140); - add(1615, 3799, 1, 141); - add(1616, 3799, 1, 142); - add(1621, 3799, 1, 143); - add(1623, 3799, 1, 144); - add(1624, 3798, 1, 145); - add(1624, 3796, 1, 146); - add(1624, 3792, 1, 147); - add(1624, 3791, 1, 148); - add(1623, 3789, 1, 149); - add(1621, 3789, 1, 150); - add(1620, 3788, 1, 151); - add(1621, 3788, 1, 152); - add(1624, 3787, 1, 153); - add(1624, 3786, 1, 154); - add(1619, 3784, 1, 155); - add(1618, 3784, 1, 156); - add(1616, 3784, 1, 157); - add(1612, 3784, 1, 158); - add(1611, 3784, 1, 159); - add(1625, 3801, 1, 160); - add(1625, 3802, 1, 161); - add(1625, 3803, 1, 162); - add(1625, 3804, 1, 163); - add(1625, 3806, 1, 164); - add(1625, 3807, 1, 165); - add(1625, 3808, 1, 166); - add(1625, 3809, 1, 167); - add(1625, 3811, 1, 168); - add(1625, 3812, 1, 169); - add(1625, 3813, 1, 170); - add(1625, 3814, 1, 171); - add(1626, 3815, 1, 172); - add(1627, 3815, 1, 173); - add(1631, 3815, 1, 174); - add(1632, 3815, 1, 175); - add(1633, 3815, 1, 176); - add(1634, 3815, 1, 177); - add(1638, 3815, 1, 178); - add(1639, 3815, 1, 179); - add(1640, 3814, 1, 180); - add(1640, 3813, 1, 181); - add(1640, 3803, 1, 182); - add(1640, 3802, 1, 183); - add(1640, 3801, 1, 184); - add(1639, 3800, 1, 185); - add(1638, 3800, 1, 186); - add(1634, 3800, 1, 187); - add(1633, 3800, 1, 188); - add(1632, 3800, 1, 189); - add(1631, 3800, 1, 190); - add(1627, 3800, 1, 191); - add(1626, 3800, 1, 192); - add(1641, 3817, 1, 193); - add(1641, 3818, 1, 194); - add(1641, 3819, 1, 195); - add(1641, 3824, 1, 196); - add(1641, 3825, 1, 197); - add(1641, 3829, 1, 198); - add(1645, 3831, 1, 199); - add(1646, 3831, 1, 200); - add(1647, 3831, 1, 201); - add(1648, 3831, 1, 202); - add(1649, 3830, 1, 203); - add(1649, 3828, 1, 204); - add(1650, 3829, 1, 205); - add(1652, 3831, 1, 206); - add(1653, 3831, 1, 207); - add(1658, 3827, 1, 208); - add(1658, 3826, 1, 209); - add(1658, 3823, 1, 210); - add(1658, 3822, 1, 211); - add(1658, 3821, 1, 212); - add(1658, 3820, 1, 213); - add(1656, 3816, 1, 214); - add(1655, 3816, 1, 215); - add(1651, 3816, 1, 216); - add(1649, 3816, 1, 217); - add(1648, 3816, 1, 218); - add(1644, 3816, 1, 219); - add(1643, 3816, 1, 220); - add(1607, 3785, 2, 221); - add(1607, 3786, 2, 222); - add(1607, 3796, 2, 223); - add(1607, 3797, 2, 224); - add(1608, 3799, 2, 225); - add(1610, 3799, 2, 226); - add(1611, 3799, 2, 227); - add(1618, 3799, 2, 228); - add(1621, 3799, 2, 229); - add(1624, 3797, 2, 230); - add(1624, 3795, 2, 231); - add(1624, 3794, 2, 232); - add(1624, 3792, 2, 233); - add(1623, 3791, 2, 234); - add(1622, 3791, 2, 235); - add(1618, 3792, 2, 236); - add(1618, 3793, 2, 237); - add(1618, 3794, 2, 238); - add(1617, 3793, 2, 239); - add(1617, 3792, 2, 240); - add(1618, 3790, 2, 241); - add(1620, 3790, 2, 242); - add(1622, 3790, 2, 243); - add(1624, 3789, 2, 244); - add(1624, 3788, 2, 245); - add(1624, 3786, 2, 246); - add(1624, 3785, 2, 247); - add(1623, 3784, 2, 248); - add(1621, 3784, 2, 249); - add(1611, 3784, 2, 250); - add(1609, 3784, 2, 251); - add(1612, 3789, 2, 252); - add(1612, 3791, 2, 253); - add(1612, 3794, 2, 254); - add(1613, 3793, 2, 255); - add(1613, 3792, 2, 256); - add(1613, 3791, 2, 257); - add(1617, 3791, 2, 258); - add(1617, 3793, 2, 259); - add(1618, 3794, 2, 260); - add(1618, 3792, 2, 261); - add(1619, 3791, 2, 262); - add(1623, 3791, 2, 263); - add(1623, 3790, 2, 264); - add(1622, 3790, 2, 265); - add(1619, 3790, 2, 266); - add(1611, 3816, 2, 267); - add(1610, 3816, 2, 268); - add(1609, 3816, 2, 269); - add(1607, 3817, 2, 270); - add(1607, 3819, 2, 271); - add(1607, 3829, 2, 272); - add(1608, 3831, 2, 273); - add(1610, 3831, 2, 274); - add(1611, 3831, 2, 275); - add(1622, 3831, 2, 276); - add(1623, 3831, 2, 277); - add(1624, 3829, 2, 278); - add(1624, 3828, 2, 279); - add(1624, 3821, 2, 280); - add(1624, 3819, 2, 281); - add(1622, 3816, 2, 282); - add(1620, 3816, 2, 283); - add(1618, 3816, 2, 284); - add(1615, 3821, 2, 285); - add(1617, 3821, 2, 286); - add(1619, 3822, 2, 287); - add(1619, 3824, 2, 288); - add(1618, 3826, 2, 289); - add(1617, 3826, 2, 290); - add(1615, 3827, 2, 291); - add(1616, 3827, 2, 292); - add(1618, 3827, 2, 293); - add(1620, 3826, 2, 294); - add(1620, 3824, 2, 295); - add(1620, 3822, 2, 296); - add(1620, 3821, 2, 297); - add(1619, 3820, 2, 298); - add(1617, 3820, 2, 299); - add(1615, 3820, 2, 300); - add(1641, 3818, 2, 301); - add(1641, 3820, 2, 302); - add(1641, 3821, 2, 303); - add(1641, 3829, 2, 304); - add(1643, 3831, 2, 305); - add(1644, 3831, 2, 306); - add(1654, 3831, 2, 307); - add(1656, 3831, 2, 308); - add(1658, 3830, 2, 309); - add(1658, 3828, 2, 310); - add(1658, 3818, 2, 311); - add(1658, 3817, 2, 312); - add(1656, 3816, 2, 313); - add(1655, 3816, 2, 314); - add(1652, 3816, 2, 315); - add(1648, 3817, 2, 316); - add(1648, 3819, 2, 317); - add(1648, 3821, 2, 318); - add(1649, 3823, 2, 319); - add(1650, 3823, 2, 320); - add(1652, 3823, 2, 321); - add(1654, 3822, 2, 322); - add(1654, 3820, 2, 323); - add(1655, 3820, 2, 324); - add(1655, 3821, 2, 325); - add(1655, 3823, 2, 326); - add(1653, 3824, 2, 327); - add(1652, 3824, 2, 328); - add(1649, 3824, 2, 329); - add(1648, 3824, 2, 330); - add(1647, 3822, 2, 331); - add(1647, 3820, 2, 332); - add(1647, 3818, 2, 333); - add(1645, 3816, 2, 334); - add(1644, 3816, 2, 335); - add(1625, 3802, 2, 336); - add(1625, 3804, 2, 337); - add(1625, 3811, 2, 338); - add(1625, 3812, 2, 339); - add(1627, 3815, 2, 340); - add(1628, 3815, 2, 341); - add(1635, 3815, 2, 342); - add(1637, 3815, 2, 343); - add(1638, 3815, 2, 344); - add(1640, 3813, 2, 345); - add(1640, 3811, 2, 346); - add(1640, 3810, 2, 347); - add(1638, 3800, 2, 348); - add(1632, 3800, 2, 349); - add(1630, 3800, 2, 350); - add(1629, 3800, 2, 351); - add(1627, 3800, 2, 352); - } +/* + * Copyright (c) 2018 Abex + * 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.kourendlibrary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; +import javax.inject.Singleton; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.coords.WorldPoint; +import static net.runelite.client.plugins.kourendlibrary.Book.BYRNES_CORONATION_SPEECH; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13514; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13515; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13516; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13517; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13518; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13519; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13520; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13521; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13522; +import static net.runelite.client.plugins.kourendlibrary.Book.DARK_MANUSCRIPT_13523; +import static net.runelite.client.plugins.kourendlibrary.Book.EATHRAM_RADA_EXTRACT; +import static net.runelite.client.plugins.kourendlibrary.Book.HOSIDIUS_LETTER; +import static net.runelite.client.plugins.kourendlibrary.Book.IDEOLOGY_OF_DARKNESS; +import static net.runelite.client.plugins.kourendlibrary.Book.KILLING_OF_A_KING; +import static net.runelite.client.plugins.kourendlibrary.Book.RADAS_CENSUS; +import static net.runelite.client.plugins.kourendlibrary.Book.RADAS_JOURNEY; +import static net.runelite.client.plugins.kourendlibrary.Book.RICKTORS_DIARY_7; +import static net.runelite.client.plugins.kourendlibrary.Book.SOUL_JOURNEY; +import static net.runelite.client.plugins.kourendlibrary.Book.TRANSPORTATION_INCANTATIONS; +import static net.runelite.client.plugins.kourendlibrary.Book.TRANSVERGENCE_THEORY; +import static net.runelite.client.plugins.kourendlibrary.Book.TREACHERY_OF_ROYALTY; +import static net.runelite.client.plugins.kourendlibrary.Book.TRISTESSAS_TRAGEDY; +import static net.runelite.client.plugins.kourendlibrary.Book.TWILL_ACCORD; +import static net.runelite.client.plugins.kourendlibrary.Book.VARLAMORE_ENVOY; +import static net.runelite.client.plugins.kourendlibrary.Book.WINTERTODT_PARABLE; + +/** + * Library represents a instance of the Kourend/Arceuus House library. + *

+ * The library changes the locations of it's books every 60-90 minutes. + * Of the 554 bookcases in the library, only 346 of them can ever have books. + * 6 of the bookcases in the south-west corner of the top floor are duplicated. + * These 6 bookcases are not handled 100% correctly due to their low chance + * of being used to train the predictor. + *

+ * Each of the 352 bookcase slots "Bookcase"s has an index which is used to + * place the book inside of them. The game chooses one of the 5 sequences and a + * bookcase starting index, then places a book from the sequence into every 13th + * bookcase, by index. Each sequence contains 26 Books, consisting of 16 books + * and 10 dark manuscripts. You can only get one dark manuscript at a time, though + * they are all placed into shelves. + */ +@Singleton +@Slf4j +class Library +{ + private final Map byPoint = new HashMap<>(); + private final Map> byLevel = new HashMap<>(); + private final List byIndex = new ArrayList<>(); + + private final List> sequences = populateSequences(); + + private final int step; + + @Getter + private SolvedState state; + + @Getter + private Book customerBook; + + @Getter + private LibraryCustomer customer; + + Library() + { + populateBooks(); + step = byIndex.size() / Book.values().length; + reset(); + } + + synchronized List getBookcasesOnLevel(int z) + { + return Collections.unmodifiableList(byLevel.get(z)); + } + + synchronized List getBookcases() + { + return Collections.unmodifiableList(byIndex); + } + + void setCustomer(LibraryCustomer customer, Book book) + { + this.customer = customer; + this.customerBook = book; + } + + synchronized void reset() + { + state = SolvedState.NO_DATA; + for (Bookcase b : byIndex) + { + b.clearBook(); + b.getPossibleBooks().clear(); + } + log.info("Library is now reset"); + } + + synchronized void mark(WorldPoint loc, Book book) + { + Bookcase bookcase = byPoint.get(loc); + if (bookcase == null) + { + log.debug("Requested non-existent bookcase at {}", loc); + return; + } + + if (bookcase.isBookSet()) + { + // Bookcase is set from a previous mark + // Check for a mismatch, unless it is now null and had a dark manuscript + if (book != bookcase.getBook() && !(book == null && bookcase.getBook().isDarkManuscript())) + { + reset(); + } + } + else if (state != SolvedState.NO_DATA) + { + // We know all of the possible things in this shelf. + if (book != null) + { + // Check to see if our guess is wrong + if (!bookcase.getPossibleBooks().contains(book)) + { + reset(); + } + } + } + + // Everything is known, nothing to do + if (state == SolvedState.COMPLETE) + { + return; + } + + log.info("Setting bookcase {} to {}", bookcase.getIndex(), book); + for (; ; ) + { + bookcase.setBook(book); + + // Basing the sequences on null is not supported, though possible + if (book == null) + { + return; + } + + // This is one of the 6 bookcases with 2 ids. Not fully supported. + if (bookcase.getIndex().size() != 1) + { + return; + } + + int bookcaseIndex = bookcase.getIndex().get(0); + + state = SolvedState.INCOMPLETE; + + // Map each sequence to the number of bookcases that match the sequence + // return 0 if it is a mismatch. + // Keep in mind that Bookcases with dark manuscripts may be set to null. + int[] certainty = sequences.stream().mapToInt(sequence -> + { + int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book); + + int found = 0; + for (int i = 0; i < byIndex.size(); i++) + { + int ai = (i + zero) % byIndex.size(); + Bookcase iBookcase = byIndex.get(ai); + if (i % step == 0) + { + int seqI = i / step; + if (iBookcase.isBookSet() && seqI < sequence.size()) + { + Book seqBook = sequence.get(seqI); + boolean isSeqManuscript = seqBook == null || seqBook.isDarkManuscript(); + if (!((isSeqManuscript && iBookcase.getBook() == null) || (iBookcase.getBook() == seqBook))) + { + log.debug("Bailing @ i={} ai={} {}; {} != {}", i, ai, iBookcase.getIndex(), iBookcase.getBook(), seqBook); + found = 0; + break; + } + found++; + } + } + else + { + // Only bail if this isn't a double bookcase + if (iBookcase.isBookSet() && iBookcase.getBook() != null && iBookcase.getIndex().size() == 1) + { + log.debug("Bailing @ i={} ai={} {}; {} is set", i, ai, iBookcase.getIndex(), iBookcase.getBook()); + found = 0; + break; + } + } + } + return found; + }).toArray(); + log.info("Certainty is now {}", certainty); + + for (Bookcase b : byIndex) + { + b.getPossibleBooks().clear(); + } + + // Write the most likely sequences onto the bookcases + int max = IntStream.of(certainty).max().getAsInt(); + + // We have books set, but 0 sequences match, Something is wrong, reset. + if (max == 0) + { + reset(); + continue; + } + + IntStream.range(0, sequences.size()) + .filter(i -> certainty[i] == max) + .forEach(isequence -> + { + List sequence = sequences.get(isequence); + int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book); + + for (int i = 0; i < byIndex.size(); i++) + { + int ai = (i + zero) % byIndex.size(); + Bookcase iBookcase = byIndex.get(ai); + if (iBookcase.getBook() == null) + { + int iseq = i / step; + if (i % step == 0 && iseq < sequence.size()) + { + Book seqBook = sequence.get(iseq); + iBookcase.getPossibleBooks().add(seqBook); + } + } + } + }); + if (IntStream.range(0, certainty.length).filter(i -> certainty[i] == max).count() == 1) + { + state = SolvedState.COMPLETE; + } + return; + } + } + + /** + * Find the bookcase index that is index zero in the sequence, identifying by the book in bookcase + */ + private int getBookcaseZeroIndexForSequenceWithBook(List sequences, int bookcaseIndex, Book book) + { + int bookSequence = sequences.indexOf(book); + assert bookSequence >= 0; + + bookcaseIndex -= step * bookSequence; + for (; bookcaseIndex < 0; ) + { + bookcaseIndex += byIndex.size(); + } + return bookcaseIndex; + } + + private List> populateSequences() + { + List> books = Arrays.asList( + Arrays.asList( + DARK_MANUSCRIPT_13516, + KILLING_OF_A_KING, + DARK_MANUSCRIPT_13520, + IDEOLOGY_OF_DARKNESS, + RADAS_JOURNEY, + TRANSVERGENCE_THEORY, + TRISTESSAS_TRAGEDY, + DARK_MANUSCRIPT_13523, + DARK_MANUSCRIPT_13521, + RADAS_CENSUS, + TREACHERY_OF_ROYALTY, + HOSIDIUS_LETTER, + DARK_MANUSCRIPT_13519, + RICKTORS_DIARY_7, + DARK_MANUSCRIPT_13514, + EATHRAM_RADA_EXTRACT, + DARK_MANUSCRIPT_13522, + VARLAMORE_ENVOY, + WINTERTODT_PARABLE, + TWILL_ACCORD, + DARK_MANUSCRIPT_13515, + BYRNES_CORONATION_SPEECH, + DARK_MANUSCRIPT_13517, + SOUL_JOURNEY, + DARK_MANUSCRIPT_13518, + TRANSPORTATION_INCANTATIONS + ), + Arrays.asList( + DARK_MANUSCRIPT_13516, + KILLING_OF_A_KING, + DARK_MANUSCRIPT_13520, + IDEOLOGY_OF_DARKNESS, + RADAS_JOURNEY, + TRANSVERGENCE_THEORY, + TRISTESSAS_TRAGEDY, + DARK_MANUSCRIPT_13523, + DARK_MANUSCRIPT_13521, + RADAS_CENSUS, + TREACHERY_OF_ROYALTY, + HOSIDIUS_LETTER, + VARLAMORE_ENVOY, + DARK_MANUSCRIPT_13519, + RICKTORS_DIARY_7, + DARK_MANUSCRIPT_13514, + EATHRAM_RADA_EXTRACT, + DARK_MANUSCRIPT_13522, + SOUL_JOURNEY, + WINTERTODT_PARABLE, + TWILL_ACCORD, + DARK_MANUSCRIPT_13515, + BYRNES_CORONATION_SPEECH, + DARK_MANUSCRIPT_13517, + DARK_MANUSCRIPT_13518, + TRANSPORTATION_INCANTATIONS + ), + Arrays.asList( + RICKTORS_DIARY_7, + VARLAMORE_ENVOY, + DARK_MANUSCRIPT_13514, + EATHRAM_RADA_EXTRACT, + IDEOLOGY_OF_DARKNESS, + DARK_MANUSCRIPT_13516, + DARK_MANUSCRIPT_13521, + RADAS_CENSUS, + DARK_MANUSCRIPT_13515, + KILLING_OF_A_KING, + DARK_MANUSCRIPT_13520, + TREACHERY_OF_ROYALTY, + HOSIDIUS_LETTER, + DARK_MANUSCRIPT_13519, + BYRNES_CORONATION_SPEECH, + DARK_MANUSCRIPT_13517, + SOUL_JOURNEY, + DARK_MANUSCRIPT_13522, + WINTERTODT_PARABLE, + TWILL_ACCORD, + RADAS_JOURNEY, + TRANSVERGENCE_THEORY, + TRISTESSAS_TRAGEDY, + DARK_MANUSCRIPT_13523, + DARK_MANUSCRIPT_13518, + TRANSPORTATION_INCANTATIONS + ), + Arrays.asList( + RADAS_CENSUS, + DARK_MANUSCRIPT_13522, + RICKTORS_DIARY_7, + DARK_MANUSCRIPT_13514, + EATHRAM_RADA_EXTRACT, + DARK_MANUSCRIPT_13516, + KILLING_OF_A_KING, + DARK_MANUSCRIPT_13520, + HOSIDIUS_LETTER, + DARK_MANUSCRIPT_13519, + DARK_MANUSCRIPT_13521, + WINTERTODT_PARABLE, + TWILL_ACCORD, + DARK_MANUSCRIPT_13515, + BYRNES_CORONATION_SPEECH, + DARK_MANUSCRIPT_13517, + IDEOLOGY_OF_DARKNESS, + RADAS_JOURNEY, + TRANSVERGENCE_THEORY, + TRISTESSAS_TRAGEDY, + DARK_MANUSCRIPT_13523, + TREACHERY_OF_ROYALTY, + DARK_MANUSCRIPT_13518, + TRANSPORTATION_INCANTATIONS, + SOUL_JOURNEY, + VARLAMORE_ENVOY + ), + Arrays.asList( + RADAS_CENSUS, + TRANSVERGENCE_THEORY, + TREACHERY_OF_ROYALTY, + RADAS_JOURNEY, + KILLING_OF_A_KING, + DARK_MANUSCRIPT_13520, + VARLAMORE_ENVOY, + DARK_MANUSCRIPT_13522, + BYRNES_CORONATION_SPEECH, + DARK_MANUSCRIPT_13517, + HOSIDIUS_LETTER, + DARK_MANUSCRIPT_13516, + DARK_MANUSCRIPT_13519, + TRISTESSAS_TRAGEDY, + DARK_MANUSCRIPT_13523, + DARK_MANUSCRIPT_13521, + RICKTORS_DIARY_7, + DARK_MANUSCRIPT_13514, + IDEOLOGY_OF_DARKNESS, + WINTERTODT_PARABLE, + TWILL_ACCORD, + SOUL_JOURNEY, + DARK_MANUSCRIPT_13515, + EATHRAM_RADA_EXTRACT, + DARK_MANUSCRIPT_13518, + TRANSPORTATION_INCANTATIONS + ) + ); + + for (int i = 0; i < books.size(); i++) + { + assert new HashSet<>(books.get(i)).size() == books.get(i).size(); + books.set(i, Collections.unmodifiableList(books.get(i))); + } + return Collections.unmodifiableList(books); + } + + private void add(int x, int y, int z, int i) + { + // 'i' is added as a parameter for readability + WorldPoint p = new WorldPoint(x, y, z); + Bookcase b = byPoint.get(p); + if (b == null) + { + b = new Bookcase(p); + byPoint.put(p, b); + byLevel.computeIfAbsent(z, a -> new ArrayList<>()).add(b); + } + b.getIndex().add(i); + assert i == byIndex.size(); + byIndex.add(b); + } + + private void populateBooks() + { + add(1626, 3795, 0, 0); + add(1625, 3793, 0, 1); + add(1623, 3793, 0, 2); + add(1620, 3792, 0, 3); + add(1624, 3792, 0, 4); + add(1626, 3788, 0, 5); + add(1626, 3787, 0, 6); + add(1624, 3784, 0, 7); + add(1623, 3784, 0, 8); + add(1621, 3784, 0, 9); + add(1615, 3785, 0, 10); + add(1615, 3788, 0, 11); + add(1615, 3790, 0, 12); + add(1614, 3790, 0, 13); + add(1614, 3788, 0, 14); + add(1614, 3786, 0, 15); + add(1612, 3784, 0, 16); + add(1610, 3784, 0, 17); + add(1609, 3784, 0, 18); + add(1607, 3786, 0, 19); + add(1607, 3789, 0, 20); + add(1607, 3795, 0, 21); + add(1607, 3796, 0, 22); + add(1607, 3799, 0, 23); + add(1610, 3801, 0, 24); + add(1612, 3801, 0, 25); + add(1618, 3801, 0, 26); + add(1620, 3801, 0, 27); + add(1620, 3814, 0, 28); + add(1618, 3814, 0, 29); + add(1617, 3814, 0, 30); + add(1615, 3816, 0, 31); + add(1615, 3817, 0, 32); + add(1615, 3820, 0, 33); + add(1614, 3820, 0, 34); + add(1614, 3817, 0, 35); + add(1614, 3816, 0, 36); + add(1612, 3814, 0, 37); + add(1610, 3814, 0, 38); + add(1607, 3816, 0, 39); + add(1607, 3817, 0, 40); + add(1607, 3820, 0, 41); + add(1607, 3826, 0, 42); + add(1607, 3828, 0, 43); + add(1609, 3831, 0, 44); + add(1612, 3831, 0, 45); + add(1614, 3831, 0, 46); + add(1619, 3831, 0, 47); + add(1621, 3831, 0, 48); + add(1624, 3831, 0, 49); + add(1626, 3829, 0, 50); + add(1626, 3827, 0, 51); + add(1624, 3823, 0, 52); + add(1622, 3823, 0, 53); + add(1620, 3823, 0, 54); + add(1621, 3822, 0, 55); + add(1624, 3822, 0, 56); + add(1626, 3820, 0, 57); + add(1639, 3821, 0, 58); + add(1639, 3822, 0, 59); + add(1639, 3827, 0, 60); + add(1639, 3829, 0, 61); + add(1642, 3831, 0, 62); + add(1645, 3831, 0, 63); + add(1646, 3829, 0, 64); + add(1646, 3827, 0, 65); + add(1646, 3826, 0, 66); + add(1647, 3827, 0, 67); + add(1647, 3829, 0, 68); + add(1647, 3830, 0, 69); + add(1652, 3831, 0, 70); + add(1653, 3831, 0, 71); + add(1656, 3831, 0, 72); + add(1658, 3829, 0, 73); + add(1658, 3826, 0, 74); + add(1658, 3825, 0, 75); + add(1658, 3820, 0, 76); + add(1658, 3819, 0, 77); + add(1658, 3816, 0, 78); + add(1655, 3814, 0, 79); + add(1654, 3814, 0, 80); + add(1651, 3817, 0, 81); + add(1651, 3819, 0, 82); + add(1651, 3820, 0, 83); + add(1650, 3821, 0, 84); + add(1650, 3819, 0, 85); + add(1650, 3816, 0, 86); + add(1648, 3814, 0, 87); + add(1646, 3814, 0, 88); + add(1645, 3814, 0, 89); + add(1607, 3820, 1, 90); + add(1607, 3821, 1, 91); + add(1609, 3822, 1, 92); + add(1612, 3823, 1, 93); + add(1611, 3823, 1, 94); + add(1607, 3824, 1, 95); + add(1607, 3825, 1, 96); + add(1607, 3827, 1, 97); + add(1611, 3831, 1, 98); + add(1612, 3831, 1, 99); + add(1613, 3831, 1, 100); + add(1617, 3831, 1, 101); + add(1618, 3831, 1, 102); + add(1620, 3831, 1, 103); + add(1624, 3831, 1, 104); + add(1624, 3829, 1, 105); + add(1624, 3825, 1, 106); + add(1624, 3824, 1, 107); + add(1624, 3819, 1, 108); + add(1624, 3817, 1, 109); + add(1623, 3816, 1, 110); + add(1621, 3816, 1, 111); + add(1617, 3816, 1, 112); + add(1616, 3816, 1, 113); + add(1611, 3816, 1, 114); + add(1609, 3816, 1, 115); + add(1620, 3820, 1, 116); + add(1620, 3822, 1, 117); + add(1620, 3824, 1, 118); + add(1620, 3825, 1, 119); + add(1620, 3827, 1, 120); + add(1621, 3826, 1, 121); + add(1621, 3822, 1, 122); + add(1621, 3820, 1, 123); + add(1607, 3788, 1, 124); + add(1607, 3789, 1, 125); + add(1609, 3790, 1, 126); + add(1611, 3790, 1, 127); + add(1613, 3790, 1, 128); + add(1614, 3789, 1, 129); + add(1615, 3788, 1, 130); + add(1615, 3790, 1, 131); + add(1614, 3791, 1, 132); + add(1613, 3791, 1, 133); + add(1610, 3791, 1, 134); + add(1609, 3791, 1, 135); + add(1608, 3791, 1, 136); + add(1607, 3793, 1, 137); + add(1607, 3794, 1, 138); + add(1608, 3799, 1, 139); + add(1610, 3799, 1, 140); + add(1615, 3799, 1, 141); + add(1616, 3799, 1, 142); + add(1621, 3799, 1, 143); + add(1623, 3799, 1, 144); + add(1624, 3798, 1, 145); + add(1624, 3796, 1, 146); + add(1624, 3792, 1, 147); + add(1624, 3791, 1, 148); + add(1623, 3789, 1, 149); + add(1621, 3789, 1, 150); + add(1620, 3788, 1, 151); + add(1621, 3788, 1, 152); + add(1624, 3787, 1, 153); + add(1624, 3786, 1, 154); + add(1619, 3784, 1, 155); + add(1618, 3784, 1, 156); + add(1616, 3784, 1, 157); + add(1612, 3784, 1, 158); + add(1611, 3784, 1, 159); + add(1625, 3801, 1, 160); + add(1625, 3802, 1, 161); + add(1625, 3803, 1, 162); + add(1625, 3804, 1, 163); + add(1625, 3806, 1, 164); + add(1625, 3807, 1, 165); + add(1625, 3808, 1, 166); + add(1625, 3809, 1, 167); + add(1625, 3811, 1, 168); + add(1625, 3812, 1, 169); + add(1625, 3813, 1, 170); + add(1625, 3814, 1, 171); + add(1626, 3815, 1, 172); + add(1627, 3815, 1, 173); + add(1631, 3815, 1, 174); + add(1632, 3815, 1, 175); + add(1633, 3815, 1, 176); + add(1634, 3815, 1, 177); + add(1638, 3815, 1, 178); + add(1639, 3815, 1, 179); + add(1640, 3814, 1, 180); + add(1640, 3813, 1, 181); + add(1640, 3803, 1, 182); + add(1640, 3802, 1, 183); + add(1640, 3801, 1, 184); + add(1639, 3800, 1, 185); + add(1638, 3800, 1, 186); + add(1634, 3800, 1, 187); + add(1633, 3800, 1, 188); + add(1632, 3800, 1, 189); + add(1631, 3800, 1, 190); + add(1627, 3800, 1, 191); + add(1626, 3800, 1, 192); + add(1641, 3817, 1, 193); + add(1641, 3818, 1, 194); + add(1641, 3819, 1, 195); + add(1641, 3824, 1, 196); + add(1641, 3825, 1, 197); + add(1641, 3829, 1, 198); + add(1645, 3831, 1, 199); + add(1646, 3831, 1, 200); + add(1647, 3831, 1, 201); + add(1648, 3831, 1, 202); + add(1649, 3830, 1, 203); + add(1649, 3828, 1, 204); + add(1650, 3829, 1, 205); + add(1652, 3831, 1, 206); + add(1653, 3831, 1, 207); + add(1658, 3827, 1, 208); + add(1658, 3826, 1, 209); + add(1658, 3823, 1, 210); + add(1658, 3822, 1, 211); + add(1658, 3821, 1, 212); + add(1658, 3820, 1, 213); + add(1656, 3816, 1, 214); + add(1655, 3816, 1, 215); + add(1651, 3816, 1, 216); + add(1649, 3816, 1, 217); + add(1648, 3816, 1, 218); + add(1644, 3816, 1, 219); + add(1643, 3816, 1, 220); + add(1607, 3785, 2, 221); + add(1607, 3786, 2, 222); + add(1607, 3796, 2, 223); + add(1607, 3797, 2, 224); + add(1608, 3799, 2, 225); + add(1610, 3799, 2, 226); + add(1611, 3799, 2, 227); + add(1618, 3799, 2, 228); + add(1621, 3799, 2, 229); + add(1624, 3797, 2, 230); + add(1624, 3795, 2, 231); + add(1624, 3794, 2, 232); + add(1624, 3792, 2, 233); + add(1623, 3791, 2, 234); + add(1622, 3791, 2, 235); + add(1618, 3792, 2, 236); + add(1618, 3793, 2, 237); + add(1618, 3794, 2, 238); + add(1617, 3793, 2, 239); + add(1617, 3792, 2, 240); + add(1618, 3790, 2, 241); + add(1620, 3790, 2, 242); + add(1622, 3790, 2, 243); + add(1624, 3789, 2, 244); + add(1624, 3788, 2, 245); + add(1624, 3786, 2, 246); + add(1624, 3785, 2, 247); + add(1623, 3784, 2, 248); + add(1621, 3784, 2, 249); + add(1611, 3784, 2, 250); + add(1609, 3784, 2, 251); + add(1612, 3789, 2, 252); + add(1612, 3791, 2, 253); + add(1612, 3794, 2, 254); + add(1613, 3793, 2, 255); + add(1613, 3792, 2, 256); + add(1613, 3791, 2, 257); + add(1617, 3791, 2, 258); + add(1617, 3793, 2, 259); + add(1618, 3794, 2, 260); + add(1618, 3792, 2, 261); + add(1619, 3791, 2, 262); + add(1623, 3791, 2, 263); + add(1623, 3790, 2, 264); + add(1622, 3790, 2, 265); + add(1619, 3790, 2, 266); + add(1611, 3816, 2, 267); + add(1610, 3816, 2, 268); + add(1609, 3816, 2, 269); + add(1607, 3817, 2, 270); + add(1607, 3819, 2, 271); + add(1607, 3829, 2, 272); + add(1608, 3831, 2, 273); + add(1610, 3831, 2, 274); + add(1611, 3831, 2, 275); + add(1622, 3831, 2, 276); + add(1623, 3831, 2, 277); + add(1624, 3829, 2, 278); + add(1624, 3828, 2, 279); + add(1624, 3821, 2, 280); + add(1624, 3819, 2, 281); + add(1622, 3816, 2, 282); + add(1620, 3816, 2, 283); + add(1618, 3816, 2, 284); + add(1615, 3821, 2, 285); + add(1617, 3821, 2, 286); + add(1619, 3822, 2, 287); + add(1619, 3824, 2, 288); + add(1618, 3826, 2, 289); + add(1617, 3826, 2, 290); + add(1615, 3827, 2, 291); + add(1616, 3827, 2, 292); + add(1618, 3827, 2, 293); + add(1620, 3826, 2, 294); + add(1620, 3824, 2, 295); + add(1620, 3822, 2, 296); + add(1620, 3821, 2, 297); + add(1619, 3820, 2, 298); + add(1617, 3820, 2, 299); + add(1615, 3820, 2, 300); + add(1641, 3818, 2, 301); + add(1641, 3820, 2, 302); + add(1641, 3821, 2, 303); + add(1641, 3829, 2, 304); + add(1643, 3831, 2, 305); + add(1644, 3831, 2, 306); + add(1654, 3831, 2, 307); + add(1656, 3831, 2, 308); + add(1658, 3830, 2, 309); + add(1658, 3828, 2, 310); + add(1658, 3818, 2, 311); + add(1658, 3817, 2, 312); + add(1656, 3816, 2, 313); + add(1655, 3816, 2, 314); + add(1652, 3816, 2, 315); + add(1648, 3817, 2, 316); + add(1648, 3819, 2, 317); + add(1648, 3821, 2, 318); + add(1649, 3823, 2, 319); + add(1650, 3823, 2, 320); + add(1652, 3823, 2, 321); + add(1654, 3822, 2, 322); + add(1654, 3820, 2, 323); + add(1655, 3820, 2, 324); + add(1655, 3821, 2, 325); + add(1655, 3823, 2, 326); + add(1653, 3824, 2, 327); + add(1652, 3824, 2, 328); + add(1649, 3824, 2, 329); + add(1648, 3824, 2, 330); + add(1647, 3822, 2, 331); + add(1647, 3820, 2, 332); + add(1647, 3818, 2, 333); + add(1645, 3816, 2, 334); + add(1644, 3816, 2, 335); + add(1625, 3802, 2, 336); + add(1625, 3804, 2, 337); + add(1625, 3811, 2, 338); + add(1625, 3812, 2, 339); + add(1627, 3815, 2, 340); + add(1628, 3815, 2, 341); + add(1635, 3815, 2, 342); + add(1637, 3815, 2, 343); + add(1638, 3815, 2, 344); + add(1640, 3813, 2, 345); + add(1640, 3811, 2, 346); + add(1640, 3810, 2, 347); + add(1638, 3800, 2, 348); + add(1632, 3800, 2, 349); + add(1630, 3800, 2, 350); + add(1629, 3800, 2, 351); + add(1627, 3800, 2, 352); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/LibraryCustomer.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/LibraryCustomer.java index 229ed37efe..cb3655cf34 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/LibraryCustomer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/LibraryCustomer.java @@ -1,67 +1,66 @@ -/* - * Copyright (c) 2018 Abex - * 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.kourendlibrary; - -import java.util.HashMap; -import java.util.Map; -import lombok.Getter; - -import net.runelite.api.NpcID; - -enum LibraryCustomer -{ - VILLIA(NpcID.VILLIA, "Villia"), - PROFESSOR_GRACKLEBONE(NpcID.PROFESSOR_GRACKLEBONE, "Prof. Gracklebone"), - SAM(NpcID.SAM_7049, "Sam"); - - @Getter - private final int id; - - @Getter - private final String name; - - private static final Map byId = buildIdMap(); - - LibraryCustomer(int id, String name) - { - this.id = id; - this.name = name; - } - - static LibraryCustomer getById(int id) - { - return byId.get(id); - } - - private static Map buildIdMap() - { - Map byId = new HashMap<>(); - for (LibraryCustomer c : values()) - { - byId.put(c.id, c); - } - return byId; - } -} +/* + * Copyright (c) 2018 Abex + * 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.kourendlibrary; + +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import net.runelite.api.NpcID; + +enum LibraryCustomer +{ + VILLIA(NpcID.VILLIA, "Villia"), + PROFESSOR_GRACKLEBONE(NpcID.PROFESSOR_GRACKLEBONE, "Prof. Gracklebone"), + SAM(NpcID.SAM_7049, "Sam"); + + @Getter + private final int id; + + @Getter + private final String name; + + private static final Map byId = buildIdMap(); + + LibraryCustomer(int id, String name) + { + this.id = id; + this.name = name; + } + + static LibraryCustomer getById(int id) + { + return byId.get(id); + } + + private static Map buildIdMap() + { + Map byId = new HashMap<>(); + for (LibraryCustomer c : values()) + { + byId.put(c.id, c); + } + return byId; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/SolvedState.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/SolvedState.java index c12f74fd25..0f05e80f4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/SolvedState.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/SolvedState.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2018 Abex - * 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.kourendlibrary; - -enum SolvedState -{ - NO_DATA, - INCOMPLETE, - COMPLETE; -} +/* + * Copyright (c) 2018 Abex + * 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.kourendlibrary; + +enum SolvedState +{ + NO_DATA, + INCOMPLETE, + COMPLETE +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanConfig.java index 96f671a295..128f179c3e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanConfig.java @@ -1,56 +1,55 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.lizardmenshaman; - -import net.runelite.client.config.Config; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("shaman") -public interface LizardmenShamanConfig extends Config -{ - @ConfigItem( - position = 1, - keyName = "showTimer", - name = "Show timer", - description = "Display timer till for lizardman shaman spawns." - ) - default boolean showTimer() - { - return true; - } - - @ConfigItem( - position = 2, - keyName = "notifyOnSpawn", - name = "Notify on spawn", - description = "Notify user when lizardman summons spawns." - ) - default boolean notifyOnSpawn() - { - return true; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.lizardmenshaman; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("shaman") +public interface LizardmenShamanConfig extends Config +{ + @ConfigItem( + position = 1, + keyName = "showTimer", + name = "Show timer", + description = "Display timer till for lizardman shaman spawns." + ) + default boolean showTimer() + { + return true; + } + + @ConfigItem( + position = 2, + keyName = "notifyOnSpawn", + name = "Notify on spawn", + description = "Notify user when lizardman summons spawns." + ) + default boolean notifyOnSpawn() + { + return true; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanPlugin.java index 6813e54e92..dee9d1d5cd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/LizardmenShamanPlugin.java @@ -1,118 +1,117 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.lizardmenshaman; - -import com.google.common.eventbus.Subscribe; -import com.google.inject.Provides; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Actor; -import net.runelite.api.Client; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.events.AnimationChanged; -import net.runelite.client.Notifier; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import java.util.HashMap; -import java.util.Map; - -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "Lizard Shamans", - description = "Configures timer for lizardmen shaman spawns.", - enabledByDefault = false, - tags = {"shaman", "lizard", "lizardmen"}, - type = PluginType.PVM -) -@Slf4j -public class LizardmenShamanPlugin extends Plugin -{ - private static final String SHAMAN = "Lizardman shaman"; - private static final String MESSAGE = "A Lizardman shaman has summoned his spawn!"; - - @Getter(AccessLevel.PACKAGE) - private final Map spawns = new HashMap<>(); - - @Inject - private OverlayManager overlayManager; - - @Inject - private ShamanSpawnOverlay overlay; - - @Inject - private LizardmenShamanConfig config; - - @Inject - private Notifier notifier; - - @Inject - private Client client; - - @Provides - LizardmenShamanConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(LizardmenShamanConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - spawns.clear(); - } - - @Subscribe - public void onAnimationChanged(AnimationChanged event) - { - Actor actor = event.getActor(); - if (actor == null || actor.getName() == null) - { - return; - } - else if (actor.getName().equals(SHAMAN) && actor.getAnimation() == 7157) - { - if (config.showTimer()) - { - spawns.put(event.getActor().getLocalLocation(), new LizardmenShamanSpawn(8.4, null)); - } - - if (config.notifyOnSpawn()) - { - notifier.notify(MESSAGE); - } - } - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.lizardmenshaman; + +import com.google.common.eventbus.Subscribe; +import com.google.inject.Provides; +import java.util.HashMap; +import java.util.Map; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.events.AnimationChanged; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Lizard Shamans", + description = "Configures timer for lizardmen shaman spawns.", + enabledByDefault = false, + tags = {"shaman", "lizard", "lizardmen"}, + type = PluginType.PVM +) +@Slf4j +public class LizardmenShamanPlugin extends Plugin +{ + private static final String SHAMAN = "Lizardman shaman"; + private static final String MESSAGE = "A Lizardman shaman has summoned his spawn!"; + + @Getter(AccessLevel.PACKAGE) + private final Map spawns = new HashMap<>(); + + @Inject + private OverlayManager overlayManager; + + @Inject + private ShamanSpawnOverlay overlay; + + @Inject + private LizardmenShamanConfig config; + + @Inject + private Notifier notifier; + + @Inject + private Client client; + + @Provides + LizardmenShamanConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(LizardmenShamanConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + spawns.clear(); + } + + @Subscribe + public void onAnimationChanged(AnimationChanged event) + { + Actor actor = event.getActor(); + if (actor == null || actor.getName() == null) + { + return; + } + else if (actor.getName().equals(SHAMAN) && actor.getAnimation() == 7157) + { + if (config.showTimer()) + { + spawns.put(event.getActor().getLocalLocation(), new LizardmenShamanSpawn(8.4, null)); + } + + if (config.notifyOnSpawn()) + { + notifier.notify(MESSAGE); + } + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/ShamanSpawnOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/ShamanSpawnOverlay.java index 8bd71ac3ca..479b063bb3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/ShamanSpawnOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lizardmenshaman/ShamanSpawnOverlay.java @@ -1,114 +1,115 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.lizardmenshaman; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.time.Duration; -import java.time.Instant; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.ProgressPieComponent; - -class ShamanSpawnOverlay extends Overlay -{ - private final Client client; - private final LizardmenShamanPlugin plugin; - - @Inject - private ShamanSpawnOverlay(Client client, LizardmenShamanPlugin plugin) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.client = client; - this.plugin = plugin; - } - @Override - public Dimension render(Graphics2D graphics) - { - plugin.getSpawns().forEach((localPoint, spawn) -> - { - final Instant now = Instant.now(); - final long startCountdown = Duration.between(spawn.getStart(), now).getSeconds(); - final double certainSec = spawn.getCountdownTimer() - startCountdown; - - if (certainSec <= 0) - { - if (spawn.getEnd() == null) - { - spawn.setEnd(Instant.now()); - } - } - - final ProgressPieComponent pieComponent = new ProgressPieComponent(); - final Point loc = Perspective.localToCanvas(client, localPoint, client.getPlane()); - - if (loc == null || certainSec < 0) - { - return; - } - - pieComponent.setPosition(loc); - pieComponent.setProgress(certainSec / spawn.getCountdownTimer()); - if (certainSec > 4.8) - { - pieComponent.setFill(Color.GREEN); - pieComponent.setBorderColor(Color.GREEN); - pieComponent.render(graphics); - } - else if (certainSec > 3.6) - { - pieComponent.setFill(Color.YELLOW); - pieComponent.setBorderColor(Color.YELLOW); - pieComponent.render(graphics); - } - else if (certainSec > 2.4) - { - pieComponent.setFill(Color.ORANGE); - pieComponent.setBorderColor(Color.ORANGE); - pieComponent.render(graphics); - } - else if (certainSec > 1.2) - { - pieComponent.setFill(new Color(255, 140, 0)); - pieComponent.setBorderColor(new Color(255, 140, 0)); - pieComponent.render(graphics); - } - else - { - pieComponent.setFill(Color.RED); - pieComponent.setBorderColor(Color.RED); - pieComponent.render(graphics); - } - }); - return null; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.lizardmenshaman; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.time.Duration; +import java.time.Instant; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ProgressPieComponent; + +class ShamanSpawnOverlay extends Overlay +{ + private final Client client; + private final LizardmenShamanPlugin plugin; + + @Inject + private ShamanSpawnOverlay(Client client, LizardmenShamanPlugin plugin) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.client = client; + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D graphics) + { + plugin.getSpawns().forEach((localPoint, spawn) -> + { + final Instant now = Instant.now(); + final long startCountdown = Duration.between(spawn.getStart(), now).getSeconds(); + final double certainSec = spawn.getCountdownTimer() - startCountdown; + + if (certainSec <= 0) + { + if (spawn.getEnd() == null) + { + spawn.setEnd(Instant.now()); + } + } + + final ProgressPieComponent pieComponent = new ProgressPieComponent(); + final Point loc = Perspective.localToCanvas(client, localPoint, client.getPlane()); + + if (loc == null || certainSec < 0) + { + return; + } + + pieComponent.setPosition(loc); + pieComponent.setProgress(certainSec / spawn.getCountdownTimer()); + if (certainSec > 4.8) + { + pieComponent.setFill(Color.GREEN); + pieComponent.setBorderColor(Color.GREEN); + pieComponent.render(graphics); + } + else if (certainSec > 3.6) + { + pieComponent.setFill(Color.YELLOW); + pieComponent.setBorderColor(Color.YELLOW); + pieComponent.render(graphics); + } + else if (certainSec > 2.4) + { + pieComponent.setFill(Color.ORANGE); + pieComponent.setBorderColor(Color.ORANGE); + pieComponent.render(graphics); + } + else if (certainSec > 1.2) + { + pieComponent.setFill(new Color(255, 140, 0)); + pieComponent.setBorderColor(new Color(255, 140, 0)); + pieComponent.render(graphics); + } + else + { + pieComponent.setFill(Color.RED); + pieComponent.setBorderColor(Color.RED); + pieComponent.render(graphics); + } + }); + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loginscreen/LoginScreenPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loginscreen/LoginScreenPlugin.java index 4da52e1492..aaa99cc0a9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loginscreen/LoginScreenPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loginscreen/LoginScreenPlugin.java @@ -1,209 +1,209 @@ -/* - * Copyright (c) 2017, Seth - * 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.loginscreen; - -import com.google.common.base.Strings; -import com.google.inject.Provides; -import java.awt.Toolkit; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.event.KeyEvent; -import java.io.IOException; -import javax.inject.Inject; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.events.GameStateChanged; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.util.OSType; - -@PluginDescriptor( - name = "Login Screen", - description = "Provides various enhancements for login screen" -) -@Slf4j -public class LoginScreenPlugin extends Plugin implements KeyListener -{ - private static final int MAX_USERNAME_LENGTH = 254; - private static final int MAX_PASSWORD_LENGTH = 20; - - @Inject - private Client client; - - @Inject - private LoginScreenConfig config; - - @Inject - private KeyManager keyManager; - - private String usernameCache; - - @Override - protected void startUp() throws Exception - { - applyUsername(); - keyManager.registerKeyListener(this); - } - - @Override - protected void shutDown() throws Exception - { - if (config.syncUsername()) - { - client.getPreferences().setRememberedUsername(usernameCache); - } - - keyManager.unregisterKeyListener(this); - } - - @Provides - LoginScreenConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(LoginScreenConfig.class); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (!config.syncUsername()) - { - return; - } - - if (event.getGameState() == GameState.LOGIN_SCREEN) - { - applyUsername(); - } - else if (event.getGameState() == GameState.LOGGED_IN) - { - String username = ""; - - if (client.getPreferences().getRememberedUsername() != null) - { - username = client.getUsername(); - } - - if (config.username().equals(username)) - { - return; - } - - log.debug("Saving username: {}", username); - config.username(username); - } - } - - @Subscribe - public void onSessionOpen(SessionOpen event) - { - // configuation for the account is available now, so update the username - applyUsername(); - } - - private void applyUsername() - { - if (!config.syncUsername()) - { - return; - } - - GameState gameState = client.getGameState(); - if (gameState == GameState.LOGIN_SCREEN) - { - String username = config.username(); - - if (Strings.isNullOrEmpty(username)) - { - return; - } - - // Save it only once - if (usernameCache == null) - { - usernameCache = client.getPreferences().getRememberedUsername(); - } - - client.getPreferences().setRememberedUsername(username); - } - } - - @Override - public void keyTyped(KeyEvent e) - { - } - - @Override - public void keyPressed(KeyEvent e) - { - if (!config.pasteEnabled() || client.getGameState() != GameState.LOGIN_SCREEN) - { - return; - } - - // enable pasting on macOS with the Command (meta) key - boolean isModifierDown = OSType.getOSType() == OSType.MacOS ? e.isMetaDown() : e.isControlDown(); - - if (e.getKeyCode() == KeyEvent.VK_V && isModifierDown) - { - try - { - final String data = Toolkit - .getDefaultToolkit() - .getSystemClipboard() - .getData(DataFlavor.stringFlavor) - .toString() - .trim(); - - // 0 is username, 1 is password - if (client.getCurrentLoginField() == 0) - { - // Truncate data to maximum username length if necessary - client.setUsername(data.substring(0, Math.min(data.length(), MAX_USERNAME_LENGTH))); - } - else - { - // Truncate data to maximum password length if necessary - client.setPassword(data.substring(0, Math.min(data.length(), MAX_PASSWORD_LENGTH))); - } - } - catch (UnsupportedFlavorException | IOException ex) - { - log.warn("failed to fetch clipboard data", ex); - } - } - } - - @Override - public void keyReleased(KeyEvent e) - { - - } +/* + * Copyright (c) 2017, Seth + * 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.loginscreen; + +import com.google.common.base.Strings; +import com.google.inject.Provides; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.event.KeyEvent; +import java.io.IOException; +import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.events.GameStateChanged; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.OSType; + +@PluginDescriptor( + name = "Login Screen", + description = "Provides various enhancements for login screen" +) +@Slf4j +public class LoginScreenPlugin extends Plugin implements KeyListener +{ + private static final int MAX_USERNAME_LENGTH = 254; + private static final int MAX_PASSWORD_LENGTH = 20; + + @Inject + private Client client; + + @Inject + private LoginScreenConfig config; + + @Inject + private KeyManager keyManager; + + private String usernameCache; + + @Override + protected void startUp() throws Exception + { + applyUsername(); + keyManager.registerKeyListener(this); + } + + @Override + protected void shutDown() throws Exception + { + if (config.syncUsername()) + { + client.getPreferences().setRememberedUsername(usernameCache); + } + + keyManager.unregisterKeyListener(this); + } + + @Provides + LoginScreenConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(LoginScreenConfig.class); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (!config.syncUsername()) + { + return; + } + + if (event.getGameState() == GameState.LOGIN_SCREEN) + { + applyUsername(); + } + else if (event.getGameState() == GameState.LOGGED_IN) + { + String username = ""; + + if (client.getPreferences().getRememberedUsername() != null) + { + username = client.getUsername(); + } + + if (config.username().equals(username)) + { + return; + } + + log.debug("Saving username: {}", username); + config.username(username); + } + } + + @Subscribe + public void onSessionOpen(SessionOpen event) + { + // configuation for the account is available now, so update the username + applyUsername(); + } + + private void applyUsername() + { + if (!config.syncUsername()) + { + return; + } + + GameState gameState = client.getGameState(); + if (gameState == GameState.LOGIN_SCREEN) + { + String username = config.username(); + + if (Strings.isNullOrEmpty(username)) + { + return; + } + + // Save it only once + if (usernameCache == null) + { + usernameCache = client.getPreferences().getRememberedUsername(); + } + + client.getPreferences().setRememberedUsername(username); + } + } + + @Override + public void keyTyped(KeyEvent e) + { + } + + @Override + public void keyPressed(KeyEvent e) + { + if (!config.pasteEnabled() || client.getGameState() != GameState.LOGIN_SCREEN) + { + return; + } + + // enable pasting on macOS with the Command (meta) key + boolean isModifierDown = OSType.getOSType() == OSType.MacOS ? e.isMetaDown() : e.isControlDown(); + + if (e.getKeyCode() == KeyEvent.VK_V && isModifierDown) + { + try + { + final String data = Toolkit + .getDefaultToolkit() + .getSystemClipboard() + .getData(DataFlavor.stringFlavor) + .toString() + .trim(); + + // 0 is username, 1 is password + if (client.getCurrentLoginField() == 0) + { + // Truncate data to maximum username length if necessary + client.setUsername(data.substring(0, Math.min(data.length(), MAX_USERNAME_LENGTH))); + } + else + { + // Truncate data to maximum password length if necessary + client.setPassword(data.substring(0, Math.min(data.length(), MAX_PASSWORD_LENGTH))); + } + } + catch (UnsupportedFlavorException | IOException ex) + { + log.warn("failed to fetch clipboard data", ex); + } + } + } + + @Override + public void keyReleased(KeyEvent e) + { + + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootAssistPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootAssistPlugin.java index 5583bab542..77b4affd86 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootAssistPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootAssistPlugin.java @@ -5,7 +5,6 @@ import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; import net.runelite.api.Actor; import net.runelite.api.AnimationID; -import net.runelite.api.Client; import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.AnimationChanged; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootPile.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootPile.java index 4e2e5125d0..32fa145088 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootPile.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootassist/LootPile.java @@ -2,7 +2,6 @@ package net.runelite.client.plugins.lootassist; import lombok.Getter; import lombok.Setter; -import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; class LootPile diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java index 4b66517489..461e752386 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java @@ -25,6 +25,11 @@ package net.runelite.client.plugins.lootingbagviewer; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.image.BufferedImage; +import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.InventoryID; import net.runelite.api.Item; @@ -36,10 +41,6 @@ import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; import net.runelite.client.ui.overlay.components.PanelComponent; -import javax.inject.Inject; -import java.awt.*; -import java.awt.image.BufferedImage; - class LootingBagViewerOverlay extends Overlay { private static final int INVENTORY_SIZE = 28; @@ -72,7 +73,8 @@ class LootingBagViewerOverlay extends Overlay { if (itemContainer == null) { - if(client.getItemContainer(InventoryID.LOOTING_BAG) != null) { + if (client.getItemContainer(InventoryID.LOOTING_BAG) != null) + { itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); if (itemContainer != null) { @@ -81,7 +83,7 @@ class LootingBagViewerOverlay extends Overlay } return null; } - else if(items != null && client.getItemContainer(InventoryID.LOOTING_BAG) != null) + else if (items != null && client.getItemContainer(InventoryID.LOOTING_BAG) != null) { itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); if (itemContainer != null) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java index ea5922af3f..51f40a8739 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java @@ -1,61 +1,60 @@ -/* - * Copyright (c) 2018 AWPH-I - * 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.lootingbagviewer; - -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.OverlayManager; - -import javax.inject.Inject; - -@PluginDescriptor( - name = "PvP Looting Bag Viewer", - description = "Add an overlay showing the contents of your looting bag", - tags = {"alternate", "items", "overlay", "second"}, - type = PluginType.PVP, - enabledByDefault = false -) -public class LootingBagViewerPlugin extends Plugin -{ - @Inject - private net.runelite.client.plugins.lootingbagviewer.LootingBagViewerOverlay overlay; - - @Inject - private OverlayManager overlayManager; - - @Override - public void startUp() - { - overlayManager.add(overlay); - } - - @Override - public void shutDown() - { - overlayManager.remove(overlay); - } -} +/* + * Copyright (c) 2018 AWPH-I + * 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.lootingbagviewer; + +import javax.inject.Inject; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "PvP Looting Bag Viewer", + description = "Add an overlay showing the contents of your looting bag", + tags = {"alternate", "items", "overlay", "second"}, + type = PluginType.PVP, + enabledByDefault = false +) +public class LootingBagViewerPlugin extends Plugin +{ + @Inject + private net.runelite.client.plugins.lootingbagviewer.LootingBagViewerOverlay overlay; + + @Inject + private OverlayManager overlayManager; + + @Override + public void startUp() + { + overlayManager.add(overlay); + } + + @Override + public void shutDown() + { + overlayManager.remove(overlay); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java index c2f355d7f9..597dcfddf9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java @@ -60,9 +60,9 @@ public interface LootTrackerConfig extends Config } @ConfigItem( - keyName = "chestLootChat", - name = "Show chest loot value in chat", - description = "Show the value of items from CoX/ToB/Barrows chests in chat" + keyName = "chestLootChat", + name = "Show chest loot value in chat", + description = "Show the value of items from CoX/ToB/Barrows chests in chat" ) default boolean chestLootChat() { 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 f561a87a25..77c151bfc4 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 @@ -51,8 +51,8 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; -import net.runelite.api.Item; import net.runelite.api.InventoryID; +import net.runelite.api.Item; import net.runelite.api.ItemComposition; import net.runelite.api.ItemContainer; import net.runelite.api.NPC; @@ -121,7 +121,7 @@ public class LootTrackerPlugin extends Plugin @Inject private ItemManager itemManager; - + @Inject private ChatMessageManager chatMessageManager; @@ -372,16 +372,16 @@ public class LootTrackerPlugin extends Plugin } final ChatMessageBuilder message = new ChatMessageBuilder() - .append(ChatColorType.HIGHLIGHT) - .append("Your loot is worth around ") - .append(StackFormatter.formatNumber(chestPrice)) - .append(" coins.") - .append(ChatColorType.NORMAL); + .append(ChatColorType.HIGHLIGHT) + .append("Your loot is worth around ") + .append(StackFormatter.formatNumber(chestPrice)) + .append(" coins.") + .append(ChatColorType.NORMAL); chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.ITEM_EXAMINE) - .runeLiteFormattedMessage(message.build()) - .build()); + .type(ChatMessageType.ITEM_EXAMINE) + .runeLiteFormattedMessage(message.build()) + .build()); } // Convert container items to array of ItemStack @@ -489,7 +489,7 @@ 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())); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerRecord.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerRecord.java index 0d75ec70c3..df03f7a75b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerRecord.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerRecord.java @@ -1,51 +1,52 @@ -/* - * Copyright (c) 2018, Psikoi - * 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.loottracker; - -import lombok.Value; - -@Value -class LootTrackerRecord -{ - private final String title; - private final String subTitle; - private final LootTrackerItem[] items; - private final long timestamp; - - /** - * Checks if this record matches specified id - * @param id other record id - * @return true if match is made - */ - boolean matches(final String id) - { - if (id == null) - { - return true; - } - - return title.equals(id); - } +/* + * Copyright (c) 2018, Psikoi + * 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.loottracker; + +import lombok.Value; + +@Value +class LootTrackerRecord +{ + private final String title; + private final String subTitle; + private final LootTrackerItem[] items; + private final long timestamp; + + /** + * Checks if this record matches specified id + * + * @param id other record id + * @return true if match is made + */ + boolean matches(final String id) + { + if (id == null) + { + return true; + } + + return title.equals(id); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/MaxHitPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/MaxHitPlugin.java index e9632d1454..88f321cbd5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/MaxHitPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/MaxHitPlugin.java @@ -1,139 +1,138 @@ -/* - * Copyright (c) 2019, Bartvollebregt - * 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.maxhit; - -import net.runelite.api.Client; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemContainer; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.ItemContainerChanged; -import net.runelite.api.events.VarbitChanged; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.maxhit.calculators.MagicMaxHitCalculator; -import net.runelite.client.plugins.maxhit.calculators.MeleeMaxHitCalculator; -import net.runelite.client.plugins.maxhit.calculators.RangeMaxHitCalculator; - -import javax.inject.Inject; - -@PluginDescriptor( - name = "Max Hit", - description = "Max Hit Calculator", - type = PluginType.UTILITY, - enabledByDefault = false -) -public class MaxHitPlugin extends Plugin -{ - - @Inject - private Client client; - - @Subscribe - public void onItemContainerChanged(final ItemContainerChanged event) - { - this.updateMaxHitWidget(); - } - - @Subscribe - public void onConfigChanged(final ConfigChanged event) - { - this.updateMaxHitWidget(); - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - this.updateMaxHitWidget(); - } - - private void updateMaxHitWidget() - { - Widget equipmentStats = client.getWidget(WidgetInfo.EQUIPMENT_INVENTORY_ITEMS_CONTAINER); - - ItemContainer equipmentContainer = client.getItemContainer(InventoryID.EQUIPMENT); - Item[] equipedItems = new Item[14]; - - if (equipmentStats != null && !equipmentStats.isHidden()) - { - if (equipmentContainer != null) - { - equipedItems = equipmentContainer.getItems(); - } - - MeleeMaxHitCalculator meleeMaxHitCalculator = new MeleeMaxHitCalculator(this.client, equipedItems); - RangeMaxHitCalculator rangeMaxHitCalculator = new RangeMaxHitCalculator(this.client, equipedItems); - MagicMaxHitCalculator magicMaxHitCalculator = new MagicMaxHitCalculator(this.client, equipedItems); - - MaxHit maxHit = new MaxHit(meleeMaxHitCalculator.getMaxHit(), rangeMaxHitCalculator.getMaxHit(), magicMaxHitCalculator.getMaxHit()); - this.setWidgetMaxHit(maxHit); - } - } - - private void setWidgetMaxHit(MaxHit maxhit) - { - Widget equipYourCharacter = client.getWidget(WidgetInfo.EQUIP_YOUR_CHARACTER); - String maxHitText = "Melee Max Hit: " + maxhit.getMaxMeleeHit(); - maxHitText += "
Range Max Hit: " + maxhit.getMaxRangeHit(); - maxHitText += "
Magic Max Hit: " + maxhit.getMaxMagicHit(); - - - equipYourCharacter.setText(maxHitText); - } - - private class MaxHit - { - private final double maxMeleeHit; - private final double maxRangeHit; - private final double maxMagicHit; - - MaxHit(double maxMeleeHit, double maxRangeHit, double maxMagicHit) - { - this.maxMeleeHit = maxMeleeHit; - this.maxRangeHit = maxRangeHit; - this.maxMagicHit = maxMagicHit; - } - - double getMaxMeleeHit() - { - return maxMeleeHit; - } - - double getMaxRangeHit() - { - return maxRangeHit; - } - - double getMaxMagicHit() - { - return maxMagicHit; - } - } - -} +/* + * Copyright (c) 2019, Bartvollebregt + * 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.maxhit; + +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.ItemContainerChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.plugins.maxhit.calculators.MagicMaxHitCalculator; +import net.runelite.client.plugins.maxhit.calculators.MeleeMaxHitCalculator; +import net.runelite.client.plugins.maxhit.calculators.RangeMaxHitCalculator; + +@PluginDescriptor( + name = "Max Hit", + description = "Max Hit Calculator", + type = PluginType.UTILITY, + enabledByDefault = false +) +public class MaxHitPlugin extends Plugin +{ + + @Inject + private Client client; + + @Subscribe + public void onItemContainerChanged(final ItemContainerChanged event) + { + this.updateMaxHitWidget(); + } + + @Subscribe + public void onConfigChanged(final ConfigChanged event) + { + this.updateMaxHitWidget(); + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + this.updateMaxHitWidget(); + } + + private void updateMaxHitWidget() + { + Widget equipmentStats = client.getWidget(WidgetInfo.EQUIPMENT_INVENTORY_ITEMS_CONTAINER); + + ItemContainer equipmentContainer = client.getItemContainer(InventoryID.EQUIPMENT); + Item[] equipedItems = new Item[14]; + + if (equipmentStats != null && !equipmentStats.isHidden()) + { + if (equipmentContainer != null) + { + equipedItems = equipmentContainer.getItems(); + } + + MeleeMaxHitCalculator meleeMaxHitCalculator = new MeleeMaxHitCalculator(this.client, equipedItems); + RangeMaxHitCalculator rangeMaxHitCalculator = new RangeMaxHitCalculator(this.client, equipedItems); + MagicMaxHitCalculator magicMaxHitCalculator = new MagicMaxHitCalculator(this.client, equipedItems); + + MaxHit maxHit = new MaxHit(meleeMaxHitCalculator.getMaxHit(), rangeMaxHitCalculator.getMaxHit(), magicMaxHitCalculator.getMaxHit()); + this.setWidgetMaxHit(maxHit); + } + } + + private void setWidgetMaxHit(MaxHit maxhit) + { + Widget equipYourCharacter = client.getWidget(WidgetInfo.EQUIP_YOUR_CHARACTER); + String maxHitText = "Melee Max Hit: " + maxhit.getMaxMeleeHit(); + maxHitText += "
Range Max Hit: " + maxhit.getMaxRangeHit(); + maxHitText += "
Magic Max Hit: " + maxhit.getMaxMagicHit(); + + + equipYourCharacter.setText(maxHitText); + } + + private class MaxHit + { + private final double maxMeleeHit; + private final double maxRangeHit; + private final double maxMagicHit; + + MaxHit(double maxMeleeHit, double maxRangeHit, double maxMagicHit) + { + this.maxMeleeHit = maxMeleeHit; + this.maxRangeHit = maxRangeHit; + this.maxMagicHit = maxMagicHit; + } + + double getMaxMeleeHit() + { + return maxMeleeHit; + } + + double getMaxRangeHit() + { + return maxRangeHit; + } + + double getMaxMagicHit() + { + return maxMagicHit; + } + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/attackstyle/WeaponType.java b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/attackstyle/WeaponType.java index 97ed177f27..a3c30d7dd2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/attackstyle/WeaponType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/attackstyle/WeaponType.java @@ -1,89 +1,97 @@ -/* - * Copyright (c) 2019, Bartvollebregt - * 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.maxhit.attackstyle; - -import java.util.HashMap; -import java.util.Map; - -import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.*; - -public enum WeaponType -{ - TYPE_0(ACCURATE, AGGRESSIVE, null, DEFENSIVE), - TYPE_1(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), - TYPE_2(ACCURATE, AGGRESSIVE, null, DEFENSIVE), - TYPE_3(ACCURATERANGING, RANGING, null, LONGRANGE), - TYPE_4(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), - TYPE_5(ACCURATERANGING, RANGING, null, LONGRANGE), - TYPE_6(AGGRESSIVE, RANGING, DEFENSIVE_CASTING, null), - TYPE_7(ACCURATERANGING, RANGING, null, LONGRANGE), - TYPE_8(OTHER, AGGRESSIVE, null, null), - TYPE_9(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), - TYPE_10(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), - TYPE_11(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), - TYPE_12(CONTROLLED, AGGRESSIVE, null, DEFENSIVE), - TYPE_13(ACCURATE, AGGRESSIVE, null, DEFENSIVE), - TYPE_14(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), - TYPE_15(CONTROLLED, CONTROLLED, CONTROLLED, DEFENSIVE), - TYPE_16(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), - TYPE_17(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), - TYPE_18(ACCURATE, AGGRESSIVE, null, DEFENSIVE, CASTING, DEFENSIVE_CASTING), - TYPE_19(ACCURATERANGING, RANGING, null, LONGRANGE), - TYPE_20(ACCURATE, CONTROLLED, null, DEFENSIVE), - TYPE_21(ACCURATE, AGGRESSIVE, null, DEFENSIVE, CASTING, DEFENSIVE_CASTING), - TYPE_22(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), - TYPE_23(CASTING, CASTING, null, DEFENSIVE_CASTING), - TYPE_24(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), - TYPE_25(CONTROLLED, AGGRESSIVE, null, DEFENSIVE), - TYPE_26(AGGRESSIVE, AGGRESSIVE, null, AGGRESSIVE), - TYPE_27(ACCURATE, null, null, OTHER); - - private static final Map weaponTypes = new HashMap<>(); - - static - { - for (WeaponType weaponType : values()) - { - weaponTypes.put(weaponType.ordinal(), weaponType); - } - } - - private final AttackStyle[] attackStyles; - - WeaponType(AttackStyle... attackStyles) - { - this.attackStyles = attackStyles; - } - - public static WeaponType getWeaponType(int id) - { - return weaponTypes.get(id); - } - - public AttackStyle[] getAttackStyles() - { - return attackStyles; - } -} +/* + * Copyright (c) 2019, Bartvollebregt + * 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.maxhit.attackstyle; + +import java.util.HashMap; +import java.util.Map; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.ACCURATE; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.ACCURATERANGING; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.AGGRESSIVE; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.CASTING; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.CONTROLLED; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.DEFENSIVE; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.DEFENSIVE_CASTING; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.LONGRANGE; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.OTHER; +import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.RANGING; + +public enum WeaponType +{ + TYPE_0(ACCURATE, AGGRESSIVE, null, DEFENSIVE), + TYPE_1(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_2(ACCURATE, AGGRESSIVE, null, DEFENSIVE), + TYPE_3(ACCURATERANGING, RANGING, null, LONGRANGE), + TYPE_4(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_5(ACCURATERANGING, RANGING, null, LONGRANGE), + TYPE_6(AGGRESSIVE, RANGING, DEFENSIVE_CASTING, null), + TYPE_7(ACCURATERANGING, RANGING, null, LONGRANGE), + TYPE_8(OTHER, AGGRESSIVE, null, null), + TYPE_9(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_10(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_11(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_12(CONTROLLED, AGGRESSIVE, null, DEFENSIVE), + TYPE_13(ACCURATE, AGGRESSIVE, null, DEFENSIVE), + TYPE_14(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_15(CONTROLLED, CONTROLLED, CONTROLLED, DEFENSIVE), + TYPE_16(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_17(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_18(ACCURATE, AGGRESSIVE, null, DEFENSIVE, CASTING, DEFENSIVE_CASTING), + TYPE_19(ACCURATERANGING, RANGING, null, LONGRANGE), + TYPE_20(ACCURATE, CONTROLLED, null, DEFENSIVE), + TYPE_21(ACCURATE, AGGRESSIVE, null, DEFENSIVE, CASTING, DEFENSIVE_CASTING), + TYPE_22(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_23(CASTING, CASTING, null, DEFENSIVE_CASTING), + TYPE_24(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_25(CONTROLLED, AGGRESSIVE, null, DEFENSIVE), + TYPE_26(AGGRESSIVE, AGGRESSIVE, null, AGGRESSIVE), + TYPE_27(ACCURATE, null, null, OTHER); + + private static final Map weaponTypes = new HashMap<>(); + + static + { + for (WeaponType weaponType : values()) + { + weaponTypes.put(weaponType.ordinal(), weaponType); + } + } + + private final AttackStyle[] attackStyles; + + WeaponType(AttackStyle... attackStyles) + { + this.attackStyles = attackStyles; + } + + public static WeaponType getWeaponType(int id) + { + return weaponTypes.get(id); + } + + public AttackStyle[] getAttackStyles() + { + return attackStyles; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/calculators/MaxHitCalculator.java b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/calculators/MaxHitCalculator.java index 95cc98a266..d23ad088e1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/calculators/MaxHitCalculator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/calculators/MaxHitCalculator.java @@ -1,178 +1,177 @@ -/* - * Copyright (c) 2019, Bartvollebregt - * 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.maxhit.calculators; - -import net.runelite.api.Client; -import net.runelite.api.Item; -import net.runelite.api.VarPlayer; -import net.runelite.api.Varbits; -import net.runelite.api.widgets.Widget; -import net.runelite.client.plugins.maxhit.attackstyle.AttackStyle; -import net.runelite.client.plugins.maxhit.attackstyle.WeaponType; -import net.runelite.client.plugins.maxhit.config.CustomFormulaConfig; -import net.runelite.client.plugins.maxhit.config.EquipmentBonusConfig; -import net.runelite.client.plugins.maxhit.config.PrayerBonusConfig; -import net.runelite.client.plugins.maxhit.equipment.EquipmentHelper; -import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset; - -import java.util.ArrayList; -import java.util.function.BiFunction; - -public abstract class MaxHitCalculator -{ - - final Client client; - private final CombatMethod combatMethod; - private final Item[] equipedItems; - int baseDamage = 0; - - MaxHitCalculator(Client client, CombatMethod combatMethod, Item[] equipedItems) - { - this.client = client; - this.combatMethod = combatMethod; - this.equipedItems = equipedItems; - } - - protected abstract String getSkillStrengthText(String equipmentText); - - abstract Widget equipmentSkillPower(); - - public abstract double getCurrentSkillPower(); - - AttackStyle getAttackStyle() - { - int equippedWeaponTypeId = client.getVar(Varbits.EQUIPPED_WEAPON_TYPE); - int attackStyleId = client.getVar(VarPlayer.ATTACK_STYLE); - - AttackStyle[] attackStyles = WeaponType.getWeaponType(equippedWeaponTypeId).getAttackStyles(); - - if (attackStyleId < attackStyles.length) - { - AttackStyle attackStyle = attackStyles[attackStyleId]; - if (attackStyle != null) - { - return attackStyle; - } - } - - return AttackStyle.OTHER; - } - - double getPrayerBonus() - { - double bonus = 1; - for (PrayerBonusConfig prayerBonus : PrayerBonusConfig.values()) - { - boolean prayerActive = client.getVar(prayerBonus.getPrayerVarbit()) == 1; - boolean sameCombatMethod = prayerBonus.getCombatMethod() == this.combatMethod; - if (prayerActive && sameCombatMethod) - { - bonus += prayerBonus.getStrengthBonus(); - } - } - return bonus; - } - - double applyEquipmentBonus(double maxhit, EquipmentBonusConfig.BonusType bonusType) - { - double bonus = 1; - ArrayList addList = new ArrayList<>(); - - ArrayList equipmentBonuses = EquipmentBonusConfig.getBonusByType(bonusType); - - for (EquipmentBonusConfig equipmentBonus : equipmentBonuses) - { - EquipmentItemset itemSet = equipmentBonus.getItemset(); - boolean wearsSet = EquipmentHelper.wearsItemSet(this.equipedItems, itemSet); - if (wearsSet && equipmentBonus.meetsRequirements(this.client)) - { - if (equipmentBonus.getOperation() == EquipmentBonusConfig.Operation.MULTIPLY) - { - bonus += equipmentBonus.getBonus(this.combatMethod); - } - else if (equipmentBonus.getOperation() == EquipmentBonusConfig.Operation.ADD) - { - addList.add(equipmentBonus.getBonus(this.combatMethod)); - } - } - } - - maxhit *= bonus; - - maxhit = maxhit + addList.stream().reduce(0.0, Double::sum); - - return maxhit; - } - - public double getMaxHit() - { - BiFunction customFormula = this.getCustomFormula(); - if (customFormula != null) - { - return customFormula.apply(this.client, this); - } - - return this.calculate(); - } - - private BiFunction getCustomFormula() - { - for (CustomFormulaConfig customFormula : CustomFormulaConfig.values()) - { - if (this.combatMethod != customFormula.getRequiredCombatMethod()) - { - continue; - } - - boolean meetsRequirements = customFormula.getRequirements().stream().allMatch(requirement -> requirement.meetsRequirements(this.client)); - - if (meetsRequirements) - { - return customFormula.getCustomFormula(); - } - } - - return null; - } - - public abstract double calculate(); - - public void setBaseDamage(int baseDamage) - { - this.baseDamage = baseDamage; - } - - double getSkillStrength() - { - return Double.parseDouble(this.getSkillStrengthText(this.equipmentSkillPower().getText())); - } - - public enum CombatMethod - { - MELEE, - RANGE, - MAGIC - } -} +/* + * Copyright (c) 2019, Bartvollebregt + * 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.maxhit.calculators; + +import java.util.ArrayList; +import java.util.function.BiFunction; +import net.runelite.api.Client; +import net.runelite.api.Item; +import net.runelite.api.VarPlayer; +import net.runelite.api.Varbits; +import net.runelite.api.widgets.Widget; +import net.runelite.client.plugins.maxhit.attackstyle.AttackStyle; +import net.runelite.client.plugins.maxhit.attackstyle.WeaponType; +import net.runelite.client.plugins.maxhit.config.CustomFormulaConfig; +import net.runelite.client.plugins.maxhit.config.EquipmentBonusConfig; +import net.runelite.client.plugins.maxhit.config.PrayerBonusConfig; +import net.runelite.client.plugins.maxhit.equipment.EquipmentHelper; +import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset; + +public abstract class MaxHitCalculator +{ + + final Client client; + private final CombatMethod combatMethod; + private final Item[] equipedItems; + int baseDamage = 0; + + MaxHitCalculator(Client client, CombatMethod combatMethod, Item[] equipedItems) + { + this.client = client; + this.combatMethod = combatMethod; + this.equipedItems = equipedItems; + } + + protected abstract String getSkillStrengthText(String equipmentText); + + abstract Widget equipmentSkillPower(); + + public abstract double getCurrentSkillPower(); + + AttackStyle getAttackStyle() + { + int equippedWeaponTypeId = client.getVar(Varbits.EQUIPPED_WEAPON_TYPE); + int attackStyleId = client.getVar(VarPlayer.ATTACK_STYLE); + + AttackStyle[] attackStyles = WeaponType.getWeaponType(equippedWeaponTypeId).getAttackStyles(); + + if (attackStyleId < attackStyles.length) + { + AttackStyle attackStyle = attackStyles[attackStyleId]; + if (attackStyle != null) + { + return attackStyle; + } + } + + return AttackStyle.OTHER; + } + + double getPrayerBonus() + { + double bonus = 1; + for (PrayerBonusConfig prayerBonus : PrayerBonusConfig.values()) + { + boolean prayerActive = client.getVar(prayerBonus.getPrayerVarbit()) == 1; + boolean sameCombatMethod = prayerBonus.getCombatMethod() == this.combatMethod; + if (prayerActive && sameCombatMethod) + { + bonus += prayerBonus.getStrengthBonus(); + } + } + return bonus; + } + + double applyEquipmentBonus(double maxhit, EquipmentBonusConfig.BonusType bonusType) + { + double bonus = 1; + ArrayList addList = new ArrayList<>(); + + ArrayList equipmentBonuses = EquipmentBonusConfig.getBonusByType(bonusType); + + for (EquipmentBonusConfig equipmentBonus : equipmentBonuses) + { + EquipmentItemset itemSet = equipmentBonus.getItemset(); + boolean wearsSet = EquipmentHelper.wearsItemSet(this.equipedItems, itemSet); + if (wearsSet && equipmentBonus.meetsRequirements(this.client)) + { + if (equipmentBonus.getOperation() == EquipmentBonusConfig.Operation.MULTIPLY) + { + bonus += equipmentBonus.getBonus(this.combatMethod); + } + else if (equipmentBonus.getOperation() == EquipmentBonusConfig.Operation.ADD) + { + addList.add(equipmentBonus.getBonus(this.combatMethod)); + } + } + } + + maxhit *= bonus; + + maxhit = maxhit + addList.stream().reduce(0.0, Double::sum); + + return maxhit; + } + + public double getMaxHit() + { + BiFunction customFormula = this.getCustomFormula(); + if (customFormula != null) + { + return customFormula.apply(this.client, this); + } + + return this.calculate(); + } + + private BiFunction getCustomFormula() + { + for (CustomFormulaConfig customFormula : CustomFormulaConfig.values()) + { + if (this.combatMethod != customFormula.getRequiredCombatMethod()) + { + continue; + } + + boolean meetsRequirements = customFormula.getRequirements().stream().allMatch(requirement -> requirement.meetsRequirements(this.client)); + + if (meetsRequirements) + { + return customFormula.getCustomFormula(); + } + } + + return null; + } + + public abstract double calculate(); + + public void setBaseDamage(int baseDamage) + { + this.baseDamage = baseDamage; + } + + double getSkillStrength() + { + return Double.parseDouble(this.getSkillStrengthText(this.equipmentSkillPower().getText())); + } + + public enum CombatMethod + { + MELEE, + RANGE, + MAGIC + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/CustomFormulaConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/CustomFormulaConfig.java index b050af543d..3e7ccaef47 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/CustomFormulaConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/CustomFormulaConfig.java @@ -1,233 +1,232 @@ -/* - * Copyright (c) 2019, Bartvollebregt - * 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.maxhit.config; - -import net.runelite.api.Client; -import net.runelite.api.EquipmentInventorySlot; -import net.runelite.api.ItemID; -import net.runelite.api.Skill; -import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator; -import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset; -import net.runelite.client.plugins.maxhit.equipment.EquipmentSlotItem; -import net.runelite.client.plugins.maxhit.requirements.EquipmentItemRequirement; -import net.runelite.client.plugins.maxhit.requirements.EquipmentItemSetRequirement; -import net.runelite.client.plugins.maxhit.requirements.Requirement; -import net.runelite.client.plugins.maxhit.requirements.SpellRequirement; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.function.BiFunction; - -public enum CustomFormulaConfig -{ - - MAGIC_DART( - MaxHitCalculator.CombatMethod.MAGIC, - new ArrayList<>(Arrays.asList( - new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.SLAYERS_STAFF, - ItemID.SLAYERS_STAFF_E - )))), - new SpellRequirement(SpellBaseDamageConfig.MAGIC_DART) - )), - (client, calculator) -> - { - int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); - return Math.floor((magicLevel / 10.0) + 10.0); - } - ), - - TRIDENT_OF_SEAS( - MaxHitCalculator.CombatMethod.MAGIC, - new ArrayList<>(Collections.singletonList( - new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.TRIDENT_OF_THE_SEAS_FULL, - ItemID.TRIDENT_OF_THE_SEAS, - ItemID.TRIDENT_OF_THE_SEAS_E - )))) - )), - (client, calculator) -> - { - int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); - - int baseDamage = (int) Math.floor(magicLevel / 3.0) - 5; - calculator.setBaseDamage(baseDamage); - - return calculator.calculate(); - } - ), - - TRIDENT_OF_SWAMP( - MaxHitCalculator.CombatMethod.MAGIC, - new ArrayList<>(Collections.singletonList( - new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.TRIDENT_OF_THE_SWAMP, - ItemID.TRIDENT_OF_THE_SWAMP_E - )))) - )), - (client, calculator) -> - { - int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); - - int baseDamage = (int) Math.floor(magicLevel / 3.0) - 2; - calculator.setBaseDamage(baseDamage); - - return calculator.calculate(); - } - ), - - SWAMP_LIZARD( - MaxHitCalculator.CombatMethod.MAGIC, - new ArrayList<>(Collections.singletonList( - new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( - ItemID.SWAMP_LIZARD - )))) - )), - (client, calculator) -> - { - int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); - return Math.floor(0.5 + magicLevel * (64.0 + 56.0) / 640.0); - } - ), - - ORANGE_SALAMANDER( - MaxHitCalculator.CombatMethod.MAGIC, - new ArrayList<>(Collections.singletonList( - new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( - ItemID.ORANGE_SALAMANDER - )))) - )), - (client, calculator) -> - { - int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); - return Math.floor(0.5 + magicLevel * (64.0 + 59.0) / 640.0); - } - ), - - RED_SALAMANDER( - MaxHitCalculator.CombatMethod.MAGIC, - new ArrayList<>(Collections.singletonList( - new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( - ItemID.RED_SALAMANDER - )))) - )), - (client, calculator) -> - { - int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); - return Math.floor(0.5 + magicLevel * (64.0 + 77.0) / 640.0); - } - ), - - BLACK_SALAMANDER( - MaxHitCalculator.CombatMethod.MAGIC, - new ArrayList<>(Collections.singletonList( - new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( - ItemID.BLACK_SALAMANDER - )))) - )), - (client, calculator) -> - { - int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); - return Math.floor(0.5 + magicLevel * (64.0 + 92.0) / 640.0); - } - ), - - DHAROK( - MaxHitCalculator.CombatMethod.MELEE, - new ArrayList<>(Collections.singletonList(new EquipmentItemSetRequirement(new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.DHAROKS_HELM, - ItemID.DHAROKS_HELM_100, - ItemID.DHAROKS_HELM_75, - ItemID.DHAROKS_HELM_50, - ItemID.DHAROKS_HELM_25, - ItemID.DHAROKS_HELM_0 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList( - ItemID.DHAROKS_PLATEBODY, - ItemID.DHAROKS_PLATEBODY_100, - ItemID.DHAROKS_PLATEBODY_75, - ItemID.DHAROKS_PLATEBODY_50, - ItemID.DHAROKS_PLATEBODY_25, - ItemID.DHAROKS_PLATEBODY_0 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Arrays.asList( - ItemID.DHAROKS_PLATELEGS, - ItemID.DHAROKS_PLATELEGS_100, - ItemID.DHAROKS_PLATELEGS_75, - ItemID.DHAROKS_PLATELEGS_50, - ItemID.DHAROKS_PLATELEGS_25, - ItemID.DHAROKS_PLATELEGS_0 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.DHAROKS_GREATAXE, - ItemID.DHAROKS_GREATAXE_100, - ItemID.DHAROKS_GREATAXE_75, - ItemID.DHAROKS_GREATAXE_50, - ItemID.DHAROKS_GREATAXE_25, - ItemID.DHAROKS_GREATAXE_0 - ))) - ))))), - (client, calculator) -> - { - int currentHP = client.getBoostedSkillLevel(Skill.HITPOINTS); - int maxHP = client.getRealSkillLevel(Skill.HITPOINTS); - int lostHP = maxHP - currentHP; - - double initialMaxHit = calculator.calculate(); - - double multiplier = (1.0 + ((lostHP / 100.0) * (maxHP / 100.0))); - - return Math.floor(initialMaxHit * multiplier); - } - ); - - private final MaxHitCalculator.CombatMethod requiredCombatMethod; - private final ArrayList requirements; - private final BiFunction customFormula; - - CustomFormulaConfig(MaxHitCalculator.CombatMethod requiredCombatMethod, ArrayList requirements, BiFunction customFormula) - { - this.requiredCombatMethod = requiredCombatMethod; - this.requirements = requirements; - this.customFormula = customFormula; - } - - public MaxHitCalculator.CombatMethod getRequiredCombatMethod() - { - return requiredCombatMethod; - } - - public BiFunction getCustomFormula() - { - return customFormula; - } - - public ArrayList getRequirements() - { - return this.requirements; - } -} +/* + * Copyright (c) 2019, Bartvollebregt + * 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.maxhit.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.function.BiFunction; +import net.runelite.api.Client; +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.api.ItemID; +import net.runelite.api.Skill; +import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator; +import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset; +import net.runelite.client.plugins.maxhit.equipment.EquipmentSlotItem; +import net.runelite.client.plugins.maxhit.requirements.EquipmentItemRequirement; +import net.runelite.client.plugins.maxhit.requirements.EquipmentItemSetRequirement; +import net.runelite.client.plugins.maxhit.requirements.Requirement; +import net.runelite.client.plugins.maxhit.requirements.SpellRequirement; + +public enum CustomFormulaConfig +{ + + MAGIC_DART( + MaxHitCalculator.CombatMethod.MAGIC, + new ArrayList<>(Arrays.asList( + new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.SLAYERS_STAFF, + ItemID.SLAYERS_STAFF_E + )))), + new SpellRequirement(SpellBaseDamageConfig.MAGIC_DART) + )), + (client, calculator) -> + { + int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); + return Math.floor((magicLevel / 10.0) + 10.0); + } + ), + + TRIDENT_OF_SEAS( + MaxHitCalculator.CombatMethod.MAGIC, + new ArrayList<>(Collections.singletonList( + new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.TRIDENT_OF_THE_SEAS_FULL, + ItemID.TRIDENT_OF_THE_SEAS, + ItemID.TRIDENT_OF_THE_SEAS_E + )))) + )), + (client, calculator) -> + { + int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); + + int baseDamage = (int) Math.floor(magicLevel / 3.0) - 5; + calculator.setBaseDamage(baseDamage); + + return calculator.calculate(); + } + ), + + TRIDENT_OF_SWAMP( + MaxHitCalculator.CombatMethod.MAGIC, + new ArrayList<>(Collections.singletonList( + new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.TRIDENT_OF_THE_SWAMP, + ItemID.TRIDENT_OF_THE_SWAMP_E + )))) + )), + (client, calculator) -> + { + int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); + + int baseDamage = (int) Math.floor(magicLevel / 3.0) - 2; + calculator.setBaseDamage(baseDamage); + + return calculator.calculate(); + } + ), + + SWAMP_LIZARD( + MaxHitCalculator.CombatMethod.MAGIC, + new ArrayList<>(Collections.singletonList( + new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( + ItemID.SWAMP_LIZARD + )))) + )), + (client, calculator) -> + { + int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); + return Math.floor(0.5 + magicLevel * (64.0 + 56.0) / 640.0); + } + ), + + ORANGE_SALAMANDER( + MaxHitCalculator.CombatMethod.MAGIC, + new ArrayList<>(Collections.singletonList( + new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( + ItemID.ORANGE_SALAMANDER + )))) + )), + (client, calculator) -> + { + int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); + return Math.floor(0.5 + magicLevel * (64.0 + 59.0) / 640.0); + } + ), + + RED_SALAMANDER( + MaxHitCalculator.CombatMethod.MAGIC, + new ArrayList<>(Collections.singletonList( + new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( + ItemID.RED_SALAMANDER + )))) + )), + (client, calculator) -> + { + int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); + return Math.floor(0.5 + magicLevel * (64.0 + 77.0) / 640.0); + } + ), + + BLACK_SALAMANDER( + MaxHitCalculator.CombatMethod.MAGIC, + new ArrayList<>(Collections.singletonList( + new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( + ItemID.BLACK_SALAMANDER + )))) + )), + (client, calculator) -> + { + int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC); + return Math.floor(0.5 + magicLevel * (64.0 + 92.0) / 640.0); + } + ), + + DHAROK( + MaxHitCalculator.CombatMethod.MELEE, + new ArrayList<>(Collections.singletonList(new EquipmentItemSetRequirement(new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.DHAROKS_HELM, + ItemID.DHAROKS_HELM_100, + ItemID.DHAROKS_HELM_75, + ItemID.DHAROKS_HELM_50, + ItemID.DHAROKS_HELM_25, + ItemID.DHAROKS_HELM_0 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList( + ItemID.DHAROKS_PLATEBODY, + ItemID.DHAROKS_PLATEBODY_100, + ItemID.DHAROKS_PLATEBODY_75, + ItemID.DHAROKS_PLATEBODY_50, + ItemID.DHAROKS_PLATEBODY_25, + ItemID.DHAROKS_PLATEBODY_0 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Arrays.asList( + ItemID.DHAROKS_PLATELEGS, + ItemID.DHAROKS_PLATELEGS_100, + ItemID.DHAROKS_PLATELEGS_75, + ItemID.DHAROKS_PLATELEGS_50, + ItemID.DHAROKS_PLATELEGS_25, + ItemID.DHAROKS_PLATELEGS_0 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.DHAROKS_GREATAXE, + ItemID.DHAROKS_GREATAXE_100, + ItemID.DHAROKS_GREATAXE_75, + ItemID.DHAROKS_GREATAXE_50, + ItemID.DHAROKS_GREATAXE_25, + ItemID.DHAROKS_GREATAXE_0 + ))) + ))))), + (client, calculator) -> + { + int currentHP = client.getBoostedSkillLevel(Skill.HITPOINTS); + int maxHP = client.getRealSkillLevel(Skill.HITPOINTS); + int lostHP = maxHP - currentHP; + + double initialMaxHit = calculator.calculate(); + + double multiplier = (1.0 + ((lostHP / 100.0) * (maxHP / 100.0))); + + return Math.floor(initialMaxHit * multiplier); + } + ); + + private final MaxHitCalculator.CombatMethod requiredCombatMethod; + private final ArrayList requirements; + private final BiFunction customFormula; + + CustomFormulaConfig(MaxHitCalculator.CombatMethod requiredCombatMethod, ArrayList requirements, BiFunction customFormula) + { + this.requiredCombatMethod = requiredCombatMethod; + this.requirements = requirements; + this.customFormula = customFormula; + } + + public MaxHitCalculator.CombatMethod getRequiredCombatMethod() + { + return requiredCombatMethod; + } + + public BiFunction getCustomFormula() + { + return customFormula; + } + + public ArrayList getRequirements() + { + return this.requirements; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/EquipmentBonusConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/EquipmentBonusConfig.java index fce5816c64..dd3bd31268 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/EquipmentBonusConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/config/EquipmentBonusConfig.java @@ -1,418 +1,424 @@ -/* - * Copyright (c) 2019, Bartvollebregt - * 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.maxhit.config; - -import net.runelite.api.Client; -import net.runelite.api.EquipmentInventorySlot; -import net.runelite.api.ItemID; -import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator; -import net.runelite.client.plugins.maxhit.equipment.EquipmentCombatBonus; -import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset; -import net.runelite.client.plugins.maxhit.equipment.EquipmentSlotItem; -import net.runelite.client.plugins.maxhit.requirements.AutocastSpellRequirement; -import net.runelite.client.plugins.maxhit.requirements.Requirement; -import net.runelite.client.plugins.maxhit.requirements.SpellBookRequirement; - -import java.util.*; - - -public enum EquipmentBonusConfig -{ - - /* - * Slayer bonus items - */ - BLACKMASK(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.BLACK_MASK_10, - ItemID.BLACK_MASK_9, - ItemID.BLACK_MASK_8, - ItemID.BLACK_MASK_7, - ItemID.BLACK_MASK_6, - ItemID.BLACK_MASK_5, - ItemID.BLACK_MASK_4, - ItemID.BLACK_MASK_3, - ItemID.BLACK_MASK_2, - ItemID.BLACK_MASK_1, - ItemID.BLACK_MASK - ))) - )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0, 0)), - - SLAYERHELM(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.SLAYER_HELMET, - ItemID.BLACK_SLAYER_HELMET, - ItemID.GREEN_SLAYER_HELMET, - ItemID.RED_SLAYER_HELMET, - ItemID.PURPLE_SLAYER_HELMET, - ItemID.TURQUOISE_SLAYER_HELMET, - ItemID.HYDRA_SLAYER_HELMET - ))) - )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0, 0)), - - BLACKMASKI(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.BLACK_MASK_10_I, - ItemID.BLACK_MASK_9_I, - ItemID.BLACK_MASK_8_I, - ItemID.BLACK_MASK_7_I, - ItemID.BLACK_MASK_6_I, - ItemID.BLACK_MASK_5_I, - ItemID.BLACK_MASK_4_I, - ItemID.BLACK_MASK_3_I, - ItemID.BLACK_MASK_2_I, - ItemID.BLACK_MASK_1_I, - ItemID.BLACK_MASK_I - ))) - )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0.15, 0.15)), - - SLAYERHELMI(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.SLAYER_HELMET_I, - ItemID.BLACK_SLAYER_HELMET_I, - ItemID.GREEN_SLAYER_HELMET_I, - ItemID.RED_SLAYER_HELMET_I, - ItemID.PURPLE_SLAYER_HELMET_I, - ItemID.TURQUOISE_SLAYER_HELMET_I, - ItemID.HYDRA_SLAYER_HELMET_I - ))) - )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0.15, 0.15)), - - /* - * Void bonus items - * */ - MELEEVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.VOID_MELEE_HELM, - ItemID.VOID_MELEE_HELM_11676 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList( - ItemID.VOID_KNIGHT_TOP, - ItemID.VOID_KNIGHT_TOP_10611 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( - ItemID.VOID_KNIGHT_ROBE - ))), - new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( - ItemID.VOID_KNIGHT_GLOVES - ))) - )), new EquipmentCombatBonus(0.1, 0, 0)), - - RANGERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.VOID_RANGER_HELM, - ItemID.VOID_RANGER_HELM_11675 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList( - ItemID.VOID_KNIGHT_TOP, - ItemID.VOID_KNIGHT_TOP_10611 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( - ItemID.VOID_KNIGHT_ROBE - ))), - new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( - ItemID.VOID_KNIGHT_GLOVES - ))) - )), new EquipmentCombatBonus(0, 0.1, 0)), - - - ELITEMELEERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.VOID_MELEE_HELM, - ItemID.VOID_MELEE_HELM_11676 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( - ItemID.ELITE_VOID_TOP - ))), - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( - ItemID.ELITE_VOID_ROBE - ))), - new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( - ItemID.VOID_KNIGHT_GLOVES - ))) - )), new EquipmentCombatBonus(0.125, 0, 0)), - - - ELITERANGERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.VOID_RANGER_HELM, - ItemID.VOID_RANGER_HELM_11675 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( - ItemID.ELITE_VOID_TOP - ))), - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( - ItemID.ELITE_VOID_ROBE - ))), - new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( - ItemID.VOID_KNIGHT_GLOVES - ))) - )), new EquipmentCombatBonus(0, 0.125, 0)), - - ELITEMAGICVOID(BonusType.EQUIPMENT, new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( - ItemID.VOID_MAGE_HELM, - ItemID.VOID_MAGE_HELM_11674 - ))), - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( - ItemID.ELITE_VOID_TOP - ))), - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( - ItemID.ELITE_VOID_ROBE - ))), - new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( - ItemID.VOID_KNIGHT_GLOVES - ))) - )), new EquipmentCombatBonus(0, 0, 0.025)), - - /* - * Special Melee Equipment - * */ - OBISIDIAN(BonusType.SPECIAL, new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Collections.singletonList( - ItemID.OBSIDIAN_HELMET - ))), - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( - ItemID.OBSIDIAN_PLATEBODY - ))), - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( - ItemID.OBSIDIAN_PLATELEGS - ))), - new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.TOKTZXILAK, - ItemID.TOKTZXILEK, - ItemID.TZHAARKETEM, - ItemID.TZHAARKETOM, - ItemID.TOKTZXILAK_20554 - ))) - )), new EquipmentCombatBonus(0.1, 0, 0)), - - BERSERKERNECKLACE(BonusType.SPECIAL, new EquipmentItemset(Arrays.asList( - new EquipmentSlotItem(EquipmentInventorySlot.AMULET, new ArrayList<>(Collections.singletonList(ItemID.BERSERKER_NECKLACE))), - new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.TOKTZXILAK, - ItemID.TOKTZXILEK, - ItemID.TZHAARKETEM, - ItemID.TZHAARKETOM, - ItemID.TOKTZXILAK_20554 - ))) - )), new EquipmentCombatBonus(0.2, 0, 0)), - - - /* - * Magic Equipment - */ - ANCESTRAL_HAT(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Collections.singletonList( - ItemID.ANCESTRAL_HAT - ))) - )), new EquipmentCombatBonus(0, 0, 0.02)), - - ANCESTRAL_ROBE_TOP(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( - ItemID.ANCESTRAL_ROBE_TOP - ))) - )), new EquipmentCombatBonus(0, 0, 0.02)), - - ANCESTRAL_ROBE_BOTTOM(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( - ItemID.ANCESTRAL_ROBE_BOTTOM - ))) - )), new EquipmentCombatBonus(0, 0, 0.02)), - - IMBUED_GOD_CAPE(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.CAPE, new ArrayList<>(Arrays.asList( - ItemID.IMBUED_SARADOMIN_MAX_CAPE, - ItemID.IMBUED_SARADOMIN_CAPE, - ItemID.IMBUED_ZAMORAK_MAX_CAPE, - ItemID.IMBUED_ZAMORAK_CAPE, - ItemID.IMBUED_GUTHIX_MAX_CAPE, - ItemID.IMBUED_GUTHIX_CAPE - ))) - )), new EquipmentCombatBonus(0, 0, 0.02)), - - KODAI_WAND(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( - ItemID.KODAI_WAND - ))) - )), new EquipmentCombatBonus(0, 0, 0.15)), - - OCCULT_NECKLACE(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.AMULET, new ArrayList<>(Arrays.asList( - ItemID.OCCULT_NECKLACE, - ItemID.OCCULT_NECKLACE_OR - ))) - )), new EquipmentCombatBonus(0, 0, 0.10)), - - STAFF_OF_THE_DEAD(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.STAFF_OF_THE_DEAD, - ItemID.TOXIC_STAFF_OF_THE_DEAD, - ItemID.STAFF_OF_LIGHT - ))) - )), new EquipmentCombatBonus(0, 0, 0.15)), - - TORMENTED_BRACELET(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( - ItemID.TORMENTED_BRACELET - ))) - )), new EquipmentCombatBonus(0, 0, 0.05)), - - SMOKE_STAFF(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( - ItemID.SMOKE_BATTLESTAFF, - ItemID.MYSTIC_SMOKE_STAFF - ))) - )), new EquipmentCombatBonus(0, 0, 0.10), Collections.singletonList(new SpellBookRequirement(SpellBaseDamageConfig.SpellBook.NORMAL))), - - - /* - * Special magic bonusses - * */ - - CHAOS_GAUNTLETS(BonusType.SPECIAL, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( - ItemID.CHAOS_GAUNTLETS - ))))), - new EquipmentCombatBonus(0, 0, 3), - Collections.singletonList( - new AutocastSpellRequirement(new ArrayList<>(Arrays.asList( - SpellBaseDamageConfig.AIR_BOLT, - SpellBaseDamageConfig.WATER_BOLT, - SpellBaseDamageConfig.EARTH_BOLT, - SpellBaseDamageConfig.FIRE_BOLT - ))) - ), - Operation.ADD - ), - - TOME_OF_FIRE(BonusType.MAGIC_SPECIAL, new EquipmentItemset(Collections.singletonList( - new EquipmentSlotItem(EquipmentInventorySlot.SHIELD, new ArrayList<>(Collections.singletonList( - ItemID.TOME_OF_FIRE - ))))), - new EquipmentCombatBonus(0, 0, 0.5), - Collections.singletonList( - new AutocastSpellRequirement(new ArrayList<>(Arrays.asList( - SpellBaseDamageConfig.FIRE_BLAST, - SpellBaseDamageConfig.FIRE_BOLT, - SpellBaseDamageConfig.FIRE_STRIKE, - SpellBaseDamageConfig.FIRE_SURGE, - SpellBaseDamageConfig.FIRE_WAVE - ))) - ) - ); - - - private static final Map> bonusTypes = new HashMap<>(); - - static - { - for (EquipmentBonusConfig equipmentBonus : values()) - { - BonusType bonusType = equipmentBonus.bonusType; - if (!bonusTypes.containsKey(bonusType)) - { - bonusTypes.put(bonusType, new ArrayList<>()); - } - ArrayList list = bonusTypes.get(bonusType); - list.add(equipmentBonus); - bonusTypes.put(bonusType, list); - } - } - - private final EquipmentItemset itemset; - private BonusType bonusType; - private EquipmentCombatBonus equipmentCombatBonus; - private List requirements = new ArrayList<>(); - private Operation operation = Operation.MULTIPLY; - EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus) - { - this.bonusType = bonusType; - this.itemset = itemset; - this.equipmentCombatBonus = equipmentCombatBonus; - } - EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus, List requirements) - { - this.bonusType = bonusType; - this.itemset = itemset; - this.equipmentCombatBonus = equipmentCombatBonus; - this.requirements = requirements; - } - - EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus, List requirements, Operation operation) - { - this.bonusType = bonusType; - this.itemset = itemset; - this.equipmentCombatBonus = equipmentCombatBonus; - this.requirements = requirements; - this.operation = operation; - } - - public static ArrayList getBonusByType(BonusType bonusType) - { - if (!bonusTypes.containsKey(bonusType)) - { - return new ArrayList<>(); - } - return bonusTypes.get(bonusType); - } - - public EquipmentItemset getItemset() - { - return itemset; - } - - public Operation getOperation() - { - return operation; - } - - public double getBonus(MaxHitCalculator.CombatMethod combatMethod) - { - return this.equipmentCombatBonus.getCombatBonus(combatMethod); - } - - public boolean meetsRequirements(Client client) - { - return requirements.stream().allMatch(requirement -> requirement.meetsRequirements(client)); - } - - public enum BonusType - { - EQUIPMENT, - SLAYER, - VOID_KNIGHT, - SPECIAL, - MAGIC_SPECIAL - } - - public enum Operation - { - ADD, - MULTIPLY - } - -} - +/* + * Copyright (c) 2019, Bartvollebregt + * 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.maxhit.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.runelite.api.Client; +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.api.ItemID; +import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator; +import net.runelite.client.plugins.maxhit.equipment.EquipmentCombatBonus; +import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset; +import net.runelite.client.plugins.maxhit.equipment.EquipmentSlotItem; +import net.runelite.client.plugins.maxhit.requirements.AutocastSpellRequirement; +import net.runelite.client.plugins.maxhit.requirements.Requirement; +import net.runelite.client.plugins.maxhit.requirements.SpellBookRequirement; + + +public enum EquipmentBonusConfig +{ + + /* + * Slayer bonus items + */ + BLACKMASK(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.BLACK_MASK_10, + ItemID.BLACK_MASK_9, + ItemID.BLACK_MASK_8, + ItemID.BLACK_MASK_7, + ItemID.BLACK_MASK_6, + ItemID.BLACK_MASK_5, + ItemID.BLACK_MASK_4, + ItemID.BLACK_MASK_3, + ItemID.BLACK_MASK_2, + ItemID.BLACK_MASK_1, + ItemID.BLACK_MASK + ))) + )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0, 0)), + + SLAYERHELM(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.SLAYER_HELMET, + ItemID.BLACK_SLAYER_HELMET, + ItemID.GREEN_SLAYER_HELMET, + ItemID.RED_SLAYER_HELMET, + ItemID.PURPLE_SLAYER_HELMET, + ItemID.TURQUOISE_SLAYER_HELMET, + ItemID.HYDRA_SLAYER_HELMET + ))) + )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0, 0)), + + BLACKMASKI(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.BLACK_MASK_10_I, + ItemID.BLACK_MASK_9_I, + ItemID.BLACK_MASK_8_I, + ItemID.BLACK_MASK_7_I, + ItemID.BLACK_MASK_6_I, + ItemID.BLACK_MASK_5_I, + ItemID.BLACK_MASK_4_I, + ItemID.BLACK_MASK_3_I, + ItemID.BLACK_MASK_2_I, + ItemID.BLACK_MASK_1_I, + ItemID.BLACK_MASK_I + ))) + )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0.15, 0.15)), + + SLAYERHELMI(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.SLAYER_HELMET_I, + ItemID.BLACK_SLAYER_HELMET_I, + ItemID.GREEN_SLAYER_HELMET_I, + ItemID.RED_SLAYER_HELMET_I, + ItemID.PURPLE_SLAYER_HELMET_I, + ItemID.TURQUOISE_SLAYER_HELMET_I, + ItemID.HYDRA_SLAYER_HELMET_I + ))) + )), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0.15, 0.15)), + + /* + * Void bonus items + * */ + MELEEVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.VOID_MELEE_HELM, + ItemID.VOID_MELEE_HELM_11676 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList( + ItemID.VOID_KNIGHT_TOP, + ItemID.VOID_KNIGHT_TOP_10611 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( + ItemID.VOID_KNIGHT_ROBE + ))), + new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( + ItemID.VOID_KNIGHT_GLOVES + ))) + )), new EquipmentCombatBonus(0.1, 0, 0)), + + RANGERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.VOID_RANGER_HELM, + ItemID.VOID_RANGER_HELM_11675 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList( + ItemID.VOID_KNIGHT_TOP, + ItemID.VOID_KNIGHT_TOP_10611 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( + ItemID.VOID_KNIGHT_ROBE + ))), + new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( + ItemID.VOID_KNIGHT_GLOVES + ))) + )), new EquipmentCombatBonus(0, 0.1, 0)), + + + ELITEMELEERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.VOID_MELEE_HELM, + ItemID.VOID_MELEE_HELM_11676 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( + ItemID.ELITE_VOID_TOP + ))), + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( + ItemID.ELITE_VOID_ROBE + ))), + new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( + ItemID.VOID_KNIGHT_GLOVES + ))) + )), new EquipmentCombatBonus(0.125, 0, 0)), + + + ELITERANGERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.VOID_RANGER_HELM, + ItemID.VOID_RANGER_HELM_11675 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( + ItemID.ELITE_VOID_TOP + ))), + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( + ItemID.ELITE_VOID_ROBE + ))), + new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( + ItemID.VOID_KNIGHT_GLOVES + ))) + )), new EquipmentCombatBonus(0, 0.125, 0)), + + ELITEMAGICVOID(BonusType.EQUIPMENT, new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList( + ItemID.VOID_MAGE_HELM, + ItemID.VOID_MAGE_HELM_11674 + ))), + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( + ItemID.ELITE_VOID_TOP + ))), + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( + ItemID.ELITE_VOID_ROBE + ))), + new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( + ItemID.VOID_KNIGHT_GLOVES + ))) + )), new EquipmentCombatBonus(0, 0, 0.025)), + + /* + * Special Melee Equipment + * */ + OBISIDIAN(BonusType.SPECIAL, new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Collections.singletonList( + ItemID.OBSIDIAN_HELMET + ))), + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( + ItemID.OBSIDIAN_PLATEBODY + ))), + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( + ItemID.OBSIDIAN_PLATELEGS + ))), + new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.TOKTZXILAK, + ItemID.TOKTZXILEK, + ItemID.TZHAARKETEM, + ItemID.TZHAARKETOM, + ItemID.TOKTZXILAK_20554 + ))) + )), new EquipmentCombatBonus(0.1, 0, 0)), + + BERSERKERNECKLACE(BonusType.SPECIAL, new EquipmentItemset(Arrays.asList( + new EquipmentSlotItem(EquipmentInventorySlot.AMULET, new ArrayList<>(Collections.singletonList(ItemID.BERSERKER_NECKLACE))), + new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.TOKTZXILAK, + ItemID.TOKTZXILEK, + ItemID.TZHAARKETEM, + ItemID.TZHAARKETOM, + ItemID.TOKTZXILAK_20554 + ))) + )), new EquipmentCombatBonus(0.2, 0, 0)), + + + /* + * Magic Equipment + */ + ANCESTRAL_HAT(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Collections.singletonList( + ItemID.ANCESTRAL_HAT + ))) + )), new EquipmentCombatBonus(0, 0, 0.02)), + + ANCESTRAL_ROBE_TOP(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList( + ItemID.ANCESTRAL_ROBE_TOP + ))) + )), new EquipmentCombatBonus(0, 0, 0.02)), + + ANCESTRAL_ROBE_BOTTOM(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList( + ItemID.ANCESTRAL_ROBE_BOTTOM + ))) + )), new EquipmentCombatBonus(0, 0, 0.02)), + + IMBUED_GOD_CAPE(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.CAPE, new ArrayList<>(Arrays.asList( + ItemID.IMBUED_SARADOMIN_MAX_CAPE, + ItemID.IMBUED_SARADOMIN_CAPE, + ItemID.IMBUED_ZAMORAK_MAX_CAPE, + ItemID.IMBUED_ZAMORAK_CAPE, + ItemID.IMBUED_GUTHIX_MAX_CAPE, + ItemID.IMBUED_GUTHIX_CAPE + ))) + )), new EquipmentCombatBonus(0, 0, 0.02)), + + KODAI_WAND(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList( + ItemID.KODAI_WAND + ))) + )), new EquipmentCombatBonus(0, 0, 0.15)), + + OCCULT_NECKLACE(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.AMULET, new ArrayList<>(Arrays.asList( + ItemID.OCCULT_NECKLACE, + ItemID.OCCULT_NECKLACE_OR + ))) + )), new EquipmentCombatBonus(0, 0, 0.10)), + + STAFF_OF_THE_DEAD(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.STAFF_OF_THE_DEAD, + ItemID.TOXIC_STAFF_OF_THE_DEAD, + ItemID.STAFF_OF_LIGHT + ))) + )), new EquipmentCombatBonus(0, 0, 0.15)), + + TORMENTED_BRACELET(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( + ItemID.TORMENTED_BRACELET + ))) + )), new EquipmentCombatBonus(0, 0, 0.05)), + + SMOKE_STAFF(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList( + ItemID.SMOKE_BATTLESTAFF, + ItemID.MYSTIC_SMOKE_STAFF + ))) + )), new EquipmentCombatBonus(0, 0, 0.10), Collections.singletonList(new SpellBookRequirement(SpellBaseDamageConfig.SpellBook.NORMAL))), + + + /* + * Special magic bonusses + * */ + + CHAOS_GAUNTLETS(BonusType.SPECIAL, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList( + ItemID.CHAOS_GAUNTLETS + ))))), + new EquipmentCombatBonus(0, 0, 3), + Collections.singletonList( + new AutocastSpellRequirement(new ArrayList<>(Arrays.asList( + SpellBaseDamageConfig.AIR_BOLT, + SpellBaseDamageConfig.WATER_BOLT, + SpellBaseDamageConfig.EARTH_BOLT, + SpellBaseDamageConfig.FIRE_BOLT + ))) + ), + Operation.ADD + ), + + TOME_OF_FIRE(BonusType.MAGIC_SPECIAL, new EquipmentItemset(Collections.singletonList( + new EquipmentSlotItem(EquipmentInventorySlot.SHIELD, new ArrayList<>(Collections.singletonList( + ItemID.TOME_OF_FIRE + ))))), + new EquipmentCombatBonus(0, 0, 0.5), + Collections.singletonList( + new AutocastSpellRequirement(new ArrayList<>(Arrays.asList( + SpellBaseDamageConfig.FIRE_BLAST, + SpellBaseDamageConfig.FIRE_BOLT, + SpellBaseDamageConfig.FIRE_STRIKE, + SpellBaseDamageConfig.FIRE_SURGE, + SpellBaseDamageConfig.FIRE_WAVE + ))) + ) + ); + + + private static final Map> bonusTypes = new HashMap<>(); + + static + { + for (EquipmentBonusConfig equipmentBonus : values()) + { + BonusType bonusType = equipmentBonus.bonusType; + if (!bonusTypes.containsKey(bonusType)) + { + bonusTypes.put(bonusType, new ArrayList<>()); + } + ArrayList list = bonusTypes.get(bonusType); + list.add(equipmentBonus); + bonusTypes.put(bonusType, list); + } + } + + private final EquipmentItemset itemset; + private BonusType bonusType; + private EquipmentCombatBonus equipmentCombatBonus; + private List requirements = new ArrayList<>(); + private Operation operation = Operation.MULTIPLY; + + EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus) + { + this.bonusType = bonusType; + this.itemset = itemset; + this.equipmentCombatBonus = equipmentCombatBonus; + } + + EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus, List requirements) + { + this.bonusType = bonusType; + this.itemset = itemset; + this.equipmentCombatBonus = equipmentCombatBonus; + this.requirements = requirements; + } + + EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus, List requirements, Operation operation) + { + this.bonusType = bonusType; + this.itemset = itemset; + this.equipmentCombatBonus = equipmentCombatBonus; + this.requirements = requirements; + this.operation = operation; + } + + public static ArrayList getBonusByType(BonusType bonusType) + { + if (!bonusTypes.containsKey(bonusType)) + { + return new ArrayList<>(); + } + return bonusTypes.get(bonusType); + } + + public EquipmentItemset getItemset() + { + return itemset; + } + + public Operation getOperation() + { + return operation; + } + + public double getBonus(MaxHitCalculator.CombatMethod combatMethod) + { + return this.equipmentCombatBonus.getCombatBonus(combatMethod); + } + + public boolean meetsRequirements(Client client) + { + return requirements.stream().allMatch(requirement -> requirement.meetsRequirements(client)); + } + + public enum BonusType + { + EQUIPMENT, + SLAYER, + VOID_KNIGHT, + SPECIAL, + MAGIC_SPECIAL + } + + public enum Operation + { + ADD, + MULTIPLY + } + +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/equipment/EquipmentSlotItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/equipment/EquipmentSlotItem.java index dbc44b3a53..2f4fb844b3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/equipment/EquipmentSlotItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/equipment/EquipmentSlotItem.java @@ -1,51 +1,50 @@ -/* - * Copyright (c) 2019, Bartvollebregt - * 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.maxhit.equipment; - -import net.runelite.api.EquipmentInventorySlot; - -import java.util.ArrayList; - -public class EquipmentSlotItem -{ - private final EquipmentInventorySlot equipmentSlot; - private final ArrayList itemIds; - - public EquipmentSlotItem(EquipmentInventorySlot equipmentSlot, ArrayList itemIds) - { - this.equipmentSlot = equipmentSlot; - this.itemIds = itemIds; - } - - public ArrayList getItems() - { - return this.itemIds; - } - - public EquipmentInventorySlot getEquipmentSlot() - { - return this.equipmentSlot; - } -} +/* + * Copyright (c) 2019, Bartvollebregt + * 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.maxhit.equipment; + +import java.util.ArrayList; +import net.runelite.api.EquipmentInventorySlot; + +public class EquipmentSlotItem +{ + private final EquipmentInventorySlot equipmentSlot; + private final ArrayList itemIds; + + public EquipmentSlotItem(EquipmentInventorySlot equipmentSlot, ArrayList itemIds) + { + this.equipmentSlot = equipmentSlot; + this.itemIds = itemIds; + } + + public ArrayList getItems() + { + return this.itemIds; + } + + public EquipmentInventorySlot getEquipmentSlot() + { + return this.equipmentSlot; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/requirements/AutocastSpellRequirement.java b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/requirements/AutocastSpellRequirement.java index 988e459631..f7a0162cf8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/requirements/AutocastSpellRequirement.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/maxhit/requirements/AutocastSpellRequirement.java @@ -1,58 +1,57 @@ -/* - * Copyright (c) 2019, Bartvollebregt - * 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.maxhit.requirements; - -import net.runelite.api.Client; -import net.runelite.api.Varbits; -import net.runelite.client.plugins.maxhit.config.SpellBaseDamageConfig; - -import java.util.ArrayList; - -public class AutocastSpellRequirement implements Requirement -{ - - private final ArrayList autocastSpells; - - public AutocastSpellRequirement(ArrayList autocastSpells) - { - this.autocastSpells = autocastSpells; - } - - @Override - public boolean meetsRequirements(Client client) - { - int autoCastSpellId = client.getVar(Varbits.AUTO_CAST_SPELL); - - if (autoCastSpellId == 0) - { - - return false; - - } - - return this.autocastSpells.stream().anyMatch(spell -> spell.getSpellID() == autoCastSpellId); - - } -} +/* + * Copyright (c) 2019, Bartvollebregt + * 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.maxhit.requirements; + +import java.util.ArrayList; +import net.runelite.api.Client; +import net.runelite.api.Varbits; +import net.runelite.client.plugins.maxhit.config.SpellBaseDamageConfig; + +public class AutocastSpellRequirement implements Requirement +{ + + private final ArrayList autocastSpells; + + public AutocastSpellRequirement(ArrayList autocastSpells) + { + this.autocastSpells = autocastSpells; + } + + @Override + public boolean meetsRequirements(Client client) + { + int autoCastSpellId = client.getVar(Varbits.AUTO_CAST_SPELL); + + if (autoCastSpellId == 0) + { + + return false; + + } + + return this.autocastSpells.stream().anyMatch(spell -> spell.getSpellID() == autoCastSpellId); + + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java index a7bc841eb9..fbfe53c822 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java @@ -100,7 +100,7 @@ public interface MenuEntrySwapperConfig extends Config ) default boolean swapContract() { - return true; + return true; } @ConfigItem( @@ -123,7 +123,7 @@ public interface MenuEntrySwapperConfig extends Config return true; } - @ConfigItem( + @ConfigItem( keyName = "swapDarkMage", name = "Repairs", description = "Swap Talk-to with Repairs for Dark Mage" @@ -282,14 +282,14 @@ public interface MenuEntrySwapperConfig extends Config { return true; } - + @ConfigItem( keyName = "rockCake", name = "Rock Cake Guzzle", description = "Enables Left Click Guzzle to Rock Cake" ) - default boolean rockCake() - { + default boolean rockCake() + { return false; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index da2c02260f..0308323471 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -363,7 +363,7 @@ public class MenuEntrySwapperPlugin extends Plugin final int eventId = event.getIdentifier(); final String option = Text.removeTags(event.getOption()).toLowerCase(); final String target = Text.removeTags(event.getTarget()).toLowerCase(); - final NPC hintArrowNpc = client.getHintArrowNpc(); + final NPC hintArrowNpc = client.getHintArrowNpc(); if (hintArrowNpc != null && hintArrowNpc.getIndex() == eventId @@ -451,32 +451,32 @@ public class MenuEntrySwapperPlugin extends Plugin swap(client, "quick-travel", option, target, true); } } - + else if (config.swapTravel() && option.equals("pass") && target.equals("energy barrier")) { swap(client, "pay-toll(2-ecto)", option, target, true); } - + else if (config.swapTravel() && option.equals("open") && target.equals("gate")) { swap(client, "pay-toll(10gp)", option, target, true); } - + else if (config.swapTravel() && option.equals("inspect") && target.equals("trapdoor")) { swap(client, "travel", option, target, true); } - + else if (config.swapHarpoon() && option.equals("cage")) { swap(client, "harpoon", option, target, true); } - + else if (config.swapHarpoon() && (option.equals("big net") || option.equals("net"))) { swap(client, "harpoon", option, target, true); } - + else if (config.swapHomePortal() != HouseMode.ENTER && option.equals("enter")) { switch (config.swapHomePortal()) @@ -504,76 +504,76 @@ public class MenuEntrySwapperPlugin extends Plugin swap(client, "configure", option, target, false); } } - + else if (config.swapFairyRing() == FairyRingMode.ZANARIS && option.equals("tree")) { swap(client, "zanaris", option, target, false); } - + else if (config.swapBoxTrap() && (option.equals("check") || option.equals("dismantle"))) { swap(client, "reset", option, target, true); } - + else if (config.swapBoxTrap() && option.equals("take")) { swap(client, "lay", option, target, true); } - + else if (config.swapChase() && option.equals("pick-up")) { swap(client, "chase", option, target, true); } - + else if (config.swapBirdhouseEmpty() && option.equals("interact") && target.contains("birdhouse")) { swap(client, "empty", option, target, true); } - + else if (config.swapQuick() && option.equals("ring")) { swap(client, "quick-start", option, target, true); } - + else if (config.swapQuick() && option.equals("pass")) { swap(client, "quick-pass", option, target, true); swap(client, "quick pass", option, target, true); } - + else if (config.swapQuick() && option.equals("open")) { swap(client, "quick-open", option, target, true); } - + else if (config.swapAdmire() && option.equals("admire")) { swap(client, "teleport", option, target, true); swap(client, "spellbook", option, target, true); swap(client, "perks", option, target, true); } - + else if (config.swapPrivate() && option.equals("shared")) { swap(client, "private", option, target, true); } - + else if (config.swapPick() && option.equals("pick")) { swap(client, "pick-lots", option, target, true); } - + else if (config.swapRogueschests() && target.contains("chest")) { swap(client, "search for traps", option, target, true); } - + else if (config.rockCake() && option.equals("eat")) { swap(client, "guzzle", option, target, true); } - - + + else if (config.shiftClickCustomization() && shiftModifier && !option.equals("use")) { Integer customOption = getSwapConfig(eventId); @@ -583,7 +583,7 @@ public class MenuEntrySwapperPlugin extends Plugin swap(client, "use", option, target, true); } } - + // Put all item-related swapping after shift-click else if (config.swapTeleportItem() && option.equals("wear")) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menumodifier/MenuModifierConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menumodifier/MenuModifierConfig.java index beef23cfd2..b67d393a3d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menumodifier/MenuModifierConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menumodifier/MenuModifierConfig.java @@ -31,37 +31,49 @@ import net.runelite.client.config.ConfigItem; @ConfigGroup("menumodifier") public interface MenuModifierConfig extends Config { - @ConfigItem( - position = 0, + @ConfigItem( + position = 0, keyName = "hideExamine", name = "Hide Examine", description = "Hides the 'examine' option from the right click menu" ) - default boolean hideExamine() { return true; } + default boolean hideExamine() + { + return true; + } - @ConfigItem( - position = 1, + @ConfigItem( + position = 1, keyName = "hideTradeWith", name = "Hide Trade With", description = "Hides the 'trade with' option from the right click menu" ) - default boolean hideTradeWith() { return true; } + default boolean hideTradeWith() + { + return true; + } - @ConfigItem( - position = 2, + @ConfigItem( + position = 2, keyName = "hideReport", name = "Hide Report", description = "Hides the 'report' option from the right click menu" ) - default boolean hideReport() { return true; } + default boolean hideReport() + { + return true; + } - @ConfigItem( - position = 3, + @ConfigItem( + position = 3, keyName = "hideLookup", name = "Hide Lookup", description = "Hides the 'lookup' option from the right click menu" ) - default boolean hideLookup() { return true; } + default boolean hideLookup() + { + return true; + } @ConfigItem( position = 4, @@ -69,7 +81,10 @@ public interface MenuModifierConfig extends Config name = "Hide Net", description = "Hides the 'net' option from the right click menu" ) - default boolean hideNet() { return true; } + default boolean hideNet() + { + return true; + } @ConfigItem( position = 5, @@ -77,5 +92,8 @@ public interface MenuModifierConfig extends Config name = "Hide Bait", description = "Hides the 'Bait' option from the right click menu" ) - default boolean hideBait() { return true; } + default boolean hideBait() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningOverlay.java index 55a4997509..fb93301723 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningOverlay.java @@ -1,122 +1,130 @@ -/* - * Copyright (c) 2018, Seth - * 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.mining; - -import com.google.common.collect.ImmutableSet; -import net.runelite.api.Client; -import net.runelite.client.plugins.mining.MiningConfig; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -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 javax.inject.Inject; -import java.awt.*; -import java.time.Duration; -import java.time.Instant; -import java.util.Set; - -import static net.runelite.api.AnimationID.*; - -class MiningOverlay extends Overlay -{ - private static final Set MINING_ANIMATION_IDS = ImmutableSet.of( - MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL, - MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT, - MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_DRAGON, MINING_MOTHERLODE_DRAGON_ORN, - MINING_MOTHERLODE_INFERNAL - ); - - private final Client client; - private final MiningPlugin plugin; - private final MiningConfig config; - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - MiningOverlay(Client client, MiningPlugin plugin, MiningConfig config) - { - setPosition(OverlayPosition.TOP_LEFT); - this.client = client; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isInMlm() || !config.showMiningStats()) - { - return null; - } - - MiningSession session = plugin.getSession(); - - if (session.getLastPayDirtMined() == null) - { - return null; - } - - Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(session.getLastPayDirtMined(), Instant.now()); - - if (sinceCut.compareTo(statTimeout) >= 0) - { - return null; - } - - panelComponent.getChildren().clear(); - - if (config.showMiningState()) - { - if (MINING_ANIMATION_IDS.contains(client.getLocalPlayer().getAnimation())) - { - panelComponent.getChildren().add(TitleComponent.builder() - .text("Mining") - .color(Color.GREEN) - .build()); - } - else - { - panelComponent.getChildren().add(TitleComponent.builder() - .text("NOT mining") - .color(Color.RED) - .build()); - } - } - - panelComponent.getChildren().add(LineComponent.builder() - .left("Pay-dirt mined:") - .right(Integer.toString(session.getTotalMined())) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Pay-dirt/hr:") - .right(session.getRecentMined() > 2 ? Integer.toString(session.getPerHour()) : "") - .build()); - - return panelComponent.render(graphics); - } -} +/* + * Copyright (c) 2018, Seth + * 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.mining; + +import com.google.common.collect.ImmutableSet; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.time.Duration; +import java.time.Instant; +import java.util.Set; +import javax.inject.Inject; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_ADAMANT; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BLACK; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BRONZE; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_ORN; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_INFERNAL; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_IRON; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_MITHRIL; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_RUNE; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_STEEL; +import net.runelite.api.Client; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +class MiningOverlay extends Overlay +{ + private static final Set MINING_ANIMATION_IDS = ImmutableSet.of( + MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL, + MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT, + MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_DRAGON, MINING_MOTHERLODE_DRAGON_ORN, + MINING_MOTHERLODE_INFERNAL + ); + + private final Client client; + private final MiningPlugin plugin; + private final MiningConfig config; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + MiningOverlay(Client client, MiningPlugin plugin, MiningConfig config) + { + setPosition(OverlayPosition.TOP_LEFT); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isInMlm() || !config.showMiningStats()) + { + return null; + } + + MiningSession session = plugin.getSession(); + + if (session.getLastPayDirtMined() == null) + { + return null; + } + + Duration statTimeout = Duration.ofMinutes(config.statTimeout()); + Duration sinceCut = Duration.between(session.getLastPayDirtMined(), Instant.now()); + + if (sinceCut.compareTo(statTimeout) >= 0) + { + return null; + } + + panelComponent.getChildren().clear(); + + if (config.showMiningState()) + { + if (MINING_ANIMATION_IDS.contains(client.getLocalPlayer().getAnimation())) + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("Mining") + .color(Color.GREEN) + .build()); + } + else + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("NOT mining") + .color(Color.RED) + .build()); + } + } + + panelComponent.getChildren().add(LineComponent.builder() + .left("Pay-dirt mined:") + .right(Integer.toString(session.getTotalMined())) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Pay-dirt/hr:") + .right(session.getRecentMined() > 2 ? Integer.toString(session.getPerHour()) : "") + .build()); + + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java index e8f0691f8d..d8aec0d7a5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java @@ -28,25 +28,33 @@ package net.runelite.client.plugins.mining; import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; +import java.time.temporal.ChronoUnit; +import java.util.HashSet; +import java.util.Set; +import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; -import net.runelite.api.*; -import net.runelite.api.events.*; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.GameState; +import net.runelite.api.ItemID; +import static net.runelite.api.ObjectID.ORE_VEIN_26661; +import static net.runelite.api.ObjectID.ORE_VEIN_26662; +import static net.runelite.api.ObjectID.ORE_VEIN_26663; +import static net.runelite.api.ObjectID.ORE_VEIN_26664; +import net.runelite.api.WallObject; +import net.runelite.api.events.GameObjectChanged; +import net.runelite.api.events.GameObjectDespawned; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GameStateChanged; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.mining.MiningConfig; import net.runelite.client.task.Schedule; import net.runelite.client.ui.overlay.OverlayManager; -import javax.inject.Inject; -import java.time.temporal.ChronoUnit; -import java.util.HashSet; -import java.util.Set; - -import static net.runelite.api.ObjectID.*; @PluginDescriptor( name = "Mining", @@ -60,13 +68,13 @@ public class MiningPlugin extends Plugin private static final Set MOTHERLODE_MAP_REGIONS = ImmutableSet.of(14679, 14680, 14681, 14935, 14936, 14937, 15191, 15192, 15193); private static final Set MINE_SPOTS = ImmutableSet.of(ORE_VEIN_26661, ORE_VEIN_26662, ORE_VEIN_26663, ORE_VEIN_26664); private static final Set MLM_ORE_TYPES = ImmutableSet.of(ItemID.RUNITE_ORE, ItemID.ADAMANTITE_ORE, - ItemID.MITHRIL_ORE, ItemID.GOLD_ORE, ItemID.COAL, ItemID.GOLDEN_NUGGET); + ItemID.MITHRIL_ORE, ItemID.GOLD_ORE, ItemID.COAL, ItemID.GOLDEN_NUGGET); private static final Set MINING_ROCKS = ImmutableSet.of( - // another website says depleted rocks are 7468, 7469 - // website says stoney 2902, 2962, 2963, 2964, - 2231, 2257, 2584, 2704, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 3805, 3806, 3807, 3808, 4437, 4438, 4676, 6669, 6670, 6671, 6672, 6673, 7453, 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, 7464, 7467, 7470, 7484, 7485, 7486, 7487, 7488, 7489, 7490, 7491, 7492, 7493, 7494, 7495, 8727, 8828, 8829, 8830, 10079, 10080, 10081, 11441, 11924, 12590, 15127, 15128, 15213, 16464, 16514, 16515, 16521, 16522, 16523, 16524, 16534, 16535, 16545, 16549, 16550, 16998, 16999, 17042, 17043, 17064, 17065, 18817, 18840, 18952, 18953, 18954, 18961, 19849, 19969, 19970, 19971, 19972, 19973, 22665, 22667, 23280, 23281, 23640, 24146, 24147, 24148, 24557, 26873, 26874, 27984, 27985, 27987, 27988, 28596, 28597, 28752, 28753, 28890 - //2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2231, 2257, 2328, 3042, 3043, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 4676, 6943, 6944, 6945, 6946, 6947, 6948, 9296, 9297, 9303, 9304, 9305, 9306, 9316, 9317, 9331, 9332, 9335, 9336, 9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, 9734, 9735, 9736, 9737, 10583, 10584, 10585, 10586, 10587, 10944, 10945, 10946, 10947, 10948, 10949, 11165, 11166, 11167, 11168, 11169, 11170, 11171, 11172, 11173, 11174, 11175, 11176, 11177, 11178, 11179, 11180, 11181, 11182, 11183, 11184, 11185, 11186, 11187, 11188, 11189, 11190, 11191, 11192, 11193, 11194, 11195, 11424, 11425, 11426, 11427, 11428, 11429, 11430, 11431, 11432, 11433, 11434, 11435, 11436, 11437, 11438, 11439, 11440, 11441, 11442, 11443, 11444, 11552, 11553, 11554, 11555, 11556, 11557, 11915, 11916, 11917, 11918, 11919, 11920, 11921, 11922, 11923, 11924, 11925, 11926, 11927, 11928, 11929, 11930, 11931, 11932, 11933, 11934, 11935, 11936, 11937, 11938, 11939, 11940, 11941, 11942, 11943, 11944, 11945, 11946, 11947, 11948, 11949, 11950, 11951, 11952, 11953, 11954, 11955, 11956, 11957, 11958, 11959, 11960, 11961, 11962, 11963, 11964, 11965 - //968, 1480, 1855, 4043, 4487, 7533, 9716, 21250, 1997, 2581, 2582, 2694, 2695, 2696, 2697, 2835, 2836, 2837, 2901, 2965, 3339, 3364, 4526, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4887, 5604, 5605, 5606, 5844, 5845, 5896, 5985, 5987, 6622, 6623, 6707, 6708, 6709, 7466, 8725, 8726, 8950, 8951, 8952, 9031, 9032, 10036, 10782, 10783, 10784, 10785, 10786, 10787, 10788, 11097, 11098, 11182, 11183, 11424, 11425, 12564, 12565, 12566, 12567, 12588, 12589, 12774, 14814, 14815, 14816, 14817, 15198, 15199, 15217, 15218, 15219, 15410, 15536, 15537, 16077, 16078, 16079, 16080, 16115, 16136, 16284, 16303, 17350, 17351, 17352, 17353, 17354, 17355, 17356, 17357, 17358, 17364, 17365, 17366, 17679, 17958, 17959, 17960, 17970, 17971, 17972, 18871, 18872, 18873, 19131, 21571, 21572, 21573, 22549, 22550, 22551, 23124, 23125, 23126, 23127, 23165, 23976, 23977, 23978, 23979, 23980, 23981, 24693, 24694, 24695, 24696, 24697, 24698, 24699, 24700, 24701, 24781, 25158, 25159, 25160, 25422, 25423, 26372, 26373, 26376, 26377, 26850, 26856, 28580, 29102, 29883, 29884, 29885, 30344, 30519, 30521, 30522, 30857, 30858, 31045, 31781, 31782, 31783, 31784, 31785, 31786, 31787, 31788, 31789 + // another website says depleted rocks are 7468, 7469 + // website says stoney 2902, 2962, 2963, 2964, + 2231, 2257, 2584, 2704, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 3805, 3806, 3807, 3808, 4437, 4438, 4676, 6669, 6670, 6671, 6672, 6673, 7453, 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, 7464, 7467, 7470, 7484, 7485, 7486, 7487, 7488, 7489, 7490, 7491, 7492, 7493, 7494, 7495, 8727, 8828, 8829, 8830, 10079, 10080, 10081, 11441, 11924, 12590, 15127, 15128, 15213, 16464, 16514, 16515, 16521, 16522, 16523, 16524, 16534, 16535, 16545, 16549, 16550, 16998, 16999, 17042, 17043, 17064, 17065, 18817, 18840, 18952, 18953, 18954, 18961, 19849, 19969, 19970, 19971, 19972, 19973, 22665, 22667, 23280, 23281, 23640, 24146, 24147, 24148, 24557, 26873, 26874, 27984, 27985, 27987, 27988, 28596, 28597, 28752, 28753, 28890 + //2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2231, 2257, 2328, 3042, 3043, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 4676, 6943, 6944, 6945, 6946, 6947, 6948, 9296, 9297, 9303, 9304, 9305, 9306, 9316, 9317, 9331, 9332, 9335, 9336, 9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, 9734, 9735, 9736, 9737, 10583, 10584, 10585, 10586, 10587, 10944, 10945, 10946, 10947, 10948, 10949, 11165, 11166, 11167, 11168, 11169, 11170, 11171, 11172, 11173, 11174, 11175, 11176, 11177, 11178, 11179, 11180, 11181, 11182, 11183, 11184, 11185, 11186, 11187, 11188, 11189, 11190, 11191, 11192, 11193, 11194, 11195, 11424, 11425, 11426, 11427, 11428, 11429, 11430, 11431, 11432, 11433, 11434, 11435, 11436, 11437, 11438, 11439, 11440, 11441, 11442, 11443, 11444, 11552, 11553, 11554, 11555, 11556, 11557, 11915, 11916, 11917, 11918, 11919, 11920, 11921, 11922, 11923, 11924, 11925, 11926, 11927, 11928, 11929, 11930, 11931, 11932, 11933, 11934, 11935, 11936, 11937, 11938, 11939, 11940, 11941, 11942, 11943, 11944, 11945, 11946, 11947, 11948, 11949, 11950, 11951, 11952, 11953, 11954, 11955, 11956, 11957, 11958, 11959, 11960, 11961, 11962, 11963, 11964, 11965 + //968, 1480, 1855, 4043, 4487, 7533, 9716, 21250, 1997, 2581, 2582, 2694, 2695, 2696, 2697, 2835, 2836, 2837, 2901, 2965, 3339, 3364, 4526, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4887, 5604, 5605, 5606, 5844, 5845, 5896, 5985, 5987, 6622, 6623, 6707, 6708, 6709, 7466, 8725, 8726, 8950, 8951, 8952, 9031, 9032, 10036, 10782, 10783, 10784, 10785, 10786, 10787, 10788, 11097, 11098, 11182, 11183, 11424, 11425, 12564, 12565, 12566, 12567, 12588, 12589, 12774, 14814, 14815, 14816, 14817, 15198, 15199, 15217, 15218, 15219, 15410, 15536, 15537, 16077, 16078, 16079, 16080, 16115, 16136, 16284, 16303, 17350, 17351, 17352, 17353, 17354, 17355, 17356, 17357, 17358, 17364, 17365, 17366, 17679, 17958, 17959, 17960, 17970, 17971, 17972, 18871, 18872, 18873, 19131, 21571, 21572, 21573, 22549, 22550, 22551, 23124, 23125, 23126, 23127, 23165, 23976, 23977, 23978, 23979, 23980, 23981, 24693, 24694, 24695, 24696, 24697, 24698, 24699, 24700, 24701, 24781, 25158, 25159, 25160, 25422, 25423, 26372, 26373, 26376, 26377, 26850, 26856, 28580, 29102, 29883, 29884, 29885, 30344, 30519, 30521, 30522, 30857, 30858, 31045, 31781, 31782, 31783, 31784, 31785, 31786, 31787, 31788, 31789 ); private static final int MAX_INVENTORY_SIZE = 28; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningRocksOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningRocksOverlay.java index 25408b5a13..daff203b28 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningRocksOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningRocksOverlay.java @@ -1,110 +1,115 @@ -/* - * Copyright (c) 2018, Seth - * Copyright (c) 2018, Adam - * Copyright (c) 2018, Lars - * 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.mining; - -import net.runelite.api.Point; -import net.runelite.api.*; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.plugins.mining.MiningConfig; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; - -import javax.inject.Inject; -import java.awt.*; -import java.awt.image.BufferedImage; - -class MiningRocksOverlay extends Overlay -{ - private static final int MAX_DISTANCE = 2350; - - private final Client client; - private final MiningPlugin plugin; - private final MiningConfig config; - - private final BufferedImage miningIcon; - - @Inject - MiningRocksOverlay(Client client, MiningPlugin plugin, MiningConfig config, SkillIconManager iconManager) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.client = client; - this.plugin = plugin; - this.config = config; - - miningIcon = iconManager.getSkillImage(Skill.MINING); - } - - @Override - public Dimension render(Graphics2D graphics) - { - Player local = client.getLocalPlayer(); - - renderTiles(graphics, local); - - return null; - } - - private void renderTiles(Graphics2D graphics, Player local) - { - LocalPoint localLocation = local.getLocalLocation(); - - if (config.showMiningRocks()) { - for (GameObject rock : plugin.getRocks()) { - - LocalPoint location = rock.getLocalLocation(); - if (localLocation.distanceTo(location) <= MAX_DISTANCE) { - renderMiningRock(graphics, rock); - } - } - } - - } - - private void renderMiningRock(Graphics2D graphics, GameObject rock) - { - Point canvasLoc = Perspective.getCanvasImageLocation(client, rock.getLocalLocation(), miningIcon, 0); - if (canvasLoc != null) - { - graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null); - } - } - -// private void renderMiningRockSquare(Graphics2D graphics, GameObject rock) -// { -// Polygon poly = Perspective.getCanvasTilePoly(client, rock.getLocalLocation()); -// -// if (poly != null) -// { -// OverlayUtil.renderPolygon(graphics, poly, Color.red); -// } -// } - -} +/* + * Copyright (c) 2018, Seth + * Copyright (c) 2018, Adam + * Copyright (c) 2018, Lars + * 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.mining; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.Perspective; +import net.runelite.api.Player; +import net.runelite.api.Point; +import net.runelite.api.Skill; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.game.SkillIconManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +class MiningRocksOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2350; + + private final Client client; + private final MiningPlugin plugin; + private final MiningConfig config; + + private final BufferedImage miningIcon; + + @Inject + MiningRocksOverlay(Client client, MiningPlugin plugin, MiningConfig config, SkillIconManager iconManager) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.client = client; + this.plugin = plugin; + this.config = config; + + miningIcon = iconManager.getSkillImage(Skill.MINING); + } + + @Override + public Dimension render(Graphics2D graphics) + { + Player local = client.getLocalPlayer(); + + renderTiles(graphics, local); + + return null; + } + + private void renderTiles(Graphics2D graphics, Player local) + { + LocalPoint localLocation = local.getLocalLocation(); + + if (config.showMiningRocks()) + { + for (GameObject rock : plugin.getRocks()) + { + + LocalPoint location = rock.getLocalLocation(); + if (localLocation.distanceTo(location) <= MAX_DISTANCE) + { + renderMiningRock(graphics, rock); + } + } + } + + } + + private void renderMiningRock(Graphics2D graphics, GameObject rock) + { + Point canvasLoc = Perspective.getCanvasImageLocation(client, rock.getLocalLocation(), miningIcon, 0); + if (canvasLoc != null) + { + graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null); + } + } + +// private void renderMiningRockSquare(Graphics2D graphics, GameObject rock) +// { +// Polygon poly = Perspective.getCanvasTilePoly(client, rock.getLocalLocation()); +// +// if (poly != null) +// { +// OverlayUtil.renderPolygon(graphics, poly, Color.red); +// } +// } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningSession.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningSession.java index 890e2453b7..fbe975f630 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningSession.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningSession.java @@ -1,140 +1,139 @@ -/* - * Copyright (c) 2018, Seth - * 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.mining; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ItemID; - -import java.time.Duration; -import java.time.Instant; - -@Slf4j -public class MiningSession -{ - private static final Duration HOUR = Duration.ofHours(1); - - private int perHour; - - private Instant lastPayDirtMined; - private int totalMined; - - private Instant recentPayDirtMined; - private int recentMined; - - @Getter(AccessLevel.PACKAGE) - private Instant lastGemFound; - - @Getter(AccessLevel.PACKAGE) - private int diamondsFound; - - @Getter(AccessLevel.PACKAGE) - private int rubiesFound; - - @Getter(AccessLevel.PACKAGE) - private int emeraldsFound; - - @Getter(AccessLevel.PACKAGE) - private int sapphiresFound; - - public void incrementGemFound(int gemID) - { - lastGemFound = Instant.now(); - - switch (gemID) - { - case ItemID.UNCUT_DIAMOND: - diamondsFound++; - break; - - case ItemID.UNCUT_RUBY: - rubiesFound++; - break; - - case ItemID.UNCUT_EMERALD: - emeraldsFound++; - break; - - case ItemID.UNCUT_SAPPHIRE: - sapphiresFound++; - break; - - default: - log.error("Invalid gem type specified. The gem count will not be incremented."); - } - } - - public void incrementPayDirtMined() - { - Instant now = Instant.now(); - - lastPayDirtMined = now; - ++totalMined; - - if (recentMined == 0) - { - recentPayDirtMined = now; - } - ++recentMined; - - Duration timeSinceStart = Duration.between(recentPayDirtMined, now); - if (!timeSinceStart.isZero()) - { - perHour = (int) ((double) recentMined * (double) HOUR.toMillis() / (double) timeSinceStart.toMillis()); - } - } - - public void resetRecent() - { - recentPayDirtMined = null; - recentMined = 0; - } - - public int getPerHour() - { - return perHour; - } - - public Instant getLastPayDirtMined() - { - return lastPayDirtMined; - } - - public int getTotalMined() - { - return totalMined; - } - - public Instant getRecentPayDirtMined() - { - return recentPayDirtMined; - } - - public int getRecentMined() - { - return recentMined; - } -} +/* + * Copyright (c) 2018, Seth + * 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.mining; + +import java.time.Duration; +import java.time.Instant; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ItemID; + +@Slf4j +public class MiningSession +{ + private static final Duration HOUR = Duration.ofHours(1); + + private int perHour; + + private Instant lastPayDirtMined; + private int totalMined; + + private Instant recentPayDirtMined; + private int recentMined; + + @Getter(AccessLevel.PACKAGE) + private Instant lastGemFound; + + @Getter(AccessLevel.PACKAGE) + private int diamondsFound; + + @Getter(AccessLevel.PACKAGE) + private int rubiesFound; + + @Getter(AccessLevel.PACKAGE) + private int emeraldsFound; + + @Getter(AccessLevel.PACKAGE) + private int sapphiresFound; + + public void incrementGemFound(int gemID) + { + lastGemFound = Instant.now(); + + switch (gemID) + { + case ItemID.UNCUT_DIAMOND: + diamondsFound++; + break; + + case ItemID.UNCUT_RUBY: + rubiesFound++; + break; + + case ItemID.UNCUT_EMERALD: + emeraldsFound++; + break; + + case ItemID.UNCUT_SAPPHIRE: + sapphiresFound++; + break; + + default: + log.error("Invalid gem type specified. The gem count will not be incremented."); + } + } + + public void incrementPayDirtMined() + { + Instant now = Instant.now(); + + lastPayDirtMined = now; + ++totalMined; + + if (recentMined == 0) + { + recentPayDirtMined = now; + } + ++recentMined; + + Duration timeSinceStart = Duration.between(recentPayDirtMined, now); + if (!timeSinceStart.isZero()) + { + perHour = (int) ((double) recentMined * (double) HOUR.toMillis() / (double) timeSinceStart.toMillis()); + } + } + + public void resetRecent() + { + recentPayDirtMined = null; + recentMined = 0; + } + + public int getPerHour() + { + return perHour; + } + + public Instant getLastPayDirtMined() + { + return lastPayDirtMined; + } + + public int getTotalMined() + { + return totalMined; + } + + public Instant getRecentPayDirtMined() + { + return recentPayDirtMined; + } + + public int getRecentMined() + { + return recentMined; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java index 8a2ad81cdf..d1811106c9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java @@ -1,124 +1,133 @@ -/* - * Copyright (c) 2018, Seth - * 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.motherlode; - -import com.google.common.collect.ImmutableSet; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.time.Duration; -import java.time.Instant; -import java.util.Set; -import javax.inject.Inject; -import static net.runelite.api.AnimationID.*; -import net.runelite.api.Client; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -class MotherlodeOverlay extends Overlay -{ - private static final Set MINING_ANIMATION_IDS = ImmutableSet.of( - MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL, - MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT, - MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_DRAGON, MINING_MOTHERLODE_DRAGON_ORN, - MINING_MOTHERLODE_INFERNAL - ); - - private final Client client; - private final MotherlodePlugin plugin; - private final MotherlodeSession motherlodeSession; - private final MotherlodeConfig config; - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - MotherlodeOverlay(Client client, MotherlodePlugin plugin, MotherlodeSession motherlodeSession, MotherlodeConfig config) - { - super(plugin); - setPosition(OverlayPosition.TOP_LEFT); - this.client = client; - this.plugin = plugin; - this.motherlodeSession = motherlodeSession; - this.config = config; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isInMlm() || !config.showMiningStats()) - { - return null; - } - - MotherlodeSession session = motherlodeSession; - - if (session.getLastPayDirtMined() == null) - { - return null; - } - - Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(session.getLastPayDirtMined(), Instant.now()); - - if (sinceCut.compareTo(statTimeout) >= 0) - { - return null; - } - - panelComponent.getChildren().clear(); - - if (config.showMiningState()) - { - if (MINING_ANIMATION_IDS.contains(client.getLocalPlayer().getAnimation())) - { - panelComponent.getChildren().add(TitleComponent.builder() - .text("Mining") - .color(Color.GREEN) - .build()); - } - else - { - panelComponent.getChildren().add(TitleComponent.builder() - .text("NOT mining") - .color(Color.RED) - .build()); - } - } - - panelComponent.getChildren().add(LineComponent.builder() - .left("Pay-dirt mined:") - .right(Integer.toString(session.getTotalMined())) - .build()); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Pay-dirt/hr:") - .right(session.getRecentMined() > 2 ? Integer.toString(session.getPerHour()) : "") - .build()); - - return panelComponent.render(graphics); - } -} +/* + * Copyright (c) 2018, Seth + * 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.motherlode; + +import com.google.common.collect.ImmutableSet; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.time.Duration; +import java.time.Instant; +import java.util.Set; +import javax.inject.Inject; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_ADAMANT; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BLACK; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BRONZE; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_ORN; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_INFERNAL; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_IRON; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_MITHRIL; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_RUNE; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_STEEL; +import net.runelite.api.Client; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +class MotherlodeOverlay extends Overlay +{ + private static final Set MINING_ANIMATION_IDS = ImmutableSet.of( + MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL, + MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT, + MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_DRAGON, MINING_MOTHERLODE_DRAGON_ORN, + MINING_MOTHERLODE_INFERNAL + ); + + private final Client client; + private final MotherlodePlugin plugin; + private final MotherlodeSession motherlodeSession; + private final MotherlodeConfig config; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + MotherlodeOverlay(Client client, MotherlodePlugin plugin, MotherlodeSession motherlodeSession, MotherlodeConfig config) + { + super(plugin); + setPosition(OverlayPosition.TOP_LEFT); + this.client = client; + this.plugin = plugin; + this.motherlodeSession = motherlodeSession; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isInMlm() || !config.showMiningStats()) + { + return null; + } + + MotherlodeSession session = motherlodeSession; + + if (session.getLastPayDirtMined() == null) + { + return null; + } + + Duration statTimeout = Duration.ofMinutes(config.statTimeout()); + Duration sinceCut = Duration.between(session.getLastPayDirtMined(), Instant.now()); + + if (sinceCut.compareTo(statTimeout) >= 0) + { + return null; + } + + panelComponent.getChildren().clear(); + + if (config.showMiningState()) + { + if (MINING_ANIMATION_IDS.contains(client.getLocalPlayer().getAnimation())) + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("Mining") + .color(Color.GREEN) + .build()); + } + else + { + panelComponent.getChildren().add(TitleComponent.builder() + .text("NOT mining") + .color(Color.RED) + .build()); + } + } + + panelComponent.getChildren().add(LineComponent.builder() + .left("Pay-dirt mined:") + .right(Integer.toString(session.getTotalMined())) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Pay-dirt/hr:") + .right(session.getRecentMined() > 2 ? Integer.toString(session.getPerHour()) : "") + .build()); + + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeRocksOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeRocksOverlay.java index e49ae1006d..e80b967168 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeRocksOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeRocksOverlay.java @@ -1,142 +1,140 @@ -/* - * Copyright (c) 2018, Seth - * Copyright (c) 2018, Adam - * Copyright (c) 2018, Lars - * 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.motherlode; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.image.BufferedImage; -import javax.inject.Inject; - -import ch.qos.logback.core.net.SyslogOutputStream; -import net.runelite.api.Client; -import net.runelite.api.GameObject; -import net.runelite.api.Perspective; -import net.runelite.api.Player; -import net.runelite.api.Point; -import net.runelite.api.Skill; -import net.runelite.api.WallObject; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; - -class MotherlodeRocksOverlay extends Overlay -{ - private static final int MAX_DISTANCE = 2350; - - private final Client client; - private final MotherlodePlugin plugin; - private final MotherlodeConfig config; - - private final BufferedImage miningIcon; - - @Inject - MotherlodeRocksOverlay(Client client, MotherlodePlugin plugin, MotherlodeConfig config, SkillIconManager iconManager) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.client = client; - this.plugin = plugin; - this.config = config; - - miningIcon = iconManager.getSkillImage(Skill.MINING); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if ((!config.showVeins() && !config.showRockFalls()) || !plugin.isInMlm()) - { - return null; - } - - Player local = client.getLocalPlayer(); - - renderTiles(graphics, local); - - return null; - } - - private void renderTiles(Graphics2D graphics, Player local) - { - LocalPoint localLocation = local.getLocalLocation(); - - if (config.showVeins()) - { - for (WallObject vein : plugin.getVeins()) - { - LocalPoint location = vein.getLocalLocation(); - if (localLocation.distanceTo(location) <= MAX_DISTANCE) - { - // Only draw veins on the same level - if (plugin.isUpstairs(localLocation) == plugin.isUpstairs(vein.getLocalLocation())) - { - renderVein(graphics, vein); - } - } - } - } - - if (config.showRockFalls()) - { - for (GameObject rock : plugin.getRocks()) - { - LocalPoint location = rock.getLocalLocation(); - if (localLocation.distanceTo(location) <= MAX_DISTANCE) - { - plugin.checkMining(); - renderRock(graphics, rock); - } - } - } - - } - - private void renderVein(Graphics2D graphics, WallObject vein) - { - Point canvasLoc = Perspective.getCanvasImageLocation(client, vein.getLocalLocation(), miningIcon, 150); - - if (canvasLoc != null) - { - graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null); - } - } - - private void renderRock(Graphics2D graphics, GameObject rock) - { - Polygon poly = Perspective.getCanvasTilePoly(client, rock.getLocalLocation()); - - if (poly != null) - { - OverlayUtil.renderPolygon(graphics, poly, Color.red); - } - } -} +/* + * Copyright (c) 2018, Seth + * Copyright (c) 2018, Adam + * Copyright (c) 2018, Lars + * 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.motherlode; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.Perspective; +import net.runelite.api.Player; +import net.runelite.api.Point; +import net.runelite.api.Skill; +import net.runelite.api.WallObject; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.game.SkillIconManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; + +class MotherlodeRocksOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2350; + + private final Client client; + private final MotherlodePlugin plugin; + private final MotherlodeConfig config; + + private final BufferedImage miningIcon; + + @Inject + MotherlodeRocksOverlay(Client client, MotherlodePlugin plugin, MotherlodeConfig config, SkillIconManager iconManager) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.client = client; + this.plugin = plugin; + this.config = config; + + miningIcon = iconManager.getSkillImage(Skill.MINING); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if ((!config.showVeins() && !config.showRockFalls()) || !plugin.isInMlm()) + { + return null; + } + + Player local = client.getLocalPlayer(); + + renderTiles(graphics, local); + + return null; + } + + private void renderTiles(Graphics2D graphics, Player local) + { + LocalPoint localLocation = local.getLocalLocation(); + + if (config.showVeins()) + { + for (WallObject vein : plugin.getVeins()) + { + LocalPoint location = vein.getLocalLocation(); + if (localLocation.distanceTo(location) <= MAX_DISTANCE) + { + // Only draw veins on the same level + if (plugin.isUpstairs(localLocation) == plugin.isUpstairs(vein.getLocalLocation())) + { + renderVein(graphics, vein); + } + } + } + } + + if (config.showRockFalls()) + { + for (GameObject rock : plugin.getRocks()) + { + LocalPoint location = rock.getLocalLocation(); + if (localLocation.distanceTo(location) <= MAX_DISTANCE) + { + plugin.checkMining(); + renderRock(graphics, rock); + } + } + } + + } + + private void renderVein(Graphics2D graphics, WallObject vein) + { + Point canvasLoc = Perspective.getCanvasImageLocation(client, vein.getLocalLocation(), miningIcon, 150); + + if (canvasLoc != null) + { + graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null); + } + } + + private void renderRock(Graphics2D graphics, GameObject rock) + { + Polygon poly = Perspective.getCanvasTilePoly(client, rock.getLocalLocation()); + + if (poly != null) + { + OverlayUtil.renderPolygon(graphics, poly, Color.red); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java index aa4d16c738..8d823f40e8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java @@ -60,7 +60,7 @@ public class GraveyardRoom extends MTARoom @Inject private GraveyardRoom(MTAConfig config, Client client, MTAPlugin plugin, - ItemManager itemManager, InfoBoxManager infoBoxManager) + ItemManager itemManager, InfoBoxManager infoBoxManager) { super(config); this.client = client; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/telekinetic/TelekineticRoom.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/telekinetic/TelekineticRoom.java index 96d7847321..99ea9b777a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/telekinetic/TelekineticRoom.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/telekinetic/TelekineticRoom.java @@ -134,8 +134,8 @@ public class TelekineticRoom extends MTARoom public void onGameTick(GameTick event) { if (!config.telekinetic() - || !inside() - || client.getGameState() != GameState.LOGGED_IN) + || !inside() + || client.getGameState() != GameState.LOGGED_IN) { maze = null; moves.clear(); @@ -374,7 +374,7 @@ public class TelekineticRoom extends MTARoom WorldPoint nghbWorld = WorldPoint.fromLocal(client, neighbour); if (!nghbWorld.equals(next) - && !closed.contains(nghbWorld)) + && !closed.contains(nghbWorld)) { int score = scores.get(next) + 1; @@ -426,10 +426,10 @@ public class TelekineticRoom extends MTARoom private LocalPoint[] neighbours(LocalPoint point) { return new LocalPoint[] - { - neighbour(point, Direction.NORTH), neighbour(point, Direction.SOUTH), - neighbour(point, Direction.EAST), neighbour(point, Direction.WEST) - }; + { + neighbour(point, Direction.NORTH), neighbour(point, Direction.SOUTH), + neighbour(point, Direction.EAST), neighbour(point, Direction.WEST) + }; } private LocalPoint neighbour(LocalPoint point, Direction direction) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java index 09cdabf83f..61c1474cbc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java @@ -1,3479 +1,3479 @@ -/* - * Copyright (c) 2018, Woox - * 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.multiindicators; - -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.Area; -import java.util.ArrayList; -import java.util.List; -import net.runelite.api.Constants; - -public class MapLocations -{ - private static final List[] MULTICOMBAT = new List[Constants.MAX_Z]; - private static final List[] NOT_MULTICOMBAT = new List[Constants.MAX_Z]; - private static final List[] ROUGH_WILDERNESS = new List[Constants.MAX_Z]; - private static final List[] DEADMAN_SAFE_ZONES = new List[Constants.MAX_Z]; - private static final List[] PVP_WORLD_SAFE_ZONES = new List[Constants.MAX_Z]; - - private static Area getArea(List shapes) - { - Area area = new Area(); - for (Shape shape : shapes) - { - area.add(new Area(shape)); - } - return area; - } - - private static Area getArea(List shapes, Rectangle view) - { - Area area = new Area(); - for (Shape shape : shapes) - { - if (shape.intersects(view)) - { - area.add(new Area(shape)); - } - } - return area; - } - - public static Area getMulticombat(int plane) - { - Area area = getArea(MULTICOMBAT[plane]); - area.subtract(getArea(NOT_MULTICOMBAT[plane])); - return area; - } - - public static Area getMulticombat(Rectangle view, int plane) - { - Area area = getArea(MULTICOMBAT[plane], view); - area.subtract(getArea(NOT_MULTICOMBAT[plane], view)); - return area; - } - - public static Area getRoughWilderness(int plane) - { - return getArea(ROUGH_WILDERNESS[plane]); - } - - public static Area getRoughWilderness(Rectangle view, int plane) - { - return getArea(ROUGH_WILDERNESS[plane], view); - } - - public static Area getDeadmanSafeZones(int plane) - { - return getArea(DEADMAN_SAFE_ZONES[plane]); - } - - public static Area getDeadmanSafeZones(Rectangle view, int plane) - { - return getArea(DEADMAN_SAFE_ZONES[plane], view); - } - - public static Area getPvpSafeZones(int plane) - { - return getArea(PVP_WORLD_SAFE_ZONES[plane]); - } - - public static Area getPvpSafeZones(Rectangle view, int plane) - { - return getArea(PVP_WORLD_SAFE_ZONES[plane], view); - } - - static - { - for (int i = 0; i < MULTICOMBAT.length; i++) - { - MULTICOMBAT[i] = new ArrayList<>(); - } - for (int i = 0; i < NOT_MULTICOMBAT.length; i++) - { - NOT_MULTICOMBAT[i] = new ArrayList<>(); - } - for (int i = 0; i < ROUGH_WILDERNESS.length; i++) - { - ROUGH_WILDERNESS[i] = new ArrayList<>(); - } - for (int i = 0; i < DEADMAN_SAFE_ZONES.length; i++) - { - DEADMAN_SAFE_ZONES[i] = new ArrayList<>(); - } - for (int i = 0; i < PVP_WORLD_SAFE_ZONES.length; i++) - { - PVP_WORLD_SAFE_ZONES[i] = new ArrayList<>(); - } - - defineMulticombatAreas(); - defineDeadmanSafeZones(); - definePvpSafeZones(); - defineWilderness(); - } - - private static void defineMulticombatAreas() - { - // Main Wilderness - addPolygonOnPlane(MULTICOMBAT, 0, - 3200, 3968, - 3392, 3968, - 3392, 3840, - 3328, 3840, - 3328, 3520, - 3136, 3520, - 3136, 3648, - 3192, 3648, - 3192, 3752, - 3152, 3752, - 3152, 3840, - 3136, 3840, - 3136, 3872, - 3112, 3872, - 3112, 3880, - 3072, 3880, - 3072, 3896, - 3048, 3896, - 3048, 3872, - 3056, 3872, - 3056, 3864, - 3048, 3864, - 3048, 3856, - 3008, 3856, - 3008, 3904, - 3200, 3904); - - // South of wildy agility training arena - addPolygonOnPlane(MULTICOMBAT, 0, - 2984, 3928, - 3008, 3928, - 3008, 3912, - 2984, 3912); - - // Wildy zamorak temple - addPolygonOnPlane(MULTICOMBAT, 0, - 2944, 3832, - 2960, 3832, - 2960, 3816, - 2944, 3816); - - // Wildy bandit camp - addPolygonOnPlane(MULTICOMBAT, 0, - 3008, 3712, - 3072, 3712, - 3072, 3600, - 3008, 3600); - - // Chaos temple north of Falador - addPolygonOnPlane(MULTICOMBAT, 0, - 2928, 3520, - 2944, 3520, - 2944, 3512, - 2928, 3512); - - // Burthorpe - addPolygonOnPlane(MULTICOMBAT, 0, - 2880, 3544, - 2904, 3544, - 2904, 3520, - 2880, 3520); - - // White Wolf Mountain - addPolygonOnPlane(MULTICOMBAT, 0, - 2880, 3520, - 2816, 3520, - 2816, 3456, - 2880, 3456); - - // Death Plateu - addPolygonOnPlane(MULTICOMBAT, 0, - 2848, 3608, - 2880, 3608, - 2880, 3600, - 2848, 3600); - - // Trollheim/Godwars - addPolygonOnPlane(MULTICOMBAT, 0, - 2880, 3776, - 2912, 3776, - 2912, 3696, - 2920, 3696, - 2920, 3688, - 2896, 3688, - 2896, 3696, - 2880, 3696, - 2880, 3728, - 2888, 3728, - 2888, 3744, - 2880, 3744); - - // Northen Rellekka - addPolygonOnPlane(MULTICOMBAT, 0, - 2656, 3736, - 2704, 3736, - 2704, 3728, - 2712, 3728, - 2712, 3736, - 2736, 3736, - 2736, 3712, - 2656, 3712); - - // Northen Fremennik Isles - addPolygonOnPlane(MULTICOMBAT, 0, - 2304, 3904, - 2432, 3904, - 2432, 3840, - 2368, 3840, - 2368, 3816, - 2352, 3816, - 2352, 3824, - 2304, 3824); - - // Pirates Cove - addPolygonOnPlane(MULTICOMBAT, 0, - 2176, 3840, - 2240, 3840, - 2240, 3776, - 2176, 3776); - - // Lunar Isle - addPolygonOnPlane(MULTICOMBAT, 0, - 2048, 3968, - 2176, 3968, - 2176, 3840, - 2048, 3840); - - // Piscatoris Fishing Colony - addPolygonOnPlane(MULTICOMBAT, 0, - 2304, 3712, - 2368, 3712, - 2368, 3648, - 2304, 3648); - - // Ranging Guild - addPolygonOnPlane(MULTICOMBAT, 0, - 2656, 3448, - 2680, 3448, - 2680, 3440, - 2688, 3440, - 2688, 3416, - 2680, 3416, - 2680, 3408, - 2656, 3408, - 2656, 3416, - 2648, 3416, - 2648, 3440, - 2656, 3440); - - // Necromancer house, southeast of Ardy - addPolygonOnPlane(MULTICOMBAT, 0, - 2656, 3256, - 2680, 3256, - 2680, 3216, - 2664, 3216, - 2664, 3232, - 2656, 3232); - - // Battlefield noth of Tree Gnome Village - addPolygonOnPlane(MULTICOMBAT, 0, - 2504, 3248, - 2544, 3248, - 2544, 3232, - 2552, 3232, - 2552, 3208, - 2504, 3208); - - // Castle Wars - addPolygonOnPlane(MULTICOMBAT, 0, - 2368, 3136, - 2432, 3136, - 2432, 3072, - 2368, 3072); - - // Jiggig - addPolygonOnPlane(MULTICOMBAT, 0, - 2456, 3056, - 2496, 3056, - 2496, 3032, - 2456, 3032); - - // East feldip hills, near rantz - addPolygonOnPlane(MULTICOMBAT, 0, - 2648, 2976, - 2656, 2976, - 2656, 2952, - 2648, 2952); - - // Ape Atoll - addPolygonOnPlane(MULTICOMBAT, 0, - 2688, 2816, - 2816, 2816, - 2816, 2688, - 2688, 2688); - - // Pest Control - addPolygonOnPlane(MULTICOMBAT, 0, - 2624, 2624, - 2688, 2624, - 2688, 2560, - 2624, 2560); - - // Desert Bandit Camp - addPolygonOnPlane(MULTICOMBAT, 0, - 3152, 3000, - 3192, 3000, - 3192, 2960, - 3152, 2960); - - // Al Kharid - addPolygonOnPlane(MULTICOMBAT, 0, - 3264, 3200, - 3328, 3200, - 3328, 3136, - 3264, 3136); - - // Wizards Tower - addPolygonOnPlane(MULTICOMBAT, 0, - 3094, 3176, - 3126, 3176, - 3126, 3144, - 3094, 3144); - - // Draynor Village - addPolygonOnPlane(MULTICOMBAT, 0, - 3112, 3264, - 3136, 3264, - 3136, 3232, - 3104, 3232, - 3104, 3256, - 3112, 3256); - - // Falador - addPolygonOnPlane(MULTICOMBAT, 0, - 2944, 3456, - 3008, 3456, - 3008, 3328, - 3016, 3328, - 3016, 3304, - 2944, 3304); - - // Southwest fally castle isn't multicombat downstairs - addPolygonOnPlane(NOT_MULTICOMBAT, 0, - 2968, 3336, - 2968, 3328, - 2960, 3328, - 2960, 3336); - - // Barbarian Village - addPolygonOnPlane(MULTICOMBAT, 0, - 3072, 3456, - 3136, 3456, - 3136, 3392, - 3048, 3392, - 3048, 3408, - 3056, 3408, - 3056, 3440, - 3064, 3440, - 3064, 3448, - 3072, 3448); - - // Ammoniate crabs at northwest fossil island - addPolygonOnPlane(MULTICOMBAT, 0, - 3648, 3885, - 3663, 3885, - 3663, 3882, - 3664, 3882, - 3664, 3872, - 3663, 3872, - 3663, 3868, - 3648, 3868); - - // Ammoniate crabs at north fossil island - addPolygonOnPlane(MULTICOMBAT, 0, - 3680, 3904, - 3744, 3904, - 3744, 3856, - 3756, 3856, - 3756, 3852, - 3755, 3852, - 3755, 3851, - 3754, 3851, - 3754, 3850, - 3751, 3850, - 3751, 3849, - 3750, 3849, - 3750, 3848, - 3749, 3848, - 3749, 3847, - 3748, 3847, - 3748, 3846, - 3747, 3846, - 3747, 3845, - 3746, 3845, - 3746, 3844, - 3742, 3844, - 3742, 3845, - 3740, 3845, - 3740, 3844, - 3732, 3844, - 3732, 3843, - 3730, 3843, - 3730, 3842, - 3724, 3842, - 3724, 3843, - 3717, 3843, - 3717, 3842, - 3712, 3842, - 3712, 3846, - 3710, 3846, - 3710, 3847, - 3709, 3847, - 3709, 3848, - 3708, 3848, - 3708, 3859, - 3709, 3859, - 3709, 3860, - 3710, 3860, - 3710, 3861, - 3712, 3861, - 3712, 3866, - 3713, 3866, - 3713, 3870, - 3714, 3870, - 3714, 3873, - 3713, 3873, - 3713, 3876, - 3712, 3876, - 3712, 3881, - 3710, 3881, - 3710, 3888, - 3712, 3888, - 3712, 3890, - 3714, 3890, - 3714, 3891, - 3716, 3891, - 3716, 3892, - 3717, 3892, - 3717, 3893, - 3716, 3893, - 3716, 3894, - 3714, 3894, - 3714, 3895, - 3713, 3895, - 3713, 3896, - 3712, 3896, - 3712, 3897, - 3705, 3897, - 3705, 3898, - 3704, 3898, - 3704, 3899, - 3692, 3899, - 3692, 3898, - 3688, 3898, - 3688, 3897, - 3686, 3897, - 3686, 3896, - 3680, 3896); - - // Zeah, southwest of Wintertodt, snowy area with ice giants and wolves - addPolygonOnPlane(MULTICOMBAT, 0, - 1540, 3898, - 1543, 3898, - 1543, 3901, - 1546, 3901, - 1546, 3903, - 1547, 3903, - 1547, 3904, - 1550, 3904, - 1550, 3903, - 1553, 3903, - 1553, 3904, - 1559, 3904, - 1559, 3902, - 1564, 3902, - 1564, 3903, - 1565, 3903, - 1565, 3904, - 1568, 3904, - 1568, 3903, - 1569, 3903, - 1569, 3902, - 1570, 3902, - 1570, 3901, - 1573, 3901, - 1573, 3898, - 1577, 3898, - 1577, 3899, - 1578, 3899, - 1578, 3902, - 1579, 3902, - 1579, 3903, - 1584, 3903, - 1584, 3902, - 1586, 3902, - 1586, 3901, - 1590, 3901, - 1590, 3891, - 1588, 3891, - 1588, 3887, - 1572, 3887, - 1572, 3872, - 1567, 3872, - 1567, 3868, - 1563, 3868, - 1563, 3867, - 1558, 3867, - 1558, 3868, - 1557, 3868, - 1557, 3870, - 1549, 3870, - 1549, 3874, - 1545, 3874, - 1545, 3876, - 1543, 3876, - 1543, 3877, - 1542, 3877, - 1542, 3879, - 1541, 3879, - 1541, 3882, - 1539, 3882, - 1539, 3887, - 1540, 3887, - 1540, 3888, - 1539, 3888, - 1539, 3894, - 1540, 3894); - - // Zeah arceuus area - addPolygonOnPlane(MULTICOMBAT, 0, - 1664, 3776, - 1664, 3785, - 1667, 3785, - 1667, 3805, - 1671, 3805, - 1671, 3811, - 1675, 3811, - 1675, 3819, - 1690, 3819, - 1690, 3814, - 1695, 3814, - 1695, 3806, - 1719, 3806, - 1719, 3787, - 1725, 3787, - 1725, 3778, - 1711, 3778, - 1711, 3776); - - // Arceuus teletab-making house - addPolygonOnPlane(MULTICOMBAT, 0, - 1667, 3772, - 1679, 3772, - 1679, 3775, - 1691, 3775, - 1691, 3761, - 1679, 3761, - 1679, 3764, - 1667, 3764); - // Next house east - addPolygonOnPlane(MULTICOMBAT, 0, - 1696, 3775, - 1708, 3775, - 1708, 3763, - 1696, 3763); - // Next house east - addPolygonOnPlane(MULTICOMBAT, 0, - 1713, 3775, - 1727, 3775, - 1727, 3763, - 1724, 3763, - 1724, 3752, - 1716, 3752, - 1716, 3763, - 1713, 3763); - // Arceuus rune shop house - addPolygonOnPlane(MULTICOMBAT, 0, - 1716, 3750, - 1728, 3750, - 1728, 3736, - 1716, 3736); - // Arceuus general store house - addPolygonOnPlane(MULTICOMBAT, 0, - 1717, 3732, - 1725, 3732, - 1725, 3715, - 1715, 3715, - 1715, 3725, - 1717, 3725); - // Arceuus pub - addPolygonOnPlane(MULTICOMBAT, 0, - 1683, 3732, - 1691, 3732, - 1691, 3725, - 1697, 3725, - 1697, 3730, - 1703, 3730, - 1703, 3712, - 1683, 3712); - // Arceuus staff store - addPolygonOnPlane(MULTICOMBAT, 0, - 1664, 3732, - 1676, 3732, - 1676, 3720, - 1664, 3720); - // Next house to the west - addPolygonOnPlane(MULTICOMBAT, 0, - 1647, 3738, - 1655, 3738, - 1655, 3726, - 1658, 3726, - 1658, 3714, - 1644, 3714, - 1644, 3726, - 1647, 3726); - // Next house to the north - addPolygonOnPlane(MULTICOMBAT, 0, - 1647, 3762, - 1657, 3762, - 1657, 3752, - 1655, 3752, - 1655, 3745, - 1647, 3745); - - // Arceuus house magic trees - addPolygonOnPlane(MULTICOMBAT, 0, - 1682, 3755, - 1692, 3755, - 1692, 3745, - 1690, 3745, - 1690, 3738, - 1682, 3738); - // West of that ^ - addPolygonOnPlane(MULTICOMBAT, 0, - 1667, 3756, - 1675, 3756, - 1675, 3740, - 1665, 3740, - 1665, 3746, - 1667, 3746); - - // This one goes through western piscarilius, northen hosidius - // and southwestern arceuus - addPolygonOnPlane(MULTICOMBAT, 0, - 1728, 3808, - 1792, 3808, - 1792, 3764, - 1856, 3764, - 1856, 3712, - 1792, 3712, - 1792, 3648, - 1664, 3648, - 1664, 3706, - 1665, 3706, - 1665, 3705, - 1668, 3705, - 1668, 3706, - 1671, 3706, - 1671, 3705, - 1675, 3705, - 1675, 3704, - 1683, 3704, - 1683, 3701, - 1684, 3701, - 1684, 3700, - 1686, 3700, - 1686, 3702, - 1687, 3702, - 1687, 3700, - 1688, 3700, - 1688, 3701, - 1690, 3701, - 1690, 3703, - 1689, 3703, - 1689, 3704, - 1690, 3704, - 1690, 3705, - 1704, 3705, - 1704, 3707, - 1706, 3707, - 1706, 3712, - 1711, 3712, - 1711, 3711, - 1710, 3711, - 1710, 3710, - 1712, 3710, - 1712, 3707, - 1728, 3707); - - // Kourend castle - addPolygonOnPlane(MULTICOMBAT, 0, - 1614, 3691, - 1619, 3691, - 1619, 3690, - 1620, 3690, - 1620, 3689, - 1653, 3689, - 1653, 3690, - 1654, 3690, - 1654, 3691, - 1657, 3691, - 1657, 3690, - 1658, 3690, - 1658, 3689, - 1659, 3689, - 1659, 3686, - 1658, 3686, - 1658, 3685, - 1657, 3685, - 1657, 3662, - 1658, 3662, - 1658, 3661, - 1659, 3661, - 1659, 3658, - 1658, 3658, - 1658, 3657, - 1657, 3657, - 1657, 3656, - 1654, 3656, - 1654, 3657, - 1653, 3657, - 1653, 3658, - 1620, 3658, - 1620, 3657, - 1619, 3657, - 1619, 3656, - 1614, 3656, - 1614, 3657, - 1613, 3657, - 1613, 3661, - 1612, 3661, - 1612, 3662, - 1611, 3662, - 1611, 3663, - 1600, 3663, - 1600, 3662, - 1599, 3662, - 1599, 3661, - 1594, 3661, - 1594, 3662, - 1593, 3662, - 1593, 3685, - 1594, 3685, - 1594, 3686, - 1599, 3686, - 1599, 3685, - 1600, 3685, - 1600, 3684, - 1611, 3684, - 1611, 3685, - 1612, 3685, - 1612, 3686, - 1613, 3686, - 1613, 3690, - 1614, 3690); - - // Western hosidius area, including woodcutting guild and western sand crabs - addPolygonOnPlane(MULTICOMBAT, 0, - 1650, 3648, - 1664, 3648, - 1664, 3520, - 1689, 3520, - 1689, 3496, - 1707, 3496, - 1707, 3485, - 1708, 3485, - 1708, 3484, - 1710, 3484, - 1710, 3483, - 1713, 3483, - 1713, 3482, - 1720, 3482, - 1720, 3481, - 1721, 3481, - 1721, 3480, - 1722, 3480, - 1722, 3479, - 1723, 3479, - 1723, 3478, - 1724, 3478, - 1724, 3477, - 1726, 3477, - 1726, 3476, - 1728, 3476, - 1728, 3472, - 1708, 3472, - 1708, 3456, - 1600, 3456, - 1600, 3584, - 1608, 3584, - 1608, 3616, - 1650, 3616); - - // Hosidius sand crabs - addPolygonOnPlane(MULTICOMBAT, 0, - 1740, 3478, - 1741, 3478, - 1741, 3479, - 1745, 3479, - 1745, 3480, - 1751, 3480, - 1751, 3479, - 1752, 3479, - 1752, 3478, - 1753, 3478, - 1753, 3477, - 1755, 3477, - 1755, 3476, - 1757, 3476, - 1757, 3475, - 1758, 3475, - 1758, 3474, - 1759, 3474, - 1759, 3473, - 1779, 3473, - 1779, 3474, - 1781, 3474, - 1781, 3475, - 1786, 3475, - 1786, 3476, - 1800, 3476, - 1800, 3475, - 1805, 3475, - 1805, 3474, - 1807, 3474, - 1807, 3473, - 1808, 3473, - 1808, 3472, - 1810, 3472, - 1810, 3471, - 1833, 3471, - 1833, 3470, - 1834, 3470, - 1834, 3469, - 1852, 3469, - 1852, 3449, - 1792, 3449, - 1792, 3424, - 1800, 3424, - 1800, 3449, - 1800, 3400, - 1728, 3400, - 1728, 3462, - 1729, 3462, - 1729, 3466, - 1730, 3466, - 1730, 3469, - 1731, 3469, - 1731, 3470, - 1732, 3470, - 1732, 3471, - 1733, 3471, - 1733, 3473, - 1734, 3473, - 1734, 3474, - 1736, 3474, - 1736, 3475, - 1737, 3475, - 1737, 3476, - 1738, 3476, - 1738, 3477, - 1740, 3477); - - // Apparently there is a 1x1 single zone on the sand crab island - addPolygonOnPlane(NOT_MULTICOMBAT, 0, - 1777, 3416, - 1777, 3417, - 1778, 3417, - 1778, 3416); - - // Eastern hosidius area - addPolygonOnPlane(MULTICOMBAT, 0, - 1834, 3584, - 1888, 3584, - 1888, 3528, - 1856, 3528, - 1856, 3520, - 1834, 3520, - 1834, 3522, - 1833, 3522, - 1833, 3535, - 1834, 3535, - 1834, 3538, - 1835, 3538, - 1835, 3539, - 1836, 3539, - 1836, 3540, - 1837, 3540, - 1837, 3541, - 1838, 3541, - 1838, 3542, - 1840, 3542, - 1840, 3543, - 1841, 3543, - 1841, 3545, - 1842, 3545, - 1842, 3546, - 1844, 3546, - 1844, 3547, - 1845, 3547, - 1845, 3548, - 1851, 3548, - 1851, 3551, - 1853, 3551, - 1853, 3563, - 1851, 3563, - 1851, 3566, - 1847, 3566, - 1847, 3567, - 1845, 3567, - 1845, 3568, - 1844, 3568, - 1844, 3569, - 1843, 3569, - 1843, 3571, - 1842, 3571, - 1842, 3573, - 1841, 3573, - 1841, 3574, - 1840, 3574, - 1840, 3575, - 1839, 3575, - 1839, 3576, - 1838, 3576, - 1838, 3577, - 1837, 3577, - 1837, 3578, - 1836, 3578, - 1836, 3579, - 1835, 3579, - 1835, 3581, - 1834, 3581); - - // Eastern hosidius area also has a 1x1 multi area - addPolygonOnPlane(MULTICOMBAT, 0, - 1849, 3563, - 1849, 3564, - 1850, 3564, - 1850, 3563); - - // Hosidius cows/chickens/pigs - addPolygonOnPlane(MULTICOMBAT, 0, - 1792, 3513, - 1802, 3513, - 1802, 3520, - 1810, 3520, - 1810, 3513, - 1816, 3513, - 1816, 3512, - 1836, 3512, - 1836, 3494, - 1796, 3494, - 1796, 3495, - 1792, 3495); - - // Hosidius southeast of tithe farm - addPolygonOnPlane(MULTICOMBAT, 0, - 1777, 3597, - 1794, 3597, - 1794, 3561, - 1777, 3561, - 1777, 3591, - 1779, 3591, - 1779, 3592, - 1777, 3592); - - // West of shayzien house - addPolygonOnPlane(MULTICOMBAT, 0, - 1408, 3584, - 1408, 3582, - 1486, 3582, - 1486, 3568, - 1528, 3568, - 1528, 3520, - 1408, 3520, - 1408, 3464, - 1380, 3464, - 1380, 3486, - 1377, 3486, - 1377, 3488, - 1373, 3488, - 1373, 3492, - 1364, 3492, - 1364, 3512, - 1358, 3512, - 1358, 3520, - 1356, 3520, - 1356, 3532, - 1358, 3532, - 1358, 3540, - 1359, 3540, - 1359, 3542, - 1360, 3542, - 1360, 3557, - 1356, 3557, - 1356, 3560, - 1351, 3560, - 1351, 3570, - 1354, 3570, - 1354, 3581, - 1346, 3581, - 1346, 3584); - - // South of chambers of xeric - addPolygonOnPlane(MULTICOMBAT, 0, - 1261, 3489, - 1259, 3489, - 1259, 3488, - 1255, 3488, - 1255, 3487, - 1243, 3487, - 1243, 3490, - 1234, 3490, - 1234, 3480, - 1192, 3480, - 1192, 3568, - 1209, 3568, - 1209, 3548, - 1215, 3548, - 1215, 3544, - 1217, 3544, - 1217, 3536, - 1235, 3536, - 1235, 3532, - 1249, 3532, - 1249, 3525, - 1248, 3525, - 1248, 3517, - 1254, 3517, - 1254, 3513, - 1274, 3513, - 1274, 3510, - 1296, 3510, - 1296, 3511, - 1300, 3511, - 1300, 3501, - 1287, 3501, - 1287, 3490, - 1280, 3490, - 1280, 3489, - 1264, 3489, - 1264, 3490, - 1261, 3490); - - // Lizardman shamans - addPolygonOnPlane(MULTICOMBAT, 0, - 1416, 3728, - 1456, 3728, - 1456, 3688, - 1416, 3688); - - // Other lizardman area at shayzien (west side) - addPolygonOnPlane(MULTICOMBAT, 0, - 1472, 3712, - 1510, 3712, - 1510, 3702, - 1509, 3702, - 1509, 3701, - 1506, 3701, - 1506, 3696, - 1500, 3696, - 1500, 3680, - 1472, 3680); - - // Other lizardman area at shayzien (east side) - addPolygonOnPlane(MULTICOMBAT, 0, - 1538, 3704, - 1560, 3704, - 1560, 3672, - 1538, 3672); - - // Lovakengj house - addPolygonOnPlane(MULTICOMBAT, 0, - 1600, 3712, - 1472, 3712, - 1472, 3840, - 1547, 3840, - 1547, 3816, - 1556, 3816, - 1556, 3809, - 1562, 3809, - 1562, 3800, - 1568, 3800, - 1568, 3793, - 1571, 3793, - 1571, 3816, - 1571, 3776, - 1600, 3776); - - // Shayzien house - addPolygonOnPlane(MULTICOMBAT, 0, - 1475, 3587, - 1475, 3641, - 1534, 3641, - 1534, 3587); - - // Shayzien house bank is non-multi - addPolygonOnPlane(NOT_MULTICOMBAT, 0, - 1495, 3622, - 1515, 3622, - 1515, 3612, - 1495, 3612); - - // Shayzien house general store - addPolygonOnPlane(MULTICOMBAT, 0, - 1539, 3640, - 1551, 3640, - 1551, 3621, - 1539, 3621); - - // Kourend woodland barbarian area - addPolygonOnPlane(MULTICOMBAT, 0, - 1572, 3442, - 1591, 3442, - 1591, 3424, - 1572, 3424); - - // Catacombs - addPolygonTo(MULTICOMBAT, - 1600, 9984, - 1600, 10067, - 1628, 10067, - 1628, 10070, - 1639, 10070, - 1639, 10112, - 1730, 10112, - 1730, 9984); - - // Zeah dungeon with sand crabs - addPolygonTo(MULTICOMBAT, - 1632, 9792, - 1632, 9856, - 1728, 9856, - 1728, 9792); - - // Waterbirth island near the doors where people use rune throwing axes - addPolygonTo(MULTICOMBAT, - 2536, 10136, - 2536, 10152, - 2552, 10152, - 2552, 10136); - - // Waterbirth island dungeon, on the path to dks - addPolygonTo(MULTICOMBAT, - 1792, 4352, - 1792, 4416, - 1984, 4416, - 1984, 4352); - - // Dagannoths in lighthouse - addPolygonTo(MULTICOMBAT, - 2496, 10048, - 2560, 10048, - 2560, 9984, - 2496, 9984); - - // Dagannoth kings (DKs) including slayer only dks - addPolygonTo(MULTICOMBAT, - 2944, 4352, - 2944, 4480, - 2880, 4480, - 2880, 4352); - - // White wolf mountain dungeon at ice queen - addPolygonTo(MULTICOMBAT, - 2856, 9928, - 2856, 9968, - 2880, 9968, - 2880, 9928); - - // Kharazi jungle dungeon (in dragon slayer 2 quest) - addPolygonTo(MULTICOMBAT, - 2816, 9296, - 2880, 9296, - 2880, 9216, - 2816, 9216); - - // Tzhaar, fight pits and inferno area - addPolygonTo(MULTICOMBAT, - 2368, 5184, - 2560, 5184, - 2560, 5056, - 2368, 5056); - - // Smoke devils - addPolygonTo(MULTICOMBAT, - 2432, 9408, - 2344, 9408, - 2344, 9472, - 2432, 9472); - - // Kraken - addPolygonTo(MULTICOMBAT, - 2270, 10045, - 2291, 10045, - 2291, 10022, - 2270, 10022); - - // Giant mole - addPolygonTo(MULTICOMBAT, - 1728, 5240, - 1792, 5240, - 1792, 5120, - 1728, 5120); - - // Godwars dungeon - addPolygonTo(MULTICOMBAT, - 2816, 5376, - 2944, 5376, - 2944, 5248, - 2816, 5248); - - // Desert treasure shadow diamond area - addPolygonTo(MULTICOMBAT, - 2752, 5064, - 2728, 5064, - 2728, 5088, - 2720, 5088, - 2720, 5096, - 2712, 5096, - 2712, 5112, - 2736, 5112, - 2736, 5120, - 2752, 5120); - - // Kalphite slayer area - addPolygonTo(MULTICOMBAT, - 3264, 9544, - 3344, 9544, - 3344, 9472, - 3264, 9472); - - // Normal kalphite area including kalphite queen - addPolygonTo(MULTICOMBAT, - 3456, 9536, - 3520, 9536, - 3520, 9472, - 3456, 9472); - - // Tarns lair - addPolygonTo(MULTICOMBAT, - 3136, 4664, - 3200, 4664, - 3200, 4544, - 3136, 4544); - - // Haunted mine boss area - addPolygonTo(MULTICOMBAT, - 2752, 4416, - 2752, 4480, - 2816, 4480, - 2816, 4416); - - // Entrance to dorgesh kaan - addPolygonTo(MULTICOMBAT, - 3328, 9600, - 3312, 9600, - 3312, 9640, - 3304, 9640, - 3304, 9664, - 3328, 9664); - - // Hammerspikes hangout in dwarven mines - addPolygonTo(MULTICOMBAT, - 2960, 9824, - 2976, 9824, - 2976, 9800, - 2960, 9800); - - // Fremennik isles dungeon - addPolygonTo(MULTICOMBAT, - 2432, 10304, - 2432, 10240, - 2368, 10240, - 2368, 10304); - - // Varrock sewers - addPolygonTo(MULTICOMBAT, - 3152, 9920, - 3288, 9920, - 3288, 9856, - 3152, 9856); - - // Stronghold of security 1st floor - addPolygonTo(MULTICOMBAT, - 1856, 5248, - 1920, 5248, - 1920, 5184, - 1856, 5184); - - // Corp cave - addPolygonTo(MULTICOMBAT, - 2960, 4400, - 3000, 4400, - 3000, 4368, - 2960, 4368); - - // ZMI altar area - addPolygonTo(MULTICOMBAT, - 3008, 5632, - 3072, 5632, - 3072, 5568, - 3008, 5568); - - // Dragon slayer 2 zeah underground puzzle - addPolygonTo(MULTICOMBAT, - 1472, 9984, - 1536, 9984, - 1536, 9920, - 1472, 9920); - - // Wildy revenant caves - addPolygonTo(MULTICOMBAT, - 3136, 10062, - 3136, 10240, - 3236, 10240, - 3236, 10229, - 3264, 10229, - 3264, 10048, - 3208, 10048, - 3208, 10062); - - // King black dragon (Kbd) - addPolygonTo(MULTICOMBAT, - 2240, 4672, - 2240, 4736, - 2304, 4736, - 2304, 4672); - - // Scorpia - addPolygonTo(MULTICOMBAT, - 3248, 10352, - 3248, 10328, - 3216, 10328, - 3216, 10352); - - // Inside mage bank - addPolygonTo(MULTICOMBAT, - 2496, 4672, - 2496, 4736, - 2560, 4736, - 2560, 4672); - - // Wildy godwars dungeon - addPolygonTo(MULTICOMBAT, - 3072, 10112, - 3008, 10112, - 3008, 10176, - 3048, 10176, - 3048, 10152, - 3056, 10152, - 3056, 10144, - 3064, 10144, - 3064, 10136, - 3072, 10136); - - // Enchanted valley - addPolygonTo(MULTICOMBAT, - 3008, 4480, - 3008, 4544, - 3072, 4544, - 3072, 4480); - - // Zulrah - addPolygonTo(MULTICOMBAT, - 2256, 3080, - 2280, 3080, - 2280, 3064, - 2256, 3064); - - // Abyssal sire and abyss - addPolygonTo(MULTICOMBAT, - 3008, 4736, - 2944, 4736, - 2944, 4864, - 3136, 4864, - 3136, 4736, - 3072, 4736, - 3072, 4800, - 3008, 4800); - } - - private static void defineDeadmanSafeZones() - { - // Varrock - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3182, 3382, - 3182, 3399, - 3174, 3399, - 3174, 3448, - 3198, 3448, - 3198, 3449, - 3197, 3449, - 3197, 3450, - 3196, 3450, - 3196, 3451, - 3195, 3451, - 3195, 3452, - 3194, 3452, - 3194, 3453, - 3193, 3453, - 3193, 3454, - 3192, 3454, - 3192, 3455, - 3191, 3455, - 3191, 3456, - 3190, 3456, - 3190, 3457, - 3185, 3457, - 3185, 3463, - 3186, 3463, - 3186, 3464, - 3187, 3464, - 3187, 3467, - 3167, 3467, - 3167, 3468, - 3163, 3468, - 3163, 3467, - 3142, 3467, - 3142, 3468, - 3141, 3468, - 3141, 3469, - 3140, 3469, - 3140, 3470, - 3139, 3470, - 3139, 3471, - 3138, 3471, - 3138, 3484, - 3139, 3484, - 3139, 3485, - 3140, 3485, - 3140, 3486, - 3141, 3486, - 3141, 3491, - 3140, 3491, - 3140, 3492, - 3139, 3492, - 3139, 3493, - 3138, 3493, - 3138, 3515, - 3139, 3515, - 3139, 3516, - 3140, 3516, - 3140, 3517, - 3141, 3517, - 3141, 3518, - 3160, 3518, - 3160, 3517, - 3161, 3517, - 3161, 3516, - 3162, 3516, - 3162, 3515, - 3167, 3515, - 3167, 3516, - 3168, 3516, - 3168, 3517, - 3169, 3517, - 3169, 3518, - 3191, 3518, - 3191, 3517, - 3192, 3517, - 3192, 3516, - 3193, 3516, - 3193, 3515, - 3194, 3515, - 3194, 3514, - 3195, 3514, - 3195, 3513, - 3196, 3513, - 3196, 3512, - 3197, 3512, - 3197, 3511, - 3198, 3511, - 3198, 3510, - 3199, 3510, - 3199, 3509, - 3200, 3509, - 3200, 3508, - 3230, 3508, - 3230, 3507, - 3231, 3507, - 3231, 3506, - 3232, 3506, - 3232, 3505, - 3233, 3505, - 3233, 3504, - 3234, 3504, - 3234, 3503, - 3235, 3503, - 3235, 3502, - 3252, 3502, - 3252, 3496, - 3253, 3496, - 3253, 3495, - 3254, 3495, - 3254, 3494, - 3255, 3494, - 3255, 3493, - 3263, 3493, - 3263, 3472, - 3264, 3472, - 3264, 3471, - 3265, 3471, - 3265, 3470, - 3266, 3470, - 3266, 3469, - 3267, 3469, - 3267, 3468, - 3268, 3468, - 3268, 3467, - 3269, 3467, - 3269, 3466, - 3270, 3466, - 3270, 3465, - 3271, 3465, - 3271, 3437, - 3274, 3437, - 3274, 3424, - 3277, 3424, - 3277, 3420, - 3274, 3420, - 3274, 3411, - 3275, 3411, - 3275, 3410, - 3276, 3410, - 3276, 3409, - 3277, 3409, - 3277, 3408, - 3288, 3408, - 3288, 3391, - 3289, 3391, - 3289, 3385, - 3290, 3385, - 3290, 3378, - 3289, 3378, - 3289, 3377, - 3288, 3377, - 3288, 3376, - 3265, 3376, - 3265, 3380, - 3253, 3380, - 3253, 3382, - 3245, 3382, - 3245, 3380, - 3242, 3380, - 3242, 3382, - 3239, 3382, - 3239, 3381, - 3209, 3381, - 3209, 3382, - 3282, 3382); - - // Lumbridge - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3201, 3257, - 3213, 3257, - 3213, 3264, - 3233, 3264, - 3233, 3257, - 3235, 3257, - 3235, 3241, - 3237, 3241, - 3237, 3237, - 3239, 3237, - 3239, 3231, - 3243, 3231, - 3243, 3220, - 3253, 3220, - 3253, 3217, - 3256, 3217, - 3256, 3212, - 3259, 3212, - 3259, 3190, - 3247, 3190, - 3247, 3191, - 3238, 3191, - 3238, 3195, - 3230, 3195, - 3230, 3201, - 3228, 3201, - 3228, 3202, - 3227, 3202, - 3227, 3205, - 3228, 3205, - 3228, 3207, - 3225, 3207, - 3225, 3206, - 3224, 3206, - 3224, 3205, - 3223, 3205, - 3223, 3204, - 3222, 3204, - 3222, 3203, - 3215, 3203, - 3215, 3202, - 3214, 3202, - 3214, 3201, - 3203, 3201, - 3203, 3202, - 3202, 3202, - 3202, 3203, - 3201, 3203, - 3201, 3217, - 3199, 3217, - 3199, 3220, - 3201, 3220); - - // Falador - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2986, 3395, - 2986, 3394, - 2987, 3394, - 2987, 3393, - 2996, 3393, - 2996, 3394, - 3002, 3394, - 3002, 3395, - 3009, 3395, - 3009, 3394, - 3010, 3394, - 3010, 3393, - 3011, 3393, - 3011, 3392, - 3021, 3392, - 3021, 3391, - 3022, 3391, - 3022, 3390, - 3041, 3390, - 3041, 3389, - 3047, 3389, - 3047, 3390, - 3062, 3390, - 3062, 3389, - 3063, 3389, - 3063, 3388, - 3064, 3388, - 3064, 3387, - 3065, 3387, - 3065, 3386, - 3066, 3386, - 3066, 3368, - 3065, 3368, - 3065, 3367, - 3064, 3367, - 3064, 3366, - 3063, 3366, - 3063, 3365, - 3062, 3365, - 3062, 3364, - 3061, 3364, - 3061, 3363, - 3060, 3363, - 3060, 3331, - 3061, 3331, - 3061, 3328, - 3058, 3328, - 3058, 3329, - 3025, 3329, - 3025, 3328, - 3024, 3328, - 3024, 3327, - 3016, 3327, - 3016, 3326, - 3015, 3326, - 3015, 3325, - 3014, 3325, - 3014, 3324, - 3013, 3324, - 3013, 3323, - 3008, 3323, - 3008, 3324, - 3006, 3324, - 3006, 3323, - 3002, 3323, - 3002, 3322, - 3001, 3322, - 3001, 3321, - 3000, 3321, - 3000, 3320, - 2999, 3320, - 2999, 3319, - 2998, 3319, - 2998, 3318, - 2997, 3318, - 2997, 3317, - 2996, 3317, - 2996, 3316, - 2992, 3316, - 2992, 3315, - 2991, 3315, - 2991, 3314, - 2990, 3314, - 2990, 3313, - 2989, 3313, - 2989, 3312, - 2988, 3312, - 2988, 3311, - 2987, 3311, - 2987, 3310, - 2986, 3310, - 2986, 3309, - 2966, 3309, - 2966, 3310, - 2956, 3310, - 2956, 3311, - 2941, 3311, - 2941, 3312, - 2940, 3312, - 2940, 3320, - 2936, 3320, - 2936, 3354, - 2937, 3354, - 2937, 3357, - 2936, 3357, - 2936, 3389, - 2937, 3389, - 2937, 3390, - 2938, 3390, - 2938, 3391, - 2939, 3391, - 2939, 3392, - 2940, 3392, - 2940, 3393, - 2943, 3393, - 2943, 3394, - 2944, 3394, - 2944, 3395, - 2950, 3395, - 2950, 3394, - 2956, 3394, - 2956, 3395); - - // Port phasmatys - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3650, 3456, - 3650, 3472, - 3651, 3472, - 3651, 3473, - 3652, 3473, - 3652, 3474, - 3653, 3474, - 3653, 3507, - 3654, 3507, - 3654, 3508, - 3668, 3508, - 3668, 3509, - 3669, 3509, - 3669, 3510, - 3670, 3510, - 3670, 3511, - 3671, 3511, - 3671, 3512, - 3672, 3512, - 3672, 3513, - 3673, 3513, - 3673, 3514, - 3674, 3514, - 3674, 3515, - 3675, 3515, - 3675, 3516, - 3676, 3516, - 3676, 3517, - 3687, 3517, - 3687, 3494, - 3690, 3494, - 3690, 3493, - 3696, 3493, - 3696, 3482, - 3699, 3482, - 3699, 3481, - 3712, 3481, - 3712, 3456); - - // Sophanem - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3274, 2752, - 3274, 2784, - 3277, 2784, - 3277, 2786, - 3274, 2786, - 3274, 2789, - 3272, 2789, - 3272, 2810, - 3322, 2810, - 3322, 2752); - - // Ardy - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2560, 3256, - 2560, 3264, - 2559, 3264, - 2559, 3328, - 2560, 3328, - 2560, 3339, - 2561, 3339, - 2561, 3340, - 2562, 3340, - 2562, 3341, - 2563, 3341, - 2563, 3342, - 2616, 3342, - 2616, 3341, - 2617, 3341, - 2617, 3340, - 2669, 3340, - 2669, 3339, - 2670, 3339, - 2670, 3338, - 2671, 3338, - 2671, 3337, - 2672, 3337, - 2672, 3336, - 2673, 3336, - 2673, 3335, - 2674, 3335, - 2674, 3334, - 2683, 3334, - 2683, 3333, - 2684, 3333, - 2684, 3332, - 2685, 3332, - 2685, 3331, - 2686, 3331, - 2686, 3330, - 2687, 3330, - 2687, 3329, - 2688, 3329, - 2688, 3264, - 2638, 3264, - 2638, 3263, - 2625, 3263, - 2625, 3264, - 2611, 3264, - 2611, 3257, - 2602, 3257, - 2602, 3264, - 2587, 3264, - 2587, 3263, - 2586, 3263, - 2586, 3262, - 2584, 3262, - 2584, 3261, - 2583, 3261, - 2583, 3260, - 2582, 3260, - 2582, 3259, - 2581, 3259, - 2581, 3258, - 2572, 3258, - 2572, 3260, - 2571, 3260, - 2571, 3261, - 2566, 3261, - 2566, 3260, - 2565, 3260, - 2565, 3259, - 2564, 3259, - 2564, 3256); - - // Yanille - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2613, 3103, - 2614, 3103, - 2614, 3102, - 2615, 3102, - 2615, 3101, - 2616, 3101, - 2616, 3100, - 2617, 3100, - 2617, 3099, - 2618, 3099, - 2618, 3098, - 2619, 3098, - 2619, 3097, - 2620, 3097, - 2620, 3075, - 2590, 3075, - 2590, 3074, - 2589, 3074, - 2589, 3073, - 2584, 3073, - 2584, 3074, - 2583, 3074, - 2583, 3075, - 2543, 3075, - 2543, 3076, - 2542, 3076, - 2542, 3077, - 2539, 3077, - 2539, 3107, - 2542, 3107, - 2542, 3108, - 2543, 3108, - 2543, 3109, - 2608, 3109, - 2608, 3108, - 2609, 3108, - 2609, 3107, - 2610, 3107, - 2610, 3106, - 2611, 3106, - 2611, 3105, - 2612, 3105, - 2612, 3104, - 2613, 3104); - - // Gnome stronghold - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2495, 3439, - 2494, 3439, - 2494, 3432, - 2495, 3432, - 2495, 3431, - 2496, 3431, - 2496, 3430, - 2497, 3430, - 2497, 3429, - 2498, 3429, - 2498, 3417, - 2497, 3417, - 2497, 3416, - 2496, 3416, - 2496, 3412, - 2495, 3412, - 2495, 3408, - 2494, 3408, - 2494, 3404, - 2495, 3404, - 2495, 3403, - 2496, 3403, - 2496, 3402, - 2497, 3402, - 2497, 3401, - 2498, 3401, - 2498, 3400, - 2499, 3400, - 2499, 3399, - 2500, 3399, - 2500, 3398, - 2501, 3398, - 2501, 3397, - 2502, 3397, - 2502, 3396, - 2506, 3396, - 2506, 3391, - 2502, 3391, - 2502, 3390, - 2492, 3390, - 2492, 3391, - 2489, 3391, - 2489, 3390, - 2488, 3390, - 2488, 3389, - 2485, 3389, - 2485, 3390, - 2482, 3390, - 2482, 3389, - 2476, 3389, - 2476, 3390, - 2471, 3390, - 2471, 3391, - 2468, 3391, - 2468, 3390, - 2467, 3390, - 2467, 3389, - 2466, 3389, - 2466, 3385, - 2465, 3385, - 2465, 3384, - 2458, 3384, - 2458, 3385, - 2457, 3385, - 2457, 3389, - 2456, 3389, - 2456, 3390, - 2455, 3390, - 2455, 3391, - 2450, 3391, - 2450, 3390, - 2446, 3390, - 2446, 3391, - 2443, 3391, - 2443, 3390, - 2442, 3390, - 2442, 3389, - 2440, 3389, - 2440, 3388, - 2434, 3388, - 2434, 3389, - 2433, 3389, - 2433, 3390, - 2432, 3390, - 2432, 3391, - 2428, 3391, - 2428, 3392, - 2427, 3392, - 2427, 3393, - 2420, 3393, - 2420, 3394, - 2419, 3394, - 2419, 3395, - 2418, 3395, - 2418, 3396, - 2417, 3396, - 2417, 3397, - 2416, 3397, - 2416, 3399, - 2415, 3399, - 2415, 3400, - 2414, 3400, - 2414, 3408, - 2413, 3408, - 2413, 3409, - 2412, 3409, - 2412, 3410, - 2411, 3410, - 2411, 3411, - 2410, 3411, - 2410, 3412, - 2387, 3412, - 2387, 3407, - 2383, 3407, - 2383, 3408, - 2380, 3408, - 2380, 3409, - 2379, 3409, - 2379, 3410, - 2377, 3410, - 2377, 3411, - 2376, 3411, - 2376, 3413, - 2375, 3413, - 2375, 3417, - 2374, 3417, - 2374, 3418, - 2373, 3418, - 2373, 3419, - 2372, 3419, - 2372, 3420, - 2371, 3420, - 2371, 3421, - 2370, 3421, - 2370, 3422, - 2369, 3422, - 2369, 3433, - 2370, 3433, - 2370, 3434, - 2371, 3434, - 2371, 3444, - 2372, 3444, - 2372, 3445, - 2373, 3445, - 2373, 3446, - 2374, 3446, - 2374, 3447, - 2375, 3447, - 2375, 3459, - 2376, 3459, - 2376, 3460, - 2377, 3460, - 2377, 3461, - 2378, 3461, - 2378, 3462, - 2379, 3462, - 2379, 3463, - 2380, 3463, - 2380, 3464, - 2381, 3464, - 2381, 3476, - 2379, 3476, - 2379, 3477, - 2378, 3477, - 2378, 3478, - 2377, 3478, - 2377, 3485, - 2376, 3485, - 2376, 3486, - 2375, 3486, - 2375, 3499, - 2376, 3499, - 2376, 3500, - 2377, 3500, - 2377, 3507, - 2378, 3507, - 2378, 3508, - 2379, 3508, - 2379, 3509, - 2380, 3509, - 2380, 3521, - 2382, 3521, - 2382, 3522, - 2384, 3522, - 2384, 3523, - 2393, 3523, - 2393, 3524, - 2399, 3524, - 2399, 3525, - 2404, 3525, - 2404, 3524, - 2405, 3524, - 2405, 3523, - 2407, 3523, - 2407, 3522, - 2415, 3522, - 2415, 3521, - 2425, 3521, - 2425, 3522, - 2427, 3522, - 2427, 3523, - 2430, 3523, - 2430, 3522, - 2431, 3522, - 2431, 3521, - 2432, 3521, - 2432, 3520, - 2448, 3520, - 2448, 3517, - 2454, 3517, - 2454, 3516, - 2455, 3516, - 2455, 3515, - 2456, 3515, - 2456, 3514, - 2457, 3514, - 2457, 3513, - 2460, 3513, - 2460, 3512, - 2461, 3512, - 2461, 3511, - 2465, 3511, - 2465, 3510, - 2468, 3510, - 2468, 3511, - 2472, 3511, - 2472, 3512, - 2473, 3512, - 2473, 3513, - 2475, 3513, - 2475, 3514, - 2476, 3514, - 2476, 3515, - 2477, 3515, - 2477, 3516, - 2478, 3516, - 2478, 3517, - 2483, 3517, - 2483, 3516, - 2487, 3516, - 2487, 3515, - 2488, 3515, - 2488, 3512, - 2487, 3512, - 2487, 3509, - 2488, 3509, - 2488, 3508, - 2489, 3508, - 2489, 3507, - 2491, 3507, - 2491, 3506, - 2492, 3506, - 2492, 3505, - 2493, 3505, - 2493, 3499, - 2492, 3499, - 2492, 3498, - 2491, 3498, - 2491, 3497, - 2490, 3497, - 2490, 3495, - 2491, 3495, - 2491, 3494, - 2492, 3494, - 2492, 3493, - 2493, 3493, - 2493, 3485, - 2490, 3485, - 2490, 3484, - 2489, 3484, - 2489, 3483, - 2488, 3483, - 2488, 3482, - 2487, 3482, - 2487, 3481, - 2486, 3481, - 2486, 3474, - 2488, 3474, - 2488, 3471, - 2489, 3471, - 2489, 3470, - 2490, 3470, - 2490, 3460, - 2491, 3460, - 2491, 3456, - 2496, 3456, - 2496, 3440, - 2495, 3440); - - // Rellekka - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2620, 3682, - 2624, 3682, - 2624, 3683, - 2625, 3683, - 2625, 3687, - 2629, 3687, - 2629, 3686, - 2630, 3686, - 2630, 3685, - 2632, 3685, - 2632, 3686, - 2636, 3686, - 2636, 3692, - 2645, 3692, - 2645, 3695, - 2647, 3695, - 2647, 3696, - 2649, 3696, - 2649, 3702, - 2650, 3702, - 2650, 3703, - 2651, 3703, - 2651, 3704, - 2652, 3704, - 2652, 3711, - 2653, 3711, - 2653, 3712, - 2691, 3712, - 2691, 3709, - 2692, 3709, - 2692, 3707, - 2693, 3707, - 2693, 3703, - 2692, 3703, - 2692, 3701, - 2691, 3701, - 2691, 3699, - 2690, 3699, - 2690, 3695, - 2691, 3695, - 2691, 3693, - 2692, 3693, - 2692, 3691, - 2693, 3691, - 2693, 3685, - 2692, 3685, - 2692, 3683, - 2691, 3683, - 2691, 3681, - 2690, 3681, - 2690, 3680, - 2689, 3680, - 2689, 3672, - 2690, 3672, - 2690, 3671, - 2691, 3671, - 2691, 3666, - 2690, 3666, - 2690, 3664, - 2689, 3664, - 2689, 3660, - 2690, 3660, - 2690, 3658, - 2691, 3658, - 2691, 3656, - 2692, 3656, - 2692, 3654, - 2693, 3654, - 2693, 3651, - 2692, 3651, - 2692, 3649, - 2690, 3649, - 2690, 3648, - 2688, 3648, - 2688, 3647, - 2686, 3647, - 2686, 3646, - 2673, 3646, - 2673, 3645, - 2636, 3645, - 2636, 3647, - 2627, 3647, - 2627, 3648, - 2625, 3648, - 2625, 3649, - 2624, 3649, - 2624, 3650, - 2622, 3650, - 2622, 3651, - 2620, 3651, - 2620, 3652, - 2618, 3652, - 2618, 3653, - 2616, 3653, - 2616, 3654, - 2609, 3654, - 2609, 3655, - 2607, 3655, - 2607, 3656, - 2603, 3656, - 2603, 3657, - 2602, 3657, - 2602, 3658, - 2601, 3658, - 2601, 3663, - 2602, 3663, - 2602, 3664, - 2603, 3664, - 2603, 3665, - 2604, 3665, - 2604, 3666, - 2605, 3666, - 2605, 3667, - 2606, 3667, - 2606, 3671, - 2609, 3671, - 2609, 3672, - 2610, 3672, - 2610, 3673, - 2611, 3673, - 2611, 3675, - 2612, 3675, - 2612, 3676, - 2614, 3676, - 2614, 3677, - 2616, 3677, - 2616, 3679, - 2618, 3679, - 2618, 3681, - 2620, 3681); - - // Jatizo - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2407, 3797, - 2407, 3793, - 2399, 3793, - 2399, 3792, - 2391, 3792, - 2391, 3791, - 2386, 3791, - 2386, 3796, - 2388, 3796, - 2388, 3802, - 2386, 3802, - 2386, 3807, - 2388, 3807, - 2388, 3809, - 2402, 3809, - 2402, 3819, - 2406, 3819, - 2406, 3824, - 2408, 3824, - 2408, 3826, - 2413, 3826, - 2413, 3824, - 2419, 3824, - 2419, 3826, - 2424, 3826, - 2424, 3821, - 2423, 3821, - 2423, 3798, - 2422, 3798, - 2422, 3797); - - // Neitiznot - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2329, 3812, - 2333, 3812, - 2333, 3813, - 2334, 3813, - 2334, 3814, - 2335, 3814, - 2335, 3815, - 2338, 3815, - 2338, 3816, - 2339, 3816, - 2339, 3817, - 2368, 3817, - 2368, 3776, - 2352, 3776, - 2352, 3796, - 2344, 3796, - 2344, 3795, - 2331, 3795, - 2331, 3797, - 2330, 3797, - 2330, 3798, - 2329, 3798); - - // Pest control - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2624, 2688, - 2688, 2688, - 2688, 2624, - 2624, 2624); - - // Tutorial island - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3052, 3135, - 3156, 3135, - 3156, 3057, - 3052, 3057); - - // Camelot bank - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2724, 3487, - 2724, 3490, - 2721, 3490, - 2721, 3494, - 2719, 3494, - 2719, 3497, - 2721, 3497, - 2721, 3498, - 2731, 3498, - 2731, 3490, - 2728, 3490, - 2728, 3487); - - // Catherby bank - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2806, 3438, - 2806, 3446, - 2813, 3446, - 2813, 3438); - - // Kourend castle - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 1627, 3658, - 1620, 3658, - 1620, 3657, - 1619, 3657, - 1619, 3656, - 1614, 3656, - 1614, 3657, - 1613, 3657, - 1613, 3661, - 1612, 3661, - 1612, 3662, - 1611, 3662, - 1611, 3663, - 1600, 3663, - 1600, 3662, - 1599, 3662, - 1599, 3661, - 1594, 3661, - 1594, 3662, - 1593, 3662, - 1593, 3685, - 1594, 3685, - 1594, 3686, - 1599, 3686, - 1599, 3685, - 1600, 3685, - 1600, 3684, - 1611, 3684, - 1611, 3685, - 1612, 3685, - 1612, 3686, - 1613, 3686, - 1613, 3690, - 1614, 3690, - 1614, 3691, - 1619, 3691, - 1619, 3690, - 1620, 3690, - 1620, 3689, - 1630, 3689, - 1630, 3686, - 1620, 3686, - 1620, 3685, - 1619, 3685, - 1619, 3683, - 1620, 3683, - 1620, 3682, - 1621, 3682, - 1621, 3681, - 1622, 3681, - 1622, 3680, - 1623, 3680, - 1623, 3679, - 1624, 3679, - 1624, 3668, - 1623, 3668, - 1623, 3667, - 1622, 3667, - 1622, 3666, - 1621, 3666, - 1621, 3665, - 1620, 3665, - 1620, 3664, - 1619, 3664, - 1619, 3662, - 1620, 3662, - 1620, 3661, - 1627, 3661); - } - - private static void definePvpSafeZones() - { - // Grand exchange - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3159, 3473, - 3159, 3474, - 3157, 3474, - 3157, 3475, - 3155, 3475, - 3155, 3476, - 3153, 3476, - 3153, 3477, - 3152, 3477, - 3152, 3478, - 3151, 3478, - 3151, 3480, - 3150, 3480, - 3150, 3482, - 3149, 3482, - 3149, 3484, - 3148, 3484, - 3148, 3496, - 3149, 3496, - 3149, 3498, - 3150, 3498, - 3150, 3500, - 3151, 3500, - 3151, 3502, - 3152, 3502, - 3152, 3503, - 3153, 3503, - 3153, 3504, - 3155, 3504, - 3155, 3505, - 3157, 3505, - 3157, 3506, - 3159, 3506, - 3159, 3507, - 3171, 3507, - 3171, 3506, - 3173, 3506, - 3173, 3505, - 3175, 3505, - 3175, 3504, - 3177, 3504, - 3177, 3503, - 3178, 3503, - 3178, 3502, - 3179, 3502, - 3179, 3500, - 3180, 3500, - 3180, 3498, - 3181, 3498, - 3181, 3496, - 3182, 3496, - 3182, 3484, - 3181, 3484, - 3181, 3482, - 3180, 3482, - 3180, 3480, - 3179, 3480, - 3179, 3478, - 3178, 3478, - 3178, 3477, - 3177, 3477, - 3177, 3476, - 3175, 3476, - 3175, 3475, - 3173, 3475, - 3173, 3474, - 3171, 3474, - 3171, 3473); - - // Edgeville - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3091, 3488, - 3091, 3493, - 3090, 3493, - 3090, 3498, - 3091, 3498, - 3091, 3500, - 3099, 3500, - 3099, 3488); - - // Fally west bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2943, 3368, - 2943, 3374, - 2948, 3374, - 2948, 3370, - 2950, 3370, - 2950, 3366, - 2949, 3366, - 2949, 3359, - 2945, 3359, - 2945, 3362, - 2946, 3362, - 2946, 3366, - 2945, 3366, - 2945, 3368); - - // Fally east bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3009, 3353, - 3009, 3359, - 3019, 3359, - 3019, 3357, - 3022, 3357, - 3022, 3353); - - // Fally castle - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2964, 3354, - 2966, 3354, - 2966, 3352, - 2967, 3352, - 2967, 3349, - 2976, 3349, - 2976, 3348, - 2977, 3348, - 2977, 3347, - 2981, 3347, - 2981, 3343, - 2982, 3343, - 2982, 3339, - 2981, 3339, - 2981, 3337, - 2967, 3337, - 2967, 3330, - 2963, 3330, - 2963, 3331, - 2962, 3331, - 2962, 3332, - 2961, 3332, - 2961, 3334, - 2964, 3334, - 2964, 3335, - 2965, 3335, - 2965, 3343, - 2964, 3343, - 2964, 3344, - 2961, 3344, - 2961, 3350, - 2963, 3350, - 2963, 3352, - 2964, 3352); - - // Varrock east bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3250, 3425, - 3258, 3425, - 3258, 3416, - 3250, 3416); - - // Varrock west bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3180, 3433, - 3180, 3448, - 3191, 3448, - 3191, 3433); - - // Port phasmatys - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3686, 3472, - 3700, 3472, - 3700, 3461, - 3686, 3461); - - // Yanille bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2609, 3088, - 2609, 3098, - 2617, 3098, - 2617, 3088); - - // Ardy east bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2649, 3280, - 2649, 3288, - 2659, 3288, - 2659, 3280); - - // Ardy west bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2612, 3330, - 2612, 3336, - 2615, 3336, - 2615, 3335, - 2619, 3335, - 2619, 3336, - 2622, 3336, - 2622, 3330); - - // Fishing guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2593, 3413, - 2588, 3413, - 2588, 3418, - 2583, 3418, - 2583, 3423, - 2590, 3423, - 2590, 3420, - 2593, 3420); - - // Gnome stronghold bank near slayer cave (2nd floor) - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, - 2444, 3431, - 2444, 3435, - 2448, 3435, - 2448, 3431, - 2447, 3431, - 2447, 3428, - 2449, 3428, - 2449, 3422, - 2447, 3422, - 2447, 3419, - 2448, 3419, - 2448, 3415, - 2444, 3415, - 2444, 3419, - 2445, 3419, - 2445, 3422, - 2443, 3422, - 2443, 3428, - 2445, 3428, - 2445, 3431); - - // Gnome stronghold bank in grand tree - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, - 2456, 3488, - 2452, 3488, - 2452, 3486, - 2450, 3486, - 2450, 3483, - 2451, 3483, - 2451, 3478, - 2448, 3478, - 2448, 3483, - 2449, 3483, - 2449, 3486, - 2447, 3486, - 2447, 3488, - 2443, 3488, - 2443, 3487, - 2438, 3487, - 2438, 3490, - 2443, 3490, - 2443, 3489, - 2447, 3489, - 2447, 3491, - 2449, 3491, - 2449, 3494, - 2448, 3494, - 2448, 3496, - 2451, 3496, - 2451, 3494, - 2450, 3494, - 2450, 3491, - 2452, 3491, - 2452, 3489, - 2456, 3489); - - // Al kharid bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3265, 3161, - 3265, 3174, - 3273, 3174, - 3273, 3161); - - // Shantay pass bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3308, 3119, - 3308, 3125, - 3310, 3125, - 3310, 3119); - - // Nardah bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3431, 2891, - 3431, 2889, - 3427, 2889, - 3427, 2887, - 3424, 2887, - 3424, 2895, - 3431, 2895, - 3431, 2893, - 3432, 2893, - 3432, 2891); - - // Sophanem bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2807, 5158, - 2792, 5158, - 2792, 5175, - 2807, 5175); - - // Canifis bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3509, 3474, - 3509, 3478, - 3508, 3478, - 3508, 3483, - 3509, 3483, - 3509, 3484, - 3517, 3484, - 3517, 3477, - 3516, 3477, - 3516, 3476, - 3513, 3476, - 3513, 3474); - - // Lumbridge castle outside - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3216, 3209, - 3216, 3210, - 3217, 3210, - 3217, 3228, - 3216, 3228, - 3216, 3229, - 3227, 3229, - 3227, 3221, - 3230, 3221, - 3230, 3217, - 3227, 3217, - 3227, 3209); - - // Lumbridge bank upstairs - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, - 3211, 3223, - 3211, 3215, - 3207, 3215, - 3207, 3223); - - // Draynor bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3098, 3240, - 3088, 3240, - 3088, 3247, - 3098, 3247); - - // Pest control bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2665, 2656, - 2670, 2656, - 2670, 2651, - 2665, 2651); - - // Shilo village bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2843, 2957, - 2846, 2957, - 2846, 2956, - 2849, 2956, - 2849, 2957, - 2850, 2957, - 2850, 2958, - 2855, 2958, - 2855, 2957, - 2856, 2957, - 2856, 2956, - 2858, 2956, - 2858, 2957, - 2862, 2957, - 2862, 2952, - 2858, 2952, - 2858, 2953, - 2856, 2953, - 2856, 2952, - 2855, 2952, - 2855, 2951, - 2850, 2951, - 2850, 2952, - 2849, 2952, - 2849, 2953, - 2847, 2953, - 2847, 2952, - 2843, 2952); - - // Legends guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, - 2731, 3374, - 2731, 3383, - 2734, 3383, - 2734, 3374); - - // Legends guild middle floor - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, - 2724, 3374, - 2724, 3383, - 2734, 3383, - 2734, 3382, - 2736, 3382, - 2736, 3375, - 2734, 3375, - 2734, 3374); - - // Warriors guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2843, 3537, - 2843, 3540, - 2841, 3540, - 2841, 3546, - 2849, 3546, - 2849, 3537, - 2847, 3537, - 2847, 3536, - 2846, 3536, - 2846, 3537); - - // Camelot bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2724, 3487, - 2724, 3490, - 2721, 3490, - 2721, 3494, - 2719, 3494, - 2719, 3497, - 2721, 3497, - 2721, 3498, - 2731, 3498, - 2731, 3490, - 2728, 3490, - 2728, 3487); - - // Camelot respawn point - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2761, 3483, - 2761, 3476, - 2755, 3476, - 2755, 3483); - - // Catherby bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2806, 3438, - 2806, 3446, - 2813, 3446, - 2813, 3438); - - // Barbarian outpost bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2536, 3572, - 2536, 3575, - 2538, 3575, - 2538, 3572); - - // Piscatoris bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2327, 3686, - 2327, 3694, - 2333, 3694, - 2333, 3686); - - // Lletya bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2350, 3161, - 2350, 3165, - 2351, 3165, - 2351, 3167, - 2357, 3167, - 2357, 3165, - 2356, 3165, - 2356, 3164, - 2355, 3164, - 2355, 3161); - - // Castle wars bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2446, 3087, - 2445, 3087, - 2445, 3085, - 2447, 3085, - 2447, 3081, - 2443, 3081, - 2443, 3082, - 2439, 3082, - 2439, 3081, - 2435, 3081, - 2435, 3099, - 2439, 3099, - 2439, 3098, - 2443, 3098, - 2443, 3099, - 2447, 3099, - 2447, 3095, - 2445, 3095, - 2445, 3093, - 2446, 3093); - - // Duel arena bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3380, 3267, - 3380, 3273, - 3381, 3273, - 3381, 3274, - 3385, 3274, - 3385, 3267); - - // Clan wars bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3375, 3165, - 3361, 3165, - 3361, 3173, - 3375, 3173); - - // Lumbridge cellar bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 3218, 9622, - 3218, 9624, - 3220, 9624, - 3220, 9622); - - // Dorgesh kaan bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2709, 5348, - 2707, 5348, - 2707, 5345, - 2701, 5345, - 2701, 5347, - 2697, 5347, - 2697, 5353, - 2701, 5353, - 2701, 5355, - 2707, 5355, - 2707, 5350, - 2709, 5350); - - // Keldagrim bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2842, 10204, - 2834, 10204, - 2834, 10216, - 2842, 10216); - - // Tzhaar bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2438, 5176, - 2438, 5180, - 2441, 5180, - 2441, 5182, - 2449, 5182, - 2449, 5181, - 2450, 5181, - 2450, 5180, - 2452, 5180, - 2452, 5175, - 2441, 5175, - 2441, 5176); - - // Inferno bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2542, 5135, - 2542, 5139, - 2539, 5139, - 2539, 5140, - 2538, 5140, - 2538, 5141, - 2537, 5141, - 2537, 5144, - 2541, 5144, - 2541, 5145, - 2543, 5145, - 2543, 5144, - 2544, 5144, - 2544, 5142, - 2545, 5142, - 2545, 5135); - - // Port khazard bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2661, 3160, - 2661, 3163, - 2666, 3163, - 2666, 3160); - - // Corsair cove bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2569, 2863, - 2569, 2868, - 2572, 2868, - 2572, 2863); - - // Burgh de rott bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3495, 3210, - 3495, 3214, - 3501, 3214, - 3501, 3210); - - // Edgeville respawn point - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3092, 3468, - 3092, 3474, - 3098, 3474, - 3098, 3468); - - // Mage bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2529, 4711, - 2529, 4724, - 2548, 4724, - 2548, 4711); - - // Lunar bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2097, 3917, - 2097, 3922, - 2105, 3922, - 2105, 3917); - - // Jatizo bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2414, 3801, - 2414, 3804, - 2420, 3804, - 2420, 3801); - - // Neitiznot bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2334, 3805, - 2334, 3809, - 2340, 3809, - 2340, 3805); - - // Hosidius bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1671, 3558, - 1671, 3577, - 1682, 3577, - 1682, 3558); - - // Woodcutting guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1589, 3475, - 1589, 3481, - 1594, 3481, - 1594, 3475); - - // Lands end bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1508, 3415, - 1508, 3424, - 1514, 3424, - 1514, 3415); - - // Chambers of xeric bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1252, 3570, - 1252, 3574, - 1257, 3574, - 1257, 3570); - - // Arceuus bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1621, 3736, - 1621, 3754, - 1627, 3754, - 1627, 3751, - 1633, 3751, - 1633, 3754, - 1639, 3754, - 1639, 3736); - - // Piscarilius bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1794, 3784, - 1794, 3794, - 1812, 3794, - 1812, 3784); - - // Lovakengj bank southeast - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1518, 3735, - 1518, 3744, - 1535, 3744, - 1535, 3735); - - // Lovakenj bank west - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1433, 3820, - 1433, 3837, - 1442, 3837, - 1442, 3820); - - // Lovakenj sulphur mine bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1452, 3855, - 1452, 3860, - 1455, 3860, - 1455, 3855); - - // Blast mine bank southeast - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1500, 3856, - 1500, 3858, - 1503, 3858, - 1503, 3856); - - // Wintertodt bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1638, 3942, - 1638, 3947, - 1642, 3947, - 1642, 3942); - - // Shayzien bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1495, 3612, - 1495, 3622, - 1515, 3622, - 1515, 3612); - - // Hosidius grape farm bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1804, 3571, - 1804, 3572, - 1808, 3572, - 1808, 3571); - - // Hosidius cooking bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1652, 3605, - 1652, 3615, - 1661, 3615, - 1661, 3605); - - // Ecteria bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2618, 3893, - 2618, 3897, - 2622, 3897, - 2622, 3893); - - // Mining guild expanded area - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 3018, 9733, - 3021, 9733, - 3021, 9729, - 3022, 9729, - 3022, 9728, - 3023, 9728, - 3023, 9727, - 3025, 9727, - 3025, 9726, - 3026, 9726, - 3026, 9725, - 3030, 9725, - 3030, 9726, - 3032, 9726, - 3032, 9727, - 3035, 9727, - 3035, 9726, - 3038, 9726, - 3038, 9727, - 3041, 9727, - 3041, 9728, - 3042, 9728, - 3042, 9730, - 3045, 9730, - 3045, 9727, - 3047, 9727, - 3047, 9726, - 3048, 9726, - 3048, 9724, - 3052, 9724, - 3052, 9725, - 3053, 9725, - 3053, 9726, - 3055, 9726, - 3055, 9725, - 3056, 9725, - 3056, 9723, - 3057, 9723, - 3057, 9720, - 3056, 9720, - 3056, 9719, - 3054, 9719, - 3054, 9718, - 3052, 9718, - 3052, 9717, - 3050, 9717, - 3050, 9718, - 3045, 9718, - 3045, 9716, - 3044, 9716, - 3044, 9715, - 3041, 9715, - 3041, 9714, - 3039, 9714, - 3039, 9713, - 3037, 9713, - 3037, 9714, - 3036, 9714, - 3036, 9715, - 3034, 9715, - 3034, 9716, - 3029, 9716, - 3029, 9715, - 3028, 9715, - 3028, 9714, - 3026, 9714, - 3026, 9709, - 3027, 9709, - 3027, 9708, - 3028, 9708, - 3028, 9705, - 3029, 9705, - 3029, 9701, - 3028, 9701, - 3028, 9700, - 3027, 9700, - 3027, 9699, - 3023, 9699, - 3023, 9700, - 3019, 9700, - 3019, 9701, - 3018, 9701, - 3018, 9705, - 3019, 9705, - 3019, 9707, - 3020, 9707, - 3020, 9708, - 3021, 9708, - 3021, 9709, - 3022, 9709, - 3022, 9713, - 3021, 9713, - 3021, 9714, - 3019, 9714, - 3019, 9715, - 3018, 9715, - 3018, 9717, - 3015, 9717, - 3015, 9716, - 3013, 9716, - 3013, 9717, - 3012, 9717, - 3012, 9720, - 3013, 9720, - 3013, 9721, - 3015, 9721, - 3015, 9723, - 3016, 9723, - 3016, 9727, - 3017, 9727, - 3017, 9730, - 3018, 9730); - - // Motherlode mine bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 3760, 5671, - 3760, 5668, - 3761, 5668, - 3761, 5665, - 3760, 5665, - 3760, 5663, - 3758, 5663, - 3758, 5671); - - // Mos le harmles bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3679, 2980, - 3679, 2985, - 3681, 2985, - 3681, 2984, - 3682, 2984, - 3682, 2985, - 3684, 2985, - 3684, 2980, - 3682, 2980, - 3682, 2981, - 3681, 2981, - 3681, 2980); - - // Zanaris bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2388, 4454, - 2380, 4454, - 2380, 4463, - 2388, 4463); - - // Wodcuting guild bank underground - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 1550, 9872, - 1550, 9874, - 1553, 9874, - 1553, 9872); - } - - private static void defineWilderness() - { - // Above ground - addPolygonTo(ROUGH_WILDERNESS, - 2944, 3523, - 3392, 3523, - 3392, 3971, - 2944, 3971); - - // Underground - addPolygonTo(ROUGH_WILDERNESS, - 2944, 9918, - 2944, 10360, - 3264, 10360, - 3264, 9918); - } - - private static void addPolygonTo(List[] shapes, int... coords) - { - Polygon poly = new Polygon(); - for (int i = 0; i < coords.length; i += 2) - { - poly.addPoint(coords[i], coords[i + 1]); - } - for (int i = 0; i < shapes.length; i++) - { - shapes[i].add(poly); - } - } - - private static void addPolygonOnPlane(List[] shapes, int plane, int... coords) - { - Polygon poly = new Polygon(); - for (int i = 0; i < coords.length; i += 2) - { - poly.addPoint(coords[i], coords[i + 1]); - } - shapes[plane].add(poly); - } - - private static void addPolygonOnPlanes(List[] shapes, int minPlane, int maxPlane, int... coords) - { - Polygon poly = new Polygon(); - for (int i = 0; i < coords.length; i += 2) - { - poly.addPoint(coords[i], coords[i + 1]); - } - for (int i = minPlane; i <= maxPlane; i++) - { - shapes[i].add(poly); - } - } +/* + * Copyright (c) 2018, Woox + * 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.multiindicators; + +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Area; +import java.util.ArrayList; +import java.util.List; +import net.runelite.api.Constants; + +public class MapLocations +{ + private static final List[] MULTICOMBAT = new List[Constants.MAX_Z]; + private static final List[] NOT_MULTICOMBAT = new List[Constants.MAX_Z]; + private static final List[] ROUGH_WILDERNESS = new List[Constants.MAX_Z]; + private static final List[] DEADMAN_SAFE_ZONES = new List[Constants.MAX_Z]; + private static final List[] PVP_WORLD_SAFE_ZONES = new List[Constants.MAX_Z]; + + private static Area getArea(List shapes) + { + Area area = new Area(); + for (Shape shape : shapes) + { + area.add(new Area(shape)); + } + return area; + } + + private static Area getArea(List shapes, Rectangle view) + { + Area area = new Area(); + for (Shape shape : shapes) + { + if (shape.intersects(view)) + { + area.add(new Area(shape)); + } + } + return area; + } + + public static Area getMulticombat(int plane) + { + Area area = getArea(MULTICOMBAT[plane]); + area.subtract(getArea(NOT_MULTICOMBAT[plane])); + return area; + } + + public static Area getMulticombat(Rectangle view, int plane) + { + Area area = getArea(MULTICOMBAT[plane], view); + area.subtract(getArea(NOT_MULTICOMBAT[plane], view)); + return area; + } + + public static Area getRoughWilderness(int plane) + { + return getArea(ROUGH_WILDERNESS[plane]); + } + + public static Area getRoughWilderness(Rectangle view, int plane) + { + return getArea(ROUGH_WILDERNESS[plane], view); + } + + public static Area getDeadmanSafeZones(int plane) + { + return getArea(DEADMAN_SAFE_ZONES[plane]); + } + + public static Area getDeadmanSafeZones(Rectangle view, int plane) + { + return getArea(DEADMAN_SAFE_ZONES[plane], view); + } + + public static Area getPvpSafeZones(int plane) + { + return getArea(PVP_WORLD_SAFE_ZONES[plane]); + } + + public static Area getPvpSafeZones(Rectangle view, int plane) + { + return getArea(PVP_WORLD_SAFE_ZONES[plane], view); + } + + static + { + for (int i = 0; i < MULTICOMBAT.length; i++) + { + MULTICOMBAT[i] = new ArrayList<>(); + } + for (int i = 0; i < NOT_MULTICOMBAT.length; i++) + { + NOT_MULTICOMBAT[i] = new ArrayList<>(); + } + for (int i = 0; i < ROUGH_WILDERNESS.length; i++) + { + ROUGH_WILDERNESS[i] = new ArrayList<>(); + } + for (int i = 0; i < DEADMAN_SAFE_ZONES.length; i++) + { + DEADMAN_SAFE_ZONES[i] = new ArrayList<>(); + } + for (int i = 0; i < PVP_WORLD_SAFE_ZONES.length; i++) + { + PVP_WORLD_SAFE_ZONES[i] = new ArrayList<>(); + } + + defineMulticombatAreas(); + defineDeadmanSafeZones(); + definePvpSafeZones(); + defineWilderness(); + } + + private static void defineMulticombatAreas() + { + // Main Wilderness + addPolygonOnPlane(MULTICOMBAT, 0, + 3200, 3968, + 3392, 3968, + 3392, 3840, + 3328, 3840, + 3328, 3520, + 3136, 3520, + 3136, 3648, + 3192, 3648, + 3192, 3752, + 3152, 3752, + 3152, 3840, + 3136, 3840, + 3136, 3872, + 3112, 3872, + 3112, 3880, + 3072, 3880, + 3072, 3896, + 3048, 3896, + 3048, 3872, + 3056, 3872, + 3056, 3864, + 3048, 3864, + 3048, 3856, + 3008, 3856, + 3008, 3904, + 3200, 3904); + + // South of wildy agility training arena + addPolygonOnPlane(MULTICOMBAT, 0, + 2984, 3928, + 3008, 3928, + 3008, 3912, + 2984, 3912); + + // Wildy zamorak temple + addPolygonOnPlane(MULTICOMBAT, 0, + 2944, 3832, + 2960, 3832, + 2960, 3816, + 2944, 3816); + + // Wildy bandit camp + addPolygonOnPlane(MULTICOMBAT, 0, + 3008, 3712, + 3072, 3712, + 3072, 3600, + 3008, 3600); + + // Chaos temple north of Falador + addPolygonOnPlane(MULTICOMBAT, 0, + 2928, 3520, + 2944, 3520, + 2944, 3512, + 2928, 3512); + + // Burthorpe + addPolygonOnPlane(MULTICOMBAT, 0, + 2880, 3544, + 2904, 3544, + 2904, 3520, + 2880, 3520); + + // White Wolf Mountain + addPolygonOnPlane(MULTICOMBAT, 0, + 2880, 3520, + 2816, 3520, + 2816, 3456, + 2880, 3456); + + // Death Plateu + addPolygonOnPlane(MULTICOMBAT, 0, + 2848, 3608, + 2880, 3608, + 2880, 3600, + 2848, 3600); + + // Trollheim/Godwars + addPolygonOnPlane(MULTICOMBAT, 0, + 2880, 3776, + 2912, 3776, + 2912, 3696, + 2920, 3696, + 2920, 3688, + 2896, 3688, + 2896, 3696, + 2880, 3696, + 2880, 3728, + 2888, 3728, + 2888, 3744, + 2880, 3744); + + // Northen Rellekka + addPolygonOnPlane(MULTICOMBAT, 0, + 2656, 3736, + 2704, 3736, + 2704, 3728, + 2712, 3728, + 2712, 3736, + 2736, 3736, + 2736, 3712, + 2656, 3712); + + // Northen Fremennik Isles + addPolygonOnPlane(MULTICOMBAT, 0, + 2304, 3904, + 2432, 3904, + 2432, 3840, + 2368, 3840, + 2368, 3816, + 2352, 3816, + 2352, 3824, + 2304, 3824); + + // Pirates Cove + addPolygonOnPlane(MULTICOMBAT, 0, + 2176, 3840, + 2240, 3840, + 2240, 3776, + 2176, 3776); + + // Lunar Isle + addPolygonOnPlane(MULTICOMBAT, 0, + 2048, 3968, + 2176, 3968, + 2176, 3840, + 2048, 3840); + + // Piscatoris Fishing Colony + addPolygonOnPlane(MULTICOMBAT, 0, + 2304, 3712, + 2368, 3712, + 2368, 3648, + 2304, 3648); + + // Ranging Guild + addPolygonOnPlane(MULTICOMBAT, 0, + 2656, 3448, + 2680, 3448, + 2680, 3440, + 2688, 3440, + 2688, 3416, + 2680, 3416, + 2680, 3408, + 2656, 3408, + 2656, 3416, + 2648, 3416, + 2648, 3440, + 2656, 3440); + + // Necromancer house, southeast of Ardy + addPolygonOnPlane(MULTICOMBAT, 0, + 2656, 3256, + 2680, 3256, + 2680, 3216, + 2664, 3216, + 2664, 3232, + 2656, 3232); + + // Battlefield noth of Tree Gnome Village + addPolygonOnPlane(MULTICOMBAT, 0, + 2504, 3248, + 2544, 3248, + 2544, 3232, + 2552, 3232, + 2552, 3208, + 2504, 3208); + + // Castle Wars + addPolygonOnPlane(MULTICOMBAT, 0, + 2368, 3136, + 2432, 3136, + 2432, 3072, + 2368, 3072); + + // Jiggig + addPolygonOnPlane(MULTICOMBAT, 0, + 2456, 3056, + 2496, 3056, + 2496, 3032, + 2456, 3032); + + // East feldip hills, near rantz + addPolygonOnPlane(MULTICOMBAT, 0, + 2648, 2976, + 2656, 2976, + 2656, 2952, + 2648, 2952); + + // Ape Atoll + addPolygonOnPlane(MULTICOMBAT, 0, + 2688, 2816, + 2816, 2816, + 2816, 2688, + 2688, 2688); + + // Pest Control + addPolygonOnPlane(MULTICOMBAT, 0, + 2624, 2624, + 2688, 2624, + 2688, 2560, + 2624, 2560); + + // Desert Bandit Camp + addPolygonOnPlane(MULTICOMBAT, 0, + 3152, 3000, + 3192, 3000, + 3192, 2960, + 3152, 2960); + + // Al Kharid + addPolygonOnPlane(MULTICOMBAT, 0, + 3264, 3200, + 3328, 3200, + 3328, 3136, + 3264, 3136); + + // Wizards Tower + addPolygonOnPlane(MULTICOMBAT, 0, + 3094, 3176, + 3126, 3176, + 3126, 3144, + 3094, 3144); + + // Draynor Village + addPolygonOnPlane(MULTICOMBAT, 0, + 3112, 3264, + 3136, 3264, + 3136, 3232, + 3104, 3232, + 3104, 3256, + 3112, 3256); + + // Falador + addPolygonOnPlane(MULTICOMBAT, 0, + 2944, 3456, + 3008, 3456, + 3008, 3328, + 3016, 3328, + 3016, 3304, + 2944, 3304); + + // Southwest fally castle isn't multicombat downstairs + addPolygonOnPlane(NOT_MULTICOMBAT, 0, + 2968, 3336, + 2968, 3328, + 2960, 3328, + 2960, 3336); + + // Barbarian Village + addPolygonOnPlane(MULTICOMBAT, 0, + 3072, 3456, + 3136, 3456, + 3136, 3392, + 3048, 3392, + 3048, 3408, + 3056, 3408, + 3056, 3440, + 3064, 3440, + 3064, 3448, + 3072, 3448); + + // Ammoniate crabs at northwest fossil island + addPolygonOnPlane(MULTICOMBAT, 0, + 3648, 3885, + 3663, 3885, + 3663, 3882, + 3664, 3882, + 3664, 3872, + 3663, 3872, + 3663, 3868, + 3648, 3868); + + // Ammoniate crabs at north fossil island + addPolygonOnPlane(MULTICOMBAT, 0, + 3680, 3904, + 3744, 3904, + 3744, 3856, + 3756, 3856, + 3756, 3852, + 3755, 3852, + 3755, 3851, + 3754, 3851, + 3754, 3850, + 3751, 3850, + 3751, 3849, + 3750, 3849, + 3750, 3848, + 3749, 3848, + 3749, 3847, + 3748, 3847, + 3748, 3846, + 3747, 3846, + 3747, 3845, + 3746, 3845, + 3746, 3844, + 3742, 3844, + 3742, 3845, + 3740, 3845, + 3740, 3844, + 3732, 3844, + 3732, 3843, + 3730, 3843, + 3730, 3842, + 3724, 3842, + 3724, 3843, + 3717, 3843, + 3717, 3842, + 3712, 3842, + 3712, 3846, + 3710, 3846, + 3710, 3847, + 3709, 3847, + 3709, 3848, + 3708, 3848, + 3708, 3859, + 3709, 3859, + 3709, 3860, + 3710, 3860, + 3710, 3861, + 3712, 3861, + 3712, 3866, + 3713, 3866, + 3713, 3870, + 3714, 3870, + 3714, 3873, + 3713, 3873, + 3713, 3876, + 3712, 3876, + 3712, 3881, + 3710, 3881, + 3710, 3888, + 3712, 3888, + 3712, 3890, + 3714, 3890, + 3714, 3891, + 3716, 3891, + 3716, 3892, + 3717, 3892, + 3717, 3893, + 3716, 3893, + 3716, 3894, + 3714, 3894, + 3714, 3895, + 3713, 3895, + 3713, 3896, + 3712, 3896, + 3712, 3897, + 3705, 3897, + 3705, 3898, + 3704, 3898, + 3704, 3899, + 3692, 3899, + 3692, 3898, + 3688, 3898, + 3688, 3897, + 3686, 3897, + 3686, 3896, + 3680, 3896); + + // Zeah, southwest of Wintertodt, snowy area with ice giants and wolves + addPolygonOnPlane(MULTICOMBAT, 0, + 1540, 3898, + 1543, 3898, + 1543, 3901, + 1546, 3901, + 1546, 3903, + 1547, 3903, + 1547, 3904, + 1550, 3904, + 1550, 3903, + 1553, 3903, + 1553, 3904, + 1559, 3904, + 1559, 3902, + 1564, 3902, + 1564, 3903, + 1565, 3903, + 1565, 3904, + 1568, 3904, + 1568, 3903, + 1569, 3903, + 1569, 3902, + 1570, 3902, + 1570, 3901, + 1573, 3901, + 1573, 3898, + 1577, 3898, + 1577, 3899, + 1578, 3899, + 1578, 3902, + 1579, 3902, + 1579, 3903, + 1584, 3903, + 1584, 3902, + 1586, 3902, + 1586, 3901, + 1590, 3901, + 1590, 3891, + 1588, 3891, + 1588, 3887, + 1572, 3887, + 1572, 3872, + 1567, 3872, + 1567, 3868, + 1563, 3868, + 1563, 3867, + 1558, 3867, + 1558, 3868, + 1557, 3868, + 1557, 3870, + 1549, 3870, + 1549, 3874, + 1545, 3874, + 1545, 3876, + 1543, 3876, + 1543, 3877, + 1542, 3877, + 1542, 3879, + 1541, 3879, + 1541, 3882, + 1539, 3882, + 1539, 3887, + 1540, 3887, + 1540, 3888, + 1539, 3888, + 1539, 3894, + 1540, 3894); + + // Zeah arceuus area + addPolygonOnPlane(MULTICOMBAT, 0, + 1664, 3776, + 1664, 3785, + 1667, 3785, + 1667, 3805, + 1671, 3805, + 1671, 3811, + 1675, 3811, + 1675, 3819, + 1690, 3819, + 1690, 3814, + 1695, 3814, + 1695, 3806, + 1719, 3806, + 1719, 3787, + 1725, 3787, + 1725, 3778, + 1711, 3778, + 1711, 3776); + + // Arceuus teletab-making house + addPolygonOnPlane(MULTICOMBAT, 0, + 1667, 3772, + 1679, 3772, + 1679, 3775, + 1691, 3775, + 1691, 3761, + 1679, 3761, + 1679, 3764, + 1667, 3764); + // Next house east + addPolygonOnPlane(MULTICOMBAT, 0, + 1696, 3775, + 1708, 3775, + 1708, 3763, + 1696, 3763); + // Next house east + addPolygonOnPlane(MULTICOMBAT, 0, + 1713, 3775, + 1727, 3775, + 1727, 3763, + 1724, 3763, + 1724, 3752, + 1716, 3752, + 1716, 3763, + 1713, 3763); + // Arceuus rune shop house + addPolygonOnPlane(MULTICOMBAT, 0, + 1716, 3750, + 1728, 3750, + 1728, 3736, + 1716, 3736); + // Arceuus general store house + addPolygonOnPlane(MULTICOMBAT, 0, + 1717, 3732, + 1725, 3732, + 1725, 3715, + 1715, 3715, + 1715, 3725, + 1717, 3725); + // Arceuus pub + addPolygonOnPlane(MULTICOMBAT, 0, + 1683, 3732, + 1691, 3732, + 1691, 3725, + 1697, 3725, + 1697, 3730, + 1703, 3730, + 1703, 3712, + 1683, 3712); + // Arceuus staff store + addPolygonOnPlane(MULTICOMBAT, 0, + 1664, 3732, + 1676, 3732, + 1676, 3720, + 1664, 3720); + // Next house to the west + addPolygonOnPlane(MULTICOMBAT, 0, + 1647, 3738, + 1655, 3738, + 1655, 3726, + 1658, 3726, + 1658, 3714, + 1644, 3714, + 1644, 3726, + 1647, 3726); + // Next house to the north + addPolygonOnPlane(MULTICOMBAT, 0, + 1647, 3762, + 1657, 3762, + 1657, 3752, + 1655, 3752, + 1655, 3745, + 1647, 3745); + + // Arceuus house magic trees + addPolygonOnPlane(MULTICOMBAT, 0, + 1682, 3755, + 1692, 3755, + 1692, 3745, + 1690, 3745, + 1690, 3738, + 1682, 3738); + // West of that ^ + addPolygonOnPlane(MULTICOMBAT, 0, + 1667, 3756, + 1675, 3756, + 1675, 3740, + 1665, 3740, + 1665, 3746, + 1667, 3746); + + // This one goes through western piscarilius, northen hosidius + // and southwestern arceuus + addPolygonOnPlane(MULTICOMBAT, 0, + 1728, 3808, + 1792, 3808, + 1792, 3764, + 1856, 3764, + 1856, 3712, + 1792, 3712, + 1792, 3648, + 1664, 3648, + 1664, 3706, + 1665, 3706, + 1665, 3705, + 1668, 3705, + 1668, 3706, + 1671, 3706, + 1671, 3705, + 1675, 3705, + 1675, 3704, + 1683, 3704, + 1683, 3701, + 1684, 3701, + 1684, 3700, + 1686, 3700, + 1686, 3702, + 1687, 3702, + 1687, 3700, + 1688, 3700, + 1688, 3701, + 1690, 3701, + 1690, 3703, + 1689, 3703, + 1689, 3704, + 1690, 3704, + 1690, 3705, + 1704, 3705, + 1704, 3707, + 1706, 3707, + 1706, 3712, + 1711, 3712, + 1711, 3711, + 1710, 3711, + 1710, 3710, + 1712, 3710, + 1712, 3707, + 1728, 3707); + + // Kourend castle + addPolygonOnPlane(MULTICOMBAT, 0, + 1614, 3691, + 1619, 3691, + 1619, 3690, + 1620, 3690, + 1620, 3689, + 1653, 3689, + 1653, 3690, + 1654, 3690, + 1654, 3691, + 1657, 3691, + 1657, 3690, + 1658, 3690, + 1658, 3689, + 1659, 3689, + 1659, 3686, + 1658, 3686, + 1658, 3685, + 1657, 3685, + 1657, 3662, + 1658, 3662, + 1658, 3661, + 1659, 3661, + 1659, 3658, + 1658, 3658, + 1658, 3657, + 1657, 3657, + 1657, 3656, + 1654, 3656, + 1654, 3657, + 1653, 3657, + 1653, 3658, + 1620, 3658, + 1620, 3657, + 1619, 3657, + 1619, 3656, + 1614, 3656, + 1614, 3657, + 1613, 3657, + 1613, 3661, + 1612, 3661, + 1612, 3662, + 1611, 3662, + 1611, 3663, + 1600, 3663, + 1600, 3662, + 1599, 3662, + 1599, 3661, + 1594, 3661, + 1594, 3662, + 1593, 3662, + 1593, 3685, + 1594, 3685, + 1594, 3686, + 1599, 3686, + 1599, 3685, + 1600, 3685, + 1600, 3684, + 1611, 3684, + 1611, 3685, + 1612, 3685, + 1612, 3686, + 1613, 3686, + 1613, 3690, + 1614, 3690); + + // Western hosidius area, including woodcutting guild and western sand crabs + addPolygonOnPlane(MULTICOMBAT, 0, + 1650, 3648, + 1664, 3648, + 1664, 3520, + 1689, 3520, + 1689, 3496, + 1707, 3496, + 1707, 3485, + 1708, 3485, + 1708, 3484, + 1710, 3484, + 1710, 3483, + 1713, 3483, + 1713, 3482, + 1720, 3482, + 1720, 3481, + 1721, 3481, + 1721, 3480, + 1722, 3480, + 1722, 3479, + 1723, 3479, + 1723, 3478, + 1724, 3478, + 1724, 3477, + 1726, 3477, + 1726, 3476, + 1728, 3476, + 1728, 3472, + 1708, 3472, + 1708, 3456, + 1600, 3456, + 1600, 3584, + 1608, 3584, + 1608, 3616, + 1650, 3616); + + // Hosidius sand crabs + addPolygonOnPlane(MULTICOMBAT, 0, + 1740, 3478, + 1741, 3478, + 1741, 3479, + 1745, 3479, + 1745, 3480, + 1751, 3480, + 1751, 3479, + 1752, 3479, + 1752, 3478, + 1753, 3478, + 1753, 3477, + 1755, 3477, + 1755, 3476, + 1757, 3476, + 1757, 3475, + 1758, 3475, + 1758, 3474, + 1759, 3474, + 1759, 3473, + 1779, 3473, + 1779, 3474, + 1781, 3474, + 1781, 3475, + 1786, 3475, + 1786, 3476, + 1800, 3476, + 1800, 3475, + 1805, 3475, + 1805, 3474, + 1807, 3474, + 1807, 3473, + 1808, 3473, + 1808, 3472, + 1810, 3472, + 1810, 3471, + 1833, 3471, + 1833, 3470, + 1834, 3470, + 1834, 3469, + 1852, 3469, + 1852, 3449, + 1792, 3449, + 1792, 3424, + 1800, 3424, + 1800, 3449, + 1800, 3400, + 1728, 3400, + 1728, 3462, + 1729, 3462, + 1729, 3466, + 1730, 3466, + 1730, 3469, + 1731, 3469, + 1731, 3470, + 1732, 3470, + 1732, 3471, + 1733, 3471, + 1733, 3473, + 1734, 3473, + 1734, 3474, + 1736, 3474, + 1736, 3475, + 1737, 3475, + 1737, 3476, + 1738, 3476, + 1738, 3477, + 1740, 3477); + + // Apparently there is a 1x1 single zone on the sand crab island + addPolygonOnPlane(NOT_MULTICOMBAT, 0, + 1777, 3416, + 1777, 3417, + 1778, 3417, + 1778, 3416); + + // Eastern hosidius area + addPolygonOnPlane(MULTICOMBAT, 0, + 1834, 3584, + 1888, 3584, + 1888, 3528, + 1856, 3528, + 1856, 3520, + 1834, 3520, + 1834, 3522, + 1833, 3522, + 1833, 3535, + 1834, 3535, + 1834, 3538, + 1835, 3538, + 1835, 3539, + 1836, 3539, + 1836, 3540, + 1837, 3540, + 1837, 3541, + 1838, 3541, + 1838, 3542, + 1840, 3542, + 1840, 3543, + 1841, 3543, + 1841, 3545, + 1842, 3545, + 1842, 3546, + 1844, 3546, + 1844, 3547, + 1845, 3547, + 1845, 3548, + 1851, 3548, + 1851, 3551, + 1853, 3551, + 1853, 3563, + 1851, 3563, + 1851, 3566, + 1847, 3566, + 1847, 3567, + 1845, 3567, + 1845, 3568, + 1844, 3568, + 1844, 3569, + 1843, 3569, + 1843, 3571, + 1842, 3571, + 1842, 3573, + 1841, 3573, + 1841, 3574, + 1840, 3574, + 1840, 3575, + 1839, 3575, + 1839, 3576, + 1838, 3576, + 1838, 3577, + 1837, 3577, + 1837, 3578, + 1836, 3578, + 1836, 3579, + 1835, 3579, + 1835, 3581, + 1834, 3581); + + // Eastern hosidius area also has a 1x1 multi area + addPolygonOnPlane(MULTICOMBAT, 0, + 1849, 3563, + 1849, 3564, + 1850, 3564, + 1850, 3563); + + // Hosidius cows/chickens/pigs + addPolygonOnPlane(MULTICOMBAT, 0, + 1792, 3513, + 1802, 3513, + 1802, 3520, + 1810, 3520, + 1810, 3513, + 1816, 3513, + 1816, 3512, + 1836, 3512, + 1836, 3494, + 1796, 3494, + 1796, 3495, + 1792, 3495); + + // Hosidius southeast of tithe farm + addPolygonOnPlane(MULTICOMBAT, 0, + 1777, 3597, + 1794, 3597, + 1794, 3561, + 1777, 3561, + 1777, 3591, + 1779, 3591, + 1779, 3592, + 1777, 3592); + + // West of shayzien house + addPolygonOnPlane(MULTICOMBAT, 0, + 1408, 3584, + 1408, 3582, + 1486, 3582, + 1486, 3568, + 1528, 3568, + 1528, 3520, + 1408, 3520, + 1408, 3464, + 1380, 3464, + 1380, 3486, + 1377, 3486, + 1377, 3488, + 1373, 3488, + 1373, 3492, + 1364, 3492, + 1364, 3512, + 1358, 3512, + 1358, 3520, + 1356, 3520, + 1356, 3532, + 1358, 3532, + 1358, 3540, + 1359, 3540, + 1359, 3542, + 1360, 3542, + 1360, 3557, + 1356, 3557, + 1356, 3560, + 1351, 3560, + 1351, 3570, + 1354, 3570, + 1354, 3581, + 1346, 3581, + 1346, 3584); + + // South of chambers of xeric + addPolygonOnPlane(MULTICOMBAT, 0, + 1261, 3489, + 1259, 3489, + 1259, 3488, + 1255, 3488, + 1255, 3487, + 1243, 3487, + 1243, 3490, + 1234, 3490, + 1234, 3480, + 1192, 3480, + 1192, 3568, + 1209, 3568, + 1209, 3548, + 1215, 3548, + 1215, 3544, + 1217, 3544, + 1217, 3536, + 1235, 3536, + 1235, 3532, + 1249, 3532, + 1249, 3525, + 1248, 3525, + 1248, 3517, + 1254, 3517, + 1254, 3513, + 1274, 3513, + 1274, 3510, + 1296, 3510, + 1296, 3511, + 1300, 3511, + 1300, 3501, + 1287, 3501, + 1287, 3490, + 1280, 3490, + 1280, 3489, + 1264, 3489, + 1264, 3490, + 1261, 3490); + + // Lizardman shamans + addPolygonOnPlane(MULTICOMBAT, 0, + 1416, 3728, + 1456, 3728, + 1456, 3688, + 1416, 3688); + + // Other lizardman area at shayzien (west side) + addPolygonOnPlane(MULTICOMBAT, 0, + 1472, 3712, + 1510, 3712, + 1510, 3702, + 1509, 3702, + 1509, 3701, + 1506, 3701, + 1506, 3696, + 1500, 3696, + 1500, 3680, + 1472, 3680); + + // Other lizardman area at shayzien (east side) + addPolygonOnPlane(MULTICOMBAT, 0, + 1538, 3704, + 1560, 3704, + 1560, 3672, + 1538, 3672); + + // Lovakengj house + addPolygonOnPlane(MULTICOMBAT, 0, + 1600, 3712, + 1472, 3712, + 1472, 3840, + 1547, 3840, + 1547, 3816, + 1556, 3816, + 1556, 3809, + 1562, 3809, + 1562, 3800, + 1568, 3800, + 1568, 3793, + 1571, 3793, + 1571, 3816, + 1571, 3776, + 1600, 3776); + + // Shayzien house + addPolygonOnPlane(MULTICOMBAT, 0, + 1475, 3587, + 1475, 3641, + 1534, 3641, + 1534, 3587); + + // Shayzien house bank is non-multi + addPolygonOnPlane(NOT_MULTICOMBAT, 0, + 1495, 3622, + 1515, 3622, + 1515, 3612, + 1495, 3612); + + // Shayzien house general store + addPolygonOnPlane(MULTICOMBAT, 0, + 1539, 3640, + 1551, 3640, + 1551, 3621, + 1539, 3621); + + // Kourend woodland barbarian area + addPolygonOnPlane(MULTICOMBAT, 0, + 1572, 3442, + 1591, 3442, + 1591, 3424, + 1572, 3424); + + // Catacombs + addPolygonTo(MULTICOMBAT, + 1600, 9984, + 1600, 10067, + 1628, 10067, + 1628, 10070, + 1639, 10070, + 1639, 10112, + 1730, 10112, + 1730, 9984); + + // Zeah dungeon with sand crabs + addPolygonTo(MULTICOMBAT, + 1632, 9792, + 1632, 9856, + 1728, 9856, + 1728, 9792); + + // Waterbirth island near the doors where people use rune throwing axes + addPolygonTo(MULTICOMBAT, + 2536, 10136, + 2536, 10152, + 2552, 10152, + 2552, 10136); + + // Waterbirth island dungeon, on the path to dks + addPolygonTo(MULTICOMBAT, + 1792, 4352, + 1792, 4416, + 1984, 4416, + 1984, 4352); + + // Dagannoths in lighthouse + addPolygonTo(MULTICOMBAT, + 2496, 10048, + 2560, 10048, + 2560, 9984, + 2496, 9984); + + // Dagannoth kings (DKs) including slayer only dks + addPolygonTo(MULTICOMBAT, + 2944, 4352, + 2944, 4480, + 2880, 4480, + 2880, 4352); + + // White wolf mountain dungeon at ice queen + addPolygonTo(MULTICOMBAT, + 2856, 9928, + 2856, 9968, + 2880, 9968, + 2880, 9928); + + // Kharazi jungle dungeon (in dragon slayer 2 quest) + addPolygonTo(MULTICOMBAT, + 2816, 9296, + 2880, 9296, + 2880, 9216, + 2816, 9216); + + // Tzhaar, fight pits and inferno area + addPolygonTo(MULTICOMBAT, + 2368, 5184, + 2560, 5184, + 2560, 5056, + 2368, 5056); + + // Smoke devils + addPolygonTo(MULTICOMBAT, + 2432, 9408, + 2344, 9408, + 2344, 9472, + 2432, 9472); + + // Kraken + addPolygonTo(MULTICOMBAT, + 2270, 10045, + 2291, 10045, + 2291, 10022, + 2270, 10022); + + // Giant mole + addPolygonTo(MULTICOMBAT, + 1728, 5240, + 1792, 5240, + 1792, 5120, + 1728, 5120); + + // Godwars dungeon + addPolygonTo(MULTICOMBAT, + 2816, 5376, + 2944, 5376, + 2944, 5248, + 2816, 5248); + + // Desert treasure shadow diamond area + addPolygonTo(MULTICOMBAT, + 2752, 5064, + 2728, 5064, + 2728, 5088, + 2720, 5088, + 2720, 5096, + 2712, 5096, + 2712, 5112, + 2736, 5112, + 2736, 5120, + 2752, 5120); + + // Kalphite slayer area + addPolygonTo(MULTICOMBAT, + 3264, 9544, + 3344, 9544, + 3344, 9472, + 3264, 9472); + + // Normal kalphite area including kalphite queen + addPolygonTo(MULTICOMBAT, + 3456, 9536, + 3520, 9536, + 3520, 9472, + 3456, 9472); + + // Tarns lair + addPolygonTo(MULTICOMBAT, + 3136, 4664, + 3200, 4664, + 3200, 4544, + 3136, 4544); + + // Haunted mine boss area + addPolygonTo(MULTICOMBAT, + 2752, 4416, + 2752, 4480, + 2816, 4480, + 2816, 4416); + + // Entrance to dorgesh kaan + addPolygonTo(MULTICOMBAT, + 3328, 9600, + 3312, 9600, + 3312, 9640, + 3304, 9640, + 3304, 9664, + 3328, 9664); + + // Hammerspikes hangout in dwarven mines + addPolygonTo(MULTICOMBAT, + 2960, 9824, + 2976, 9824, + 2976, 9800, + 2960, 9800); + + // Fremennik isles dungeon + addPolygonTo(MULTICOMBAT, + 2432, 10304, + 2432, 10240, + 2368, 10240, + 2368, 10304); + + // Varrock sewers + addPolygonTo(MULTICOMBAT, + 3152, 9920, + 3288, 9920, + 3288, 9856, + 3152, 9856); + + // Stronghold of security 1st floor + addPolygonTo(MULTICOMBAT, + 1856, 5248, + 1920, 5248, + 1920, 5184, + 1856, 5184); + + // Corp cave + addPolygonTo(MULTICOMBAT, + 2960, 4400, + 3000, 4400, + 3000, 4368, + 2960, 4368); + + // ZMI altar area + addPolygonTo(MULTICOMBAT, + 3008, 5632, + 3072, 5632, + 3072, 5568, + 3008, 5568); + + // Dragon slayer 2 zeah underground puzzle + addPolygonTo(MULTICOMBAT, + 1472, 9984, + 1536, 9984, + 1536, 9920, + 1472, 9920); + + // Wildy revenant caves + addPolygonTo(MULTICOMBAT, + 3136, 10062, + 3136, 10240, + 3236, 10240, + 3236, 10229, + 3264, 10229, + 3264, 10048, + 3208, 10048, + 3208, 10062); + + // King black dragon (Kbd) + addPolygonTo(MULTICOMBAT, + 2240, 4672, + 2240, 4736, + 2304, 4736, + 2304, 4672); + + // Scorpia + addPolygonTo(MULTICOMBAT, + 3248, 10352, + 3248, 10328, + 3216, 10328, + 3216, 10352); + + // Inside mage bank + addPolygonTo(MULTICOMBAT, + 2496, 4672, + 2496, 4736, + 2560, 4736, + 2560, 4672); + + // Wildy godwars dungeon + addPolygonTo(MULTICOMBAT, + 3072, 10112, + 3008, 10112, + 3008, 10176, + 3048, 10176, + 3048, 10152, + 3056, 10152, + 3056, 10144, + 3064, 10144, + 3064, 10136, + 3072, 10136); + + // Enchanted valley + addPolygonTo(MULTICOMBAT, + 3008, 4480, + 3008, 4544, + 3072, 4544, + 3072, 4480); + + // Zulrah + addPolygonTo(MULTICOMBAT, + 2256, 3080, + 2280, 3080, + 2280, 3064, + 2256, 3064); + + // Abyssal sire and abyss + addPolygonTo(MULTICOMBAT, + 3008, 4736, + 2944, 4736, + 2944, 4864, + 3136, 4864, + 3136, 4736, + 3072, 4736, + 3072, 4800, + 3008, 4800); + } + + private static void defineDeadmanSafeZones() + { + // Varrock + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3182, 3382, + 3182, 3399, + 3174, 3399, + 3174, 3448, + 3198, 3448, + 3198, 3449, + 3197, 3449, + 3197, 3450, + 3196, 3450, + 3196, 3451, + 3195, 3451, + 3195, 3452, + 3194, 3452, + 3194, 3453, + 3193, 3453, + 3193, 3454, + 3192, 3454, + 3192, 3455, + 3191, 3455, + 3191, 3456, + 3190, 3456, + 3190, 3457, + 3185, 3457, + 3185, 3463, + 3186, 3463, + 3186, 3464, + 3187, 3464, + 3187, 3467, + 3167, 3467, + 3167, 3468, + 3163, 3468, + 3163, 3467, + 3142, 3467, + 3142, 3468, + 3141, 3468, + 3141, 3469, + 3140, 3469, + 3140, 3470, + 3139, 3470, + 3139, 3471, + 3138, 3471, + 3138, 3484, + 3139, 3484, + 3139, 3485, + 3140, 3485, + 3140, 3486, + 3141, 3486, + 3141, 3491, + 3140, 3491, + 3140, 3492, + 3139, 3492, + 3139, 3493, + 3138, 3493, + 3138, 3515, + 3139, 3515, + 3139, 3516, + 3140, 3516, + 3140, 3517, + 3141, 3517, + 3141, 3518, + 3160, 3518, + 3160, 3517, + 3161, 3517, + 3161, 3516, + 3162, 3516, + 3162, 3515, + 3167, 3515, + 3167, 3516, + 3168, 3516, + 3168, 3517, + 3169, 3517, + 3169, 3518, + 3191, 3518, + 3191, 3517, + 3192, 3517, + 3192, 3516, + 3193, 3516, + 3193, 3515, + 3194, 3515, + 3194, 3514, + 3195, 3514, + 3195, 3513, + 3196, 3513, + 3196, 3512, + 3197, 3512, + 3197, 3511, + 3198, 3511, + 3198, 3510, + 3199, 3510, + 3199, 3509, + 3200, 3509, + 3200, 3508, + 3230, 3508, + 3230, 3507, + 3231, 3507, + 3231, 3506, + 3232, 3506, + 3232, 3505, + 3233, 3505, + 3233, 3504, + 3234, 3504, + 3234, 3503, + 3235, 3503, + 3235, 3502, + 3252, 3502, + 3252, 3496, + 3253, 3496, + 3253, 3495, + 3254, 3495, + 3254, 3494, + 3255, 3494, + 3255, 3493, + 3263, 3493, + 3263, 3472, + 3264, 3472, + 3264, 3471, + 3265, 3471, + 3265, 3470, + 3266, 3470, + 3266, 3469, + 3267, 3469, + 3267, 3468, + 3268, 3468, + 3268, 3467, + 3269, 3467, + 3269, 3466, + 3270, 3466, + 3270, 3465, + 3271, 3465, + 3271, 3437, + 3274, 3437, + 3274, 3424, + 3277, 3424, + 3277, 3420, + 3274, 3420, + 3274, 3411, + 3275, 3411, + 3275, 3410, + 3276, 3410, + 3276, 3409, + 3277, 3409, + 3277, 3408, + 3288, 3408, + 3288, 3391, + 3289, 3391, + 3289, 3385, + 3290, 3385, + 3290, 3378, + 3289, 3378, + 3289, 3377, + 3288, 3377, + 3288, 3376, + 3265, 3376, + 3265, 3380, + 3253, 3380, + 3253, 3382, + 3245, 3382, + 3245, 3380, + 3242, 3380, + 3242, 3382, + 3239, 3382, + 3239, 3381, + 3209, 3381, + 3209, 3382, + 3282, 3382); + + // Lumbridge + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3201, 3257, + 3213, 3257, + 3213, 3264, + 3233, 3264, + 3233, 3257, + 3235, 3257, + 3235, 3241, + 3237, 3241, + 3237, 3237, + 3239, 3237, + 3239, 3231, + 3243, 3231, + 3243, 3220, + 3253, 3220, + 3253, 3217, + 3256, 3217, + 3256, 3212, + 3259, 3212, + 3259, 3190, + 3247, 3190, + 3247, 3191, + 3238, 3191, + 3238, 3195, + 3230, 3195, + 3230, 3201, + 3228, 3201, + 3228, 3202, + 3227, 3202, + 3227, 3205, + 3228, 3205, + 3228, 3207, + 3225, 3207, + 3225, 3206, + 3224, 3206, + 3224, 3205, + 3223, 3205, + 3223, 3204, + 3222, 3204, + 3222, 3203, + 3215, 3203, + 3215, 3202, + 3214, 3202, + 3214, 3201, + 3203, 3201, + 3203, 3202, + 3202, 3202, + 3202, 3203, + 3201, 3203, + 3201, 3217, + 3199, 3217, + 3199, 3220, + 3201, 3220); + + // Falador + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2986, 3395, + 2986, 3394, + 2987, 3394, + 2987, 3393, + 2996, 3393, + 2996, 3394, + 3002, 3394, + 3002, 3395, + 3009, 3395, + 3009, 3394, + 3010, 3394, + 3010, 3393, + 3011, 3393, + 3011, 3392, + 3021, 3392, + 3021, 3391, + 3022, 3391, + 3022, 3390, + 3041, 3390, + 3041, 3389, + 3047, 3389, + 3047, 3390, + 3062, 3390, + 3062, 3389, + 3063, 3389, + 3063, 3388, + 3064, 3388, + 3064, 3387, + 3065, 3387, + 3065, 3386, + 3066, 3386, + 3066, 3368, + 3065, 3368, + 3065, 3367, + 3064, 3367, + 3064, 3366, + 3063, 3366, + 3063, 3365, + 3062, 3365, + 3062, 3364, + 3061, 3364, + 3061, 3363, + 3060, 3363, + 3060, 3331, + 3061, 3331, + 3061, 3328, + 3058, 3328, + 3058, 3329, + 3025, 3329, + 3025, 3328, + 3024, 3328, + 3024, 3327, + 3016, 3327, + 3016, 3326, + 3015, 3326, + 3015, 3325, + 3014, 3325, + 3014, 3324, + 3013, 3324, + 3013, 3323, + 3008, 3323, + 3008, 3324, + 3006, 3324, + 3006, 3323, + 3002, 3323, + 3002, 3322, + 3001, 3322, + 3001, 3321, + 3000, 3321, + 3000, 3320, + 2999, 3320, + 2999, 3319, + 2998, 3319, + 2998, 3318, + 2997, 3318, + 2997, 3317, + 2996, 3317, + 2996, 3316, + 2992, 3316, + 2992, 3315, + 2991, 3315, + 2991, 3314, + 2990, 3314, + 2990, 3313, + 2989, 3313, + 2989, 3312, + 2988, 3312, + 2988, 3311, + 2987, 3311, + 2987, 3310, + 2986, 3310, + 2986, 3309, + 2966, 3309, + 2966, 3310, + 2956, 3310, + 2956, 3311, + 2941, 3311, + 2941, 3312, + 2940, 3312, + 2940, 3320, + 2936, 3320, + 2936, 3354, + 2937, 3354, + 2937, 3357, + 2936, 3357, + 2936, 3389, + 2937, 3389, + 2937, 3390, + 2938, 3390, + 2938, 3391, + 2939, 3391, + 2939, 3392, + 2940, 3392, + 2940, 3393, + 2943, 3393, + 2943, 3394, + 2944, 3394, + 2944, 3395, + 2950, 3395, + 2950, 3394, + 2956, 3394, + 2956, 3395); + + // Port phasmatys + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3650, 3456, + 3650, 3472, + 3651, 3472, + 3651, 3473, + 3652, 3473, + 3652, 3474, + 3653, 3474, + 3653, 3507, + 3654, 3507, + 3654, 3508, + 3668, 3508, + 3668, 3509, + 3669, 3509, + 3669, 3510, + 3670, 3510, + 3670, 3511, + 3671, 3511, + 3671, 3512, + 3672, 3512, + 3672, 3513, + 3673, 3513, + 3673, 3514, + 3674, 3514, + 3674, 3515, + 3675, 3515, + 3675, 3516, + 3676, 3516, + 3676, 3517, + 3687, 3517, + 3687, 3494, + 3690, 3494, + 3690, 3493, + 3696, 3493, + 3696, 3482, + 3699, 3482, + 3699, 3481, + 3712, 3481, + 3712, 3456); + + // Sophanem + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3274, 2752, + 3274, 2784, + 3277, 2784, + 3277, 2786, + 3274, 2786, + 3274, 2789, + 3272, 2789, + 3272, 2810, + 3322, 2810, + 3322, 2752); + + // Ardy + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2560, 3256, + 2560, 3264, + 2559, 3264, + 2559, 3328, + 2560, 3328, + 2560, 3339, + 2561, 3339, + 2561, 3340, + 2562, 3340, + 2562, 3341, + 2563, 3341, + 2563, 3342, + 2616, 3342, + 2616, 3341, + 2617, 3341, + 2617, 3340, + 2669, 3340, + 2669, 3339, + 2670, 3339, + 2670, 3338, + 2671, 3338, + 2671, 3337, + 2672, 3337, + 2672, 3336, + 2673, 3336, + 2673, 3335, + 2674, 3335, + 2674, 3334, + 2683, 3334, + 2683, 3333, + 2684, 3333, + 2684, 3332, + 2685, 3332, + 2685, 3331, + 2686, 3331, + 2686, 3330, + 2687, 3330, + 2687, 3329, + 2688, 3329, + 2688, 3264, + 2638, 3264, + 2638, 3263, + 2625, 3263, + 2625, 3264, + 2611, 3264, + 2611, 3257, + 2602, 3257, + 2602, 3264, + 2587, 3264, + 2587, 3263, + 2586, 3263, + 2586, 3262, + 2584, 3262, + 2584, 3261, + 2583, 3261, + 2583, 3260, + 2582, 3260, + 2582, 3259, + 2581, 3259, + 2581, 3258, + 2572, 3258, + 2572, 3260, + 2571, 3260, + 2571, 3261, + 2566, 3261, + 2566, 3260, + 2565, 3260, + 2565, 3259, + 2564, 3259, + 2564, 3256); + + // Yanille + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2613, 3103, + 2614, 3103, + 2614, 3102, + 2615, 3102, + 2615, 3101, + 2616, 3101, + 2616, 3100, + 2617, 3100, + 2617, 3099, + 2618, 3099, + 2618, 3098, + 2619, 3098, + 2619, 3097, + 2620, 3097, + 2620, 3075, + 2590, 3075, + 2590, 3074, + 2589, 3074, + 2589, 3073, + 2584, 3073, + 2584, 3074, + 2583, 3074, + 2583, 3075, + 2543, 3075, + 2543, 3076, + 2542, 3076, + 2542, 3077, + 2539, 3077, + 2539, 3107, + 2542, 3107, + 2542, 3108, + 2543, 3108, + 2543, 3109, + 2608, 3109, + 2608, 3108, + 2609, 3108, + 2609, 3107, + 2610, 3107, + 2610, 3106, + 2611, 3106, + 2611, 3105, + 2612, 3105, + 2612, 3104, + 2613, 3104); + + // Gnome stronghold + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2495, 3439, + 2494, 3439, + 2494, 3432, + 2495, 3432, + 2495, 3431, + 2496, 3431, + 2496, 3430, + 2497, 3430, + 2497, 3429, + 2498, 3429, + 2498, 3417, + 2497, 3417, + 2497, 3416, + 2496, 3416, + 2496, 3412, + 2495, 3412, + 2495, 3408, + 2494, 3408, + 2494, 3404, + 2495, 3404, + 2495, 3403, + 2496, 3403, + 2496, 3402, + 2497, 3402, + 2497, 3401, + 2498, 3401, + 2498, 3400, + 2499, 3400, + 2499, 3399, + 2500, 3399, + 2500, 3398, + 2501, 3398, + 2501, 3397, + 2502, 3397, + 2502, 3396, + 2506, 3396, + 2506, 3391, + 2502, 3391, + 2502, 3390, + 2492, 3390, + 2492, 3391, + 2489, 3391, + 2489, 3390, + 2488, 3390, + 2488, 3389, + 2485, 3389, + 2485, 3390, + 2482, 3390, + 2482, 3389, + 2476, 3389, + 2476, 3390, + 2471, 3390, + 2471, 3391, + 2468, 3391, + 2468, 3390, + 2467, 3390, + 2467, 3389, + 2466, 3389, + 2466, 3385, + 2465, 3385, + 2465, 3384, + 2458, 3384, + 2458, 3385, + 2457, 3385, + 2457, 3389, + 2456, 3389, + 2456, 3390, + 2455, 3390, + 2455, 3391, + 2450, 3391, + 2450, 3390, + 2446, 3390, + 2446, 3391, + 2443, 3391, + 2443, 3390, + 2442, 3390, + 2442, 3389, + 2440, 3389, + 2440, 3388, + 2434, 3388, + 2434, 3389, + 2433, 3389, + 2433, 3390, + 2432, 3390, + 2432, 3391, + 2428, 3391, + 2428, 3392, + 2427, 3392, + 2427, 3393, + 2420, 3393, + 2420, 3394, + 2419, 3394, + 2419, 3395, + 2418, 3395, + 2418, 3396, + 2417, 3396, + 2417, 3397, + 2416, 3397, + 2416, 3399, + 2415, 3399, + 2415, 3400, + 2414, 3400, + 2414, 3408, + 2413, 3408, + 2413, 3409, + 2412, 3409, + 2412, 3410, + 2411, 3410, + 2411, 3411, + 2410, 3411, + 2410, 3412, + 2387, 3412, + 2387, 3407, + 2383, 3407, + 2383, 3408, + 2380, 3408, + 2380, 3409, + 2379, 3409, + 2379, 3410, + 2377, 3410, + 2377, 3411, + 2376, 3411, + 2376, 3413, + 2375, 3413, + 2375, 3417, + 2374, 3417, + 2374, 3418, + 2373, 3418, + 2373, 3419, + 2372, 3419, + 2372, 3420, + 2371, 3420, + 2371, 3421, + 2370, 3421, + 2370, 3422, + 2369, 3422, + 2369, 3433, + 2370, 3433, + 2370, 3434, + 2371, 3434, + 2371, 3444, + 2372, 3444, + 2372, 3445, + 2373, 3445, + 2373, 3446, + 2374, 3446, + 2374, 3447, + 2375, 3447, + 2375, 3459, + 2376, 3459, + 2376, 3460, + 2377, 3460, + 2377, 3461, + 2378, 3461, + 2378, 3462, + 2379, 3462, + 2379, 3463, + 2380, 3463, + 2380, 3464, + 2381, 3464, + 2381, 3476, + 2379, 3476, + 2379, 3477, + 2378, 3477, + 2378, 3478, + 2377, 3478, + 2377, 3485, + 2376, 3485, + 2376, 3486, + 2375, 3486, + 2375, 3499, + 2376, 3499, + 2376, 3500, + 2377, 3500, + 2377, 3507, + 2378, 3507, + 2378, 3508, + 2379, 3508, + 2379, 3509, + 2380, 3509, + 2380, 3521, + 2382, 3521, + 2382, 3522, + 2384, 3522, + 2384, 3523, + 2393, 3523, + 2393, 3524, + 2399, 3524, + 2399, 3525, + 2404, 3525, + 2404, 3524, + 2405, 3524, + 2405, 3523, + 2407, 3523, + 2407, 3522, + 2415, 3522, + 2415, 3521, + 2425, 3521, + 2425, 3522, + 2427, 3522, + 2427, 3523, + 2430, 3523, + 2430, 3522, + 2431, 3522, + 2431, 3521, + 2432, 3521, + 2432, 3520, + 2448, 3520, + 2448, 3517, + 2454, 3517, + 2454, 3516, + 2455, 3516, + 2455, 3515, + 2456, 3515, + 2456, 3514, + 2457, 3514, + 2457, 3513, + 2460, 3513, + 2460, 3512, + 2461, 3512, + 2461, 3511, + 2465, 3511, + 2465, 3510, + 2468, 3510, + 2468, 3511, + 2472, 3511, + 2472, 3512, + 2473, 3512, + 2473, 3513, + 2475, 3513, + 2475, 3514, + 2476, 3514, + 2476, 3515, + 2477, 3515, + 2477, 3516, + 2478, 3516, + 2478, 3517, + 2483, 3517, + 2483, 3516, + 2487, 3516, + 2487, 3515, + 2488, 3515, + 2488, 3512, + 2487, 3512, + 2487, 3509, + 2488, 3509, + 2488, 3508, + 2489, 3508, + 2489, 3507, + 2491, 3507, + 2491, 3506, + 2492, 3506, + 2492, 3505, + 2493, 3505, + 2493, 3499, + 2492, 3499, + 2492, 3498, + 2491, 3498, + 2491, 3497, + 2490, 3497, + 2490, 3495, + 2491, 3495, + 2491, 3494, + 2492, 3494, + 2492, 3493, + 2493, 3493, + 2493, 3485, + 2490, 3485, + 2490, 3484, + 2489, 3484, + 2489, 3483, + 2488, 3483, + 2488, 3482, + 2487, 3482, + 2487, 3481, + 2486, 3481, + 2486, 3474, + 2488, 3474, + 2488, 3471, + 2489, 3471, + 2489, 3470, + 2490, 3470, + 2490, 3460, + 2491, 3460, + 2491, 3456, + 2496, 3456, + 2496, 3440, + 2495, 3440); + + // Rellekka + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2620, 3682, + 2624, 3682, + 2624, 3683, + 2625, 3683, + 2625, 3687, + 2629, 3687, + 2629, 3686, + 2630, 3686, + 2630, 3685, + 2632, 3685, + 2632, 3686, + 2636, 3686, + 2636, 3692, + 2645, 3692, + 2645, 3695, + 2647, 3695, + 2647, 3696, + 2649, 3696, + 2649, 3702, + 2650, 3702, + 2650, 3703, + 2651, 3703, + 2651, 3704, + 2652, 3704, + 2652, 3711, + 2653, 3711, + 2653, 3712, + 2691, 3712, + 2691, 3709, + 2692, 3709, + 2692, 3707, + 2693, 3707, + 2693, 3703, + 2692, 3703, + 2692, 3701, + 2691, 3701, + 2691, 3699, + 2690, 3699, + 2690, 3695, + 2691, 3695, + 2691, 3693, + 2692, 3693, + 2692, 3691, + 2693, 3691, + 2693, 3685, + 2692, 3685, + 2692, 3683, + 2691, 3683, + 2691, 3681, + 2690, 3681, + 2690, 3680, + 2689, 3680, + 2689, 3672, + 2690, 3672, + 2690, 3671, + 2691, 3671, + 2691, 3666, + 2690, 3666, + 2690, 3664, + 2689, 3664, + 2689, 3660, + 2690, 3660, + 2690, 3658, + 2691, 3658, + 2691, 3656, + 2692, 3656, + 2692, 3654, + 2693, 3654, + 2693, 3651, + 2692, 3651, + 2692, 3649, + 2690, 3649, + 2690, 3648, + 2688, 3648, + 2688, 3647, + 2686, 3647, + 2686, 3646, + 2673, 3646, + 2673, 3645, + 2636, 3645, + 2636, 3647, + 2627, 3647, + 2627, 3648, + 2625, 3648, + 2625, 3649, + 2624, 3649, + 2624, 3650, + 2622, 3650, + 2622, 3651, + 2620, 3651, + 2620, 3652, + 2618, 3652, + 2618, 3653, + 2616, 3653, + 2616, 3654, + 2609, 3654, + 2609, 3655, + 2607, 3655, + 2607, 3656, + 2603, 3656, + 2603, 3657, + 2602, 3657, + 2602, 3658, + 2601, 3658, + 2601, 3663, + 2602, 3663, + 2602, 3664, + 2603, 3664, + 2603, 3665, + 2604, 3665, + 2604, 3666, + 2605, 3666, + 2605, 3667, + 2606, 3667, + 2606, 3671, + 2609, 3671, + 2609, 3672, + 2610, 3672, + 2610, 3673, + 2611, 3673, + 2611, 3675, + 2612, 3675, + 2612, 3676, + 2614, 3676, + 2614, 3677, + 2616, 3677, + 2616, 3679, + 2618, 3679, + 2618, 3681, + 2620, 3681); + + // Jatizo + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2407, 3797, + 2407, 3793, + 2399, 3793, + 2399, 3792, + 2391, 3792, + 2391, 3791, + 2386, 3791, + 2386, 3796, + 2388, 3796, + 2388, 3802, + 2386, 3802, + 2386, 3807, + 2388, 3807, + 2388, 3809, + 2402, 3809, + 2402, 3819, + 2406, 3819, + 2406, 3824, + 2408, 3824, + 2408, 3826, + 2413, 3826, + 2413, 3824, + 2419, 3824, + 2419, 3826, + 2424, 3826, + 2424, 3821, + 2423, 3821, + 2423, 3798, + 2422, 3798, + 2422, 3797); + + // Neitiznot + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2329, 3812, + 2333, 3812, + 2333, 3813, + 2334, 3813, + 2334, 3814, + 2335, 3814, + 2335, 3815, + 2338, 3815, + 2338, 3816, + 2339, 3816, + 2339, 3817, + 2368, 3817, + 2368, 3776, + 2352, 3776, + 2352, 3796, + 2344, 3796, + 2344, 3795, + 2331, 3795, + 2331, 3797, + 2330, 3797, + 2330, 3798, + 2329, 3798); + + // Pest control + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2624, 2688, + 2688, 2688, + 2688, 2624, + 2624, 2624); + + // Tutorial island + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3052, 3135, + 3156, 3135, + 3156, 3057, + 3052, 3057); + + // Camelot bank + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2724, 3487, + 2724, 3490, + 2721, 3490, + 2721, 3494, + 2719, 3494, + 2719, 3497, + 2721, 3497, + 2721, 3498, + 2731, 3498, + 2731, 3490, + 2728, 3490, + 2728, 3487); + + // Catherby bank + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2806, 3438, + 2806, 3446, + 2813, 3446, + 2813, 3438); + + // Kourend castle + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 1627, 3658, + 1620, 3658, + 1620, 3657, + 1619, 3657, + 1619, 3656, + 1614, 3656, + 1614, 3657, + 1613, 3657, + 1613, 3661, + 1612, 3661, + 1612, 3662, + 1611, 3662, + 1611, 3663, + 1600, 3663, + 1600, 3662, + 1599, 3662, + 1599, 3661, + 1594, 3661, + 1594, 3662, + 1593, 3662, + 1593, 3685, + 1594, 3685, + 1594, 3686, + 1599, 3686, + 1599, 3685, + 1600, 3685, + 1600, 3684, + 1611, 3684, + 1611, 3685, + 1612, 3685, + 1612, 3686, + 1613, 3686, + 1613, 3690, + 1614, 3690, + 1614, 3691, + 1619, 3691, + 1619, 3690, + 1620, 3690, + 1620, 3689, + 1630, 3689, + 1630, 3686, + 1620, 3686, + 1620, 3685, + 1619, 3685, + 1619, 3683, + 1620, 3683, + 1620, 3682, + 1621, 3682, + 1621, 3681, + 1622, 3681, + 1622, 3680, + 1623, 3680, + 1623, 3679, + 1624, 3679, + 1624, 3668, + 1623, 3668, + 1623, 3667, + 1622, 3667, + 1622, 3666, + 1621, 3666, + 1621, 3665, + 1620, 3665, + 1620, 3664, + 1619, 3664, + 1619, 3662, + 1620, 3662, + 1620, 3661, + 1627, 3661); + } + + private static void definePvpSafeZones() + { + // Grand exchange + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3159, 3473, + 3159, 3474, + 3157, 3474, + 3157, 3475, + 3155, 3475, + 3155, 3476, + 3153, 3476, + 3153, 3477, + 3152, 3477, + 3152, 3478, + 3151, 3478, + 3151, 3480, + 3150, 3480, + 3150, 3482, + 3149, 3482, + 3149, 3484, + 3148, 3484, + 3148, 3496, + 3149, 3496, + 3149, 3498, + 3150, 3498, + 3150, 3500, + 3151, 3500, + 3151, 3502, + 3152, 3502, + 3152, 3503, + 3153, 3503, + 3153, 3504, + 3155, 3504, + 3155, 3505, + 3157, 3505, + 3157, 3506, + 3159, 3506, + 3159, 3507, + 3171, 3507, + 3171, 3506, + 3173, 3506, + 3173, 3505, + 3175, 3505, + 3175, 3504, + 3177, 3504, + 3177, 3503, + 3178, 3503, + 3178, 3502, + 3179, 3502, + 3179, 3500, + 3180, 3500, + 3180, 3498, + 3181, 3498, + 3181, 3496, + 3182, 3496, + 3182, 3484, + 3181, 3484, + 3181, 3482, + 3180, 3482, + 3180, 3480, + 3179, 3480, + 3179, 3478, + 3178, 3478, + 3178, 3477, + 3177, 3477, + 3177, 3476, + 3175, 3476, + 3175, 3475, + 3173, 3475, + 3173, 3474, + 3171, 3474, + 3171, 3473); + + // Edgeville + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3091, 3488, + 3091, 3493, + 3090, 3493, + 3090, 3498, + 3091, 3498, + 3091, 3500, + 3099, 3500, + 3099, 3488); + + // Fally west bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2943, 3368, + 2943, 3374, + 2948, 3374, + 2948, 3370, + 2950, 3370, + 2950, 3366, + 2949, 3366, + 2949, 3359, + 2945, 3359, + 2945, 3362, + 2946, 3362, + 2946, 3366, + 2945, 3366, + 2945, 3368); + + // Fally east bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3009, 3353, + 3009, 3359, + 3019, 3359, + 3019, 3357, + 3022, 3357, + 3022, 3353); + + // Fally castle + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2964, 3354, + 2966, 3354, + 2966, 3352, + 2967, 3352, + 2967, 3349, + 2976, 3349, + 2976, 3348, + 2977, 3348, + 2977, 3347, + 2981, 3347, + 2981, 3343, + 2982, 3343, + 2982, 3339, + 2981, 3339, + 2981, 3337, + 2967, 3337, + 2967, 3330, + 2963, 3330, + 2963, 3331, + 2962, 3331, + 2962, 3332, + 2961, 3332, + 2961, 3334, + 2964, 3334, + 2964, 3335, + 2965, 3335, + 2965, 3343, + 2964, 3343, + 2964, 3344, + 2961, 3344, + 2961, 3350, + 2963, 3350, + 2963, 3352, + 2964, 3352); + + // Varrock east bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3250, 3425, + 3258, 3425, + 3258, 3416, + 3250, 3416); + + // Varrock west bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3180, 3433, + 3180, 3448, + 3191, 3448, + 3191, 3433); + + // Port phasmatys + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3686, 3472, + 3700, 3472, + 3700, 3461, + 3686, 3461); + + // Yanille bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2609, 3088, + 2609, 3098, + 2617, 3098, + 2617, 3088); + + // Ardy east bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2649, 3280, + 2649, 3288, + 2659, 3288, + 2659, 3280); + + // Ardy west bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2612, 3330, + 2612, 3336, + 2615, 3336, + 2615, 3335, + 2619, 3335, + 2619, 3336, + 2622, 3336, + 2622, 3330); + + // Fishing guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2593, 3413, + 2588, 3413, + 2588, 3418, + 2583, 3418, + 2583, 3423, + 2590, 3423, + 2590, 3420, + 2593, 3420); + + // Gnome stronghold bank near slayer cave (2nd floor) + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, + 2444, 3431, + 2444, 3435, + 2448, 3435, + 2448, 3431, + 2447, 3431, + 2447, 3428, + 2449, 3428, + 2449, 3422, + 2447, 3422, + 2447, 3419, + 2448, 3419, + 2448, 3415, + 2444, 3415, + 2444, 3419, + 2445, 3419, + 2445, 3422, + 2443, 3422, + 2443, 3428, + 2445, 3428, + 2445, 3431); + + // Gnome stronghold bank in grand tree + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, + 2456, 3488, + 2452, 3488, + 2452, 3486, + 2450, 3486, + 2450, 3483, + 2451, 3483, + 2451, 3478, + 2448, 3478, + 2448, 3483, + 2449, 3483, + 2449, 3486, + 2447, 3486, + 2447, 3488, + 2443, 3488, + 2443, 3487, + 2438, 3487, + 2438, 3490, + 2443, 3490, + 2443, 3489, + 2447, 3489, + 2447, 3491, + 2449, 3491, + 2449, 3494, + 2448, 3494, + 2448, 3496, + 2451, 3496, + 2451, 3494, + 2450, 3494, + 2450, 3491, + 2452, 3491, + 2452, 3489, + 2456, 3489); + + // Al kharid bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3265, 3161, + 3265, 3174, + 3273, 3174, + 3273, 3161); + + // Shantay pass bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3308, 3119, + 3308, 3125, + 3310, 3125, + 3310, 3119); + + // Nardah bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3431, 2891, + 3431, 2889, + 3427, 2889, + 3427, 2887, + 3424, 2887, + 3424, 2895, + 3431, 2895, + 3431, 2893, + 3432, 2893, + 3432, 2891); + + // Sophanem bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2807, 5158, + 2792, 5158, + 2792, 5175, + 2807, 5175); + + // Canifis bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3509, 3474, + 3509, 3478, + 3508, 3478, + 3508, 3483, + 3509, 3483, + 3509, 3484, + 3517, 3484, + 3517, 3477, + 3516, 3477, + 3516, 3476, + 3513, 3476, + 3513, 3474); + + // Lumbridge castle outside + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3216, 3209, + 3216, 3210, + 3217, 3210, + 3217, 3228, + 3216, 3228, + 3216, 3229, + 3227, 3229, + 3227, 3221, + 3230, 3221, + 3230, 3217, + 3227, 3217, + 3227, 3209); + + // Lumbridge bank upstairs + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, + 3211, 3223, + 3211, 3215, + 3207, 3215, + 3207, 3223); + + // Draynor bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3098, 3240, + 3088, 3240, + 3088, 3247, + 3098, 3247); + + // Pest control bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2665, 2656, + 2670, 2656, + 2670, 2651, + 2665, 2651); + + // Shilo village bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2843, 2957, + 2846, 2957, + 2846, 2956, + 2849, 2956, + 2849, 2957, + 2850, 2957, + 2850, 2958, + 2855, 2958, + 2855, 2957, + 2856, 2957, + 2856, 2956, + 2858, 2956, + 2858, 2957, + 2862, 2957, + 2862, 2952, + 2858, 2952, + 2858, 2953, + 2856, 2953, + 2856, 2952, + 2855, 2952, + 2855, 2951, + 2850, 2951, + 2850, 2952, + 2849, 2952, + 2849, 2953, + 2847, 2953, + 2847, 2952, + 2843, 2952); + + // Legends guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, + 2731, 3374, + 2731, 3383, + 2734, 3383, + 2734, 3374); + + // Legends guild middle floor + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, + 2724, 3374, + 2724, 3383, + 2734, 3383, + 2734, 3382, + 2736, 3382, + 2736, 3375, + 2734, 3375, + 2734, 3374); + + // Warriors guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2843, 3537, + 2843, 3540, + 2841, 3540, + 2841, 3546, + 2849, 3546, + 2849, 3537, + 2847, 3537, + 2847, 3536, + 2846, 3536, + 2846, 3537); + + // Camelot bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2724, 3487, + 2724, 3490, + 2721, 3490, + 2721, 3494, + 2719, 3494, + 2719, 3497, + 2721, 3497, + 2721, 3498, + 2731, 3498, + 2731, 3490, + 2728, 3490, + 2728, 3487); + + // Camelot respawn point + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2761, 3483, + 2761, 3476, + 2755, 3476, + 2755, 3483); + + // Catherby bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2806, 3438, + 2806, 3446, + 2813, 3446, + 2813, 3438); + + // Barbarian outpost bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2536, 3572, + 2536, 3575, + 2538, 3575, + 2538, 3572); + + // Piscatoris bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2327, 3686, + 2327, 3694, + 2333, 3694, + 2333, 3686); + + // Lletya bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2350, 3161, + 2350, 3165, + 2351, 3165, + 2351, 3167, + 2357, 3167, + 2357, 3165, + 2356, 3165, + 2356, 3164, + 2355, 3164, + 2355, 3161); + + // Castle wars bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2446, 3087, + 2445, 3087, + 2445, 3085, + 2447, 3085, + 2447, 3081, + 2443, 3081, + 2443, 3082, + 2439, 3082, + 2439, 3081, + 2435, 3081, + 2435, 3099, + 2439, 3099, + 2439, 3098, + 2443, 3098, + 2443, 3099, + 2447, 3099, + 2447, 3095, + 2445, 3095, + 2445, 3093, + 2446, 3093); + + // Duel arena bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3380, 3267, + 3380, 3273, + 3381, 3273, + 3381, 3274, + 3385, 3274, + 3385, 3267); + + // Clan wars bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3375, 3165, + 3361, 3165, + 3361, 3173, + 3375, 3173); + + // Lumbridge cellar bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 3218, 9622, + 3218, 9624, + 3220, 9624, + 3220, 9622); + + // Dorgesh kaan bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2709, 5348, + 2707, 5348, + 2707, 5345, + 2701, 5345, + 2701, 5347, + 2697, 5347, + 2697, 5353, + 2701, 5353, + 2701, 5355, + 2707, 5355, + 2707, 5350, + 2709, 5350); + + // Keldagrim bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2842, 10204, + 2834, 10204, + 2834, 10216, + 2842, 10216); + + // Tzhaar bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2438, 5176, + 2438, 5180, + 2441, 5180, + 2441, 5182, + 2449, 5182, + 2449, 5181, + 2450, 5181, + 2450, 5180, + 2452, 5180, + 2452, 5175, + 2441, 5175, + 2441, 5176); + + // Inferno bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2542, 5135, + 2542, 5139, + 2539, 5139, + 2539, 5140, + 2538, 5140, + 2538, 5141, + 2537, 5141, + 2537, 5144, + 2541, 5144, + 2541, 5145, + 2543, 5145, + 2543, 5144, + 2544, 5144, + 2544, 5142, + 2545, 5142, + 2545, 5135); + + // Port khazard bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2661, 3160, + 2661, 3163, + 2666, 3163, + 2666, 3160); + + // Corsair cove bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2569, 2863, + 2569, 2868, + 2572, 2868, + 2572, 2863); + + // Burgh de rott bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3495, 3210, + 3495, 3214, + 3501, 3214, + 3501, 3210); + + // Edgeville respawn point + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3092, 3468, + 3092, 3474, + 3098, 3474, + 3098, 3468); + + // Mage bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2529, 4711, + 2529, 4724, + 2548, 4724, + 2548, 4711); + + // Lunar bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2097, 3917, + 2097, 3922, + 2105, 3922, + 2105, 3917); + + // Jatizo bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2414, 3801, + 2414, 3804, + 2420, 3804, + 2420, 3801); + + // Neitiznot bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2334, 3805, + 2334, 3809, + 2340, 3809, + 2340, 3805); + + // Hosidius bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1671, 3558, + 1671, 3577, + 1682, 3577, + 1682, 3558); + + // Woodcutting guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1589, 3475, + 1589, 3481, + 1594, 3481, + 1594, 3475); + + // Lands end bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1508, 3415, + 1508, 3424, + 1514, 3424, + 1514, 3415); + + // Chambers of xeric bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1252, 3570, + 1252, 3574, + 1257, 3574, + 1257, 3570); + + // Arceuus bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1621, 3736, + 1621, 3754, + 1627, 3754, + 1627, 3751, + 1633, 3751, + 1633, 3754, + 1639, 3754, + 1639, 3736); + + // Piscarilius bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1794, 3784, + 1794, 3794, + 1812, 3794, + 1812, 3784); + + // Lovakengj bank southeast + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1518, 3735, + 1518, 3744, + 1535, 3744, + 1535, 3735); + + // Lovakenj bank west + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1433, 3820, + 1433, 3837, + 1442, 3837, + 1442, 3820); + + // Lovakenj sulphur mine bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1452, 3855, + 1452, 3860, + 1455, 3860, + 1455, 3855); + + // Blast mine bank southeast + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1500, 3856, + 1500, 3858, + 1503, 3858, + 1503, 3856); + + // Wintertodt bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1638, 3942, + 1638, 3947, + 1642, 3947, + 1642, 3942); + + // Shayzien bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1495, 3612, + 1495, 3622, + 1515, 3622, + 1515, 3612); + + // Hosidius grape farm bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1804, 3571, + 1804, 3572, + 1808, 3572, + 1808, 3571); + + // Hosidius cooking bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1652, 3605, + 1652, 3615, + 1661, 3615, + 1661, 3605); + + // Ecteria bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2618, 3893, + 2618, 3897, + 2622, 3897, + 2622, 3893); + + // Mining guild expanded area + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 3018, 9733, + 3021, 9733, + 3021, 9729, + 3022, 9729, + 3022, 9728, + 3023, 9728, + 3023, 9727, + 3025, 9727, + 3025, 9726, + 3026, 9726, + 3026, 9725, + 3030, 9725, + 3030, 9726, + 3032, 9726, + 3032, 9727, + 3035, 9727, + 3035, 9726, + 3038, 9726, + 3038, 9727, + 3041, 9727, + 3041, 9728, + 3042, 9728, + 3042, 9730, + 3045, 9730, + 3045, 9727, + 3047, 9727, + 3047, 9726, + 3048, 9726, + 3048, 9724, + 3052, 9724, + 3052, 9725, + 3053, 9725, + 3053, 9726, + 3055, 9726, + 3055, 9725, + 3056, 9725, + 3056, 9723, + 3057, 9723, + 3057, 9720, + 3056, 9720, + 3056, 9719, + 3054, 9719, + 3054, 9718, + 3052, 9718, + 3052, 9717, + 3050, 9717, + 3050, 9718, + 3045, 9718, + 3045, 9716, + 3044, 9716, + 3044, 9715, + 3041, 9715, + 3041, 9714, + 3039, 9714, + 3039, 9713, + 3037, 9713, + 3037, 9714, + 3036, 9714, + 3036, 9715, + 3034, 9715, + 3034, 9716, + 3029, 9716, + 3029, 9715, + 3028, 9715, + 3028, 9714, + 3026, 9714, + 3026, 9709, + 3027, 9709, + 3027, 9708, + 3028, 9708, + 3028, 9705, + 3029, 9705, + 3029, 9701, + 3028, 9701, + 3028, 9700, + 3027, 9700, + 3027, 9699, + 3023, 9699, + 3023, 9700, + 3019, 9700, + 3019, 9701, + 3018, 9701, + 3018, 9705, + 3019, 9705, + 3019, 9707, + 3020, 9707, + 3020, 9708, + 3021, 9708, + 3021, 9709, + 3022, 9709, + 3022, 9713, + 3021, 9713, + 3021, 9714, + 3019, 9714, + 3019, 9715, + 3018, 9715, + 3018, 9717, + 3015, 9717, + 3015, 9716, + 3013, 9716, + 3013, 9717, + 3012, 9717, + 3012, 9720, + 3013, 9720, + 3013, 9721, + 3015, 9721, + 3015, 9723, + 3016, 9723, + 3016, 9727, + 3017, 9727, + 3017, 9730, + 3018, 9730); + + // Motherlode mine bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 3760, 5671, + 3760, 5668, + 3761, 5668, + 3761, 5665, + 3760, 5665, + 3760, 5663, + 3758, 5663, + 3758, 5671); + + // Mos le harmles bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3679, 2980, + 3679, 2985, + 3681, 2985, + 3681, 2984, + 3682, 2984, + 3682, 2985, + 3684, 2985, + 3684, 2980, + 3682, 2980, + 3682, 2981, + 3681, 2981, + 3681, 2980); + + // Zanaris bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2388, 4454, + 2380, 4454, + 2380, 4463, + 2388, 4463); + + // Wodcuting guild bank underground + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 1550, 9872, + 1550, 9874, + 1553, 9874, + 1553, 9872); + } + + private static void defineWilderness() + { + // Above ground + addPolygonTo(ROUGH_WILDERNESS, + 2944, 3523, + 3392, 3523, + 3392, 3971, + 2944, 3971); + + // Underground + addPolygonTo(ROUGH_WILDERNESS, + 2944, 9918, + 2944, 10360, + 3264, 10360, + 3264, 9918); + } + + private static void addPolygonTo(List[] shapes, int... coords) + { + Polygon poly = new Polygon(); + for (int i = 0; i < coords.length; i += 2) + { + poly.addPoint(coords[i], coords[i + 1]); + } + for (int i = 0; i < shapes.length; i++) + { + shapes[i].add(poly); + } + } + + private static void addPolygonOnPlane(List[] shapes, int plane, int... coords) + { + Polygon poly = new Polygon(); + for (int i = 0; i < coords.length; i += 2) + { + poly.addPoint(coords[i], coords[i + 1]); + } + shapes[plane].add(poly); + } + + private static void addPolygonOnPlanes(List[] shapes, int minPlane, int maxPlane, int... coords) + { + Polygon poly = new Polygon(); + for (int i = 0; i < coords.length; i += 2) + { + poly.addPoint(coords[i], coords[i + 1]); + } + for (int i = minPlane; i <= maxPlane; i++) + { + shapes[i].add(poly); + } + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsConfig.java index 0436d936ce..6101dbf3c1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsConfig.java @@ -1,111 +1,111 @@ -/* - * Copyright (c) 2018, Woox - * 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.multiindicators; - -import java.awt.Color; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("multiindicators") -public interface MultiIndicatorsConfig extends Config -{ - @ConfigItem( - keyName = "multicombatZoneVisibility", - name = "Multicombat zones", - description = "Determine where multicombat zones should be shown", - position = 1 - ) - default ZoneVisibility multicombatZoneVisibility() - { - return ZoneVisibility.SHOW_IN_PVP; - } - - @ConfigItem( - keyName = "pvpSafeZones", - name = "PvP safe zones", - description = "Show safe zones in PvP worlds", - position = 2 - ) - default boolean showPvpSafeZones() - { - return true; - } - - @ConfigItem( - keyName = "deadmanSafeZones", - name = "Deadman safe zones", - description = "Show safe zones in Deadman worlds", - position = 3 - ) - default boolean showDeadmanSafeZones() - { - return true; - } - - @ConfigItem( - keyName = "collisionDetection", - name = "Collision detection", - description = "Only show lines where they can be walked through", - position = 4 - ) - default boolean collisionDetection() - { - return false; - } - - @ConfigItem( - keyName = "showMinimapLines", - name = "Show on minimap", - description = "Show multicombat and safe zones on the minimap", - position = 5 - ) - default boolean showMinimapLines() - { - return true; - } - - @ConfigItem( - keyName = "multicombatColor", - name = "Multicombat zone color", - description = "Choose color to use for marking multicombat zones", - position = 6 - ) - default Color multicombatColor() - { - return Color.MAGENTA; - } - - @ConfigItem( - keyName = "safeZoneColor", - name = "Safe zone color", - description = "Choose color to use for marking safe zones in PvP/Deadman", - position = 7 - ) - default Color safeZoneColor() - { - return Color.GREEN; - } +/* + * Copyright (c) 2018, Woox + * 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.multiindicators; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("multiindicators") +public interface MultiIndicatorsConfig extends Config +{ + @ConfigItem( + keyName = "multicombatZoneVisibility", + name = "Multicombat zones", + description = "Determine where multicombat zones should be shown", + position = 1 + ) + default ZoneVisibility multicombatZoneVisibility() + { + return ZoneVisibility.SHOW_IN_PVP; + } + + @ConfigItem( + keyName = "pvpSafeZones", + name = "PvP safe zones", + description = "Show safe zones in PvP worlds", + position = 2 + ) + default boolean showPvpSafeZones() + { + return true; + } + + @ConfigItem( + keyName = "deadmanSafeZones", + name = "Deadman safe zones", + description = "Show safe zones in Deadman worlds", + position = 3 + ) + default boolean showDeadmanSafeZones() + { + return true; + } + + @ConfigItem( + keyName = "collisionDetection", + name = "Collision detection", + description = "Only show lines where they can be walked through", + position = 4 + ) + default boolean collisionDetection() + { + return false; + } + + @ConfigItem( + keyName = "showMinimapLines", + name = "Show on minimap", + description = "Show multicombat and safe zones on the minimap", + position = 5 + ) + default boolean showMinimapLines() + { + return true; + } + + @ConfigItem( + keyName = "multicombatColor", + name = "Multicombat zone color", + description = "Choose color to use for marking multicombat zones", + position = 6 + ) + default Color multicombatColor() + { + return Color.MAGENTA; + } + + @ConfigItem( + keyName = "safeZoneColor", + name = "Safe zone color", + description = "Choose color to use for marking safe zones in PvP/Deadman", + position = 7 + ) + default Color safeZoneColor() + { + return Color.GREEN; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsMinimapOverlay.java index a0d87a4691..016785bfd2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsMinimapOverlay.java @@ -1,116 +1,116 @@ -/* - * Copyright (c) 2018, Woox - * 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.multiindicators; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.GeneralPath; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.geometry.Geometry; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; - -public class MultiIndicatorsMinimapOverlay extends Overlay -{ - private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; - - @Inject - private Client client; - - @Inject - private MultiIndicatorsPlugin plugin; - - @Inject - private MultiIndicatorsConfig config; - - @Inject - public MultiIndicatorsMinimapOverlay() - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ALWAYS_ON_TOP); - setPriority(OverlayPriority.LOW); - } - - private Color getTransparentColorVersion(Color c) - { - return new Color(c.getRed(), c.getGreen(), c.getBlue(), 192); - } - - private void renderPath(Graphics2D graphics, GeneralPath path, Color color) - { - LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); - Rectangle viewArea = new Rectangle( - playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, - playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, - MAX_LOCAL_DRAW_LENGTH * 2, - MAX_LOCAL_DRAW_LENGTH * 2); - - graphics.setColor(color); - - path = Geometry.clipPath(path, viewArea); - path = Geometry.filterPath(path, (p1, p2) -> - Perspective.localToMinimap(client, new LocalPoint((int)p1[0], (int)p1[1])) != null && - Perspective.localToMinimap(client, new LocalPoint((int)p2[0], (int)p2[1])) != null); - path = Geometry.transformPath(path, coords -> - { - Point point = Perspective.localToMinimap(client, new LocalPoint((int)coords[0], (int)coords[1])); - coords[0] = point.getX(); - coords[1] = point.getY(); - }); - - graphics.draw(path); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!config.showMinimapLines()) - { - return null; - } - - GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; - GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; - - if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) - { - renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); - } - if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) - { - renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); - } - - return null; - } +/* + * Copyright (c) 2018, Woox + * 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.multiindicators; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.geometry.Geometry; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +public class MultiIndicatorsMinimapOverlay extends Overlay +{ + private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; + + @Inject + private Client client; + + @Inject + private MultiIndicatorsPlugin plugin; + + @Inject + private MultiIndicatorsConfig config; + + @Inject + public MultiIndicatorsMinimapOverlay() + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ALWAYS_ON_TOP); + setPriority(OverlayPriority.LOW); + } + + private Color getTransparentColorVersion(Color c) + { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), 192); + } + + private void renderPath(Graphics2D graphics, GeneralPath path, Color color) + { + LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); + Rectangle viewArea = new Rectangle( + playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, + playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, + MAX_LOCAL_DRAW_LENGTH * 2, + MAX_LOCAL_DRAW_LENGTH * 2); + + graphics.setColor(color); + + path = Geometry.clipPath(path, viewArea); + path = Geometry.filterPath(path, (p1, p2) -> + Perspective.localToMinimap(client, new LocalPoint((int) p1[0], (int) p1[1])) != null && + Perspective.localToMinimap(client, new LocalPoint((int) p2[0], (int) p2[1])) != null); + path = Geometry.transformPath(path, coords -> + { + Point point = Perspective.localToMinimap(client, new LocalPoint((int) coords[0], (int) coords[1])); + coords[0] = point.getX(); + coords[1] = point.getY(); + }); + + graphics.draw(path); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!config.showMinimapLines()) + { + return null; + } + + GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; + GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; + + if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) + { + renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); + } + if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) + { + renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); + } + + return null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsOverlay.java index 242effb5aa..a4e4424627 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsOverlay.java @@ -1,113 +1,113 @@ -/* - * Copyright (c) 2018, Woox - * 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.multiindicators; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.GeneralPath; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.geometry.Geometry; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; - -public class MultiIndicatorsOverlay extends Overlay -{ - private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; - - @Inject - private Client client; - - @Inject - private MultiIndicatorsPlugin plugin; - - @Inject - private MultiIndicatorsConfig config; - - @Inject - public MultiIndicatorsOverlay() - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - setPriority(OverlayPriority.LOW); - } - - private Color getTransparentColorVersion(Color c) - { - return new Color(c.getRed(), c.getGreen(), c.getBlue(), 92); - } - - private void renderPath(Graphics2D graphics, GeneralPath path, Color color) - { - LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); - Rectangle viewArea = new Rectangle( - playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, - playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, - MAX_LOCAL_DRAW_LENGTH * 2, - MAX_LOCAL_DRAW_LENGTH * 2); - - graphics.setColor(color); - graphics.setStroke(new BasicStroke(2)); - - path = Geometry.clipPath(path, viewArea); - path = Geometry.filterPath(path, (p1, p2) -> - Perspective.localToCanvas(client, new LocalPoint((int)p1[0], (int)p1[1]), client.getPlane()) != null && - Perspective.localToCanvas(client, new LocalPoint((int)p2[0], (int)p2[1]), client.getPlane()) != null); - path = Geometry.transformPath(path, coords -> - { - Point point = Perspective.localToCanvas(client, new LocalPoint((int)coords[0], (int)coords[1]), client.getPlane()); - coords[0] = point.getX(); - coords[1] = point.getY(); - }); - - graphics.draw(path); - } - - @Override - public Dimension render(Graphics2D graphics) - { - GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; - GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; - - if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) - { - renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); - } - if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) - { - renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); - } - - return null; - } +/* + * Copyright (c) 2018, Woox + * 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.multiindicators; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.geometry.Geometry; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +public class MultiIndicatorsOverlay extends Overlay +{ + private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; + + @Inject + private Client client; + + @Inject + private MultiIndicatorsPlugin plugin; + + @Inject + private MultiIndicatorsConfig config; + + @Inject + public MultiIndicatorsOverlay() + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + setPriority(OverlayPriority.LOW); + } + + private Color getTransparentColorVersion(Color c) + { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), 92); + } + + private void renderPath(Graphics2D graphics, GeneralPath path, Color color) + { + LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); + Rectangle viewArea = new Rectangle( + playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, + playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, + MAX_LOCAL_DRAW_LENGTH * 2, + MAX_LOCAL_DRAW_LENGTH * 2); + + graphics.setColor(color); + graphics.setStroke(new BasicStroke(2)); + + path = Geometry.clipPath(path, viewArea); + path = Geometry.filterPath(path, (p1, p2) -> + Perspective.localToCanvas(client, new LocalPoint((int) p1[0], (int) p1[1]), client.getPlane()) != null && + Perspective.localToCanvas(client, new LocalPoint((int) p2[0], (int) p2[1]), client.getPlane()) != null); + path = Geometry.transformPath(path, coords -> + { + Point point = Perspective.localToCanvas(client, new LocalPoint((int) coords[0], (int) coords[1]), client.getPlane()); + coords[0] = point.getX(); + coords[1] = point.getY(); + }); + + graphics.draw(path); + } + + @Override + public Dimension render(Graphics2D graphics) + { + GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; + GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; + + if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) + { + renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); + } + if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) + { + renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); + } + + return null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsPlugin.java index 4882930ed6..c0722e00c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MultiIndicatorsPlugin.java @@ -1,299 +1,299 @@ -/* - * Copyright (c) 2018, Woox - * 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.multiindicators; - -import net.runelite.client.eventbus.Subscribe; -import com.google.inject.Provides; -import java.awt.Rectangle; -import java.awt.geom.GeneralPath; -import java.util.Arrays; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.Constants; -import net.runelite.api.GameState; -import net.runelite.api.ObjectComposition; -import net.runelite.api.Perspective; -import net.runelite.api.Tile; -import net.runelite.api.WallObject; -import net.runelite.api.WorldType; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldArea; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.geometry.Geometry; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "Multi-Lines", - description = "Show borders of multicombat and PvP safezones", - tags = {"multicombat", "lines", "pvp", "deadman", "safezones", "bogla"}, - enabledByDefault = false, - type = PluginType.PVP -) -public class MultiIndicatorsPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private MultiIndicatorsConfig config; - - @Inject - private MultiIndicatorsOverlay overlay; - - @Inject - private MultiIndicatorsMinimapOverlay minimapOverlay; - - @Inject - private OverlayManager overlayManager; - - @Getter - private GeneralPath[] multicombatPathToDisplay; - - @Getter - private GeneralPath[] pvpPathToDisplay; - - @Getter - private boolean inPvp; - - @Getter - private boolean inDeadman; - - private int currentPlane; - - @Provides - MultiIndicatorsConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(MultiIndicatorsConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - overlayManager.add(minimapOverlay); - - multicombatPathToDisplay = new GeneralPath[Constants.MAX_Z]; - pvpPathToDisplay = new GeneralPath[Constants.MAX_Z]; - - clientThread.invokeLater(() -> - { - if (client.getGameState() == GameState.LOGGED_IN) - { - findLinesInScene(); - } - }); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - overlayManager.remove(minimapOverlay); - - multicombatPathToDisplay = null; - pvpPathToDisplay = null; - } - - private void transformWorldToLocal(float[] coords) - { - LocalPoint lp = LocalPoint.fromWorld(client, (int)coords[0], (int)coords[1]); - coords[0] = lp.getX() - Perspective.LOCAL_TILE_SIZE / 2; - coords[1] = lp.getY() - Perspective.LOCAL_TILE_SIZE / 2; - } - - private boolean isOpenableAt(WorldPoint wp) - { - int sceneX = wp.getX() - client.getBaseX(); - int sceneY = wp.getY() - client.getBaseY(); - - Tile tile = client.getScene().getTiles()[wp.getPlane()][sceneX][sceneY]; - if (tile == null) - { - return false; - } - - WallObject wallObject = tile.getWallObject(); - if (wallObject == null) - { - return false; - } - - ObjectComposition objectComposition = client.getObjectDefinition(wallObject.getId()); - if (objectComposition == null) - { - return false; - } - - String[] actions = objectComposition.getActions(); - if (actions == null) - { - return false; - } - - return Arrays.stream(actions).anyMatch(x -> x != null && x.toLowerCase().equals("open")); - } - - private boolean collisionFilter(float[] p1, float[] p2) - { - int x1 = (int)p1[0]; - int y1 = (int)p1[1]; - int x2 = (int)p2[0]; - int y2 = (int)p2[1]; - - if (x1 > x2) - { - int temp = x1; - x1 = x2; - x2 = temp; - } - if (y1 > y2) - { - int temp = y1; - y1 = y2; - y2 = temp; - } - int dx = x2 - x1; - int dy = y2 - y1; - WorldArea wa1 = new WorldArea(new WorldPoint( - x1, y1, currentPlane), 1, 1); - WorldArea wa2 = new WorldArea(new WorldPoint( - x1 - dy, y1 - dx, currentPlane), 1, 1); - - if (isOpenableAt(wa1.toWorldPoint()) || isOpenableAt(wa2.toWorldPoint())) - { - // When there's something with the open option (e.g. a door) on the tile, - // we assume it can be opened and walked through afterwards. Without this - // check, the line for that tile wouldn't render with collision detection - // because the collision check isn't done if collision data changes. - return true; - } - - boolean b1 = wa1.canTravelInDirection(client, -dy, -dx); - boolean b2 = wa2.canTravelInDirection(client, dy, dx); - return b1 && b2; - } - - private void findLinesInScene() - { - inDeadman = client.getWorldType().stream().anyMatch(x -> - x == WorldType.DEADMAN || x == WorldType.SEASONAL_DEADMAN); - inPvp = client.getWorldType().stream().anyMatch(x -> - x == WorldType.PVP || x == WorldType.HIGH_RISK); - - Rectangle sceneRect = new Rectangle( - client.getBaseX() + 1, client.getBaseY() + 1, - Constants.SCENE_SIZE - 2, Constants.SCENE_SIZE - 2); - - // Generate lines for multicombat zones - if (config.multicombatZoneVisibility() == ZoneVisibility.HIDE) - { - for (int i = 0; i < multicombatPathToDisplay.length; i++) - { - multicombatPathToDisplay[i] = null; - } - } - else - { - for (int i = 0; i < multicombatPathToDisplay.length; i++) - { - currentPlane = i; - - GeneralPath lines = new GeneralPath(MapLocations.getMulticombat(sceneRect, i)); - lines = Geometry.clipPath(lines, sceneRect); - if (config.multicombatZoneVisibility() == ZoneVisibility.SHOW_IN_PVP && - !isInDeadman() && !isInPvp()) - { - lines = Geometry.clipPath(lines, MapLocations.getRoughWilderness(i)); - } - lines = Geometry.splitIntoSegments(lines, 1); - if (config.collisionDetection()) - { - lines = Geometry.filterPath(lines, this::collisionFilter); - } - lines = Geometry.transformPath(lines, this::transformWorldToLocal); - multicombatPathToDisplay[i] = lines; - } - } - - // Generate safezone lines for deadman/pvp worlds - for (int i = 0; i < pvpPathToDisplay.length; i++) - { - currentPlane = i; - - GeneralPath safeZonePath = null; - if (config.showDeadmanSafeZones() && isInDeadman()) - { - safeZonePath = new GeneralPath(MapLocations.getDeadmanSafeZones(sceneRect, i)); - } - else if (config.showPvpSafeZones() && isInPvp()) - { - safeZonePath = new GeneralPath(MapLocations.getPvpSafeZones(sceneRect, i)); - } - if (safeZonePath != null) - { - safeZonePath = Geometry.clipPath(safeZonePath, sceneRect); - safeZonePath = Geometry.splitIntoSegments(safeZonePath, 1); - if (config.collisionDetection()) - { - safeZonePath = Geometry.filterPath(safeZonePath, this::collisionFilter); - } - safeZonePath = Geometry.transformPath(safeZonePath, this::transformWorldToLocal); - } - pvpPathToDisplay[i] = safeZonePath; - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getKey().equals("collisionDetection") || - event.getKey().equals("multicombatZoneVisibility") || - event.getKey().equals("deadmanSafeZones") || - event.getKey().equals("pvpSafeZones")) - { - findLinesInScene(); - } - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGGED_IN) - { - findLinesInScene(); - } - } -} +/* + * Copyright (c) 2018, Woox + * 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.multiindicators; + +import com.google.inject.Provides; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; +import java.util.Arrays; +import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Constants; +import net.runelite.api.GameState; +import net.runelite.api.ObjectComposition; +import net.runelite.api.Perspective; +import net.runelite.api.Tile; +import net.runelite.api.WallObject; +import net.runelite.api.WorldType; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldArea; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.geometry.Geometry; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Multi-Lines", + description = "Show borders of multicombat and PvP safezones", + tags = {"multicombat", "lines", "pvp", "deadman", "safezones", "bogla"}, + enabledByDefault = false, + type = PluginType.PVP +) +public class MultiIndicatorsPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private MultiIndicatorsConfig config; + + @Inject + private MultiIndicatorsOverlay overlay; + + @Inject + private MultiIndicatorsMinimapOverlay minimapOverlay; + + @Inject + private OverlayManager overlayManager; + + @Getter + private GeneralPath[] multicombatPathToDisplay; + + @Getter + private GeneralPath[] pvpPathToDisplay; + + @Getter + private boolean inPvp; + + @Getter + private boolean inDeadman; + + private int currentPlane; + + @Provides + MultiIndicatorsConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(MultiIndicatorsConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + overlayManager.add(minimapOverlay); + + multicombatPathToDisplay = new GeneralPath[Constants.MAX_Z]; + pvpPathToDisplay = new GeneralPath[Constants.MAX_Z]; + + clientThread.invokeLater(() -> + { + if (client.getGameState() == GameState.LOGGED_IN) + { + findLinesInScene(); + } + }); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + overlayManager.remove(minimapOverlay); + + multicombatPathToDisplay = null; + pvpPathToDisplay = null; + } + + private void transformWorldToLocal(float[] coords) + { + LocalPoint lp = LocalPoint.fromWorld(client, (int) coords[0], (int) coords[1]); + coords[0] = lp.getX() - Perspective.LOCAL_TILE_SIZE / 2; + coords[1] = lp.getY() - Perspective.LOCAL_TILE_SIZE / 2; + } + + private boolean isOpenableAt(WorldPoint wp) + { + int sceneX = wp.getX() - client.getBaseX(); + int sceneY = wp.getY() - client.getBaseY(); + + Tile tile = client.getScene().getTiles()[wp.getPlane()][sceneX][sceneY]; + if (tile == null) + { + return false; + } + + WallObject wallObject = tile.getWallObject(); + if (wallObject == null) + { + return false; + } + + ObjectComposition objectComposition = client.getObjectDefinition(wallObject.getId()); + if (objectComposition == null) + { + return false; + } + + String[] actions = objectComposition.getActions(); + if (actions == null) + { + return false; + } + + return Arrays.stream(actions).anyMatch(x -> x != null && x.toLowerCase().equals("open")); + } + + private boolean collisionFilter(float[] p1, float[] p2) + { + int x1 = (int) p1[0]; + int y1 = (int) p1[1]; + int x2 = (int) p2[0]; + int y2 = (int) p2[1]; + + if (x1 > x2) + { + int temp = x1; + x1 = x2; + x2 = temp; + } + if (y1 > y2) + { + int temp = y1; + y1 = y2; + y2 = temp; + } + int dx = x2 - x1; + int dy = y2 - y1; + WorldArea wa1 = new WorldArea(new WorldPoint( + x1, y1, currentPlane), 1, 1); + WorldArea wa2 = new WorldArea(new WorldPoint( + x1 - dy, y1 - dx, currentPlane), 1, 1); + + if (isOpenableAt(wa1.toWorldPoint()) || isOpenableAt(wa2.toWorldPoint())) + { + // When there's something with the open option (e.g. a door) on the tile, + // we assume it can be opened and walked through afterwards. Without this + // check, the line for that tile wouldn't render with collision detection + // because the collision check isn't done if collision data changes. + return true; + } + + boolean b1 = wa1.canTravelInDirection(client, -dy, -dx); + boolean b2 = wa2.canTravelInDirection(client, dy, dx); + return b1 && b2; + } + + private void findLinesInScene() + { + inDeadman = client.getWorldType().stream().anyMatch(x -> + x == WorldType.DEADMAN || x == WorldType.SEASONAL_DEADMAN); + inPvp = client.getWorldType().stream().anyMatch(x -> + x == WorldType.PVP || x == WorldType.HIGH_RISK); + + Rectangle sceneRect = new Rectangle( + client.getBaseX() + 1, client.getBaseY() + 1, + Constants.SCENE_SIZE - 2, Constants.SCENE_SIZE - 2); + + // Generate lines for multicombat zones + if (config.multicombatZoneVisibility() == ZoneVisibility.HIDE) + { + for (int i = 0; i < multicombatPathToDisplay.length; i++) + { + multicombatPathToDisplay[i] = null; + } + } + else + { + for (int i = 0; i < multicombatPathToDisplay.length; i++) + { + currentPlane = i; + + GeneralPath lines = new GeneralPath(MapLocations.getMulticombat(sceneRect, i)); + lines = Geometry.clipPath(lines, sceneRect); + if (config.multicombatZoneVisibility() == ZoneVisibility.SHOW_IN_PVP && + !isInDeadman() && !isInPvp()) + { + lines = Geometry.clipPath(lines, MapLocations.getRoughWilderness(i)); + } + lines = Geometry.splitIntoSegments(lines, 1); + if (config.collisionDetection()) + { + lines = Geometry.filterPath(lines, this::collisionFilter); + } + lines = Geometry.transformPath(lines, this::transformWorldToLocal); + multicombatPathToDisplay[i] = lines; + } + } + + // Generate safezone lines for deadman/pvp worlds + for (int i = 0; i < pvpPathToDisplay.length; i++) + { + currentPlane = i; + + GeneralPath safeZonePath = null; + if (config.showDeadmanSafeZones() && isInDeadman()) + { + safeZonePath = new GeneralPath(MapLocations.getDeadmanSafeZones(sceneRect, i)); + } + else if (config.showPvpSafeZones() && isInPvp()) + { + safeZonePath = new GeneralPath(MapLocations.getPvpSafeZones(sceneRect, i)); + } + if (safeZonePath != null) + { + safeZonePath = Geometry.clipPath(safeZonePath, sceneRect); + safeZonePath = Geometry.splitIntoSegments(safeZonePath, 1); + if (config.collisionDetection()) + { + safeZonePath = Geometry.filterPath(safeZonePath, this::collisionFilter); + } + safeZonePath = Geometry.transformPath(safeZonePath, this::transformWorldToLocal); + } + pvpPathToDisplay[i] = safeZonePath; + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getKey().equals("collisionDetection") || + event.getKey().equals("multicombatZoneVisibility") || + event.getKey().equals("deadmanSafeZones") || + event.getKey().equals("pvpSafeZones")) + { + findLinesInScene(); + } + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState() == GameState.LOGGED_IN) + { + findLinesInScene(); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/ZoneVisibility.java b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/ZoneVisibility.java index 93ca7e8e26..104dce7770 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/ZoneVisibility.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/ZoneVisibility.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2018, Woox - * 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.multiindicators; - -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public enum ZoneVisibility -{ - HIDE("Hide"), - SHOW_IN_PVP("Show in PvP"), - SHOW_EVERYWHERE("Show everywhere"); - - private final String visibility; - - @Override - public String toString() - { - return visibility; - } +/* + * Copyright (c) 2018, Woox + * 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.multiindicators; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum ZoneVisibility +{ + HIDE("Hide"), + SHOW_IN_PVP("Show in PvP"), + SHOW_EVERYWHERE("Show everywhere"); + + private final String visibility; + + @Override + public String toString() + { + return visibility; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MidiFileAdjuster.java b/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MidiFileAdjuster.java index ee67b0a694..ea2b61252d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MidiFileAdjuster.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MidiFileAdjuster.java @@ -1,165 +1,202 @@ -/* - * Copyright (c) 2019, Rodolfo Ruiz-Velasco - * 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.musicmodifier; - -import javax.sound.midi.*; -import java.io.IOException; - -public class MidiFileAdjuster { - - private int bankLSBValue; - private int chPosition = -1; - - private boolean customBank = false; - - public Sequence reorderTracks(Sequence sequence) throws InvalidMidiDataException, IOException { - for (Track track : sequence.getTracks()) { - for (int i = 0; i < track.size(); i++) { - MidiEvent midiEvent = track.get(i); - MidiMessage midiMessage = midiEvent.getMessage(); - - if (midiMessage instanceof ShortMessage) { - ShortMessage sm = (ShortMessage) midiMessage; - - if (sm.getChannel() < 16) { - getBankLSB(sm); - - if (i == 0 & bankLSBValue != 1) { - chPosition++; - if (chPosition == 9) { - chPosition = 10; - } - } - - if (!customBank) { - - if (sm.getChannel() == 9) { - bankLSBValue = 1; - } - - if (sm.getChannel() != 9) { - bankLSBValue = 0; - } - } - } - - if (bankLSBValue == 1) { - - int drumChannel = 9; - if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) { - sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) { - sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.NOTE_OFF) { - sm.setMessage(ShortMessage.NOTE_OFF, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.NOTE_ON) { - sm.setMessage(ShortMessage.NOTE_ON, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) { - sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) { - sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.PITCH_BEND) { - sm.setMessage(ShortMessage.PITCH_BEND, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) { - sm.setMessage(ShortMessage.CHANNEL_PRESSURE, drumChannel, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.POLY_PRESSURE) { - sm.setMessage(ShortMessage.POLY_PRESSURE, drumChannel, sm.getData1(), sm.getData2()); - } - } else { - - if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) { - sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) { - sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.NOTE_OFF) { - sm.setMessage(ShortMessage.NOTE_OFF, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.NOTE_ON) { - sm.setMessage(ShortMessage.NOTE_ON, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) { - sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) { - sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.PITCH_BEND) { - sm.setMessage(ShortMessage.PITCH_BEND, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) { - sm.setMessage(ShortMessage.CHANNEL_PRESSURE, chPosition, sm.getData1(), sm.getData2()); - } - - if (sm.getCommand() == ShortMessage.POLY_PRESSURE) { - sm.setMessage(ShortMessage.POLY_PRESSURE, chPosition, sm.getData1(), sm.getData2()); - } - } - } - } - } - return sequence; - } - - private void getBankLSB(ShortMessage sm) throws InvalidMidiDataException - { - if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) - { - if (sm.getData1() == 32) - { - bankLSBValue = sm.getData2(); - customBank = true; - } - if (sm.getData1() == 0) - { - sm.setMessage(sm.getCommand(), sm.getChannel(), sm.getData1(), bankLSBValue); - } - } - } -} +/* + * Copyright (c) 2019, Rodolfo Ruiz-Velasco + * 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.musicmodifier; + +import java.io.IOException; +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +public class MidiFileAdjuster +{ + + private int bankLSBValue; + private int chPosition = -1; + + private boolean customBank = false; + + public Sequence reorderTracks(Sequence sequence) throws InvalidMidiDataException, IOException + { + for (Track track : sequence.getTracks()) + { + for (int i = 0; i < track.size(); i++) + { + MidiEvent midiEvent = track.get(i); + MidiMessage midiMessage = midiEvent.getMessage(); + + if (midiMessage instanceof ShortMessage) + { + ShortMessage sm = (ShortMessage) midiMessage; + + if (sm.getChannel() < 16) + { + getBankLSB(sm); + + if (i == 0 & bankLSBValue != 1) + { + chPosition++; + if (chPosition == 9) + { + chPosition = 10; + } + } + + if (!customBank) + { + + if (sm.getChannel() == 9) + { + bankLSBValue = 1; + } + + if (sm.getChannel() != 9) + { + bankLSBValue = 0; + } + } + } + + if (bankLSBValue == 1) + { + + int drumChannel = 9; + if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) + { + sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) + { + sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.NOTE_OFF) + { + sm.setMessage(ShortMessage.NOTE_OFF, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.NOTE_ON) + { + sm.setMessage(ShortMessage.NOTE_ON, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) + { + sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) + { + sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.PITCH_BEND) + { + sm.setMessage(ShortMessage.PITCH_BEND, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) + { + sm.setMessage(ShortMessage.CHANNEL_PRESSURE, drumChannel, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.POLY_PRESSURE) + { + sm.setMessage(ShortMessage.POLY_PRESSURE, drumChannel, sm.getData1(), sm.getData2()); + } + } + else + { + + if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) + { + sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) + { + sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.NOTE_OFF) + { + sm.setMessage(ShortMessage.NOTE_OFF, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.NOTE_ON) + { + sm.setMessage(ShortMessage.NOTE_ON, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) + { + sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) + { + sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.PITCH_BEND) + { + sm.setMessage(ShortMessage.PITCH_BEND, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) + { + sm.setMessage(ShortMessage.CHANNEL_PRESSURE, chPosition, sm.getData1(), sm.getData2()); + } + + if (sm.getCommand() == ShortMessage.POLY_PRESSURE) + { + sm.setMessage(ShortMessage.POLY_PRESSURE, chPosition, sm.getData1(), sm.getData2()); + } + } + } + } + } + return sequence; + } + + private void getBankLSB(ShortMessage sm) throws InvalidMidiDataException + { + if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) + { + if (sm.getData1() == 32) + { + bankLSBValue = sm.getData2(); + customBank = true; + } + if (sm.getData1() == 0) + { + sm.setMessage(sm.getCommand(), sm.getChannel(), sm.getData1(), bankLSBValue); + } + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MusicCustomizerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MusicCustomizerPlugin.java index 009fd81bf8..91d877d303 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MusicCustomizerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/MusicCustomizerPlugin.java @@ -1,357 +1,363 @@ -/* - * Copyright (c) 2019, Rodolfo Ruiz-Velasco - * 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.musicmodifier; - -import net.runelite.api.*; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.widgets.*; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.chatbox.ChatboxPanelManager; -import net.runelite.client.game.chatbox.ChatboxTextInput; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; - -import javax.inject.Inject; -import java.io.File; -import net.runelite.client.plugins.PluginType; - -@PluginDescriptor( - name = "Music Track Customizer", - description = "Customize what track plays and how it sounds, with local files", - tags = {"music", "sound"}, - type = PluginType.UTILITY, - enabledByDefault = false -) - -public class MusicCustomizerPlugin extends Plugin -{ - - @Inject - private Client client; - - @Inject - private ChatboxPanelManager chatboxPanelManager; - - @Inject - private ClientThread clientThread; - - private RealTimeMIDIPlayer realTimeMIDIPlayer = new RealTimeMIDIPlayer(); - - private String songName = "Scape Main"; - - private ChatboxTextInput songInput; - - private Widget playlistModeButton; - - private Widget playlistBox; - - private Widget hidePlaylistButton; - - private Widget addPlaylistSongButton; - - private Widget playlistText; - - private Widget playlistSong; - - private String defaultUnlockedSongs; - - private boolean isLooping = true; - - private boolean playlistMode = false; - - private int newSongY = 34; - - private int playlistCount = 0; - - @Override - public void startUp() - { - playSong(songName); - } - - @Override - public void shutDown() - { - if (realTimeMIDIPlayer != null) - { - realTimeMIDIPlayer.stopSong(); - } - } - - @Subscribe - public void onGameTick(GameTick event) - { - try - { - if (!playlistMode) - { - String newSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getText(); - - if (!newSong.equals(songName)) - { - songName = newSong; - playSongFromList(songName); - } - } - } catch (NullPointerException ignored) - { - - } - - } - - private void playSong(String song) - { - File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" + - "Music/" + song + ".mid/"); - if (realTimeMIDIPlayer.midi == null) - { - realTimeMIDIPlayer.midi = midiMusicFile; - realTimeMIDIPlayer.run(); - } - - else - { - if (realTimeMIDIPlayer.isPlaying()) - { - realTimeMIDIPlayer.stopSong(); - } - realTimeMIDIPlayer.midi = midiMusicFile; - realTimeMIDIPlayer.run(); - } - } - - @Subscribe - private void onWidgetLoaded(WidgetLoaded widgetLoaded) - { - if (widgetLoaded.getGroupId() == WidgetID.MUSICTAB_GROUP_ID) - { - Widget musicPlayerSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS); - if (musicPlayerSongs != null) - { - playlistModeButton = musicPlayerSongs.createChild(-1, WidgetType.GRAPHIC); - playlistModeButton.setSpriteId(SpriteID.RS2_TAB_MUSIC); - playlistModeButton.setOriginalWidth(32); - playlistModeButton.setOriginalHeight(32); - playlistModeButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); - playlistModeButton.setOriginalX(0); - playlistModeButton.setOriginalY(0); - playlistModeButton.setHasListener(true); - playlistModeButton.setAction(1, "Open"); - playlistModeButton.setOnOpListener((JavaScriptCallback) e -> openPlaylist()); - playlistModeButton.setName("Playlist"); - playlistModeButton.setHidden(true); //Playlist is not enabled for this release (Unfinished). - playlistModeButton.revalidate(); - } - } - } - - private void openPlaylist() - { - playlistMode = true; - - Widget currentPlayingSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME); - Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS); - Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR); - allInGameSongs.setHidden(true); - musicScrollbar.setHidden(true); - - defaultUnlockedSongs = client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).getText(); - - client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10"); - - playlistBox = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE); - - playlistText = playlistBox.createChild(-1, WidgetType.TEXT); - playlistText.setText("Music Playlist"); - playlistText.setFontId(497); - playlistText.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - playlistText.setOriginalX(40); - playlistText.setOriginalY(14); - playlistText.setOriginalHeight(1); - playlistText.setOriginalWidth(1); - playlistText.setTextColor(currentPlayingSong.getTextColor()); - playlistText.revalidate(); - - hidePlaylistButton = playlistBox.createChild(-1, WidgetType.GRAPHIC); - hidePlaylistButton.setSpriteId(SpriteID.RS2_TAB_MUSIC); - hidePlaylistButton.setOriginalWidth(32); - hidePlaylistButton.setOriginalHeight(32); - hidePlaylistButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); - hidePlaylistButton.setOriginalX(0); - hidePlaylistButton.setOriginalY(6); - hidePlaylistButton.setHasListener(true); - hidePlaylistButton.setAction(1, "Close"); - hidePlaylistButton.setOnOpListener((JavaScriptCallback) e -> closePlaylist()); - hidePlaylistButton.setName("Playlist"); - hidePlaylistButton.revalidate(); - - addPlaylistSongButton = playlistBox.createChild(-1, WidgetType.GRAPHIC); - addPlaylistSongButton.setSpriteId(SpriteID.BANK_ADD_TAB_ICON); - addPlaylistSongButton.setOriginalWidth(36); - addPlaylistSongButton.setOriginalHeight(32); - addPlaylistSongButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_LEFT); - addPlaylistSongButton.setOriginalX(0); - addPlaylistSongButton.setOriginalY(6); - addPlaylistSongButton.setHasListener(true); - addPlaylistSongButton.setAction(1, "Add to"); - addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput()); - addPlaylistSongButton.setName("Playlist"); - addPlaylistSongButton.revalidate(); - - if (playlistSong != null) - { - playlistSong.setHidden(false); - } - } - - private void closePlaylist() - { - playlistMode = false; - - Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS); - Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR); - allInGameSongs.setHidden(false); - musicScrollbar.setHidden(false); - - client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(defaultUnlockedSongs); - playlistText.setHidden(true); - addPlaylistSongButton.setHidden(true); - hidePlaylistButton.setHidden(true); - - if (playlistSong != null) - { - playlistSong.setHidden(true); - } - } - - private void addSongFromInput() - { - addPlaylistSongButton.setAction(1, "Close search"); - addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> closeInput()); - songInput = chatboxPanelManager.openTextInput("Please type a valid song name") - .onChanged(s -> clientThread.invokeLater(() -> updateSongs(s))) - .onClose(() -> - { - clientThread.invokeLater(() -> updateSongs(songInput.getValue())); - addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput()); - addPlaylistSongButton.setAction(1, "Add to"); - }) - .build(); - } - - private void updateSongs() - { - String song = ""; - if (chatboxIsOpen()) - { - song = songInput.getValue(); - } - updateSongs(song); - } - - private void updateSongs(String song) - { - if (playlistBox == null) - { - return; - } - - if (new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" + - "Music/" + song + ".mid/").exists()) - { - playListSongPlayer(song); - } - } - - private void playListSongPlayer(String song) - { - if (!song.equals(songName) && !chatboxIsOpen() && playlistCount < 10) - { - Widget playlistWidget = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE); - playlistSong = playlistWidget.createChild(-1, WidgetType.TEXT); - playlistSong.setText(song); - playlistSong.setFontId(495); - playlistSong.setOriginalX(12); - playlistSong.setOriginalY(newSongY); - playlistSong.setOriginalWidth(120); - playlistSong.setOriginalHeight(16); - playlistSong.setTextColor(client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getTextColor()); - playlistSong.setHasListener(true); - playlistSong.setAction(1, "Play"); - playlistSong.setOnOpListener((JavaScriptCallback) e -> playSongFromList(song)); - playlistSong.setName(song); - playlistSong.revalidate(); - - newSongY = newSongY + 15; - - songName = song; - - playlistCount++; - client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10"); - - if (playlistCount == 10) - { - addPlaylistSongButton.setHidden(true); - } - } - } - - private boolean chatboxIsOpen() - { - return songInput != null && chatboxPanelManager.getCurrentInput() == songInput; - } - - private void closeInput() - { - updateSongs(); - chatboxPanelManager.close(); - } - - private void playSongFromList(String song) - { - client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).setName(song); - File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" + - "Music/" + song + ".mid/"); - - if (realTimeMIDIPlayer.midi == null) - { - realTimeMIDIPlayer.midi = midiMusicFile; - realTimeMIDIPlayer.run(); - } - - else - { - if (realTimeMIDIPlayer.isPlaying()) - { - realTimeMIDIPlayer.stopSong(); - } - realTimeMIDIPlayer.midi = midiMusicFile; - realTimeMIDIPlayer.run(); - } - } -} +/* + * Copyright (c) 2019, Rodolfo Ruiz-Velasco + * 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.musicmodifier; + +import java.io.File; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.SpriteID; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.chatbox.ChatboxPanelManager; +import net.runelite.client.game.chatbox.ChatboxTextInput; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; + +@PluginDescriptor( + name = "Music Track Customizer", + description = "Customize what track plays and how it sounds, with local files", + tags = {"music", "sound"}, + type = PluginType.UTILITY, + enabledByDefault = false +) + +public class MusicCustomizerPlugin extends Plugin +{ + + @Inject + private Client client; + + @Inject + private ChatboxPanelManager chatboxPanelManager; + + @Inject + private ClientThread clientThread; + + private RealTimeMIDIPlayer realTimeMIDIPlayer = new RealTimeMIDIPlayer(); + + private String songName = "Scape Main"; + + private ChatboxTextInput songInput; + + private Widget playlistModeButton; + + private Widget playlistBox; + + private Widget hidePlaylistButton; + + private Widget addPlaylistSongButton; + + private Widget playlistText; + + private Widget playlistSong; + + private String defaultUnlockedSongs; + + private boolean isLooping = true; + + private boolean playlistMode = false; + + private int newSongY = 34; + + private int playlistCount = 0; + + @Override + public void startUp() + { + playSong(songName); + } + + @Override + public void shutDown() + { + if (realTimeMIDIPlayer != null) + { + realTimeMIDIPlayer.stopSong(); + } + } + + @Subscribe + public void onGameTick(GameTick event) + { + try + { + if (!playlistMode) + { + String newSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getText(); + + if (!newSong.equals(songName)) + { + songName = newSong; + playSongFromList(songName); + } + } + } + catch (NullPointerException ignored) + { + + } + + } + + private void playSong(String song) + { + File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" + + "Music/" + song + ".mid/"); + if (realTimeMIDIPlayer.midi == null) + { + realTimeMIDIPlayer.midi = midiMusicFile; + realTimeMIDIPlayer.run(); + } + + else + { + if (realTimeMIDIPlayer.isPlaying()) + { + realTimeMIDIPlayer.stopSong(); + } + realTimeMIDIPlayer.midi = midiMusicFile; + realTimeMIDIPlayer.run(); + } + } + + @Subscribe + private void onWidgetLoaded(WidgetLoaded widgetLoaded) + { + if (widgetLoaded.getGroupId() == WidgetID.MUSICTAB_GROUP_ID) + { + Widget musicPlayerSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS); + if (musicPlayerSongs != null) + { + playlistModeButton = musicPlayerSongs.createChild(-1, WidgetType.GRAPHIC); + playlistModeButton.setSpriteId(SpriteID.RS2_TAB_MUSIC); + playlistModeButton.setOriginalWidth(32); + playlistModeButton.setOriginalHeight(32); + playlistModeButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); + playlistModeButton.setOriginalX(0); + playlistModeButton.setOriginalY(0); + playlistModeButton.setHasListener(true); + playlistModeButton.setAction(1, "Open"); + playlistModeButton.setOnOpListener((JavaScriptCallback) e -> openPlaylist()); + playlistModeButton.setName("Playlist"); + playlistModeButton.setHidden(true); //Playlist is not enabled for this release (Unfinished). + playlistModeButton.revalidate(); + } + } + } + + private void openPlaylist() + { + playlistMode = true; + + Widget currentPlayingSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME); + Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS); + Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR); + allInGameSongs.setHidden(true); + musicScrollbar.setHidden(true); + + defaultUnlockedSongs = client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).getText(); + + client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10"); + + playlistBox = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE); + + playlistText = playlistBox.createChild(-1, WidgetType.TEXT); + playlistText.setText("Music Playlist"); + playlistText.setFontId(497); + playlistText.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + playlistText.setOriginalX(40); + playlistText.setOriginalY(14); + playlistText.setOriginalHeight(1); + playlistText.setOriginalWidth(1); + playlistText.setTextColor(currentPlayingSong.getTextColor()); + playlistText.revalidate(); + + hidePlaylistButton = playlistBox.createChild(-1, WidgetType.GRAPHIC); + hidePlaylistButton.setSpriteId(SpriteID.RS2_TAB_MUSIC); + hidePlaylistButton.setOriginalWidth(32); + hidePlaylistButton.setOriginalHeight(32); + hidePlaylistButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); + hidePlaylistButton.setOriginalX(0); + hidePlaylistButton.setOriginalY(6); + hidePlaylistButton.setHasListener(true); + hidePlaylistButton.setAction(1, "Close"); + hidePlaylistButton.setOnOpListener((JavaScriptCallback) e -> closePlaylist()); + hidePlaylistButton.setName("Playlist"); + hidePlaylistButton.revalidate(); + + addPlaylistSongButton = playlistBox.createChild(-1, WidgetType.GRAPHIC); + addPlaylistSongButton.setSpriteId(SpriteID.BANK_ADD_TAB_ICON); + addPlaylistSongButton.setOriginalWidth(36); + addPlaylistSongButton.setOriginalHeight(32); + addPlaylistSongButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_LEFT); + addPlaylistSongButton.setOriginalX(0); + addPlaylistSongButton.setOriginalY(6); + addPlaylistSongButton.setHasListener(true); + addPlaylistSongButton.setAction(1, "Add to"); + addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput()); + addPlaylistSongButton.setName("Playlist"); + addPlaylistSongButton.revalidate(); + + if (playlistSong != null) + { + playlistSong.setHidden(false); + } + } + + private void closePlaylist() + { + playlistMode = false; + + Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS); + Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR); + allInGameSongs.setHidden(false); + musicScrollbar.setHidden(false); + + client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(defaultUnlockedSongs); + playlistText.setHidden(true); + addPlaylistSongButton.setHidden(true); + hidePlaylistButton.setHidden(true); + + if (playlistSong != null) + { + playlistSong.setHidden(true); + } + } + + private void addSongFromInput() + { + addPlaylistSongButton.setAction(1, "Close search"); + addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> closeInput()); + songInput = chatboxPanelManager.openTextInput("Please type a valid song name") + .onChanged(s -> clientThread.invokeLater(() -> updateSongs(s))) + .onClose(() -> + { + clientThread.invokeLater(() -> updateSongs(songInput.getValue())); + addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput()); + addPlaylistSongButton.setAction(1, "Add to"); + }) + .build(); + } + + private void updateSongs() + { + String song = ""; + if (chatboxIsOpen()) + { + song = songInput.getValue(); + } + updateSongs(song); + } + + private void updateSongs(String song) + { + if (playlistBox == null) + { + return; + } + + if (new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" + + "Music/" + song + ".mid/").exists()) + { + playListSongPlayer(song); + } + } + + private void playListSongPlayer(String song) + { + if (!song.equals(songName) && !chatboxIsOpen() && playlistCount < 10) + { + Widget playlistWidget = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE); + playlistSong = playlistWidget.createChild(-1, WidgetType.TEXT); + playlistSong.setText(song); + playlistSong.setFontId(495); + playlistSong.setOriginalX(12); + playlistSong.setOriginalY(newSongY); + playlistSong.setOriginalWidth(120); + playlistSong.setOriginalHeight(16); + playlistSong.setTextColor(client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getTextColor()); + playlistSong.setHasListener(true); + playlistSong.setAction(1, "Play"); + playlistSong.setOnOpListener((JavaScriptCallback) e -> playSongFromList(song)); + playlistSong.setName(song); + playlistSong.revalidate(); + + newSongY = newSongY + 15; + + songName = song; + + playlistCount++; + client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10"); + + if (playlistCount == 10) + { + addPlaylistSongButton.setHidden(true); + } + } + } + + private boolean chatboxIsOpen() + { + return songInput != null && chatboxPanelManager.getCurrentInput() == songInput; + } + + private void closeInput() + { + updateSongs(); + chatboxPanelManager.close(); + } + + private void playSongFromList(String song) + { + client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).setName(song); + File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" + + "Music/" + song + ".mid/"); + + if (realTimeMIDIPlayer.midi == null) + { + realTimeMIDIPlayer.midi = midiMusicFile; + realTimeMIDIPlayer.run(); + } + + else + { + if (realTimeMIDIPlayer.isPlaying()) + { + realTimeMIDIPlayer.stopSong(); + } + realTimeMIDIPlayer.midi = midiMusicFile; + realTimeMIDIPlayer.run(); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/RealTimeMIDIPlayer.java b/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/RealTimeMIDIPlayer.java index 858c7465fd..6990c5cfbc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/RealTimeMIDIPlayer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/musicmodifier/RealTimeMIDIPlayer.java @@ -1,229 +1,282 @@ -/* - * Copyright (c) 2019, Rodolfo Ruiz-Velasco - * 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.musicmodifier; - -import com.sun.media.sound.AudioSynthesizer; - -import javax.sound.midi.*; -import javax.sound.sampled.*; -import java.io.*; -import java.util.HashMap; -import java.util.Map; - -public class RealTimeMIDIPlayer implements Runnable -{ - private AudioFormat format; - - private Sequence midiSequence; - - private Soundbank soundbank; - - private SourceDataLine sdl; - - private MusicCustomizerPlugin customMusicPlugin; - - private MidiFileAdjuster adjuster; - - private Clip clip; - - public boolean looping = true; - - public File soundFont = new File(System.getProperty("user.home") + "/RuneLiteAudio/SoundFonts/" + - "RuneScape 2.sf2/"); - - public File midi; - - @Override - public void run() { - - try { - - adjuster = new MidiFileAdjuster(); //Unfinished class - - midiSequence = MidiSystem.getSequence(midi); - soundbank = MidiSystem.getSoundbank(soundFont); - init(); - } - catch (IOException | InvalidMidiDataException e) - { - e.printStackTrace(); - } - } - - public void stopSong() - { - if (sdl.isRunning()) - { - sdl.stop(); - } - } - - public static AudioSynthesizer findAudioSynthesizer() throws MidiUnavailableException - { - Synthesizer synth = MidiSystem.getSynthesizer(); - if (synth instanceof AudioSynthesizer) - return (AudioSynthesizer) synth; - - double gain = 0.8D; - - MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); - MidiChannel[] channels = synth.getChannels(); - - for (int i = 0; i < channels.length; i++) - { - channels[i].controlChange(7, ((int) (channels[i].getController(7) * gain))); - } - - for (int i = 0; i < infos.length; i++) - { - MidiDevice device = MidiSystem.getMidiDevice(infos[i]); - - if (device instanceof AudioSynthesizer) - return (AudioSynthesizer) device; - } - return null; - } - - public boolean isPlaying() - { - return sdl.isActive(); - } - - public static double send(Sequence sequence, Receiver receiver) { - float divtype = sequence.getDivisionType(); - assert (sequence.getDivisionType() == Sequence.PPQ); - Track[] tracks = sequence.getTracks(); - int[] trackspos = new int[tracks.length]; - int mpq = 500000; - int seqres = sequence.getResolution(); - long lasttick = 0; - long curtime = 0; - while (true) { - MidiEvent selevent = null; - int seltrack = -1; - for (int i = 0; i < tracks.length; i++) { - int trackpos = trackspos[i]; - Track track = tracks[i]; - if (trackpos < track.size()) { - MidiEvent event = track.get(trackpos); - if (selevent == null - || event.getTick() < selevent.getTick()) { - selevent = event; - seltrack = i; - } - } - } - if (seltrack == -1) - break; - trackspos[seltrack]++; - long tick = selevent.getTick(); - if (divtype == Sequence.PPQ) - curtime += ((tick - lasttick) * mpq) / seqres; - else - curtime = (long) ((tick * 1000000.0 * divtype) / seqres); - lasttick = tick; - MidiMessage msg = selevent.getMessage(); - if (msg instanceof MetaMessage) { - if (divtype == Sequence.PPQ) - if (((MetaMessage) msg).getType() == 0x51) { - byte[] data = ((MetaMessage) msg).getData(); - mpq = ((data[0] & 0xff) << 16) - | ((data[1] & 0xff) << 8) | (data[2] & 0xff); - } - } else { - if (receiver != null) - receiver.send(msg, curtime); - } - } - return curtime / 1000000.0; - } - - public void init() { - new Thread(new Runnable() { - @Override - public void run() { - - AudioSynthesizer synth = null; - try { - synth = findAudioSynthesizer(); - format = new AudioFormat(44100, 16, 2, true, false); - - Map info = new HashMap(); - info.put("resamplerType", "sinc"); - info.put("maxPolyphony", "8192"); - AudioInputStream ais = synth.openStream(format, info); - synth.unloadAllInstruments(synth.getDefaultSoundbank()); - synth.loadAllInstruments(soundbank); - double total = send(midiSequence, synth.getReceiver()); - long length = (long) (ais.getFormat().getFrameRate() * (total + 4)); - AudioInputStream stream = new AudioInputStream(ais, format, length); - sdl = AudioSystem.getSourceDataLine(format); - sdl.open(format); - sdl.start(); - writeAudio(sdl, stream); - } catch (LineUnavailableException | MidiUnavailableException e) { - e.printStackTrace(); - } - } - }).start(); - } - - public void writeAudio(SourceDataLine sdl, AudioInputStream stream) - { - new Thread(new Runnable() { - @Override - public void run() { - - byte[] sampledAudio = new byte[1024]; - - int numBytesRead = 0; - - while (numBytesRead != -1) { - try - { - numBytesRead = stream.read(sampledAudio, 0, sampledAudio.length); - - if (numBytesRead >= 0) { - sdl.write(sampledAudio, 0, numBytesRead); - } - } - - catch (IOException e) - { - e.printStackTrace(); - } - - finally { - - if (!isPlaying() && looping) - { - this.run(); - } - } - } - } - }).start(); - } -} +/* + * Copyright (c) 2019, Rodolfo Ruiz-Velasco + * 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.musicmodifier; + +import com.sun.media.sound.AudioSynthesizer; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequence; +import javax.sound.midi.Soundbank; +import javax.sound.midi.Synthesizer; +import javax.sound.midi.Track; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; + +public class RealTimeMIDIPlayer implements Runnable +{ + private AudioFormat format; + + private Sequence midiSequence; + + private Soundbank soundbank; + + private SourceDataLine sdl; + + private MusicCustomizerPlugin customMusicPlugin; + + private MidiFileAdjuster adjuster; + + private Clip clip; + + public boolean looping = true; + + public File soundFont = new File(System.getProperty("user.home") + "/RuneLiteAudio/SoundFonts/" + + "RuneScape 2.sf2/"); + + public File midi; + + @Override + public void run() + { + + try + { + + adjuster = new MidiFileAdjuster(); //Unfinished class + + midiSequence = MidiSystem.getSequence(midi); + soundbank = MidiSystem.getSoundbank(soundFont); + init(); + } + catch (IOException | InvalidMidiDataException e) + { + e.printStackTrace(); + } + } + + public void stopSong() + { + if (sdl.isRunning()) + { + sdl.stop(); + } + } + + public static AudioSynthesizer findAudioSynthesizer() throws MidiUnavailableException + { + Synthesizer synth = MidiSystem.getSynthesizer(); + if (synth instanceof AudioSynthesizer) + { + return (AudioSynthesizer) synth; + } + + double gain = 0.8D; + + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + MidiChannel[] channels = synth.getChannels(); + + for (int i = 0; i < channels.length; i++) + { + channels[i].controlChange(7, ((int) (channels[i].getController(7) * gain))); + } + + for (int i = 0; i < infos.length; i++) + { + MidiDevice device = MidiSystem.getMidiDevice(infos[i]); + + if (device instanceof AudioSynthesizer) + { + return (AudioSynthesizer) device; + } + } + return null; + } + + public boolean isPlaying() + { + return sdl.isActive(); + } + + public static double send(Sequence sequence, Receiver receiver) + { + float divtype = sequence.getDivisionType(); + assert (sequence.getDivisionType() == Sequence.PPQ); + Track[] tracks = sequence.getTracks(); + int[] trackspos = new int[tracks.length]; + int mpq = 500000; + int seqres = sequence.getResolution(); + long lasttick = 0; + long curtime = 0; + while (true) + { + MidiEvent selevent = null; + int seltrack = -1; + for (int i = 0; i < tracks.length; i++) + { + int trackpos = trackspos[i]; + Track track = tracks[i]; + if (trackpos < track.size()) + { + MidiEvent event = track.get(trackpos); + if (selevent == null + || event.getTick() < selevent.getTick()) + { + selevent = event; + seltrack = i; + } + } + } + if (seltrack == -1) + { + break; + } + trackspos[seltrack]++; + long tick = selevent.getTick(); + if (divtype == Sequence.PPQ) + { + curtime += ((tick - lasttick) * mpq) / seqres; + } + else + { + curtime = (long) ((tick * 1000000.0 * divtype) / seqres); + } + lasttick = tick; + MidiMessage msg = selevent.getMessage(); + if (msg instanceof MetaMessage) + { + if (divtype == Sequence.PPQ) + { + if (((MetaMessage) msg).getType() == 0x51) + { + byte[] data = ((MetaMessage) msg).getData(); + mpq = ((data[0] & 0xff) << 16) + | ((data[1] & 0xff) << 8) | (data[2] & 0xff); + } + } + } + else + { + if (receiver != null) + { + receiver.send(msg, curtime); + } + } + } + return curtime / 1000000.0; + } + + public void init() + { + new Thread(new Runnable() + { + @Override + public void run() + { + + AudioSynthesizer synth = null; + try + { + synth = findAudioSynthesizer(); + format = new AudioFormat(44100, 16, 2, true, false); + + Map info = new HashMap(); + info.put("resamplerType", "sinc"); + info.put("maxPolyphony", "8192"); + AudioInputStream ais = synth.openStream(format, info); + synth.unloadAllInstruments(synth.getDefaultSoundbank()); + synth.loadAllInstruments(soundbank); + double total = send(midiSequence, synth.getReceiver()); + long length = (long) (ais.getFormat().getFrameRate() * (total + 4)); + AudioInputStream stream = new AudioInputStream(ais, format, length); + sdl = AudioSystem.getSourceDataLine(format); + sdl.open(format); + sdl.start(); + writeAudio(sdl, stream); + } + catch (LineUnavailableException | MidiUnavailableException e) + { + e.printStackTrace(); + } + } + }).start(); + } + + public void writeAudio(SourceDataLine sdl, AudioInputStream stream) + { + new Thread(new Runnable() + { + @Override + public void run() + { + + byte[] sampledAudio = new byte[1024]; + + int numBytesRead = 0; + + while (numBytesRead != -1) + { + try + { + numBytesRead = stream.read(sampledAudio, 0, sampledAudio.length); + + if (numBytesRead >= 0) + { + sdl.write(sampledAudio, 0, numBytesRead); + } + } + + catch (IOException e) + { + e.printStackTrace(); + } + + finally + { + + if (!isPlaying() && looping) + { + this.run(); + } + } + } + } + }).start(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java index 4671edde12..3ff04b6f10 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2018, Nickolaj - * 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.nightmarezone; - -import java.awt.Color; -import java.awt.image.BufferedImage; -import lombok.Setter; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.ui.overlay.infobox.Counter; - -@Setter -public class AbsorptionCounter extends Counter -{ - private int threshold; - private Color aboveThresholdColor = Color.GREEN; - private Color belowThresholdColor = Color.RED; - - AbsorptionCounter(BufferedImage image, Plugin plugin, int absorption, int threshold) - { - super(image, plugin, absorption); - this.threshold = threshold; - } - - @Override - public Color getTextColor() - { - int absorption = getCount(); - if (absorption >= threshold) - { - return aboveThresholdColor; - } - else - { - return belowThresholdColor; - } - } - - @Override - public String getTooltip() - { - int absorption = getCount(); - return "Absorption: " + absorption; - } -} +/* + * Copyright (c) 2018, Nickolaj + * 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.nightmarezone; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import lombok.Setter; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.ui.overlay.infobox.Counter; + +@Setter +public class AbsorptionCounter extends Counter +{ + private int threshold; + private Color aboveThresholdColor = Color.GREEN; + private Color belowThresholdColor = Color.RED; + + AbsorptionCounter(BufferedImage image, Plugin plugin, int absorption, int threshold) + { + super(image, plugin, absorption); + this.threshold = threshold; + } + + @Override + public Color getTextColor() + { + int absorption = getCount(); + if (absorption >= threshold) + { + return aboveThresholdColor; + } + else + { + return belowThresholdColor; + } + } + + @Override + public String getTooltip() + { + int absorption = getCount(); + return "Absorption: " + absorption; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java index 71ae196d3e..88846f02d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java @@ -1,160 +1,160 @@ -/* - * Copyright (c) 2018, Nickolaj - * 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.nightmarezone; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.ItemID; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; -import net.runelite.api.Varbits; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.overlay.Overlay; -import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; -import net.runelite.client.ui.overlay.OverlayMenuEntry; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; -import net.runelite.client.util.StackFormatter; - -class NightmareZoneOverlay extends Overlay -{ - private final Client client; - private final NightmareZoneConfig config; - private final NightmareZonePlugin plugin; - private final InfoBoxManager infoBoxManager; - private final ItemManager itemManager; - - private AbsorptionCounter absorptionCounter; - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - NightmareZoneOverlay( - Client client, - NightmareZoneConfig config, - NightmareZonePlugin plugin, - InfoBoxManager infoBoxManager, - ItemManager itemManager) - { - super(plugin); - setPosition(OverlayPosition.TOP_LEFT); - setPriority(OverlayPriority.LOW); - this.client = client; - this.config = config; - this.plugin = plugin; - this.infoBoxManager = infoBoxManager; - this.itemManager = itemManager; - getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "NMZ overlay")); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isInNightmareZone() || !config.moveOverlay()) - { - if (absorptionCounter != null) - { - removeAbsorptionCounter(); - // Restore original widget - Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); - if (nmzWidget != null) - { - nmzWidget.setHidden(false); - } - } - return null; - } - - Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); - - if (nmzWidget != null) - { - nmzWidget.setHidden(true); - } - - renderAbsorptionCounter(); - - panelComponent.getChildren().clear(); - panelComponent.getChildren().add(LineComponent.builder() - .left("Points: ") - .right(StackFormatter.formatNumber(client.getVar(Varbits.NMZ_POINTS))) - .build()); - - return panelComponent.render(graphics); - } - - private void renderAbsorptionCounter() - { - int absorptionPoints = client.getVar(Varbits.NMZ_ABSORPTION); - if (absorptionPoints == 0) - { - if (absorptionCounter != null) - { - removeAbsorptionCounter(); - absorptionCounter = null; - } - } - else if (config.moveOverlay()) - { - if (absorptionCounter == null) - { - addAbsorptionCounter(absorptionPoints); - } - else - { - absorptionCounter.setCount(absorptionPoints); - } - } - } - - private void addAbsorptionCounter(int startValue) - { - absorptionCounter = new AbsorptionCounter(itemManager.getImage(ItemID.ABSORPTION_4), plugin, startValue, config.absorptionThreshold()); - absorptionCounter.setAboveThresholdColor(config.absorptionColorAboveThreshold()); - absorptionCounter.setBelowThresholdColor(config.absorptionColorBelowThreshold()); - infoBoxManager.addInfoBox(absorptionCounter); - } - - public void removeAbsorptionCounter() - { - infoBoxManager.removeInfoBox(absorptionCounter); - absorptionCounter = null; - } - - public void updateConfig() - { - if (absorptionCounter != null) - { - absorptionCounter.setAboveThresholdColor(config.absorptionColorAboveThreshold()); - absorptionCounter.setBelowThresholdColor(config.absorptionColorBelowThreshold()); - absorptionCounter.setThreshold(config.absorptionThreshold()); - } - } -} +/* + * Copyright (c) 2018, Nickolaj + * 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.nightmarezone; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.ItemID; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.api.Varbits; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.Overlay; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.util.StackFormatter; + +class NightmareZoneOverlay extends Overlay +{ + private final Client client; + private final NightmareZoneConfig config; + private final NightmareZonePlugin plugin; + private final InfoBoxManager infoBoxManager; + private final ItemManager itemManager; + + private AbsorptionCounter absorptionCounter; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + NightmareZoneOverlay( + Client client, + NightmareZoneConfig config, + NightmareZonePlugin plugin, + InfoBoxManager infoBoxManager, + ItemManager itemManager) + { + super(plugin); + setPosition(OverlayPosition.TOP_LEFT); + setPriority(OverlayPriority.LOW); + this.client = client; + this.config = config; + this.plugin = plugin; + this.infoBoxManager = infoBoxManager; + this.itemManager = itemManager; + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "NMZ overlay")); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isInNightmareZone() || !config.moveOverlay()) + { + if (absorptionCounter != null) + { + removeAbsorptionCounter(); + // Restore original widget + Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); + if (nmzWidget != null) + { + nmzWidget.setHidden(false); + } + } + return null; + } + + Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); + + if (nmzWidget != null) + { + nmzWidget.setHidden(true); + } + + renderAbsorptionCounter(); + + panelComponent.getChildren().clear(); + panelComponent.getChildren().add(LineComponent.builder() + .left("Points: ") + .right(StackFormatter.formatNumber(client.getVar(Varbits.NMZ_POINTS))) + .build()); + + return panelComponent.render(graphics); + } + + private void renderAbsorptionCounter() + { + int absorptionPoints = client.getVar(Varbits.NMZ_ABSORPTION); + if (absorptionPoints == 0) + { + if (absorptionCounter != null) + { + removeAbsorptionCounter(); + absorptionCounter = null; + } + } + else if (config.moveOverlay()) + { + if (absorptionCounter == null) + { + addAbsorptionCounter(absorptionPoints); + } + else + { + absorptionCounter.setCount(absorptionPoints); + } + } + } + + private void addAbsorptionCounter(int startValue) + { + absorptionCounter = new AbsorptionCounter(itemManager.getImage(ItemID.ABSORPTION_4), plugin, startValue, config.absorptionThreshold()); + absorptionCounter.setAboveThresholdColor(config.absorptionColorAboveThreshold()); + absorptionCounter.setBelowThresholdColor(config.absorptionColorBelowThreshold()); + infoBoxManager.addInfoBox(absorptionCounter); + } + + public void removeAbsorptionCounter() + { + infoBoxManager.removeInfoBox(absorptionCounter); + absorptionCounter = null; + } + + public void updateConfig() + { + if (absorptionCounter != null) + { + absorptionCounter.setAboveThresholdColor(config.absorptionColorAboveThreshold()); + absorptionCounter.setBelowThresholdColor(config.absorptionColorBelowThreshold()); + absorptionCounter.setThreshold(config.absorptionThreshold()); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java index d5b91a94cd..2cf0c9885f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java @@ -1,200 +1,200 @@ -/* - * Copyright (c) 2018, Nickolaj - * 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.nightmarezone; - -import com.google.inject.Provides; -import java.util.Arrays; -import javax.inject.Inject; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.Varbits; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.Notifier; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.Text; - -@PluginDescriptor( - name = "Nightmare Zone", - description = "Show NMZ points/absorption and/or notify about expiring potions", - tags = {"combat", "nmz", "minigame", "notifications"} -) -public class NightmareZonePlugin extends Plugin -{ - private static final int[] NMZ_MAP_REGION = {9033}; - - @Inject - private Notifier notifier; - - @Inject - private Client client; - - @Inject - private OverlayManager overlayManager; - - @Inject - private NightmareZoneConfig config; - - @Inject - private NightmareZoneOverlay overlay; - - // This starts as true since you need to get - // above the threshold before sending notifications - private boolean absorptionNotificationSend = true; - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - overlay.removeAbsorptionCounter(); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - overlay.removeAbsorptionCounter(); - - Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); - - if (nmzWidget != null) - { - nmzWidget.setHidden(false); - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - overlay.updateConfig(); - } - - @Provides - NightmareZoneConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(NightmareZoneConfig.class); - } - - @Subscribe - public void onGameTick(GameTick event) - { - if (!isInNightmareZone()) - { - if (!absorptionNotificationSend) - { - absorptionNotificationSend = true; - } - - return; - } - if (config.absorptionNotification()) - { - checkAbsorption(); - } - } - - @Subscribe - public void onChatMessage(ChatMessage event) - { - if (event.getType() != ChatMessageType.GAMEMESSAGE - || !isInNightmareZone()) - { - return; - } - - String msg = Text.removeTags(event.getMessage()); //remove color - if (msg.contains("The effects of overload have worn off, and you feel normal again.")) - { - if (config.overloadNotification()) - { - notifier.notify("Your overload has worn off"); - } - } - else if (msg.contains("A power-up has spawned:")) - { - if (msg.contains("Power surge")) - { - if (config.powerSurgeNotification()) - { - notifier.notify(msg); - } - } - else if (msg.contains("Recurrent damage")) - { - if (config.recurrentDamageNotification()) - { - notifier.notify(msg); - } - } - else if (msg.contains("Zapper")) - { - if (config.zapperNotification()) - { - notifier.notify(msg); - } - } - else if (msg.contains("Ultimate force")) - { - if (config.ultimateForceNotification()) - { - notifier.notify(msg); - } - } - } - } - - private void checkAbsorption() - { - int absorptionPoints = client.getVar(Varbits.NMZ_ABSORPTION); - - if (!absorptionNotificationSend) - { - if (absorptionPoints < config.absorptionThreshold()) - { - notifier.notify("Absorption points below: " + config.absorptionThreshold()); - absorptionNotificationSend = true; - } - } - else - { - if (absorptionPoints > config.absorptionThreshold()) - { - absorptionNotificationSend = false; - } - } - } - - public boolean isInNightmareZone() - { - return Arrays.equals(client.getMapRegions(), NMZ_MAP_REGION); - } -} +/* + * Copyright (c) 2018, Nickolaj + * 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.nightmarezone; + +import com.google.inject.Provides; +import java.util.Arrays; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.Varbits; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.Text; + +@PluginDescriptor( + name = "Nightmare Zone", + description = "Show NMZ points/absorption and/or notify about expiring potions", + tags = {"combat", "nmz", "minigame", "notifications"} +) +public class NightmareZonePlugin extends Plugin +{ + private static final int[] NMZ_MAP_REGION = {9033}; + + @Inject + private Notifier notifier; + + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private NightmareZoneConfig config; + + @Inject + private NightmareZoneOverlay overlay; + + // This starts as true since you need to get + // above the threshold before sending notifications + private boolean absorptionNotificationSend = true; + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + overlay.removeAbsorptionCounter(); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + overlay.removeAbsorptionCounter(); + + Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); + + if (nmzWidget != null) + { + nmzWidget.setHidden(false); + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + overlay.updateConfig(); + } + + @Provides + NightmareZoneConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(NightmareZoneConfig.class); + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (!isInNightmareZone()) + { + if (!absorptionNotificationSend) + { + absorptionNotificationSend = true; + } + + return; + } + if (config.absorptionNotification()) + { + checkAbsorption(); + } + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (event.getType() != ChatMessageType.GAMEMESSAGE + || !isInNightmareZone()) + { + return; + } + + String msg = Text.removeTags(event.getMessage()); //remove color + if (msg.contains("The effects of overload have worn off, and you feel normal again.")) + { + if (config.overloadNotification()) + { + notifier.notify("Your overload has worn off"); + } + } + else if (msg.contains("A power-up has spawned:")) + { + if (msg.contains("Power surge")) + { + if (config.powerSurgeNotification()) + { + notifier.notify(msg); + } + } + else if (msg.contains("Recurrent damage")) + { + if (config.recurrentDamageNotification()) + { + notifier.notify(msg); + } + } + else if (msg.contains("Zapper")) + { + if (config.zapperNotification()) + { + notifier.notify(msg); + } + } + else if (msg.contains("Ultimate force")) + { + if (config.ultimateForceNotification()) + { + notifier.notify(msg); + } + } + } + } + + private void checkAbsorption() + { + int absorptionPoints = client.getVar(Varbits.NMZ_ABSORPTION); + + if (!absorptionNotificationSend) + { + if (absorptionPoints < config.absorptionThreshold()) + { + notifier.notify("Absorption points below: " + config.absorptionThreshold()); + absorptionNotificationSend = true; + } + } + else + { + if (absorptionPoints > config.absorptionThreshold()) + { + absorptionNotificationSend = false; + } + } + } + + public boolean isInNightmareZone() + { + return Arrays.equals(client.getMapRegions(), NMZ_MAP_REGION); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/notes/NotesPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/notes/NotesPlugin.java index 0b23ac8eb2..67f397c646 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/notes/NotesPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/notes/NotesPlugin.java @@ -1,93 +1,93 @@ -/* - * Copyright (c) 2018 Charlie Waters - * 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.notes; - -import com.google.inject.Provides; -import java.awt.image.BufferedImage; -import javax.inject.Inject; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.util.ImageUtil; - -@PluginDescriptor( - name = "Notes", - description = "Enable the Notes panel", - tags = {"panel"}, - loadWhenOutdated = true -) -public class NotesPlugin extends Plugin -{ - @Inject - private ClientToolbar clientToolbar; - - @Inject - private NotesConfig config; - - private NotesPanel panel; - private NavigationButton navButton; - - @Provides - NotesConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(NotesConfig.class); - } - - @Override - protected void startUp() throws Exception - { - panel = injector.getInstance(NotesPanel.class); - panel.init(config); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "notes_icon.png"); - - navButton = NavigationButton.builder() - .tooltip("Notes") - .icon(icon) - .priority(7) - .panel(panel) - .build(); - - clientToolbar.addNavigation(navButton); - } - - @Override - protected void shutDown() - { - clientToolbar.removeNavigation(navButton); - } - - @Subscribe - public void onSessionOpen(SessionOpen event) - { - // update notes - String data = config.notesData(); - panel.setNotes(data); - } -} +/* + * Copyright (c) 2018 Charlie Waters + * 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.notes; + +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.ImageUtil; + +@PluginDescriptor( + name = "Notes", + description = "Enable the Notes panel", + tags = {"panel"}, + loadWhenOutdated = true +) +public class NotesPlugin extends Plugin +{ + @Inject + private ClientToolbar clientToolbar; + + @Inject + private NotesConfig config; + + private NotesPanel panel; + private NavigationButton navButton; + + @Provides + NotesConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(NotesConfig.class); + } + + @Override + protected void startUp() throws Exception + { + panel = injector.getInstance(NotesPanel.class); + panel.init(config); + + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "notes_icon.png"); + + navButton = NavigationButton.builder() + .tooltip("Notes") + .icon(icon) + .priority(7) + .panel(panel) + .build(); + + clientToolbar.addNavigation(navButton); + } + + @Override + protected void shutDown() + { + clientToolbar.removeNavigation(navButton); + } + + @Subscribe + public void onSessionOpen(SessionOpen event) + { + // update notes + String data = config.notesData(); + panel.setNotes(data); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java index 983668eb00..1e114c453c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java @@ -67,7 +67,6 @@ import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.ColorUtil; import net.runelite.client.util.Text; import net.runelite.client.util.WildcardMatcher; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index e84b6106e9..db84106343 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -62,7 +62,7 @@ public class NpcSceneOverlay extends Overlay static { - ((DecimalFormat)TIME_LEFT_FORMATTER).applyPattern("#0.0"); + ((DecimalFormat) TIME_LEFT_FORMATTER).applyPattern("#0.0"); } private final Client client; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaOverlay.java index 811952de57..f697d68473 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaOverlay.java @@ -1,119 +1,119 @@ -/* - * Copyright (c) 2018, Woox - * 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.npcunaggroarea; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.GeneralPath; -import java.time.Instant; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.geometry.Geometry; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; - -class NpcAggroAreaOverlay extends Overlay -{ - private static final int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; - - private final Client client; - private final NpcAggroAreaConfig config; - private final NpcAggroAreaPlugin plugin; - - @Inject - private NpcAggroAreaOverlay(Client client, NpcAggroAreaConfig config, NpcAggroAreaPlugin plugin) - { - this.client = client; - this.config = config; - this.plugin = plugin; - - setLayer(OverlayLayer.ABOVE_SCENE); - setPriority(OverlayPriority.LOW); - setPosition(OverlayPosition.DYNAMIC); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isActive() || plugin.getSafeCenters()[1] == null) - { - return null; - } - - GeneralPath lines = plugin.getLinesToDisplay()[client.getPlane()]; - if (lines == null) - { - return null; - } - - Color outlineColor = config.aggroAreaColor(); - AggressionTimer timer = plugin.getCurrentTimer(); - if (timer == null || Instant.now().compareTo(timer.getEndTime()) < 0) - { - outlineColor = new Color( - outlineColor.getRed(), - outlineColor.getGreen(), - outlineColor.getBlue(), - 100); - } - - renderPath(graphics, lines, outlineColor); - return null; - } - - private void renderPath(Graphics2D graphics, GeneralPath path, Color color) - { - LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); - Rectangle viewArea = new Rectangle( - playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, - playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, - MAX_LOCAL_DRAW_LENGTH * 2, - MAX_LOCAL_DRAW_LENGTH * 2); - - graphics.setColor(color); - graphics.setStroke(new BasicStroke(1)); - - path = Geometry.clipPath(path, viewArea); - path = Geometry.filterPath(path, (p1, p2) -> - Perspective.localToCanvas(client, new LocalPoint((int)p1[0], (int)p1[1]), client.getPlane()) != null && - Perspective.localToCanvas(client, new LocalPoint((int)p2[0], (int)p2[1]), client.getPlane()) != null); - path = Geometry.transformPath(path, coords -> - { - Point point = Perspective.localToCanvas(client, new LocalPoint((int)coords[0], (int)coords[1]), client.getPlane()); - coords[0] = point.getX(); - coords[1] = point.getY(); - }); - - graphics.draw(path); - } -} +/* + * Copyright (c) 2018, Woox + * 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.npcunaggroarea; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; +import java.time.Instant; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.geometry.Geometry; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +class NpcAggroAreaOverlay extends Overlay +{ + private static final int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; + + private final Client client; + private final NpcAggroAreaConfig config; + private final NpcAggroAreaPlugin plugin; + + @Inject + private NpcAggroAreaOverlay(Client client, NpcAggroAreaConfig config, NpcAggroAreaPlugin plugin) + { + this.client = client; + this.config = config; + this.plugin = plugin; + + setLayer(OverlayLayer.ABOVE_SCENE); + setPriority(OverlayPriority.LOW); + setPosition(OverlayPosition.DYNAMIC); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isActive() || plugin.getSafeCenters()[1] == null) + { + return null; + } + + GeneralPath lines = plugin.getLinesToDisplay()[client.getPlane()]; + if (lines == null) + { + return null; + } + + Color outlineColor = config.aggroAreaColor(); + AggressionTimer timer = plugin.getCurrentTimer(); + if (timer == null || Instant.now().compareTo(timer.getEndTime()) < 0) + { + outlineColor = new Color( + outlineColor.getRed(), + outlineColor.getGreen(), + outlineColor.getBlue(), + 100); + } + + renderPath(graphics, lines, outlineColor); + return null; + } + + private void renderPath(Graphics2D graphics, GeneralPath path, Color color) + { + LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); + Rectangle viewArea = new Rectangle( + playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, + playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, + MAX_LOCAL_DRAW_LENGTH * 2, + MAX_LOCAL_DRAW_LENGTH * 2); + + graphics.setColor(color); + graphics.setStroke(new BasicStroke(1)); + + path = Geometry.clipPath(path, viewArea); + path = Geometry.filterPath(path, (p1, p2) -> + Perspective.localToCanvas(client, new LocalPoint((int) p1[0], (int) p1[1]), client.getPlane()) != null && + Perspective.localToCanvas(client, new LocalPoint((int) p2[0], (int) p2[1]), client.getPlane()) != null); + path = Geometry.transformPath(path, coords -> + { + Point point = Perspective.localToCanvas(client, new LocalPoint((int) coords[0], (int) coords[1]), client.getPlane()); + coords[0] = point.getX(); + coords[1] = point.getY(); + }); + + graphics.draw(path); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java index 6d10bdba62..50aac7cf2c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java @@ -194,7 +194,7 @@ public class NpcAggroAreaPlugin extends Plugin private void transformWorldToLocal(float[] coords) { - final LocalPoint lp = LocalPoint.fromWorld(client, (int)coords[0], (int)coords[1]); + final LocalPoint lp = LocalPoint.fromWorld(client, (int) coords[0], (int) coords[1]); coords[0] = lp.getX() - Perspective.LOCAL_TILE_SIZE / 2f; coords[1] = lp.getY() - Perspective.LOCAL_TILE_SIZE / 2f; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java index 05fd84d0d8..3ab1377b8a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java @@ -1,391 +1,391 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * Copyright (c) 2018, Adam - * 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.objectindicators; - -import com.google.common.base.Strings; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.google.inject.Provides; -import java.awt.event.KeyEvent; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import static net.runelite.api.Constants.REGION_SIZE; -import net.runelite.api.DecorativeObject; -import net.runelite.api.GameObject; -import net.runelite.api.GameState; -import net.runelite.api.MenuAction; -import net.runelite.api.MenuEntry; -import net.runelite.api.ObjectComposition; -import net.runelite.api.Scene; -import net.runelite.api.Tile; -import net.runelite.api.TileObject; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.FocusChanged; -import net.runelite.api.events.GameObjectDespawned; -import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.events.MenuOptionClicked; -import net.runelite.api.events.DecorativeObjectSpawned; -import net.runelite.api.events.DecorativeObjectDespawned; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -@Slf4j -@PluginDescriptor( - name = "Object Markers", - description = "Enable marking of objects using the Shift key", - tags = {"overlay", "objects", "mark", "marker"}, - enabledByDefault = false -) -public class ObjectIndicatorsPlugin extends Plugin implements KeyListener -{ - private static final String CONFIG_GROUP = "objectindicators"; - private static final String MARK = "Mark object"; - - private final Gson GSON = new Gson(); - @Getter(AccessLevel.PACKAGE) - private final List objects = new ArrayList<>(); - private final Map> points = new HashMap<>(); - private boolean hotKeyPressed; - - @Inject - private Client client; - - @Inject - private ConfigManager configManager; - - @Inject - private OverlayManager overlayManager; - - @Inject - private ObjectIndicatorsOverlay overlay; - - @Inject - private KeyManager keyManager; - - @Provides - ObjectIndicatorsConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(ObjectIndicatorsConfig.class); - } - - @Override - protected void startUp() - { - overlayManager.add(overlay); - keyManager.registerKeyListener(this); - } - - @Override - protected void shutDown() - { - overlayManager.remove(overlay); - keyManager.unregisterKeyListener(this); - points.clear(); - objects.clear(); - hotKeyPressed = false; - } - - @Override - public void keyTyped(KeyEvent e) - { - - } - - @Override - public void keyPressed(KeyEvent e) - { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) - { - hotKeyPressed = true; - } - } - - @Override - public void keyReleased(KeyEvent e) - { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) - { - hotKeyPressed = false; - } - } - - @Subscribe - public void onFocusChanged(final FocusChanged event) - { - if (!event.isFocused()) - { - hotKeyPressed = false; - } - } - - @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) - { - final GameObject eventObject = event.getGameObject(); - checkObjectPoints(eventObject); - } - - @Subscribe - public void onDecorativeObjectSpawned(DecorativeObjectSpawned event) - { - final DecorativeObject eventObject = event.getDecorativeObject(); - checkObjectPoints(eventObject); - } - - @Subscribe - public void onGameObjectDespawned(GameObjectDespawned event) - { - objects.remove(event.getGameObject()); - } - - @Subscribe - public void onDecorativeObjectDespawned(DecorativeObjectDespawned event) - { - objects.remove(event.getDecorativeObject()); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged gameStateChanged) - { - GameState gameState = gameStateChanged.getGameState(); - if (gameState == GameState.LOADING) - { - // Reload points with new map regions - - points.clear(); - for (int regionId : client.getMapRegions()) - { - // load points for region - final Set regionPoints = loadPoints(regionId); - if (regionPoints != null) - { - points.put(regionId, regionPoints); - } - } - } - - if (gameStateChanged.getGameState() != GameState.LOGGED_IN) - { - objects.clear(); - } - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) - { - if (!hotKeyPressed || event.getType() != MenuAction.EXAMINE_OBJECT.getId()) - { - return; - } - - MenuEntry[] menuEntries = client.getMenuEntries(); - menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); - MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - menuEntry.setOption(MARK); - menuEntry.setTarget(event.getTarget()); - menuEntry.setParam0(event.getActionParam0()); - menuEntry.setParam1(event.getActionParam1()); - menuEntry.setIdentifier(event.getIdentifier()); - menuEntry.setType(MenuAction.RUNELITE.getId()); - client.setMenuEntries(menuEntries); - } - - @Subscribe - public void onMenuOptionClicked(MenuOptionClicked event) - { - if (event.getMenuAction() != MenuAction.RUNELITE || !event.getMenuOption().equals(MARK)) - { - return; - } - - Scene scene = client.getScene(); - Tile[][][] tiles = scene.getTiles(); - final int x = event.getActionParam(); - final int y = event.getWidgetId(); - final int z = client.getPlane(); - final Tile tile = tiles[z][x][y]; - - TileObject object = findTileObject(tile, event.getId()); - if (object == null) - { - return; - } - - ObjectComposition objectDefinition = client.getObjectDefinition(object.getId()); - String name = objectDefinition.getName(); - if (Strings.isNullOrEmpty(name)) - { - return; - } - - markObject(name, object); - } - - private void checkObjectPoints(TileObject object) - { - final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, object.getLocalLocation()); - final Set objectPoints = points.get(worldPoint.getRegionID()); - - if (objectPoints == null) - { - return; - } - - for (ObjectPoint objectPoint : objectPoints) - { - if ((worldPoint.getX() & (REGION_SIZE - 1)) == objectPoint.getRegionX() - && (worldPoint.getY() & (REGION_SIZE - 1)) == objectPoint.getRegionY()) - { - if (objectPoint.getName().equals(client.getObjectDefinition(object.getId()).getName())) - { - objects.add(object); - break; - } - } - } - } - - private TileObject findTileObject(Tile tile, int id) - { - if (tile == null) - { - return null; - } - - final GameObject[] tileGameObjects = tile.getGameObjects(); - final DecorativeObject tileDecorativeObject = tile.getDecorativeObject(); - - if (tileDecorativeObject != null && tileDecorativeObject.getId() == id) - { - return tileDecorativeObject; - } - - for (GameObject object : tileGameObjects) - { - if (object == null) - { - continue; - } - - if (object.getId() == id) - { - return object; - } - - // Check impostors - final ObjectComposition comp = client.getObjectDefinition(object.getId()); - - if (comp.getImpostorIds() != null) - { - for (int impostorId : comp.getImpostorIds()) - { - if (impostorId == id) - { - return object; - } - } - } - } - - return null; - } - - private void markObject(String name, final TileObject object) - { - if (object == null) - { - return; - } - - final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, object.getLocalLocation()); - final int regionId = worldPoint.getRegionID(); - final ObjectPoint point = new ObjectPoint( - name, - regionId, - worldPoint.getX() & (REGION_SIZE - 1), - worldPoint.getY() & (REGION_SIZE - 1), - client.getPlane()); - - Set objectPoints = points.computeIfAbsent(regionId, k -> new HashSet<>()); - - if (objectPoints.contains(point)) - { - objectPoints.remove(point); - objects.remove(object); - } - else - { - objectPoints.add(point); - objects.add(object); - } - - savePoints(regionId, objectPoints); - } - - private void savePoints(final int id, final Set points) - { - if (points.isEmpty()) - { - configManager.unsetConfiguration(CONFIG_GROUP, "region_" + id); - } - else - { - final String json = GSON.toJson(points); - configManager.setConfiguration(CONFIG_GROUP, "region_" + id, json); - } - } - - private Set loadPoints(final int id) - { - final String json = configManager.getConfiguration(CONFIG_GROUP, "region_" + id); - - if (Strings.isNullOrEmpty(json)) - { - return null; - } - - return GSON.fromJson(json, new TypeToken>() - { - }.getType()); - } +/* + * Copyright (c) 2018, Tomas Slusny + * Copyright (c) 2018, Adam + * 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.objectindicators; + +import com.google.common.base.Strings; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.inject.Provides; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import static net.runelite.api.Constants.REGION_SIZE; +import net.runelite.api.DecorativeObject; +import net.runelite.api.GameObject; +import net.runelite.api.GameState; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.ObjectComposition; +import net.runelite.api.Scene; +import net.runelite.api.Tile; +import net.runelite.api.TileObject; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.DecorativeObjectDespawned; +import net.runelite.api.events.DecorativeObjectSpawned; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.events.GameObjectDespawned; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +@Slf4j +@PluginDescriptor( + name = "Object Markers", + description = "Enable marking of objects using the Shift key", + tags = {"overlay", "objects", "mark", "marker"}, + enabledByDefault = false +) +public class ObjectIndicatorsPlugin extends Plugin implements KeyListener +{ + private static final String CONFIG_GROUP = "objectindicators"; + private static final String MARK = "Mark object"; + + private final Gson GSON = new Gson(); + @Getter(AccessLevel.PACKAGE) + private final List objects = new ArrayList<>(); + private final Map> points = new HashMap<>(); + private boolean hotKeyPressed; + + @Inject + private Client client; + + @Inject + private ConfigManager configManager; + + @Inject + private OverlayManager overlayManager; + + @Inject + private ObjectIndicatorsOverlay overlay; + + @Inject + private KeyManager keyManager; + + @Provides + ObjectIndicatorsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(ObjectIndicatorsConfig.class); + } + + @Override + protected void startUp() + { + overlayManager.add(overlay); + keyManager.registerKeyListener(this); + } + + @Override + protected void shutDown() + { + overlayManager.remove(overlay); + keyManager.unregisterKeyListener(this); + points.clear(); + objects.clear(); + hotKeyPressed = false; + } + + @Override + public void keyTyped(KeyEvent e) + { + + } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) + { + hotKeyPressed = true; + } + } + + @Override + public void keyReleased(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) + { + hotKeyPressed = false; + } + } + + @Subscribe + public void onFocusChanged(final FocusChanged event) + { + if (!event.isFocused()) + { + hotKeyPressed = false; + } + } + + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) + { + final GameObject eventObject = event.getGameObject(); + checkObjectPoints(eventObject); + } + + @Subscribe + public void onDecorativeObjectSpawned(DecorativeObjectSpawned event) + { + final DecorativeObject eventObject = event.getDecorativeObject(); + checkObjectPoints(eventObject); + } + + @Subscribe + public void onGameObjectDespawned(GameObjectDespawned event) + { + objects.remove(event.getGameObject()); + } + + @Subscribe + public void onDecorativeObjectDespawned(DecorativeObjectDespawned event) + { + objects.remove(event.getDecorativeObject()); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + GameState gameState = gameStateChanged.getGameState(); + if (gameState == GameState.LOADING) + { + // Reload points with new map regions + + points.clear(); + for (int regionId : client.getMapRegions()) + { + // load points for region + final Set regionPoints = loadPoints(regionId); + if (regionPoints != null) + { + points.put(regionId, regionPoints); + } + } + } + + if (gameStateChanged.getGameState() != GameState.LOGGED_IN) + { + objects.clear(); + } + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + if (!hotKeyPressed || event.getType() != MenuAction.EXAMINE_OBJECT.getId()) + { + return; + } + + MenuEntry[] menuEntries = client.getMenuEntries(); + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); + MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); + menuEntry.setOption(MARK); + menuEntry.setTarget(event.getTarget()); + menuEntry.setParam0(event.getActionParam0()); + menuEntry.setParam1(event.getActionParam1()); + menuEntry.setIdentifier(event.getIdentifier()); + menuEntry.setType(MenuAction.RUNELITE.getId()); + client.setMenuEntries(menuEntries); + } + + @Subscribe + public void onMenuOptionClicked(MenuOptionClicked event) + { + if (event.getMenuAction() != MenuAction.RUNELITE || !event.getMenuOption().equals(MARK)) + { + return; + } + + Scene scene = client.getScene(); + Tile[][][] tiles = scene.getTiles(); + final int x = event.getActionParam(); + final int y = event.getWidgetId(); + final int z = client.getPlane(); + final Tile tile = tiles[z][x][y]; + + TileObject object = findTileObject(tile, event.getId()); + if (object == null) + { + return; + } + + ObjectComposition objectDefinition = client.getObjectDefinition(object.getId()); + String name = objectDefinition.getName(); + if (Strings.isNullOrEmpty(name)) + { + return; + } + + markObject(name, object); + } + + private void checkObjectPoints(TileObject object) + { + final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, object.getLocalLocation()); + final Set objectPoints = points.get(worldPoint.getRegionID()); + + if (objectPoints == null) + { + return; + } + + for (ObjectPoint objectPoint : objectPoints) + { + if ((worldPoint.getX() & (REGION_SIZE - 1)) == objectPoint.getRegionX() + && (worldPoint.getY() & (REGION_SIZE - 1)) == objectPoint.getRegionY()) + { + if (objectPoint.getName().equals(client.getObjectDefinition(object.getId()).getName())) + { + objects.add(object); + break; + } + } + } + } + + private TileObject findTileObject(Tile tile, int id) + { + if (tile == null) + { + return null; + } + + final GameObject[] tileGameObjects = tile.getGameObjects(); + final DecorativeObject tileDecorativeObject = tile.getDecorativeObject(); + + if (tileDecorativeObject != null && tileDecorativeObject.getId() == id) + { + return tileDecorativeObject; + } + + for (GameObject object : tileGameObjects) + { + if (object == null) + { + continue; + } + + if (object.getId() == id) + { + return object; + } + + // Check impostors + final ObjectComposition comp = client.getObjectDefinition(object.getId()); + + if (comp.getImpostorIds() != null) + { + for (int impostorId : comp.getImpostorIds()) + { + if (impostorId == id) + { + return object; + } + } + } + } + + return null; + } + + private void markObject(String name, final TileObject object) + { + if (object == null) + { + return; + } + + final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, object.getLocalLocation()); + final int regionId = worldPoint.getRegionID(); + final ObjectPoint point = new ObjectPoint( + name, + regionId, + worldPoint.getX() & (REGION_SIZE - 1), + worldPoint.getY() & (REGION_SIZE - 1), + client.getPlane()); + + Set objectPoints = points.computeIfAbsent(regionId, k -> new HashSet<>()); + + if (objectPoints.contains(point)) + { + objectPoints.remove(point); + objects.remove(object); + } + else + { + objectPoints.add(point); + objects.add(object); + } + + savePoints(regionId, objectPoints); + } + + private void savePoints(final int id, final Set points) + { + if (points.isEmpty()) + { + configManager.unsetConfiguration(CONFIG_GROUP, "region_" + id); + } + else + { + final String json = GSON.toJson(points); + configManager.setConfiguration(CONFIG_GROUP, "region_" + id, json); + } + } + + private Set loadPoints(final int id) + { + final String json = configManager.getConfiguration(CONFIG_GROUP, "region_" + id); + + if (Strings.isNullOrEmpty(json)) + { + return null; + } + + return GSON.fromJson(json, new TypeToken>() + { + }.getType()); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/PlayerComparisonOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/PlayerComparisonOverlay.java index 7517e4e3bf..9f3f8afb4c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/PlayerComparisonOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/PlayerComparisonOverlay.java @@ -1,187 +1,187 @@ -/* - * Copyright (c) 2018, Jordan Atwood - * Copyright (c) 2018, Adam - * 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.opponentinfo; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; -import net.runelite.api.Actor; -import net.runelite.api.Client; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; -import net.runelite.api.Player; -import net.runelite.api.Skill; -import net.runelite.client.game.HiscoreManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; -import net.runelite.client.ui.overlay.OverlayMenuEntry; -import net.runelite.client.ui.overlay.OverlayPosition; -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.Text; -import net.runelite.http.api.hiscore.HiscoreResult; -import net.runelite.http.api.hiscore.HiscoreSkill; - -class PlayerComparisonOverlay extends Overlay -{ - private static final Color HIGHER_STAT_TEXT_COLOR = Color.GREEN; - private static final Color LOWER_STAT_TEXT_COLOR = Color.RED; - private static final Color NEUTRAL_TEXT_COLOR = Color.WHITE; - private static final Color HIGHLIGHT_COLOR = new Color(255, 200, 0, 255); - - private static final Skill[] COMBAT_SKILLS = new Skill[]{ - Skill.ATTACK, - Skill.STRENGTH, - Skill.DEFENCE, - Skill.HITPOINTS, - Skill.RANGED, - Skill.MAGIC, - Skill.PRAYER - }; - - private static final HiscoreSkill[] HISCORE_COMBAT_SKILLS = new HiscoreSkill[]{ - HiscoreSkill.ATTACK, - HiscoreSkill.STRENGTH, - HiscoreSkill.DEFENCE, - HiscoreSkill.HITPOINTS, - HiscoreSkill.RANGED, - HiscoreSkill.MAGIC, - HiscoreSkill.PRAYER - }; - - private static final String LEFT_COLUMN_HEADER = "Skill"; - private static final String RIGHT_COLUMN_HEADER = "You/Them"; - - private final Client client; - private final OpponentInfoPlugin opponentInfoPlugin; - private final OpponentInfoConfig config; - private final HiscoreManager hiscoreManager; - private final PanelComponent panelComponent = new PanelComponent(); - - @Inject - private PlayerComparisonOverlay(Client client, OpponentInfoPlugin opponentInfoPlugin, OpponentInfoConfig config, HiscoreManager hiscoreManager) - { - super(opponentInfoPlugin); - this.client = client; - this.opponentInfoPlugin = opponentInfoPlugin; - this.config = config; - this.hiscoreManager = hiscoreManager; - - setPosition(OverlayPosition.BOTTOM_LEFT); - setLayer(OverlayLayer.ABOVE_WIDGETS); - getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Opponent info overlay")); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!config.lookupOnInteraction()) - { - return null; - } - - final Actor opponent = opponentInfoPlugin.getLastOpponent(); - - if (opponent == null) - { - return null; - } - - // Don't try to look up NPC names - if (!(opponent instanceof Player)) - { - return null; - } - - final String opponentName = Text.removeTags(opponent.getName()); - final HiscoreResult hiscoreResult = hiscoreManager.lookupAsync(opponentName, opponentInfoPlugin.getHiscoreEndpoint()); - if (hiscoreResult == null) - { - return null; - } - - panelComponent.getChildren().clear(); - generateComparisonTable(panelComponent, hiscoreResult); - return panelComponent.render(graphics); - } - - private void generateComparisonTable(PanelComponent panelComponent, HiscoreResult opponentSkills) - { - final String opponentName = opponentSkills.getPlayer(); - - panelComponent.getChildren().add( - TitleComponent.builder() - .text(opponentName) - .color(HIGHLIGHT_COLOR) - .build()); - - panelComponent.getChildren().add( - LineComponent.builder() - .left(LEFT_COLUMN_HEADER) - .leftColor(HIGHLIGHT_COLOR) - .right(RIGHT_COLUMN_HEADER) - .rightColor(HIGHLIGHT_COLOR) - .build()); - - for (int i = 0; i < COMBAT_SKILLS.length; ++i) - { - final HiscoreSkill hiscoreSkill = HISCORE_COMBAT_SKILLS[i]; - final Skill skill = COMBAT_SKILLS[i]; - - final net.runelite.http.api.hiscore.Skill opponentSkill = opponentSkills.getSkill(hiscoreSkill); - - if (opponentSkill == null || opponentSkill.getLevel() == -1) - { - continue; - } - - final int playerSkillLevel = client.getRealSkillLevel(skill); - final int opponentSkillLevel = opponentSkill.getLevel(); - - panelComponent.getChildren().add( - LineComponent.builder() - .left(hiscoreSkill.getName()) - .right(Integer.toString(playerSkillLevel) + "/" + Integer.toString(opponentSkillLevel)) - .rightColor(comparisonStatColor(playerSkillLevel, opponentSkillLevel)) - .build()); - } - } - - private static Color comparisonStatColor(int a, int b) - { - if (a > b) - { - return HIGHER_STAT_TEXT_COLOR; - } - if (a < b) - { - return LOWER_STAT_TEXT_COLOR; - } - return NEUTRAL_TEXT_COLOR; - } -} +/* + * Copyright (c) 2018, Jordan Atwood + * Copyright (c) 2018, Adam + * 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.opponentinfo; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.api.Player; +import net.runelite.api.Skill; +import net.runelite.client.game.HiscoreManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.OverlayPosition; +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.Text; +import net.runelite.http.api.hiscore.HiscoreResult; +import net.runelite.http.api.hiscore.HiscoreSkill; + +class PlayerComparisonOverlay extends Overlay +{ + private static final Color HIGHER_STAT_TEXT_COLOR = Color.GREEN; + private static final Color LOWER_STAT_TEXT_COLOR = Color.RED; + private static final Color NEUTRAL_TEXT_COLOR = Color.WHITE; + private static final Color HIGHLIGHT_COLOR = new Color(255, 200, 0, 255); + + private static final Skill[] COMBAT_SKILLS = new Skill[]{ + Skill.ATTACK, + Skill.STRENGTH, + Skill.DEFENCE, + Skill.HITPOINTS, + Skill.RANGED, + Skill.MAGIC, + Skill.PRAYER + }; + + private static final HiscoreSkill[] HISCORE_COMBAT_SKILLS = new HiscoreSkill[]{ + HiscoreSkill.ATTACK, + HiscoreSkill.STRENGTH, + HiscoreSkill.DEFENCE, + HiscoreSkill.HITPOINTS, + HiscoreSkill.RANGED, + HiscoreSkill.MAGIC, + HiscoreSkill.PRAYER + }; + + private static final String LEFT_COLUMN_HEADER = "Skill"; + private static final String RIGHT_COLUMN_HEADER = "You/Them"; + + private final Client client; + private final OpponentInfoPlugin opponentInfoPlugin; + private final OpponentInfoConfig config; + private final HiscoreManager hiscoreManager; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + private PlayerComparisonOverlay(Client client, OpponentInfoPlugin opponentInfoPlugin, OpponentInfoConfig config, HiscoreManager hiscoreManager) + { + super(opponentInfoPlugin); + this.client = client; + this.opponentInfoPlugin = opponentInfoPlugin; + this.config = config; + this.hiscoreManager = hiscoreManager; + + setPosition(OverlayPosition.BOTTOM_LEFT); + setLayer(OverlayLayer.ABOVE_WIDGETS); + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Opponent info overlay")); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!config.lookupOnInteraction()) + { + return null; + } + + final Actor opponent = opponentInfoPlugin.getLastOpponent(); + + if (opponent == null) + { + return null; + } + + // Don't try to look up NPC names + if (!(opponent instanceof Player)) + { + return null; + } + + final String opponentName = Text.removeTags(opponent.getName()); + final HiscoreResult hiscoreResult = hiscoreManager.lookupAsync(opponentName, opponentInfoPlugin.getHiscoreEndpoint()); + if (hiscoreResult == null) + { + return null; + } + + panelComponent.getChildren().clear(); + generateComparisonTable(panelComponent, hiscoreResult); + return panelComponent.render(graphics); + } + + private void generateComparisonTable(PanelComponent panelComponent, HiscoreResult opponentSkills) + { + final String opponentName = opponentSkills.getPlayer(); + + panelComponent.getChildren().add( + TitleComponent.builder() + .text(opponentName) + .color(HIGHLIGHT_COLOR) + .build()); + + panelComponent.getChildren().add( + LineComponent.builder() + .left(LEFT_COLUMN_HEADER) + .leftColor(HIGHLIGHT_COLOR) + .right(RIGHT_COLUMN_HEADER) + .rightColor(HIGHLIGHT_COLOR) + .build()); + + for (int i = 0; i < COMBAT_SKILLS.length; ++i) + { + final HiscoreSkill hiscoreSkill = HISCORE_COMBAT_SKILLS[i]; + final Skill skill = COMBAT_SKILLS[i]; + + final net.runelite.http.api.hiscore.Skill opponentSkill = opponentSkills.getSkill(hiscoreSkill); + + if (opponentSkill == null || opponentSkill.getLevel() == -1) + { + continue; + } + + final int playerSkillLevel = client.getRealSkillLevel(skill); + final int opponentSkillLevel = opponentSkill.getLevel(); + + panelComponent.getChildren().add( + LineComponent.builder() + .left(hiscoreSkill.getName()) + .right(playerSkillLevel + "/" + opponentSkillLevel) + .rightColor(comparisonStatColor(playerSkillLevel, opponentSkillLevel)) + .build()); + } + } + + private static Color comparisonStatColor(int a, int b) + { + if (a > b) + { + return HIGHER_STAT_TEXT_COLOR; + } + if (a < b) + { + return LOWER_STAT_TEXT_COLOR; + } + return NEUTRAL_TEXT_COLOR; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPluginService.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPluginService.java index 8f944eb833..c31fd86444 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPluginService.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPluginService.java @@ -1,40 +1,41 @@ -/* - * Copyright (c) 2019, Adam - * 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.party; - -import java.util.UUID; -import javax.annotation.Nullable; -import net.runelite.client.plugins.party.data.PartyData; - -public interface PartyPluginService -{ - /** - * Get the party data for a party member - * @param memberId member id - * @return party data for member - */ - @Nullable - PartyData getPartyData(UUID memberId); -} +/* + * Copyright (c) 2019, Adam + * 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.party; + +import java.util.UUID; +import javax.annotation.Nullable; +import net.runelite.client.plugins.party.data.PartyData; + +public interface PartyPluginService +{ + /** + * Get the party data for a party member + * + * @param memberId member id + * @return party data for member + */ + @Nullable + PartyData getPartyData(UUID memberId); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PortalWeaknessOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PortalWeaknessOverlay.java index ff0deee9c2..ed83ff2b2e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PortalWeaknessOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PortalWeaknessOverlay.java @@ -1,198 +1,194 @@ -/* - * Copyright (c) 2019, Yani - * 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.pestcontrol; - -import com.google.inject.Inject; -import java.awt.AlphaComposite; -import java.awt.Composite; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.ItemID; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.Skill; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; - -@Slf4j -public class PortalWeaknessOverlay extends Overlay -{ - private int zOffset = 100; - - private final PestControlConfig config; - private final PestControlPlugin plugin; - private final Client client; - - private BufferedImage magicImage; - private BufferedImage rangedImage; - private BufferedImage stabImage; - private BufferedImage slashImage; - private BufferedImage crushImage; - - @Inject - PortalWeaknessOverlay( - PestControlConfig config, - PestControlPlugin plugin, - Client client, - ItemManager itemManager, - SkillIconManager skillIconManager - ) - { - this.config = config; - this.plugin = plugin; - this.client = client; - - this.magicImage = skillIconManager.getSkillImage(Skill.MAGIC); - this.rangedImage = skillIconManager.getSkillImage(Skill.RANGED); - - this.stabImage = itemManager.getImage(ItemID.WHITE_DAGGER); - this.slashImage = itemManager.getImage(ItemID.WHITE_SCIMITAR); - this.crushImage = itemManager.getImage(ItemID.WHITE_WARHAMMER); - - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.UNDER_WIDGETS); - } - - private Point getPortalPoint(Portal portal) - { - WorldPoint portalLocation = portal.getLocation(); - LocalPoint localLocation = LocalPoint.fromWorld(client, portalLocation); - - if (localLocation == null) - { - return null; - } - - // We can use any image here as it's only needed to calculate the position - Point imageLocation = Perspective.getCanvasImageLocation(client, localLocation, magicImage, zOffset); - - if (imageLocation != null) - { - return imageLocation; - } - - return null; - } - - private void renderPortalWeakness(Graphics2D graphics, Portal portal, BufferedImage image) - { - Point portalPoint = getPortalPoint(portal); - - if (portalPoint != null) - { - Composite originalComposite = graphics.getComposite(); - Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - graphics.setComposite(translucentComposite); - - OverlayUtil.renderImageLocation(graphics, portalPoint, image); - - graphics.setComposite(originalComposite); - } - } - - private void renderDoublePortalWeakness( - Graphics2D graphics, - Portal portal, - BufferedImage imageLeft, - BufferedImage imageRight - ) - { - Point portalPoint = getPortalPoint(portal); - - if (portalPoint != null) - { - Point portalLeft = new Point( - portalPoint.getX() - (imageLeft.getWidth() / 2) - 5, - portalPoint.getY() - ); - - Point portalRight = new Point( - portalPoint.getX() + (imageRight.getWidth() / 2) + 5, - portalPoint.getY() - ); - - Composite originalComposite = graphics.getComposite(); - Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - graphics.setComposite(translucentComposite); - - OverlayUtil.renderImageLocation(graphics, portalLeft, imageLeft); - OverlayUtil.renderImageLocation(graphics, portalPoint, imageRight); - - graphics.setComposite(originalComposite); - } - } - - @Override - public Dimension render(Graphics2D graphics) - { - Game game = plugin.getGame(); - - if (game == null) - { - return null; - } - - for (Portal portal : game.getPortals()) - { - if (!portal.isDead()) - { - switch (portal.getColor()) - { - case BLUE: - { - renderPortalWeakness(graphics, portal, magicImage); - break; - } - case YELLOW: - { - renderDoublePortalWeakness(graphics, portal, stabImage, slashImage); - break; - } - case RED: - { - renderPortalWeakness(graphics, portal, crushImage); - break; - } - case PURPLE: - { - renderPortalWeakness(graphics, portal, rangedImage); - break; - } - } - } - } - - return null; - } +/* + * Copyright (c) 2019, Yani + * 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.pestcontrol; + +import com.google.inject.Inject; +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.ItemID; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.Skill; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SkillIconManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; + +@Slf4j +public class PortalWeaknessOverlay extends Overlay +{ + private int zOffset = 100; + + private final PestControlConfig config; + private final PestControlPlugin plugin; + private final Client client; + + private BufferedImage magicImage; + private BufferedImage rangedImage; + private BufferedImage stabImage; + private BufferedImage slashImage; + private BufferedImage crushImage; + + @Inject + PortalWeaknessOverlay( + PestControlConfig config, + PestControlPlugin plugin, + Client client, + ItemManager itemManager, + SkillIconManager skillIconManager + ) + { + this.config = config; + this.plugin = plugin; + this.client = client; + + this.magicImage = skillIconManager.getSkillImage(Skill.MAGIC); + this.rangedImage = skillIconManager.getSkillImage(Skill.RANGED); + + this.stabImage = itemManager.getImage(ItemID.WHITE_DAGGER); + this.slashImage = itemManager.getImage(ItemID.WHITE_SCIMITAR); + this.crushImage = itemManager.getImage(ItemID.WHITE_WARHAMMER); + + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.UNDER_WIDGETS); + } + + private Point getPortalPoint(Portal portal) + { + WorldPoint portalLocation = portal.getLocation(); + LocalPoint localLocation = LocalPoint.fromWorld(client, portalLocation); + + if (localLocation == null) + { + return null; + } + + // We can use any image here as it's only needed to calculate the position + Point imageLocation = Perspective.getCanvasImageLocation(client, localLocation, magicImage, zOffset); + + return imageLocation; + + } + + private void renderPortalWeakness(Graphics2D graphics, Portal portal, BufferedImage image) + { + Point portalPoint = getPortalPoint(portal); + + if (portalPoint != null) + { + Composite originalComposite = graphics.getComposite(); + Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); + graphics.setComposite(translucentComposite); + + OverlayUtil.renderImageLocation(graphics, portalPoint, image); + + graphics.setComposite(originalComposite); + } + } + + private void renderDoublePortalWeakness( + Graphics2D graphics, + Portal portal, + BufferedImage imageLeft, + BufferedImage imageRight + ) + { + Point portalPoint = getPortalPoint(portal); + + if (portalPoint != null) + { + Point portalLeft = new Point( + portalPoint.getX() - (imageLeft.getWidth() / 2) - 5, + portalPoint.getY() + ); + + Point portalRight = new Point( + portalPoint.getX() + (imageRight.getWidth() / 2) + 5, + portalPoint.getY() + ); + + Composite originalComposite = graphics.getComposite(); + Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); + graphics.setComposite(translucentComposite); + + OverlayUtil.renderImageLocation(graphics, portalLeft, imageLeft); + OverlayUtil.renderImageLocation(graphics, portalPoint, imageRight); + + graphics.setComposite(originalComposite); + } + } + + @Override + public Dimension render(Graphics2D graphics) + { + Game game = plugin.getGame(); + + if (game == null) + { + return null; + } + + for (Portal portal : game.getPortals()) + { + if (!portal.isDead()) + { + switch (portal.getColor()) + { + case BLUE: + { + renderPortalWeakness(graphics, portal, magicImage); + break; + } + case YELLOW: + { + renderDoublePortalWeakness(graphics, portal, stabImage, slashImage); + break; + } + case RED: + { + renderPortalWeakness(graphics, portal, crushImage); + break; + } + case PURPLE: + { + renderPortalWeakness(graphics, portal, rangedImage); + break; + } + } + } + } + + return null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/WidgetOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/WidgetOverlay.java index 4633128d6d..9fb06588fd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/WidgetOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/WidgetOverlay.java @@ -1,210 +1,210 @@ -/* - * Copyright (c) 2017, Kronos - * Copyright (c) 2017, Adam - * Copyright (c) 2019, Yani - * 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.pestcontrol; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; -import javax.inject.Inject; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -@Slf4j -public class WidgetOverlay extends Overlay -{ - private final Client client; - - private final PestControlPlugin plugin; - - @Inject - public WidgetOverlay(Client client, PestControlPlugin plugin) - { - this.plugin = plugin; - this.client = client; - - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - } - - public Integer getPortalHitpoints(PortalColor color) - { - if (plugin.getGame() == null) - { - return null; - } - - WidgetInfo healthWidgetInfo = null; - - switch (color) - { - case RED: - { - healthWidgetInfo = WidgetPortal.RED.getHitpoints(); - break; - } - case BLUE: - { - healthWidgetInfo = WidgetPortal.BLUE.getHitpoints(); - break; - } - case PURPLE: - { - healthWidgetInfo = WidgetPortal.PURPLE.getHitpoints(); - break; - } - case YELLOW: - { - healthWidgetInfo = WidgetPortal.YELLOW.getHitpoints(); - break; - } - } - - if (healthWidgetInfo == null) - { - return null; - } - - Widget healthWidget = client.getWidget(healthWidgetInfo); - - if (healthWidget == null) - { - return null; - } - - return Integer.parseInt(healthWidget.getText().trim()); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (plugin.getGame() == null) - { - return null; - } - - for (Portal portal : plugin.getGame().getNextPortals()) - { - renderWidgetOverlay(graphics, portal, "NEXT", Color.ORANGE); - } - - for (Portal portal : plugin.getGame().getActivePortals()) - { - renderWidgetOverlay(graphics, portal, "ATT", Color.RED); - } - - renderProgressWidget(graphics); - - return null; - } - - private void renderWidgetOverlay(Graphics2D graphics, Portal portal, String text, Color color) - { - Widget shield = client.getWidget(portal.getWidget().getShield()); - Widget icon = client.getWidget(portal.getWidget().getIcon()); - Widget hp = client.getWidget(portal.getWidget().getHitpoints()); - - Widget bar = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_BAR).getChild(0); - - Rectangle2D barBounds = bar.getBounds().getBounds2D(); - - // create one rectangle from two different widget bounds - Rectangle2D bounds = union(shield.getBounds().getBounds2D(), icon.getBounds().getBounds2D()); - bounds = union(bounds, hp.getBounds().getBounds2D()); - - graphics.setColor(color); - graphics.draw(new Rectangle2D.Double(bounds.getX(), bounds.getY() - 2, bounds.getWidth(), bounds.getHeight() - 3)); - - FontMetrics fm = graphics.getFontMetrics(); - Rectangle2D textBounds = fm.getStringBounds(text, graphics); - int x = (int) (bounds.getX() + (bounds.getWidth() / 2) - (textBounds.getWidth() / 2)); - int y = (int) (bounds.getY() + bounds.getHeight() + textBounds.getHeight() + barBounds.getHeight()); - - graphics.setColor(Color.BLACK); - graphics.drawString(text, x + 1, y + 5); - graphics.setColor(color); - graphics.drawString(text, x, y + 4); - } - - private void renderProgressWidget(Graphics2D graphics) - { - String text; - int percentage; - - Widget bar = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_BAR).getChild(0); - Rectangle2D bounds = bar.getBounds().getBounds2D(); - - Widget prgs = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_PROGRESS).getChild(0); - - // At 0% the inner widget changes and your progress will not increase anymore - if ((int) (prgs.getBounds().getX()) - bounds.getX() != 2) - { - percentage = 0; - text = "FAILED"; - } - else - { - percentage = (int) ((prgs.getBounds().getWidth() / bounds.getWidth()) * 100); - text = String.valueOf(percentage) + "%"; - } - - Color color = Color.GREEN; - if (percentage < 25) - { - color = Color.RED; - } - - FontMetrics fm = graphics.getFontMetrics(); - Rectangle2D textBounds = fm.getStringBounds(text, graphics); - int x = (int) (bounds.getX() - textBounds.getWidth() - 4); - int y = (int) (bounds.getY() + fm.getHeight() - 2); - - graphics.setColor(Color.BLACK); - graphics.drawString(text, x + 1, y + 1); - graphics.setColor(color); - graphics.drawString(text, x, y); - } - - private static Rectangle2D union(Rectangle2D src1, Rectangle2D src2) - { - double x1 = Math.min(src1.getMinX(), src2.getMinX()); - double y1 = Math.min(src1.getMinY(), src2.getMinY()); - double x2 = Math.max(src1.getMaxX(), src2.getMaxX()); - double y2 = Math.max(src1.getMaxY(), src2.getMaxY()); - - Rectangle2D result = new Rectangle2D.Double(); - result.setFrameFromDiagonal(x1, y1, x2, y2); - - return result; - } -} +/* + * Copyright (c) 2017, Kronos + * Copyright (c) 2017, Adam + * Copyright (c) 2019, Yani + * 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.pestcontrol; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +@Slf4j +public class WidgetOverlay extends Overlay +{ + private final Client client; + + private final PestControlPlugin plugin; + + @Inject + public WidgetOverlay(Client client, PestControlPlugin plugin) + { + this.plugin = plugin; + this.client = client; + + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + } + + public Integer getPortalHitpoints(PortalColor color) + { + if (plugin.getGame() == null) + { + return null; + } + + WidgetInfo healthWidgetInfo = null; + + switch (color) + { + case RED: + { + healthWidgetInfo = WidgetPortal.RED.getHitpoints(); + break; + } + case BLUE: + { + healthWidgetInfo = WidgetPortal.BLUE.getHitpoints(); + break; + } + case PURPLE: + { + healthWidgetInfo = WidgetPortal.PURPLE.getHitpoints(); + break; + } + case YELLOW: + { + healthWidgetInfo = WidgetPortal.YELLOW.getHitpoints(); + break; + } + } + + if (healthWidgetInfo == null) + { + return null; + } + + Widget healthWidget = client.getWidget(healthWidgetInfo); + + if (healthWidget == null) + { + return null; + } + + return Integer.parseInt(healthWidget.getText().trim()); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (plugin.getGame() == null) + { + return null; + } + + for (Portal portal : plugin.getGame().getNextPortals()) + { + renderWidgetOverlay(graphics, portal, "NEXT", Color.ORANGE); + } + + for (Portal portal : plugin.getGame().getActivePortals()) + { + renderWidgetOverlay(graphics, portal, "ATT", Color.RED); + } + + renderProgressWidget(graphics); + + return null; + } + + private void renderWidgetOverlay(Graphics2D graphics, Portal portal, String text, Color color) + { + Widget shield = client.getWidget(portal.getWidget().getShield()); + Widget icon = client.getWidget(portal.getWidget().getIcon()); + Widget hp = client.getWidget(portal.getWidget().getHitpoints()); + + Widget bar = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_BAR).getChild(0); + + Rectangle2D barBounds = bar.getBounds().getBounds2D(); + + // create one rectangle from two different widget bounds + Rectangle2D bounds = union(shield.getBounds().getBounds2D(), icon.getBounds().getBounds2D()); + bounds = union(bounds, hp.getBounds().getBounds2D()); + + graphics.setColor(color); + graphics.draw(new Rectangle2D.Double(bounds.getX(), bounds.getY() - 2, bounds.getWidth(), bounds.getHeight() - 3)); + + FontMetrics fm = graphics.getFontMetrics(); + Rectangle2D textBounds = fm.getStringBounds(text, graphics); + int x = (int) (bounds.getX() + (bounds.getWidth() / 2) - (textBounds.getWidth() / 2)); + int y = (int) (bounds.getY() + bounds.getHeight() + textBounds.getHeight() + barBounds.getHeight()); + + graphics.setColor(Color.BLACK); + graphics.drawString(text, x + 1, y + 5); + graphics.setColor(color); + graphics.drawString(text, x, y + 4); + } + + private void renderProgressWidget(Graphics2D graphics) + { + String text; + int percentage; + + Widget bar = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_BAR).getChild(0); + Rectangle2D bounds = bar.getBounds().getBounds2D(); + + Widget prgs = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_PROGRESS).getChild(0); + + // At 0% the inner widget changes and your progress will not increase anymore + if ((int) (prgs.getBounds().getX()) - bounds.getX() != 2) + { + percentage = 0; + text = "FAILED"; + } + else + { + percentage = (int) ((prgs.getBounds().getWidth() / bounds.getWidth()) * 100); + text = percentage + "%"; + } + + Color color = Color.GREEN; + if (percentage < 25) + { + color = Color.RED; + } + + FontMetrics fm = graphics.getFontMetrics(); + Rectangle2D textBounds = fm.getStringBounds(text, graphics); + int x = (int) (bounds.getX() - textBounds.getWidth() - 4); + int y = (int) (bounds.getY() + fm.getHeight() - 2); + + graphics.setColor(Color.BLACK); + graphics.drawString(text, x + 1, y + 1); + graphics.setColor(color); + graphics.drawString(text, x, y); + } + + private static Rectangle2D union(Rectangle2D src1, Rectangle2D src2) + { + double x1 = Math.min(src1.getMinX(), src2.getMinX()); + double y1 = Math.min(src1.getMinY(), src2.getMinY()); + double x2 = Math.max(src1.getMaxX(), src2.getMaxX()); + double y2 = Math.max(src1.getMaxY(), src2.getMaxY()); + + Rectangle2D result = new Rectangle2D.Double(); + result.setFrameFromDiagonal(x1, y1, x2, y2); + + return result; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java index 79bd8a7eb7..ffeccd7def 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java @@ -25,7 +25,6 @@ package net.runelite.client.plugins.playerindicators; import java.awt.Color; - import net.runelite.api.ClanMemberRank; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; @@ -201,11 +200,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - position = 15, - keyName = "highlightTargets", - name = "Highlight attackable players in wilderness on the minimap", - description = "Highlights players on the minimap that the current player can attack based on combat/wilderness levels", - group = "Target Indicator" + position = 15, + keyName = "highlightTargets", + name = "Highlight attackable players in wilderness on the minimap", + description = "Highlights players on the minimap that the current player can attack based on combat/wilderness levels", + group = "Target Indicator" ) default boolean highlightTargets() { @@ -213,11 +212,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - position = 16, - keyName = "highlightOverheadTargets", - name = "Highlights attackable players over their head", - description = "Highlights players over their head that the current player can attack based on combat/wilderness levels", - group = "Target Indicator" + position = 16, + keyName = "highlightOverheadTargets", + name = "Highlights attackable players over their head", + description = "Highlights players over their head that the current player can attack based on combat/wilderness levels", + group = "Target Indicator" ) default boolean highlightOverheadTargets() { @@ -225,11 +224,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - position = 17, - keyName = "targetColor", - name = "Target color", - description = "Color of attackable targets", - group = "Target Indicator" + position = 17, + keyName = "targetColor", + name = "Target color", + description = "Color of attackable targets", + group = "Target Indicator" ) default Color getTargetColor() { @@ -237,11 +236,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - position = 18, - keyName = "showCombat", - name = "Show Combat Levels", - description = "Show the combat level of attackable players next to their name.", - group = "Target Indicator" + position = 18, + keyName = "showCombat", + name = "Show Combat Levels", + description = "Show the combat level of attackable players next to their name.", + group = "Target Indicator" ) default boolean showCombatLevel() { @@ -249,11 +248,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - position = 19, - keyName = "playerSkull", - name = "Show Skull Information", - description = "Indicate of the player is skulled.", - group = "Target Indicator" + position = 19, + keyName = "playerSkull", + name = "Show Skull Information", + description = "Indicate of the player is skulled.", + group = "Target Indicator" ) default boolean playerSkull() { @@ -273,11 +272,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - position = 19, - keyName = "skulledTargetsOnly", - name = "Tag Skulls Only", - description = "Only indicate skulled targets (which are also attackable)", - group = "Target Indicator" + position = 19, + keyName = "skulledTargetsOnly", + name = "Tag Skulls Only", + description = "Only indicate skulled targets (which are also attackable)", + group = "Target Indicator" ) default boolean skulledTargetsOnly() { @@ -285,11 +284,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - position = 19, - keyName = "targetRisk", - name = "Indicate Target Risk", - description = "Indicates the risk (in K GP) of the target", - group = "Target Indicator" + position = 19, + keyName = "targetRisk", + name = "Indicate Target Risk", + description = "Indicates the risk (in K GP) of the target", + group = "Target Indicator" ) default boolean targetRisk() { @@ -308,11 +307,11 @@ public interface PlayerIndicatorsConfig extends Config }*/ @ConfigItem( - keyName = "useClanchatRanks", - name = "Use Ranks as Callers", - description = "Uses clanchat ranks as the list of callers", - group = "Callers", - position = 24 + keyName = "useClanchatRanks", + name = "Use Ranks as Callers", + description = "Uses clanchat ranks as the list of callers", + group = "Callers", + position = 24 ) default boolean useClanchatRanks() { @@ -320,11 +319,11 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - keyName = "callerRank", - name = "Minimum rank for Clan Caller", - description = "Chooses the minimum rank to use as clanchat callers.", - group = "Callers", - position = 25 + keyName = "callerRank", + name = "Minimum rank for Clan Caller", + description = "Chooses the minimum rank to use as clanchat callers.", + group = "Callers", + position = 25 ) default ClanMemberRank callerRank() { @@ -332,54 +331,58 @@ public interface PlayerIndicatorsConfig extends Config } @ConfigItem( - keyName = "callers", - name = "List of callers to highlight", - description = "Highlights callers, only highlights one at a time. Separate each entry with a comma and enter" + - " in the order you want them highlighted.", - group = "Callers" + keyName = "callers", + name = "List of callers to highlight", + description = "Highlights callers, only highlights one at a time. Separate each entry with a comma and enter" + + " in the order you want them highlighted.", + group = "Callers" ) default String callers() { return " "; } + @ConfigItem( - keyName = "highlightCallers", - name = "Highlight Callers", - description = "Highlights Callers Onscreen", - group = "Callers" + keyName = "highlightCallers", + name = "Highlight Callers", + description = "Highlights Callers Onscreen", + group = "Callers" ) default boolean highlightCallers() { return true; } + @ConfigItem( - position = 26, - keyName = "callerColor", - name = "Caller Color", - description = "Color of Indicated Callers", - group = "Callers" + position = 26, + keyName = "callerColor", + name = "Caller Color", + description = "Color of Indicated Callers", + group = "Callers" ) default Color callerColor() { return Color.WHITE; } + @ConfigItem( - position = 27, - keyName = "highlightPile", - name = "Highlight Pile", - description = "Highlights Pile Onscreen", - group = "Callers" + position = 27, + keyName = "highlightPile", + name = "Highlight Pile", + description = "Highlights Pile Onscreen", + group = "Callers" ) default boolean highlightPile() { return false; } + @ConfigItem( - position = 29, - keyName = "drawPileHull", - name = "Draws the hull of the pile.", - description = "Draws the hull of the pile for best visibility.", - group = "Callers" + position = 29, + keyName = "drawPileHull", + name = "Draws the hull of the pile.", + description = "Draws the hull of the pile for best visibility.", + group = "Callers" ) default boolean drawPileHull() { @@ -387,29 +390,30 @@ public interface PlayerIndicatorsConfig extends Config } @Range( - min = 1, - max = 10 + min = 1, + max = 10 ) @ConfigItem( - position = 30, - keyName = "pileColor", - name = "Pile Color", - description = "Color of Indicated Pile", - group = "Callers" + position = 30, + keyName = "pileColor", + name = "Pile Color", + description = "Color of Indicated Pile", + group = "Callers" ) default Color pileColor() { return Color.WHITE; } + @ConfigItem( - position = 27, - keyName = "unchargedGlory", - name = "Uncharged Glory Indication", - description = "Indicates if players have an uncharged glory" + position = 27, + keyName = "unchargedGlory", + name = "Uncharged Glory Indication", + description = "Indicates if players have an uncharged glory" ) default boolean unchargedGlory() { return false; } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java index 97ba662798..6f2aff1484 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java @@ -70,7 +70,7 @@ public class PlayerIndicatorsOverlay extends Overlay @Inject private PlayerIndicatorsOverlay(PlayerIndicatorsConfig config, PlayerIndicatorsService playerIndicatorsService, - ClanManager clanManager) + ClanManager clanManager) { this.config = config; this.playerIndicatorsService = playerIndicatorsService; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index 2c38b7fc3d..e1c62de125 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -36,7 +36,19 @@ import net.runelite.api.ClanMember; import net.runelite.api.ClanMemberRank; import static net.runelite.api.ClanMemberRank.UNRANKED; import net.runelite.api.Client; -import static net.runelite.api.MenuAction.*; +import static net.runelite.api.MenuAction.FOLLOW; +import static net.runelite.api.MenuAction.ITEM_USE_ON_PLAYER; +import static net.runelite.api.MenuAction.PLAYER_EIGTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FIFTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FIRST_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FOURTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SECOND_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SEVENTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SIXTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_THIRD_OPTION; +import static net.runelite.api.MenuAction.RUNELITE; +import static net.runelite.api.MenuAction.SPELL_CAST_ON_PLAYER; +import static net.runelite.api.MenuAction.TRADE; import net.runelite.api.MenuEntry; import net.runelite.api.Player; import net.runelite.api.events.ClanMemberJoined; @@ -54,39 +66,39 @@ import net.runelite.client.util.ColorUtil; import net.runelite.client.util.PvPUtil; @PluginDescriptor( - name = "Player Indicators", - description = "Highlight players on-screen and/or on the minimap", - tags = {"highlight", "minimap", "overlay", "players", "pklite"} + name = "Player Indicators", + description = "Highlight players on-screen and/or on the minimap", + tags = {"highlight", "minimap", "overlay", "players", "pklite"} ) public class PlayerIndicatorsPlugin extends Plugin { @Inject private OverlayManager overlayManager; - + @Inject private PlayerIndicatorsConfig config; - + @Inject private PlayerIndicatorsOverlay playerIndicatorsOverlay; - + @Inject private PlayerIndicatorsTileOverlay playerIndicatorsTileOverlay; - + @Inject private PlayerIndicatorsMinimapOverlay playerIndicatorsMinimapOverlay; - + @Inject private Client client; - + @Inject private ClanManager clanManager; - + @Provides PlayerIndicatorsConfig provideConfig(ConfigManager configManager) { return configManager.getConfig(PlayerIndicatorsConfig.class); } - + @Override protected void startUp() throws Exception { @@ -95,7 +107,7 @@ public class PlayerIndicatorsPlugin extends Plugin overlayManager.add(playerIndicatorsMinimapOverlay); getCallerList(); } - + @Override protected void shutDown() throws Exception { @@ -103,10 +115,10 @@ public class PlayerIndicatorsPlugin extends Plugin overlayManager.remove(playerIndicatorsTileOverlay); overlayManager.remove(playerIndicatorsMinimapOverlay); } - - private ArrayList callers = new ArrayList<>(); + + private ArrayList callers = new ArrayList<>(); private List pileList; - + @Subscribe public void onConfigChanged(ConfigChanged e) { @@ -115,7 +127,7 @@ public class PlayerIndicatorsPlugin extends Plugin getCallerList(); } } - + @Subscribe public void onGameTick(GameTick gameTick) { @@ -123,7 +135,7 @@ public class PlayerIndicatorsPlugin extends Plugin { for (Player p : client.getPlayers()) { - for (String name:callers) + for (String name : callers) { Actor pile; String finalName = name.toLowerCase().replace("_", " "); @@ -144,19 +156,19 @@ public class PlayerIndicatorsPlugin extends Plugin } } } - + @Subscribe public void onClanMemberJoined(ClanMemberJoined event) { getCallerList(); } - + @Subscribe public void onClanMemberLeft(ClanMemberLeft event) { getCallerList(); } - + private void getCallerList() { callers.clear(); @@ -183,12 +195,12 @@ public class PlayerIndicatorsPlugin extends Plugin } pileList = Arrays.asList(new String[callers.size()]); } - + boolean isCaller(Player player) { if (callers != null) { - for (String name:callers) + for (String name : callers) { String finalName = name.toLowerCase().replace("_", " "); if (player.getName().toLowerCase().replace("_", " ").equals(finalName)) @@ -200,7 +212,7 @@ public class PlayerIndicatorsPlugin extends Plugin return false; } - + boolean isPile(Player player) { if (Objects.nonNull(pileList) && pileList.size() > 0) @@ -209,48 +221,48 @@ public class PlayerIndicatorsPlugin extends Plugin } return false; } - + @Subscribe public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) { int type = menuEntryAdded.getType(); - + if (type >= 2000) { type -= 2000; } - + int identifier = menuEntryAdded.getIdentifier(); if (type == FOLLOW.getId() || type == TRADE.getId() - || type == SPELL_CAST_ON_PLAYER.getId() || type == ITEM_USE_ON_PLAYER.getId() - || type == PLAYER_FIRST_OPTION.getId() - || type == PLAYER_SECOND_OPTION.getId() - || type == PLAYER_THIRD_OPTION.getId() - || type == PLAYER_FOURTH_OPTION.getId() - || type == PLAYER_FIFTH_OPTION.getId() - || type == PLAYER_SIXTH_OPTION.getId() - || type == PLAYER_SEVENTH_OPTION.getId() - || type == PLAYER_EIGTH_OPTION.getId() - || type == RUNELITE.getId()) + || type == SPELL_CAST_ON_PLAYER.getId() || type == ITEM_USE_ON_PLAYER.getId() + || type == PLAYER_FIRST_OPTION.getId() + || type == PLAYER_SECOND_OPTION.getId() + || type == PLAYER_THIRD_OPTION.getId() + || type == PLAYER_FOURTH_OPTION.getId() + || type == PLAYER_FIFTH_OPTION.getId() + || type == PLAYER_SIXTH_OPTION.getId() + || type == PLAYER_SEVENTH_OPTION.getId() + || type == PLAYER_EIGTH_OPTION.getId() + || type == RUNELITE.getId()) { final Player localPlayer = client.getLocalPlayer(); Player[] players = client.getCachedPlayers(); Player player = null; - + if (identifier >= 0 && identifier < players.length) { player = players[identifier]; } - + if (player == null) { return; } - + int image = -1; int image2 = -1; Color color = null; - + if (config.colorPlayerMenu() && client.isFriended(player.getName(), false)) { color = config.getFriendColor(); @@ -258,7 +270,7 @@ public class PlayerIndicatorsPlugin extends Plugin else if (config.colorPlayerMenu() && player.isClanMember()) { color = config.getClanMemberColor(); - + ClanMemberRank rank = clanManager.getRank(player.getName()); if (rank != UNRANKED) { @@ -266,21 +278,21 @@ public class PlayerIndicatorsPlugin extends Plugin } } else if (config.colorPlayerMenu() && player.getTeam() > 0 && localPlayer.getTeam() == player.getTeam()) - { - color = config.getTeamMemberColor(); - } - else if (!player.isClanMember() && !player.isFriend() && !PvPUtil.isAttackable(client, player)) - { - color = config.getNonClanMemberColor(); - } - else if (config.colorPlayerMenu() && !player.isClanMember() && client.isFriended(player.getName(), false) && PvPUtil.isAttackable(client, player)) - { - color = config.getTargetColor(); - } - else if (config.colorPlayerMenu() && PvPUtil.isAttackable(client, player) && !player.isClanMember() && !player.isFriend()) - { - color = config.getTargetColor(); - } + { + color = config.getTeamMemberColor(); + } + else if (!player.isClanMember() && !player.isFriend() && !PvPUtil.isAttackable(client, player)) + { + color = config.getNonClanMemberColor(); + } + else if (config.colorPlayerMenu() && !player.isClanMember() && client.isFriended(player.getName(), false) && PvPUtil.isAttackable(client, player)) + { + color = config.getTargetColor(); + } + else if (config.colorPlayerMenu() && PvPUtil.isAttackable(client, player) && !player.isClanMember() && !player.isFriend()) + { + color = config.getTargetColor(); + } /* if (config.rightClickOverhead() && !player.isClanMember() && player.getOverheadIcon() != null) { if (player.getOverheadIcon().equals(HeadIcon.MAGIC)) @@ -324,8 +336,8 @@ public class PlayerIndicatorsPlugin extends Plugin { MenuEntry[] menuEntries = client.getMenuEntries(); MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; - - + + if (color != null && config.colorPlayerMenu()) { // strip out existing " + lastEntry.getTarget()); } - + client.setMenuEntries(menuEntries); } } } - + public enum minimapSkullLocations { BEFORE_NAME, diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java index 98602e7a4c..bf69efda5f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsTileOverlay.java @@ -25,7 +25,11 @@ package net.runelite.client.plugins.playerindicators; -import java.awt.*; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; import javax.inject.Inject; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; @@ -41,7 +45,7 @@ public class PlayerIndicatorsTileOverlay extends Overlay @Inject private PlayerIndicatorsTileOverlay(PlayerIndicatorsConfig config, - PlayerIndicatorsService playerIndicatorsService, PlayerIndicatorsPlugin plugin) + PlayerIndicatorsService playerIndicatorsService, PlayerIndicatorsPlugin plugin) { this.config = config; this.playerIndicatorsService = playerIndicatorsService; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoConfig.java index af6767f1b0..19c46301bf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoConfig.java @@ -1,123 +1,122 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.playerinfo; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -import java.awt.*; - -@ConfigGroup("playerinfo") -public interface PlayerInfoConfig extends Config -{ - @ConfigItem( - keyName = "enableHealth", - name = "Enable Health Display", - description = "Configures whether or not to display health information", - position = 1 - ) - default boolean enableHealth() - { - return true; - } - - @ConfigItem( - keyName = "enablePrayer", - name = "Enable Prayer Display", - description = "Configures whether or not to display prayer information", - position = 2 - ) - default boolean enablePrayer() - { - return true; - } - - @ConfigItem( - keyName = "enableEnergy", - name = "Enable Run Energy Display", - description = "Configures whether or not to display run energy information", - position = 3 - ) - default boolean enableEnergy() - { - return true; - } - - @ConfigItem( - keyName = "enableSpec", - name = "Enable Special Attack Display", - description = "Configures whether or not to display special attack information", - position = 4 - ) - default boolean enableSpec() - { - return true; - } - - @ConfigItem( - keyName = "enableWorld", - name = "Enable World Display", - description = "Configures whether or not to display world information", - position = 4 - ) - default boolean enableWorld() - { - return true; - } - - @ConfigItem( - keyName = "colorHigh", - name = "Color High", - description = "The color displayed for high values.", - position = 5 - ) - default Color colorHigh() - { - return Color.GREEN; - } - - @ConfigItem( - keyName = "colorMed", - name = "Color Medium", - description = "The color displayed for medium values.", - position = 6 - ) - default Color colorMed() - { - return Color.YELLOW; - } - - @ConfigItem( - keyName = "colorLow", - name = "Color Low", - description = "The color displayed for low values.", - position = 7 - ) - default Color colorLow() - { - return Color.RED; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.playerinfo; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("playerinfo") +public interface PlayerInfoConfig extends Config +{ + @ConfigItem( + keyName = "enableHealth", + name = "Enable Health Display", + description = "Configures whether or not to display health information", + position = 1 + ) + default boolean enableHealth() + { + return true; + } + + @ConfigItem( + keyName = "enablePrayer", + name = "Enable Prayer Display", + description = "Configures whether or not to display prayer information", + position = 2 + ) + default boolean enablePrayer() + { + return true; + } + + @ConfigItem( + keyName = "enableEnergy", + name = "Enable Run Energy Display", + description = "Configures whether or not to display run energy information", + position = 3 + ) + default boolean enableEnergy() + { + return true; + } + + @ConfigItem( + keyName = "enableSpec", + name = "Enable Special Attack Display", + description = "Configures whether or not to display special attack information", + position = 4 + ) + default boolean enableSpec() + { + return true; + } + + @ConfigItem( + keyName = "enableWorld", + name = "Enable World Display", + description = "Configures whether or not to display world information", + position = 4 + ) + default boolean enableWorld() + { + return true; + } + + @ConfigItem( + keyName = "colorHigh", + name = "Color High", + description = "The color displayed for high values.", + position = 5 + ) + default Color colorHigh() + { + return Color.GREEN; + } + + @ConfigItem( + keyName = "colorMed", + name = "Color Medium", + description = "The color displayed for medium values.", + position = 6 + ) + default Color colorMed() + { + return Color.YELLOW; + } + + @ConfigItem( + keyName = "colorLow", + name = "Color Low", + description = "The color displayed for low values.", + position = 7 + ) + default Color colorLow() + { + return Color.RED; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java index cadf30033b..b76a0b9b52 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java @@ -1,140 +1,140 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.playerinfo; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.Skill; -import net.runelite.api.VarPlayer; -import net.runelite.client.ui.overlay.infobox.InfoBox; -import net.runelite.client.util.ColorUtil; - -import java.awt.*; - -public class PlayerInfoCustomIndicator extends InfoBox -{ - @AllArgsConstructor - @Getter - enum IndicatorType - { - HEALTH("Current Hitpoints"), - PRAYER("Current Prayer Points"), - ENERGY("Current Run Energy"), - SPECIAL("Current Special Attack"), - WORLD("Current World"); - - private final String description; - } - - private final PlayerInfoConfig config; - private final Client client; - private final IndicatorType type; - - PlayerInfoCustomIndicator(Image image, PlayerInfoPlugin plugin, PlayerInfoConfig config, Client client, IndicatorType type) - { - super(image, plugin); - this.config = config; - this.client = client; - this.type = type; - - setTooltip(type.getDescription()); - } - - @Override - public String getText() - { - switch (type) - { - case HEALTH: - return String.valueOf(client.getBoostedSkillLevel(Skill.HITPOINTS)); - case PRAYER: - return String.valueOf(client.getBoostedSkillLevel(Skill.PRAYER)); - case ENERGY: - return String.valueOf(client.getEnergy()); - case SPECIAL: - return String.valueOf(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT) / 10); - case WORLD: - return String.valueOf(client.getWorld()); - } - - return null; - } - - @Override - public Color getTextColor() - { - float currLvl = 0; - switch (type) - { - case HEALTH: - currLvl = client.getBoostedSkillLevel(Skill.HITPOINTS) / (float) client.getRealSkillLevel(Skill.HITPOINTS); - break; - case PRAYER: - currLvl = client.getBoostedSkillLevel(Skill.PRAYER) / (float) client.getRealSkillLevel(Skill.PRAYER); - break; - case ENERGY: - currLvl = client.getEnergy() / 100.0F; - break; - case SPECIAL: - currLvl = client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT) / 1000.0F; - case WORLD: - currLvl = 1000; // hacky - } - - if (currLvl > 1.0) - { - return config.colorHigh(); - } - else if (currLvl > 0.5) - { - return ColorUtil.colorLerp(config.colorMed(), config.colorHigh(), (currLvl * 2) - 1.0F); - } - else - { - return ColorUtil.colorLerp(config.colorLow(), config.colorMed(), (currLvl * 2)); - } - } - - @Override - public boolean render() - { - switch (type) - { - case HEALTH: - return config.enableHealth(); - case PRAYER: - return config.enablePrayer(); - case ENERGY: - return config.enableEnergy(); - case SPECIAL: - return config.enableSpec(); - case WORLD: - return config.enableWorld(); - } - - return false; - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.playerinfo; + +import java.awt.Color; +import java.awt.Image; +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Skill; +import net.runelite.api.VarPlayer; +import net.runelite.client.ui.overlay.infobox.InfoBox; +import net.runelite.client.util.ColorUtil; + +public class PlayerInfoCustomIndicator extends InfoBox +{ + @AllArgsConstructor + @Getter + enum IndicatorType + { + HEALTH("Current Hitpoints"), + PRAYER("Current Prayer Points"), + ENERGY("Current Run Energy"), + SPECIAL("Current Special Attack"), + WORLD("Current World"); + + private final String description; + } + + private final PlayerInfoConfig config; + private final Client client; + private final IndicatorType type; + + PlayerInfoCustomIndicator(Image image, PlayerInfoPlugin plugin, PlayerInfoConfig config, Client client, IndicatorType type) + { + super(image, plugin); + this.config = config; + this.client = client; + this.type = type; + + setTooltip(type.getDescription()); + } + + @Override + public String getText() + { + switch (type) + { + case HEALTH: + return String.valueOf(client.getBoostedSkillLevel(Skill.HITPOINTS)); + case PRAYER: + return String.valueOf(client.getBoostedSkillLevel(Skill.PRAYER)); + case ENERGY: + return String.valueOf(client.getEnergy()); + case SPECIAL: + return String.valueOf(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT) / 10); + case WORLD: + return String.valueOf(client.getWorld()); + } + + return null; + } + + @Override + public Color getTextColor() + { + float currLvl = 0; + switch (type) + { + case HEALTH: + currLvl = client.getBoostedSkillLevel(Skill.HITPOINTS) / (float) client.getRealSkillLevel(Skill.HITPOINTS); + break; + case PRAYER: + currLvl = client.getBoostedSkillLevel(Skill.PRAYER) / (float) client.getRealSkillLevel(Skill.PRAYER); + break; + case ENERGY: + currLvl = client.getEnergy() / 100.0F; + break; + case SPECIAL: + currLvl = client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT) / 1000.0F; + case WORLD: + currLvl = 1000; // hacky + } + + if (currLvl > 1.0) + { + return config.colorHigh(); + } + else if (currLvl > 0.5) + { + return ColorUtil.colorLerp(config.colorMed(), config.colorHigh(), (currLvl * 2) - 1.0F); + } + else + { + return ColorUtil.colorLerp(config.colorLow(), config.colorMed(), (currLvl * 2)); + } + } + + @Override + public boolean render() + { + switch (type) + { + case HEALTH: + return config.enableHealth(); + case PRAYER: + return config.enablePrayer(); + case ENERGY: + return config.enableEnergy(); + case SPECIAL: + return config.enableSpec(); + case WORLD: + return config.enableWorld(); + } + + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoPlugin.java index 6ab9e47f82..4cef00950f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoPlugin.java @@ -1,110 +1,109 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.playerinfo; - -import com.google.inject.Provides; -import net.runelite.api.*; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import java.awt.image.BufferedImage; - -import static net.runelite.client.plugins.playerinfo.PlayerInfoCustomIndicator.*; - -@PluginDescriptor( - name = "Player Information", - description = "An alternative to the Minimap Orbs", - tags = {"combat", "overlay"}, - type = PluginType.UTILITY, - enabledByDefault = false -) -@Singleton -public class PlayerInfoPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private InfoBoxManager infoBoxManager; - - @Inject - private PlayerInfoConfig config; - - @Inject - private SpriteManager spriteManager; - - @Inject - private SkillIconManager skillIconManager; - - @Provides - PlayerInfoConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(PlayerInfoConfig.class); - } - - @Override - protected void startUp() throws Exception - { - clientThread.invoke(() -> - { - if (client.getGameState().ordinal() < GameState.LOGIN_SCREEN.ordinal()) - { - return false; - } - - BufferedImage healthImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_HITPOINTS_ICON, 0); - BufferedImage prayerImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_PRAYER_ICON, 0); - BufferedImage energyImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_RUN_ICON, 0); - BufferedImage combatImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_SPECIAL_ICON, 0); - BufferedImage worldImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_WORLD_MAP_PLANET, 0); - - infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(healthImg, this, config, client, IndicatorType.HEALTH)); - infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(prayerImg, this, config, client, IndicatorType.PRAYER)); - infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(energyImg, this, config, client, IndicatorType.ENERGY)); - infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(combatImg, this, config, client, IndicatorType.SPECIAL)); - infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(worldImg, this, config, client, IndicatorType.WORLD)); - - return true; - }); - } - - @Override - protected void shutDown() throws Exception - { - infoBoxManager.removeIf(i -> i instanceof PlayerInfoCustomIndicator); - } -} +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.playerinfo; + +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import javax.inject.Singleton; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.SpriteID; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.game.SkillIconManager; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import static net.runelite.client.plugins.playerinfo.PlayerInfoCustomIndicator.IndicatorType; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; + +@PluginDescriptor( + name = "Player Information", + description = "An alternative to the Minimap Orbs", + tags = {"combat", "overlay"}, + type = PluginType.UTILITY, + enabledByDefault = false +) +@Singleton +public class PlayerInfoPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private InfoBoxManager infoBoxManager; + + @Inject + private PlayerInfoConfig config; + + @Inject + private SpriteManager spriteManager; + + @Inject + private SkillIconManager skillIconManager; + + @Provides + PlayerInfoConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(PlayerInfoConfig.class); + } + + @Override + protected void startUp() throws Exception + { + clientThread.invoke(() -> + { + if (client.getGameState().ordinal() < GameState.LOGIN_SCREEN.ordinal()) + { + return false; + } + + BufferedImage healthImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_HITPOINTS_ICON, 0); + BufferedImage prayerImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_PRAYER_ICON, 0); + BufferedImage energyImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_RUN_ICON, 0); + BufferedImage combatImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_SPECIAL_ICON, 0); + BufferedImage worldImg = spriteManager.getSprite(SpriteID.MINIMAP_ORB_WORLD_MAP_PLANET, 0); + + infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(healthImg, this, config, client, IndicatorType.HEALTH)); + infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(prayerImg, this, config, client, IndicatorType.PRAYER)); + infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(energyImg, this, config, client, IndicatorType.ENERGY)); + infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(combatImg, this, config, client, IndicatorType.SPECIAL)); + infoBoxManager.addInfoBox(new PlayerInfoCustomIndicator(worldImg, this, config, client, IndicatorType.WORLD)); + + return true; + }); + } + + @Override + protected void shutDown() throws Exception + { + infoBoxManager.removeIf(i -> i instanceof PlayerInfoCustomIndicator); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java index 656cf85716..db671698fa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohIcons.java @@ -39,7 +39,164 @@ import static net.runelite.api.NullObjectID.NULL_13632; import static net.runelite.api.NullObjectID.NULL_13634; import static net.runelite.api.NullObjectID.NULL_29228; import static net.runelite.api.NullObjectID.NULL_29229; -import static net.runelite.api.ObjectID.*; +import static net.runelite.api.ObjectID.ALTAR_13179; +import static net.runelite.api.ObjectID.ALTAR_13180; +import static net.runelite.api.ObjectID.ALTAR_13181; +import static net.runelite.api.ObjectID.ALTAR_13182; +import static net.runelite.api.ObjectID.ALTAR_13183; +import static net.runelite.api.ObjectID.ALTAR_13184; +import static net.runelite.api.ObjectID.ALTAR_13185; +import static net.runelite.api.ObjectID.ALTAR_13186; +import static net.runelite.api.ObjectID.ALTAR_13187; +import static net.runelite.api.ObjectID.ALTAR_13188; +import static net.runelite.api.ObjectID.ALTAR_13189; +import static net.runelite.api.ObjectID.ALTAR_13190; +import static net.runelite.api.ObjectID.ALTAR_13191; +import static net.runelite.api.ObjectID.ALTAR_13192; +import static net.runelite.api.ObjectID.ALTAR_13193; +import static net.runelite.api.ObjectID.ALTAR_13194; +import static net.runelite.api.ObjectID.ALTAR_13196; +import static net.runelite.api.ObjectID.ALTAR_13197; +import static net.runelite.api.ObjectID.ALTAR_13198; +import static net.runelite.api.ObjectID.ALTAR_13199; +import static net.runelite.api.ObjectID.ALTAR_OF_THE_OCCULT; +import static net.runelite.api.ObjectID.AMULET_OF_GLORY; +import static net.runelite.api.ObjectID.ANCIENT_ALTAR; +import static net.runelite.api.ObjectID.ANNAKARL_PORTAL; +import static net.runelite.api.ObjectID.ANNAKARL_PORTAL_29349; +import static net.runelite.api.ObjectID.ANNAKARL_PORTAL_29357; +import static net.runelite.api.ObjectID.ARDOUGNE_PORTAL; +import static net.runelite.api.ObjectID.ARDOUGNE_PORTAL_13626; +import static net.runelite.api.ObjectID.ARDOUGNE_PORTAL_13633; +import static net.runelite.api.ObjectID.ARMOUR_REPAIR_STAND; +import static net.runelite.api.ObjectID.BASIC_JEWELLERY_BOX; +import static net.runelite.api.ObjectID.CARRALLANGAR_PORTAL; +import static net.runelite.api.ObjectID.CARRALLANGAR_PORTAL_33437; +import static net.runelite.api.ObjectID.CARRALLANGAR_PORTAL_33440; +import static net.runelite.api.ObjectID.CATHERBY_PORTAL; +import static net.runelite.api.ObjectID.CATHERBY_PORTAL_33435; +import static net.runelite.api.ObjectID.CATHERBY_PORTAL_33438; +import static net.runelite.api.ObjectID.DARK_ALTAR; +import static net.runelite.api.ObjectID.DIGSITE_PENDANT; +import static net.runelite.api.ObjectID.DIGSITE_PENDANT_33417; +import static net.runelite.api.ObjectID.DIGSITE_PENDANT_33418; +import static net.runelite.api.ObjectID.DIGSITE_PENDANT_33420; +import static net.runelite.api.ObjectID.FALADOR_PORTAL; +import static net.runelite.api.ObjectID.FALADOR_PORTAL_13624; +import static net.runelite.api.ObjectID.FALADOR_PORTAL_13631; +import static net.runelite.api.ObjectID.FANCY_JEWELLERY_BOX; +import static net.runelite.api.ObjectID.FANCY_REJUVENATION_POOL; +import static net.runelite.api.ObjectID.FISHING_GUILD_PORTAL; +import static net.runelite.api.ObjectID.FISHING_GUILD_PORTAL_29351; +import static net.runelite.api.ObjectID.FISHING_GUILD_PORTAL_29359; +import static net.runelite.api.ObjectID.GHORROCK_PORTAL; +import static net.runelite.api.ObjectID.GHORROCK_PORTAL_33436; +import static net.runelite.api.ObjectID.GHORROCK_PORTAL_33439; +import static net.runelite.api.ObjectID.KHARYRLL_PORTAL; +import static net.runelite.api.ObjectID.KHARYRLL_PORTAL_29346; +import static net.runelite.api.ObjectID.KHARYRLL_PORTAL_29354; +import static net.runelite.api.ObjectID.KOUREND_PORTAL; +import static net.runelite.api.ObjectID.KOUREND_PORTAL_29353; +import static net.runelite.api.ObjectID.KOUREND_PORTAL_29361; +import static net.runelite.api.ObjectID.LUMBRIDGE_PORTAL; +import static net.runelite.api.ObjectID.LUMBRIDGE_PORTAL_13623; +import static net.runelite.api.ObjectID.LUMBRIDGE_PORTAL_13630; +import static net.runelite.api.ObjectID.LUNAR_ALTAR; +import static net.runelite.api.ObjectID.LUNAR_ISLE_PORTAL; +import static net.runelite.api.ObjectID.LUNAR_ISLE_PORTAL_29347; +import static net.runelite.api.ObjectID.LUNAR_ISLE_PORTAL_29355; +import static net.runelite.api.ObjectID.MARIM_PORTAL; +import static net.runelite.api.ObjectID.MARIM_PORTAL_29352; +import static net.runelite.api.ObjectID.MARIM_PORTAL_29360; +import static net.runelite.api.ObjectID.OBELISK_31554; +import static net.runelite.api.ObjectID.ORNATE_JEWELLERY_BOX; +import static net.runelite.api.ObjectID.ORNATE_REJUVENATION_POOL; +import static net.runelite.api.ObjectID.POOL_OF_REJUVENATION; +import static net.runelite.api.ObjectID.POOL_OF_RESTORATION; +import static net.runelite.api.ObjectID.POOL_OF_REVITALISATION; +import static net.runelite.api.ObjectID.PORTAL_4525; +import static net.runelite.api.ObjectID.PORTAL_NEXUS; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33355; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33356; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33357; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33358; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33359; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33360; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33361; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33362; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33363; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33364; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33365; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33366; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33367; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33368; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33369; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33370; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33371; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33372; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33373; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33374; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33375; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33376; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33377; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33378; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33379; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33380; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33381; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33382; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33383; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33384; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33385; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33386; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33387; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33388; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33389; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33390; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33391; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33392; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33393; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33394; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33395; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33396; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33397; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33398; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33399; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33400; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33401; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33402; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33403; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33404; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33405; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33406; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33407; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33408; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33409; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33410; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33423; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33424; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33425; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33426; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33427; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33428; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33429; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33430; +import static net.runelite.api.ObjectID.PORTAL_NEXUS_33431; +import static net.runelite.api.ObjectID.SENNTISTEN_PORTAL; +import static net.runelite.api.ObjectID.SENNTISTEN_PORTAL_29348; +import static net.runelite.api.ObjectID.SENNTISTEN_PORTAL_29356; +import static net.runelite.api.ObjectID.SPIRIT_TREE_29227; +import static net.runelite.api.ObjectID.TROLL_STRONGHOLD_PORTAL; +import static net.runelite.api.ObjectID.TROLL_STRONGHOLD_PORTAL_33180; +import static net.runelite.api.ObjectID.TROLL_STRONGHOLD_PORTAL_33181; +import static net.runelite.api.ObjectID.WATERBIRTH_ISLAND_PORTAL; +import static net.runelite.api.ObjectID.WATERBIRTH_ISLAND_PORTAL_29350; +import static net.runelite.api.ObjectID.WATERBIRTH_ISLAND_PORTAL_29358; +import static net.runelite.api.ObjectID.XERICS_TALISMAN; +import static net.runelite.api.ObjectID.XERICS_TALISMAN_33412; +import static net.runelite.api.ObjectID.XERICS_TALISMAN_33413; +import static net.runelite.api.ObjectID.XERICS_TALISMAN_33414; +import static net.runelite.api.ObjectID.XERICS_TALISMAN_33415; +import static net.runelite.api.ObjectID.XERICS_TALISMAN_33419; import net.runelite.client.util.ImageUtil; public enum PohIcons @@ -85,7 +242,7 @@ public enum PohIcons PORTAL_NEXUS_33403, PORTAL_NEXUS_33404, PORTAL_NEXUS_33405, PORTAL_NEXUS_33406, PORTAL_NEXUS_33407, PORTAL_NEXUS_33408, PORTAL_NEXUS_33409, PORTAL_NEXUS_33410, PORTAL_NEXUS_33423, PORTAL_NEXUS_33424, PORTAL_NEXUS_33425, PORTAL_NEXUS_33426, PORTAL_NEXUS_33427, PORTAL_NEXUS_33428, PORTAL_NEXUS_33429, PORTAL_NEXUS_33430, PORTAL_NEXUS_33431 - ), + ), XERICSTALISMAN("xericstalisman", XERICS_TALISMAN, XERICS_TALISMAN_33412, XERICS_TALISMAN_33413, XERICS_TALISMAN_33414, XERICS_TALISMAN_33415, XERICS_TALISMAN_33419 ), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohOverlay.java index 368e763f8f..f0c8a85289 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohOverlay.java @@ -1,148 +1,148 @@ -/* - * Copyright (c) 2018, Seth - * 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.poh; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -public class PohOverlay extends Overlay -{ - private static final PohIcons[] PORTALS = new PohIcons[] - { - PohIcons.LUMBRIDGE, PohIcons.FALADOR, PohIcons.VARROCK, PohIcons.CAMELOT, PohIcons.ARDOUGNE, - PohIcons.YANILLE, PohIcons.LUNARISLE, PohIcons.WATERBIRTH, PohIcons.FISHINGGUILD, - PohIcons.SENNTISTEN, PohIcons.KHARYLL, PohIcons.ANNAKARL, PohIcons.KOUREND, PohIcons.MARIM, PohIcons.TROLLSTRONGHOLD, PohIcons.CARRALLANGAR, PohIcons.CATHERBY, PohIcons.GHORROCK - - }; - - private static final int MAX_DISTANCE = 2350; - - @Getter - private final List iconList = new ArrayList<>(); - - private final Client client; - private final PohConfig config; - private final PohPlugin plugin; - - @Inject - public PohOverlay(Client client, PohConfig config, PohPlugin plugin) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_WIDGETS); - this.client = client; - this.config = config; - this.plugin = plugin; - } - - @Override - public Dimension render(Graphics2D graphics) - { - LocalPoint localLocation = client.getLocalPlayer().getLocalLocation(); - plugin.getPohObjects().forEach((object, tile) -> - { - LocalPoint location = object.getLocalLocation(); - if (tile.getPlane() == client.getPlane() && localLocation.distanceTo(location) <= MAX_DISTANCE) - { - PohIcons icon = PohIcons.getIcon(object.getId()); - - if (icon != null && iconList.contains(icon)) - { - net.runelite.api.Point minimapLoc = Perspective.getMiniMapImageLocation(client, object.getLocalLocation(), icon.getImage()); - - if (minimapLoc != null) - { - graphics.drawImage(icon.getImage(), minimapLoc.getX(), minimapLoc.getY(), null); - } - } - } - }); - - return null; - } - - public void updateConfig() - { - iconList.clear(); - if (config.showPortals()) - { - Collections.addAll(iconList, PORTALS); - } - if (config.showAltar()) - { - iconList.add(PohIcons.ALTAR); - } - if (config.showGlory()) - { - iconList.add(PohIcons.GLORY); - } - if (config.showRepairStand()) - { - iconList.add(PohIcons.REPAIR); - } - if (config.showPools()) - { - iconList.add(PohIcons.POOLS); - } - if (config.showExitPortal()) - { - iconList.add(PohIcons.EXITPORTAL); - } - if (config.showSpellbook()) - { - iconList.add(PohIcons.SPELLBOOKALTAR); - } - if (config.showJewelleryBox()) - { - iconList.add(PohIcons.JEWELLERYBOX); - } - if (config.showMagicTravel()) - { - iconList.add(PohIcons.MAGICTRAVEL); - } - if (config.showPortalNexus()) - { - iconList.add(PohIcons.PORTALNEXUS); - } - if (config.showDigsitePendant()) - { - iconList.add(PohIcons.DIGSITEPENDANT); - } - if (config.showXericsTalisman()) - { - iconList.add(PohIcons.XERICSTALISMAN); - } - } -} +/* + * Copyright (c) 2018, Seth + * 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.poh; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +public class PohOverlay extends Overlay +{ + private static final PohIcons[] PORTALS = new PohIcons[] + { + PohIcons.LUMBRIDGE, PohIcons.FALADOR, PohIcons.VARROCK, PohIcons.CAMELOT, PohIcons.ARDOUGNE, + PohIcons.YANILLE, PohIcons.LUNARISLE, PohIcons.WATERBIRTH, PohIcons.FISHINGGUILD, + PohIcons.SENNTISTEN, PohIcons.KHARYLL, PohIcons.ANNAKARL, PohIcons.KOUREND, PohIcons.MARIM, PohIcons.TROLLSTRONGHOLD, PohIcons.CARRALLANGAR, PohIcons.CATHERBY, PohIcons.GHORROCK + + }; + + private static final int MAX_DISTANCE = 2350; + + @Getter + private final List iconList = new ArrayList<>(); + + private final Client client; + private final PohConfig config; + private final PohPlugin plugin; + + @Inject + public PohOverlay(Client client, PohConfig config, PohPlugin plugin) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.client = client; + this.config = config; + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D graphics) + { + LocalPoint localLocation = client.getLocalPlayer().getLocalLocation(); + plugin.getPohObjects().forEach((object, tile) -> + { + LocalPoint location = object.getLocalLocation(); + if (tile.getPlane() == client.getPlane() && localLocation.distanceTo(location) <= MAX_DISTANCE) + { + PohIcons icon = PohIcons.getIcon(object.getId()); + + if (icon != null && iconList.contains(icon)) + { + net.runelite.api.Point minimapLoc = Perspective.getMiniMapImageLocation(client, object.getLocalLocation(), icon.getImage()); + + if (minimapLoc != null) + { + graphics.drawImage(icon.getImage(), minimapLoc.getX(), minimapLoc.getY(), null); + } + } + } + }); + + return null; + } + + public void updateConfig() + { + iconList.clear(); + if (config.showPortals()) + { + Collections.addAll(iconList, PORTALS); + } + if (config.showAltar()) + { + iconList.add(PohIcons.ALTAR); + } + if (config.showGlory()) + { + iconList.add(PohIcons.GLORY); + } + if (config.showRepairStand()) + { + iconList.add(PohIcons.REPAIR); + } + if (config.showPools()) + { + iconList.add(PohIcons.POOLS); + } + if (config.showExitPortal()) + { + iconList.add(PohIcons.EXITPORTAL); + } + if (config.showSpellbook()) + { + iconList.add(PohIcons.SPELLBOOKALTAR); + } + if (config.showJewelleryBox()) + { + iconList.add(PohIcons.JEWELLERYBOX); + } + if (config.showMagicTravel()) + { + iconList.add(PohIcons.MAGICTRAVEL); + } + if (config.showPortalNexus()) + { + iconList.add(PohIcons.PORTALNEXUS); + } + if (config.showDigsitePendant()) + { + iconList.add(PohIcons.DIGSITEPENDANT); + } + if (config.showXericsTalisman()) + { + iconList.add(PohIcons.XERICSTALISMAN); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java index 04df91d05c..be70c9689d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java @@ -80,7 +80,7 @@ public class PohPlugin extends Plugin private final Map pohObjects = new HashMap<>(); @Getter(AccessLevel.PACKAGE) - private final Map incenseBurners = new HashMap<>(); + private final Map incenseBurners = new HashMap<>(); @Inject private OverlayManager overlayManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonInfobox.java b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonInfobox.java index f8d7233ab1..2be70c1e13 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonInfobox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonInfobox.java @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2018 Hydrox6 - * 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.poison; - -import java.awt.Color; -import java.time.Duration; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.infobox.Timer; - -class PoisonInfobox extends Timer -{ - private final PoisonPlugin plugin; - - PoisonInfobox(int duration, BufferedImage image, PoisonPlugin plugin) - { - super(duration, ChronoUnit.MILLIS, image, plugin); - this.plugin = plugin; - } - - @Override - public String getTooltip() - { - return plugin.createTooltip(); - } - - @Override - public Color getTextColor() - { - return Color.RED.brighter(); - } - - @Override - public String getText() - { - Duration timeLeft = Duration.between(Instant.now(), getEndTime()); - - if (!timeLeft.isNegative()) - { - return super.getText(); - } - return " "; - } - - @Override - public boolean render() - { - return true; - } - - @Override - public boolean cull() - { - return false; - } -} - +/* + * Copyright (c) 2018 Hydrox6 + * 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.poison; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import net.runelite.client.ui.overlay.infobox.Timer; + +class PoisonInfobox extends Timer +{ + private final PoisonPlugin plugin; + + PoisonInfobox(int duration, BufferedImage image, PoisonPlugin plugin) + { + super(duration, ChronoUnit.MILLIS, image, plugin); + this.plugin = plugin; + } + + @Override + public String getTooltip() + { + return plugin.createTooltip(); + } + + @Override + public Color getTextColor() + { + return Color.RED.brighter(); + } + + @Override + public String getText() + { + Duration timeLeft = Duration.between(Instant.now(), getEndTime()); + + if (!timeLeft.isNegative()) + { + return super.getText(); + } + return " "; + } + + @Override + public boolean render() + { + return true; + } + + @Override + public boolean cull() + { + return false; + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java index 05fc574947..8ce309843c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java @@ -1,357 +1,357 @@ -/* - * Copyright (c) 2018 Hydrox6 - * Copyright (c) 2019, Lucas - * 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.poison; - -import com.google.inject.Provides; -import java.awt.Color; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.image.BufferedImage; -import java.text.MessageFormat; -import java.time.Duration; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.SpriteID; -import net.runelite.api.VarPlayer; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.VarbitChanged; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; -import net.runelite.client.util.ColorUtil; -import net.runelite.client.util.ImageUtil; - -@PluginDescriptor( - name = "Poison", - description = "Tracks current damage values for Poison and Venom", - tags = {"combat", "poison", "venom", "heart", "hp"} -) -public class PoisonPlugin extends Plugin -{ - private static final int POISON_TICK_MILLIS = 18000; - private static final int VENOM_THRESHOLD = 1000000; - private static final int VENOM_MAXIMUM_DAMAGE = 20; - - private static final BufferedImage HEART_DISEASE; - private static final BufferedImage HEART_POISON; - private static final BufferedImage HEART_VENOM; - - static - { - HEART_DISEASE = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-DISEASE.png"), 26, 26); - HEART_POISON = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-POISON.png"), 26, 26); - HEART_VENOM = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-VENOM.png"), 26, 26); - } - - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private PoisonOverlay poisonOverlay; - - @Inject - private OverlayManager overlayManager; - - @Inject - private InfoBoxManager infoBoxManager; - - @Inject - private SpriteManager spriteManager; - - @Inject - private PoisonConfig config; - - @Getter - private int lastDamage; - private boolean envenomed; - private PoisonInfobox infobox; - private Instant nextPoisonTick; - private int lastValue = 0; - private int lastDiseaseValue = 0; - private BufferedImage heart; - private int nextTickCount; - - @Provides - PoisonConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(PoisonConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(poisonOverlay); - - if (client.getGameState() == GameState.LOGGED_IN) - { - clientThread.invoke(this::checkHealthIcon); - } - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(poisonOverlay); - - if (infobox != null) - { - infoBoxManager.removeInfoBox(infobox); - infobox = null; - } - - envenomed = false; - lastDamage = 0; - nextPoisonTick = null; - lastValue = 0; - lastDiseaseValue = 0; - - clientThread.invoke(this::resetHealthIcon); - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - final int poisonValue = client.getVar(VarPlayer.POISON); - if (poisonValue != lastValue) - { - envenomed = poisonValue >= VENOM_THRESHOLD; - - if (nextTickCount - client.getTickCount() <= 30 || lastValue == 0) - { - nextPoisonTick = Instant.now().plus(Duration.of(POISON_TICK_MILLIS, ChronoUnit.MILLIS)); - nextTickCount = client.getTickCount() + 30; - } - - lastValue = poisonValue; - final int damage = nextDamage(poisonValue); - this.lastDamage = damage; - - if (config.showInfoboxes()) - { - if (infobox != null) - { - infoBoxManager.removeInfoBox(infobox); - infobox = null; - } - - if (damage > 0) - { - final BufferedImage image = getSplat(envenomed ? SpriteID.HITSPLAT_DARK_GREEN_VENOM : SpriteID.HITSPLAT_GREEN_POISON, damage); - - if (image != null) - { - int duration = 600 * (nextTickCount - client.getTickCount()); - infobox = new PoisonInfobox(duration, image, this); - infoBoxManager.addInfoBox(infobox); - } - } - } - checkHealthIcon(); - } - - final int diseaseValue = client.getVar(VarPlayer.DISEASE_VALUE); - if (diseaseValue != lastDiseaseValue) - { - lastDiseaseValue = diseaseValue; - checkHealthIcon(); - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (!event.getGroup().equals(PoisonConfig.GROUP)) - { - return; - } - - if (!config.showInfoboxes() && infobox != null) - { - infoBoxManager.removeInfoBox(infobox); - infobox = null; - } - - if (config.changeHealthIcon()) - { - clientThread.invoke(this::checkHealthIcon); - } - else - { - clientThread.invoke(this::resetHealthIcon); - } - } - - private static int nextDamage(int poisonValue) - { - int damage; - - if (poisonValue >= VENOM_THRESHOLD) - { - //Venom Damage starts at 6, and increments in twos; - //The VarPlayer increments in values of 1, however. - poisonValue -= VENOM_THRESHOLD - 3; - damage = poisonValue * 2; - //Venom Damage caps at 20, but the VarPlayer keeps increasing - if (damage > VENOM_MAXIMUM_DAMAGE) - { - damage = VENOM_MAXIMUM_DAMAGE; - } - } - else - { - damage = (int) Math.ceil(poisonValue / 5.0f); - } - - return damage; - } - - private BufferedImage getSplat(int id, int damage) - { - //Get a copy of the hitsplat to get a clean one each time - final BufferedImage rawSplat = spriteManager.getSprite(id, 0); - if (rawSplat == null) - { - return null; - } - - final BufferedImage splat = new BufferedImage( - rawSplat.getColorModel(), - rawSplat.copyData(null), - rawSplat.getColorModel().isAlphaPremultiplied(), - null); - - final Graphics g = splat.getGraphics(); - g.setFont(FontManager.getRunescapeSmallFont()); - - // Align the text in the centre of the hitsplat - final FontMetrics metrics = g.getFontMetrics(); - final String text = String.valueOf(damage); - final int x = (splat.getWidth() - metrics.stringWidth(text)) / 2; - final int y = (splat.getHeight() - metrics.getHeight()) / 2 + metrics.getAscent(); - - g.setColor(Color.BLACK); - g.drawString(String.valueOf(damage), x + 1, y + 1); - g.setColor(Color.WHITE); - g.drawString(String.valueOf(damage), x, y); - return splat; - } - - private static String getFormattedTime(Duration timeLeft) - { - if (timeLeft.isNegative()) - { - return "Now!"; - } - - int seconds = (int) (timeLeft.toMillis() / 1000L); - int minutes = seconds / 60; - int secs = seconds % 60; - - return String.format("%d:%02d", minutes, secs); - } - - String createTooltip() - { - Duration timeLeft; - if (nextPoisonTick.isBefore(Instant.now()) && !envenomed) - { - timeLeft = Duration.of(POISON_TICK_MILLIS * (lastValue - 1), ChronoUnit.MILLIS); - } - else - { - timeLeft = Duration.between(Instant.now(), nextPoisonTick).plusMillis(POISON_TICK_MILLIS * (lastValue - 1)); - } - - String line1 = MessageFormat.format("Next {0} damage: {1}
Time until damage: {2}", - envenomed ? "venom" : "poison", ColorUtil.wrapWithColorTag(String.valueOf(lastDamage), Color.RED), - getFormattedTime(Duration.between(Instant.now(), nextPoisonTick))); - String line2 = envenomed ? "" : MessageFormat.format("
Time until cure: {0}", getFormattedTime(timeLeft)); - - return line1 + line2; - } - - private void checkHealthIcon() - { - if (!config.changeHealthIcon()) - { - return; - } - - final BufferedImage newHeart; - final int poison = client.getVar(VarPlayer.IS_POISONED); - - if (poison >= VENOM_THRESHOLD) - { - newHeart = HEART_VENOM; - } - else if (poison > 0) - { - newHeart = HEART_POISON; - } - else if (client.getVar(VarPlayer.DISEASE_VALUE) > 0) - { - newHeart = HEART_DISEASE; - } - else - { - resetHealthIcon(); - return; - } - - // Only update sprites when the heart icon actually changes - if (newHeart != heart) - { - heart = newHeart; - client.getWidgetSpriteCache().reset(); - client.getSpriteOverrides().put(SpriteID.MINIMAP_ORB_HITPOINTS_ICON, ImageUtil.getImageSpritePixels(heart, client)); - } - } - - private void resetHealthIcon() - { - if (heart == null) - { - return; - } - - client.getWidgetSpriteCache().reset(); - client.getSpriteOverrides().remove(SpriteID.MINIMAP_ORB_HITPOINTS_ICON); - heart = null; - } +/* + * Copyright (c) 2018 Hydrox6 + * Copyright (c) 2019, Lucas + * 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.poison; + +import com.google.inject.Provides; +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.text.MessageFormat; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.SpriteID; +import net.runelite.api.VarPlayer; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.ImageUtil; + +@PluginDescriptor( + name = "Poison", + description = "Tracks current damage values for Poison and Venom", + tags = {"combat", "poison", "venom", "heart", "hp"} +) +public class PoisonPlugin extends Plugin +{ + private static final int POISON_TICK_MILLIS = 18000; + private static final int VENOM_THRESHOLD = 1000000; + private static final int VENOM_MAXIMUM_DAMAGE = 20; + + private static final BufferedImage HEART_DISEASE; + private static final BufferedImage HEART_POISON; + private static final BufferedImage HEART_VENOM; + + static + { + HEART_DISEASE = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-DISEASE.png"), 26, 26); + HEART_POISON = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-POISON.png"), 26, 26); + HEART_VENOM = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-VENOM.png"), 26, 26); + } + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private PoisonOverlay poisonOverlay; + + @Inject + private OverlayManager overlayManager; + + @Inject + private InfoBoxManager infoBoxManager; + + @Inject + private SpriteManager spriteManager; + + @Inject + private PoisonConfig config; + + @Getter + private int lastDamage; + private boolean envenomed; + private PoisonInfobox infobox; + private Instant nextPoisonTick; + private int lastValue = 0; + private int lastDiseaseValue = 0; + private BufferedImage heart; + private int nextTickCount; + + @Provides + PoisonConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(PoisonConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(poisonOverlay); + + if (client.getGameState() == GameState.LOGGED_IN) + { + clientThread.invoke(this::checkHealthIcon); + } + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(poisonOverlay); + + if (infobox != null) + { + infoBoxManager.removeInfoBox(infobox); + infobox = null; + } + + envenomed = false; + lastDamage = 0; + nextPoisonTick = null; + lastValue = 0; + lastDiseaseValue = 0; + + clientThread.invoke(this::resetHealthIcon); + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + final int poisonValue = client.getVar(VarPlayer.POISON); + if (poisonValue != lastValue) + { + envenomed = poisonValue >= VENOM_THRESHOLD; + + if (nextTickCount - client.getTickCount() <= 30 || lastValue == 0) + { + nextPoisonTick = Instant.now().plus(Duration.of(POISON_TICK_MILLIS, ChronoUnit.MILLIS)); + nextTickCount = client.getTickCount() + 30; + } + + lastValue = poisonValue; + final int damage = nextDamage(poisonValue); + this.lastDamage = damage; + + if (config.showInfoboxes()) + { + if (infobox != null) + { + infoBoxManager.removeInfoBox(infobox); + infobox = null; + } + + if (damage > 0) + { + final BufferedImage image = getSplat(envenomed ? SpriteID.HITSPLAT_DARK_GREEN_VENOM : SpriteID.HITSPLAT_GREEN_POISON, damage); + + if (image != null) + { + int duration = 600 * (nextTickCount - client.getTickCount()); + infobox = new PoisonInfobox(duration, image, this); + infoBoxManager.addInfoBox(infobox); + } + } + } + checkHealthIcon(); + } + + final int diseaseValue = client.getVar(VarPlayer.DISEASE_VALUE); + if (diseaseValue != lastDiseaseValue) + { + lastDiseaseValue = diseaseValue; + checkHealthIcon(); + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!event.getGroup().equals(PoisonConfig.GROUP)) + { + return; + } + + if (!config.showInfoboxes() && infobox != null) + { + infoBoxManager.removeInfoBox(infobox); + infobox = null; + } + + if (config.changeHealthIcon()) + { + clientThread.invoke(this::checkHealthIcon); + } + else + { + clientThread.invoke(this::resetHealthIcon); + } + } + + private static int nextDamage(int poisonValue) + { + int damage; + + if (poisonValue >= VENOM_THRESHOLD) + { + //Venom Damage starts at 6, and increments in twos; + //The VarPlayer increments in values of 1, however. + poisonValue -= VENOM_THRESHOLD - 3; + damage = poisonValue * 2; + //Venom Damage caps at 20, but the VarPlayer keeps increasing + if (damage > VENOM_MAXIMUM_DAMAGE) + { + damage = VENOM_MAXIMUM_DAMAGE; + } + } + else + { + damage = (int) Math.ceil(poisonValue / 5.0f); + } + + return damage; + } + + private BufferedImage getSplat(int id, int damage) + { + //Get a copy of the hitsplat to get a clean one each time + final BufferedImage rawSplat = spriteManager.getSprite(id, 0); + if (rawSplat == null) + { + return null; + } + + final BufferedImage splat = new BufferedImage( + rawSplat.getColorModel(), + rawSplat.copyData(null), + rawSplat.getColorModel().isAlphaPremultiplied(), + null); + + final Graphics g = splat.getGraphics(); + g.setFont(FontManager.getRunescapeSmallFont()); + + // Align the text in the centre of the hitsplat + final FontMetrics metrics = g.getFontMetrics(); + final String text = String.valueOf(damage); + final int x = (splat.getWidth() - metrics.stringWidth(text)) / 2; + final int y = (splat.getHeight() - metrics.getHeight()) / 2 + metrics.getAscent(); + + g.setColor(Color.BLACK); + g.drawString(String.valueOf(damage), x + 1, y + 1); + g.setColor(Color.WHITE); + g.drawString(String.valueOf(damage), x, y); + return splat; + } + + private static String getFormattedTime(Duration timeLeft) + { + if (timeLeft.isNegative()) + { + return "Now!"; + } + + int seconds = (int) (timeLeft.toMillis() / 1000L); + int minutes = seconds / 60; + int secs = seconds % 60; + + return String.format("%d:%02d", minutes, secs); + } + + String createTooltip() + { + Duration timeLeft; + if (nextPoisonTick.isBefore(Instant.now()) && !envenomed) + { + timeLeft = Duration.of(POISON_TICK_MILLIS * (lastValue - 1), ChronoUnit.MILLIS); + } + else + { + timeLeft = Duration.between(Instant.now(), nextPoisonTick).plusMillis(POISON_TICK_MILLIS * (lastValue - 1)); + } + + String line1 = MessageFormat.format("Next {0} damage: {1}
Time until damage: {2}", + envenomed ? "venom" : "poison", ColorUtil.wrapWithColorTag(String.valueOf(lastDamage), Color.RED), + getFormattedTime(Duration.between(Instant.now(), nextPoisonTick))); + String line2 = envenomed ? "" : MessageFormat.format("
Time until cure: {0}", getFormattedTime(timeLeft)); + + return line1 + line2; + } + + private void checkHealthIcon() + { + if (!config.changeHealthIcon()) + { + return; + } + + final BufferedImage newHeart; + final int poison = client.getVar(VarPlayer.IS_POISONED); + + if (poison >= VENOM_THRESHOLD) + { + newHeart = HEART_VENOM; + } + else if (poison > 0) + { + newHeart = HEART_POISON; + } + else if (client.getVar(VarPlayer.DISEASE_VALUE) > 0) + { + newHeart = HEART_DISEASE; + } + else + { + resetHealthIcon(); + return; + } + + // Only update sprites when the heart icon actually changes + if (newHeart != heart) + { + heart = newHeart; + client.getWidgetSpriteCache().reset(); + client.getSpriteOverrides().put(SpriteID.MINIMAP_ORB_HITPOINTS_ICON, ImageUtil.getImageSpritePixels(heart, client)); + } + } + + private void resetHealthIcon() + { + if (heart == null) + { + return; + } + + client.getWidgetSpriteCache().reset(); + client.getSpriteOverrides().remove(SpriteID.MINIMAP_ORB_HITPOINTS_ICON); + heart = null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/PrayAgainstPlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/PrayAgainstPlayerPlugin.java index 32c539a637..bc0598a4c9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/PrayAgainstPlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/PrayAgainstPlayerPlugin.java @@ -29,16 +29,13 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; -import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; import java.awt.image.WritableRaster; import java.util.ArrayList; -import java.util.Arrays; import javax.inject.Inject; import net.runelite.api.AnimationID; import net.runelite.api.Client; import net.runelite.api.GameState; -import net.runelite.api.IndexedSprite; import net.runelite.api.Player; import net.runelite.api.SpriteID; import net.runelite.api.events.AnimationChanged; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/WeaponType.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/WeaponType.java index 1dc00c8311..358ba36726 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/WeaponType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayagainstplayer/WeaponType.java @@ -29,7 +29,8 @@ import net.runelite.api.ItemComposition; import net.runelite.api.Player; import net.runelite.api.kit.KitType; -enum WeaponType { +enum WeaponType +{ WEAPON_MELEE, WEAPON_RANGED, @@ -38,32 +39,46 @@ enum WeaponType { /** * im fully aware this could of been done better!!! + * * @param client * @param attacker * @return */ - public static WeaponType checkWeaponOnPlayer (Client client, Player attacker) { + public static WeaponType checkWeaponOnPlayer(Client client, Player attacker) + { int itemId = attacker.getPlayerComposition().getEquipmentId(KitType.WEAPON); ItemComposition itemComposition = client.getItemDefinition(itemId); String weaponNameGivenLowerCase = itemComposition.getName().toLowerCase(); - if (itemId == -1) return WEAPON_MELEE; - if (weaponNameGivenLowerCase == null || weaponNameGivenLowerCase.toLowerCase().contains("null")) return WEAPON_MELEE; + if (itemId == -1) + { + return WEAPON_MELEE; + } + if (weaponNameGivenLowerCase == null || weaponNameGivenLowerCase.toLowerCase().contains("null")) + { + return WEAPON_MELEE; + } - for (String meleeWeaponName : meleeWeaponNames) { - if (weaponNameGivenLowerCase.contains(meleeWeaponName) && !weaponNameGivenLowerCase.contains("thrownaxe")) { + for (String meleeWeaponName : meleeWeaponNames) + { + if (weaponNameGivenLowerCase.contains(meleeWeaponName) && !weaponNameGivenLowerCase.contains("thrownaxe")) + { return WEAPON_MELEE; } } - for (String rangedWeaponName : rangedWeaponNames) { - if (weaponNameGivenLowerCase.contains(rangedWeaponName)) { + for (String rangedWeaponName : rangedWeaponNames) + { + if (weaponNameGivenLowerCase.contains(rangedWeaponName)) + { return WEAPON_RANGED; } } - for (String magicWeaponName : magicWeaponNames) { - if (weaponNameGivenLowerCase.contains(magicWeaponName)) { + for (String magicWeaponName : magicWeaponNames) + { + if (weaponNameGivenLowerCase.contains(magicWeaponName)) + { return WEAPON_MAGIC; } } @@ -73,35 +88,35 @@ enum WeaponType { } private static String[] meleeWeaponNames = { - "sword", - "scimitar", - "dagger", - "spear", - "mace", - "axe", - "whip", - "tentacle", - "-ket-", - "-xil-", - "warhammer", - "halberd", - "claws", - "hasta", - "scythe", - "maul", - "anchor", - "sabre", - "excalibur", - "machete", - "dragon hunter lance", - "event rpg", - "silverlight", - "darklight", - "arclight", - "flail", - "granite hammer", - "rapier", - "bulwark" + "sword", + "scimitar", + "dagger", + "spear", + "mace", + "axe", + "whip", + "tentacle", + "-ket-", + "-xil-", + "warhammer", + "halberd", + "claws", + "hasta", + "scythe", + "maul", + "anchor", + "sabre", + "excalibur", + "machete", + "dragon hunter lance", + "event rpg", + "silverlight", + "darklight", + "arclight", + "flail", + "granite hammer", + "rapier", + "bulwark" }; private static String[] rangedWeaponNames = { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java index ab1d91fb16..c9b590a4d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java @@ -199,6 +199,6 @@ class PrayerDoseOverlay extends Overlay final int seconds = (int) Math.floor(secondsLeft - (minutes * 60.0)); // Return the text - return Integer.toString(minutes) + ":" + StringUtils.leftPad(Integer.toString(seconds), 2, "0"); + return minutes + ":" + StringUtils.leftPad(Integer.toString(seconds), 2, "0"); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java index 46864425c3..5ec398a7bf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java @@ -439,7 +439,7 @@ class ProfilesPanel extends PluginPanel private void addAccounts(String data) { - // log.info("Data: " + data); + // log.info("Data: " + data); data = data.trim(); if (!data.contains(":")) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/PuzzleSolverOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/PuzzleSolverOverlay.java index 67c821d841..9788e1e445 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/PuzzleSolverOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/PuzzleSolverOverlay.java @@ -1,478 +1,478 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Henke - * 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 HOLDER 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.puzzlesolver; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.util.Arrays; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import javax.inject.Inject; -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.SpriteID.MINIMAP_DESTINATION_FLAG; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver; -import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; -import net.runelite.client.plugins.puzzlesolver.solver.heuristics.ManhattanDistance; -import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.IDAStar; -import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.IDAStarMM; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.BackgroundComponent; -import net.runelite.client.ui.overlay.components.TextComponent; -import net.runelite.client.util.ImageUtil; - -public class PuzzleSolverOverlay extends Overlay -{ - private static final int INFO_BOX_WIDTH = 100; - private static final int INFO_BOX_OFFSET_Y = 50; - private static final int INFO_BOX_TOP_BORDER = 2; - private static final int INFO_BOX_BOTTOM_BORDER = 2; - - private static final int PUZZLE_TILE_SIZE = 39; - private static final int DOT_MARKER_SIZE = 16; - - private final Client client; - private final PuzzleSolverConfig config; - private final ScheduledExecutorService executorService; - private final SpriteManager spriteManager; - - private PuzzleSolver solver; - private Future solverFuture; - private int[] cachedItems; - - private BufferedImage upArrow; - private BufferedImage leftArrow; - private BufferedImage rightArrow; - - @Inject - public PuzzleSolverOverlay(Client client, PuzzleSolverConfig config, ScheduledExecutorService executorService, SpriteManager spriteManager) - { - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.HIGH); - setLayer(OverlayLayer.ABOVE_WIDGETS); - this.client = client; - this.config = config; - this.executorService = executorService; - this.spriteManager = spriteManager; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if ((!config.displaySolution() && !config.displayRemainingMoves()) - || client.getGameState() != GameState.LOGGED_IN) - { - return null; - } - - boolean useNormalSolver = true; - ItemContainer container = client.getItemContainer(InventoryID.PUZZLE_BOX); - - if (container == null) - { - useNormalSolver = false; - container = client.getItemContainer(InventoryID.MONKEY_MADNESS_PUZZLE_BOX); - - if (container == null) - { - return null; - } - } - - Widget puzzleBox = client.getWidget(WidgetInfo.PUZZLE_BOX); - - if (puzzleBox == null) - { - return null; - } - - net.runelite.api.Point puzzleBoxLocation = puzzleBox.getCanvasLocation(); - - String infoString = "Solving.."; - - int[] itemIds = getItemIds(container, useNormalSolver); - boolean shouldCache = false; - - if (solver != null) - { - if (solver.hasFailed()) - { - infoString = "The puzzle could not be solved"; - } - else - { - if (solver.hasSolution()) - { - boolean foundPosition = false; - - // Find the current state by looking at the current step and then the next 5 steps - for (int i = 0; i < 6; i++) - { - int j = solver.getPosition() + i; - - if (j == solver.getStepCount()) - { - break; - } - - PuzzleState currentState = solver.getStep(j); - - // If this is false, player has moved the empty tile - if (currentState != null && currentState.hasPieces(itemIds)) - { - foundPosition = true; - solver.setPosition(j); - if (i > 0) - { - shouldCache = true; - } - break; - } - } - - // If looking at the next steps didn't find the current state, - // see if we can find the current state in the 5 previous steps - if (!foundPosition) - { - for (int i = 1; i < 6; i++) - { - int j = solver.getPosition() - i; - - if (j < 0) - { - break; - } - - PuzzleState currentState = solver.getStep(j); - - if (currentState != null && currentState.hasPieces(itemIds)) - { - foundPosition = true; - shouldCache = true; - solver.setPosition(j); - break; - } - } - } - - if (foundPosition) - { - int stepsLeft = solver.getStepCount() - solver.getPosition() - 1; - - if (stepsLeft == 0) - { - infoString = "Solved!"; - } - else if (config.displayRemainingMoves()) - { - infoString = "Moves left: " + stepsLeft; - } - else - { - infoString = null; - } - - if (config.displaySolution()) - { - if (config.drawDots()) - { - graphics.setColor(Color.YELLOW); - - // Display the next 4 steps - for (int i = 1; i < 5; i++) - { - int j = solver.getPosition() + i; - - if (j >= solver.getStepCount()) - { - break; - } - - PuzzleState futureMove = solver.getStep(j); - - if (futureMove == null) - { - break; - } - - int blankX = futureMove.getEmptyPiece() % DIMENSION; - int blankY = futureMove.getEmptyPiece() / DIMENSION; - - int markerSize = DOT_MARKER_SIZE - i * 3; - - int x = puzzleBoxLocation.getX() + blankX * PUZZLE_TILE_SIZE - + PUZZLE_TILE_SIZE / 2 - markerSize / 2; - - int y = puzzleBoxLocation.getY() + blankY * PUZZLE_TILE_SIZE - + PUZZLE_TILE_SIZE / 2 - markerSize / 2; - - graphics.fillOval(x, y, markerSize, markerSize); - } - } - else - { - // Find the current blank tile position - PuzzleState currentMove = solver.getStep(solver.getPosition()); - - int lastBlankX = currentMove.getEmptyPiece() % DIMENSION; - int lastBlankY = currentMove.getEmptyPiece() / DIMENSION; - - // Display the next 3 steps - for (int i = 1; i < 4; i++) - { - int j = solver.getPosition() + i; - - if (j >= solver.getStepCount()) - { - break; - } - - PuzzleState futureMove = solver.getStep(j); - - if (futureMove == null) - { - break; - } - - int blankX = futureMove.getEmptyPiece() % DIMENSION; - int blankY = futureMove.getEmptyPiece() / DIMENSION; - - int xDelta = blankX - lastBlankX; - int yDelta = blankY - lastBlankY; - - BufferedImage arrow; - if (xDelta > 0) - { - arrow = getRightArrow(); - } - else if (xDelta < 0) - { - arrow = getLeftArrow(); - } - else if (yDelta > 0) - { - arrow = getDownArrow(); - } - else - { - arrow = getUpArrow(); - } - - int x = puzzleBoxLocation.getX() + blankX * PUZZLE_TILE_SIZE - + PUZZLE_TILE_SIZE / 2 - arrow.getWidth() / 2; - - int y = puzzleBoxLocation.getY() + blankY * PUZZLE_TILE_SIZE - + PUZZLE_TILE_SIZE / 2 - arrow.getHeight() / 2; - - OverlayUtil.renderImageLocation(graphics, new net.runelite.api.Point(x, y), arrow); - - lastBlankX = blankX; - lastBlankY = blankY; - } - } - } - } - } - } - } - - // Draw info box - if (infoString != null) - { - int x = puzzleBoxLocation.getX() + puzzleBox.getWidth() / 2 - INFO_BOX_WIDTH / 2; - int y = puzzleBoxLocation.getY() - INFO_BOX_OFFSET_Y; - - FontMetrics fm = graphics.getFontMetrics(); - int height = INFO_BOX_TOP_BORDER + fm.getHeight() + INFO_BOX_BOTTOM_BORDER; - - BackgroundComponent backgroundComponent = new BackgroundComponent(); - backgroundComponent.setRectangle(new Rectangle(x, y, INFO_BOX_WIDTH, height)); - backgroundComponent.render(graphics); - - int textOffsetX = (INFO_BOX_WIDTH - fm.stringWidth(infoString)) / 2; - int textOffsetY = fm.getHeight(); - - TextComponent textComponent = new TextComponent(); - textComponent.setPosition(new Point(x + textOffsetX, y + textOffsetY)); - textComponent.setText(infoString); - textComponent.render(graphics); - } - - // Solve the puzzle if we don't have an up to date solution - if (solver == null || cachedItems == null - || (!shouldCache && solver.hasExceededWaitDuration() && !Arrays.equals(cachedItems, itemIds))) - { - solve(itemIds, useNormalSolver); - shouldCache = true; - } - - if (shouldCache) - { - cacheItems(itemIds); - } - - return null; - } - - private int[] getItemIds(ItemContainer container, boolean useNormalSolver) - { - int[] itemIds = new int[DIMENSION * DIMENSION]; - - Item[] items = container.getItems(); - - for (int i = 0; i < items.length; i++) - { - itemIds[i] = items[i].getId(); - } - - // If blank is in the last position, items doesn't contain it, so let's add it manually - if (itemIds.length > items.length) - { - itemIds[items.length] = BLANK_TILE_VALUE; - } - - return convertToSolverFormat(itemIds, useNormalSolver); - } - - private int[] convertToSolverFormat(int[] items, boolean useNormalSolver) - { - int lowestId = Integer.MAX_VALUE; - - int[] convertedItems = new int[items.length]; - - for (int id : items) - { - if (id == BLANK_TILE_VALUE) - { - continue; - } - - if (lowestId > id) - { - lowestId = id; - } - } - - for (int i = 0; i < items.length; i++) - { - if (items[i] != BLANK_TILE_VALUE) - { - int value = items[i] - lowestId; - - // The MM puzzle has gaps - if (!useNormalSolver) - { - value /= 2; - } - - convertedItems[i] = value; - } - else - { - convertedItems[i] = BLANK_TILE_VALUE; - } - } - - return convertedItems; - } - - private void cacheItems(int[] items) - { - cachedItems = new int[items.length]; - System.arraycopy(items, 0, cachedItems, 0, cachedItems.length); - } - - private void solve(int[] items, boolean useNormalSolver) - { - if (solverFuture != null) - { - solverFuture.cancel(true); - } - - PuzzleState puzzleState = new PuzzleState(items); - - if (useNormalSolver) - { - solver = new PuzzleSolver(new IDAStar(new ManhattanDistance()), puzzleState); - } - else - { - solver = new PuzzleSolver(new IDAStarMM(new ManhattanDistance()), puzzleState); - } - - solverFuture = executorService.submit(solver); - } - - private BufferedImage getDownArrow() - { - return spriteManager.getSprite(MINIMAP_DESTINATION_FLAG, 1); - } - - private BufferedImage getUpArrow() - { - if (upArrow == null) - { - upArrow = ImageUtil.rotateImage(getDownArrow(), Math.PI); - } - return upArrow; - } - - private BufferedImage getLeftArrow() - { - if (leftArrow == null) - { - leftArrow = ImageUtil.rotateImage(getDownArrow(), Math.PI / 2); - } - return leftArrow; - } - - private BufferedImage getRightArrow() - { - if (rightArrow == null) - { - rightArrow = ImageUtil.rotateImage(getDownArrow(), 3 * Math.PI / 2); - } - return rightArrow; - } -} +/* + * Copyright (c) 2018, Lotto + * Copyright (c) 2018, Henke + * 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 HOLDER 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.puzzlesolver; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.util.Arrays; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +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.SpriteID.MINIMAP_DESTINATION_FLAG; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; +import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; +import net.runelite.client.plugins.puzzlesolver.solver.heuristics.ManhattanDistance; +import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.IDAStar; +import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.IDAStarMM; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.BackgroundComponent; +import net.runelite.client.ui.overlay.components.TextComponent; +import net.runelite.client.util.ImageUtil; + +public class PuzzleSolverOverlay extends Overlay +{ + private static final int INFO_BOX_WIDTH = 100; + private static final int INFO_BOX_OFFSET_Y = 50; + private static final int INFO_BOX_TOP_BORDER = 2; + private static final int INFO_BOX_BOTTOM_BORDER = 2; + + private static final int PUZZLE_TILE_SIZE = 39; + private static final int DOT_MARKER_SIZE = 16; + + private final Client client; + private final PuzzleSolverConfig config; + private final ScheduledExecutorService executorService; + private final SpriteManager spriteManager; + + private PuzzleSolver solver; + private Future solverFuture; + private int[] cachedItems; + + private BufferedImage upArrow; + private BufferedImage leftArrow; + private BufferedImage rightArrow; + + @Inject + public PuzzleSolverOverlay(Client client, PuzzleSolverConfig config, ScheduledExecutorService executorService, SpriteManager spriteManager) + { + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGH); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.client = client; + this.config = config; + this.executorService = executorService; + this.spriteManager = spriteManager; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if ((!config.displaySolution() && !config.displayRemainingMoves()) + || client.getGameState() != GameState.LOGGED_IN) + { + return null; + } + + boolean useNormalSolver = true; + ItemContainer container = client.getItemContainer(InventoryID.PUZZLE_BOX); + + if (container == null) + { + useNormalSolver = false; + container = client.getItemContainer(InventoryID.MONKEY_MADNESS_PUZZLE_BOX); + + if (container == null) + { + return null; + } + } + + Widget puzzleBox = client.getWidget(WidgetInfo.PUZZLE_BOX); + + if (puzzleBox == null) + { + return null; + } + + net.runelite.api.Point puzzleBoxLocation = puzzleBox.getCanvasLocation(); + + String infoString = "Solving.."; + + int[] itemIds = getItemIds(container, useNormalSolver); + boolean shouldCache = false; + + if (solver != null) + { + if (solver.hasFailed()) + { + infoString = "The puzzle could not be solved"; + } + else + { + if (solver.hasSolution()) + { + boolean foundPosition = false; + + // Find the current state by looking at the current step and then the next 5 steps + for (int i = 0; i < 6; i++) + { + int j = solver.getPosition() + i; + + if (j == solver.getStepCount()) + { + break; + } + + PuzzleState currentState = solver.getStep(j); + + // If this is false, player has moved the empty tile + if (currentState != null && currentState.hasPieces(itemIds)) + { + foundPosition = true; + solver.setPosition(j); + if (i > 0) + { + shouldCache = true; + } + break; + } + } + + // If looking at the next steps didn't find the current state, + // see if we can find the current state in the 5 previous steps + if (!foundPosition) + { + for (int i = 1; i < 6; i++) + { + int j = solver.getPosition() - i; + + if (j < 0) + { + break; + } + + PuzzleState currentState = solver.getStep(j); + + if (currentState != null && currentState.hasPieces(itemIds)) + { + foundPosition = true; + shouldCache = true; + solver.setPosition(j); + break; + } + } + } + + if (foundPosition) + { + int stepsLeft = solver.getStepCount() - solver.getPosition() - 1; + + if (stepsLeft == 0) + { + infoString = "Solved!"; + } + else if (config.displayRemainingMoves()) + { + infoString = "Moves left: " + stepsLeft; + } + else + { + infoString = null; + } + + if (config.displaySolution()) + { + if (config.drawDots()) + { + graphics.setColor(Color.YELLOW); + + // Display the next 4 steps + for (int i = 1; i < 5; i++) + { + int j = solver.getPosition() + i; + + if (j >= solver.getStepCount()) + { + break; + } + + PuzzleState futureMove = solver.getStep(j); + + if (futureMove == null) + { + break; + } + + int blankX = futureMove.getEmptyPiece() % DIMENSION; + int blankY = futureMove.getEmptyPiece() / DIMENSION; + + int markerSize = DOT_MARKER_SIZE - i * 3; + + int x = puzzleBoxLocation.getX() + blankX * PUZZLE_TILE_SIZE + + PUZZLE_TILE_SIZE / 2 - markerSize / 2; + + int y = puzzleBoxLocation.getY() + blankY * PUZZLE_TILE_SIZE + + PUZZLE_TILE_SIZE / 2 - markerSize / 2; + + graphics.fillOval(x, y, markerSize, markerSize); + } + } + else + { + // Find the current blank tile position + PuzzleState currentMove = solver.getStep(solver.getPosition()); + + int lastBlankX = currentMove.getEmptyPiece() % DIMENSION; + int lastBlankY = currentMove.getEmptyPiece() / DIMENSION; + + // Display the next 3 steps + for (int i = 1; i < 4; i++) + { + int j = solver.getPosition() + i; + + if (j >= solver.getStepCount()) + { + break; + } + + PuzzleState futureMove = solver.getStep(j); + + if (futureMove == null) + { + break; + } + + int blankX = futureMove.getEmptyPiece() % DIMENSION; + int blankY = futureMove.getEmptyPiece() / DIMENSION; + + int xDelta = blankX - lastBlankX; + int yDelta = blankY - lastBlankY; + + BufferedImage arrow; + if (xDelta > 0) + { + arrow = getRightArrow(); + } + else if (xDelta < 0) + { + arrow = getLeftArrow(); + } + else if (yDelta > 0) + { + arrow = getDownArrow(); + } + else + { + arrow = getUpArrow(); + } + + int x = puzzleBoxLocation.getX() + blankX * PUZZLE_TILE_SIZE + + PUZZLE_TILE_SIZE / 2 - arrow.getWidth() / 2; + + int y = puzzleBoxLocation.getY() + blankY * PUZZLE_TILE_SIZE + + PUZZLE_TILE_SIZE / 2 - arrow.getHeight() / 2; + + OverlayUtil.renderImageLocation(graphics, new net.runelite.api.Point(x, y), arrow); + + lastBlankX = blankX; + lastBlankY = blankY; + } + } + } + } + } + } + } + + // Draw info box + if (infoString != null) + { + int x = puzzleBoxLocation.getX() + puzzleBox.getWidth() / 2 - INFO_BOX_WIDTH / 2; + int y = puzzleBoxLocation.getY() - INFO_BOX_OFFSET_Y; + + FontMetrics fm = graphics.getFontMetrics(); + int height = INFO_BOX_TOP_BORDER + fm.getHeight() + INFO_BOX_BOTTOM_BORDER; + + BackgroundComponent backgroundComponent = new BackgroundComponent(); + backgroundComponent.setRectangle(new Rectangle(x, y, INFO_BOX_WIDTH, height)); + backgroundComponent.render(graphics); + + int textOffsetX = (INFO_BOX_WIDTH - fm.stringWidth(infoString)) / 2; + int textOffsetY = fm.getHeight(); + + TextComponent textComponent = new TextComponent(); + textComponent.setPosition(new Point(x + textOffsetX, y + textOffsetY)); + textComponent.setText(infoString); + textComponent.render(graphics); + } + + // Solve the puzzle if we don't have an up to date solution + if (solver == null || cachedItems == null + || (!shouldCache && solver.hasExceededWaitDuration() && !Arrays.equals(cachedItems, itemIds))) + { + solve(itemIds, useNormalSolver); + shouldCache = true; + } + + if (shouldCache) + { + cacheItems(itemIds); + } + + return null; + } + + private int[] getItemIds(ItemContainer container, boolean useNormalSolver) + { + int[] itemIds = new int[DIMENSION * DIMENSION]; + + Item[] items = container.getItems(); + + for (int i = 0; i < items.length; i++) + { + itemIds[i] = items[i].getId(); + } + + // If blank is in the last position, items doesn't contain it, so let's add it manually + if (itemIds.length > items.length) + { + itemIds[items.length] = BLANK_TILE_VALUE; + } + + return convertToSolverFormat(itemIds, useNormalSolver); + } + + private int[] convertToSolverFormat(int[] items, boolean useNormalSolver) + { + int lowestId = Integer.MAX_VALUE; + + int[] convertedItems = new int[items.length]; + + for (int id : items) + { + if (id == BLANK_TILE_VALUE) + { + continue; + } + + if (lowestId > id) + { + lowestId = id; + } + } + + for (int i = 0; i < items.length; i++) + { + if (items[i] != BLANK_TILE_VALUE) + { + int value = items[i] - lowestId; + + // The MM puzzle has gaps + if (!useNormalSolver) + { + value /= 2; + } + + convertedItems[i] = value; + } + else + { + convertedItems[i] = BLANK_TILE_VALUE; + } + } + + return convertedItems; + } + + private void cacheItems(int[] items) + { + cachedItems = new int[items.length]; + System.arraycopy(items, 0, cachedItems, 0, cachedItems.length); + } + + private void solve(int[] items, boolean useNormalSolver) + { + if (solverFuture != null) + { + solverFuture.cancel(true); + } + + PuzzleState puzzleState = new PuzzleState(items); + + if (useNormalSolver) + { + solver = new PuzzleSolver(new IDAStar(new ManhattanDistance()), puzzleState); + } + else + { + solver = new PuzzleSolver(new IDAStarMM(new ManhattanDistance()), puzzleState); + } + + solverFuture = executorService.submit(solver); + } + + private BufferedImage getDownArrow() + { + return spriteManager.getSprite(MINIMAP_DESTINATION_FLAG, 1); + } + + private BufferedImage getUpArrow() + { + if (upArrow == null) + { + upArrow = ImageUtil.rotateImage(getDownArrow(), Math.PI); + } + return upArrow; + } + + private BufferedImage getLeftArrow() + { + if (leftArrow == null) + { + leftArrow = ImageUtil.rotateImage(getDownArrow(), Math.PI / 2); + } + return leftArrow; + } + + private BufferedImage getRightArrow() + { + if (rightArrow == null) + { + rightArrow = ImageUtil.rotateImage(getDownArrow(), 3 * Math.PI / 2); + } + return rightArrow; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/lightbox/Combination.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/lightbox/Combination.java index 5ed1afd0ea..50749d2755 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/lightbox/Combination.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/lightbox/Combination.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2018, Adam - * 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.puzzlesolver.lightbox; - -public enum Combination -{ - A, B, C, D, E, F, G, H; -} +/* + * Copyright (c) 2018, Adam + * 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.puzzlesolver.lightbox; + +public enum Combination +{ + A, B, C, D, E, F, G, H +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleState.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleState.java index a34675feb8..2d0c9b0257 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleState.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleState.java @@ -1,225 +1,221 @@ -/* - * Copyright (c) 2018, Lotto - * 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 HOLDER 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.puzzlesolver.solver; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import net.runelite.client.plugins.puzzlesolver.solver.heuristics.Heuristic; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; - -public class PuzzleState -{ - private PuzzleState parent; - - private int[] pieces; - private int emptyPiece = -1; - - private int h = -1; - - public PuzzleState(int[] pieces) - { - if (pieces == null) - { - throw new IllegalStateException("Pieces cannot be null"); - } - - if (DIMENSION * DIMENSION != pieces.length) - { - throw new IllegalStateException("Piece array does not have the right dimensions"); - } - - this.pieces = pieces; - findEmptyPiece(); - } - - private PuzzleState(PuzzleState state) - { - this.pieces = Arrays.copyOf(state.pieces, state.pieces.length); - this.emptyPiece = state.emptyPiece; - } - - private void findEmptyPiece() - { - for (int i = 0; i < pieces.length; i++) - { - if (pieces[i] == BLANK_TILE_VALUE) - { - this.emptyPiece = i; - return; - } - } - throw new IllegalStateException("Incorrect empty piece passed in!"); - } - - public List computeMoves() - { - List moves = new ArrayList<>(); - - int emptyPieceX = emptyPiece % DIMENSION; - int emptyPieceY = emptyPiece / DIMENSION; - - // Move left if there is space to the left - if (emptyPieceX > 0) - { - if (parent == null || parent.emptyPiece != emptyPiece - 1) - { - PuzzleState state = new PuzzleState(this); - state.parent = this; - - state.pieces[emptyPiece - 1] = BLANK_TILE_VALUE; - state.pieces[emptyPiece] = pieces[emptyPiece - 1]; - state.emptyPiece--; - - moves.add(state); - } - } - - // Move right if there is space to the right - if (emptyPieceX < DIMENSION - 1) - { - if (parent == null || parent.emptyPiece != emptyPiece + 1) - { - PuzzleState state = new PuzzleState(this); - state.parent = this; - - state.pieces[emptyPiece + 1] = BLANK_TILE_VALUE; - state.pieces[emptyPiece] = pieces[emptyPiece + 1]; - state.emptyPiece++; - - moves.add(state); - } - } - - // Move up if there is space upwards - if (emptyPieceY > 0) - { - if (parent == null || parent.emptyPiece != emptyPiece - DIMENSION) - { - PuzzleState state = new PuzzleState(this); - state.parent = this; - - state.pieces[emptyPiece - DIMENSION] = BLANK_TILE_VALUE; - state.pieces[emptyPiece] = pieces[emptyPiece - DIMENSION]; - state.emptyPiece -= DIMENSION; - - moves.add(state); - } - } - - // Move down if there is space downwards - if (emptyPieceY < DIMENSION - 1) - { - if (parent == null || parent.emptyPiece != emptyPiece + DIMENSION) - { - PuzzleState state = new PuzzleState(this); - state.parent = this; - - state.pieces[emptyPiece + DIMENSION] = BLANK_TILE_VALUE; - state.pieces[emptyPiece] = pieces[emptyPiece + DIMENSION]; - state.emptyPiece += DIMENSION; - - moves.add(state); - } - } - - return moves; - } - - public PuzzleState getParent() - { - return parent; - } - - public boolean hasPieces(int[] pieces) - { - return Arrays.equals(pieces, this.pieces); - } - - public int getPiece(int x, int y) - { - return pieces[y * DIMENSION + x]; - } - - public int getEmptyPiece() - { - return emptyPiece; - } - - public int getHeuristicValue(Heuristic heuristic) - { - if (h == -1) - { - // cache the value - h = heuristic.computeValue(this); - } - - return h; - } - - public PuzzleState swap(int x1, int y1, int x2, int y2) - { - int val1 = getPiece(x1, y1); - int val2 = getPiece(x2, y2); - - if (!isValidSwap(x1, y1, x2, y2)) - { - throw new IllegalStateException(String.format("Invalid swap: (%1$d, %2$d), (%3$d, %4$d)", x1, y1, x2, y2)); - } - - PuzzleState newState = new PuzzleState(this); - - newState.pieces[y1 * DIMENSION + x1] = val2; - newState.pieces[y2 * DIMENSION + x2] = val1; - newState.findEmptyPiece(); - - return newState; - } - - private boolean isValidSwap(int x1, int y1, int x2, int y2) - { - int absX = Math.abs(x1 - x2); - int absY = Math.abs(y1 - y2); - - if (getPiece(x1, y1) != BLANK_TILE_VALUE && getPiece(x2, y2) != BLANK_TILE_VALUE) - { - return false; - } - - if (x1 == x2 && absY == 1) - { - return true; - } - - if (y1 == y2 && absX == 1) - { - return true; - } - - return false; - } -} +/* + * Copyright (c) 2018, Lotto + * 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 HOLDER 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.puzzlesolver.solver; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; +import net.runelite.client.plugins.puzzlesolver.solver.heuristics.Heuristic; + +public class PuzzleState +{ + private PuzzleState parent; + + private int[] pieces; + private int emptyPiece = -1; + + private int h = -1; + + public PuzzleState(int[] pieces) + { + if (pieces == null) + { + throw new IllegalStateException("Pieces cannot be null"); + } + + if (DIMENSION * DIMENSION != pieces.length) + { + throw new IllegalStateException("Piece array does not have the right dimensions"); + } + + this.pieces = pieces; + findEmptyPiece(); + } + + private PuzzleState(PuzzleState state) + { + this.pieces = Arrays.copyOf(state.pieces, state.pieces.length); + this.emptyPiece = state.emptyPiece; + } + + private void findEmptyPiece() + { + for (int i = 0; i < pieces.length; i++) + { + if (pieces[i] == BLANK_TILE_VALUE) + { + this.emptyPiece = i; + return; + } + } + throw new IllegalStateException("Incorrect empty piece passed in!"); + } + + public List computeMoves() + { + List moves = new ArrayList<>(); + + int emptyPieceX = emptyPiece % DIMENSION; + int emptyPieceY = emptyPiece / DIMENSION; + + // Move left if there is space to the left + if (emptyPieceX > 0) + { + if (parent == null || parent.emptyPiece != emptyPiece - 1) + { + PuzzleState state = new PuzzleState(this); + state.parent = this; + + state.pieces[emptyPiece - 1] = BLANK_TILE_VALUE; + state.pieces[emptyPiece] = pieces[emptyPiece - 1]; + state.emptyPiece--; + + moves.add(state); + } + } + + // Move right if there is space to the right + if (emptyPieceX < DIMENSION - 1) + { + if (parent == null || parent.emptyPiece != emptyPiece + 1) + { + PuzzleState state = new PuzzleState(this); + state.parent = this; + + state.pieces[emptyPiece + 1] = BLANK_TILE_VALUE; + state.pieces[emptyPiece] = pieces[emptyPiece + 1]; + state.emptyPiece++; + + moves.add(state); + } + } + + // Move up if there is space upwards + if (emptyPieceY > 0) + { + if (parent == null || parent.emptyPiece != emptyPiece - DIMENSION) + { + PuzzleState state = new PuzzleState(this); + state.parent = this; + + state.pieces[emptyPiece - DIMENSION] = BLANK_TILE_VALUE; + state.pieces[emptyPiece] = pieces[emptyPiece - DIMENSION]; + state.emptyPiece -= DIMENSION; + + moves.add(state); + } + } + + // Move down if there is space downwards + if (emptyPieceY < DIMENSION - 1) + { + if (parent == null || parent.emptyPiece != emptyPiece + DIMENSION) + { + PuzzleState state = new PuzzleState(this); + state.parent = this; + + state.pieces[emptyPiece + DIMENSION] = BLANK_TILE_VALUE; + state.pieces[emptyPiece] = pieces[emptyPiece + DIMENSION]; + state.emptyPiece += DIMENSION; + + moves.add(state); + } + } + + return moves; + } + + public PuzzleState getParent() + { + return parent; + } + + public boolean hasPieces(int[] pieces) + { + return Arrays.equals(pieces, this.pieces); + } + + public int getPiece(int x, int y) + { + return pieces[y * DIMENSION + x]; + } + + public int getEmptyPiece() + { + return emptyPiece; + } + + public int getHeuristicValue(Heuristic heuristic) + { + if (h == -1) + { + // cache the value + h = heuristic.computeValue(this); + } + + return h; + } + + public PuzzleState swap(int x1, int y1, int x2, int y2) + { + int val1 = getPiece(x1, y1); + int val2 = getPiece(x2, y2); + + if (!isValidSwap(x1, y1, x2, y2)) + { + throw new IllegalStateException(String.format("Invalid swap: (%1$d, %2$d), (%3$d, %4$d)", x1, y1, x2, y2)); + } + + PuzzleState newState = new PuzzleState(this); + + newState.pieces[y1 * DIMENSION + x1] = val2; + newState.pieces[y2 * DIMENSION + x2] = val1; + newState.findEmptyPiece(); + + return newState; + } + + private boolean isValidSwap(int x1, int y1, int x2, int y2) + { + int absX = Math.abs(x1 - x2); + int absY = Math.abs(y1 - y2); + + if (getPiece(x1, y1) != BLANK_TILE_VALUE && getPiece(x2, y2) != BLANK_TILE_VALUE) + { + return false; + } + + if (x1 == x2 && absY == 1) + { + return true; + } + + return y1 == y2 && absX == 1; + + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleSwapPattern.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleSwapPattern.java index fe7949efd5..80e5622082 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleSwapPattern.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/PuzzleSwapPattern.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2018, Steffen Hauge - * 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.puzzlesolver.solver; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum PuzzleSwapPattern -{ - ROTATE_LEFT_UP(new int[]{1, -1, 0, -1, -1, -1, -1, 0}, 1, 1), //Reference point - ROTATE_LEFT_DOWN(1, -1), - ROTATE_RIGHT_UP(-1, 1), - ROTATE_RIGHT_DOWN(-1, -1), - ROTATE_UP_LEFT(new int[]{-1, 1, -1, 0, -1, -1, 0, -1}, 1 , 1), //Reference point - ROTATE_UP_RIGHT(-1, 1), - ROTATE_DOWN_LEFT(1, -1), - ROTATE_DOWN_RIGHT(-1, -1), - LAST_PIECE_ROW(new int[]{-1, -1, 0, -1, -1, 0, -1, 1}, 1, 1), - LAST_PIECE_COLUMN(new int[]{-1, -1, -1, 0, 0, -1, 1, -1}, 1, 1), - SHUFFLE_UP_RIGHT(new int[]{1, -1, 0, -1}, 1, 1), - SHUFFLE_UP_LEFT(new int[]{-1, -1, 0, -1}, 1, 1), - SHUFFLE_UP_BELOW(new int[]{-1, 1, -1, 0}, 1, 1), - SHUFFLE_UP_ABOVE(new int[]{-1, -1, -1, 0}, 1, 1); - - /** - * Points used for swaps relative to locVal - */ - private final int[] points; - /** - * Modifier for X coordinate - */ - private final int modX; - /** - * Modifier for Y coordinate - */ - private final int modY; - - PuzzleSwapPattern(int modX, int modY) - { - this(null, modX, modY); - } -} +/* + * Copyright (c) 2018, Steffen Hauge + * 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.puzzlesolver.solver; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum PuzzleSwapPattern +{ + ROTATE_LEFT_UP(new int[]{1, -1, 0, -1, -1, -1, -1, 0}, 1, 1), //Reference point + ROTATE_LEFT_DOWN(1, -1), + ROTATE_RIGHT_UP(-1, 1), + ROTATE_RIGHT_DOWN(-1, -1), + ROTATE_UP_LEFT(new int[]{-1, 1, -1, 0, -1, -1, 0, -1}, 1, 1), //Reference point + ROTATE_UP_RIGHT(-1, 1), + ROTATE_DOWN_LEFT(1, -1), + ROTATE_DOWN_RIGHT(-1, -1), + LAST_PIECE_ROW(new int[]{-1, -1, 0, -1, -1, 0, -1, 1}, 1, 1), + LAST_PIECE_COLUMN(new int[]{-1, -1, -1, 0, 0, -1, 1, -1}, 1, 1), + SHUFFLE_UP_RIGHT(new int[]{1, -1, 0, -1}, 1, 1), + SHUFFLE_UP_LEFT(new int[]{-1, -1, 0, -1}, 1, 1), + SHUFFLE_UP_BELOW(new int[]{-1, 1, -1, 0}, 1, 1), + SHUFFLE_UP_ABOVE(new int[]{-1, -1, -1, 0}, 1, 1); + + /** + * Points used for swaps relative to locVal + */ + private final int[] points; + /** + * Modifier for X coordinate + */ + private final int modX; + /** + * Modifier for Y coordinate + */ + private final int modY; + + PuzzleSwapPattern(int modX, int modY) + { + this(null, modX, modY); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/heuristics/ManhattanDistance.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/heuristics/ManhattanDistance.java index 9c89f9e71d..df9b66d9ad 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/heuristics/ManhattanDistance.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/heuristics/ManhattanDistance.java @@ -1,122 +1,146 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Henke - * 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 HOLDER 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.puzzlesolver.solver.heuristics; - -import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; - -/** - * An implementation of the manhattan distance heuristic function. - * - * https://heuristicswiki.wikispaces.com/Manhattan+Distance - */ -public class ManhattanDistance implements Heuristic -{ - @Override - public int computeValue(PuzzleState state) - { - int value = 0; - - PuzzleState parent = state.getParent(); - - if (parent == null) - { - for (int x = 0; x < DIMENSION; x++) - { - for (int y = 0; y < DIMENSION; y++) - { - int piece = state.getPiece(x, y); - - if (piece == BLANK_TILE_VALUE) - { - continue; - } - - int goalX = piece % DIMENSION; - int goalY = piece / DIMENSION; - - value += Math.abs(x - goalX) + Math.abs(y - goalY); - } - } - } - else - { - /* - If the Manhattan distance for the parent has already been - calculated, we can take advantage of that and just - add/subtract from their heuristic value. - - Doing this decreases the execution time of the heuristic by about 25%. - */ - value = parent.getHeuristicValue(this); - - int x = parent.getEmptyPiece() % DIMENSION; - int y = parent.getEmptyPiece() / DIMENSION; - - int x2 = state.getEmptyPiece() % DIMENSION; - int y2 = state.getEmptyPiece() / DIMENSION; - - int piece = state.getPiece(x, y); - - if (x2 > x) - { - int targetX = piece % DIMENSION; - - // right - if (targetX > x) value++; - else value--; - } - else if (x2 < x) - { - int targetX = piece % DIMENSION; - - // left - if (targetX < x) value++; - else value--; - } - else if (y2 > y) - { - int targetY = piece / DIMENSION; - - // down - if (targetY > y) value++; - else value--; - } - else - { - int targetY = piece / DIMENSION; - - // up - if (targetY < y) value++; - else value--; - } - } - - return value; - } -} +/* + * Copyright (c) 2018, Lotto + * Copyright (c) 2018, Henke + * 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 HOLDER 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.puzzlesolver.solver.heuristics; + +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; +import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; + +/** + * An implementation of the manhattan distance heuristic function. + *

+ * https://heuristicswiki.wikispaces.com/Manhattan+Distance + */ +public class ManhattanDistance implements Heuristic +{ + @Override + public int computeValue(PuzzleState state) + { + int value = 0; + + PuzzleState parent = state.getParent(); + + if (parent == null) + { + for (int x = 0; x < DIMENSION; x++) + { + for (int y = 0; y < DIMENSION; y++) + { + int piece = state.getPiece(x, y); + + if (piece == BLANK_TILE_VALUE) + { + continue; + } + + int goalX = piece % DIMENSION; + int goalY = piece / DIMENSION; + + value += Math.abs(x - goalX) + Math.abs(y - goalY); + } + } + } + else + { + /* + If the Manhattan distance for the parent has already been + calculated, we can take advantage of that and just + add/subtract from their heuristic value. + + Doing this decreases the execution time of the heuristic by about 25%. + */ + value = parent.getHeuristicValue(this); + + int x = parent.getEmptyPiece() % DIMENSION; + int y = parent.getEmptyPiece() / DIMENSION; + + int x2 = state.getEmptyPiece() % DIMENSION; + int y2 = state.getEmptyPiece() / DIMENSION; + + int piece = state.getPiece(x, y); + + if (x2 > x) + { + int targetX = piece % DIMENSION; + + // right + if (targetX > x) + { + value++; + } + else + { + value--; + } + } + else if (x2 < x) + { + int targetX = piece % DIMENSION; + + // left + if (targetX < x) + { + value++; + } + else + { + value--; + } + } + else if (y2 > y) + { + int targetY = piece / DIMENSION; + + // down + if (targetY > y) + { + value++; + } + else + { + value--; + } + } + else + { + int targetY = piece / DIMENSION; + + // up + if (targetY < y) + { + value++; + } + else + { + value--; + } + } + } + + return value; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStar.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStar.java index b43418a291..fc26d1889e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStar.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStar.java @@ -1,106 +1,106 @@ -/* - * Copyright (c) 2018, Lotto - * 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 HOLDER 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.puzzlesolver.solver.pathfinding; - -import java.util.ArrayList; -import java.util.List; -import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; -import net.runelite.client.plugins.puzzlesolver.solver.heuristics.Heuristic; - -/** - * An implementation of the IDA* algorithm. - * - * https://en.wikipedia.org/wiki/Iterative_deepening_A* - */ -public class IDAStar extends Pathfinder -{ - public IDAStar(Heuristic heuristic) - { - super(heuristic); - } - - @Override - public List computePath(PuzzleState root) - { - PuzzleState goalNode = path(root); - - List path = new ArrayList<>(); - - PuzzleState parent = goalNode; - while (parent != null) - { - path.add(0, parent); - parent = parent.getParent(); - } - - return path; - } - - private PuzzleState path(PuzzleState root) - { - int bound = root.getHeuristicValue(getHeuristic()); - - while (true) - { - PuzzleState t = search(root, 0, bound); - - if (t != null) - { - return t; - } - - bound += 1; - } - } - - private PuzzleState search(PuzzleState node, int g, int bound) - { - int h = node.getHeuristicValue(getHeuristic()); - int f = g + h; - - if (f > bound) - { - return null; - } - - if (h == 0) - { - return node; - } - - for (PuzzleState successor : node.computeMoves()) - { - PuzzleState t = search(successor, g + 1, bound); - - if (t != null) - { - return t; - } - } - - return null; - } -} +/* + * Copyright (c) 2018, Lotto + * 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 HOLDER 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.puzzlesolver.solver.pathfinding; + +import java.util.ArrayList; +import java.util.List; +import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; +import net.runelite.client.plugins.puzzlesolver.solver.heuristics.Heuristic; + +/** + * An implementation of the IDA* algorithm. + *

+ * https://en.wikipedia.org/wiki/Iterative_deepening_A* + */ +public class IDAStar extends Pathfinder +{ + public IDAStar(Heuristic heuristic) + { + super(heuristic); + } + + @Override + public List computePath(PuzzleState root) + { + PuzzleState goalNode = path(root); + + List path = new ArrayList<>(); + + PuzzleState parent = goalNode; + while (parent != null) + { + path.add(0, parent); + parent = parent.getParent(); + } + + return path; + } + + private PuzzleState path(PuzzleState root) + { + int bound = root.getHeuristicValue(getHeuristic()); + + while (true) + { + PuzzleState t = search(root, 0, bound); + + if (t != null) + { + return t; + } + + bound += 1; + } + } + + private PuzzleState search(PuzzleState node, int g, int bound) + { + int h = node.getHeuristicValue(getHeuristic()); + int f = g + h; + + if (f > bound) + { + return null; + } + + if (h == 0) + { + return node; + } + + for (PuzzleState successor : node.computeMoves()) + { + PuzzleState t = search(successor, g + 1, bound); + + if (t != null) + { + return t; + } + } + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java index f96b6971bd..97749e048a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java @@ -1,716 +1,729 @@ -/* - * Copyright (c) 2018, Steffen Hauge - * 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.puzzlesolver.solver.pathfinding; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import net.runelite.api.Point; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; -import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; -import net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern; -import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.*; -import net.runelite.client.plugins.puzzlesolver.solver.heuristics.Heuristic; - -public class IDAStarMM extends IDAStar -{ - private PuzzleState currentState; - private List stateList = new ArrayList<>(); - private List> validRowNumbers = new ArrayList<>(); - private List> validColumnNumbers = new ArrayList<>(); - - public IDAStarMM(Heuristic heuristic) - { - super(heuristic); - - //Add valid numbers for rows and columns - validRowNumbers.add(Arrays.asList(0, 1, 2, 3, 4)); - validRowNumbers.add(Arrays.asList(6, 7, 8, 9)); - validColumnNumbers.add(Arrays.asList(5, 10, 15, 20)); - } - - @Override - public List computePath(PuzzleState root) - { - currentState = root; - stateList.add(root); - - List path = new ArrayList<>(); - - //Reduce to 4x5 - solveRow(0); - - //Reduce to 4x4 - solveColumn(); - - //Reduce to 3x4 - solveRow(1); - - //Remove last state - stateList.remove(stateList.size() - 1); - - //Pathfinder for 4x4 - path.addAll(super.computePath(currentState)); - - path.addAll(0, stateList); - - return path; - } - - private void solveRow(int row) - { - for (int i = row; i < DIMENSION; i++) - { - int valTarget = row * DIMENSION + i; - - int valCurrent = currentState.getPiece(i, row); - - if (valCurrent != valTarget) - { - moveTowardsVal(valTarget, i, row, true); - } - } - } - - private void solveColumn() - { - int column = 0; - - for (int i = column + 1; i < DIMENSION; i++) - { - int valTarget = column + i * DIMENSION; - - int valCurrent = currentState.getPiece(column, i); - - if (valCurrent != valTarget) - { - moveTowardsVal(valTarget, column, i, false); - } - } - } - - private void moveTowardsVal(int valTarget, int x, int y, boolean rowMode) - { - //Not in place - boolean reached = false; - - while (currentState.getPiece(x, y) != valTarget) - { - //Find piece location - Point locVal = findPiece(valTarget); - Point locBlank = findPiece(BLANK_TILE_VALUE); - - if (reached) - { - //Swap towards locTarget - if (rowMode) - { - alignTargetX(valTarget, x, y); - swapUpRow(valTarget, x, y); - } - else - { - alignTargetY(valTarget, x, y); - swapLeftColumn(valTarget, x, y); - } - } - else - { - int distX = locVal.getX() - locBlank.getX(); - int distY = locVal.getY() - locBlank.getY(); - int distAbsX = Math.abs(distX); - int distAbsY = Math.abs(distY); - - if (distX == 0) - { - //Same column - if (distAbsY == 1) - { - //Next to - reached = true; - } - else - { - //More than 2 away, move towards on Y-axis - if (distY >= 2) - { - Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); - swap(locBlank, locSwap); - } - else if (distY <= -2) - { - Point locSwap = new Point(locBlank.getX(), locBlank.getY() - 1); - swap(locBlank, locSwap); - } - } - } - else if (distY == 0) - { - //Same row - if (distAbsX == 1) - { - //Next to - reached = true; - } - else - { - //More than 2 away, move towards on X-axis - if (distX >= 2) - { - Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); - swap(locBlank, locSwap); - } - else if (distX <= -2) - { - Point locSwap = new Point(locBlank.getX() - 1, locBlank.getY()); - swap(locBlank, locSwap); - } - } - } - else - { - //Different row and column - if (rowMode) - { - //Check if already correct above - if (locBlank.getY() - 1 == y - && validRowNumbers.get(y).contains(currentState.getPiece(locBlank.getX(), locBlank.getY() - 1)) - && currentState.getPiece(locBlank.getX(), locBlank.getY() - 1) < valTarget - && distY <= -1) - { - //Move forward - Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); - swap(locBlank, locSwap); - continue; - } - - //Move downwards or upwards - if (distY >= 1) - { - Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); - swap(locBlank, locSwap); - } - else if (distY <= -1) - { - Point locSwap = new Point(locBlank.getX(), locBlank.getY() - 1); - swap(locBlank, locSwap); - } - } - else - { - //Check if already correct to the left - if (locBlank.getX() - 1 == x - && validColumnNumbers.get(x).contains(currentState.getPiece(locBlank.getX() - 1, locBlank.getY())) - && currentState.getPiece(locBlank.getX() - 1, locBlank.getY()) < valTarget - && distX <= -1) - { - //Move down - Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); - swap(locBlank, locSwap); - continue; - } - - //Move right or left - if (distX >= 1) - { - Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); - swap(locBlank, locSwap); - } - else if (distX <= -1) - { - Point locSwap = new Point(locBlank.getX() - 1, locBlank.getY()); - swap(locBlank, locSwap); - } - } - } - } - } - } - - private void alignTargetX(int valTarget, int x, int y) - { - Point locVal = findPiece(valTarget); - - //Check if same column - if (locVal.getX() == x) - { - return; - } - - //1 = right, -1 = left - int direction = Integer.signum(x - locVal.getX()); - - while (locVal.getX() != x) - { - locVal = findPiece(valTarget); - Point locBlank = findPiece(BLANK_TILE_VALUE); - - //Check if aligned - if (x - locVal.getX() == 0) - { - break; - } - - if (locVal.getX() == locBlank.getX()) - { - int diff = locBlank.getY() - locVal.getY(); - if (diff == 1) - { - //Below - Point loc1 = new Point(locBlank.getX() + direction, locBlank.getY()); - Point loc2 = new Point(loc1.getX(), loc1.getY() - 1); - - swap(locBlank, loc1); - swap(loc1, loc2); - swap(loc2, locVal); - } - else if (diff == -1) - { - //Above - swap(locBlank, locVal); - } - } - else if (locVal.getY() == locBlank.getY()) - { - int diff = locBlank.getX() - locVal.getX(); - if (diff == 1) - { - //Right - if (direction == 1) - { - swap(locVal, locBlank); - } - else if (direction == -1) - { - //Check space - if (locVal.getY() == DIMENSION - 1) - { - //No space below, use upper rotate - performSwapPattern(locBlank, locVal, ROTATE_LEFT_UP); - } - else - { - //Space below, use lower rotate - performSwapPattern(locBlank, locVal, ROTATE_LEFT_DOWN); - } - } - } - else if (diff == -1) - { - //Left - if (direction == -1) - { - swap(locVal, locBlank); - } - else if (direction == 1) - { - //Check space - if (locVal.getY() == DIMENSION - 1) - { - //No space below, use upper rotate - performSwapPattern(locBlank, locVal, ROTATE_RIGHT_UP); - } - else - { - //Space below, use lower rotate - performSwapPattern(locBlank, locVal, ROTATE_RIGHT_DOWN); - } - } - } - } - } - } - - //Swaps up until inserted into the correct place - private void swapUpRow(int valTarget, int x, int y) - { - Point locVal = findPiece(valTarget); - Point locBlank = findPiece(BLANK_TILE_VALUE); - - //Check if already placed correct - if (locVal.getX() == x && locVal.getY() == y) - { - return; - } - - //Check if simple swap is enough - if (locBlank.getX() == x && locBlank.getY() == y && locVal.getY() - 1 == y) - { - swap(locBlank, locVal); - return; - } - - //Move up - while (true) - { - locVal = findPiece(valTarget); - locBlank = findPiece(BLANK_TILE_VALUE); - - //Check if already placed correct - if (locVal.getX() == x && locVal.getY() == y) - { - return; - } - - if (locVal.getX() == locBlank.getX()) - { - int diff = locBlank.getY() - locVal.getY(); - if (diff == 1) - { - //Below - - //Last piece - if (x == DIMENSION - 1) - { - performSwapPattern(locBlank, locVal, LAST_PIECE_ROW); - return; - } - - performSwapPattern(locBlank, locVal, ROTATE_UP_RIGHT); - } - else if (diff == -1) - { - //Above - swap(locBlank, locVal); - } - } - else if (locVal.getY() == locBlank.getY()) - { - int diff = locBlank.getX() - locVal.getX(); - if (diff == 1) - { - //Right - performSwapPattern(locBlank, locVal, SHUFFLE_UP_RIGHT); - } - else if (diff == -1) - { - //Left - - //Don't remove correct pieces from row - if (locVal.getY() - 1 == y) - { - //Swap blank to below and continue - Point loc1 = new Point(locBlank.getX(), locBlank.getY() + 1); - Point loc2 = new Point(loc1.getX() + 1, loc1.getY()); - - swap(locBlank, loc1); - swap(loc1, loc2); - - continue; - } - - performSwapPattern(locBlank, locVal, SHUFFLE_UP_LEFT); - } - } - } - } - - private void alignTargetY(int valTarget, int x, int y) - { - Point locVal = findPiece(valTarget); - - //Check if same row - if (locVal.getY() == y) - { - return; - } - - //1 = down, -1 = up - int direction = Integer.signum(y - locVal.getY()); - - while (locVal.getY() != y) - { - locVal = findPiece(valTarget); - Point locBlank = findPiece(BLANK_TILE_VALUE); - - //Check if aligned - if (y - locVal.getY() == 0) - { - break; - } - - if (locVal.getY() == locBlank.getY()) - { - int diff = locBlank.getX() - locVal.getX(); - if (diff == 1) - { - //Right - Point loc1 = new Point(locBlank.getX(), locBlank.getY() + direction); - Point loc2 = new Point(loc1.getX() - 1, loc1.getY()); - - swap(locBlank, loc1); - swap(loc1, loc2); - swap(loc2, locVal); - } - else if (diff == -1) - { - //Left - swap(locBlank, locVal); - } - } - else if (locVal.getX() == locBlank.getX()) - { - int diff = locBlank.getY() - locVal.getY(); - if (diff == 1) - { - //Below - if (direction == 1) - { - swap(locVal, locBlank); - } - else if (direction == -1) - { - //Check space - if (locVal.getX() == DIMENSION - 1) - { - //No space to the right, use left rotate - performSwapPattern(locBlank, locVal, ROTATE_UP_LEFT); - } - else - { - //Space to the right, use right rotate - performSwapPattern(locBlank, locVal, ROTATE_UP_RIGHT); - } - } - } - else if (diff == -1) - { - //Above - if (direction == -1) - { - swap(locVal, locBlank); - } - else if (direction == 1) - { - //Check space - if (locVal.getX() == DIMENSION - 1) - { - //No space to the right, use left rotate - performSwapPattern(locBlank, locVal, ROTATE_DOWN_LEFT); - } - else - { - //Space to the right, use right rotate - performSwapPattern(locBlank, locVal, ROTATE_DOWN_RIGHT); - } - } - } - } - } - } - - //Swaps left until inserted into the correct place - private void swapLeftColumn(int valTarget, int x, int y) - { - Point locVal = findPiece(valTarget); - Point locBlank = findPiece(BLANK_TILE_VALUE); - - //Check if already placed correct - if (locVal.getX() == x && locVal.getY() == y) - { - return; - } - - //Check if simple swap is enough - if (locBlank.getX() == x && locBlank.getY() == y && locVal.getX() - 1 == x) - { - swap(locBlank, locVal); - return; - } - - //Move left - while (true) - { - locVal = findPiece(valTarget); - locBlank = findPiece(BLANK_TILE_VALUE); - - //Check if already placed correct - if (locVal.getX() == x && locVal.getY() == y) - { - return; - } - - if (locVal.getX() == locBlank.getX()) - { - int diff = locBlank.getY() - locVal.getY(); - if (diff == 1) - { - //Below - performSwapPattern(locBlank, locVal, SHUFFLE_UP_BELOW); - } - else if (diff == -1) - { - //Above - - //Don't remove correct pices from row - if (locVal.getX() - 1 == x) - { - //Swap blank to right and continue - Point loc1 = new Point(locBlank.getX() + 1, locBlank.getY()); - Point loc2 = new Point(loc1.getX(), loc1.getY() + 1); - - swap(locBlank, loc1); - swap(loc1, loc2); - - continue; - } - - performSwapPattern(locBlank, locVal, SHUFFLE_UP_ABOVE); - } - } - else if (locVal.getY() == locBlank.getY()) - { - int diff = locBlank.getX() - locVal.getX(); - if (diff == 1) - { - //Right - - //Last piece - if (y == DIMENSION - 1) - { - performSwapPattern(locBlank, locVal, LAST_PIECE_COLUMN); - return; - } - - performSwapPattern(locBlank, locVal, ROTATE_LEFT_DOWN); - } - else if (diff == -1) - { - //Left - swap(locBlank, locVal); - } - } - } - } - - private void swap(Point p1, Point p2) - { - PuzzleState newState = currentState.swap(p1.getX(), p1.getY(), p2.getX(), p2.getY()); - - currentState = newState; - stateList.add(newState); - } - - private Point findPiece(int val) - { - for (int x = 0; x < DIMENSION; x++) - { - for (int y = 0; y < DIMENSION; y++) - { - if (currentState.getPiece(x, y) == val) - { - return new Point(x, y); - } - } - } - // This should never happen - throw new IllegalStateException("Piece wasn't found!"); - } - - /** - * Assumes locBlank is first point for swap and locVal is last point for swap - * - * swap(locBlank, loc1); - * swap(loc1, loc2); - * swap(loc2, locVal); - */ - private void performSwapPattern(Point locBlank, Point locVal, PuzzleSwapPattern pattern) - { - int[] offsets; - switch (pattern) - { - case ROTATE_LEFT_UP: - case ROTATE_RIGHT_UP: - case ROTATE_RIGHT_DOWN: - case ROTATE_LEFT_DOWN: - offsets = ROTATE_LEFT_UP.getPoints(); - break; - case ROTATE_UP_LEFT: - case ROTATE_UP_RIGHT: - case ROTATE_DOWN_LEFT: - case ROTATE_DOWN_RIGHT: - offsets = ROTATE_UP_LEFT.getPoints(); - break; - default: - offsets = pattern.getPoints(); - } - - if (offsets == null || offsets.length % 2 == 1) - { - // This should never happen - throw new IllegalStateException("Unexpected points given in pattern!"); - } - - int modX = pattern.getModX(); - int modY = pattern.getModY(); - - ArrayList points = new ArrayList<>(); - - for (int i = 0; i < offsets.length; i += 2) - { - int x = locVal.getX() + modX * offsets[i]; - int y = locVal.getY() + modY * offsets[i + 1]; - - points.add(new Point(x, y)); - } - - // Add locVal as last point - points.add(locVal); - - if (pattern != LAST_PIECE_ROW && pattern != LAST_PIECE_COLUMN) - { - Point start = locBlank; - for (Point p : points) - { - swap(start, p); - start = p; - } - } - else - { - Point loc1 = points.get(0); - Point loc2 = points.get(1); - Point loc3 = points.get(2); - Point loc4 = points.get(3); - - swap(locBlank, locVal); - swap(locVal, loc3); - swap(loc3, loc1); - swap(loc1, loc2); - swap(loc2, locVal); - swap(locVal, loc3); - swap(loc3, loc1); - swap(loc1, loc2); - swap(loc2, locVal); - swap(locVal, locBlank); - swap(locBlank, loc4); - swap(loc4, loc3); - swap(loc3, loc1); - swap(loc1, loc2); - swap(loc2, locVal); - } - } -} +/* + * Copyright (c) 2018, Steffen Hauge + * 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.puzzlesolver.solver.pathfinding; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import net.runelite.api.Point; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.BLANK_TILE_VALUE; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; +import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; +import net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.LAST_PIECE_COLUMN; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.LAST_PIECE_ROW; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_DOWN_LEFT; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_DOWN_RIGHT; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_LEFT_DOWN; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_LEFT_UP; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_RIGHT_DOWN; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_RIGHT_UP; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_UP_LEFT; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.ROTATE_UP_RIGHT; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.SHUFFLE_UP_ABOVE; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.SHUFFLE_UP_BELOW; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.SHUFFLE_UP_LEFT; +import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSwapPattern.SHUFFLE_UP_RIGHT; +import net.runelite.client.plugins.puzzlesolver.solver.heuristics.Heuristic; + +public class IDAStarMM extends IDAStar +{ + private PuzzleState currentState; + private List stateList = new ArrayList<>(); + private List> validRowNumbers = new ArrayList<>(); + private List> validColumnNumbers = new ArrayList<>(); + + public IDAStarMM(Heuristic heuristic) + { + super(heuristic); + + //Add valid numbers for rows and columns + validRowNumbers.add(Arrays.asList(0, 1, 2, 3, 4)); + validRowNumbers.add(Arrays.asList(6, 7, 8, 9)); + validColumnNumbers.add(Arrays.asList(5, 10, 15, 20)); + } + + @Override + public List computePath(PuzzleState root) + { + currentState = root; + stateList.add(root); + + List path = new ArrayList<>(); + + //Reduce to 4x5 + solveRow(0); + + //Reduce to 4x4 + solveColumn(); + + //Reduce to 3x4 + solveRow(1); + + //Remove last state + stateList.remove(stateList.size() - 1); + + //Pathfinder for 4x4 + path.addAll(super.computePath(currentState)); + + path.addAll(0, stateList); + + return path; + } + + private void solveRow(int row) + { + for (int i = row; i < DIMENSION; i++) + { + int valTarget = row * DIMENSION + i; + + int valCurrent = currentState.getPiece(i, row); + + if (valCurrent != valTarget) + { + moveTowardsVal(valTarget, i, row, true); + } + } + } + + private void solveColumn() + { + int column = 0; + + for (int i = column + 1; i < DIMENSION; i++) + { + int valTarget = column + i * DIMENSION; + + int valCurrent = currentState.getPiece(column, i); + + if (valCurrent != valTarget) + { + moveTowardsVal(valTarget, column, i, false); + } + } + } + + private void moveTowardsVal(int valTarget, int x, int y, boolean rowMode) + { + //Not in place + boolean reached = false; + + while (currentState.getPiece(x, y) != valTarget) + { + //Find piece location + Point locVal = findPiece(valTarget); + Point locBlank = findPiece(BLANK_TILE_VALUE); + + if (reached) + { + //Swap towards locTarget + if (rowMode) + { + alignTargetX(valTarget, x, y); + swapUpRow(valTarget, x, y); + } + else + { + alignTargetY(valTarget, x, y); + swapLeftColumn(valTarget, x, y); + } + } + else + { + int distX = locVal.getX() - locBlank.getX(); + int distY = locVal.getY() - locBlank.getY(); + int distAbsX = Math.abs(distX); + int distAbsY = Math.abs(distY); + + if (distX == 0) + { + //Same column + if (distAbsY == 1) + { + //Next to + reached = true; + } + else + { + //More than 2 away, move towards on Y-axis + if (distY >= 2) + { + Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); + swap(locBlank, locSwap); + } + else if (distY <= -2) + { + Point locSwap = new Point(locBlank.getX(), locBlank.getY() - 1); + swap(locBlank, locSwap); + } + } + } + else if (distY == 0) + { + //Same row + if (distAbsX == 1) + { + //Next to + reached = true; + } + else + { + //More than 2 away, move towards on X-axis + if (distX >= 2) + { + Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); + swap(locBlank, locSwap); + } + else if (distX <= -2) + { + Point locSwap = new Point(locBlank.getX() - 1, locBlank.getY()); + swap(locBlank, locSwap); + } + } + } + else + { + //Different row and column + if (rowMode) + { + //Check if already correct above + if (locBlank.getY() - 1 == y + && validRowNumbers.get(y).contains(currentState.getPiece(locBlank.getX(), locBlank.getY() - 1)) + && currentState.getPiece(locBlank.getX(), locBlank.getY() - 1) < valTarget + && distY <= -1) + { + //Move forward + Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); + swap(locBlank, locSwap); + continue; + } + + //Move downwards or upwards + if (distY >= 1) + { + Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); + swap(locBlank, locSwap); + } + else if (distY <= -1) + { + Point locSwap = new Point(locBlank.getX(), locBlank.getY() - 1); + swap(locBlank, locSwap); + } + } + else + { + //Check if already correct to the left + if (locBlank.getX() - 1 == x + && validColumnNumbers.get(x).contains(currentState.getPiece(locBlank.getX() - 1, locBlank.getY())) + && currentState.getPiece(locBlank.getX() - 1, locBlank.getY()) < valTarget + && distX <= -1) + { + //Move down + Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); + swap(locBlank, locSwap); + continue; + } + + //Move right or left + if (distX >= 1) + { + Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); + swap(locBlank, locSwap); + } + else if (distX <= -1) + { + Point locSwap = new Point(locBlank.getX() - 1, locBlank.getY()); + swap(locBlank, locSwap); + } + } + } + } + } + } + + private void alignTargetX(int valTarget, int x, int y) + { + Point locVal = findPiece(valTarget); + + //Check if same column + if (locVal.getX() == x) + { + return; + } + + //1 = right, -1 = left + int direction = Integer.signum(x - locVal.getX()); + + while (locVal.getX() != x) + { + locVal = findPiece(valTarget); + Point locBlank = findPiece(BLANK_TILE_VALUE); + + //Check if aligned + if (x - locVal.getX() == 0) + { + break; + } + + if (locVal.getX() == locBlank.getX()) + { + int diff = locBlank.getY() - locVal.getY(); + if (diff == 1) + { + //Below + Point loc1 = new Point(locBlank.getX() + direction, locBlank.getY()); + Point loc2 = new Point(loc1.getX(), loc1.getY() - 1); + + swap(locBlank, loc1); + swap(loc1, loc2); + swap(loc2, locVal); + } + else if (diff == -1) + { + //Above + swap(locBlank, locVal); + } + } + else if (locVal.getY() == locBlank.getY()) + { + int diff = locBlank.getX() - locVal.getX(); + if (diff == 1) + { + //Right + if (direction == 1) + { + swap(locVal, locBlank); + } + else if (direction == -1) + { + //Check space + if (locVal.getY() == DIMENSION - 1) + { + //No space below, use upper rotate + performSwapPattern(locBlank, locVal, ROTATE_LEFT_UP); + } + else + { + //Space below, use lower rotate + performSwapPattern(locBlank, locVal, ROTATE_LEFT_DOWN); + } + } + } + else if (diff == -1) + { + //Left + if (direction == -1) + { + swap(locVal, locBlank); + } + else if (direction == 1) + { + //Check space + if (locVal.getY() == DIMENSION - 1) + { + //No space below, use upper rotate + performSwapPattern(locBlank, locVal, ROTATE_RIGHT_UP); + } + else + { + //Space below, use lower rotate + performSwapPattern(locBlank, locVal, ROTATE_RIGHT_DOWN); + } + } + } + } + } + } + + //Swaps up until inserted into the correct place + private void swapUpRow(int valTarget, int x, int y) + { + Point locVal = findPiece(valTarget); + Point locBlank = findPiece(BLANK_TILE_VALUE); + + //Check if already placed correct + if (locVal.getX() == x && locVal.getY() == y) + { + return; + } + + //Check if simple swap is enough + if (locBlank.getX() == x && locBlank.getY() == y && locVal.getY() - 1 == y) + { + swap(locBlank, locVal); + return; + } + + //Move up + while (true) + { + locVal = findPiece(valTarget); + locBlank = findPiece(BLANK_TILE_VALUE); + + //Check if already placed correct + if (locVal.getX() == x && locVal.getY() == y) + { + return; + } + + if (locVal.getX() == locBlank.getX()) + { + int diff = locBlank.getY() - locVal.getY(); + if (diff == 1) + { + //Below + + //Last piece + if (x == DIMENSION - 1) + { + performSwapPattern(locBlank, locVal, LAST_PIECE_ROW); + return; + } + + performSwapPattern(locBlank, locVal, ROTATE_UP_RIGHT); + } + else if (diff == -1) + { + //Above + swap(locBlank, locVal); + } + } + else if (locVal.getY() == locBlank.getY()) + { + int diff = locBlank.getX() - locVal.getX(); + if (diff == 1) + { + //Right + performSwapPattern(locBlank, locVal, SHUFFLE_UP_RIGHT); + } + else if (diff == -1) + { + //Left + + //Don't remove correct pieces from row + if (locVal.getY() - 1 == y) + { + //Swap blank to below and continue + Point loc1 = new Point(locBlank.getX(), locBlank.getY() + 1); + Point loc2 = new Point(loc1.getX() + 1, loc1.getY()); + + swap(locBlank, loc1); + swap(loc1, loc2); + + continue; + } + + performSwapPattern(locBlank, locVal, SHUFFLE_UP_LEFT); + } + } + } + } + + private void alignTargetY(int valTarget, int x, int y) + { + Point locVal = findPiece(valTarget); + + //Check if same row + if (locVal.getY() == y) + { + return; + } + + //1 = down, -1 = up + int direction = Integer.signum(y - locVal.getY()); + + while (locVal.getY() != y) + { + locVal = findPiece(valTarget); + Point locBlank = findPiece(BLANK_TILE_VALUE); + + //Check if aligned + if (y - locVal.getY() == 0) + { + break; + } + + if (locVal.getY() == locBlank.getY()) + { + int diff = locBlank.getX() - locVal.getX(); + if (diff == 1) + { + //Right + Point loc1 = new Point(locBlank.getX(), locBlank.getY() + direction); + Point loc2 = new Point(loc1.getX() - 1, loc1.getY()); + + swap(locBlank, loc1); + swap(loc1, loc2); + swap(loc2, locVal); + } + else if (diff == -1) + { + //Left + swap(locBlank, locVal); + } + } + else if (locVal.getX() == locBlank.getX()) + { + int diff = locBlank.getY() - locVal.getY(); + if (diff == 1) + { + //Below + if (direction == 1) + { + swap(locVal, locBlank); + } + else if (direction == -1) + { + //Check space + if (locVal.getX() == DIMENSION - 1) + { + //No space to the right, use left rotate + performSwapPattern(locBlank, locVal, ROTATE_UP_LEFT); + } + else + { + //Space to the right, use right rotate + performSwapPattern(locBlank, locVal, ROTATE_UP_RIGHT); + } + } + } + else if (diff == -1) + { + //Above + if (direction == -1) + { + swap(locVal, locBlank); + } + else if (direction == 1) + { + //Check space + if (locVal.getX() == DIMENSION - 1) + { + //No space to the right, use left rotate + performSwapPattern(locBlank, locVal, ROTATE_DOWN_LEFT); + } + else + { + //Space to the right, use right rotate + performSwapPattern(locBlank, locVal, ROTATE_DOWN_RIGHT); + } + } + } + } + } + } + + //Swaps left until inserted into the correct place + private void swapLeftColumn(int valTarget, int x, int y) + { + Point locVal = findPiece(valTarget); + Point locBlank = findPiece(BLANK_TILE_VALUE); + + //Check if already placed correct + if (locVal.getX() == x && locVal.getY() == y) + { + return; + } + + //Check if simple swap is enough + if (locBlank.getX() == x && locBlank.getY() == y && locVal.getX() - 1 == x) + { + swap(locBlank, locVal); + return; + } + + //Move left + while (true) + { + locVal = findPiece(valTarget); + locBlank = findPiece(BLANK_TILE_VALUE); + + //Check if already placed correct + if (locVal.getX() == x && locVal.getY() == y) + { + return; + } + + if (locVal.getX() == locBlank.getX()) + { + int diff = locBlank.getY() - locVal.getY(); + if (diff == 1) + { + //Below + performSwapPattern(locBlank, locVal, SHUFFLE_UP_BELOW); + } + else if (diff == -1) + { + //Above + + //Don't remove correct pices from row + if (locVal.getX() - 1 == x) + { + //Swap blank to right and continue + Point loc1 = new Point(locBlank.getX() + 1, locBlank.getY()); + Point loc2 = new Point(loc1.getX(), loc1.getY() + 1); + + swap(locBlank, loc1); + swap(loc1, loc2); + + continue; + } + + performSwapPattern(locBlank, locVal, SHUFFLE_UP_ABOVE); + } + } + else if (locVal.getY() == locBlank.getY()) + { + int diff = locBlank.getX() - locVal.getX(); + if (diff == 1) + { + //Right + + //Last piece + if (y == DIMENSION - 1) + { + performSwapPattern(locBlank, locVal, LAST_PIECE_COLUMN); + return; + } + + performSwapPattern(locBlank, locVal, ROTATE_LEFT_DOWN); + } + else if (diff == -1) + { + //Left + swap(locBlank, locVal); + } + } + } + } + + private void swap(Point p1, Point p2) + { + PuzzleState newState = currentState.swap(p1.getX(), p1.getY(), p2.getX(), p2.getY()); + + currentState = newState; + stateList.add(newState); + } + + private Point findPiece(int val) + { + for (int x = 0; x < DIMENSION; x++) + { + for (int y = 0; y < DIMENSION; y++) + { + if (currentState.getPiece(x, y) == val) + { + return new Point(x, y); + } + } + } + // This should never happen + throw new IllegalStateException("Piece wasn't found!"); + } + + /** + * Assumes locBlank is first point for swap and locVal is last point for swap + *

+ * swap(locBlank, loc1); + * swap(loc1, loc2); + * swap(loc2, locVal); + */ + private void performSwapPattern(Point locBlank, Point locVal, PuzzleSwapPattern pattern) + { + int[] offsets; + switch (pattern) + { + case ROTATE_LEFT_UP: + case ROTATE_RIGHT_UP: + case ROTATE_RIGHT_DOWN: + case ROTATE_LEFT_DOWN: + offsets = ROTATE_LEFT_UP.getPoints(); + break; + case ROTATE_UP_LEFT: + case ROTATE_UP_RIGHT: + case ROTATE_DOWN_LEFT: + case ROTATE_DOWN_RIGHT: + offsets = ROTATE_UP_LEFT.getPoints(); + break; + default: + offsets = pattern.getPoints(); + } + + if (offsets == null || offsets.length % 2 == 1) + { + // This should never happen + throw new IllegalStateException("Unexpected points given in pattern!"); + } + + int modX = pattern.getModX(); + int modY = pattern.getModY(); + + ArrayList points = new ArrayList<>(); + + for (int i = 0; i < offsets.length; i += 2) + { + int x = locVal.getX() + modX * offsets[i]; + int y = locVal.getY() + modY * offsets[i + 1]; + + points.add(new Point(x, y)); + } + + // Add locVal as last point + points.add(locVal); + + if (pattern != LAST_PIECE_ROW && pattern != LAST_PIECE_COLUMN) + { + Point start = locBlank; + for (Point p : points) + { + swap(start, p); + start = p; + } + } + else + { + Point loc1 = points.get(0); + Point loc2 = points.get(1); + Point loc3 = points.get(2); + Point loc4 = points.get(3); + + swap(locBlank, locVal); + swap(locVal, loc3); + swap(loc3, loc1); + swap(loc1, loc2); + swap(loc2, locVal); + swap(locVal, loc3); + swap(loc3, loc1); + swap(loc1, loc2); + swap(loc2, locVal); + swap(locVal, locBlank); + swap(locBlank, loc4); + swap(loc4, loc3); + swap(loc3, loc1); + swap(loc1, loc2); + swap(loc2, locVal); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java index 6e709ede39..3156f8061c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java @@ -14,7 +14,6 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; -import javax.inject.Inject; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JLabel; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java index fd61a03229..7607a8022f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java @@ -1,131 +1,132 @@ -/* - * Copyright (c) 2018, Steffen Hauge - * 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.pyramidplunder; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.geom.Area; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.ObjectComposition; -import static net.runelite.api.ObjectID.SPEARTRAP_21280; -import static net.runelite.api.ObjectID.TOMB_DOOR_20948; -import static net.runelite.api.ObjectID.TOMB_DOOR_20949; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -public class PyramidPlunderOverlay extends Overlay -{ - private static final int MAX_DISTANCE = 2400; - private static final Color COLOR_DOOR = Color.GREEN; - private static final Color COLOR_SPEAR_TRAP = Color.ORANGE; - - private final Client client; - private final PyramidPlunderPlugin plugin; - private final PyramidPlunderConfig config; - - @Inject - private PyramidPlunderOverlay(Client client, PyramidPlunderPlugin plugin, PyramidPlunderConfig config) - { - this.client = client; - this.plugin = plugin; - this.config = config; - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - } - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isInGame()) - { - return null; - } - - LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation(); - Point mousePosition = client.getMouseCanvasPosition(); - - plugin.getObstacles().forEach((object, tile) -> - { - if (Obstacles.WALL_OBSTACLE_IDS.contains(object.getId()) && !config.highlightDoors() || - Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId()) && !config.highlightSpearTrap()) - { - return; - } - - if (tile.getPlane() == client.getPlane() && - object.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) - { - int objectID = object.getId(); - if (Obstacles.WALL_OBSTACLE_IDS.contains(object.getId())) - { - //Impostor - ObjectComposition comp = client.getObjectDefinition(objectID); - ObjectComposition impostor = comp.getImpostor(); - - if (impostor == null) - { - return; - } - objectID = impostor.getId(); - } - - Area objectClickbox = object.getClickbox(); - if (objectClickbox != null) - { - Color configColor = Color.GREEN; - switch (objectID) - { - case SPEARTRAP_21280: - configColor = COLOR_SPEAR_TRAP; - break; - case TOMB_DOOR_20948: - case TOMB_DOOR_20949: - configColor = COLOR_DOOR; - break; - } - - if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) - { - graphics.setColor(configColor.darker()); - } - else - { - graphics.setColor(configColor); - } - - graphics.draw(objectClickbox); - graphics.setColor(new Color(configColor.getRed(), configColor.getGreen(), configColor.getBlue(), 50)); - graphics.fill(objectClickbox); - } - } - }); - - return null; - } -} +/* + * Copyright (c) 2018, Steffen Hauge + * 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.pyramidplunder; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Area; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.ObjectComposition; +import static net.runelite.api.ObjectID.SPEARTRAP_21280; +import static net.runelite.api.ObjectID.TOMB_DOOR_20948; +import static net.runelite.api.ObjectID.TOMB_DOOR_20949; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +public class PyramidPlunderOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2400; + private static final Color COLOR_DOOR = Color.GREEN; + private static final Color COLOR_SPEAR_TRAP = Color.ORANGE; + + private final Client client; + private final PyramidPlunderPlugin plugin; + private final PyramidPlunderConfig config; + + @Inject + private PyramidPlunderOverlay(Client client, PyramidPlunderPlugin plugin, PyramidPlunderConfig config) + { + this.client = client; + this.plugin = plugin; + this.config = config; + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isInGame()) + { + return null; + } + + LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation(); + Point mousePosition = client.getMouseCanvasPosition(); + + plugin.getObstacles().forEach((object, tile) -> + { + if (Obstacles.WALL_OBSTACLE_IDS.contains(object.getId()) && !config.highlightDoors() || + Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId()) && !config.highlightSpearTrap()) + { + return; + } + + if (tile.getPlane() == client.getPlane() && + object.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) + { + int objectID = object.getId(); + if (Obstacles.WALL_OBSTACLE_IDS.contains(object.getId())) + { + //Impostor + ObjectComposition comp = client.getObjectDefinition(objectID); + ObjectComposition impostor = comp.getImpostor(); + + if (impostor == null) + { + return; + } + objectID = impostor.getId(); + } + + Area objectClickbox = object.getClickbox(); + if (objectClickbox != null) + { + Color configColor = Color.GREEN; + switch (objectID) + { + case SPEARTRAP_21280: + configColor = COLOR_SPEAR_TRAP; + break; + case TOMB_DOOR_20948: + case TOMB_DOOR_20949: + configColor = COLOR_DOOR; + break; + } + + if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) + { + graphics.setColor(configColor.darker()); + } + else + { + graphics.setColor(configColor); + } + + graphics.draw(objectClickbox); + graphics.setColor(new Color(configColor.getRed(), configColor.getGreen(), configColor.getBlue(), 50)); + graphics.fill(objectClickbox); + } + } + }); + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java index 1ada10d2bc..31beb64cd8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java @@ -1,273 +1,269 @@ -/* - * Copyright (c) 2018, Steffen Hauge - * 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.pyramidplunder; - -import com.google.common.eventbus.Subscribe; -import com.google.inject.Provides; -import java.time.temporal.ChronoUnit; -import java.util.HashMap; -import java.util.Map; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.Client; -import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE; -import net.runelite.api.Player; -import net.runelite.api.Tile; -import net.runelite.api.TileObject; -import net.runelite.api.Varbits; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameObjectChanged; -import net.runelite.api.events.GameObjectDespawned; -import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.VarbitChanged; -import net.runelite.api.events.WallObjectChanged; -import net.runelite.api.events.WallObjectDespawned; -import net.runelite.api.events.WallObjectSpawned; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; - -@PluginDescriptor( - name = "PyramidPlunder", - description = "Highlights doors and spear traps in pyramid plunder and adds a numerical timer", - tags = {"pyramidplunder", "pyramid", "plunder", "overlay", "skilling", "thieving"}, - type = PluginType.UTILITY, - enabledByDefault = false -) - -public class PyramidPlunderPlugin extends Plugin -{ - private static final int PYRAMIND_PLUNDER_REGION_ID = 7749; - private static final int PYRAMIND_PLUNDER_TIMER_MAX = 500; - private static final double GAMETICK_SECOND = 0.6; - - @Getter - private final Map obstacles = new HashMap<>(); - - @Inject - private Client client; - - @Inject - private PyramidPlunderConfig config; - - @Inject - private InfoBoxManager infoBoxManager; - - @Inject - private ItemManager itemManager; - - @Inject - private OverlayManager overlayManager; - - @Inject - private PyramidPlunderOverlay pyramidPlunderOverlay; - - @Getter - private boolean isInGame; - - private int pyramidTimer = 0; - - @Provides - PyramidPlunderConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(PyramidPlunderConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(pyramidPlunderOverlay); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(pyramidPlunderOverlay); - obstacles.clear(); - reset(); - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (!config.showTimer()) - { - removeTimer(); - } - - if (config.showTimer() && isInGame) - { - int remainingTime = PYRAMIND_PLUNDER_TIMER_MAX - pyramidTimer; - - if (remainingTime >= 2) - { - double timeInSeconds = remainingTime * GAMETICK_SECOND; - showTimer((int)timeInSeconds, ChronoUnit.SECONDS); - } - } - } - - private void removeTimer() - { - infoBoxManager.removeIf(infoBox -> infoBox instanceof PyramidPlunderTimer); - } - - private void showTimer() - { - showTimer(5, ChronoUnit.MINUTES); - } - - private void showTimer(int period, ChronoUnit chronoUnit) - { - removeTimer(); - infoBoxManager.addInfoBox(new PyramidPlunderTimer(this, itemManager.getImage(PHARAOHS_SCEPTRE), period, chronoUnit)); - } - - @Subscribe - public void onGameStateChange(GameStateChanged event) - { - switch (event.getGameState()) - { - case HOPPING: - case LOGIN_SCREEN: - reset(); - break; - case LOADING: - obstacles.clear(); - case LOGGED_IN: - if (!isInRegion()) - { - reset(); - } - break; - } - } - - private boolean isInRegion() - { - Player local = client.getLocalPlayer(); - if (local == null) - { - return false; - } - - WorldPoint location = local.getWorldLocation(); - if (location.getRegionID() != PYRAMIND_PLUNDER_REGION_ID) - { - return false; - } - - return true; - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - int lastValue = pyramidTimer; - pyramidTimer = client.getVar(Varbits.PYRAMID_PLUNDER_TIMER); - - if (lastValue == pyramidTimer) - { - return; - } - - if (pyramidTimer == 0) - { - reset(); - } - if (pyramidTimer == 1) - { - isInGame = true; - if (config.showTimer()) - { - showTimer(); - } - } - } - - private void reset() - { - isInGame = false; - removeTimer(); - } - - @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) - { - onTileObject(event.getTile(), null, event.getGameObject()); - } - - @Subscribe - public void onGameObjectChanged(GameObjectChanged event) - { - onTileObject(event.getTile(), event.getPrevious(), event.getGameObject()); - } - - @Subscribe - public void onGameObjectDeSpawned(GameObjectDespawned event) - { - onTileObject(event.getTile(), event.getGameObject(), null); - } - - @Subscribe - public void onWallObjectSpawned(WallObjectSpawned event) - { - onTileObject(event.getTile(), null, event.getWallObject()); - } - - @Subscribe - public void onWallObjectChanged(WallObjectChanged event) - { - onTileObject(event.getTile(), event.getPrevious(), event.getWallObject()); - } - - @Subscribe - public void onWallObjectDeSpawned(WallObjectDespawned event) - { - onTileObject(event.getTile(), event.getWallObject(), null); - } - - private void onTileObject(Tile tile, TileObject oldObject, TileObject newObject) - { - obstacles.remove(oldObject); - - if (newObject == null) - { - return; - } - - if (Obstacles.WALL_OBSTACLE_IDS.contains(newObject.getId()) || - Obstacles.TRAP_OBSTACLE_IDS.contains(newObject.getId())) - { - obstacles.put(newObject, tile); - } - } -} +/* + * Copyright (c) 2018, Steffen Hauge + * 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.pyramidplunder; + +import com.google.common.eventbus.Subscribe; +import com.google.inject.Provides; +import java.time.temporal.ChronoUnit; +import java.util.HashMap; +import java.util.Map; +import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.Client; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE; +import net.runelite.api.Player; +import net.runelite.api.Tile; +import net.runelite.api.TileObject; +import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameObjectChanged; +import net.runelite.api.events.GameObjectDespawned; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.events.WallObjectChanged; +import net.runelite.api.events.WallObjectDespawned; +import net.runelite.api.events.WallObjectSpawned; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; + +@PluginDescriptor( + name = "PyramidPlunder", + description = "Highlights doors and spear traps in pyramid plunder and adds a numerical timer", + tags = {"pyramidplunder", "pyramid", "plunder", "overlay", "skilling", "thieving"}, + type = PluginType.UTILITY, + enabledByDefault = false +) + +public class PyramidPlunderPlugin extends Plugin +{ + private static final int PYRAMIND_PLUNDER_REGION_ID = 7749; + private static final int PYRAMIND_PLUNDER_TIMER_MAX = 500; + private static final double GAMETICK_SECOND = 0.6; + + @Getter + private final Map obstacles = new HashMap<>(); + + @Inject + private Client client; + + @Inject + private PyramidPlunderConfig config; + + @Inject + private InfoBoxManager infoBoxManager; + + @Inject + private ItemManager itemManager; + + @Inject + private OverlayManager overlayManager; + + @Inject + private PyramidPlunderOverlay pyramidPlunderOverlay; + + @Getter + private boolean isInGame; + + private int pyramidTimer = 0; + + @Provides + PyramidPlunderConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(PyramidPlunderConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(pyramidPlunderOverlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(pyramidPlunderOverlay); + obstacles.clear(); + reset(); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!config.showTimer()) + { + removeTimer(); + } + + if (config.showTimer() && isInGame) + { + int remainingTime = PYRAMIND_PLUNDER_TIMER_MAX - pyramidTimer; + + if (remainingTime >= 2) + { + double timeInSeconds = remainingTime * GAMETICK_SECOND; + showTimer((int) timeInSeconds, ChronoUnit.SECONDS); + } + } + } + + private void removeTimer() + { + infoBoxManager.removeIf(infoBox -> infoBox instanceof PyramidPlunderTimer); + } + + private void showTimer() + { + showTimer(5, ChronoUnit.MINUTES); + } + + private void showTimer(int period, ChronoUnit chronoUnit) + { + removeTimer(); + infoBoxManager.addInfoBox(new PyramidPlunderTimer(this, itemManager.getImage(PHARAOHS_SCEPTRE), period, chronoUnit)); + } + + @Subscribe + public void onGameStateChange(GameStateChanged event) + { + switch (event.getGameState()) + { + case HOPPING: + case LOGIN_SCREEN: + reset(); + break; + case LOADING: + obstacles.clear(); + case LOGGED_IN: + if (!isInRegion()) + { + reset(); + } + break; + } + } + + private boolean isInRegion() + { + Player local = client.getLocalPlayer(); + if (local == null) + { + return false; + } + + WorldPoint location = local.getWorldLocation(); + return location.getRegionID() == PYRAMIND_PLUNDER_REGION_ID; + + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + int lastValue = pyramidTimer; + pyramidTimer = client.getVar(Varbits.PYRAMID_PLUNDER_TIMER); + + if (lastValue == pyramidTimer) + { + return; + } + + if (pyramidTimer == 0) + { + reset(); + } + if (pyramidTimer == 1) + { + isInGame = true; + if (config.showTimer()) + { + showTimer(); + } + } + } + + private void reset() + { + isInGame = false; + removeTimer(); + } + + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) + { + onTileObject(event.getTile(), null, event.getGameObject()); + } + + @Subscribe + public void onGameObjectChanged(GameObjectChanged event) + { + onTileObject(event.getTile(), event.getPrevious(), event.getGameObject()); + } + + @Subscribe + public void onGameObjectDeSpawned(GameObjectDespawned event) + { + onTileObject(event.getTile(), event.getGameObject(), null); + } + + @Subscribe + public void onWallObjectSpawned(WallObjectSpawned event) + { + onTileObject(event.getTile(), null, event.getWallObject()); + } + + @Subscribe + public void onWallObjectChanged(WallObjectChanged event) + { + onTileObject(event.getTile(), event.getPrevious(), event.getWallObject()); + } + + @Subscribe + public void onWallObjectDeSpawned(WallObjectDespawned event) + { + onTileObject(event.getTile(), event.getWallObject(), null); + } + + private void onTileObject(Tile tile, TileObject oldObject, TileObject newObject) + { + obstacles.remove(oldObject); + + if (newObject == null) + { + return; + } + + if (Obstacles.WALL_OBSTACLE_IDS.contains(newObject.getId()) || + Obstacles.TRAP_OBSTACLE_IDS.contains(newObject.getId())) + { + obstacles.put(newObject, tile); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/cooksassistant/CooksAssistant.java b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/cooksassistant/CooksAssistant.java index da55e5662e..4905524600 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/cooksassistant/CooksAssistant.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/cooksassistant/CooksAssistant.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2019, Trevor - * 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.questhelper.quests.cooksassistant; - -import java.util.HashMap; -import java.util.Map; -import net.runelite.api.ItemID; -import net.runelite.api.NpcID; -import net.runelite.api.Quest; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.plugins.questhelper.ItemRequirement; -import net.runelite.client.plugins.questhelper.QuestHelper; -import net.runelite.client.plugins.questhelper.steps.NpcTalkStep; -import net.runelite.client.plugins.questhelper.steps.QuestStep; -import net.runelite.client.plugins.questhelper.QuestDescriptor; - -@QuestDescriptor( - quest = Quest.COOKS_ASSISTANT -) -public class CooksAssistant extends QuestHelper -{ - @Override - protected Map loadSteps() - { - Map steps = new HashMap<>(); - - steps.put(0, new NpcTalkStep(this, NpcID.COOK_4626, new WorldPoint(3206, 3214, 0), - "Give the Cook in Lumbridge Castle's kitchen the required items to finish the quest.", - new ItemRequirement(ItemID.BUCKET_OF_MILK), new ItemRequirement(ItemID.POT_OF_FLOUR), - new ItemRequirement(ItemID.EGG))); - - steps.put(1, steps.get(0)); - - return steps; - } +/* + * Copyright (c) 2019, Trevor + * 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.questhelper.quests.cooksassistant; + +import java.util.HashMap; +import java.util.Map; +import net.runelite.api.ItemID; +import net.runelite.api.NpcID; +import net.runelite.api.Quest; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.plugins.questhelper.ItemRequirement; +import net.runelite.client.plugins.questhelper.QuestDescriptor; +import net.runelite.client.plugins.questhelper.QuestHelper; +import net.runelite.client.plugins.questhelper.steps.NpcTalkStep; +import net.runelite.client.plugins.questhelper.steps.QuestStep; + +@QuestDescriptor( + quest = Quest.COOKS_ASSISTANT +) +public class CooksAssistant extends QuestHelper +{ + @Override + protected Map loadSteps() + { + Map steps = new HashMap<>(); + + steps.put(0, new NpcTalkStep(this, NpcID.COOK_4626, new WorldPoint(3206, 3214, 0), + "Give the Cook in Lumbridge Castle's kitchen the required items to finish the quest.", + new ItemRequirement(ItemID.BUCKET_OF_MILK), new ItemRequirement(ItemID.POT_OF_FLOUR), + new ItemRequirement(ItemID.EGG))); + + steps.put(1, steps.get(0)); + + return steps; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/impcatcher/ImpCatcher.java b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/impcatcher/ImpCatcher.java index 666fe7ea5f..8083582671 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/impcatcher/ImpCatcher.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/impcatcher/ImpCatcher.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2019, Trevor - * 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.questhelper.quests.impcatcher; - -import java.util.HashMap; -import java.util.Map; -import net.runelite.api.ItemID; -import net.runelite.api.NpcID; -import net.runelite.api.Quest; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.plugins.questhelper.ItemRequirement; -import net.runelite.client.plugins.questhelper.QuestHelper; -import net.runelite.client.plugins.questhelper.steps.NpcTalkStep; -import net.runelite.client.plugins.questhelper.steps.QuestStep; -import net.runelite.client.plugins.questhelper.QuestDescriptor; - -@QuestDescriptor( - quest = Quest.IMP_CATCHER -) -public class ImpCatcher extends QuestHelper -{ - @Override - protected Map loadSteps() - { - Map steps = new HashMap<>(); - - steps.put(0, new NpcTalkStep(this, NpcID.WIZARD_MIZGOG, new WorldPoint(3103, 3163, 2), - "Talk to Wizard Mizgog on the top floor of the Wizards' Tower with the required items to finish the quest.", - new ItemRequirement(ItemID.BLACK_BEAD), new ItemRequirement(ItemID.WHITE_BEAD), - new ItemRequirement(ItemID.RED_BEAD), new ItemRequirement(ItemID.YELLOW_BEAD))); - - steps.put(1, steps.get(0)); - - return steps; - } -} +/* + * Copyright (c) 2019, Trevor + * 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.questhelper.quests.impcatcher; + +import java.util.HashMap; +import java.util.Map; +import net.runelite.api.ItemID; +import net.runelite.api.NpcID; +import net.runelite.api.Quest; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.plugins.questhelper.ItemRequirement; +import net.runelite.client.plugins.questhelper.QuestDescriptor; +import net.runelite.client.plugins.questhelper.QuestHelper; +import net.runelite.client.plugins.questhelper.steps.NpcTalkStep; +import net.runelite.client.plugins.questhelper.steps.QuestStep; + +@QuestDescriptor( + quest = Quest.IMP_CATCHER +) +public class ImpCatcher extends QuestHelper +{ + @Override + protected Map loadSteps() + { + Map steps = new HashMap<>(); + + steps.put(0, new NpcTalkStep(this, NpcID.WIZARD_MIZGOG, new WorldPoint(3103, 3163, 2), + "Talk to Wizard Mizgog on the top floor of the Wizards' Tower with the required items to finish the quest.", + new ItemRequirement(ItemID.BLACK_BEAD), new ItemRequirement(ItemID.WHITE_BEAD), + new ItemRequirement(ItemID.RED_BEAD), new ItemRequirement(ItemID.YELLOW_BEAD))); + + steps.put(1, steps.get(0)); + + return steps; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/xmarksthespot/XMarksTheSpot.java b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/xmarksthespot/XMarksTheSpot.java index e18fab85e0..f6b98a2e0d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/xmarksthespot/XMarksTheSpot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/quests/xmarksthespot/XMarksTheSpot.java @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2019, Trevor - * 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.questhelper.quests.xmarksthespot; - -import java.util.HashMap; -import java.util.Map; -import net.runelite.api.ItemID; -import net.runelite.api.NpcID; -import net.runelite.api.Quest; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.plugins.questhelper.ItemRequirement; -import net.runelite.client.plugins.questhelper.QuestHelper; -import net.runelite.client.plugins.questhelper.steps.DigStep; -import net.runelite.client.plugins.questhelper.steps.NpcTalkStep; -import net.runelite.client.plugins.questhelper.steps.QuestStep; -import net.runelite.client.plugins.questhelper.QuestDescriptor; - -@QuestDescriptor( - quest = Quest.X_MARKS_THE_SPOT -) -public class XMarksTheSpot extends QuestHelper -{ - @Override - protected Map loadSteps() - { - Map steps = new HashMap<>(); - - steps.put(0, new NpcTalkStep(this, NpcID.VEOS_8484, new WorldPoint(3228, 3242, 0), - "Talk to Veos in The Sheared Ram pub in Lumbridge to start the quest.")); - - steps.put(1, steps.get(0)); - - steps.put(2, new DigStep(this, new WorldPoint(3230, 3209, 0), - "Dig north of Bob's Brilliant Axes, on the west side of the plant against the wall of his house.", - new ItemRequirement(ItemID.TREASURE_SCROLL))); - - steps.put(3, new DigStep(this, new WorldPoint(3203, 3212, 0), - "Dig behind Lumbridge Castle, just outside the kitchen door.", - new ItemRequirement(ItemID.TREASURE_SCROLL_23068))); - - steps.put(4, new DigStep(this, new WorldPoint(3109, 3264, 0), - "Dig north-west of the Draynor Village jail, just by the wheat farm.", - new ItemRequirement(ItemID.MYSTERIOUS_ORB_23069))); - - steps.put(5, new DigStep(this, new WorldPoint(3078, 3259, 0), - "Dig in the pig pen just west where Martin the Master Gardener is.", - new ItemRequirement(ItemID.TREASURE_SCROLL_23070))); - - steps.put(6, new NpcTalkStep(this, NpcID.VEOS_8484, new WorldPoint(3054, 3245, 0), - "Talk to Veos directly south of the Rusty Anchor Inn in Port Sarim to finish the quest.", - new ItemRequirement(ItemID.ANCIENT_CASKET))); - - steps.put(7, new NpcTalkStep(this, NpcID.VEOS_8484, new WorldPoint(3054, 3245, 0), - "Talk to Veos directly south of the Rusty Anchor Inn in Port Sarim to finish the quest.")); - - return steps; - } -} +/* + * Copyright (c) 2019, Trevor + * 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.questhelper.quests.xmarksthespot; + +import java.util.HashMap; +import java.util.Map; +import net.runelite.api.ItemID; +import net.runelite.api.NpcID; +import net.runelite.api.Quest; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.plugins.questhelper.ItemRequirement; +import net.runelite.client.plugins.questhelper.QuestDescriptor; +import net.runelite.client.plugins.questhelper.QuestHelper; +import net.runelite.client.plugins.questhelper.steps.DigStep; +import net.runelite.client.plugins.questhelper.steps.NpcTalkStep; +import net.runelite.client.plugins.questhelper.steps.QuestStep; + +@QuestDescriptor( + quest = Quest.X_MARKS_THE_SPOT +) +public class XMarksTheSpot extends QuestHelper +{ + @Override + protected Map loadSteps() + { + Map steps = new HashMap<>(); + + steps.put(0, new NpcTalkStep(this, NpcID.VEOS_8484, new WorldPoint(3228, 3242, 0), + "Talk to Veos in The Sheared Ram pub in Lumbridge to start the quest.")); + + steps.put(1, steps.get(0)); + + steps.put(2, new DigStep(this, new WorldPoint(3230, 3209, 0), + "Dig north of Bob's Brilliant Axes, on the west side of the plant against the wall of his house.", + new ItemRequirement(ItemID.TREASURE_SCROLL))); + + steps.put(3, new DigStep(this, new WorldPoint(3203, 3212, 0), + "Dig behind Lumbridge Castle, just outside the kitchen door.", + new ItemRequirement(ItemID.TREASURE_SCROLL_23068))); + + steps.put(4, new DigStep(this, new WorldPoint(3109, 3264, 0), + "Dig north-west of the Draynor Village jail, just by the wheat farm.", + new ItemRequirement(ItemID.MYSTERIOUS_ORB_23069))); + + steps.put(5, new DigStep(this, new WorldPoint(3078, 3259, 0), + "Dig in the pig pen just west where Martin the Master Gardener is.", + new ItemRequirement(ItemID.TREASURE_SCROLL_23070))); + + steps.put(6, new NpcTalkStep(this, NpcID.VEOS_8484, new WorldPoint(3054, 3245, 0), + "Talk to Veos directly south of the Rusty Anchor Inn in Port Sarim to finish the quest.", + new ItemRequirement(ItemID.ANCIENT_CASKET))); + + steps.put(7, new NpcTalkStep(this, NpcID.VEOS_8484, new WorldPoint(3054, 3245, 0), + "Talk to Veos directly south of the Rusty Anchor Inn in Port Sarim to finish the quest.")); + + return steps; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/steps/NpcTalkStep.java b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/steps/NpcTalkStep.java index a42b4c7bf9..c5e87854c2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/steps/NpcTalkStep.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/questhelper/steps/NpcTalkStep.java @@ -1,161 +1,158 @@ -/* - * Copyright (c) 2019, Trevor - * 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.questhelper.steps; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.NPC; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.NpcDespawned; -import net.runelite.api.events.NpcSpawned; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.questhelper.ItemRequirement; -import net.runelite.client.plugins.questhelper.QuestHelper; -import net.runelite.client.plugins.questhelper.QuestHelperPlugin; -import net.runelite.client.plugins.questhelper.QuestHelperWorldMapPoint; -import static net.runelite.client.plugins.questhelper.QuestHelperWorldOverlay.IMAGE_Z_OFFSET; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; - -public class NpcTalkStep extends QuestStep -{ - @Inject - protected Client client; - - @Inject - protected ItemManager itemManager; - - @Inject - protected WorldMapPointManager worldMapPointManager; - - private int npcID; - private WorldPoint worldPoint; - private List npcsToHighlight = new ArrayList<>(); - List itemRequirements; - - public NpcTalkStep(QuestHelper questHelper, int npcID, WorldPoint worldPoint, String text, ItemRequirement... itemRequirements) - { - super(questHelper, text); - this.npcID = npcID; - this.worldPoint = worldPoint; - this.itemRequirements = Arrays.asList(itemRequirements); - } - - @Override - public void startUp() throws Exception - { - for (NPC npc : client.getNpcs()) - { - if (npcID == npc.getId()) - { - npcsToHighlight.add(npc); - } - } - worldMapPointManager.add(new QuestHelperWorldMapPoint(worldPoint, getQuestImage())); - } - - @Override - public void shutDown() throws Exception - { - npcsToHighlight.clear(); - worldMapPointManager.removeIf(QuestHelperWorldMapPoint.class::isInstance); - } - - @Subscribe - public void onNpcSpawned(NpcSpawned event) - { - if (event.getNpc().getId() == npcID) - { - npcsToHighlight.add(event.getNpc()); - } - } - - @Subscribe - public void onNpcDespawned(NpcDespawned event) - { - if (npcsToHighlight.contains(event.getNpc())) - { - npcsToHighlight.remove(event.getNpc()); - } - } - - @Override - public void makeOverlayHint(PanelComponent panelComponent, QuestHelperPlugin plugin) - { - super.makeOverlayHint(panelComponent, plugin); - - if (itemRequirements.isEmpty()) - { - return; - } - - panelComponent.getChildren().add(LineComponent.builder().left("Required Items:").build()); - for (ItemRequirement itemRequirement : itemRequirements) - { - String text = itemRequirement.getQuantity() + " x " + itemManager.getItemComposition(itemRequirement.getId()).getName(); - Color color; - if (itemRequirement.check(client)) - { - color = Color.GREEN; - } - else - { - color = Color.RED; - } - panelComponent.getChildren().add(LineComponent.builder() - .left(text) - .leftColor(color) - .build()); - } - } - - @Override - public void makeWorldOverlayHint(Graphics2D graphics, QuestHelperPlugin plugin) - { - if (!worldPoint.isInScene(client)) - { - return; - } - - if (npcsToHighlight.isEmpty()) - { - return; - } - - for (NPC npc : npcsToHighlight) - { - OverlayUtil.renderActorOverlayImage(graphics, npc, getQuestImage(), Color.CYAN, IMAGE_Z_OFFSET); - } - - } -} +/* + * Copyright (c) 2019, Trevor + * 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.questhelper.steps; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.NpcDespawned; +import net.runelite.api.events.NpcSpawned; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.questhelper.ItemRequirement; +import net.runelite.client.plugins.questhelper.QuestHelper; +import net.runelite.client.plugins.questhelper.QuestHelperPlugin; +import net.runelite.client.plugins.questhelper.QuestHelperWorldMapPoint; +import static net.runelite.client.plugins.questhelper.QuestHelperWorldOverlay.IMAGE_Z_OFFSET; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; + +public class NpcTalkStep extends QuestStep +{ + @Inject + protected Client client; + + @Inject + protected ItemManager itemManager; + + @Inject + protected WorldMapPointManager worldMapPointManager; + + private int npcID; + private WorldPoint worldPoint; + private List npcsToHighlight = new ArrayList<>(); + List itemRequirements; + + public NpcTalkStep(QuestHelper questHelper, int npcID, WorldPoint worldPoint, String text, ItemRequirement... itemRequirements) + { + super(questHelper, text); + this.npcID = npcID; + this.worldPoint = worldPoint; + this.itemRequirements = Arrays.asList(itemRequirements); + } + + @Override + public void startUp() throws Exception + { + for (NPC npc : client.getNpcs()) + { + if (npcID == npc.getId()) + { + npcsToHighlight.add(npc); + } + } + worldMapPointManager.add(new QuestHelperWorldMapPoint(worldPoint, getQuestImage())); + } + + @Override + public void shutDown() throws Exception + { + npcsToHighlight.clear(); + worldMapPointManager.removeIf(QuestHelperWorldMapPoint.class::isInstance); + } + + @Subscribe + public void onNpcSpawned(NpcSpawned event) + { + if (event.getNpc().getId() == npcID) + { + npcsToHighlight.add(event.getNpc()); + } + } + + @Subscribe + public void onNpcDespawned(NpcDespawned event) + { + npcsToHighlight.remove(event.getNpc()); + } + + @Override + public void makeOverlayHint(PanelComponent panelComponent, QuestHelperPlugin plugin) + { + super.makeOverlayHint(panelComponent, plugin); + + if (itemRequirements.isEmpty()) + { + return; + } + + panelComponent.getChildren().add(LineComponent.builder().left("Required Items:").build()); + for (ItemRequirement itemRequirement : itemRequirements) + { + String text = itemRequirement.getQuantity() + " x " + itemManager.getItemComposition(itemRequirement.getId()).getName(); + Color color; + if (itemRequirement.check(client)) + { + color = Color.GREEN; + } + else + { + color = Color.RED; + } + panelComponent.getChildren().add(LineComponent.builder() + .left(text) + .leftColor(color) + .build()); + } + } + + @Override + public void makeWorldOverlayHint(Graphics2D graphics, QuestHelperPlugin plugin) + { + if (!worldPoint.isInScene(client)) + { + return; + } + + if (npcsToHighlight.isEmpty()) + { + return; + } + + for (NPC npc : npcsToHighlight) + { + OverlayUtil.renderActorOverlayImage(graphics, npc, getQuestImage(), Color.CYAN, IMAGE_Z_OFFSET); + } + + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java index 2ebf2a4318..20871956d9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java @@ -1,398 +1,398 @@ -/* - * Copyright (c) 2019 Spudjb - * 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.questlist; - -import com.google.common.collect.ImmutableList; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.ScriptID; -import net.runelite.api.SoundEffectID; -import net.runelite.api.SpriteID; -import net.runelite.api.VarClientInt; -import net.runelite.api.Varbits; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.events.VarClientIntChanged; -import net.runelite.api.events.VarbitChanged; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.api.widgets.WidgetPositionMode; -import net.runelite.api.widgets.WidgetType; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.chatbox.ChatboxPanelManager; -import net.runelite.client.game.chatbox.ChatboxTextInput; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.util.Text; -import javax.inject.Inject; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.EnumMap; -import java.util.List; -import java.util.stream.Collectors; - -@PluginDescriptor( - name = "Quest List", - description = "Adds searching and filtering to the quest list" -) -public class QuestListPlugin extends Plugin -{ - private static final int ENTRY_PADDING = 8; - private static final List QUEST_HEADERS = ImmutableList.of("Free Quests", "Members' Quests", "Miniquests"); - - private static final String MENU_OPEN = "Open"; - private static final String MENU_CLOSE = "Close"; - - private static final String MENU_TOGGLE = "Toggle"; - - private static final String MENU_SEARCH = "Search"; - private static final String MENU_SHOW = "Show"; - - @Inject - private Client client; - - @Inject - private ChatboxPanelManager chatboxPanelManager; - - @Inject - private ClientThread clientThread; - - private ChatboxTextInput searchInput; - private Widget questSearchButton; - private Widget questHideButton; - - private EnumMap> questSet; - - private QuestState currentFilterState; - - @Subscribe - public void onGameStateChanged(GameStateChanged e) - { - if (e.getGameState() == GameState.LOGGING_IN) - { - currentFilterState = QuestState.ALL; - } - } - - @Subscribe - public void onScriptCallbackEvent(ScriptCallbackEvent event) - { - if (!event.getEventName().equals("questProgressUpdated")) - { - return; - } - - Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX); - if (header != null) - { - questSearchButton = header.createChild(-1, WidgetType.GRAPHIC); - questSearchButton.setSpriteId(SpriteID.GE_SEARCH); - questSearchButton.setOriginalWidth(18); - questSearchButton.setOriginalHeight(17); - questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); - questSearchButton.setOriginalX(5); - questSearchButton.setOriginalY(0); - questSearchButton.setHasListener(true); - questSearchButton.setAction(1, MENU_OPEN); - questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch()); - questSearchButton.setName(MENU_SEARCH); - questSearchButton.revalidate(); - - questHideButton = header.createChild(-1, WidgetType.GRAPHIC); - redrawHideButton(); - - questHideButton.setOriginalWidth(13); - questHideButton.setOriginalHeight(13); - questHideButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); - questHideButton.setOriginalX(24); - questHideButton.setOriginalY(2); - questHideButton.setHasListener(true); - questHideButton.setOnOpListener((JavaScriptCallback) e -> toggleHidden()); - questHideButton.setAction(1, MENU_TOGGLE); - questHideButton.revalidate(); - - questSet = new EnumMap<>(QuestContainer.class); - - updateFilter(); - } - } - - @Subscribe - public void onVarbitChanged(VarbitChanged varbitChanged) - { - if (isChatboxOpen() && !isOnQuestTab()) - { - chatboxPanelManager.close(); - } - } - - @Subscribe - public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged) - { - if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex()) - { - if (isChatboxOpen() && !isOnQuestTab()) - { - chatboxPanelManager.close(); - } - } - } - - private void toggleHidden() - { - QuestState[] questStates = QuestState.values(); - int nextState = (currentFilterState.ordinal() + 1) % questStates.length; - currentFilterState = questStates[nextState]; - - redrawHideButton(); - - updateFilter(); - client.playSoundEffect(SoundEffectID.UI_BOOP); - } - - private void redrawHideButton() - { - questHideButton.setSpriteId(currentFilterState.getSpriteId()); - questHideButton.setName(MENU_SHOW + " " + currentFilterState.getName()); - } - - private boolean isOnQuestTab() - { - return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2; - } - - private boolean isChatboxOpen() - { - return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput; - } - - private void closeSearch() - { - updateFilter(""); - chatboxPanelManager.close(); - client.playSoundEffect(SoundEffectID.UI_BOOP); - } - - private void openSearch() - { - updateFilter(""); - client.playSoundEffect(SoundEffectID.UI_BOOP); - questSearchButton.setAction(1, MENU_CLOSE); - questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch()); - searchInput = chatboxPanelManager.openTextInput("Search quest list") - .onChanged(s -> clientThread.invokeLater(() -> updateFilter(s))) - .onClose(() -> - { - clientThread.invokeLater(() -> updateFilter("")); - questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch()); - questSearchButton.setAction(1, MENU_OPEN); - }) - .build(); - } - - private void updateFilter() - { - String filter = ""; - if (isChatboxOpen()) - { - filter = searchInput.getValue(); - } - - updateFilter(filter); - } - - private void updateFilter(String filter) - { - filter = filter.toLowerCase(); - final Widget container = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER); - - final Widget freeList = client.getWidget(QuestContainer.FREE_QUESTS.widgetInfo); - final Widget memberList = client.getWidget(QuestContainer.MEMBER_QUESTS.widgetInfo); - final Widget miniList = client.getWidget(QuestContainer.MINI_QUESTS.widgetInfo); - - if (container == null || freeList == null || memberList == null || miniList == null) - { - return; - } - - updateList(QuestContainer.FREE_QUESTS, filter); - updateList(QuestContainer.MEMBER_QUESTS, filter); - updateList(QuestContainer.MINI_QUESTS, filter); - - memberList.setOriginalY(freeList.getOriginalY() + freeList.getOriginalHeight() + ENTRY_PADDING); - miniList.setOriginalY(memberList.getOriginalY() + memberList.getOriginalHeight() + ENTRY_PADDING); - - // originalHeight is changed within updateList so revalidate all lists - freeList.revalidate(); - memberList.revalidate(); - miniList.revalidate(); - - int y = miniList.getRelativeY() + miniList.getHeight() + 10; - - int newHeight; - if (container.getScrollHeight() > 0) - { - newHeight = (container.getScrollY() * y) / container.getScrollHeight(); - } - else - { - newHeight = 0; - } - - container.setScrollHeight(y); - container.revalidateScroll(); - - clientThread.invokeLater(() -> - client.runScript( - ScriptID.UPDATE_SCROLLBAR, - WidgetInfo.QUESTLIST_SCROLLBAR.getId(), - WidgetInfo.QUESTLIST_CONTAINER.getId(), - newHeight - )); - } - - private void updateList(QuestContainer questContainer, String filter) - { - Widget list = client.getWidget(questContainer.widgetInfo); - if (list == null) - { - return; - } - - Collection quests = questSet.get(questContainer); - - if (quests != null) - { - // Check to make sure the list hasn't been rebuild since we were last her - // Do this by making sure the list's dynamic children are the same as when we last saw them - if (quests.stream().noneMatch(w -> - { - Widget codeWidget = w.getQuest(); - if (codeWidget == null) - { - return false; - } - return list.getChild(codeWidget.getIndex()) == codeWidget; - })) - { - quests = null; - } - } - - if (quests == null) - { - // Find all of the widgets that we care about, sorting by their Y value - quests = Arrays.stream(list.getDynamicChildren()) - .sorted(Comparator.comparing(Widget::getRelativeY)) - .filter(w -> !QUEST_HEADERS.contains(w.getText())) - .map(w -> new QuestWidget(w, Text.removeTags(w.getText()).toLowerCase())) - .collect(Collectors.toList()); - questSet.put(questContainer, quests); - } - - // offset because of header - int y = 20; - for (QuestWidget questInfo : quests) - { - Widget quest = questInfo.getQuest(); - QuestState questState = QuestState.getByColor(quest.getTextColor()); - - boolean hidden; - if (!filter.isEmpty()) - { - // If searching, show result regardless of filtered state - hidden = !questInfo.getTitle().contains(filter); - } - else - { - // Otherwise hide if it doesn't match the filter state - hidden = currentFilterState != QuestState.ALL && questState != currentFilterState; - } - - quest.setHidden(hidden); - quest.setOriginalY(y); - quest.revalidate(); - - if (!hidden) - { - y += quest.getHeight(); - } - } - - list.setOriginalHeight(y); - } - - @AllArgsConstructor - @Getter - private enum QuestContainer - { - FREE_QUESTS(WidgetInfo.QUESTLIST_FREE_CONTAINER), - MEMBER_QUESTS(WidgetInfo.QUESTLIST_MEMBERS_CONTAINER), - MINI_QUESTS(WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER); - - private final WidgetInfo widgetInfo; - } - - @AllArgsConstructor - @Getter - private enum QuestState - { - NOT_STARTED(0xff0000, "Not started", SpriteID.MINIMAP_ORB_HITPOINTS), - IN_PROGRESS(0xffff00, "In progress", SpriteID.MINIMAP_ORB_HITPOINTS_DISEASE), - COMPLETE(0xdc10d, "Completed", SpriteID.MINIMAP_ORB_HITPOINTS_POISON), - ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER); - - private final int color; - private final String name; - private final int spriteId; - - static QuestState getByColor(int color) - { - for (QuestState value : values()) - { - if (value.getColor() == color) - { - return value; - } - } - - return null; - } - } - - @Data - @AllArgsConstructor - private static class QuestWidget - { - private Widget quest; - private String title; - } -} +/* + * Copyright (c) 2019 Spudjb + * 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.questlist; + +import com.google.common.collect.ImmutableList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.List; +import java.util.stream.Collectors; +import javax.inject.Inject; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.ScriptID; +import net.runelite.api.SoundEffectID; +import net.runelite.api.SpriteID; +import net.runelite.api.VarClientInt; +import net.runelite.api.Varbits; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.events.VarClientIntChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.chatbox.ChatboxPanelManager; +import net.runelite.client.game.chatbox.ChatboxTextInput; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.Text; + +@PluginDescriptor( + name = "Quest List", + description = "Adds searching and filtering to the quest list" +) +public class QuestListPlugin extends Plugin +{ + private static final int ENTRY_PADDING = 8; + private static final List QUEST_HEADERS = ImmutableList.of("Free Quests", "Members' Quests", "Miniquests"); + + private static final String MENU_OPEN = "Open"; + private static final String MENU_CLOSE = "Close"; + + private static final String MENU_TOGGLE = "Toggle"; + + private static final String MENU_SEARCH = "Search"; + private static final String MENU_SHOW = "Show"; + + @Inject + private Client client; + + @Inject + private ChatboxPanelManager chatboxPanelManager; + + @Inject + private ClientThread clientThread; + + private ChatboxTextInput searchInput; + private Widget questSearchButton; + private Widget questHideButton; + + private EnumMap> questSet; + + private QuestState currentFilterState; + + @Subscribe + public void onGameStateChanged(GameStateChanged e) + { + if (e.getGameState() == GameState.LOGGING_IN) + { + currentFilterState = QuestState.ALL; + } + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent event) + { + if (!event.getEventName().equals("questProgressUpdated")) + { + return; + } + + Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX); + if (header != null) + { + questSearchButton = header.createChild(-1, WidgetType.GRAPHIC); + questSearchButton.setSpriteId(SpriteID.GE_SEARCH); + questSearchButton.setOriginalWidth(18); + questSearchButton.setOriginalHeight(17); + questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); + questSearchButton.setOriginalX(5); + questSearchButton.setOriginalY(0); + questSearchButton.setHasListener(true); + questSearchButton.setAction(1, MENU_OPEN); + questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch()); + questSearchButton.setName(MENU_SEARCH); + questSearchButton.revalidate(); + + questHideButton = header.createChild(-1, WidgetType.GRAPHIC); + redrawHideButton(); + + questHideButton.setOriginalWidth(13); + questHideButton.setOriginalHeight(13); + questHideButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); + questHideButton.setOriginalX(24); + questHideButton.setOriginalY(2); + questHideButton.setHasListener(true); + questHideButton.setOnOpListener((JavaScriptCallback) e -> toggleHidden()); + questHideButton.setAction(1, MENU_TOGGLE); + questHideButton.revalidate(); + + questSet = new EnumMap<>(QuestContainer.class); + + updateFilter(); + } + } + + @Subscribe + public void onVarbitChanged(VarbitChanged varbitChanged) + { + if (isChatboxOpen() && !isOnQuestTab()) + { + chatboxPanelManager.close(); + } + } + + @Subscribe + public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged) + { + if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex()) + { + if (isChatboxOpen() && !isOnQuestTab()) + { + chatboxPanelManager.close(); + } + } + } + + private void toggleHidden() + { + QuestState[] questStates = QuestState.values(); + int nextState = (currentFilterState.ordinal() + 1) % questStates.length; + currentFilterState = questStates[nextState]; + + redrawHideButton(); + + updateFilter(); + client.playSoundEffect(SoundEffectID.UI_BOOP); + } + + private void redrawHideButton() + { + questHideButton.setSpriteId(currentFilterState.getSpriteId()); + questHideButton.setName(MENU_SHOW + " " + currentFilterState.getName()); + } + + private boolean isOnQuestTab() + { + return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2; + } + + private boolean isChatboxOpen() + { + return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput; + } + + private void closeSearch() + { + updateFilter(""); + chatboxPanelManager.close(); + client.playSoundEffect(SoundEffectID.UI_BOOP); + } + + private void openSearch() + { + updateFilter(""); + client.playSoundEffect(SoundEffectID.UI_BOOP); + questSearchButton.setAction(1, MENU_CLOSE); + questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch()); + searchInput = chatboxPanelManager.openTextInput("Search quest list") + .onChanged(s -> clientThread.invokeLater(() -> updateFilter(s))) + .onClose(() -> + { + clientThread.invokeLater(() -> updateFilter("")); + questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch()); + questSearchButton.setAction(1, MENU_OPEN); + }) + .build(); + } + + private void updateFilter() + { + String filter = ""; + if (isChatboxOpen()) + { + filter = searchInput.getValue(); + } + + updateFilter(filter); + } + + private void updateFilter(String filter) + { + filter = filter.toLowerCase(); + final Widget container = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER); + + final Widget freeList = client.getWidget(QuestContainer.FREE_QUESTS.widgetInfo); + final Widget memberList = client.getWidget(QuestContainer.MEMBER_QUESTS.widgetInfo); + final Widget miniList = client.getWidget(QuestContainer.MINI_QUESTS.widgetInfo); + + if (container == null || freeList == null || memberList == null || miniList == null) + { + return; + } + + updateList(QuestContainer.FREE_QUESTS, filter); + updateList(QuestContainer.MEMBER_QUESTS, filter); + updateList(QuestContainer.MINI_QUESTS, filter); + + memberList.setOriginalY(freeList.getOriginalY() + freeList.getOriginalHeight() + ENTRY_PADDING); + miniList.setOriginalY(memberList.getOriginalY() + memberList.getOriginalHeight() + ENTRY_PADDING); + + // originalHeight is changed within updateList so revalidate all lists + freeList.revalidate(); + memberList.revalidate(); + miniList.revalidate(); + + int y = miniList.getRelativeY() + miniList.getHeight() + 10; + + int newHeight; + if (container.getScrollHeight() > 0) + { + newHeight = (container.getScrollY() * y) / container.getScrollHeight(); + } + else + { + newHeight = 0; + } + + container.setScrollHeight(y); + container.revalidateScroll(); + + clientThread.invokeLater(() -> + client.runScript( + ScriptID.UPDATE_SCROLLBAR, + WidgetInfo.QUESTLIST_SCROLLBAR.getId(), + WidgetInfo.QUESTLIST_CONTAINER.getId(), + newHeight + )); + } + + private void updateList(QuestContainer questContainer, String filter) + { + Widget list = client.getWidget(questContainer.widgetInfo); + if (list == null) + { + return; + } + + Collection quests = questSet.get(questContainer); + + if (quests != null) + { + // Check to make sure the list hasn't been rebuild since we were last her + // Do this by making sure the list's dynamic children are the same as when we last saw them + if (quests.stream().noneMatch(w -> + { + Widget codeWidget = w.getQuest(); + if (codeWidget == null) + { + return false; + } + return list.getChild(codeWidget.getIndex()) == codeWidget; + })) + { + quests = null; + } + } + + if (quests == null) + { + // Find all of the widgets that we care about, sorting by their Y value + quests = Arrays.stream(list.getDynamicChildren()) + .sorted(Comparator.comparing(Widget::getRelativeY)) + .filter(w -> !QUEST_HEADERS.contains(w.getText())) + .map(w -> new QuestWidget(w, Text.removeTags(w.getText()).toLowerCase())) + .collect(Collectors.toList()); + questSet.put(questContainer, quests); + } + + // offset because of header + int y = 20; + for (QuestWidget questInfo : quests) + { + Widget quest = questInfo.getQuest(); + QuestState questState = QuestState.getByColor(quest.getTextColor()); + + boolean hidden; + if (!filter.isEmpty()) + { + // If searching, show result regardless of filtered state + hidden = !questInfo.getTitle().contains(filter); + } + else + { + // Otherwise hide if it doesn't match the filter state + hidden = currentFilterState != QuestState.ALL && questState != currentFilterState; + } + + quest.setHidden(hidden); + quest.setOriginalY(y); + quest.revalidate(); + + if (!hidden) + { + y += quest.getHeight(); + } + } + + list.setOriginalHeight(y); + } + + @AllArgsConstructor + @Getter + private enum QuestContainer + { + FREE_QUESTS(WidgetInfo.QUESTLIST_FREE_CONTAINER), + MEMBER_QUESTS(WidgetInfo.QUESTLIST_MEMBERS_CONTAINER), + MINI_QUESTS(WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER); + + private final WidgetInfo widgetInfo; + } + + @AllArgsConstructor + @Getter + private enum QuestState + { + NOT_STARTED(0xff0000, "Not started", SpriteID.MINIMAP_ORB_HITPOINTS), + IN_PROGRESS(0xffff00, "In progress", SpriteID.MINIMAP_ORB_HITPOINTS_DISEASE), + COMPLETE(0xdc10d, "Completed", SpriteID.MINIMAP_ORB_HITPOINTS_POISON), + ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER); + + private final int color; + private final String name; + private final int spriteId; + + static QuestState getByColor(int color) + { + for (QuestState value : values()) + { + if (value.getColor() == color) + { + return value; + } + } + + return null; + } + } + + @Data + @AllArgsConstructor + private static class QuestWidget + { + private Widget quest; + private String title; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java index 4adc61df11..14f5add239 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java @@ -25,12 +25,9 @@ package net.runelite.client.plugins.raids; import java.awt.Color; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.Keybind; @ConfigGroup("raids") public interface RaidsConfig extends Config @@ -189,6 +186,7 @@ public interface RaidsConfig extends Config { return true; } + @ConfigItem( position = 16, keyName = "showRecommendedItems", @@ -300,10 +298,10 @@ public interface RaidsConfig extends Config } @ConfigItem( - position = 26, - keyName = "displayFloorBreak", - name = "Layout floor break", - description = "Displays floor break in layout" + position = 26, + keyName = "displayFloorBreak", + name = "Layout floor break", + description = "Displays floor break in layout" ) default boolean displayFloorBreak() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java index 98fc24efa9..de7fd5779a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java @@ -24,31 +24,35 @@ */ package net.runelite.client.plugins.raids; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; import java.awt.Point; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.inject.Inject; import lombok.Getter; import lombok.Setter; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; import net.runelite.api.SpriteID; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.game.ItemManager; import net.runelite.client.game.SpriteManager; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; import net.runelite.client.plugins.raids.solver.Room; import net.runelite.client.ui.overlay.Overlay; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.*; +import net.runelite.client.ui.overlay.components.ComponentOrientation; +import net.runelite.client.ui.overlay.components.ImageComponent; +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.ImageUtil; import net.runelite.client.util.Text; @@ -191,7 +195,9 @@ public class RaidsOverlay extends Overlay roomCount++; } if (tightrope) + { puzzles = crabs ? "cr" : iceDemon ? "ri" : thieving ? "tr" : "?r"; + } else if (config.hideRopeless()) { panelComponent.getChildren().add(TitleComponent.builder() @@ -211,7 +217,9 @@ public class RaidsOverlay extends Overlay for (Integer s : scavRooms) { if (s > i) + { break; + } prev = s; } scavsBeforeIceRooms.add(prev); @@ -280,7 +288,9 @@ public class RaidsOverlay extends Overlay if (config.showRecommendedItems()) { if (plugin.getRecommendedItemsList().get(bossNameLC) != null) + { imageIds.addAll(plugin.getRecommendedItemsList().get(bossNameLC)); + } } panelComponent.getChildren().add(LineComponent.builder() @@ -295,7 +305,9 @@ public class RaidsOverlay extends Overlay String puzzleName = room.getPuzzle().getName(); String puzzleNameLC = puzzleName.toLowerCase(); if (plugin.getRecommendedItemsList().get(puzzleNameLC) != null) + { imageIds.addAll(plugin.getRecommendedItemsList().get(puzzleNameLC)); + } if (plugin.getRoomWhitelist().contains(puzzleNameLC)) { color = Color.GREEN; @@ -370,7 +382,7 @@ public class RaidsOverlay extends Overlay panelImages.setPreferredLocation(new Point(0, imagesVerticalOffset)); panelImages.setBackgroundColor(null); - if (2 * (imagesMaxHeight / ICON_SIZE) >= idArray.length ) + if (2 * (imagesMaxHeight / ICON_SIZE) >= idArray.length) { panelImages.setWrapping(2); } @@ -399,15 +411,25 @@ public class RaidsOverlay extends Overlay { BufferedImage bim; if (id != SpriteID.SPELL_ICE_BARRAGE) + { bim = itemManager.getImage(id); + } else + { bim = spriteManager.getSprite(id, 0); + } if (bim == null) + { return null; + } if (!small) + { return ImageUtil.resizeCanvas(bim, ICON_SIZE, ICON_SIZE); + } if (id != SpriteID.SPELL_ICE_BARRAGE) + { return ImageUtil.resizeImage(bim, SMALL_ICON_SIZE, SMALL_ICON_SIZE); + } return ImageUtil.resizeCanvas(bim, SMALL_ICON_SIZE, SMALL_ICON_SIZE); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 5729d20cd6..66becd116f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -1,872 +1,879 @@ -/* - * Copyright (c) 2018, Kamiel - * 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.raids; - -import com.google.inject.Binder; -import com.google.inject.Provides; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.inject.Inject; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.InstanceTemplates; -import net.runelite.api.ItemID; -import net.runelite.api.NullObjectID; -import static net.runelite.api.Perspective.SCENE_SIZE; -import net.runelite.api.Point; -import net.runelite.api.SpriteID; -import static net.runelite.api.SpriteID.TAB_QUESTS_BROWN_RAIDING_PARTY; -import net.runelite.api.Tile; -import net.runelite.api.VarPlayer; -import net.runelite.api.Varbits; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ClientTick; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.VarbitChanged; -import net.runelite.api.events.WidgetHiddenChanged; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.chat.ChatColorType; -import net.runelite.client.chat.ChatMessageBuilder; -import net.runelite.client.chat.ChatMessageManager; -import net.runelite.client.chat.QueuedMessage; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.game.ItemManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.raids.solver.Layout; -import net.runelite.client.plugins.raids.solver.LayoutSolver; -import net.runelite.client.plugins.raids.solver.RotationSolver; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.DrawManager; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.ui.overlay.WidgetOverlay; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; -import net.runelite.client.ui.overlay.tooltip.Tooltip; -import net.runelite.client.ui.overlay.tooltip.TooltipManager; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.Text; -import net.runelite.client.util.HotkeyListener; -import org.apache.commons.lang3.StringUtils; - -@PluginDescriptor( - name = "Chambers Of Xeric", - description = "Show helpful information for the Chambers of Xeric raid", - tags = {"combat", "raid", "overlay", "pve", "pvm", "bosses", "cox", "olm"}, - type = PluginType.PVM -) -@Slf4j -public class RaidsPlugin extends Plugin -{ - private static final int LOBBY_PLANE = 3; - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##"); - static final DecimalFormat POINTS_FORMAT = new DecimalFormat("#,###"); - private static final String SPLIT_REGEX = "\\s*,\\s*"; - private static final Pattern ROTATION_REGEX = Pattern.compile("\\[(.*?)]"); - private static final int LINE_COMPONENT_HEIGHT = 16; - - @Inject - private ItemManager itemManager; - private static final Pattern LEVEL_COMPLETE_REGEX = Pattern.compile("(.+) level complete! Duration: ([0-9:]+)"); - private static final Pattern RAID_COMPLETE_REGEX = Pattern.compile("Congratulations - your raid is complete! Duration: ([0-9:]+)"); - - @Inject - private ChatMessageManager chatMessageManager; - - @Inject - private InfoBoxManager infoBoxManager; - - @Inject - private Client client; - - @Inject - private DrawManager drawManager; - - @Inject - private ScheduledExecutorService executor; - - @Inject - private RaidsConfig config; - - @Inject - private OverlayManager overlayManager; - - @Inject - private RaidsOverlay overlay; - - @Inject - private RaidsPointsOverlay pointsOverlay; - - @Inject - private LayoutSolver layoutSolver; - - @Inject - private SpriteManager spriteManager; - - @Inject - private ClientThread clientThread; - - @Inject - private KeyManager keyManager; - - @Inject - private TooltipManager tooltipManager; - - @Getter - private final ArrayList roomWhitelist = new ArrayList<>(); - - @Getter - private final ArrayList roomBlacklist = new ArrayList<>(); - - @Getter - private final ArrayList rotationWhitelist = new ArrayList<>(); - - @Getter - private final ArrayList layoutWhitelist = new ArrayList<>(); - - @Getter - private final Map> recommendedItemsList = new HashMap<>(); - - @Getter - private Raid raid; - - @Getter - private boolean inRaidChambers; - - @Inject - private ClientToolbar clientToolbar; - private RaidsPanel panel; - private int upperTime = -1; - private int middleTime = -1; - private int lowerTime = -1; - private int raidTime = -1; - private WidgetOverlay widgetOverlay; - private String tooltip; - public boolean canShow; - private NavigationButton navButton; - - @Provides - RaidsConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(RaidsConfig.class); - } - - @Override - public void configure(Binder binder) - { - binder.bind(RaidsOverlay.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - overlayManager.add(pointsOverlay); - updateLists(); - clientThread.invokeLater(() -> checkRaidPresence(true)); - widgetOverlay = overlayManager.getWidgetOverlay(WidgetInfo.RAIDS_POINTS_INFOBOX); - panel = injector.getInstance(RaidsPanel.class); - panel.init(config); - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "instancereloadhelper.png"); - navButton = NavigationButton.builder() - .tooltip("Raids Reload") - .icon(icon) - .priority(8) - .panel(panel) - .build(); - clientToolbar.addNavigation(navButton); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - overlayManager.remove(pointsOverlay); - clientToolbar.removeNavigation(navButton); - inRaidChambers = false; - widgetOverlay = null; - raid = null; - - final Widget widget = client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX); - if (widget != null) - { - widget.setHidden(false); - } - reset(); - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (!event.getGroup().equals("raids")) - { - return; - } - - updateLists(); - clientThread.invokeLater(() -> checkRaidPresence(true)); - } - - @Subscribe - public void onWidgetHiddenChanged(WidgetHiddenChanged event) - { - if (!inRaidChambers || event.isHidden()) - { - return; - } - - Widget widget = event.getWidget(); - - if (widget == client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX)) - { - widget.setHidden(true); - } - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - checkRaidPresence(false); - } - - @Subscribe - public void onChatMessage(ChatMessage event) - { - if (inRaidChambers && event.getType() == ChatMessageType.FRIENDSCHATNOTIFICATION) - { - String message = Text.removeTags(event.getMessage()); - Matcher matcher; - - matcher = LEVEL_COMPLETE_REGEX.matcher(message); - if (matcher.find()) - { - String floor = matcher.group(1); - int time = timeToSeconds(matcher.group(2)); - if (floor.equals("Upper")) - { - upperTime = time; - } - else if (floor.equals("Middle")) - { - middleTime = time; - } - else if (floor.equals("Lower")) - { - lowerTime = time; - } - updateTooltip(); - } - - matcher = RAID_COMPLETE_REGEX.matcher(message); - if (matcher.find()) - { - raidTime = timeToSeconds(matcher.group(1)); - int timesec = timeToSeconds(matcher.group(1)); - updateTooltip(); - - if (config.pointsMessage()) - { - int totalPoints = client.getVar(Varbits.TOTAL_POINTS); - int personalPoints = client.getVar(Varbits.PERSONAL_POINTS); - int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); - - double percentage = personalPoints / (totalPoints / 100.0); - - String chatMessage = new ChatMessageBuilder() - .append(ChatColorType.NORMAL) - .append("Total points: ") - .append(ChatColorType.HIGHLIGHT) - .append(POINTS_FORMAT.format(totalPoints)) - .append(ChatColorType.NORMAL) - .append(", Personal points: ") - .append(ChatColorType.HIGHLIGHT) - .append(POINTS_FORMAT.format(personalPoints)) - .append(ChatColorType.NORMAL) - .append(" (") - .append(ChatColorType.HIGHLIGHT) - .append(DECIMAL_FORMAT.format(percentage)) - .append(ChatColorType.NORMAL) - .append("%)") - .build(); - - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.FRIENDSCHATNOTIFICATION) - .runeLiteFormattedMessage(chatMessage) - .build()); - if (config.ptsHr()) - { - String ptssolo; - { - ptssolo = POINTS_FORMAT.format(((float) personalPoints / (float) timesec) * 3600); - } - - String ptsteam; - { - ptsteam = POINTS_FORMAT.format(((float) totalPoints / (float) timesec) * 3600); - } - - String ptssplit; - { - ptssplit = POINTS_FORMAT.format(((float) (totalPoints / (float) timesec) * 3600) / (partySize)); - } - - - String chatMessage2 = new ChatMessageBuilder() - .append(ChatColorType.NORMAL) - .append("Solo Pts/Hr: ") - .append(ChatColorType.HIGHLIGHT) - .append(ptssolo) - .append(ChatColorType.NORMAL) - .append("Team Pts/Hr: ") - .append(ChatColorType.HIGHLIGHT) - .append(ptsteam) - .build(); - - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.FRIENDSCHATNOTIFICATION) - .runeLiteFormattedMessage(chatMessage2) - .build()); - - String chatMessage3 = new ChatMessageBuilder() - .append(ChatColorType.NORMAL) - .append("Split Pts/Hr: ") - .append(ChatColorType.HIGHLIGHT) - .append(ptssplit) - .build(); - - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.FRIENDSCHATNOTIFICATION) - .runeLiteFormattedMessage(chatMessage3) - .build()); - } - } - } - } - } - - @Subscribe - public void onClientTick(ClientTick event) - { - if (!config.raidsTimer() - || !client.getGameState().equals(GameState.LOGGED_IN) - || tooltip == null) - { - return; - } - - final Point mousePosition = client.getMouseCanvasPosition(); - if (widgetOverlay.getBounds().contains(mousePosition.getX(), mousePosition.getY())) - { - tooltipManager.add(new Tooltip(tooltip)); - } - } - - public void checkRaidPresence(boolean force) - { - if (client.getGameState() != GameState.LOGGED_IN) - { - return; - } - - boolean setting = client.getVar(Varbits.IN_RAID) == 1; - - if (force || inRaidChambers != setting) - { - inRaidChambers = setting; - - if (inRaidChambers) - { - raid = buildRaid(); - - if (raid == null) - { - log.debug("Failed to build raid"); - return; - } - - Layout layout = layoutSolver.findLayout(raid.toCode()); - - if (layout == null) - { - log.debug("Could not find layout match"); - return; - } - - raid.updateLayout(layout); - RotationSolver.solve(raid.getCombatRooms()); - overlay.setScoutOverlayShown(true); - sendRaidLayoutMessage(); - } - else - { - if (!config.scoutOverlayAtBank()) - { - overlay.setScoutOverlayShown(false); - } - - reset(); - } - } - - // If we left party raid was started or we left raid - if (client.getVar(VarPlayer.IN_RAID_PARTY) == -1 && (!inRaidChambers || !config.scoutOverlayInRaid())) - { - overlay.setScoutOverlayShown(false); - } - } - - private void sendRaidLayoutMessage() - { - if (!config.layoutMessage()) - { - return; - } - - final String layout = getRaid().getLayout().toCodeString(); - final String rooms = getRaid().toRoomString(); - final String raidData = "[" + layout + "]: " + rooms; - - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.FRIENDSCHATNOTIFICATION) - .runeLiteFormattedMessage(new ChatMessageBuilder() - .append(ChatColorType.HIGHLIGHT) - .append("Layout: ") - .append(ChatColorType.NORMAL) - .append(raidData) - .build()) - .build()); - } - - - private void updateLists() - { - updateList(roomWhitelist, config.whitelistedRooms()); - updateList(roomBlacklist, config.blacklistedRooms()); - updateList(rotationWhitelist, config.whitelistedRotations()); - updateList(layoutWhitelist, config.whitelistedLayouts()); - updateMap(recommendedItemsList, config.recommendedItems()); - } - - private void updateMap(Map> map, String input) - { - map.clear(); - - Matcher m = ROTATION_REGEX.matcher(input); - while (m.find()) - { - String everything = m.group(1).toLowerCase(); - int split = everything.indexOf(','); - if (split < 0) - continue; - String key = everything.substring(0, split); - if (key.length() < 1) - continue; - String[] itemNames = everything.substring(split).split(SPLIT_REGEX); - - map.computeIfAbsent(key, k -> new ArrayList<>()); - - for (String itemName : itemNames) - { - if (itemName.equals("")) - continue; - if (itemName.equals("ice barrage")) - map.get(key).add(SpriteID.SPELL_ICE_BARRAGE); - else if (itemName.startsWith("salve")) - map.get(key).add(ItemID.SALVE_AMULETEI); - else if (itemManager.search(itemName).size() > 0) - map.get(key).add(itemManager.search(itemName).get(0).getId()); - else - log.info("RaidsPlugin: Could not find an item ID for item: " + itemName); - } - } - } - - private void updateList(ArrayList list, String input) - { - list.clear(); - - if (list == rotationWhitelist) - { - Matcher m = ROTATION_REGEX.matcher(input); - while (m.find()) - { - String rotation = m.group(1).toLowerCase(); - - if (!list.contains(rotation)) - { - list.add(rotation); - } - } - } - else - { - list.addAll(Arrays.asList(input.toLowerCase().split(SPLIT_REGEX))); - } - } - - int getRotationMatches() - { - String rotation = raid.getRotationString().toLowerCase(); - String[] bosses = rotation.split(SPLIT_REGEX); - - if (rotationWhitelist.contains(rotation)) - { - return bosses.length; - } - - for (String whitelisted : rotationWhitelist) - { - int matches = 0; - String[] whitelistedBosses = whitelisted.split(SPLIT_REGEX); - - for (int i = 0; i < whitelistedBosses.length; i++) - { - if (i < bosses.length && whitelistedBosses[i].equals(bosses[i])) - { - matches++; - } - else - { - matches = 0; - break; - } - } - - if (matches >= 2) - { - return matches; - } - } - - return 0; - } - - private Point findLobbyBase() - { - Tile[][] tiles = client.getScene().getTiles()[LOBBY_PLANE]; - - for (int x = 0; x < SCENE_SIZE; x++) - { - for (int y = 0; y < SCENE_SIZE; y++) - { - if (tiles[x][y] == null || tiles[x][y].getWallObject() == null) - { - continue; - } - - if (tiles[x][y].getWallObject().getId() == NullObjectID.NULL_12231) - { - return tiles[x][y].getSceneLocation(); - } - } - } - - return null; - } - - private Raid buildRaid() - { - Point gridBase = findLobbyBase(); - - if (gridBase == null) - { - return null; - } - - Raid raid = new Raid(); - Tile[][] tiles; - int position, x, y, offsetX; - int startX = -2; - - for (int plane = 3; plane > 1; plane--) - { - tiles = client.getScene().getTiles()[plane]; - - if (tiles[gridBase.getX() + RaidRoom.ROOM_MAX_SIZE][gridBase.getY()] == null) - { - position = 1; - } - else - { - position = 0; - } - - for (int i = 1; i > -2; i--) - { - y = gridBase.getY() + (i * RaidRoom.ROOM_MAX_SIZE); - - for (int j = startX; j < 4; j++) - { - x = gridBase.getX() + (j * RaidRoom.ROOM_MAX_SIZE); - offsetX = 0; - - if (x > SCENE_SIZE && position > 1 && position < 4) - { - position++; - } - - if (x < 0) - { - offsetX = Math.abs(x) + 1; //add 1 because the tile at x=0 will always be null - } - - if (x < SCENE_SIZE && y >= 0 && y < SCENE_SIZE) - { - if (tiles[x + offsetX][y] == null) - { - if (position == 4) - { - position++; - break; - } - - continue; - } - - if (position == 0 && startX != j) - { - startX = j; - } - - Tile base = tiles[offsetX > 0 ? 1 : x][y]; - RaidRoom room = determineRoom(base); - raid.setRoom(room, position + Math.abs((plane - 3) * 8)); - position++; - } - } - } - } - - return raid; - } - - private RaidRoom determineRoom(Tile base) - { - RaidRoom room = new RaidRoom(base, RaidRoom.Type.EMPTY); - int chunkData = client.getInstanceTemplateChunks()[base.getPlane()][(base.getSceneLocation().getX()) / 8][base.getSceneLocation().getY() / 8]; - InstanceTemplates template = InstanceTemplates.findMatch(chunkData); - - if (template == null) - { - return room; - } - - switch (template) - { - case RAIDS_LOBBY: - case RAIDS_START: - room.setType(RaidRoom.Type.START); - break; - - case RAIDS_END: - room.setType(RaidRoom.Type.END); - break; - - case RAIDS_SCAVENGERS: - case RAIDS_SCAVENGERS2: - room.setType(RaidRoom.Type.SCAVENGERS); - break; - - case RAIDS_SHAMANS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.SHAMANS); - break; - - case RAIDS_VASA: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.VASA); - break; - - case RAIDS_VANGUARDS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.VANGUARDS); - break; - - case RAIDS_ICE_DEMON: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.ICE_DEMON); - break; - - case RAIDS_THIEVING: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.THIEVING); - break; - - case RAIDS_FARMING: - case RAIDS_FARMING2: - room.setType(RaidRoom.Type.FARMING); - break; - - case RAIDS_MUTTADILES: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.MUTTADILES); - break; - - case RAIDS_MYSTICS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.MYSTICS); - break; - - case RAIDS_TEKTON: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.TEKTON); - break; - - case RAIDS_TIGHTROPE: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.TIGHTROPE); - break; - - case RAIDS_GUARDIANS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.GUARDIANS); - break; - - case RAIDS_CRABS: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.CRABS); - break; - - case RAIDS_VESPULA: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.VESPULA); - break; - } - - return room; - } - - public void reset() - { - raid = null; - upperTime = -1; - middleTime = -1; - lowerTime = -1; - raidTime = -1; - tooltip = null; - } - - private int timeToSeconds(String s) - { - int seconds = -1; - String[] split = s.split(":"); - if (split.length == 2) - { - seconds = Integer.parseInt(split[0]) * 60 + Integer.parseInt(split[1]); - } - if (split.length == 3) - { - seconds = Integer.parseInt(split[0]) * 3600 + Integer.parseInt(split[1]) * 60 + Integer.parseInt(split[2]); - } - return seconds; - } - - private String secondsToTime(int seconds) - { - StringBuilder builder = new StringBuilder(); - if (seconds >= 3600) - { - builder.append((int)Math.floor(seconds / 3600) + ";"); - } - seconds %= 3600; - if (builder.toString().equals("")) - { - builder.append((int)Math.floor(seconds / 60)); - } - else - { - builder.append(StringUtils.leftPad(String.valueOf((int)Math.floor(seconds / 60)), 2, '0')); - } - builder.append(":"); - seconds %= 60; - builder.append(StringUtils.leftPad(String.valueOf(seconds), 2, '0')); - return builder.toString(); - } - - private void updateTooltip() - { - StringBuilder builder = new StringBuilder(); - if (upperTime == -1) - { - tooltip = null; - return; - } - builder.append("Upper level: " + secondsToTime(upperTime)); - if (middleTime == -1) - { - if (lowerTime == -1) - { - tooltip = builder.toString(); - return; - } - else - { - builder.append("
Lower level: " + secondsToTime(lowerTime - upperTime)); - } - } - else - { - builder.append("
Middle level: " + secondsToTime(middleTime - upperTime)); - if (lowerTime == -1) - { - tooltip = builder.toString(); - return; - } - else - { - builder.append("
Lower level: " + secondsToTime(lowerTime - middleTime)); - } - } - if (raidTime == -1) - { - tooltip = builder.toString(); - return; - } - builder.append("
Olm: " + secondsToTime(raidTime - lowerTime)); - tooltip = builder.toString(); - } -} +/* + * Copyright (c) 2018, Kamiel + * 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.raids; + +import com.google.inject.Binder; +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.inject.Inject; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.InstanceTemplates; +import net.runelite.api.ItemID; +import net.runelite.api.NullObjectID; +import static net.runelite.api.Perspective.SCENE_SIZE; +import net.runelite.api.Point; +import net.runelite.api.SpriteID; +import net.runelite.api.Tile; +import net.runelite.api.VarPlayer; +import net.runelite.api.Varbits; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ClientTick; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.events.WidgetHiddenChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.chat.ChatColorType; +import net.runelite.client.chat.ChatMessageBuilder; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.chat.QueuedMessage; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.plugins.raids.solver.Layout; +import net.runelite.client.plugins.raids.solver.LayoutSolver; +import net.runelite.client.plugins.raids.solver.RotationSolver; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.DrawManager; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.WidgetOverlay; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.ui.overlay.tooltip.Tooltip; +import net.runelite.client.ui.overlay.tooltip.TooltipManager; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.Text; +import org.apache.commons.lang3.StringUtils; + +@PluginDescriptor( + name = "Chambers Of Xeric", + description = "Show helpful information for the Chambers of Xeric raid", + tags = {"combat", "raid", "overlay", "pve", "pvm", "bosses", "cox", "olm"}, + type = PluginType.PVM +) +@Slf4j +public class RaidsPlugin extends Plugin +{ + private static final int LOBBY_PLANE = 3; + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##"); + static final DecimalFormat POINTS_FORMAT = new DecimalFormat("#,###"); + private static final String SPLIT_REGEX = "\\s*,\\s*"; + private static final Pattern ROTATION_REGEX = Pattern.compile("\\[(.*?)]"); + private static final int LINE_COMPONENT_HEIGHT = 16; + + @Inject + private ItemManager itemManager; + private static final Pattern LEVEL_COMPLETE_REGEX = Pattern.compile("(.+) level complete! Duration: ([0-9:]+)"); + private static final Pattern RAID_COMPLETE_REGEX = Pattern.compile("Congratulations - your raid is complete! Duration: ([0-9:]+)"); + + @Inject + private ChatMessageManager chatMessageManager; + + @Inject + private InfoBoxManager infoBoxManager; + + @Inject + private Client client; + + @Inject + private DrawManager drawManager; + + @Inject + private ScheduledExecutorService executor; + + @Inject + private RaidsConfig config; + + @Inject + private OverlayManager overlayManager; + + @Inject + private RaidsOverlay overlay; + + @Inject + private RaidsPointsOverlay pointsOverlay; + + @Inject + private LayoutSolver layoutSolver; + + @Inject + private SpriteManager spriteManager; + + @Inject + private ClientThread clientThread; + + @Inject + private KeyManager keyManager; + + @Inject + private TooltipManager tooltipManager; + + @Getter + private final ArrayList roomWhitelist = new ArrayList<>(); + + @Getter + private final ArrayList roomBlacklist = new ArrayList<>(); + + @Getter + private final ArrayList rotationWhitelist = new ArrayList<>(); + + @Getter + private final ArrayList layoutWhitelist = new ArrayList<>(); + + @Getter + private final Map> recommendedItemsList = new HashMap<>(); + + @Getter + private Raid raid; + + @Getter + private boolean inRaidChambers; + + @Inject + private ClientToolbar clientToolbar; + private RaidsPanel panel; + private int upperTime = -1; + private int middleTime = -1; + private int lowerTime = -1; + private int raidTime = -1; + private WidgetOverlay widgetOverlay; + private String tooltip; + public boolean canShow; + private NavigationButton navButton; + + @Provides + RaidsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(RaidsConfig.class); + } + + @Override + public void configure(Binder binder) + { + binder.bind(RaidsOverlay.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + overlayManager.add(pointsOverlay); + updateLists(); + clientThread.invokeLater(() -> checkRaidPresence(true)); + widgetOverlay = overlayManager.getWidgetOverlay(WidgetInfo.RAIDS_POINTS_INFOBOX); + panel = injector.getInstance(RaidsPanel.class); + panel.init(config); + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "instancereloadhelper.png"); + navButton = NavigationButton.builder() + .tooltip("Raids Reload") + .icon(icon) + .priority(8) + .panel(panel) + .build(); + clientToolbar.addNavigation(navButton); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + overlayManager.remove(pointsOverlay); + clientToolbar.removeNavigation(navButton); + inRaidChambers = false; + widgetOverlay = null; + raid = null; + + final Widget widget = client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX); + if (widget != null) + { + widget.setHidden(false); + } + reset(); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!event.getGroup().equals("raids")) + { + return; + } + + updateLists(); + clientThread.invokeLater(() -> checkRaidPresence(true)); + } + + @Subscribe + public void onWidgetHiddenChanged(WidgetHiddenChanged event) + { + if (!inRaidChambers || event.isHidden()) + { + return; + } + + Widget widget = event.getWidget(); + + if (widget == client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX)) + { + widget.setHidden(true); + } + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + checkRaidPresence(false); + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (inRaidChambers && event.getType() == ChatMessageType.FRIENDSCHATNOTIFICATION) + { + String message = Text.removeTags(event.getMessage()); + Matcher matcher; + + matcher = LEVEL_COMPLETE_REGEX.matcher(message); + if (matcher.find()) + { + String floor = matcher.group(1); + int time = timeToSeconds(matcher.group(2)); + if (floor.equals("Upper")) + { + upperTime = time; + } + else if (floor.equals("Middle")) + { + middleTime = time; + } + else if (floor.equals("Lower")) + { + lowerTime = time; + } + updateTooltip(); + } + + matcher = RAID_COMPLETE_REGEX.matcher(message); + if (matcher.find()) + { + raidTime = timeToSeconds(matcher.group(1)); + int timesec = timeToSeconds(matcher.group(1)); + updateTooltip(); + + if (config.pointsMessage()) + { + int totalPoints = client.getVar(Varbits.TOTAL_POINTS); + int personalPoints = client.getVar(Varbits.PERSONAL_POINTS); + int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); + + double percentage = personalPoints / (totalPoints / 100.0); + + String chatMessage = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Total points: ") + .append(ChatColorType.HIGHLIGHT) + .append(POINTS_FORMAT.format(totalPoints)) + .append(ChatColorType.NORMAL) + .append(", Personal points: ") + .append(ChatColorType.HIGHLIGHT) + .append(POINTS_FORMAT.format(personalPoints)) + .append(ChatColorType.NORMAL) + .append(" (") + .append(ChatColorType.HIGHLIGHT) + .append(DECIMAL_FORMAT.format(percentage)) + .append(ChatColorType.NORMAL) + .append("%)") + .build(); + + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.FRIENDSCHATNOTIFICATION) + .runeLiteFormattedMessage(chatMessage) + .build()); + if (config.ptsHr()) + { + String ptssolo; + { + ptssolo = POINTS_FORMAT.format(((float) personalPoints / (float) timesec) * 3600); + } + + String ptsteam; + { + ptsteam = POINTS_FORMAT.format(((float) totalPoints / (float) timesec) * 3600); + } + + String ptssplit; + { + ptssplit = POINTS_FORMAT.format(((totalPoints / (float) timesec) * 3600) / (partySize)); + } + + + String chatMessage2 = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Solo Pts/Hr: ") + .append(ChatColorType.HIGHLIGHT) + .append(ptssolo) + .append(ChatColorType.NORMAL) + .append("Team Pts/Hr: ") + .append(ChatColorType.HIGHLIGHT) + .append(ptsteam) + .build(); + + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.FRIENDSCHATNOTIFICATION) + .runeLiteFormattedMessage(chatMessage2) + .build()); + + String chatMessage3 = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Split Pts/Hr: ") + .append(ChatColorType.HIGHLIGHT) + .append(ptssplit) + .build(); + + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.FRIENDSCHATNOTIFICATION) + .runeLiteFormattedMessage(chatMessage3) + .build()); + } + } + } + } + } + + @Subscribe + public void onClientTick(ClientTick event) + { + if (!config.raidsTimer() + || !client.getGameState().equals(GameState.LOGGED_IN) + || tooltip == null) + { + return; + } + + final Point mousePosition = client.getMouseCanvasPosition(); + if (widgetOverlay.getBounds().contains(mousePosition.getX(), mousePosition.getY())) + { + tooltipManager.add(new Tooltip(tooltip)); + } + } + + public void checkRaidPresence(boolean force) + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + boolean setting = client.getVar(Varbits.IN_RAID) == 1; + + if (force || inRaidChambers != setting) + { + inRaidChambers = setting; + + if (inRaidChambers) + { + raid = buildRaid(); + + if (raid == null) + { + log.debug("Failed to build raid"); + return; + } + + Layout layout = layoutSolver.findLayout(raid.toCode()); + + if (layout == null) + { + log.debug("Could not find layout match"); + return; + } + + raid.updateLayout(layout); + RotationSolver.solve(raid.getCombatRooms()); + overlay.setScoutOverlayShown(true); + sendRaidLayoutMessage(); + } + else + { + if (!config.scoutOverlayAtBank()) + { + overlay.setScoutOverlayShown(false); + } + + reset(); + } + } + + // If we left party raid was started or we left raid + if (client.getVar(VarPlayer.IN_RAID_PARTY) == -1 && (!inRaidChambers || !config.scoutOverlayInRaid())) + { + overlay.setScoutOverlayShown(false); + } + } + + private void sendRaidLayoutMessage() + { + if (!config.layoutMessage()) + { + return; + } + + final String layout = getRaid().getLayout().toCodeString(); + final String rooms = getRaid().toRoomString(); + final String raidData = "[" + layout + "]: " + rooms; + + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.FRIENDSCHATNOTIFICATION) + .runeLiteFormattedMessage(new ChatMessageBuilder() + .append(ChatColorType.HIGHLIGHT) + .append("Layout: ") + .append(ChatColorType.NORMAL) + .append(raidData) + .build()) + .build()); + } + + + private void updateLists() + { + updateList(roomWhitelist, config.whitelistedRooms()); + updateList(roomBlacklist, config.blacklistedRooms()); + updateList(rotationWhitelist, config.whitelistedRotations()); + updateList(layoutWhitelist, config.whitelistedLayouts()); + updateMap(recommendedItemsList, config.recommendedItems()); + } + + private void updateMap(Map> map, String input) + { + map.clear(); + + Matcher m = ROTATION_REGEX.matcher(input); + while (m.find()) + { + String everything = m.group(1).toLowerCase(); + int split = everything.indexOf(','); + if (split < 0) + { + continue; + } + String key = everything.substring(0, split); + if (key.length() < 1) + { + continue; + } + String[] itemNames = everything.substring(split).split(SPLIT_REGEX); + + map.computeIfAbsent(key, k -> new ArrayList<>()); + + for (String itemName : itemNames) + { + if (itemName.equals("")) + { + continue; + } + if (itemName.equals("ice barrage")) + { + map.get(key).add(SpriteID.SPELL_ICE_BARRAGE); + } + else if (itemName.startsWith("salve")) + { + map.get(key).add(ItemID.SALVE_AMULETEI); + } + else if (itemManager.search(itemName).size() > 0) + { + map.get(key).add(itemManager.search(itemName).get(0).getId()); + } + else + { + log.info("RaidsPlugin: Could not find an item ID for item: " + itemName); + } + } + } + } + + private void updateList(ArrayList list, String input) + { + list.clear(); + + if (list == rotationWhitelist) + { + Matcher m = ROTATION_REGEX.matcher(input); + while (m.find()) + { + String rotation = m.group(1).toLowerCase(); + + if (!list.contains(rotation)) + { + list.add(rotation); + } + } + } + else + { + list.addAll(Arrays.asList(input.toLowerCase().split(SPLIT_REGEX))); + } + } + + int getRotationMatches() + { + String rotation = raid.getRotationString().toLowerCase(); + String[] bosses = rotation.split(SPLIT_REGEX); + + if (rotationWhitelist.contains(rotation)) + { + return bosses.length; + } + + for (String whitelisted : rotationWhitelist) + { + int matches = 0; + String[] whitelistedBosses = whitelisted.split(SPLIT_REGEX); + + for (int i = 0; i < whitelistedBosses.length; i++) + { + if (i < bosses.length && whitelistedBosses[i].equals(bosses[i])) + { + matches++; + } + else + { + matches = 0; + break; + } + } + + if (matches >= 2) + { + return matches; + } + } + + return 0; + } + + private Point findLobbyBase() + { + Tile[][] tiles = client.getScene().getTiles()[LOBBY_PLANE]; + + for (int x = 0; x < SCENE_SIZE; x++) + { + for (int y = 0; y < SCENE_SIZE; y++) + { + if (tiles[x][y] == null || tiles[x][y].getWallObject() == null) + { + continue; + } + + if (tiles[x][y].getWallObject().getId() == NullObjectID.NULL_12231) + { + return tiles[x][y].getSceneLocation(); + } + } + } + + return null; + } + + private Raid buildRaid() + { + Point gridBase = findLobbyBase(); + + if (gridBase == null) + { + return null; + } + + Raid raid = new Raid(); + Tile[][] tiles; + int position, x, y, offsetX; + int startX = -2; + + for (int plane = 3; plane > 1; plane--) + { + tiles = client.getScene().getTiles()[plane]; + + if (tiles[gridBase.getX() + RaidRoom.ROOM_MAX_SIZE][gridBase.getY()] == null) + { + position = 1; + } + else + { + position = 0; + } + + for (int i = 1; i > -2; i--) + { + y = gridBase.getY() + (i * RaidRoom.ROOM_MAX_SIZE); + + for (int j = startX; j < 4; j++) + { + x = gridBase.getX() + (j * RaidRoom.ROOM_MAX_SIZE); + offsetX = 0; + + if (x > SCENE_SIZE && position > 1 && position < 4) + { + position++; + } + + if (x < 0) + { + offsetX = Math.abs(x) + 1; //add 1 because the tile at x=0 will always be null + } + + if (x < SCENE_SIZE && y >= 0 && y < SCENE_SIZE) + { + if (tiles[x + offsetX][y] == null) + { + if (position == 4) + { + position++; + break; + } + + continue; + } + + if (position == 0 && startX != j) + { + startX = j; + } + + Tile base = tiles[offsetX > 0 ? 1 : x][y]; + RaidRoom room = determineRoom(base); + raid.setRoom(room, position + Math.abs((plane - 3) * 8)); + position++; + } + } + } + } + + return raid; + } + + private RaidRoom determineRoom(Tile base) + { + RaidRoom room = new RaidRoom(base, RaidRoom.Type.EMPTY); + int chunkData = client.getInstanceTemplateChunks()[base.getPlane()][(base.getSceneLocation().getX()) / 8][base.getSceneLocation().getY() / 8]; + InstanceTemplates template = InstanceTemplates.findMatch(chunkData); + + if (template == null) + { + return room; + } + + switch (template) + { + case RAIDS_LOBBY: + case RAIDS_START: + room.setType(RaidRoom.Type.START); + break; + + case RAIDS_END: + room.setType(RaidRoom.Type.END); + break; + + case RAIDS_SCAVENGERS: + case RAIDS_SCAVENGERS2: + room.setType(RaidRoom.Type.SCAVENGERS); + break; + + case RAIDS_SHAMANS: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.SHAMANS); + break; + + case RAIDS_VASA: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.VASA); + break; + + case RAIDS_VANGUARDS: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.VANGUARDS); + break; + + case RAIDS_ICE_DEMON: + room.setType(RaidRoom.Type.PUZZLE); + room.setPuzzle(RaidRoom.Puzzle.ICE_DEMON); + break; + + case RAIDS_THIEVING: + room.setType(RaidRoom.Type.PUZZLE); + room.setPuzzle(RaidRoom.Puzzle.THIEVING); + break; + + case RAIDS_FARMING: + case RAIDS_FARMING2: + room.setType(RaidRoom.Type.FARMING); + break; + + case RAIDS_MUTTADILES: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.MUTTADILES); + break; + + case RAIDS_MYSTICS: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.MYSTICS); + break; + + case RAIDS_TEKTON: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.TEKTON); + break; + + case RAIDS_TIGHTROPE: + room.setType(RaidRoom.Type.PUZZLE); + room.setPuzzle(RaidRoom.Puzzle.TIGHTROPE); + break; + + case RAIDS_GUARDIANS: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.GUARDIANS); + break; + + case RAIDS_CRABS: + room.setType(RaidRoom.Type.PUZZLE); + room.setPuzzle(RaidRoom.Puzzle.CRABS); + break; + + case RAIDS_VESPULA: + room.setType(RaidRoom.Type.COMBAT); + room.setBoss(RaidRoom.Boss.VESPULA); + break; + } + + return room; + } + + public void reset() + { + raid = null; + upperTime = -1; + middleTime = -1; + lowerTime = -1; + raidTime = -1; + tooltip = null; + } + + private int timeToSeconds(String s) + { + int seconds = -1; + String[] split = s.split(":"); + if (split.length == 2) + { + seconds = Integer.parseInt(split[0]) * 60 + Integer.parseInt(split[1]); + } + if (split.length == 3) + { + seconds = Integer.parseInt(split[0]) * 3600 + Integer.parseInt(split[1]) * 60 + Integer.parseInt(split[2]); + } + return seconds; + } + + private String secondsToTime(int seconds) + { + StringBuilder builder = new StringBuilder(); + if (seconds >= 3600) + { + builder.append((int) Math.floor(seconds / 3600) + ";"); + } + seconds %= 3600; + if (builder.toString().equals("")) + { + builder.append((int) Math.floor(seconds / 60)); + } + else + { + builder.append(StringUtils.leftPad(String.valueOf((int) Math.floor(seconds / 60)), 2, '0')); + } + builder.append(":"); + seconds %= 60; + builder.append(StringUtils.leftPad(String.valueOf(seconds), 2, '0')); + return builder.toString(); + } + + private void updateTooltip() + { + StringBuilder builder = new StringBuilder(); + if (upperTime == -1) + { + tooltip = null; + return; + } + builder.append("Upper level: " + secondsToTime(upperTime)); + if (middleTime == -1) + { + if (lowerTime == -1) + { + tooltip = builder.toString(); + return; + } + else + { + builder.append("
Lower level: " + secondsToTime(lowerTime - upperTime)); + } + } + else + { + builder.append("
Middle level: " + secondsToTime(middleTime - upperTime)); + if (lowerTime == -1) + { + tooltip = builder.toString(); + return; + } + else + { + builder.append("
Lower level: " + secondsToTime(lowerTime - middleTime)); + } + } + if (raidTime == -1) + { + tooltip = builder.toString(); + return; + } + builder.append("
Olm: " + secondsToTime(raidTime - lowerTime)); + tooltip = builder.toString(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java index 5e4c98f4c8..ba6de9983f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java @@ -1,121 +1,122 @@ -/* - * Copyright (c) 2018, Kamiel - * 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.raids; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.text.NumberFormat; -import java.util.Locale; -import javax.inject.Inject; -import net.runelite.api.Client; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; -import net.runelite.api.Varbits; -import static net.runelite.client.plugins.raids.RaidsPlugin.POINTS_FORMAT; -import net.runelite.client.ui.overlay.Overlay; -import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; -import net.runelite.client.ui.overlay.OverlayMenuEntry; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; - -public class RaidsPointsOverlay extends Overlay -{ - @Inject - private Client client; - - @Inject - private RaidsPlugin plugin; - - private final PanelComponent panel = new PanelComponent(); - - private static final NumberFormat UNIQUE_FORMAT = NumberFormat.getPercentInstance(Locale.ENGLISH); - static - { - UNIQUE_FORMAT.setMaximumFractionDigits(2); - UNIQUE_FORMAT.setMinimumFractionDigits(2); - } - - @Inject - private RaidsPointsOverlay(RaidsPlugin plugin) - { - super(plugin); - setPosition(OverlayPosition.TOP_RIGHT); - setPriority(OverlayPriority.HIGH); - getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Raids overlay")); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isInRaidChambers()) - { - return null; - } - - int totalPoints = client.getVar(Varbits.TOTAL_POINTS); - int personalPoints = client.getVar(Varbits.PERSONAL_POINTS); - int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); - double uniqueChance = totalPoints / 867500f; - - panel.getChildren().clear(); - panel.getChildren().add(LineComponent.builder() - .left("Total:") - .right(POINTS_FORMAT.format(totalPoints)) - .build()); - - panel.getChildren().add(LineComponent.builder() - .left(client.getLocalPlayer().getName() + ":") - .right(POINTS_FORMAT.format(personalPoints)) - .build()); - - - if (partySize > 1) - { - panel.getChildren().add(LineComponent.builder() - .left("Party size:") - .right(String.valueOf(partySize)) - .build()); - } - - panel.getChildren().add(LineComponent.builder() - .left("Unique:") - .right(UNIQUE_FORMAT.format(uniqueChance)) - .build()); - //TODO this is annoyingly bugged, personalpoints returns null for some reason -/* - if (partySize > 1) - { - double personalChance = uniqueChance * (double)(personalPoints / totalPoints); - - panel.getChildren().add(LineComponent.builder() - .left("Personal:") - .right(UNIQUE_FORMAT.format(personalChance)) - .build()); - }*/ - - return panel.render(graphics); - } +/* + * Copyright (c) 2018, Kamiel + * 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.raids; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.text.NumberFormat; +import java.util.Locale; +import javax.inject.Inject; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.api.Varbits; +import static net.runelite.client.plugins.raids.RaidsPlugin.POINTS_FORMAT; +import net.runelite.client.ui.overlay.Overlay; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +public class RaidsPointsOverlay extends Overlay +{ + @Inject + private Client client; + + @Inject + private RaidsPlugin plugin; + + private final PanelComponent panel = new PanelComponent(); + + private static final NumberFormat UNIQUE_FORMAT = NumberFormat.getPercentInstance(Locale.ENGLISH); + + static + { + UNIQUE_FORMAT.setMaximumFractionDigits(2); + UNIQUE_FORMAT.setMinimumFractionDigits(2); + } + + @Inject + private RaidsPointsOverlay(RaidsPlugin plugin) + { + super(plugin); + setPosition(OverlayPosition.TOP_RIGHT); + setPriority(OverlayPriority.HIGH); + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Raids overlay")); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isInRaidChambers()) + { + return null; + } + + int totalPoints = client.getVar(Varbits.TOTAL_POINTS); + int personalPoints = client.getVar(Varbits.PERSONAL_POINTS); + int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); + double uniqueChance = totalPoints / 867500f; + + panel.getChildren().clear(); + panel.getChildren().add(LineComponent.builder() + .left("Total:") + .right(POINTS_FORMAT.format(totalPoints)) + .build()); + + panel.getChildren().add(LineComponent.builder() + .left(client.getLocalPlayer().getName() + ":") + .right(POINTS_FORMAT.format(personalPoints)) + .build()); + + + if (partySize > 1) + { + panel.getChildren().add(LineComponent.builder() + .left("Party size:") + .right(String.valueOf(partySize)) + .build()); + } + + panel.getChildren().add(LineComponent.builder() + .left("Unique:") + .right(UNIQUE_FORMAT.format(uniqueChance)) + .build()); + //TODO this is annoyingly bugged, personalpoints returns null for some reason +/* + if (partySize > 1) + { + double personalChance = uniqueChance * (double)(personalPoints / totalPoints); + + panel.getChildren().add(LineComponent.builder() + .left("Personal:") + .right(UNIQUE_FORMAT.format(personalChance)) + .build()); + }*/ + + return panel.render(graphics); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutConfig.java index 857afd3a4d..78dc54f534 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutConfig.java @@ -4,7 +4,8 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; @ConfigGroup("shortcut") -public interface ShortcutConfig { +public interface ShortcutConfig +{ @ConfigItem( keyName = "highlightShortcuts", name = "Highlight shortcuts", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java index c23c99521f..6ae37169e8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java @@ -4,9 +4,7 @@ import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.image.BufferedImage; - import javax.inject.Inject; - import net.runelite.api.Client; import net.runelite.api.GameObject; import net.runelite.api.Perspective; @@ -27,7 +25,7 @@ public class ShortcutOverlay extends Overlay private final BufferedImage treeIcon; private final BufferedImage strengthIcon; private final BufferedImage miningIcon; - + @Inject ShortcutOverlay(Client client, ShortcutConfig config, ShortcutPlugin plugin, SkillIconManager iconManager) { @@ -37,72 +35,72 @@ public class ShortcutOverlay extends Overlay setPosition(OverlayPosition.DYNAMIC); setPriority(OverlayPriority.LOW); setLayer(OverlayLayer.ABOVE_SCENE); - + treeIcon = iconManager.getSkillImage(Skill.WOODCUTTING); strengthIcon = iconManager.getSkillImage(Skill.STRENGTH); miningIcon = iconManager.getSkillImage(Skill.MINING); } - + @Override - public Dimension render(Graphics2D graphics) + public Dimension render(Graphics2D graphics) { - for (TileObject shortcut : plugin.getShortcut()) + for (TileObject shortcut : plugin.getShortcut()) { - if (shortcut.getPlane() == client.getPlane()) + if (shortcut.getPlane() == client.getPlane()) { Polygon poly; - if ((shortcut instanceof GameObject)) + if ((shortcut instanceof GameObject)) { poly = ((GameObject) shortcut).getConvexHull(); } - else + else { poly = shortcut.getCanvasTilePoly(); } - if (poly != null) + if (poly != null) { String name; - switch (shortcut.getId()) + switch (shortcut.getId()) { - case 29736: - name = "Tree"; - break; - case 29738: - name = "Rocks"; - break; - case 297480: - name = "Boulder"; - break; - case 29737: - case 29739: - default: - name = "null"; + case 29736: + name = "Tree"; + break; + case 29738: + name = "Rocks"; + break; + case 297480: + name = "Boulder"; + break; + case 29737: + case 29739: + default: + name = "null"; } if (config.highlightShortcuts()) { - if (name.equals("Tree")) + if (name.equals("Tree")) { Point canvasLoc = Perspective.getCanvasImageLocation(client, shortcut.getLocalLocation(), - treeIcon, 150); - if (canvasLoc != null) + treeIcon, 150); + if (canvasLoc != null) { graphics.drawImage(treeIcon, canvasLoc.getX(), canvasLoc.getY(), null); } } - if (name.equals("Rocks")) + if (name.equals("Rocks")) { Point canvasLoc = Perspective.getCanvasImageLocation(client, shortcut.getLocalLocation(), - miningIcon, 150); - if (canvasLoc != null) + miningIcon, 150); + if (canvasLoc != null) { graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null); } } - if (name.equals("Boulder")) + if (name.equals("Boulder")) { Point canvasLoc = Perspective.getCanvasImageLocation(client, shortcut.getLocalLocation(), - strengthIcon, 150); - if (canvasLoc != null) + strengthIcon, 150); + if (canvasLoc != null) { graphics.drawImage(strengthIcon, canvasLoc.getX(), canvasLoc.getY(), null); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutPlugin.java index 30fb3b2e42..ec60f730f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutPlugin.java @@ -1,13 +1,10 @@ package net.runelite.client.plugins.raids.shortcuts; +import com.google.inject.Provides; import java.util.ArrayList; import java.util.Iterator; import java.util.List; - import javax.inject.Inject; - -import com.google.inject.Provides; - import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.TileObject; @@ -31,58 +28,58 @@ public class ShortcutPlugin extends Plugin { @Inject private Client client; - + @Inject private OverlayManager overlayManager; - + @Inject private ShortcutOverlay overlay; - + private final List shortcut = new ArrayList<>(); - + List getShortcut() { return shortcut; } - + @Provides ShortcutConfig provideConfig(ConfigManager configManager) { - return (ShortcutConfig)configManager.getConfig(ShortcutConfig.class); + return configManager.getConfig(ShortcutConfig.class); } - + @Override protected void startUp() { overlayManager.add(overlay); } - + @Override protected void shutDown() { overlayManager.remove(overlay); } - + @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) + public void onGameObjectSpawned(GameObjectSpawned event) { WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, event.getGameObject().getLocalLocation()); if (worldPoint == null) { return; } - if ((event.getGameObject().getId() == 29740) || (event.getGameObject().getId() == 29736) || (event.getGameObject().getId() == 29738)) + if ((event.getGameObject().getId() == 29740) || (event.getGameObject().getId() == 29736) || (event.getGameObject().getId() == 29738)) { shortcut.add(event.getGameObject()); } - } - + } + @Subscribe public void onGameObjectDespawned(GameObjectDespawned event) { shortcut.remove(event.getGameObject()); } - + @Subscribe public void onGameTick(GameTick tick) { @@ -93,8 +90,8 @@ public class ShortcutPlugin extends Plugin Iterator it = shortcut.iterator(); while (it.hasNext()) { - TileObject object = (TileObject)it.next(); - if (object.getCanvasLocation() == null) + TileObject object = it.next(); + if (object.getCanvasLocation() == null) { it.remove(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/LayoutSolver.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/LayoutSolver.java index 10cba7bf20..c06a7ffc0b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/LayoutSolver.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/LayoutSolver.java @@ -1,222 +1,222 @@ -/* - * Copyright (c) 2018, Kamiel - * 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.raids.solver; - -import com.google.inject.Singleton; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -/* - * Implementation of https://github.com/WooxSolo/raids-layout - * Copyright (c) 2017 WooxSolo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - */ -@Slf4j -@Singleton -public class LayoutSolver -{ - @Getter - private static final List layouts = new ArrayList<>(); - private static final Pattern regex = Pattern.compile("^([A-Z]*)\\.([A-Z]*) - #([A-Z]*)#([A-Z]*)$"); - private static final String[] codes = - { - "FSCCP.PCSCF - #WNWSWN#ESEENW", - "FSCCS.PCPSF - #WSEEEN#WSWNWS", - "FSCPC.CSCPF - #WNWWSE#EENWWW", - "SCCFC.PSCSF - #EEENWW#WSEEEN", - "SCCFP.CCSPF - #NESEEN#WSWNWS", - "SCFCP.CCSPF - #ESEENW#ESWWNW", - "SCFCP.CSCFS - #ENEESW#ENWWSW", - "SCFCPC.CSPCSF - #ESWWNWS#NESENES", - "SCFPC.CSPCF - #WSWWNE#WSEENE", - "SCFPC.PCCSF - #WSEENE#WWWSEE", - "SCFPC.SCPCF - #NESENE#WSWWNE", - "SCPFC.CCPSF - #NWWWSE#WNEESE", - "SCPFC.CSPCF - #NEEESW#WWNEEE", - "SCPFC.CSPSF - #WWSEEE#NWSWWN", - "SCSPF.CCSPF - #ESWWNW#ESENES", - "SFCCP.CSCPF - #WNEESE#NWSWWN", - "SFCCS.PCPSF - #ENWWSW#ENESEN", - "SPCFC.CSPCF - #WWNEEE#WSWNWS", - "SPCFC.SCCPF - #ESENES#WWWNEE", - "SPSFP.CCCSF - #NWSWWN#ESEENW", - "SCFCP.CSCPF - #ENESEN#WWWSEE", - "SCPFC.PCSCF - #WNEEES#NWSWNW", - "SFCCPC.PCSCPF - #WSEENES#WWWNEEE", - "FSPCC.PSCCF - #WWWSEE#ENWWSW", - "FSCCP.PCSCF - #ENWWWS#NEESEN", - "SCPFC.CCSSF - #NEESEN#WSWWNE", - }; - - public LayoutSolver() - { - build(); - } - - public Layout findLayout(String code) - { - Layout solution = null; - int matches = 0; - boolean match; - - for (Layout layout : layouts) - { - match = true; - - for (int i = 0; i < code.length(); i++) - { - Room room = layout.getRoomAt(i); - char c = code.charAt(i); - - if (room != null && c != ' ' && c != room.getSymbol()) - { - match = false; - break; - } - } - - if (match) - { - solution = layout; - matches++; - log.debug("Found matching layout: " + layout.toCode()); - } - } - - if (matches == 1) - { - return solution; - } - - return null; - } - - private int calcStart(String directions) - { - int startPos = 0; - int position = 0; - - for (int i = 0; i < directions.length(); i++) - { - char c = directions.charAt(i); - int delta = dirToPosDelta(c); - position += delta; - - if (position < 0 || position >= 8 || (position == 3 && delta == -1) || (position == 4 && delta == 1)) - { - position -= delta; - startPos -= delta; - } - } - - return startPos; - } - - private int dirToPosDelta(char direction) - { - switch (String.valueOf(direction)) - { - case "N": - return -4; - - case "E": - return 1; - - case "S": - return 4; - - case "W": - return -1; - - default: - return 0; - } - } - - private void build() - { - for (String code : codes) - { - Matcher match = regex.matcher(code); - - if (!match.find()) - { - continue; - } - - String symbols, directions; - int position = calcStart(match.group(3)); - Layout layout = new Layout(); - Room lastRoom = null; - Room room; - - for (int floor = 0; floor < 2; floor++) - { - symbols = match.group(1 + floor); - directions = match.group(3 + floor); - - for (int i = 0; i < directions.length(); i++) - { - char symbol = (i == 0 ? '#' : symbols.charAt(i - 1)); - - room = new Room(position, symbol); - - if (lastRoom != null) - { - lastRoom.setNext(room); - room.setPrevious(lastRoom); - } - - layout.add(room); - lastRoom = room; - - int delta = dirToPosDelta(directions.charAt(i)); - position += delta; - } - - room = new Room(position, '¤'); - room.setPrevious(lastRoom); - lastRoom.setNext(room); - layout.add(room); - position += 8; - } - - layouts.add(layout); - } - } -} +/* + * Copyright (c) 2018, Kamiel + * 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.raids.solver; + +import com.google.inject.Singleton; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/* + * Implementation of https://github.com/WooxSolo/raids-layout + * Copyright (c) 2017 WooxSolo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + */ +@Slf4j +@Singleton +public class LayoutSolver +{ + @Getter + private static final List layouts = new ArrayList<>(); + private static final Pattern regex = Pattern.compile("^([A-Z]*)\\.([A-Z]*) - #([A-Z]*)#([A-Z]*)$"); + private static final String[] codes = + { + "FSCCP.PCSCF - #WNWSWN#ESEENW", + "FSCCS.PCPSF - #WSEEEN#WSWNWS", + "FSCPC.CSCPF - #WNWWSE#EENWWW", + "SCCFC.PSCSF - #EEENWW#WSEEEN", + "SCCFP.CCSPF - #NESEEN#WSWNWS", + "SCFCP.CCSPF - #ESEENW#ESWWNW", + "SCFCP.CSCFS - #ENEESW#ENWWSW", + "SCFCPC.CSPCSF - #ESWWNWS#NESENES", + "SCFPC.CSPCF - #WSWWNE#WSEENE", + "SCFPC.PCCSF - #WSEENE#WWWSEE", + "SCFPC.SCPCF - #NESENE#WSWWNE", + "SCPFC.CCPSF - #NWWWSE#WNEESE", + "SCPFC.CSPCF - #NEEESW#WWNEEE", + "SCPFC.CSPSF - #WWSEEE#NWSWWN", + "SCSPF.CCSPF - #ESWWNW#ESENES", + "SFCCP.CSCPF - #WNEESE#NWSWWN", + "SFCCS.PCPSF - #ENWWSW#ENESEN", + "SPCFC.CSPCF - #WWNEEE#WSWNWS", + "SPCFC.SCCPF - #ESENES#WWWNEE", + "SPSFP.CCCSF - #NWSWWN#ESEENW", + "SCFCP.CSCPF - #ENESEN#WWWSEE", + "SCPFC.PCSCF - #WNEEES#NWSWNW", + "SFCCPC.PCSCPF - #WSEENES#WWWNEEE", + "FSPCC.PSCCF - #WWWSEE#ENWWSW", + "FSCCP.PCSCF - #ENWWWS#NEESEN", + "SCPFC.CCSSF - #NEESEN#WSWWNE", + }; + + public LayoutSolver() + { + build(); + } + + public Layout findLayout(String code) + { + Layout solution = null; + int matches = 0; + boolean match; + + for (Layout layout : layouts) + { + match = true; + + for (int i = 0; i < code.length(); i++) + { + Room room = layout.getRoomAt(i); + char c = code.charAt(i); + + if (room != null && c != ' ' && c != room.getSymbol()) + { + match = false; + break; + } + } + + if (match) + { + solution = layout; + matches++; + log.debug("Found matching layout: " + layout.toCode()); + } + } + + if (matches == 1) + { + return solution; + } + + return null; + } + + private int calcStart(String directions) + { + int startPos = 0; + int position = 0; + + for (int i = 0; i < directions.length(); i++) + { + char c = directions.charAt(i); + int delta = dirToPosDelta(c); + position += delta; + + if (position < 0 || position >= 8 || (position == 3 && delta == -1) || (position == 4 && delta == 1)) + { + position -= delta; + startPos -= delta; + } + } + + return startPos; + } + + private int dirToPosDelta(char direction) + { + switch (String.valueOf(direction)) + { + case "N": + return -4; + + case "E": + return 1; + + case "S": + return 4; + + case "W": + return -1; + + default: + return 0; + } + } + + private void build() + { + for (String code : codes) + { + Matcher match = regex.matcher(code); + + if (!match.find()) + { + continue; + } + + String symbols, directions; + int position = calcStart(match.group(3)); + Layout layout = new Layout(); + Room lastRoom = null; + Room room; + + for (int floor = 0; floor < 2; floor++) + { + symbols = match.group(1 + floor); + directions = match.group(3 + floor); + + for (int i = 0; i < directions.length(); i++) + { + char symbol = (i == 0 ? '#' : symbols.charAt(i - 1)); + + room = new Room(position, symbol); + + if (lastRoom != null) + { + lastRoom.setNext(room); + room.setPrevious(lastRoom); + } + + layout.add(room); + lastRoom = room; + + int delta = dirToPosDelta(directions.charAt(i)); + position += delta; + } + + room = new Room(position, '¤'); + room.setPrevious(lastRoom); + lastRoom.setNext(room); + layout.add(room); + position += 8; + } + + layouts.add(layout); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/RotationSolver.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/RotationSolver.java index 1acf3ed2df..52f363a28f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/RotationSolver.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/solver/RotationSolver.java @@ -1,150 +1,150 @@ -/* - * Copyright (c) 2018, Kamiel - * 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.raids.solver; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import net.runelite.client.plugins.raids.RaidRoom; -import net.runelite.client.plugins.raids.RaidRoom.Boss; - -public class RotationSolver -{ - private static class Rotation extends ArrayList - { - Rotation(Collection bosses) - { - super(bosses); - } - - @Override - public E get(int index) - { - if (index < 0) - { - index = index + size(); - } - - return super.get(index % size()); - } - } - - private static final Rotation[] ROTATIONS = - { - new Rotation<>(Arrays.asList(Boss.TEKTON, Boss.VASA, Boss.GUARDIANS, Boss.MYSTICS, Boss.SHAMANS, Boss.MUTTADILES, Boss.VANGUARDS, Boss.VESPULA)), - new Rotation<>(Arrays.asList(Boss.TEKTON, Boss.MUTTADILES, Boss.GUARDIANS, Boss.VESPULA, Boss.SHAMANS, Boss.VASA, Boss.VANGUARDS, Boss.MYSTICS)), - new Rotation<>(Arrays.asList(Boss.VESPULA, Boss.VANGUARDS, Boss.MUTTADILES, Boss.SHAMANS, Boss.MYSTICS, Boss.GUARDIANS, Boss.VASA, Boss.TEKTON)), - new Rotation<>(Arrays.asList(Boss.MYSTICS, Boss.VANGUARDS, Boss.VASA, Boss.SHAMANS, Boss.VESPULA, Boss.GUARDIANS, Boss.MUTTADILES, Boss.TEKTON)) - }; - - public static boolean solve(RaidRoom[] rooms) - { - if (rooms == null) - { - return false; - } - - Rotation match = null; - Integer start = null; - Integer index = null; - int known = 0; - - for (int i = 0; i < rooms.length; i++) - { - if (rooms[i] == null || rooms[i].getBoss() == null || rooms[i].getBoss() == Boss.UNKNOWN) - { - continue; - } - - if (start == null) - { - start = i; - } - - known++; - } - - if (known < 2) - { - return false; - } - - if (known == rooms.length) - { - return true; - } - - for (Rotation rotation : ROTATIONS) - { - COMPARE: - for (int i = 0; i < rotation.size(); i++) - { - if (rooms[start].getBoss() == rotation.get(i)) - { - for (int j = start + 1; j < rooms.length; j++) - { - if (rooms[j].getBoss() == null || rooms[j].getBoss() == Boss.UNKNOWN) - { - continue; - } - - if (rooms[j].getBoss() != rotation.get(i + j - start)) - { - break COMPARE; - } - } - - if (match != null && match != rotation) - { - return false; - } - - index = i - start; - match = rotation; - } - } - } - - if (match == null) - { - return false; - } - - for (int i = 0; i < rooms.length; i++) - { - if (rooms[i] == null) - { - continue; - } - - if (rooms[i].getBoss() == null || rooms[i].getBoss() == Boss.UNKNOWN) - { - rooms[i].setBoss(match.get(index + i)); - } - } - - return true; - } -} +/* + * Copyright (c) 2018, Kamiel + * 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.raids.solver; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import net.runelite.client.plugins.raids.RaidRoom; +import net.runelite.client.plugins.raids.RaidRoom.Boss; + +public class RotationSolver +{ + private static class Rotation extends ArrayList + { + Rotation(Collection bosses) + { + super(bosses); + } + + @Override + public E get(int index) + { + if (index < 0) + { + index = index + size(); + } + + return super.get(index % size()); + } + } + + private static final Rotation[] ROTATIONS = + { + new Rotation<>(Arrays.asList(Boss.TEKTON, Boss.VASA, Boss.GUARDIANS, Boss.MYSTICS, Boss.SHAMANS, Boss.MUTTADILES, Boss.VANGUARDS, Boss.VESPULA)), + new Rotation<>(Arrays.asList(Boss.TEKTON, Boss.MUTTADILES, Boss.GUARDIANS, Boss.VESPULA, Boss.SHAMANS, Boss.VASA, Boss.VANGUARDS, Boss.MYSTICS)), + new Rotation<>(Arrays.asList(Boss.VESPULA, Boss.VANGUARDS, Boss.MUTTADILES, Boss.SHAMANS, Boss.MYSTICS, Boss.GUARDIANS, Boss.VASA, Boss.TEKTON)), + new Rotation<>(Arrays.asList(Boss.MYSTICS, Boss.VANGUARDS, Boss.VASA, Boss.SHAMANS, Boss.VESPULA, Boss.GUARDIANS, Boss.MUTTADILES, Boss.TEKTON)) + }; + + public static boolean solve(RaidRoom[] rooms) + { + if (rooms == null) + { + return false; + } + + Rotation match = null; + Integer start = null; + Integer index = null; + int known = 0; + + for (int i = 0; i < rooms.length; i++) + { + if (rooms[i] == null || rooms[i].getBoss() == null || rooms[i].getBoss() == Boss.UNKNOWN) + { + continue; + } + + if (start == null) + { + start = i; + } + + known++; + } + + if (known < 2) + { + return false; + } + + if (known == rooms.length) + { + return true; + } + + for (Rotation rotation : ROTATIONS) + { + COMPARE: + for (int i = 0; i < rotation.size(); i++) + { + if (rooms[start].getBoss() == rotation.get(i)) + { + for (int j = start + 1; j < rooms.length; j++) + { + if (rooms[j].getBoss() == null || rooms[j].getBoss() == Boss.UNKNOWN) + { + continue; + } + + if (rooms[j].getBoss() != rotation.get(i + j - start)) + { + break COMPARE; + } + } + + if (match != null && match != rotation) + { + return false; + } + + index = i - start; + match = rotation; + } + } + } + + if (match == null) + { + return false; + } + + for (int i = 0; i < rooms.length; i++) + { + if (rooms[i] == null) + { + continue; + } + + if (rooms[i].getBoss() == null || rooms[i].getBoss() == Boss.UNKNOWN) + { + rooms[i].setBoss(match.get(index + i)); + } + } + + return true; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java index ebbad81a54..ae285cf44b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java @@ -1,193 +1,193 @@ -/* - * Copyright (c) 2018, Tim Lehner - * 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.raidsthieving.BatSolver; - -import java.util.Map; -import java.util.HashSet; -import java.util.HashMap; -import java.util.TreeSet; -import java.util.List; -import java.util.ArrayList; -import static net.runelite.client.plugins.raidsthieving.BatSolver.SolutionSet.SOLUTION_SETS; - -public class BatSolver -{ - private Map numberOfSolutionsWithPoison; - private final SolutionSet solution; - - private final HashSet grubsChests; - - public BatSolver(ThievingRoomType roomType) - { - solution = new SolutionSet(roomType); - grubsChests = new HashSet<>(); - } - - public void addEmptyChest(int chestId) - { - // When a new empty chest is found, add it to the current solution set - solution.addEmptyChest(chestId); - calculateChanceOfPoison(); - } - - public void addGrubsChest(int chestId) - { - // When a chest with grubs is found, keep track of it to invalidate solutions - grubsChests.add(chestId); - calculateChanceOfPoison(); - } - - public TreeSet matchSolutions() - { - TreeSet possibleEmptyChests = new TreeSet<>(); - for (SolutionSet knownSolution : SolutionSet.SOLUTION_SETS) - { - if (knownSolution.getType() == solution.getType() && matchSolution(knownSolution)) - { - possibleEmptyChests.addAll(knownSolution.getEmptyChests()); - } - } - - return possibleEmptyChests; - } - - private boolean matchSolution(SolutionSet testSolution) - { - for (Integer grubsChest : grubsChests) - { - if (testSolution.containsChest(grubsChest)) - { - // If one of the chests is known to have grubs, it cannot be a solution - return false; - } - } - - boolean matchesAll = true; - boolean everMatched = false; - for (int i : solution.getEmptyChests()) - { - if (!testSolution.containsChest(i)) - { - matchesAll = false; - } - else - { - everMatched = true; - } - } - return matchesAll && everMatched; - } - - public ThievingRoomType getType() - { - return solution.getType(); - } - - - public void calculateChanceOfPoison() - { - if (getType() == null) - { - numberOfSolutionsWithPoison = null; - return; - } - - numberOfSolutionsWithPoison = new HashMap<>(); - for (SolutionSet sol : getPosssibleSolutions()) - { - if (getType() == sol.getType() && (solution.getEmptyChests().size() == 0 || matchSolution(sol))) - { - for (Integer i : sol.getEmptyChests()) - { - if (numberOfSolutionsWithPoison.containsKey(i)) - { - numberOfSolutionsWithPoison.put(i, numberOfSolutionsWithPoison.get(i) + 1); - } - else - { - numberOfSolutionsWithPoison.put(i, 1); - } - } - } - } - } - - private List getPosssibleSolutions() - { - List possibleSolutions = new ArrayList<>(); - for (SolutionSet soln : SOLUTION_SETS) - { - // Check if we've found grubs in one of the chests, invalidating it as an solution - boolean foundMatch = false; - for (int i : grubsChests) - { - if (soln.containsChest(i)) - { - foundMatch = true; - } - } - if (!foundMatch) - { - possibleSolutions.add(soln); - } - } - return possibleSolutions; - } - - public double relativeLikelihoodPoison(int chestId) - { - // Returns a double between 0 and 1 of how likely the chest has poison based on the number of possible solutions - // Uses a Sigmoid like function to give good contrast in drawn opacity, - // perhaps could be changed to something more accurate quantitavely. - if (numberOfSolutionsWithPoison == null) - { - calculateChanceOfPoison(); - } - if (numberOfSolutionsWithPoison == null) - { - return 1.0; - } - int mostFrequentPoison = 0; - for (Map.Entry entry : numberOfSolutionsWithPoison.entrySet()) - { - if (entry.getValue() > mostFrequentPoison) - { - mostFrequentPoison = entry.getValue(); - } - } - int timesFound = 0; - if (numberOfSolutionsWithPoison.containsKey(chestId)) - { - timesFound = numberOfSolutionsWithPoison.get(chestId); - } - double chestChance = (double) (timesFound) / (double) (mostFrequentPoison); - return 1. / (1 + Math.exp(5 - 10 * chestChance)); - } - - public int getNumberOfEmptyChests() - { - return solution.getEmptyChests().size(); - } -} +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; +import static net.runelite.client.plugins.raidsthieving.BatSolver.SolutionSet.SOLUTION_SETS; + +public class BatSolver +{ + private Map numberOfSolutionsWithPoison; + private final SolutionSet solution; + + private final HashSet grubsChests; + + public BatSolver(ThievingRoomType roomType) + { + solution = new SolutionSet(roomType); + grubsChests = new HashSet<>(); + } + + public void addEmptyChest(int chestId) + { + // When a new empty chest is found, add it to the current solution set + solution.addEmptyChest(chestId); + calculateChanceOfPoison(); + } + + public void addGrubsChest(int chestId) + { + // When a chest with grubs is found, keep track of it to invalidate solutions + grubsChests.add(chestId); + calculateChanceOfPoison(); + } + + public TreeSet matchSolutions() + { + TreeSet possibleEmptyChests = new TreeSet<>(); + for (SolutionSet knownSolution : SolutionSet.SOLUTION_SETS) + { + if (knownSolution.getType() == solution.getType() && matchSolution(knownSolution)) + { + possibleEmptyChests.addAll(knownSolution.getEmptyChests()); + } + } + + return possibleEmptyChests; + } + + private boolean matchSolution(SolutionSet testSolution) + { + for (Integer grubsChest : grubsChests) + { + if (testSolution.containsChest(grubsChest)) + { + // If one of the chests is known to have grubs, it cannot be a solution + return false; + } + } + + boolean matchesAll = true; + boolean everMatched = false; + for (int i : solution.getEmptyChests()) + { + if (!testSolution.containsChest(i)) + { + matchesAll = false; + } + else + { + everMatched = true; + } + } + return matchesAll && everMatched; + } + + public ThievingRoomType getType() + { + return solution.getType(); + } + + + public void calculateChanceOfPoison() + { + if (getType() == null) + { + numberOfSolutionsWithPoison = null; + return; + } + + numberOfSolutionsWithPoison = new HashMap<>(); + for (SolutionSet sol : getPosssibleSolutions()) + { + if (getType() == sol.getType() && (solution.getEmptyChests().size() == 0 || matchSolution(sol))) + { + for (Integer i : sol.getEmptyChests()) + { + if (numberOfSolutionsWithPoison.containsKey(i)) + { + numberOfSolutionsWithPoison.put(i, numberOfSolutionsWithPoison.get(i) + 1); + } + else + { + numberOfSolutionsWithPoison.put(i, 1); + } + } + } + } + } + + private List getPosssibleSolutions() + { + List possibleSolutions = new ArrayList<>(); + for (SolutionSet soln : SOLUTION_SETS) + { + // Check if we've found grubs in one of the chests, invalidating it as an solution + boolean foundMatch = false; + for (int i : grubsChests) + { + if (soln.containsChest(i)) + { + foundMatch = true; + } + } + if (!foundMatch) + { + possibleSolutions.add(soln); + } + } + return possibleSolutions; + } + + public double relativeLikelihoodPoison(int chestId) + { + // Returns a double between 0 and 1 of how likely the chest has poison based on the number of possible solutions + // Uses a Sigmoid like function to give good contrast in drawn opacity, + // perhaps could be changed to something more accurate quantitavely. + if (numberOfSolutionsWithPoison == null) + { + calculateChanceOfPoison(); + } + if (numberOfSolutionsWithPoison == null) + { + return 1.0; + } + int mostFrequentPoison = 0; + for (Map.Entry entry : numberOfSolutionsWithPoison.entrySet()) + { + if (entry.getValue() > mostFrequentPoison) + { + mostFrequentPoison = entry.getValue(); + } + } + int timesFound = 0; + if (numberOfSolutionsWithPoison.containsKey(chestId)) + { + timesFound = numberOfSolutionsWithPoison.get(chestId); + } + double chestChance = (double) (timesFound) / (double) (mostFrequentPoison); + return 1. / (1 + Math.exp(5 - 10 * chestChance)); + } + + public int getNumberOfEmptyChests() + { + return solution.getEmptyChests().size(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java index 7346e4ecf6..5fab1e39d5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java @@ -1,261 +1,261 @@ -/* - * Copyright (c) 2018, Tim Lehner - * 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.raidsthieving.BatSolver; - -import net.runelite.client.plugins.raidsthieving.InstancePoint; -import net.runelite.client.plugins.raidsthieving.ThievingChest; -import java.util.HashMap; -import java.util.Map; - -public class ChestIdentifier -{ - public ChestIdentifier(ThievingRoomType roomType) - { - chestIds = new HashMap<>(); - switch (roomType) - { - case LEFT_TURN: - chestIds.put(new InstancePoint(3283, 5379), 1); - chestIds.put(new InstancePoint(3285, 5380), 2); - chestIds.put(new InstancePoint(3279, 5381), 3); - chestIds.put(new InstancePoint(3287, 5382), 4); - chestIds.put(new InstancePoint(3281, 5382), 5); - chestIds.put(new InstancePoint(3284, 5383), 6); - chestIds.put(new InstancePoint(3283, 5384), 7); - chestIds.put(new InstancePoint(3286, 5384), 8); - chestIds.put(new InstancePoint(3288, 5384), 9); - chestIds.put(new InstancePoint(3277, 5385), 10); - chestIds.put(new InstancePoint(3280, 5385), 11); - chestIds.put(new InstancePoint(3285, 5386), 12); - chestIds.put(new InstancePoint(3290, 5386), 13); - chestIds.put(new InstancePoint(3275, 5387), 14); - chestIds.put(new InstancePoint(3287, 5387), 15); - chestIds.put(new InstancePoint(3288, 5387), 16); - chestIds.put(new InstancePoint(3281, 5388), 17); - chestIds.put(new InstancePoint(3291, 5388), 18); - chestIds.put(new InstancePoint(3280, 5389), 19); - chestIds.put(new InstancePoint(3285, 5389), 20); - chestIds.put(new InstancePoint(3289, 5389), 21); - chestIds.put(new InstancePoint(3283, 5390), 22); - chestIds.put(new InstancePoint(3285, 5390), 23); - chestIds.put(new InstancePoint(3288, 5390), 24); - chestIds.put(new InstancePoint(3290, 5390), 25); - chestIds.put(new InstancePoint(3282, 5391), 26); - chestIds.put(new InstancePoint(3289, 5391), 27); - chestIds.put(new InstancePoint(3292, 5391), 28); - chestIds.put(new InstancePoint(3279, 5392), 29); - chestIds.put(new InstancePoint(3276, 5393), 30); - chestIds.put(new InstancePoint(3279, 5393), 31); - chestIds.put(new InstancePoint(3284, 5393), 32); - chestIds.put(new InstancePoint(3285, 5393), 33); - chestIds.put(new InstancePoint(3291, 5393), 34); - chestIds.put(new InstancePoint(3275, 5394), 35); - chestIds.put(new InstancePoint(3277, 5394), 36); - chestIds.put(new InstancePoint(3288, 5394), 37); - chestIds.put(new InstancePoint(3276, 5395), 38); - chestIds.put(new InstancePoint(3281, 5395), 39); - chestIds.put(new InstancePoint(3285, 5395), 40); - chestIds.put(new InstancePoint(3287, 5395), 41); - chestIds.put(new InstancePoint(3289, 5395), 42); - chestIds.put(new InstancePoint(3274, 5396), 43); - chestIds.put(new InstancePoint(3283, 5396), 44); - chestIds.put(new InstancePoint(3285, 5396), 45); - chestIds.put(new InstancePoint(3288, 5396), 46); - chestIds.put(new InstancePoint(3272, 5397), 47); - chestIds.put(new InstancePoint(3280, 5397), 48); - chestIds.put(new InstancePoint(3277, 5398), 49); - chestIds.put(new InstancePoint(3281, 5398), 50); - chestIds.put(new InstancePoint(3284, 5398), 51); - chestIds.put(new InstancePoint(3276, 5399), 52); - chestIds.put(new InstancePoint(3278, 5399), 53); - chestIds.put(new InstancePoint(3283, 5399), 54); - chestIds.put(new InstancePoint(3285, 5399), 55); - chestIds.put(new InstancePoint(3277, 5400), 56); - chestIds.put(new InstancePoint(3284, 5400), 57); - chestIds.put(new InstancePoint(3288, 5400), 58); - chestIds.put(new InstancePoint(3281, 5401), 59); - chestIds.put(new InstancePoint(3286, 5401), 60); - chestIds.put(new InstancePoint(3279, 5402), 61); - chestIds.put(new InstancePoint(3285, 5402), 62); - chestIds.put(new InstancePoint(3280, 5403), 63); - chestIds.put(new InstancePoint(3283, 5403), 64); - break; - case RIGHT_TURN: - chestIds.put(new InstancePoint(3338, 5405), 1); - chestIds.put(new InstancePoint(3334, 5405), 2); - chestIds.put(new InstancePoint(3342, 5404), 3); - chestIds.put(new InstancePoint(3340, 5404), 4); - chestIds.put(new InstancePoint(3345, 5403), 5); - chestIds.put(new InstancePoint(3334, 5403), 6); - chestIds.put(new InstancePoint(3330, 5403), 7); - chestIds.put(new InstancePoint(3343, 5402), 8); - chestIds.put(new InstancePoint(3342, 5402), 9); - chestIds.put(new InstancePoint(3339, 5402), 10); - chestIds.put(new InstancePoint(3338, 5402), 11); - chestIds.put(new InstancePoint(3336, 5402), 12); - chestIds.put(new InstancePoint(3347, 5401), 13); - chestIds.put(new InstancePoint(3330, 5401), 14); - chestIds.put(new InstancePoint(3345, 5400), 15); - chestIds.put(new InstancePoint(3341, 5400), 16); - chestIds.put(new InstancePoint(3337, 5400), 17); - chestIds.put(new InstancePoint(3334, 5400), 18); - chestIds.put(new InstancePoint(3345, 5399), 19); - chestIds.put(new InstancePoint(3343, 5399), 20); - chestIds.put(new InstancePoint(3340, 5399), 21); - chestIds.put(new InstancePoint(3335, 5399), 22); - chestIds.put(new InstancePoint(3331, 5399), 23); - chestIds.put(new InstancePoint(3338, 5398), 24); - chestIds.put(new InstancePoint(3337, 5398), 25); - chestIds.put(new InstancePoint(3345, 5397), 26); - chestIds.put(new InstancePoint(3341, 5397), 27); - chestIds.put(new InstancePoint(3334, 5397), 28); - chestIds.put(new InstancePoint(3331, 5397), 29); - chestIds.put(new InstancePoint(3346, 5396), 30); - chestIds.put(new InstancePoint(3343, 5396), 31); - chestIds.put(new InstancePoint(3339, 5396), 32); - chestIds.put(new InstancePoint(3335, 5396), 33); - chestIds.put(new InstancePoint(3333, 5396), 34); - chestIds.put(new InstancePoint(3340, 5395), 35); - chestIds.put(new InstancePoint(3337, 5395), 36); - chestIds.put(new InstancePoint(3334, 5395), 37); - chestIds.put(new InstancePoint(3345, 5394), 38); - chestIds.put(new InstancePoint(3342, 5394), 39); - chestIds.put(new InstancePoint(3332, 5394), 40); - chestIds.put(new InstancePoint(3343, 5393), 41); - chestIds.put(new InstancePoint(3341, 5393), 42); - chestIds.put(new InstancePoint(3338, 5393), 43); - chestIds.put(new InstancePoint(3335, 5393), 44); - chestIds.put(new InstancePoint(3334, 5393), 45); - chestIds.put(new InstancePoint(3346, 5392), 46); - chestIds.put(new InstancePoint(3342, 5392), 47); - chestIds.put(new InstancePoint(3332, 5392), 48); - chestIds.put(new InstancePoint(3350, 5391), 49); - chestIds.put(new InstancePoint(3346, 5391), 50); - chestIds.put(new InstancePoint(3340, 5391), 51); - chestIds.put(new InstancePoint(3339, 5391), 52); - chestIds.put(new InstancePoint(3336, 5391), 53); - chestIds.put(new InstancePoint(3333, 5391), 54); - chestIds.put(new InstancePoint(3349, 5390), 55); - chestIds.put(new InstancePoint(3343, 5390), 56); - chestIds.put(new InstancePoint(3337, 5390), 57); - chestIds.put(new InstancePoint(3335, 5390), 58); - chestIds.put(new InstancePoint(3344, 5389), 59); - chestIds.put(new InstancePoint(3340, 5389), 60); - chestIds.put(new InstancePoint(3336, 5389), 61); - chestIds.put(new InstancePoint(3333, 5389), 62); - chestIds.put(new InstancePoint(3346, 5388), 63); - chestIds.put(new InstancePoint(3340, 5387), 64); - chestIds.put(new InstancePoint(3337, 5386), 65); - chestIds.put(new InstancePoint(3333, 5386), 66); - chestIds.put(new InstancePoint(3338, 5385), 67); - chestIds.put(new InstancePoint(3336, 5385), 68); - chestIds.put(new InstancePoint(3337, 5384), 69); - chestIds.put(new InstancePoint(3340, 5382), 70); - chestIds.put(new InstancePoint(3334, 5383), 71); - chestIds.put(new InstancePoint(3340, 5379), 72); - chestIds.put(new InstancePoint(3338, 5380), 73); - chestIds.put(new InstancePoint(3336, 5381), 74); - break; - case STRAIGHT: - chestIds.put(new InstancePoint(3308, 5378), 1); - chestIds.put(new InstancePoint(3305, 5379), 2); - chestIds.put(new InstancePoint(3307, 5379), 3); - chestIds.put(new InstancePoint(3304, 5381), 4); - chestIds.put(new InstancePoint(3310, 5381), 5); - chestIds.put(new InstancePoint(3302, 5382), 6); - chestIds.put(new InstancePoint(3307, 5382), 7); - chestIds.put(new InstancePoint(3312, 5382), 8); - chestIds.put(new InstancePoint(3317, 5382), 9); - chestIds.put(new InstancePoint(3319, 5382), 10); - chestIds.put(new InstancePoint(3304, 5383), 11); - chestIds.put(new InstancePoint(3305, 5383), 12); - chestIds.put(new InstancePoint(3307, 5383), 13); - chestIds.put(new InstancePoint(3310, 5383), 14); - chestIds.put(new InstancePoint(3315, 5383), 15); - chestIds.put(new InstancePoint(3320, 5383), 16); - chestIds.put(new InstancePoint(3300, 5384), 17); - chestIds.put(new InstancePoint(3309, 5384), 18); - chestIds.put(new InstancePoint(3311, 5384), 19); - chestIds.put(new InstancePoint(3313, 5384), 20); - chestIds.put(new InstancePoint(3317, 5384), 21); - chestIds.put(new InstancePoint(3318, 5384), 22); - chestIds.put(new InstancePoint(3302, 5385), 23); - chestIds.put(new InstancePoint(3306, 5385), 24); - chestIds.put(new InstancePoint(3310, 5385), 25); - chestIds.put(new InstancePoint(3313, 5385), 26); - chestIds.put(new InstancePoint(3320, 5385), 27); - chestIds.put(new InstancePoint(3302, 5386), 28); - chestIds.put(new InstancePoint(3305, 5386), 29); - chestIds.put(new InstancePoint(3316, 5386), 30); - chestIds.put(new InstancePoint(3321, 5386), 31); - chestIds.put(new InstancePoint(3300, 5387), 32); - chestIds.put(new InstancePoint(3308, 5387), 33); - chestIds.put(new InstancePoint(3314, 5387), 34); - chestIds.put(new InstancePoint(3317, 5387), 35); - chestIds.put(new InstancePoint(3301, 5388), 36); - chestIds.put(new InstancePoint(3306, 5388), 37); - chestIds.put(new InstancePoint(3312, 5388), 38); - chestIds.put(new InstancePoint(3322, 5388), 39); - chestIds.put(new InstancePoint(3309, 5389), 40); - chestIds.put(new InstancePoint(3311, 5389), 41); - chestIds.put(new InstancePoint(3313, 5389), 42); - chestIds.put(new InstancePoint(3316, 5389), 43); - chestIds.put(new InstancePoint(3320, 5389), 44); - chestIds.put(new InstancePoint(3300, 5390), 45); - chestIds.put(new InstancePoint(3303, 5390), 46); - chestIds.put(new InstancePoint(3304, 5390), 47); - chestIds.put(new InstancePoint(3312, 5390), 48); - chestIds.put(new InstancePoint(3320, 5390), 49); - chestIds.put(new InstancePoint(3307, 5391), 50); - chestIds.put(new InstancePoint(3310, 5391), 51); - chestIds.put(new InstancePoint(3317, 5391), 52); - chestIds.put(new InstancePoint(3318, 5391), 53); - chestIds.put(new InstancePoint(3323, 5391), 54); - chestIds.put(new InstancePoint(3301, 5392), 55); - chestIds.put(new InstancePoint(3303, 5392), 56); - chestIds.put(new InstancePoint(3309, 5392), 57); - chestIds.put(new InstancePoint(3314, 5392), 58); - chestIds.put(new InstancePoint(3322, 5392), 59); - chestIds.put(new InstancePoint(3305, 5393), 60); - chestIds.put(new InstancePoint(3307, 5393), 61); - chestIds.put(new InstancePoint(3316, 5393), 62); - chestIds.put(new InstancePoint(3309, 5394), 63); - chestIds.put(new InstancePoint(3312, 5394), 64); - chestIds.put(new InstancePoint(3322, 5394), 65); - chestIds.put(new InstancePoint(3310, 5379), 66); - break; - } - - } - - public int indentifyChest(ThievingChest chest) - { - int id = chestIds.get(chest.getInstancePoint()); - chest.setChestId(id); - return id; - } - - private Map chestIds; -} +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +import java.util.HashMap; +import java.util.Map; +import net.runelite.client.plugins.raidsthieving.InstancePoint; +import net.runelite.client.plugins.raidsthieving.ThievingChest; + +public class ChestIdentifier +{ + public ChestIdentifier(ThievingRoomType roomType) + { + chestIds = new HashMap<>(); + switch (roomType) + { + case LEFT_TURN: + chestIds.put(new InstancePoint(3283, 5379), 1); + chestIds.put(new InstancePoint(3285, 5380), 2); + chestIds.put(new InstancePoint(3279, 5381), 3); + chestIds.put(new InstancePoint(3287, 5382), 4); + chestIds.put(new InstancePoint(3281, 5382), 5); + chestIds.put(new InstancePoint(3284, 5383), 6); + chestIds.put(new InstancePoint(3283, 5384), 7); + chestIds.put(new InstancePoint(3286, 5384), 8); + chestIds.put(new InstancePoint(3288, 5384), 9); + chestIds.put(new InstancePoint(3277, 5385), 10); + chestIds.put(new InstancePoint(3280, 5385), 11); + chestIds.put(new InstancePoint(3285, 5386), 12); + chestIds.put(new InstancePoint(3290, 5386), 13); + chestIds.put(new InstancePoint(3275, 5387), 14); + chestIds.put(new InstancePoint(3287, 5387), 15); + chestIds.put(new InstancePoint(3288, 5387), 16); + chestIds.put(new InstancePoint(3281, 5388), 17); + chestIds.put(new InstancePoint(3291, 5388), 18); + chestIds.put(new InstancePoint(3280, 5389), 19); + chestIds.put(new InstancePoint(3285, 5389), 20); + chestIds.put(new InstancePoint(3289, 5389), 21); + chestIds.put(new InstancePoint(3283, 5390), 22); + chestIds.put(new InstancePoint(3285, 5390), 23); + chestIds.put(new InstancePoint(3288, 5390), 24); + chestIds.put(new InstancePoint(3290, 5390), 25); + chestIds.put(new InstancePoint(3282, 5391), 26); + chestIds.put(new InstancePoint(3289, 5391), 27); + chestIds.put(new InstancePoint(3292, 5391), 28); + chestIds.put(new InstancePoint(3279, 5392), 29); + chestIds.put(new InstancePoint(3276, 5393), 30); + chestIds.put(new InstancePoint(3279, 5393), 31); + chestIds.put(new InstancePoint(3284, 5393), 32); + chestIds.put(new InstancePoint(3285, 5393), 33); + chestIds.put(new InstancePoint(3291, 5393), 34); + chestIds.put(new InstancePoint(3275, 5394), 35); + chestIds.put(new InstancePoint(3277, 5394), 36); + chestIds.put(new InstancePoint(3288, 5394), 37); + chestIds.put(new InstancePoint(3276, 5395), 38); + chestIds.put(new InstancePoint(3281, 5395), 39); + chestIds.put(new InstancePoint(3285, 5395), 40); + chestIds.put(new InstancePoint(3287, 5395), 41); + chestIds.put(new InstancePoint(3289, 5395), 42); + chestIds.put(new InstancePoint(3274, 5396), 43); + chestIds.put(new InstancePoint(3283, 5396), 44); + chestIds.put(new InstancePoint(3285, 5396), 45); + chestIds.put(new InstancePoint(3288, 5396), 46); + chestIds.put(new InstancePoint(3272, 5397), 47); + chestIds.put(new InstancePoint(3280, 5397), 48); + chestIds.put(new InstancePoint(3277, 5398), 49); + chestIds.put(new InstancePoint(3281, 5398), 50); + chestIds.put(new InstancePoint(3284, 5398), 51); + chestIds.put(new InstancePoint(3276, 5399), 52); + chestIds.put(new InstancePoint(3278, 5399), 53); + chestIds.put(new InstancePoint(3283, 5399), 54); + chestIds.put(new InstancePoint(3285, 5399), 55); + chestIds.put(new InstancePoint(3277, 5400), 56); + chestIds.put(new InstancePoint(3284, 5400), 57); + chestIds.put(new InstancePoint(3288, 5400), 58); + chestIds.put(new InstancePoint(3281, 5401), 59); + chestIds.put(new InstancePoint(3286, 5401), 60); + chestIds.put(new InstancePoint(3279, 5402), 61); + chestIds.put(new InstancePoint(3285, 5402), 62); + chestIds.put(new InstancePoint(3280, 5403), 63); + chestIds.put(new InstancePoint(3283, 5403), 64); + break; + case RIGHT_TURN: + chestIds.put(new InstancePoint(3338, 5405), 1); + chestIds.put(new InstancePoint(3334, 5405), 2); + chestIds.put(new InstancePoint(3342, 5404), 3); + chestIds.put(new InstancePoint(3340, 5404), 4); + chestIds.put(new InstancePoint(3345, 5403), 5); + chestIds.put(new InstancePoint(3334, 5403), 6); + chestIds.put(new InstancePoint(3330, 5403), 7); + chestIds.put(new InstancePoint(3343, 5402), 8); + chestIds.put(new InstancePoint(3342, 5402), 9); + chestIds.put(new InstancePoint(3339, 5402), 10); + chestIds.put(new InstancePoint(3338, 5402), 11); + chestIds.put(new InstancePoint(3336, 5402), 12); + chestIds.put(new InstancePoint(3347, 5401), 13); + chestIds.put(new InstancePoint(3330, 5401), 14); + chestIds.put(new InstancePoint(3345, 5400), 15); + chestIds.put(new InstancePoint(3341, 5400), 16); + chestIds.put(new InstancePoint(3337, 5400), 17); + chestIds.put(new InstancePoint(3334, 5400), 18); + chestIds.put(new InstancePoint(3345, 5399), 19); + chestIds.put(new InstancePoint(3343, 5399), 20); + chestIds.put(new InstancePoint(3340, 5399), 21); + chestIds.put(new InstancePoint(3335, 5399), 22); + chestIds.put(new InstancePoint(3331, 5399), 23); + chestIds.put(new InstancePoint(3338, 5398), 24); + chestIds.put(new InstancePoint(3337, 5398), 25); + chestIds.put(new InstancePoint(3345, 5397), 26); + chestIds.put(new InstancePoint(3341, 5397), 27); + chestIds.put(new InstancePoint(3334, 5397), 28); + chestIds.put(new InstancePoint(3331, 5397), 29); + chestIds.put(new InstancePoint(3346, 5396), 30); + chestIds.put(new InstancePoint(3343, 5396), 31); + chestIds.put(new InstancePoint(3339, 5396), 32); + chestIds.put(new InstancePoint(3335, 5396), 33); + chestIds.put(new InstancePoint(3333, 5396), 34); + chestIds.put(new InstancePoint(3340, 5395), 35); + chestIds.put(new InstancePoint(3337, 5395), 36); + chestIds.put(new InstancePoint(3334, 5395), 37); + chestIds.put(new InstancePoint(3345, 5394), 38); + chestIds.put(new InstancePoint(3342, 5394), 39); + chestIds.put(new InstancePoint(3332, 5394), 40); + chestIds.put(new InstancePoint(3343, 5393), 41); + chestIds.put(new InstancePoint(3341, 5393), 42); + chestIds.put(new InstancePoint(3338, 5393), 43); + chestIds.put(new InstancePoint(3335, 5393), 44); + chestIds.put(new InstancePoint(3334, 5393), 45); + chestIds.put(new InstancePoint(3346, 5392), 46); + chestIds.put(new InstancePoint(3342, 5392), 47); + chestIds.put(new InstancePoint(3332, 5392), 48); + chestIds.put(new InstancePoint(3350, 5391), 49); + chestIds.put(new InstancePoint(3346, 5391), 50); + chestIds.put(new InstancePoint(3340, 5391), 51); + chestIds.put(new InstancePoint(3339, 5391), 52); + chestIds.put(new InstancePoint(3336, 5391), 53); + chestIds.put(new InstancePoint(3333, 5391), 54); + chestIds.put(new InstancePoint(3349, 5390), 55); + chestIds.put(new InstancePoint(3343, 5390), 56); + chestIds.put(new InstancePoint(3337, 5390), 57); + chestIds.put(new InstancePoint(3335, 5390), 58); + chestIds.put(new InstancePoint(3344, 5389), 59); + chestIds.put(new InstancePoint(3340, 5389), 60); + chestIds.put(new InstancePoint(3336, 5389), 61); + chestIds.put(new InstancePoint(3333, 5389), 62); + chestIds.put(new InstancePoint(3346, 5388), 63); + chestIds.put(new InstancePoint(3340, 5387), 64); + chestIds.put(new InstancePoint(3337, 5386), 65); + chestIds.put(new InstancePoint(3333, 5386), 66); + chestIds.put(new InstancePoint(3338, 5385), 67); + chestIds.put(new InstancePoint(3336, 5385), 68); + chestIds.put(new InstancePoint(3337, 5384), 69); + chestIds.put(new InstancePoint(3340, 5382), 70); + chestIds.put(new InstancePoint(3334, 5383), 71); + chestIds.put(new InstancePoint(3340, 5379), 72); + chestIds.put(new InstancePoint(3338, 5380), 73); + chestIds.put(new InstancePoint(3336, 5381), 74); + break; + case STRAIGHT: + chestIds.put(new InstancePoint(3308, 5378), 1); + chestIds.put(new InstancePoint(3305, 5379), 2); + chestIds.put(new InstancePoint(3307, 5379), 3); + chestIds.put(new InstancePoint(3304, 5381), 4); + chestIds.put(new InstancePoint(3310, 5381), 5); + chestIds.put(new InstancePoint(3302, 5382), 6); + chestIds.put(new InstancePoint(3307, 5382), 7); + chestIds.put(new InstancePoint(3312, 5382), 8); + chestIds.put(new InstancePoint(3317, 5382), 9); + chestIds.put(new InstancePoint(3319, 5382), 10); + chestIds.put(new InstancePoint(3304, 5383), 11); + chestIds.put(new InstancePoint(3305, 5383), 12); + chestIds.put(new InstancePoint(3307, 5383), 13); + chestIds.put(new InstancePoint(3310, 5383), 14); + chestIds.put(new InstancePoint(3315, 5383), 15); + chestIds.put(new InstancePoint(3320, 5383), 16); + chestIds.put(new InstancePoint(3300, 5384), 17); + chestIds.put(new InstancePoint(3309, 5384), 18); + chestIds.put(new InstancePoint(3311, 5384), 19); + chestIds.put(new InstancePoint(3313, 5384), 20); + chestIds.put(new InstancePoint(3317, 5384), 21); + chestIds.put(new InstancePoint(3318, 5384), 22); + chestIds.put(new InstancePoint(3302, 5385), 23); + chestIds.put(new InstancePoint(3306, 5385), 24); + chestIds.put(new InstancePoint(3310, 5385), 25); + chestIds.put(new InstancePoint(3313, 5385), 26); + chestIds.put(new InstancePoint(3320, 5385), 27); + chestIds.put(new InstancePoint(3302, 5386), 28); + chestIds.put(new InstancePoint(3305, 5386), 29); + chestIds.put(new InstancePoint(3316, 5386), 30); + chestIds.put(new InstancePoint(3321, 5386), 31); + chestIds.put(new InstancePoint(3300, 5387), 32); + chestIds.put(new InstancePoint(3308, 5387), 33); + chestIds.put(new InstancePoint(3314, 5387), 34); + chestIds.put(new InstancePoint(3317, 5387), 35); + chestIds.put(new InstancePoint(3301, 5388), 36); + chestIds.put(new InstancePoint(3306, 5388), 37); + chestIds.put(new InstancePoint(3312, 5388), 38); + chestIds.put(new InstancePoint(3322, 5388), 39); + chestIds.put(new InstancePoint(3309, 5389), 40); + chestIds.put(new InstancePoint(3311, 5389), 41); + chestIds.put(new InstancePoint(3313, 5389), 42); + chestIds.put(new InstancePoint(3316, 5389), 43); + chestIds.put(new InstancePoint(3320, 5389), 44); + chestIds.put(new InstancePoint(3300, 5390), 45); + chestIds.put(new InstancePoint(3303, 5390), 46); + chestIds.put(new InstancePoint(3304, 5390), 47); + chestIds.put(new InstancePoint(3312, 5390), 48); + chestIds.put(new InstancePoint(3320, 5390), 49); + chestIds.put(new InstancePoint(3307, 5391), 50); + chestIds.put(new InstancePoint(3310, 5391), 51); + chestIds.put(new InstancePoint(3317, 5391), 52); + chestIds.put(new InstancePoint(3318, 5391), 53); + chestIds.put(new InstancePoint(3323, 5391), 54); + chestIds.put(new InstancePoint(3301, 5392), 55); + chestIds.put(new InstancePoint(3303, 5392), 56); + chestIds.put(new InstancePoint(3309, 5392), 57); + chestIds.put(new InstancePoint(3314, 5392), 58); + chestIds.put(new InstancePoint(3322, 5392), 59); + chestIds.put(new InstancePoint(3305, 5393), 60); + chestIds.put(new InstancePoint(3307, 5393), 61); + chestIds.put(new InstancePoint(3316, 5393), 62); + chestIds.put(new InstancePoint(3309, 5394), 63); + chestIds.put(new InstancePoint(3312, 5394), 64); + chestIds.put(new InstancePoint(3322, 5394), 65); + chestIds.put(new InstancePoint(3310, 5379), 66); + break; + } + + } + + public int indentifyChest(ThievingChest chest) + { + int id = chestIds.get(chest.getInstancePoint()); + chest.setChestId(id); + return id; + } + + private Map chestIds; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java index dc1c3c3dc2..56c4520160 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java @@ -1,165 +1,165 @@ -/* - * Copyright (c) 2018, Tim Lehner - * 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.raidsthieving.BatSolver; - -import lombok.Getter; -import java.util.HashSet; -import java.util.Arrays; -import java.util.Set; - -// Each Thieving room has 4 empty chests -// User-reported data shows these 4 come in groups, -// -// e.g. if there is an empty chest in L room chest 1, the other empty chests could be 16, 17, 38, 54, 55 -// See https://dikkenoob.github.io/ for more information - -public class SolutionSet -{ - public static final SolutionSet[] SOLUTION_SETS = - { - new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 16, 17, 55), - new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 17, 38, 54), - new SolutionSet(ThievingRoomType.LEFT_TURN, 2, 7, 21, 37), - new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 5, 19, 30), - new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 11, 15, 40), - new SolutionSet(ThievingRoomType.LEFT_TURN, 4, 22, 27, 46), - new SolutionSet(ThievingRoomType.LEFT_TURN, 5, 9, 19, 45), - new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 24, 26, 41), - new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 26, 32, 52), - new SolutionSet(ThievingRoomType.LEFT_TURN, 7, 13, 44, 59), - new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 14, 41, 43), - new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 10, 28, 33), - new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 31, 47, 50), - new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 35, 54, 63), - new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 30, 32, 59), - new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 40, 53, 56), - new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 13, 42, 54), - new SolutionSet(ThievingRoomType.LEFT_TURN, 13, 22, 27, 46), - new SolutionSet(ThievingRoomType.LEFT_TURN, 14, 18, 23, 51), - new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 43, 44, 58), - new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 16, 42, 45), - new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 29, 45, 51), - new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 25, 32, 34), - new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 28, 51, 62), - new SolutionSet(ThievingRoomType.LEFT_TURN, 21, 39, 41, 58), - new SolutionSet(ThievingRoomType.LEFT_TURN, 22, 25, 54, 64), - new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 31, 47, 55), - new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 33, 37, 60), - new SolutionSet(ThievingRoomType.LEFT_TURN, 24, 34, 55), - new SolutionSet(ThievingRoomType.LEFT_TURN, 26, 50, 63, 27), - new SolutionSet(ThievingRoomType.LEFT_TURN, 29, 39, 41, 61), - new SolutionSet(ThievingRoomType.LEFT_TURN, 33, 46, 52, 57), - new SolutionSet(ThievingRoomType.LEFT_TURN, 34, 45, 49, 60), - new SolutionSet(ThievingRoomType.LEFT_TURN, 36, 40, 42, 62), - new SolutionSet(ThievingRoomType.LEFT_TURN, 37, 38, 51, 64), - new SolutionSet(ThievingRoomType.LEFT_TURN, 48, 53, 55, 56), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 6, 28, 41), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 42, 55, 60), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 10, 31, 44), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 33, 51, 68), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 31, 43, 46), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 5, 21, 48), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 20, 24, 33), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 38, 47), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 21, 48), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 17, 35, 63), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 17, 45, 47), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 37, 41, 52), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 13, 40, 42), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 20, 24, 30), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 15, 23, 35), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 13, 21, 50), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 18, 37, 39), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 12, 14, 27, 34), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 14, 45, 67, 71), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 22, 29, 32), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 18, 28, 31, 64), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 19, 21, 63, 69), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 20, 51, 68, 72), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 22, 29, 56, 61), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 23, 53, 66, 74), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 26, 35, 53, 59), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 27, 30, 55, 57), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 31, 58, 60, 73), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 34, 57, 58, 70), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 38, 56, 61, 70), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 40, 54, 65, 72), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 42, 46, 65), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 47, 49, 66, 67), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 48, 62, 69), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 19, 32, 41), - new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 26, 36, 39), - new SolutionSet(ThievingRoomType.STRAIGHT, 1, 39, 43, 51), - new SolutionSet(ThievingRoomType.STRAIGHT, 2, 15, 20, 53), - new SolutionSet(ThievingRoomType.STRAIGHT, 3, 10, 42, 44), - new SolutionSet(ThievingRoomType.STRAIGHT, 4, 14, 38, 52), - new SolutionSet(ThievingRoomType.STRAIGHT, 5, 6, 35, 41), - new SolutionSet(ThievingRoomType.STRAIGHT, 7, 16, 34, 49), - new SolutionSet(ThievingRoomType.STRAIGHT, 9, 12, 26, 27), - new SolutionSet(ThievingRoomType.STRAIGHT, 13, 25, 30, 31), - new SolutionSet(ThievingRoomType.STRAIGHT, 15, 20, 53), - new SolutionSet(ThievingRoomType.STRAIGHT, 17, 24, 34, 58), - new SolutionSet(ThievingRoomType.STRAIGHT, 18, 23, 35, 57), - new SolutionSet(ThievingRoomType.STRAIGHT, 19, 26, 47, 65), - new SolutionSet(ThievingRoomType.STRAIGHT, 21, 33, 36, 61), - new SolutionSet(ThievingRoomType.STRAIGHT, 21, 54, 66), - new SolutionSet(ThievingRoomType.STRAIGHT, 22, 25, 46, 55), - new SolutionSet(ThievingRoomType.STRAIGHT, 24, 34, 58), - new SolutionSet(ThievingRoomType.STRAIGHT, 28, 40, 52, 62), - new SolutionSet(ThievingRoomType.STRAIGHT, 29, 41, 42, 63), - new SolutionSet(ThievingRoomType.STRAIGHT, 30, 32, 37, 64), - new SolutionSet(ThievingRoomType.STRAIGHT, 39, 43, 51), - new SolutionSet(ThievingRoomType.STRAIGHT, 43, 45, 50, 60), - new SolutionSet(ThievingRoomType.STRAIGHT, 51, 53, 56, 59) - }; - - SolutionSet(ThievingRoomType type) - { - this.type = type; - emptyChests = new HashSet<>(); - } - - private SolutionSet(ThievingRoomType type, Integer... emptyChests) - { - this.type = type; - this.emptyChests = new HashSet<>(Arrays.asList(emptyChests)); - } - - public void addEmptyChest(int chestId) - { - emptyChests.add(chestId); - } - - public boolean containsChest(int chestId) - { - return emptyChests.contains(chestId); - } - - @Getter - private ThievingRoomType type; - - @Getter - private Set emptyChests; -} +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import lombok.Getter; + +// Each Thieving room has 4 empty chests +// User-reported data shows these 4 come in groups, +// +// e.g. if there is an empty chest in L room chest 1, the other empty chests could be 16, 17, 38, 54, 55 +// See https://dikkenoob.github.io/ for more information + +public class SolutionSet +{ + public static final SolutionSet[] SOLUTION_SETS = + { + new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 16, 17, 55), + new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 17, 38, 54), + new SolutionSet(ThievingRoomType.LEFT_TURN, 2, 7, 21, 37), + new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 5, 19, 30), + new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 11, 15, 40), + new SolutionSet(ThievingRoomType.LEFT_TURN, 4, 22, 27, 46), + new SolutionSet(ThievingRoomType.LEFT_TURN, 5, 9, 19, 45), + new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 24, 26, 41), + new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 26, 32, 52), + new SolutionSet(ThievingRoomType.LEFT_TURN, 7, 13, 44, 59), + new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 14, 41, 43), + new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 10, 28, 33), + new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 31, 47, 50), + new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 35, 54, 63), + new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 30, 32, 59), + new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 40, 53, 56), + new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 13, 42, 54), + new SolutionSet(ThievingRoomType.LEFT_TURN, 13, 22, 27, 46), + new SolutionSet(ThievingRoomType.LEFT_TURN, 14, 18, 23, 51), + new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 43, 44, 58), + new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 16, 42, 45), + new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 29, 45, 51), + new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 25, 32, 34), + new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 28, 51, 62), + new SolutionSet(ThievingRoomType.LEFT_TURN, 21, 39, 41, 58), + new SolutionSet(ThievingRoomType.LEFT_TURN, 22, 25, 54, 64), + new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 31, 47, 55), + new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 33, 37, 60), + new SolutionSet(ThievingRoomType.LEFT_TURN, 24, 34, 55), + new SolutionSet(ThievingRoomType.LEFT_TURN, 26, 50, 63, 27), + new SolutionSet(ThievingRoomType.LEFT_TURN, 29, 39, 41, 61), + new SolutionSet(ThievingRoomType.LEFT_TURN, 33, 46, 52, 57), + new SolutionSet(ThievingRoomType.LEFT_TURN, 34, 45, 49, 60), + new SolutionSet(ThievingRoomType.LEFT_TURN, 36, 40, 42, 62), + new SolutionSet(ThievingRoomType.LEFT_TURN, 37, 38, 51, 64), + new SolutionSet(ThievingRoomType.LEFT_TURN, 48, 53, 55, 56), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 6, 28, 41), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 42, 55, 60), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 10, 31, 44), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 33, 51, 68), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 31, 43, 46), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 5, 21, 48), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 20, 24, 33), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 38, 47), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 21, 48), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 17, 35, 63), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 17, 45, 47), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 37, 41, 52), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 13, 40, 42), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 20, 24, 30), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 15, 23, 35), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 13, 21, 50), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 18, 37, 39), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 12, 14, 27, 34), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 14, 45, 67, 71), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 22, 29, 32), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 18, 28, 31, 64), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 19, 21, 63, 69), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 20, 51, 68, 72), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 22, 29, 56, 61), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 23, 53, 66, 74), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 26, 35, 53, 59), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 27, 30, 55, 57), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 31, 58, 60, 73), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 34, 57, 58, 70), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 38, 56, 61, 70), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 40, 54, 65, 72), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 42, 46, 65), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 47, 49, 66, 67), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 48, 62, 69), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 19, 32, 41), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 26, 36, 39), + new SolutionSet(ThievingRoomType.STRAIGHT, 1, 39, 43, 51), + new SolutionSet(ThievingRoomType.STRAIGHT, 2, 15, 20, 53), + new SolutionSet(ThievingRoomType.STRAIGHT, 3, 10, 42, 44), + new SolutionSet(ThievingRoomType.STRAIGHT, 4, 14, 38, 52), + new SolutionSet(ThievingRoomType.STRAIGHT, 5, 6, 35, 41), + new SolutionSet(ThievingRoomType.STRAIGHT, 7, 16, 34, 49), + new SolutionSet(ThievingRoomType.STRAIGHT, 9, 12, 26, 27), + new SolutionSet(ThievingRoomType.STRAIGHT, 13, 25, 30, 31), + new SolutionSet(ThievingRoomType.STRAIGHT, 15, 20, 53), + new SolutionSet(ThievingRoomType.STRAIGHT, 17, 24, 34, 58), + new SolutionSet(ThievingRoomType.STRAIGHT, 18, 23, 35, 57), + new SolutionSet(ThievingRoomType.STRAIGHT, 19, 26, 47, 65), + new SolutionSet(ThievingRoomType.STRAIGHT, 21, 33, 36, 61), + new SolutionSet(ThievingRoomType.STRAIGHT, 21, 54, 66), + new SolutionSet(ThievingRoomType.STRAIGHT, 22, 25, 46, 55), + new SolutionSet(ThievingRoomType.STRAIGHT, 24, 34, 58), + new SolutionSet(ThievingRoomType.STRAIGHT, 28, 40, 52, 62), + new SolutionSet(ThievingRoomType.STRAIGHT, 29, 41, 42, 63), + new SolutionSet(ThievingRoomType.STRAIGHT, 30, 32, 37, 64), + new SolutionSet(ThievingRoomType.STRAIGHT, 39, 43, 51), + new SolutionSet(ThievingRoomType.STRAIGHT, 43, 45, 50, 60), + new SolutionSet(ThievingRoomType.STRAIGHT, 51, 53, 56, 59) + }; + + SolutionSet(ThievingRoomType type) + { + this.type = type; + emptyChests = new HashSet<>(); + } + + private SolutionSet(ThievingRoomType type, Integer... emptyChests) + { + this.type = type; + this.emptyChests = new HashSet<>(Arrays.asList(emptyChests)); + } + + public void addEmptyChest(int chestId) + { + emptyChests.add(chestId); + } + + public boolean containsChest(int chestId) + { + return emptyChests.contains(chestId); + } + + @Getter + private ThievingRoomType type; + + @Getter + private Set emptyChests; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java index 5e09486f89..6e478bae1d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java @@ -1,172 +1,172 @@ -/* - * Copyright (c) 2018, Tim Lehner - * 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.raidsthieving; - -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.ProgressPieComponent; -import javax.inject.Inject; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.util.Map; -import java.util.TreeSet; - -/** - * Represents the overlay that shows timers on traps that are placed by the - * player. - */ -public class ChestOverlay extends Overlay -{ - - private final Client client; - private final RaidsThievingPlugin plugin; - private final RaidsThievingConfig config; - - @Inject - ChestOverlay(Client client, RaidsThievingPlugin plugin, RaidsThievingConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.plugin = plugin; - this.config = config; - this.client = client; - } - - @Override - public Dimension render(Graphics2D graphics) - { - drawChests(graphics); - return null; - } - - /** - * Updates the timer colors. - */ - public void updateConfig() - { - } - - /** - * Iterates over all the traps that were placed by the local player, and - * draws a circle or a timer on the trap, depending on the trap state. - * - * @param graphics - */ - private void drawChests(Graphics2D graphics) - { - - for (Map.Entry entry : plugin.getChests().entrySet()) - { - ThievingChest chest = entry.getValue(); - WorldPoint pos = entry.getKey(); - - - if (chest != null) - { - if (!plugin.isBatsFound() && !chest.isEverOpened()) - { - if (shouldDrawChest(pos)) - { - Color drawColor = new Color(config.getPotentialBatColor().getRed(), - config.getPotentialBatColor().getGreen(), - config.getPotentialBatColor().getBlue(), - getChestOpacity(pos)); - drawCircleOnTrap(graphics, chest, drawColor); - } - } - if (chest.isPoison()) - { - drawCircleOnTrap(graphics, chest, config.getPoisonTrapColor()); - } - } - } - } - - private boolean shouldDrawChest(WorldPoint chestPos) - { - if (plugin.numberOfEmptyChestsFound() == 0) - { - return true; - } - int chestId = plugin.getChestId(chestPos); - BatSolver solver = plugin.getSolver(); - if (solver != null && chestId != -1) - { - TreeSet matches = solver.matchSolutions(); - return matches.contains(chestId) || matches.size() == 0; - } - return true; - } - - /** - * Draws a timer on a given trap. - * - * @param graphics - * @param chest The chest on which the circle needs to be drawn - * @param fill The fill color of the timer - */ - private void drawCircleOnTrap(Graphics2D graphics, ThievingChest chest, Color fill) - { - if (chest.getLocalPoint().getPlane() != client.getPlane()) - { - return; - } - LocalPoint localLoc = LocalPoint.fromWorld(client, chest.getLocalPoint()); - if (localLoc == null) - { - return; - } - Point loc = Perspective.localToCanvas(client, localLoc, chest.getLocalPoint().getPlane()); - - ProgressPieComponent pie = new ProgressPieComponent(); - pie.setFill(fill); - pie.setBorderColor(Color.BLACK); - pie.setPosition(loc); - pie.setProgress(1); - if (graphics != null && loc != null) - { - pie.render(graphics); - } - } - - private int getChestOpacity(WorldPoint chestPos) - { - int chestId = plugin.getChestId(chestPos); - BatSolver solver = plugin.getSolver(); - if (solver != null && chestId != -1) - { - return (int) (255 * solver.relativeLikelihoodPoison(chestId)); - } - return 255; - } -} +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.util.Map; +import java.util.TreeSet; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ProgressPieComponent; + +/** + * Represents the overlay that shows timers on traps that are placed by the + * player. + */ +public class ChestOverlay extends Overlay +{ + + private final Client client; + private final RaidsThievingPlugin plugin; + private final RaidsThievingConfig config; + + @Inject + ChestOverlay(Client client, RaidsThievingPlugin plugin, RaidsThievingConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.plugin = plugin; + this.config = config; + this.client = client; + } + + @Override + public Dimension render(Graphics2D graphics) + { + drawChests(graphics); + return null; + } + + /** + * Updates the timer colors. + */ + public void updateConfig() + { + } + + /** + * Iterates over all the traps that were placed by the local player, and + * draws a circle or a timer on the trap, depending on the trap state. + * + * @param graphics + */ + private void drawChests(Graphics2D graphics) + { + + for (Map.Entry entry : plugin.getChests().entrySet()) + { + ThievingChest chest = entry.getValue(); + WorldPoint pos = entry.getKey(); + + + if (chest != null) + { + if (!plugin.isBatsFound() && !chest.isEverOpened()) + { + if (shouldDrawChest(pos)) + { + Color drawColor = new Color(config.getPotentialBatColor().getRed(), + config.getPotentialBatColor().getGreen(), + config.getPotentialBatColor().getBlue(), + getChestOpacity(pos)); + drawCircleOnTrap(graphics, chest, drawColor); + } + } + if (chest.isPoison()) + { + drawCircleOnTrap(graphics, chest, config.getPoisonTrapColor()); + } + } + } + } + + private boolean shouldDrawChest(WorldPoint chestPos) + { + if (plugin.numberOfEmptyChestsFound() == 0) + { + return true; + } + int chestId = plugin.getChestId(chestPos); + BatSolver solver = plugin.getSolver(); + if (solver != null && chestId != -1) + { + TreeSet matches = solver.matchSolutions(); + return matches.contains(chestId) || matches.size() == 0; + } + return true; + } + + /** + * Draws a timer on a given trap. + * + * @param graphics + * @param chest The chest on which the circle needs to be drawn + * @param fill The fill color of the timer + */ + private void drawCircleOnTrap(Graphics2D graphics, ThievingChest chest, Color fill) + { + if (chest.getLocalPoint().getPlane() != client.getPlane()) + { + return; + } + LocalPoint localLoc = LocalPoint.fromWorld(client, chest.getLocalPoint()); + if (localLoc == null) + { + return; + } + Point loc = Perspective.localToCanvas(client, localLoc, chest.getLocalPoint().getPlane()); + + ProgressPieComponent pie = new ProgressPieComponent(); + pie.setFill(fill); + pie.setBorderColor(Color.BLACK); + pie.setPosition(loc); + pie.setProgress(1); + if (graphics != null && loc != null) + { + pie.render(graphics); + } + } + + private int getChestOpacity(WorldPoint chestPos) + { + int chestId = plugin.getChestId(chestPos); + BatSolver solver = plugin.getSolver(); + if (solver != null && chestId != -1) + { + return (int) (255 * solver.relativeLikelihoodPoison(chestId)); + } + return 255; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java index 0df80aeb65..ea463317e4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java @@ -1,98 +1,103 @@ -package net.runelite.client.plugins.raidsthieving; - -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.Point; -import net.runelite.api.coords.WorldPoint; - -import java.util.Objects; - -/** - * Represents a point in the instance chunk, invariant of rotation. - */ -@Getter -public class InstancePoint -{ - private static final int CHUNK_SIZE = 8; - private static final double CHUNK_OFFSET = 3.5; - - public InstancePoint(int x, int y, int rot) - { - this.x = x; - this.y = y; - this.rot = rot; - } - - public InstancePoint(int x, int y) - { - this.x = x; - this.y = y; - this.rot = 0; - } - - public static InstancePoint buildFromPoint(WorldPoint worldPoint, Client client) - { - Point point = new Point(worldPoint.getX(), worldPoint.getY()); - Point base = new Point(client.getBaseX(), client.getBaseY()); - int plane = worldPoint.getPlane(); - - int deltaX = point.getX() - base.getX(); - int deltaY = point.getY() - base.getY(); - int chunkIndexX = deltaX / CHUNK_SIZE; - int chunkIndexY = deltaY / CHUNK_SIZE; - - int chunkData = client.getInstanceTemplateChunks()[plane][chunkIndexX][chunkIndexY]; - int rotation = chunkData >> 1 & 0x3; - int y = (chunkData >> 3 & 0x7FF) * 8; - int x = (chunkData >> 14 & 0x3FF) * 8; - - return buildFromTile(base, point, rotation, new Point(x, y)); - } - - public static InstancePoint buildFromTile(Point base, Point tile, int rot, Point chunkOrigin) - { - int deltaX = tile.getX() - base.getX(); - int deltaY = tile.getY() - base.getY(); - - double chunkOffsetX = (deltaX % CHUNK_SIZE) - CHUNK_OFFSET; - double chunkOffsetY = (deltaY % CHUNK_SIZE) - CHUNK_OFFSET; - - for (int i = 0; i < rot; i++) - { - double temp = chunkOffsetX; - chunkOffsetX = -chunkOffsetY; - chunkOffsetY = temp; - } - - chunkOffsetX += CHUNK_OFFSET; - chunkOffsetY += CHUNK_OFFSET; - - int invariantChunkOffsetX = (int) chunkOffsetX; - int invariantChunkOffsetY = (int) chunkOffsetY; - - return new InstancePoint( - chunkOrigin.getX() + invariantChunkOffsetX, - chunkOrigin.getY() + invariantChunkOffsetY, - rot); - } - - @Override - public boolean equals(Object o) - { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - InstancePoint that = (InstancePoint) o; - return x == that.x && - y == that.y; - } - - @Override - public int hashCode() - { - return Objects.hash(x, y); - } - - private int x; - private int y; - private int rot; -} +package net.runelite.client.plugins.raidsthieving; + +import java.util.Objects; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.coords.WorldPoint; + +/** + * Represents a point in the instance chunk, invariant of rotation. + */ +@Getter +public class InstancePoint +{ + private static final int CHUNK_SIZE = 8; + private static final double CHUNK_OFFSET = 3.5; + + public InstancePoint(int x, int y, int rot) + { + this.x = x; + this.y = y; + this.rot = rot; + } + + public InstancePoint(int x, int y) + { + this.x = x; + this.y = y; + this.rot = 0; + } + + public static InstancePoint buildFromPoint(WorldPoint worldPoint, Client client) + { + Point point = new Point(worldPoint.getX(), worldPoint.getY()); + Point base = new Point(client.getBaseX(), client.getBaseY()); + int plane = worldPoint.getPlane(); + + int deltaX = point.getX() - base.getX(); + int deltaY = point.getY() - base.getY(); + int chunkIndexX = deltaX / CHUNK_SIZE; + int chunkIndexY = deltaY / CHUNK_SIZE; + + int chunkData = client.getInstanceTemplateChunks()[plane][chunkIndexX][chunkIndexY]; + int rotation = chunkData >> 1 & 0x3; + int y = (chunkData >> 3 & 0x7FF) * 8; + int x = (chunkData >> 14 & 0x3FF) * 8; + + return buildFromTile(base, point, rotation, new Point(x, y)); + } + + public static InstancePoint buildFromTile(Point base, Point tile, int rot, Point chunkOrigin) + { + int deltaX = tile.getX() - base.getX(); + int deltaY = tile.getY() - base.getY(); + + double chunkOffsetX = (deltaX % CHUNK_SIZE) - CHUNK_OFFSET; + double chunkOffsetY = (deltaY % CHUNK_SIZE) - CHUNK_OFFSET; + + for (int i = 0; i < rot; i++) + { + double temp = chunkOffsetX; + chunkOffsetX = -chunkOffsetY; + chunkOffsetY = temp; + } + + chunkOffsetX += CHUNK_OFFSET; + chunkOffsetY += CHUNK_OFFSET; + + int invariantChunkOffsetX = (int) chunkOffsetX; + int invariantChunkOffsetY = (int) chunkOffsetY; + + return new InstancePoint( + chunkOrigin.getX() + invariantChunkOffsetX, + chunkOrigin.getY() + invariantChunkOffsetY, + rot); + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (o == null || getClass() != o.getClass()) + { + return false; + } + InstancePoint that = (InstancePoint) o; + return x == that.x && + y == that.y; + } + + @Override + public int hashCode() + { + return Objects.hash(x, y); + } + + private int x; + private int y; + private int rot; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java index bb055edf4e..90d8415302 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java @@ -1,67 +1,67 @@ -/* - * Copyright (c) 2017, Tim Lehner - * 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.raidsthieving; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; -import java.awt.Color; - -@ConfigGroup("raidsthievingplugin") -public interface RaidsThievingConfig extends Config -{ - @ConfigItem( - position = 1, - keyName = "hexColorPotentialBat", - name = "Potential Bat", - description = "Color of marker for chests which could have bat" - ) - default Color getPotentialBatColor() - { - return Color.YELLOW; - } - - @ConfigItem( - position = 2, - keyName = "hexColorPoison", - name = "Poison trap", - description = "Color of chest with poison" - ) - default Color getPoisonTrapColor() - { - return Color.GREEN; - } - - @ConfigItem( - position = 5, - keyName = "batNotify", - name = "Notify when found", - description = "Send notification if you see bats being found." - ) - default boolean batFoundNotify() - { - return false; - } -} +/* + * Copyright (c) 2017, Tim Lehner + * 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.raidsthieving; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("raidsthievingplugin") +public interface RaidsThievingConfig extends Config +{ + @ConfigItem( + position = 1, + keyName = "hexColorPotentialBat", + name = "Potential Bat", + description = "Color of marker for chests which could have bat" + ) + default Color getPotentialBatColor() + { + return Color.YELLOW; + } + + @ConfigItem( + position = 2, + keyName = "hexColorPoison", + name = "Poison trap", + description = "Color of chest with poison" + ) + default Color getPoisonTrapColor() + { + return Color.GREEN; + } + + @ConfigItem( + position = 5, + keyName = "batNotify", + name = "Notify when found", + description = "Send notification if you see bats being found." + ) + default boolean batFoundNotify() + { + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java index 8f0baf9639..3c1b19a4e5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java @@ -1,272 +1,272 @@ -/* - * Copyright (c) 2017, Tim Lehner - * 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.raidsthieving; - -import com.google.inject.Provides; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.GameObject; -import net.runelite.api.GraphicsObject; -import net.runelite.api.Varbits; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameObjectSpawned; -import net.runelite.api.events.GraphicsObjectCreated; -import net.runelite.api.events.VarbitChanged; -import net.runelite.client.Notifier; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver; -import net.runelite.client.plugins.raidsthieving.BatSolver.ChestIdentifier; -import net.runelite.client.plugins.raidsthieving.BatSolver.ThievingRoomType; -import net.runelite.client.ui.overlay.OverlayManager; -import javax.inject.Inject; -import java.text.MessageFormat; -import java.time.Instant; -import java.util.HashMap; -import java.util.Map; - -@Slf4j -@PluginDescriptor( - name = "Raids Bat Finder", - description = "Tracks which chests need to be searched for bats and which poison", - tags = {"overlay", "skilling", "raid"}, - type = PluginType.PVM -) -public class RaidsThievingPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private OverlayManager overlayManager; - - @Inject - private ChestOverlay overlay; - - @Inject - private Notifier notifier; - - @Inject - private RaidsThievingConfig config; - - @Getter - private final Map chests = new HashMap<>(); - - @Getter - private Instant lastActionTime = Instant.ofEpochMilli(0); - - private boolean inRaidChambers; - - @Getter - private boolean batsFound; - - @Getter - private BatSolver solver; - - @Getter - private ChestIdentifier mapper; - - - @Provides - RaidsThievingConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(RaidsThievingConfig.class); - } - - @Override - protected void startUp() - { - overlayManager.add(overlay); - overlay.updateConfig(); - reset(); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - lastActionTime = Instant.ofEpochMilli(0); - chests.clear(); - } - - - @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) - { - GameObject obj = event.getGameObject(); - WorldPoint loc = obj.getWorldLocation(); - InstancePoint absLoc = InstancePoint.buildFromPoint(loc, client); - - if (obj.getId() == RaidsThievingConstants.EMPTY_TROUGH) - { - ThievingRoomType type = ThievingRoomType.IdentifyByInstancePoint(absLoc); - - if (type != null) - { - solver = new BatSolver(type); - mapper = new ChestIdentifier(type); - for (ThievingChest chest : chests.values()) - { - mapper.indentifyChest(chest); - } - } - else - { - log.error(MessageFormat.format("Unable to identify room type with: {0} {1} {2} {3} {4}.", - loc.getX(), loc.getY(), absLoc.getX(), absLoc.getY(), absLoc.getRot())); - log.error("Please report this @https://github.com/runelite/runelite/pull/4914!"); - } - } - if (obj.getId() == RaidsThievingConstants.CLOSED_CHEST_ID) - { - if (!chests.containsKey(loc)) - { - ThievingChest chest = new ThievingChest(obj, absLoc); - - if (mapper != null) - { - mapper.indentifyChest(chest); - } - - chests.put(loc, chest); - } - else - { - checkForBats(); - } - } - - if (obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_1 || - obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_2) - { - ThievingChest chest = chests.get(obj.getWorldLocation()); - // We found a chest that has grubs - log.info(MessageFormat.format("Found grubs at {0}, {1} chestId: {2}", loc.getX(), loc.getY(), chest.getChestId())); - if (solver != null && chest.getChestId() != -1) - { - chest.setEverOpened(true); - solver.addGrubsChest(chest.getChestId()); - } - checkForBats(); - } - - if (obj.getId() == RaidsThievingConstants.OPEN_EMPTY_CHEST) - { - ThievingChest chest = chests.get(obj.getWorldLocation()); - // We found a chest that could have poison - if (solver != null && chest.getChestId() != -1) - { - chest.setEmpty(true); - chest.setEverOpened(true); - solver.addEmptyChest(chest.getChestId()); - } - } - } - - - @Subscribe - public void onGraphicsObjectCreated(GraphicsObjectCreated event) - { - GraphicsObject obj = event.getGraphicsObject(); - if (obj.getId() == 184) - { - log.debug("Found poison splat"); - WorldPoint loc = WorldPoint.fromLocal(client, obj.getLocation()); - chests.get(loc).setPoison(true); - } - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - boolean setting = client.getVar(Varbits.IN_RAID) == 1; - - if (inRaidChambers != setting) - { - inRaidChambers = setting; - reset(); - } - - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("raidsthievingplugin")) - { - overlay.updateConfig(); - } - } - - private void reset() - { - chests.clear(); - batsFound = false; - solver = null; - mapper = null; - } - - public int numberOfEmptyChestsFound() - { - int total = 0; - for (ThievingChest chest : chests.values()) - { - if (chest.isEmpty()) - { - total++; - } - } - return total; - } - - - private boolean checkForBats() - { - for (ThievingChest chest : chests.values()) - { - if (chest.isEmpty() && !chest.isPoison()) - { - batsFound = true; - if (config.batFoundNotify()) - { - notifier.notify("Bats have been found!"); - } - return true; - } - } - return false; - } - - public int getChestId(WorldPoint worldPoint) - { - return chests.get(worldPoint).getChestId(); - } -} - +/* + * Copyright (c) 2017, Tim Lehner + * 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.raidsthieving; + +import com.google.inject.Provides; +import java.text.MessageFormat; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import javax.inject.Inject; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.GraphicsObject; +import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GraphicsObjectCreated; +import net.runelite.api.events.VarbitChanged; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver; +import net.runelite.client.plugins.raidsthieving.BatSolver.ChestIdentifier; +import net.runelite.client.plugins.raidsthieving.BatSolver.ThievingRoomType; +import net.runelite.client.ui.overlay.OverlayManager; + +@Slf4j +@PluginDescriptor( + name = "Raids Bat Finder", + description = "Tracks which chests need to be searched for bats and which poison", + tags = {"overlay", "skilling", "raid"}, + type = PluginType.PVM +) +public class RaidsThievingPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private ChestOverlay overlay; + + @Inject + private Notifier notifier; + + @Inject + private RaidsThievingConfig config; + + @Getter + private final Map chests = new HashMap<>(); + + @Getter + private Instant lastActionTime = Instant.ofEpochMilli(0); + + private boolean inRaidChambers; + + @Getter + private boolean batsFound; + + @Getter + private BatSolver solver; + + @Getter + private ChestIdentifier mapper; + + + @Provides + RaidsThievingConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(RaidsThievingConfig.class); + } + + @Override + protected void startUp() + { + overlayManager.add(overlay); + overlay.updateConfig(); + reset(); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + lastActionTime = Instant.ofEpochMilli(0); + chests.clear(); + } + + + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) + { + GameObject obj = event.getGameObject(); + WorldPoint loc = obj.getWorldLocation(); + InstancePoint absLoc = InstancePoint.buildFromPoint(loc, client); + + if (obj.getId() == RaidsThievingConstants.EMPTY_TROUGH) + { + ThievingRoomType type = ThievingRoomType.IdentifyByInstancePoint(absLoc); + + if (type != null) + { + solver = new BatSolver(type); + mapper = new ChestIdentifier(type); + for (ThievingChest chest : chests.values()) + { + mapper.indentifyChest(chest); + } + } + else + { + log.error(MessageFormat.format("Unable to identify room type with: {0} {1} {2} {3} {4}.", + loc.getX(), loc.getY(), absLoc.getX(), absLoc.getY(), absLoc.getRot())); + log.error("Please report this @https://github.com/runelite/runelite/pull/4914!"); + } + } + if (obj.getId() == RaidsThievingConstants.CLOSED_CHEST_ID) + { + if (!chests.containsKey(loc)) + { + ThievingChest chest = new ThievingChest(obj, absLoc); + + if (mapper != null) + { + mapper.indentifyChest(chest); + } + + chests.put(loc, chest); + } + else + { + checkForBats(); + } + } + + if (obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_1 || + obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_2) + { + ThievingChest chest = chests.get(obj.getWorldLocation()); + // We found a chest that has grubs + log.info(MessageFormat.format("Found grubs at {0}, {1} chestId: {2}", loc.getX(), loc.getY(), chest.getChestId())); + if (solver != null && chest.getChestId() != -1) + { + chest.setEverOpened(true); + solver.addGrubsChest(chest.getChestId()); + } + checkForBats(); + } + + if (obj.getId() == RaidsThievingConstants.OPEN_EMPTY_CHEST) + { + ThievingChest chest = chests.get(obj.getWorldLocation()); + // We found a chest that could have poison + if (solver != null && chest.getChestId() != -1) + { + chest.setEmpty(true); + chest.setEverOpened(true); + solver.addEmptyChest(chest.getChestId()); + } + } + } + + + @Subscribe + public void onGraphicsObjectCreated(GraphicsObjectCreated event) + { + GraphicsObject obj = event.getGraphicsObject(); + if (obj.getId() == 184) + { + log.debug("Found poison splat"); + WorldPoint loc = WorldPoint.fromLocal(client, obj.getLocation()); + chests.get(loc).setPoison(true); + } + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + boolean setting = client.getVar(Varbits.IN_RAID) == 1; + + if (inRaidChambers != setting) + { + inRaidChambers = setting; + reset(); + } + + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("raidsthievingplugin")) + { + overlay.updateConfig(); + } + } + + private void reset() + { + chests.clear(); + batsFound = false; + solver = null; + mapper = null; + } + + public int numberOfEmptyChestsFound() + { + int total = 0; + for (ThievingChest chest : chests.values()) + { + if (chest.isEmpty()) + { + total++; + } + } + return total; + } + + + private boolean checkForBats() + { + for (ThievingChest chest : chests.values()) + { + if (chest.isEmpty() && !chest.isPoison()) + { + batsFound = true; + if (config.batFoundNotify()) + { + notifier.notify("Bats have been found!"); + } + return true; + } + } + return false; + } + + public int getChestId(WorldPoint worldPoint) + { + return chests.get(worldPoint).getChestId(); + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java index 20775b1d35..d27f688d2e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java @@ -1,48 +1,48 @@ -/* - * Copyright (c) 2018, Infinitay - * Copyright (c) 2018, Shaun Dreclin - * - * 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.rememberclan; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("rememberclan") -public interface RememberClanConfig extends Config -{ - @ConfigItem( - position = 1, - keyName = "clanname", - name = "Clan Name", - description = "Clanname to always remember" - ) - default String clanname() - { - return ""; - } - - -} +/* + * Copyright (c) 2018, Infinitay + * Copyright (c) 2018, Shaun Dreclin + * + * 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.rememberclan; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("rememberclan") +public interface RememberClanConfig extends Config +{ + @ConfigItem( + position = 1, + keyName = "clanname", + name = "Clan Name", + description = "Clanname to always remember" + ) + default String clanname() + { + return ""; + } + + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java index bdac2a3289..e28d856023 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java @@ -1,80 +1,75 @@ -/* - * Copyright (c) 2018, Infinitay - * Copyright (c) 2018, Shaun Dreclin - * 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.rememberclan; - -import com.google.inject.Provides; -import javax.inject.Inject; - -import net.runelite.api.*; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.vars.AccountType; -import net.runelite.client.chat.ChatColorType; -import net.runelite.client.chat.ChatMessageBuilder; -import net.runelite.client.chat.ChatMessageManager; -import net.runelite.client.chat.QueuedMessage; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; - -@PluginDescriptor( - name = "Remember Clan", - description = "Remember a specific clan!", - type = PluginType.UTILITY, - enabledByDefault = false -) -public class RememberClanPlugin extends Plugin -{ - - @Inject - private Client client; - - @Inject - private RememberClanConfig config; - - @Inject - private ChatMessageManager chatMessageManager; - - private boolean loggingIn; - - @Provides - RememberClanConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(RememberClanConfig.class); - } - - @Subscribe - public void onGameTick(GameTick event) - { - client.setVar(VarClientStr.RECENT_CLAN_CHAT,config.clanname()); - - } - - -} +/* + * Copyright (c) 2018, Infinitay + * Copyright (c) 2018, Shaun Dreclin + * 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.rememberclan; + +import com.google.inject.Provides; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.VarClientStr; +import net.runelite.api.events.GameTick; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; + +@PluginDescriptor( + name = "Remember Clan", + description = "Remember a specific clan!", + type = PluginType.UTILITY, + enabledByDefault = false +) +public class RememberClanPlugin extends Plugin +{ + + @Inject + private Client client; + + @Inject + private RememberClanConfig config; + + @Inject + private ChatMessageManager chatMessageManager; + + private boolean loggingIn; + + @Provides + RememberClanConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(RememberClanConfig.class); + } + + @Subscribe + public void onGameTick(GameTick event) + { + client.setVar(VarClientStr.RECENT_CLAN_CHAT, config.clanname()); + + } + + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java index 0c85f32c8e..64d1051add 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java @@ -1,453 +1,453 @@ -/* - * Copyright (c) 2018, Adam - * 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.reorderprayers; - -import com.google.common.collect.ImmutableList; -import com.google.inject.Provides; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.HashTable; -import net.runelite.api.Prayer; -import net.runelite.api.WidgetNode; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.DraggingWidgetChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.events.WidgetMenuOptionClicked; -import net.runelite.api.widgets.Widget; -import static net.runelite.api.widgets.WidgetConfig.DRAG; -import static net.runelite.api.widgets.WidgetConfig.DRAG_ON; -import net.runelite.api.widgets.WidgetID; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.menus.MenuManager; -import net.runelite.client.menus.WidgetMenuOption; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; - -@PluginDescriptor( - name = "Reorder Prayers", - description = "Reorder the prayers displayed on the Prayer panel" -) -public class ReorderPrayersPlugin extends Plugin -{ - - static final String CONFIG_GROUP_KEY = "reorderprayers"; - - static final String CONFIG_UNLOCK_REORDERING_KEY = "unlockPrayerReordering"; - - static final String CONFIG_PRAYER_ORDER_KEY = "prayerOrder"; - - private static final int PRAYER_WIDTH = 34; - - private static final int PRAYER_HEIGHT = 34; - - private static final int PRAYER_X_OFFSET = 37; - - private static final int PRAYER_Y_OFFSET = 37; - - private static final int QUICK_PRAYER_SPRITE_X_OFFSET = 2; - - private static final int QUICK_PRAYER_SPRITE_Y_OFFSET = 2; - - private static final int PRAYER_COLUMN_COUNT = 5; - - private static final int PRAYER_COUNT = Prayer.values().length; - - private static final List PRAYER_WIDGET_INFO_LIST = ImmutableList.of( - WidgetInfo.PRAYER_THICK_SKIN, - WidgetInfo.PRAYER_BURST_OF_STRENGTH, - WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, - WidgetInfo.PRAYER_SHARP_EYE, - WidgetInfo.PRAYER_MYSTIC_WILL, - WidgetInfo.PRAYER_ROCK_SKIN, - WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, - WidgetInfo.PRAYER_IMPROVED_REFLEXES, - WidgetInfo.PRAYER_RAPID_RESTORE, - WidgetInfo.PRAYER_RAPID_HEAL, - WidgetInfo.PRAYER_PROTECT_ITEM, - WidgetInfo.PRAYER_HAWK_EYE, - WidgetInfo.PRAYER_MYSTIC_LORE, - WidgetInfo.PRAYER_STEEL_SKIN, - WidgetInfo.PRAYER_ULTIMATE_STRENGTH, - WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, - WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, - WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, - WidgetInfo.PRAYER_PROTECT_FROM_MELEE, - WidgetInfo.PRAYER_EAGLE_EYE, - WidgetInfo.PRAYER_MYSTIC_MIGHT, - WidgetInfo.PRAYER_RETRIBUTION, - WidgetInfo.PRAYER_REDEMPTION, - WidgetInfo.PRAYER_SMITE, - WidgetInfo.PRAYER_PRESERVE, - WidgetInfo.PRAYER_CHIVALRY, - WidgetInfo.PRAYER_PIETY, - WidgetInfo.PRAYER_RIGOUR, - WidgetInfo.PRAYER_AUGURY - ); - - private static final List QUICK_PRAYER_CHILD_IDS = ImmutableList.of( - WidgetID.QuickPrayer.THICK_SKIN_CHILD_ID, - WidgetID.QuickPrayer.BURST_OF_STRENGTH_CHILD_ID, - WidgetID.QuickPrayer.CLARITY_OF_THOUGHT_CHILD_ID, - WidgetID.QuickPrayer.SHARP_EYE_CHILD_ID, - WidgetID.QuickPrayer.MYSTIC_WILL_CHILD_ID, - WidgetID.QuickPrayer.ROCK_SKIN_CHILD_ID, - WidgetID.QuickPrayer.SUPERHUMAN_STRENGTH_CHILD_ID, - WidgetID.QuickPrayer.IMPROVED_REFLEXES_CHILD_ID, - WidgetID.QuickPrayer.RAPID_RESTORE_CHILD_ID, - WidgetID.QuickPrayer.RAPID_HEAL_CHILD_ID, - WidgetID.QuickPrayer.PROTECT_ITEM_CHILD_ID, - WidgetID.QuickPrayer.HAWK_EYE_CHILD_ID, - WidgetID.QuickPrayer.MYSTIC_LORE_CHILD_ID, - WidgetID.QuickPrayer.STEEL_SKIN_CHILD_ID, - WidgetID.QuickPrayer.ULTIMATE_STRENGTH_CHILD_ID, - WidgetID.QuickPrayer.INCREDIBLE_REFLEXES_CHILD_ID, - WidgetID.QuickPrayer.PROTECT_FROM_MAGIC_CHILD_ID, - WidgetID.QuickPrayer.PROTECT_FROM_MISSILES_CHILD_ID, - WidgetID.QuickPrayer.PROTECT_FROM_MELEE_CHILD_ID, - WidgetID.QuickPrayer.EAGLE_EYE_CHILD_ID, - WidgetID.QuickPrayer.MYSTIC_MIGHT_CHILD_ID, - WidgetID.QuickPrayer.RETRIBUTION_CHILD_ID, - WidgetID.QuickPrayer.REDEMPTION_CHILD_ID, - WidgetID.QuickPrayer.SMITE_CHILD_ID, - WidgetID.QuickPrayer.PRESERVE_CHILD_ID, - WidgetID.QuickPrayer.CHIVALRY_CHILD_ID, - WidgetID.QuickPrayer.PIETY_CHILD_ID, - WidgetID.QuickPrayer.RIGOUR_CHILD_ID, - WidgetID.QuickPrayer.AUGURY_CHILD_ID - ); - - private static final String LOCK = "Lock"; - - private static final String UNLOCK = "Unlock"; - - private static final String MENU_TARGET = "Reordering"; - - private static final WidgetMenuOption FIXED_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, - MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB); - - private static final WidgetMenuOption FIXED_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, - MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB); - - private static final WidgetMenuOption RESIZABLE_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, - MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB); - - private static final WidgetMenuOption RESIZABLE_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, - MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB); - - private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, - MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB); - - private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, - MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB); - - @Inject - private Client client; - - @Inject - private ReorderPrayersConfig config; - - @Inject - private MenuManager menuManager; - - private Prayer[] prayerOrder; - - static String prayerOrderToString(Prayer[] prayerOrder) - { - return Arrays.stream(prayerOrder) - .map(Prayer::name) - .collect(Collectors.joining(",")); - } - - private static Prayer[] stringToPrayerOrder(String string) - { - return Arrays.stream(string.split(",")) - .map(Prayer::valueOf) - .toArray(Prayer[]::new); - } - - private static int getPrayerIndex(Widget widget) - { - int x = widget.getOriginalX() / PRAYER_X_OFFSET; - int y = widget.getOriginalY() / PRAYER_Y_OFFSET; - return x + y * PRAYER_COLUMN_COUNT; - } - - private static void setWidgetPosition(Widget widget, int x, int y) - { - widget.setRelativeX(x); - widget.setRelativeY(y); - widget.setOriginalX(x); - widget.setOriginalY(y); - } - - @Provides - ReorderPrayersConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(ReorderPrayersConfig.class); - } - - @Override - protected void startUp() throws Exception - { - refreshPrayerTabOption(); - prayerOrder = stringToPrayerOrder(config.prayerOrder()); - reorderPrayers(); - } - - @Override - protected void shutDown() throws Exception - { - clearPrayerTabMenus(); - prayerOrder = Prayer.values(); - reorderPrayers(false); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGGED_IN) - { - reorderPrayers(); - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals(CONFIG_GROUP_KEY)) - { - if (event.getKey().equals(CONFIG_PRAYER_ORDER_KEY)) - { - prayerOrder = stringToPrayerOrder(config.prayerOrder()); - } - else if (event.getKey().equals(CONFIG_UNLOCK_REORDERING_KEY)) - { - refreshPrayerTabOption(); - } - reorderPrayers(); - } - } - - @Subscribe - public void onWidgetLoaded(WidgetLoaded event) - { - if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) - { - reorderPrayers(); - } - } - - @Subscribe - public void onDraggingWidgetChanged(DraggingWidgetChanged event) - { - // is dragging widget and mouse button released - if (event.isDraggingWidget() && client.getMouseCurrentButton() == 0) - { - Widget draggedWidget = client.getDraggedWidget(); - Widget draggedOnWidget = client.getDraggedOnWidget(); - if (draggedWidget != null && draggedOnWidget != null) - { - int draggedGroupId = WidgetInfo.TO_GROUP(draggedWidget.getId()); - int draggedOnGroupId = WidgetInfo.TO_GROUP(draggedOnWidget.getId()); - if (draggedGroupId != WidgetID.PRAYER_GROUP_ID || draggedOnGroupId != WidgetID.PRAYER_GROUP_ID - || draggedOnWidget.getWidth() != PRAYER_WIDTH || draggedOnWidget.getHeight() != PRAYER_HEIGHT) - { - return; - } - // reset dragged on widget to prevent sending a drag widget packet to the server - client.setDraggedOnWidget(null); - - int fromPrayerIndex = getPrayerIndex(draggedWidget); - int toPrayerIndex = getPrayerIndex(draggedOnWidget); - - Prayer tmp = prayerOrder[toPrayerIndex]; - prayerOrder[toPrayerIndex] = prayerOrder[fromPrayerIndex]; - prayerOrder[fromPrayerIndex] = tmp; - - save(); - } - } - } - - @Subscribe - public void onWidgetMenuOptionClicked(WidgetMenuOptionClicked event) - { - if (event.getWidget() == WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB - || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB - || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB) - { - config.unlockPrayerReordering(event.getMenuOption().equals(UNLOCK)); - } - } - - private void clearPrayerTabMenus() - { - menuManager.removeManagedCustomMenu(FIXED_PRAYER_TAB_LOCK); - menuManager.removeManagedCustomMenu(RESIZABLE_PRAYER_TAB_LOCK); - menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK); - menuManager.removeManagedCustomMenu(FIXED_PRAYER_TAB_UNLOCK); - menuManager.removeManagedCustomMenu(RESIZABLE_PRAYER_TAB_UNLOCK); - menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK); - } - - private void refreshPrayerTabOption() - { - clearPrayerTabMenus(); - if (config.unlockPrayerReordering()) - { - menuManager.addManagedCustomMenu(FIXED_PRAYER_TAB_LOCK); - menuManager.addManagedCustomMenu(RESIZABLE_PRAYER_TAB_LOCK); - menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK); - } - else - { - menuManager.addManagedCustomMenu(FIXED_PRAYER_TAB_UNLOCK); - menuManager.addManagedCustomMenu(RESIZABLE_PRAYER_TAB_UNLOCK); - menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK); - } - } - - private PrayerTabState getPrayerTabState() - { - HashTable componentTable = client.getComponentTable(); - for (WidgetNode widgetNode : componentTable.getNodes()) - { - if (widgetNode.getId() == WidgetID.PRAYER_GROUP_ID) - { - return PrayerTabState.PRAYERS; - } - else if (widgetNode.getId() == WidgetID.QUICK_PRAYERS_GROUP_ID) - { - return PrayerTabState.QUICK_PRAYERS; - } - } - return PrayerTabState.NONE; - } - - private void save() - { - config.prayerOrder(prayerOrderToString(prayerOrder)); - } - - private void reorderPrayers() - { - reorderPrayers(config.unlockPrayerReordering()); - } - - private void reorderPrayers(boolean unlocked) - { - if (client.getGameState() != GameState.LOGGED_IN) - { - return; - } - - PrayerTabState prayerTabState = getPrayerTabState(); - - if (prayerTabState == PrayerTabState.PRAYERS) - { - List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream() - .map(client::getWidget) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) - { - return; - } - - for (int index = 0; index < prayerOrder.length; index++) - { - Prayer prayer = prayerOrder[index]; - Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); - - int widgetConfig = prayerWidget.getClickMask(); - if (unlocked) - { - // allow dragging of this widget - widgetConfig |= DRAG; - // allow this widget to be dragged on - widgetConfig |= DRAG_ON; - } - else - { - // remove drag flag - widgetConfig &= ~DRAG; - // remove drag on flag - widgetConfig &= ~DRAG_ON; - } - prayerWidget.setClickMask(widgetConfig); - - int x = index % PRAYER_COLUMN_COUNT; - int y = index / PRAYER_COLUMN_COUNT; - int widgetX = x * PRAYER_X_OFFSET; - int widgetY = y * PRAYER_Y_OFFSET; - setWidgetPosition(prayerWidget, widgetX, widgetY); - } - } - else if (prayerTabState == PrayerTabState.QUICK_PRAYERS) - { - Widget prayersContainer = client.getWidget(WidgetInfo.QUICK_PRAYER_PRAYERS); - if (prayersContainer == null) - { - return; - } - Widget[] prayerWidgets = prayersContainer.getDynamicChildren(); - if (prayerWidgets == null || prayerWidgets.length != PRAYER_COUNT * 3) - { - return; - } - - for (int index = 0; index < prayerOrder.length; index++) - { - Prayer prayer = prayerOrder[index]; - - int x = index % PRAYER_COLUMN_COUNT; - int y = index / PRAYER_COLUMN_COUNT; - - Widget prayerWidget = prayerWidgets[QUICK_PRAYER_CHILD_IDS.get(prayer.ordinal())]; - setWidgetPosition(prayerWidget, x * PRAYER_X_OFFSET, y * PRAYER_Y_OFFSET); - - int childId = PRAYER_COUNT + 2 * prayer.ordinal(); - - Widget prayerSpriteWidget = prayerWidgets[childId]; - setWidgetPosition(prayerSpriteWidget, - QUICK_PRAYER_SPRITE_X_OFFSET + x * PRAYER_X_OFFSET, - QUICK_PRAYER_SPRITE_Y_OFFSET + y * PRAYER_Y_OFFSET); - - Widget prayerToggleWidget = prayerWidgets[childId + 1]; - setWidgetPosition(prayerToggleWidget, x * PRAYER_X_OFFSET, y * PRAYER_Y_OFFSET); - } - } - } - -} +/* + * Copyright (c) 2018, Adam + * 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.reorderprayers; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Provides; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HashTable; +import net.runelite.api.Prayer; +import net.runelite.api.WidgetNode; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.DraggingWidgetChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.events.WidgetMenuOptionClicked; +import net.runelite.api.widgets.Widget; +import static net.runelite.api.widgets.WidgetConfig.DRAG; +import static net.runelite.api.widgets.WidgetConfig.DRAG_ON; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.menus.MenuManager; +import net.runelite.client.menus.WidgetMenuOption; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +@PluginDescriptor( + name = "Reorder Prayers", + description = "Reorder the prayers displayed on the Prayer panel" +) +public class ReorderPrayersPlugin extends Plugin +{ + + static final String CONFIG_GROUP_KEY = "reorderprayers"; + + static final String CONFIG_UNLOCK_REORDERING_KEY = "unlockPrayerReordering"; + + static final String CONFIG_PRAYER_ORDER_KEY = "prayerOrder"; + + private static final int PRAYER_WIDTH = 34; + + private static final int PRAYER_HEIGHT = 34; + + private static final int PRAYER_X_OFFSET = 37; + + private static final int PRAYER_Y_OFFSET = 37; + + private static final int QUICK_PRAYER_SPRITE_X_OFFSET = 2; + + private static final int QUICK_PRAYER_SPRITE_Y_OFFSET = 2; + + private static final int PRAYER_COLUMN_COUNT = 5; + + private static final int PRAYER_COUNT = Prayer.values().length; + + private static final List PRAYER_WIDGET_INFO_LIST = ImmutableList.of( + WidgetInfo.PRAYER_THICK_SKIN, + WidgetInfo.PRAYER_BURST_OF_STRENGTH, + WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, + WidgetInfo.PRAYER_SHARP_EYE, + WidgetInfo.PRAYER_MYSTIC_WILL, + WidgetInfo.PRAYER_ROCK_SKIN, + WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, + WidgetInfo.PRAYER_IMPROVED_REFLEXES, + WidgetInfo.PRAYER_RAPID_RESTORE, + WidgetInfo.PRAYER_RAPID_HEAL, + WidgetInfo.PRAYER_PROTECT_ITEM, + WidgetInfo.PRAYER_HAWK_EYE, + WidgetInfo.PRAYER_MYSTIC_LORE, + WidgetInfo.PRAYER_STEEL_SKIN, + WidgetInfo.PRAYER_ULTIMATE_STRENGTH, + WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, + WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, + WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, + WidgetInfo.PRAYER_PROTECT_FROM_MELEE, + WidgetInfo.PRAYER_EAGLE_EYE, + WidgetInfo.PRAYER_MYSTIC_MIGHT, + WidgetInfo.PRAYER_RETRIBUTION, + WidgetInfo.PRAYER_REDEMPTION, + WidgetInfo.PRAYER_SMITE, + WidgetInfo.PRAYER_PRESERVE, + WidgetInfo.PRAYER_CHIVALRY, + WidgetInfo.PRAYER_PIETY, + WidgetInfo.PRAYER_RIGOUR, + WidgetInfo.PRAYER_AUGURY + ); + + private static final List QUICK_PRAYER_CHILD_IDS = ImmutableList.of( + WidgetID.QuickPrayer.THICK_SKIN_CHILD_ID, + WidgetID.QuickPrayer.BURST_OF_STRENGTH_CHILD_ID, + WidgetID.QuickPrayer.CLARITY_OF_THOUGHT_CHILD_ID, + WidgetID.QuickPrayer.SHARP_EYE_CHILD_ID, + WidgetID.QuickPrayer.MYSTIC_WILL_CHILD_ID, + WidgetID.QuickPrayer.ROCK_SKIN_CHILD_ID, + WidgetID.QuickPrayer.SUPERHUMAN_STRENGTH_CHILD_ID, + WidgetID.QuickPrayer.IMPROVED_REFLEXES_CHILD_ID, + WidgetID.QuickPrayer.RAPID_RESTORE_CHILD_ID, + WidgetID.QuickPrayer.RAPID_HEAL_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_ITEM_CHILD_ID, + WidgetID.QuickPrayer.HAWK_EYE_CHILD_ID, + WidgetID.QuickPrayer.MYSTIC_LORE_CHILD_ID, + WidgetID.QuickPrayer.STEEL_SKIN_CHILD_ID, + WidgetID.QuickPrayer.ULTIMATE_STRENGTH_CHILD_ID, + WidgetID.QuickPrayer.INCREDIBLE_REFLEXES_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_FROM_MAGIC_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_FROM_MISSILES_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_FROM_MELEE_CHILD_ID, + WidgetID.QuickPrayer.EAGLE_EYE_CHILD_ID, + WidgetID.QuickPrayer.MYSTIC_MIGHT_CHILD_ID, + WidgetID.QuickPrayer.RETRIBUTION_CHILD_ID, + WidgetID.QuickPrayer.REDEMPTION_CHILD_ID, + WidgetID.QuickPrayer.SMITE_CHILD_ID, + WidgetID.QuickPrayer.PRESERVE_CHILD_ID, + WidgetID.QuickPrayer.CHIVALRY_CHILD_ID, + WidgetID.QuickPrayer.PIETY_CHILD_ID, + WidgetID.QuickPrayer.RIGOUR_CHILD_ID, + WidgetID.QuickPrayer.AUGURY_CHILD_ID + ); + + private static final String LOCK = "Lock"; + + private static final String UNLOCK = "Unlock"; + + private static final String MENU_TARGET = "Reordering"; + + private static final WidgetMenuOption FIXED_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, + MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption FIXED_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, + MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB); + + @Inject + private Client client; + + @Inject + private ReorderPrayersConfig config; + + @Inject + private MenuManager menuManager; + + private Prayer[] prayerOrder; + + static String prayerOrderToString(Prayer[] prayerOrder) + { + return Arrays.stream(prayerOrder) + .map(Prayer::name) + .collect(Collectors.joining(",")); + } + + private static Prayer[] stringToPrayerOrder(String string) + { + return Arrays.stream(string.split(",")) + .map(Prayer::valueOf) + .toArray(Prayer[]::new); + } + + private static int getPrayerIndex(Widget widget) + { + int x = widget.getOriginalX() / PRAYER_X_OFFSET; + int y = widget.getOriginalY() / PRAYER_Y_OFFSET; + return x + y * PRAYER_COLUMN_COUNT; + } + + private static void setWidgetPosition(Widget widget, int x, int y) + { + widget.setRelativeX(x); + widget.setRelativeY(y); + widget.setOriginalX(x); + widget.setOriginalY(y); + } + + @Provides + ReorderPrayersConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(ReorderPrayersConfig.class); + } + + @Override + protected void startUp() throws Exception + { + refreshPrayerTabOption(); + prayerOrder = stringToPrayerOrder(config.prayerOrder()); + reorderPrayers(); + } + + @Override + protected void shutDown() throws Exception + { + clearPrayerTabMenus(); + prayerOrder = Prayer.values(); + reorderPrayers(false); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState() == GameState.LOGGED_IN) + { + reorderPrayers(); + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals(CONFIG_GROUP_KEY)) + { + if (event.getKey().equals(CONFIG_PRAYER_ORDER_KEY)) + { + prayerOrder = stringToPrayerOrder(config.prayerOrder()); + } + else if (event.getKey().equals(CONFIG_UNLOCK_REORDERING_KEY)) + { + refreshPrayerTabOption(); + } + reorderPrayers(); + } + } + + @Subscribe + public void onWidgetLoaded(WidgetLoaded event) + { + if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) + { + reorderPrayers(); + } + } + + @Subscribe + public void onDraggingWidgetChanged(DraggingWidgetChanged event) + { + // is dragging widget and mouse button released + if (event.isDraggingWidget() && client.getMouseCurrentButton() == 0) + { + Widget draggedWidget = client.getDraggedWidget(); + Widget draggedOnWidget = client.getDraggedOnWidget(); + if (draggedWidget != null && draggedOnWidget != null) + { + int draggedGroupId = WidgetInfo.TO_GROUP(draggedWidget.getId()); + int draggedOnGroupId = WidgetInfo.TO_GROUP(draggedOnWidget.getId()); + if (draggedGroupId != WidgetID.PRAYER_GROUP_ID || draggedOnGroupId != WidgetID.PRAYER_GROUP_ID + || draggedOnWidget.getWidth() != PRAYER_WIDTH || draggedOnWidget.getHeight() != PRAYER_HEIGHT) + { + return; + } + // reset dragged on widget to prevent sending a drag widget packet to the server + client.setDraggedOnWidget(null); + + int fromPrayerIndex = getPrayerIndex(draggedWidget); + int toPrayerIndex = getPrayerIndex(draggedOnWidget); + + Prayer tmp = prayerOrder[toPrayerIndex]; + prayerOrder[toPrayerIndex] = prayerOrder[fromPrayerIndex]; + prayerOrder[fromPrayerIndex] = tmp; + + save(); + } + } + } + + @Subscribe + public void onWidgetMenuOptionClicked(WidgetMenuOptionClicked event) + { + if (event.getWidget() == WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB + || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB + || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB) + { + config.unlockPrayerReordering(event.getMenuOption().equals(UNLOCK)); + } + } + + private void clearPrayerTabMenus() + { + menuManager.removeManagedCustomMenu(FIXED_PRAYER_TAB_LOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_PRAYER_TAB_LOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK); + menuManager.removeManagedCustomMenu(FIXED_PRAYER_TAB_UNLOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_PRAYER_TAB_UNLOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK); + } + + private void refreshPrayerTabOption() + { + clearPrayerTabMenus(); + if (config.unlockPrayerReordering()) + { + menuManager.addManagedCustomMenu(FIXED_PRAYER_TAB_LOCK); + menuManager.addManagedCustomMenu(RESIZABLE_PRAYER_TAB_LOCK); + menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK); + } + else + { + menuManager.addManagedCustomMenu(FIXED_PRAYER_TAB_UNLOCK); + menuManager.addManagedCustomMenu(RESIZABLE_PRAYER_TAB_UNLOCK); + menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK); + } + } + + private PrayerTabState getPrayerTabState() + { + HashTable componentTable = client.getComponentTable(); + for (WidgetNode widgetNode : componentTable.getNodes()) + { + if (widgetNode.getId() == WidgetID.PRAYER_GROUP_ID) + { + return PrayerTabState.PRAYERS; + } + else if (widgetNode.getId() == WidgetID.QUICK_PRAYERS_GROUP_ID) + { + return PrayerTabState.QUICK_PRAYERS; + } + } + return PrayerTabState.NONE; + } + + private void save() + { + config.prayerOrder(prayerOrderToString(prayerOrder)); + } + + private void reorderPrayers() + { + reorderPrayers(config.unlockPrayerReordering()); + } + + private void reorderPrayers(boolean unlocked) + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + PrayerTabState prayerTabState = getPrayerTabState(); + + if (prayerTabState == PrayerTabState.PRAYERS) + { + List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream() + .map(client::getWidget) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { + return; + } + + for (int index = 0; index < prayerOrder.length; index++) + { + Prayer prayer = prayerOrder[index]; + Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); + + int widgetConfig = prayerWidget.getClickMask(); + if (unlocked) + { + // allow dragging of this widget + widgetConfig |= DRAG; + // allow this widget to be dragged on + widgetConfig |= DRAG_ON; + } + else + { + // remove drag flag + widgetConfig &= ~DRAG; + // remove drag on flag + widgetConfig &= ~DRAG_ON; + } + prayerWidget.setClickMask(widgetConfig); + + int x = index % PRAYER_COLUMN_COUNT; + int y = index / PRAYER_COLUMN_COUNT; + int widgetX = x * PRAYER_X_OFFSET; + int widgetY = y * PRAYER_Y_OFFSET; + setWidgetPosition(prayerWidget, widgetX, widgetY); + } + } + else if (prayerTabState == PrayerTabState.QUICK_PRAYERS) + { + Widget prayersContainer = client.getWidget(WidgetInfo.QUICK_PRAYER_PRAYERS); + if (prayersContainer == null) + { + return; + } + Widget[] prayerWidgets = prayersContainer.getDynamicChildren(); + if (prayerWidgets == null || prayerWidgets.length != PRAYER_COUNT * 3) + { + return; + } + + for (int index = 0; index < prayerOrder.length; index++) + { + Prayer prayer = prayerOrder[index]; + + int x = index % PRAYER_COLUMN_COUNT; + int y = index / PRAYER_COLUMN_COUNT; + + Widget prayerWidget = prayerWidgets[QUICK_PRAYER_CHILD_IDS.get(prayer.ordinal())]; + setWidgetPosition(prayerWidget, x * PRAYER_X_OFFSET, y * PRAYER_Y_OFFSET); + + int childId = PRAYER_COUNT + 2 * prayer.ordinal(); + + Widget prayerSpriteWidget = prayerWidgets[childId]; + setWidgetPosition(prayerSpriteWidget, + QUICK_PRAYER_SPRITE_X_OFFSET + x * PRAYER_X_OFFSET, + QUICK_PRAYER_SPRITE_Y_OFFSET + y * PRAYER_Y_OFFSET); + + Widget prayerToggleWidget = prayerWidgets[childId + 1]; + setWidgetPosition(prayerToggleWidget, x * PRAYER_X_OFFSET, y * PRAYER_Y_OFFSET); + } + } + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/Obstacles.java b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/Obstacles.java index 13c6052336..d4c2b356c3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/Obstacles.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/Obstacles.java @@ -1,53 +1,64 @@ -/* - * Copyright (c) 2018, Shaun Dreclin - * 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.roguesden; - -import com.google.common.collect.Sets; -import java.util.Set; -import static net.runelite.api.ObjectID.*; -import static net.runelite.api.NullObjectID.*; - -class Obstacles -{ - public static final Set OBSTACLE_IDS_HULL = Sets.newHashSet( - SPINNING_BLADES_7224, - CONTORTION_BARS, - PENDULUM, - WALL_7249, /*Wall crushers*/ - WALL_7248, /*Wall blade*/ - LEDGE_7240, /*Ledge climb*/ - NULL_7235 /*Wall safe*/ - ); - - public static final Set OBSTACLE_IDS_TILE = Sets.newHashSet( - FLOOR, /*Floor spikes*/ - WALL_7228, /*Wall spikes*/ - WALL_7229, /*Wall spears*/ - FLOOR_7245, /*Pressure pad a*/ - FLOOR_7230, /*Pressure pad b*/ - BLADE_7252, /*Floor blade*/ - 7239 /*Bridge [Ground object]*/ - ); -} +/* + * Copyright (c) 2018, Shaun Dreclin + * 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.roguesden; + +import com.google.common.collect.Sets; +import java.util.Set; +import static net.runelite.api.NullObjectID.NULL_7235; +import static net.runelite.api.ObjectID.BLADE_7252; +import static net.runelite.api.ObjectID.CONTORTION_BARS; +import static net.runelite.api.ObjectID.FLOOR; +import static net.runelite.api.ObjectID.FLOOR_7230; +import static net.runelite.api.ObjectID.FLOOR_7245; +import static net.runelite.api.ObjectID.LEDGE_7240; +import static net.runelite.api.ObjectID.PENDULUM; +import static net.runelite.api.ObjectID.SPINNING_BLADES_7224; +import static net.runelite.api.ObjectID.WALL_7228; +import static net.runelite.api.ObjectID.WALL_7229; +import static net.runelite.api.ObjectID.WALL_7248; +import static net.runelite.api.ObjectID.WALL_7249; + +class Obstacles +{ + public static final Set OBSTACLE_IDS_HULL = Sets.newHashSet( + SPINNING_BLADES_7224, + CONTORTION_BARS, + PENDULUM, + WALL_7249, /*Wall crushers*/ + WALL_7248, /*Wall blade*/ + LEDGE_7240, /*Ledge climb*/ + NULL_7235 /*Wall safe*/ + ); + + public static final Set OBSTACLE_IDS_TILE = Sets.newHashSet( + FLOOR, /*Floor spikes*/ + WALL_7228, /*Wall spikes*/ + WALL_7229, /*Wall spears*/ + FLOOR_7245, /*Pressure pad a*/ + FLOOR_7230, /*Pressure pad b*/ + BLADE_7252, /*Floor blade*/ + 7239 /*Bridge [Ground object]*/ + ); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java index 23f8e390b8..9e8a28ff6b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java @@ -1,241 +1,241 @@ -/* - * Copyright (c) 2016-2018, Seth - * 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.runecraft; - -import java.awt.Color; -import java.awt.Polygon; -import java.awt.geom.Area; -import static net.runelite.client.plugins.runecraft.AbyssRifts.AIR_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.BLOOD_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.BODY_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.CHAOS_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.COSMIC_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.DEATH_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.EARTH_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.FIRE_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.LAW_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.MIND_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.NATURE_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.SOUL_RIFT; -import static net.runelite.client.plugins.runecraft.AbyssRifts.WATER_RIFT; -import com.google.inject.Inject; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import net.runelite.api.Client; -import net.runelite.api.DecorativeObject; -import net.runelite.api.NPC; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; - -class AbyssOverlay extends Overlay -{ - private static final Dimension IMAGE_SIZE = new Dimension(15, 14); - - private final Set rifts = new HashSet<>(); - private final Map abyssIcons = new HashMap<>(); - - private final Client client; - private final RunecraftPlugin plugin; - private final RunecraftConfig config; - - @Inject - private ItemManager itemManager; - - @Inject - AbyssOverlay(Client client, RunecraftPlugin plugin, RunecraftConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_WIDGETS); - this.client = client; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (config.showRifts()) - { - for (DecorativeObject object : plugin.getAbyssObjects()) - { - renderRifts(graphics, object); - } - } - - if (config.hightlightDarkMage()) - { - highlightDarkMage(graphics); - } - - return null; - } - - private void highlightDarkMage(Graphics2D graphics) - { - if (!plugin.isDegradedPouchInInventory()) - { - return; - } - - NPC darkMage = plugin.getDarkMage(); - if (darkMage == null) - { - return; - } - - Polygon tilePoly = darkMage.getCanvasTilePoly(); - if (tilePoly == null) - { - return; - } - - OverlayUtil.renderPolygon(graphics, tilePoly, Color.green); - } - - private void renderRifts(Graphics2D graphics, DecorativeObject object) - { - AbyssRifts rift = AbyssRifts.getRift(object.getId()); - if (rift == null || !rifts.contains(rift)) - { - return; - } - - if (config.showClickBox()) - { - //Draw clickbox - Point mousePosition = client.getMouseCanvasPosition(); - Area objectClickbox = object.getClickbox(); - if (objectClickbox != null) - { - if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) - { - graphics.setColor(Color.MAGENTA.darker()); - } - else - { - graphics.setColor(Color.MAGENTA); - } - graphics.draw(objectClickbox); - graphics.setColor(new Color(255, 0, 255, 20)); - graphics.fill(objectClickbox); - } - } - - //Draw minimap - BufferedImage image = getImage(rift); - Point miniMapImage = Perspective.getMiniMapImageLocation(client, object.getLocalLocation(), image); - - if (miniMapImage != null) - { - graphics.drawImage(image, miniMapImage.getX(), miniMapImage.getY(), null); - } - } - - public BufferedImage getImage(AbyssRifts rift) - { - BufferedImage image = abyssIcons.get(rift); - if (image != null) - { - return image; - } - - // Since item image is too big, we must resize it first. - image = itemManager.getImage(rift.getItemId()); - BufferedImage resizedImage = new BufferedImage(IMAGE_SIZE.width, IMAGE_SIZE.height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = resizedImage.createGraphics(); - g.drawImage(image, 0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height, null); - g.dispose(); - - abyssIcons.put(rift, resizedImage); - return resizedImage; - } - - public void updateConfig() - { - rifts.clear(); - if (config.showAir()) - { - rifts.add(AIR_RIFT); - } - if (config.showBlood()) - { - rifts.add(BLOOD_RIFT); - } - if (config.showBody()) - { - rifts.add(BODY_RIFT); - } - if (config.showChaos()) - { - rifts.add(CHAOS_RIFT); - } - if (config.showCosmic()) - { - rifts.add(COSMIC_RIFT); - } - if (config.showDeath()) - { - rifts.add(DEATH_RIFT); - } - if (config.showEarth()) - { - rifts.add(EARTH_RIFT); - } - if (config.showFire()) - { - rifts.add(FIRE_RIFT); - } - if (config.showLaw()) - { - rifts.add(LAW_RIFT); - } - if (config.showMind()) - { - rifts.add(MIND_RIFT); - } - if (config.showNature()) - { - rifts.add(NATURE_RIFT); - } - if (config.showSoul()) - { - rifts.add(SOUL_RIFT); - } - if (config.showWater()) - { - rifts.add(WATER_RIFT); - } - } -} +/* + * Copyright (c) 2016-2018, Seth + * 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.runecraft; + +import com.google.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.geom.Area; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import net.runelite.api.Client; +import net.runelite.api.DecorativeObject; +import net.runelite.api.NPC; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.client.game.ItemManager; +import static net.runelite.client.plugins.runecraft.AbyssRifts.AIR_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.BLOOD_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.BODY_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.CHAOS_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.COSMIC_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.DEATH_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.EARTH_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.FIRE_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.LAW_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.MIND_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.NATURE_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.SOUL_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.WATER_RIFT; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; + +class AbyssOverlay extends Overlay +{ + private static final Dimension IMAGE_SIZE = new Dimension(15, 14); + + private final Set rifts = new HashSet<>(); + private final Map abyssIcons = new HashMap<>(); + + private final Client client; + private final RunecraftPlugin plugin; + private final RunecraftConfig config; + + @Inject + private ItemManager itemManager; + + @Inject + AbyssOverlay(Client client, RunecraftPlugin plugin, RunecraftConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (config.showRifts()) + { + for (DecorativeObject object : plugin.getAbyssObjects()) + { + renderRifts(graphics, object); + } + } + + if (config.hightlightDarkMage()) + { + highlightDarkMage(graphics); + } + + return null; + } + + private void highlightDarkMage(Graphics2D graphics) + { + if (!plugin.isDegradedPouchInInventory()) + { + return; + } + + NPC darkMage = plugin.getDarkMage(); + if (darkMage == null) + { + return; + } + + Polygon tilePoly = darkMage.getCanvasTilePoly(); + if (tilePoly == null) + { + return; + } + + OverlayUtil.renderPolygon(graphics, tilePoly, Color.green); + } + + private void renderRifts(Graphics2D graphics, DecorativeObject object) + { + AbyssRifts rift = AbyssRifts.getRift(object.getId()); + if (rift == null || !rifts.contains(rift)) + { + return; + } + + if (config.showClickBox()) + { + //Draw clickbox + Point mousePosition = client.getMouseCanvasPosition(); + Area objectClickbox = object.getClickbox(); + if (objectClickbox != null) + { + if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) + { + graphics.setColor(Color.MAGENTA.darker()); + } + else + { + graphics.setColor(Color.MAGENTA); + } + graphics.draw(objectClickbox); + graphics.setColor(new Color(255, 0, 255, 20)); + graphics.fill(objectClickbox); + } + } + + //Draw minimap + BufferedImage image = getImage(rift); + Point miniMapImage = Perspective.getMiniMapImageLocation(client, object.getLocalLocation(), image); + + if (miniMapImage != null) + { + graphics.drawImage(image, miniMapImage.getX(), miniMapImage.getY(), null); + } + } + + public BufferedImage getImage(AbyssRifts rift) + { + BufferedImage image = abyssIcons.get(rift); + if (image != null) + { + return image; + } + + // Since item image is too big, we must resize it first. + image = itemManager.getImage(rift.getItemId()); + BufferedImage resizedImage = new BufferedImage(IMAGE_SIZE.width, IMAGE_SIZE.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = resizedImage.createGraphics(); + g.drawImage(image, 0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height, null); + g.dispose(); + + abyssIcons.put(rift, resizedImage); + return resizedImage; + } + + public void updateConfig() + { + rifts.clear(); + if (config.showAir()) + { + rifts.add(AIR_RIFT); + } + if (config.showBlood()) + { + rifts.add(BLOOD_RIFT); + } + if (config.showBody()) + { + rifts.add(BODY_RIFT); + } + if (config.showChaos()) + { + rifts.add(CHAOS_RIFT); + } + if (config.showCosmic()) + { + rifts.add(COSMIC_RIFT); + } + if (config.showDeath()) + { + rifts.add(DEATH_RIFT); + } + if (config.showEarth()) + { + rifts.add(EARTH_RIFT); + } + if (config.showFire()) + { + rifts.add(FIRE_RIFT); + } + if (config.showLaw()) + { + rifts.add(LAW_RIFT); + } + if (config.showMind()) + { + rifts.add(MIND_RIFT); + } + if (config.showNature()) + { + rifts.add(NATURE_RIFT); + } + if (config.showSoul()) + { + rifts.add(SOUL_RIFT); + } + if (config.showWater()) + { + rifts.add(WATER_RIFT); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java index 38d6edc501..743d8b13d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java @@ -218,6 +218,7 @@ public interface RunecraftConfig extends Config { return true; } + @ConfigItem( keyName = "opLavas", name = "Op lavas", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java index 475a6bf998..55563b2fb9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java @@ -174,7 +174,7 @@ public class RunecraftPlugin extends Plugin swap(client, "fill", option, target); swap(client, "cancel", option, "", target); } - else if (option.equals("fill") && id != 9) + else if (option.equals("fill") && id != 9) { swap(client, "empty", option, target); } @@ -232,6 +232,7 @@ public class RunecraftPlugin extends Plugin { return searchIndex(entries, option, target, false); } + private int searchIndex(MenuEntry[] entries, String option, String target, boolean contains) { for (int i = entries.length - 1; i >= 0; i--) @@ -290,9 +291,9 @@ public class RunecraftPlugin extends Plugin if (event.getItemContainer() == client.getItemContainer(InventoryID.INVENTORY)) { - final Item[] items = event.getItemContainer().getItems(); - degradedPouchInInventory = Stream.of(items).anyMatch(i -> DEGRADED_POUCHES.contains(i.getId())); - } + final Item[] items = event.getItemContainer().getItems(); + degradedPouchInInventory = Stream.of(items).anyMatch(i -> DEGRADED_POUCHES.contains(i.getId())); + } else if (event.getItemContainer() == client.getItemContainer(InventoryID.EQUIPMENT)) { final Item[] items = event.getItemContainer().getItems(); @@ -319,6 +320,7 @@ public class RunecraftPlugin extends Plugin darkMage = null; } } + private boolean wearingBindingNeck() { final ItemContainer worn = client.getItemContainer(InventoryID.EQUIPMENT); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuConfig.java index 5d6cab6084..ddfc69a4dd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuConfig.java @@ -1,84 +1,111 @@ package net.runelite.client.plugins.runedoku; +import java.awt.Color; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -import java.awt.*; - @ConfigGroup("runedoku") -public interface RunedokuConfig extends Config { +public interface RunedokuConfig extends Config +{ @ConfigItem( - position = 0, - keyName = "mindRuneColor", - name = "Mind Rune Color", - description = "Color used to highlight Mind runes." + position = 0, + keyName = "mindRuneColor", + name = "Mind Rune Color", + description = "Color used to highlight Mind runes." ) - default Color mindRuneColor() { return Color.PINK; } + default Color mindRuneColor() + { + return Color.PINK; + } @ConfigItem( - position = 1, - keyName = "fireRuneColor", - name = "Fire Rune Color", - description = "Color used to highlight Fire runes." + position = 1, + keyName = "fireRuneColor", + name = "Fire Rune Color", + description = "Color used to highlight Fire runes." ) - default Color fireRuneColor() { return Color.RED; } + default Color fireRuneColor() + { + return Color.RED; + } @ConfigItem( - position = 2, - keyName = "bodyRuneColor", - name = "Body Rune Color", - description = "Color used to highlight Body runes." + position = 2, + keyName = "bodyRuneColor", + name = "Body Rune Color", + description = "Color used to highlight Body runes." ) - default Color bodyRuneColor() { return Color.MAGENTA; } + default Color bodyRuneColor() + { + return Color.MAGENTA; + } @ConfigItem( - position = 3, - keyName = "airRuneColor", - name = "Air Rune Color", - description = "Color used to highlight Air runes." + position = 3, + keyName = "airRuneColor", + name = "Air Rune Color", + description = "Color used to highlight Air runes." ) - default Color airRuneColor() { return Color.WHITE; } + default Color airRuneColor() + { + return Color.WHITE; + } @ConfigItem( - position = 4, - keyName = "deathRuneColor", - name = "Death Rune Color", - description = "Color used to highlight Death runes." + position = 4, + keyName = "deathRuneColor", + name = "Death Rune Color", + description = "Color used to highlight Death runes." ) - default Color deathRuneColor() { return Color.BLACK; } + default Color deathRuneColor() + { + return Color.BLACK; + } @ConfigItem( - position = 5, - keyName = "waterRuneColor", - name = "Water Rune Color", - description = "Color used to highlight Water runes." + position = 5, + keyName = "waterRuneColor", + name = "Water Rune Color", + description = "Color used to highlight Water runes." ) - default Color waterRuneColor() { return Color.BLUE; } + default Color waterRuneColor() + { + return Color.BLUE; + } @ConfigItem( - position = 6, - keyName = "chaosRuneColor", - name = "Chaos Rune Color", - description = "Color used to highlight Chaos runes." + position = 6, + keyName = "chaosRuneColor", + name = "Chaos Rune Color", + description = "Color used to highlight Chaos runes." ) - default Color chaosRuneColor() { return Color.YELLOW; } + default Color chaosRuneColor() + { + return Color.YELLOW; + } @ConfigItem( - position = 7, - keyName = "earthRuneColor", - name = "Earth Rune Color", - description = "Color used to highlight Earth runes." + position = 7, + keyName = "earthRuneColor", + name = "Earth Rune Color", + description = "Color used to highlight Earth runes." ) - default Color earthRuneColor() { return Color.GREEN; } + default Color earthRuneColor() + { + return Color.GREEN; + } @ConfigItem( - position = 8, - keyName = "lawRuneColor", - name = "Law Rune Color", - description = "Color used to highlight Law runes." + position = 8, + keyName = "lawRuneColor", + name = "Law Rune Color", + description = "Color used to highlight Law runes." ) - default Color lawRuneColor() { return Color.CYAN; } + default Color lawRuneColor() + { + return Color.CYAN; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java index 2f92172386..5cdb2908ce 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java @@ -24,22 +24,25 @@ package net.runelite.client.plugins.runedoku; +import java.awt.Color; +import static java.awt.Color.RED; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.util.ArrayList; +import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.widgets.Widget; -import net.runelite.client.ui.overlay.*; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.tooltip.TooltipManager; - -import javax.inject.Inject; -import java.awt.*; -import java.util.ArrayList; - -import static java.awt.Color.RED; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; /** * @author gazivodag */ -class RunedokuOverlay extends Overlay { +class RunedokuOverlay extends Overlay +{ private final RunedokuPlugin plugin; private final Client client; @@ -47,7 +50,8 @@ class RunedokuOverlay extends Overlay { @Inject - private RunedokuOverlay(final RunedokuPlugin plugin, final Client client, final RunedokuUtil util) { + private RunedokuOverlay(final RunedokuPlugin plugin, final Client client, final RunedokuUtil util) + { super(plugin); this.plugin = plugin; this.client = client; @@ -59,12 +63,15 @@ class RunedokuOverlay extends Overlay { } @Override - public Dimension render(Graphics2D graphics) { + public Dimension render(Graphics2D graphics) + { - final Widget sudokuScreen = client.getWidget(288,131); + final Widget sudokuScreen = client.getWidget(288, 131); - if (sudokuScreen != null) { - if (!sudokuScreen.isHidden()) { + if (sudokuScreen != null) + { + if (!sudokuScreen.isHidden()) + { Sudoku sudoku = new Sudoku(util.createTable(client)); boolean solved = sudoku.solve(); @@ -79,20 +86,29 @@ class RunedokuOverlay extends Overlay { /** * highlights the runes on the left handside so you know which runes to place on the board + * * @param graphics * @param solved */ - private void renderReferenceRunes(Graphics2D graphics, boolean solved) { + private void renderReferenceRunes(Graphics2D graphics, boolean solved) + { //reference runes on the left handside - for (int i = 121 ; i < 130 ; i++) { + for (int i = 121; i < 130; i++) + { Widget widget = client.getWidget(288, i); - if (solved) { - if (!util.makeSimple(util.createTable(client)).contains(0)) { + if (solved) + { + if (!util.makeSimple(util.createTable(client)).contains(0)) + { OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), Color.GREEN); - } else { + } + else + { OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), util.referenceColors(i)); } - } else { + } + else + { OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), RED); } @@ -101,24 +117,33 @@ class RunedokuOverlay extends Overlay { /** * goes through each 9x9 cell and tells you which piece to place in there + * * @param graphics * @param sudoku * @param solved */ - private void renderSolvedPuzzle(Graphics2D graphics, Sudoku sudoku, boolean solved) { + private void renderSolvedPuzzle(Graphics2D graphics, Sudoku sudoku, boolean solved) + { ArrayList simpleArr = util.makeSimple(sudoku.getBoard()); //highlight each cell to tell you which piece to place int iteration = 0; - for (int i = 10 ; i < 91 ; i++) { + for (int i = 10; i < 91; i++) + { Widget squareToHighlight = client.getWidget(288, i); - if (solved) { - if (!util.makeSimple(util.createTable(client)).contains(0)) { + if (solved) + { + if (!util.makeSimple(util.createTable(client)).contains(0)) + { OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), Color.GREEN); - } else { + } + else + { OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), util.sudokuPieceToColor(simpleArr.get(iteration))); } iteration++; - } else { + } + else + { OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), RED); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPiece.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPiece.java index c6a79628d6..7a6f50ab08 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPiece.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPiece.java @@ -24,7 +24,8 @@ package net.runelite.client.plugins.runedoku; -public enum RunedokuPiece { +public enum RunedokuPiece +{ NPC_PLACED_MIND_RUNE(6436, 1), //1 NPC_PLACED_FIRE_RUNE(6428, 2), //2 @@ -50,22 +51,28 @@ public enum RunedokuPiece { private final int pieceID; private final int pieceForSudoku; - RunedokuPiece (int pieceID, int pieceForSudoku) { + RunedokuPiece(int pieceID, int pieceForSudoku) + { this.pieceID = pieceID; this.pieceForSudoku = pieceForSudoku; } - int getId () { + int getId() + { return pieceID; } - int getPieceForSudoku() { + int getPieceForSudoku() + { return pieceForSudoku; } - static RunedokuPiece getById(int pieceID) { - for (RunedokuPiece e : RunedokuPiece.values()) { - if (e.getId() == pieceID) { + static RunedokuPiece getById(int pieceID) + { + for (RunedokuPiece e : RunedokuPiece.values()) + { + if (e.getId() == pieceID) + { return e; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPlugin.java index 81f80367d9..d984405992 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuPlugin.java @@ -25,6 +25,8 @@ package net.runelite.client.plugins.runedoku; import com.google.inject.Provides; +import javax.inject.Inject; +import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.client.config.ConfigManager; @@ -33,18 +35,16 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.ui.overlay.OverlayManager; -import javax.inject.Inject; -import javax.inject.Singleton; - @PluginDescriptor( - name = "Runedoku Solver", - description = "Show solutions for current Runedoku puzzle.", - tags = {"overlay", "runedoku", "sudoku", "puzzle", "solving"}, - type = PluginType.UTILITY + name = "Runedoku Solver", + description = "Show solutions for current Runedoku puzzle.", + tags = {"overlay", "runedoku", "sudoku", "puzzle", "solving"}, + type = PluginType.UTILITY ) @Slf4j @Singleton -public class RunedokuPlugin extends Plugin { +public class RunedokuPlugin extends Plugin +{ @Inject private Client client; @@ -62,17 +62,20 @@ public class RunedokuPlugin extends Plugin { private RunedokuConfig config; @Provides - RunedokuConfig provideConfig(ConfigManager configManager) { + RunedokuConfig provideConfig(ConfigManager configManager) + { return configManager.getConfig(RunedokuConfig.class); } @Override - protected void startUp() throws Exception { + protected void startUp() throws Exception + { overlayManager.add(runedokuOverlay); } @Override - protected void shutDown() throws Exception { + protected void shutDown() throws Exception + { overlayManager.remove(runedokuOverlay); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java index 3c15d85c07..2f6baf1c6b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java @@ -1,24 +1,29 @@ package net.runelite.client.plugins.runedoku; +import java.awt.Color; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.util.ArrayList; +import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetItem; -import javax.inject.Inject; -import java.awt.*; -import java.util.ArrayList; - -public class RunedokuUtil { +public class RunedokuUtil +{ private final RunedokuConfig config; @Inject - RunedokuUtil(final RunedokuConfig config) { + RunedokuUtil(final RunedokuConfig config) + { this.config = config; } - protected Color sudokuPieceToColor(int i) { - switch (i) { + protected Color sudokuPieceToColor(int i) + { + switch (i) + { case 1: return config.mindRuneColor(); case 2: @@ -42,8 +47,10 @@ public class RunedokuUtil { } } - protected Color referenceColors(int i) { - switch (i) { + protected Color referenceColors(int i) + { + switch (i) + { case 121: //earth return config.earthRuneColor(); case 122: //water @@ -69,13 +76,17 @@ public class RunedokuUtil { /** * Make the 2d array into an arraylist + * * @param board * @return */ - protected ArrayList makeSimple(int[][] board) { + protected ArrayList makeSimple(int[][] board) + { ArrayList list = new ArrayList<>(); - for (int i = 0 ; i < 9 ; i++) { - for (int ii = 0 ; ii < 9 ; ii++) { + for (int i = 0; i < 9; i++) + { + for (int ii = 0; ii < 9; ii++) + { list.add(board[i][ii]); } } @@ -84,10 +95,12 @@ public class RunedokuUtil { /** * utility method + * * @param rect * @return */ - protected Polygon RectangleToPolygon(Rectangle rect) { + protected Polygon RectangleToPolygon(Rectangle rect) + { int[] xpoints = {rect.x, rect.x + rect.width, rect.x + rect.width, rect.x}; int[] ypoints = {rect.y, rect.y, rect.y + rect.height, rect.y + rect.height}; return new Polygon(xpoints, ypoints, 4); @@ -95,27 +108,40 @@ public class RunedokuUtil { /** * Pulls data from what's on the Runedoku interface and creates a 2dimensional array for it - * @author gazivodag + * * @param client * @return sudoku table that the client currently sees in a 2d array + * @author gazivodag */ - protected int[][] createTable(Client client) { + protected int[][] createTable(Client client) + { int[][] myArr = new int[9][9]; - Widget sudokuScreen = client.getWidget(288,131); - for (int i = 0 ; i < 9 ; i++) { - for (int ii = 0 ; ii < 9 ; ii++) { + Widget sudokuScreen = client.getWidget(288, 131); + for (int i = 0; i < 9; i++) + { + for (int ii = 0; ii < 9; ii++) + { WidgetItem item; int myIndex; - if (i > 0) { + if (i > 0) + { myIndex = ((i * 10) + ii) - i; - } else { + } + else + { myIndex = ii; } - if (myIndex == 81) break; + if (myIndex == 81) + { + break; + } item = sudokuScreen.getWidgetItem(myIndex); - if (item != null) { + if (item != null) + { myArr[i][ii] = RunedokuPiece.getById(item.getId()).getPieceForSudoku(); - } else { + } + else + { myArr[i][ii] = 0; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/Sudoku.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/Sudoku.java index 666e026bd7..d04aa2464e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/Sudoku.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/Sudoku.java @@ -2,65 +2,97 @@ package net.runelite.client.plugins.runedoku; /** * Credits to whoever wrote this sudoku class. + * * @author ? */ -public class Sudoku { +public class Sudoku +{ private int[][] board; public static final int EMPTY = 0; public static final int SIZE = 9; - Sudoku(int[][] board) { + Sudoku(int[][] board) + { this.board = new int[SIZE][SIZE]; - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { + for (int i = 0; i < SIZE; i++) + { + for (int j = 0; j < SIZE; j++) + { this.board[i][j] = board[i][j]; } } } - private boolean isInRow(int row, int number) { + private boolean isInRow(int row, int number) + { for (int i = 0; i < SIZE; i++) + { if (board[row][i] == number) + { return true; + } + } return false; } - private boolean isInCol(int col, int number) { + private boolean isInCol(int col, int number) + { for (int i = 0; i < SIZE; i++) + { if (board[i][col] == number) + { return true; + } + } return false; } - private boolean isInBox(int row, int col, int number) { + private boolean isInBox(int row, int col, int number) + { int r = row - row % 3; int c = col - col % 3; for (int i = r; i < r + 3; i++) + { for (int j = c; j < c + 3; j++) + { if (board[i][j] == number) + { return true; + } + } + } return false; } - private boolean isOk(int row, int col, int number) { - return !isInRow(row, number) && !isInCol(col, number) && !isInBox(row, col, number); + private boolean isOk(int row, int col, int number) + { + return !isInRow(row, number) && !isInCol(col, number) && !isInBox(row, col, number); } - public boolean solve() { - for (int row = 0; row < SIZE; row++) { - for (int col = 0; col < SIZE; col++) { - if (board[row][col] == EMPTY) { - for (int number = 1; number <= SIZE; number++) { - if (isOk(row, col, number)) { + public boolean solve() + { + for (int row = 0; row < SIZE; row++) + { + for (int col = 0; col < SIZE; col++) + { + if (board[row][col] == EMPTY) + { + for (int number = 1; number <= SIZE; number++) + { + if (isOk(row, col, number)) + { board[row][col] = number; - if (solve()) { + if (solve()) + { return true; - } else { + } + else + { board[row][col] = EMPTY; } } @@ -73,9 +105,12 @@ public class Sudoku { return true; } - public void display() { - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { + public void display() + { + for (int i = 0; i < SIZE; i++) + { + for (int j = 0; j < SIZE; j++) + { System.out.print(" " + board[i][j]); } @@ -85,7 +120,8 @@ public class Sudoku { System.out.println(); } - public int[][] getBoard() { + public int[][] getBoard() + { return board; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java index fff84a100d..52170baa4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java @@ -33,7 +33,99 @@ import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; -import static net.runelite.api.ItemID.*; +import static net.runelite.api.ItemID.AGILITY_CAPE; +import static net.runelite.api.ItemID.AGILITY_CAPET; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_11861; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13589; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13590; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13601; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13602; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13613; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13614; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13625; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13626; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13637; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13638; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13677; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13678; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_21076; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_21078; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_11853; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13581; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13582; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13593; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13594; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13605; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13606; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13617; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13618; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13629; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13630; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13669; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13670; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_21064; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_21066; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_11859; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13587; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13588; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13599; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13600; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13611; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13612; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13623; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13624; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13635; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13636; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13675; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13676; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_21073; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_21075; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_11851; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13579; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13580; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13591; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13592; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13603; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13604; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13615; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13616; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13627; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13628; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13667; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13668; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_21061; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_21063; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_11857; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13585; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13586; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13597; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13598; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13609; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13610; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13621; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13622; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13633; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13634; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13673; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13674; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_21070; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_21072; +import static net.runelite.api.ItemID.GRACEFUL_TOP_11855; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13583; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13584; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13595; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13596; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13607; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13608; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13619; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13620; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13631; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13632; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13671; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13672; +import static net.runelite.api.ItemID.GRACEFUL_TOP_21067; +import static net.runelite.api.ItemID.GRACEFUL_TOP_21069; +import static net.runelite.api.ItemID.MAX_CAPE; import net.runelite.api.Skill; import net.runelite.api.Varbits; import net.runelite.api.coords.WorldPoint; @@ -135,8 +227,8 @@ public class RunEnergyPlugin extends Plugin { localPlayerRunningToDestination = prevLocalPlayerLocation != null && - client.getLocalDestinationLocation() != null && - prevLocalPlayerLocation.distanceTo(client.getLocalPlayer().getWorldLocation()) > 1; + client.getLocalDestinationLocation() != null && + prevLocalPlayerLocation.distanceTo(client.getLocalPlayer().getWorldLocation()) > 1; prevLocalPlayerLocation = client.getLocalPlayer().getWorldLocation(); @@ -188,14 +280,14 @@ public class RunEnergyPlugin extends Plugin // Return the text if (inSeconds) { - return Integer.toString((int) Math.floor(secondsLeft)) + "s"; + return (int) Math.floor(secondsLeft) + "s"; } else { final int minutes = (int) Math.floor(secondsLeft / 60.0); final int seconds = (int) Math.floor(secondsLeft - (minutes * 60.0)); - return Integer.toString(minutes) + ":" + StringUtils.leftPad(Integer.toString(seconds), 2, "0"); + return minutes + ":" + StringUtils.leftPad(Integer.toString(seconds), 2, "0"); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java index a7e2fd86d7..014fe007f7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/RunepouchOverlay.java @@ -1,179 +1,179 @@ -/* - * Copyright (c) 2017, Tyler - * 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.runepouch; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.ItemID; -import net.runelite.api.Point; -import net.runelite.api.Varbits; -import net.runelite.api.widgets.WidgetItem; -import net.runelite.client.game.ItemManager; -import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.BOTH; -import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.MOUSE_HOVER; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.overlay.OverlayUtil; -import net.runelite.client.ui.overlay.WidgetItemOverlay; -import net.runelite.client.ui.overlay.tooltip.Tooltip; -import net.runelite.client.ui.overlay.tooltip.TooltipManager; -import net.runelite.client.util.ColorUtil; - -public class RunepouchOverlay extends WidgetItemOverlay -{ - private static final Varbits[] AMOUNT_VARBITS = - { - Varbits.RUNE_POUCH_AMOUNT1, Varbits.RUNE_POUCH_AMOUNT2, Varbits.RUNE_POUCH_AMOUNT3 - }; - private static final Varbits[] RUNE_VARBITS = - { - Varbits.RUNE_POUCH_RUNE1, Varbits.RUNE_POUCH_RUNE2, Varbits.RUNE_POUCH_RUNE3 - }; - private static final Dimension IMAGE_SIZE = new Dimension(11, 11); - - private final Client client; - private final RunepouchConfig config; - private final TooltipManager tooltipManager; - - @Inject - private ItemManager itemManager; - - @Inject - RunepouchOverlay(Client client, RunepouchConfig config, TooltipManager tooltipManager) - { - this.tooltipManager = tooltipManager; - this.client = client; - this.config = config; - showOnInventory(); - showOnBank(); - } - - @Override - public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem itemWidget) - { - if (itemId != ItemID.RUNE_POUCH) - { - return; - } - - assert AMOUNT_VARBITS.length == RUNE_VARBITS.length; - - graphics.setFont(FontManager.getRunescapeSmallFont()); - - Point location = itemWidget.getCanvasLocation(); - StringBuilder tooltipBuilder = new StringBuilder(); - - for (int i = 0; i < AMOUNT_VARBITS.length; i++) - { - Varbits amountVarbit = AMOUNT_VARBITS[i]; - - int amount = client.getVar(amountVarbit); - if (amount <= 0) - { - continue; - } - - Varbits runeVarbit = RUNE_VARBITS[i]; - int runeId = client.getVar(runeVarbit); - Runes rune = Runes.getRune(runeId); - if (rune == null) - { - continue; - } - - tooltipBuilder - .append(amount) - .append(" ") - .append(ColorUtil.wrapWithColorTag(rune.getName(), Color.YELLOW)) - .append("
"); - - if (config.runePouchOverlayMode() == MOUSE_HOVER) - { - continue; - } - - graphics.setColor(Color.black); - graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 13 : 6), - location.getY() + 14 + (graphics.getFontMetrics().getHeight() - 1) * i); - - graphics.setColor(config.fontColor()); - graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 12 : 5), - location.getY() + 13 + (graphics.getFontMetrics().getHeight() - 1) * i); - - if (!config.showIcons()) - { - continue; - } - - BufferedImage image = getRuneImage(rune); - if (image != null) - { - OverlayUtil.renderImageLocation(graphics, - new Point(location.getX(), location.getY() + graphics.getFontMetrics().getHeight() * i), - image); - } - } - - String tooltip = tooltipBuilder.toString(); - - if (!tooltip.isEmpty() - && itemWidget.getCanvasBounds().contains(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY()) - && (config.runePouchOverlayMode() == MOUSE_HOVER || config.runePouchOverlayMode() == BOTH)) - { - tooltipManager.add(new Tooltip(tooltip)); - } - } - - private BufferedImage getRuneImage(Runes rune) - { - BufferedImage runeImg = rune.getImage(); - if (runeImg != null) - { - return runeImg; - } - - runeImg = itemManager.getImage(rune.getItemId()); - if (runeImg == null) - { - return null; - } - - BufferedImage resizedImg = new BufferedImage(IMAGE_SIZE.width, IMAGE_SIZE.height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = resizedImg.createGraphics(); - g.drawImage(runeImg, 0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height, null); - g.dispose(); - - rune.setImage(resizedImg); - return resizedImg; - } - - private static String formatNumber(int amount) - { - return amount < 1000 ? String.valueOf(amount) : amount / 1000 + "K"; - } -} +/* + * Copyright (c) 2017, Tyler + * 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.runepouch; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.ItemID; +import net.runelite.api.Point; +import net.runelite.api.Varbits; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.game.ItemManager; +import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.BOTH; +import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.MOUSE_HOVER; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.WidgetItemOverlay; +import net.runelite.client.ui.overlay.tooltip.Tooltip; +import net.runelite.client.ui.overlay.tooltip.TooltipManager; +import net.runelite.client.util.ColorUtil; + +public class RunepouchOverlay extends WidgetItemOverlay +{ + private static final Varbits[] AMOUNT_VARBITS = + { + Varbits.RUNE_POUCH_AMOUNT1, Varbits.RUNE_POUCH_AMOUNT2, Varbits.RUNE_POUCH_AMOUNT3 + }; + private static final Varbits[] RUNE_VARBITS = + { + Varbits.RUNE_POUCH_RUNE1, Varbits.RUNE_POUCH_RUNE2, Varbits.RUNE_POUCH_RUNE3 + }; + private static final Dimension IMAGE_SIZE = new Dimension(11, 11); + + private final Client client; + private final RunepouchConfig config; + private final TooltipManager tooltipManager; + + @Inject + private ItemManager itemManager; + + @Inject + RunepouchOverlay(Client client, RunepouchConfig config, TooltipManager tooltipManager) + { + this.tooltipManager = tooltipManager; + this.client = client; + this.config = config; + showOnInventory(); + showOnBank(); + } + + @Override + public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem itemWidget) + { + if (itemId != ItemID.RUNE_POUCH) + { + return; + } + + assert AMOUNT_VARBITS.length == RUNE_VARBITS.length; + + graphics.setFont(FontManager.getRunescapeSmallFont()); + + Point location = itemWidget.getCanvasLocation(); + StringBuilder tooltipBuilder = new StringBuilder(); + + for (int i = 0; i < AMOUNT_VARBITS.length; i++) + { + Varbits amountVarbit = AMOUNT_VARBITS[i]; + + int amount = client.getVar(amountVarbit); + if (amount <= 0) + { + continue; + } + + Varbits runeVarbit = RUNE_VARBITS[i]; + int runeId = client.getVar(runeVarbit); + Runes rune = Runes.getRune(runeId); + if (rune == null) + { + continue; + } + + tooltipBuilder + .append(amount) + .append(" ") + .append(ColorUtil.wrapWithColorTag(rune.getName(), Color.YELLOW)) + .append("
"); + + if (config.runePouchOverlayMode() == MOUSE_HOVER) + { + continue; + } + + graphics.setColor(Color.black); + graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 13 : 6), + location.getY() + 14 + (graphics.getFontMetrics().getHeight() - 1) * i); + + graphics.setColor(config.fontColor()); + graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 12 : 5), + location.getY() + 13 + (graphics.getFontMetrics().getHeight() - 1) * i); + + if (!config.showIcons()) + { + continue; + } + + BufferedImage image = getRuneImage(rune); + if (image != null) + { + OverlayUtil.renderImageLocation(graphics, + new Point(location.getX(), location.getY() + graphics.getFontMetrics().getHeight() * i), + image); + } + } + + String tooltip = tooltipBuilder.toString(); + + if (!tooltip.isEmpty() + && itemWidget.getCanvasBounds().contains(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY()) + && (config.runePouchOverlayMode() == MOUSE_HOVER || config.runePouchOverlayMode() == BOTH)) + { + tooltipManager.add(new Tooltip(tooltip)); + } + } + + private BufferedImage getRuneImage(Runes rune) + { + BufferedImage runeImg = rune.getImage(); + if (runeImg != null) + { + return runeImg; + } + + runeImg = itemManager.getImage(rune.getItemId()); + if (runeImg == null) + { + return null; + } + + BufferedImage resizedImg = new BufferedImage(IMAGE_SIZE.width, IMAGE_SIZE.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = resizedImg.createGraphics(); + g.drawImage(runeImg, 0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height, null); + g.dispose(); + + rune.setImage(resizedImg); + return resizedImg; + } + + private static String formatNumber(int amount) + { + return amount < 1000 ? String.valueOf(amount) : amount / 1000 + "K"; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java index b5aebe9bf6..3031aa7b97 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runepouch/Runes.java @@ -111,7 +111,7 @@ public enum Runes public String getName() { String name = this.name(); - name = name.substring(0, 1) + name.substring(1, name.length()).toLowerCase(); + name = name.substring(0, 1) + name.substring(1).toLowerCase(); return name; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java index c586b9cd91..dcd010d81e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java @@ -1,754 +1,754 @@ -/* - * Copyright (c) 2018, Lotto - * 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.screenshot; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.inject.Provides; -import java.awt.Desktop; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Toolkit; -import java.awt.TrayIcon; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.StringSelection; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.util.Date; -import java.util.EnumSet; -import java.util.concurrent.ScheduledExecutorService; -import java.util.function.Consumer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.imageio.ImageIO; -import javax.inject.Inject; -import javax.swing.SwingUtilities; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.Player; -import net.runelite.api.Point; -import net.runelite.api.SpriteID; -import net.runelite.api.WorldType; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.LocalPlayerDeath; -import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.widgets.Widget; -import static net.runelite.api.widgets.WidgetID.BARROWS_REWARD_GROUP_ID; -import static net.runelite.api.widgets.WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID; -import static net.runelite.api.widgets.WidgetID.CLUE_SCROLL_REWARD_GROUP_ID; -import static net.runelite.api.widgets.WidgetID.DIALOG_SPRITE_GROUP_ID; -import static net.runelite.api.widgets.WidgetID.KINGDOM_GROUP_ID; -import static net.runelite.api.widgets.WidgetID.LEVEL_UP_GROUP_ID; -import static net.runelite.api.widgets.WidgetID.QUEST_COMPLETED_GROUP_ID; -import static net.runelite.api.widgets.WidgetID.THEATRE_OF_BLOOD_REWARD_GROUP_ID; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.Notifier; -import static net.runelite.client.RuneLite.SCREENSHOT_DIR; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.events.PlayerLootReceived; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.screenshot.imgur.ImageUploadRequest; -import net.runelite.client.plugins.screenshot.imgur.ImageUploadResponse; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.ClientUI; -import net.runelite.client.ui.DrawManager; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.HotkeyListener; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.Text; -import net.runelite.http.api.RuneLiteAPI; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.HttpUrl; -import okhttp3.MediaType; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -@PluginDescriptor( - name = "Screenshot", - description = "Enable the manual and automatic taking of screenshots", - tags = {"external", "images", "imgur", "integration", "notifications"} -) -@Slf4j -public class ScreenshotPlugin extends Plugin -{ - private static final String IMGUR_CLIENT_ID = "30d71e5f6860809"; - private static final HttpUrl IMGUR_IMAGE_UPLOAD_URL = HttpUrl.parse("https://api.imgur.com/3/image"); - private static final MediaType JSON = MediaType.parse("application/json"); - - private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); - - private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)"); - private static final Pattern LEVEL_UP_PATTERN = Pattern.compile(".*Your ([a-zA-Z]+) (?:level is|are)? now (\\d+)\\."); - private static final Pattern BOSSKILL_MESSAGE_PATTERN = Pattern.compile("Your (.+) kill count is: (\\d+)."); - private static final Pattern VALUABLE_DROP_PATTERN = Pattern.compile(".*Valuable drop: ([^<>]+)(?:)?"); - private static final Pattern UNTRADEABLE_DROP_PATTERN = Pattern.compile(".*Untradeable drop: ([^<>]+)(?:)?"); - private static final Pattern DUEL_END_PATTERN = Pattern.compile("You have now (won|lost) ([0-9]+) duels?\\."); - private static final ImmutableList PET_MESSAGES = ImmutableList.of("You have a funny feeling like you're being followed", - "You feel something weird sneaking into your backpack", - "You have a funny feeling like you would have been followed"); - - static String format(Date date) - { - synchronized (TIME_FORMAT) - { - return TIME_FORMAT.format(date); - } - } - - private String clueType; - private Integer clueNumber; - - private Integer barrowsNumber; - - private Integer chambersOfXericNumber; - - private Integer chambersOfXericChallengeNumber; - - private Integer theatreOfBloodNumber; - - private boolean shouldTakeScreenshot; - - @Inject - private ScreenshotConfig config; - - @Inject - private OverlayManager overlayManager; - - @Inject - private ScreenshotOverlay screenshotOverlay; - - @Inject - private Notifier notifier; - - @Inject - private Client client; - - @Inject - private ClientUI clientUi; - - @Inject - private ClientToolbar clientToolbar; - - @Inject - private DrawManager drawManager; - - @Inject - private ScheduledExecutorService executor; - - @Inject - private KeyManager keyManager; - - @Inject - private SpriteManager spriteManager; - - @Getter(AccessLevel.PACKAGE) - private BufferedImage reportButton; - - private NavigationButton titleBarButton; - - private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.hotkey()) - { - @Override - public void hotkeyPressed() - { - takeScreenshot(format(new Date())); - } - }; - - @Provides - ScreenshotConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(ScreenshotConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(screenshotOverlay); - SCREENSHOT_DIR.mkdirs(); - keyManager.registerKeyListener(hotkeyListener); - - final BufferedImage iconImage = ImageUtil.getResourceStreamFromClass(getClass(), "screenshot.png"); - - titleBarButton = NavigationButton.builder() - .tab(false) - .tooltip("Take screenshot") - .icon(iconImage) - .onClick(() -> takeScreenshot(format(new Date()))) - .popup(ImmutableMap - .builder() - .put("Open screenshot folder...", () -> - { - try - { - Desktop.getDesktop().open(SCREENSHOT_DIR); - } - catch (IOException ex) - { - log.warn("Error opening screenshot dir", ex); - } - }) - .build()) - .build(); - - clientToolbar.addNavigation(titleBarButton); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(screenshotOverlay); - clientToolbar.removeNavigation(titleBarButton); - keyManager.unregisterKeyListener(hotkeyListener); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGGED_IN - && reportButton == null) - { - reportButton = spriteManager.getSprite(SpriteID.CHATBOX_REPORT_BUTTON, 0); - } - } - - @Subscribe - public void onGameTick(GameTick event) - { - if (!shouldTakeScreenshot) - { - return; - } - - shouldTakeScreenshot = false; - - String fileName = null; - if (client.getWidget(WidgetInfo.LEVEL_UP_LEVEL) != null) - { - fileName = parseLevelUpWidget(WidgetInfo.LEVEL_UP_LEVEL); - } - else if (client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT) != null) - { - fileName = parseLevelUpWidget(WidgetInfo.DIALOG_SPRITE_TEXT); - } - else if (client.getWidget(WidgetInfo.QUEST_COMPLETED_NAME_TEXT) != null) - { - // "You have completed The Corsair Curse!" - String text = client.getWidget(WidgetInfo.QUEST_COMPLETED_NAME_TEXT).getText(); - fileName = "Quest(" + text.substring(19, text.length() - 1) + ")"; - } - - if (fileName != null) - { - takeScreenshot(fileName); - } - } - - @Subscribe - public void onLocalPlayerDeath(LocalPlayerDeath death) - { - if (config.screenshotPlayerDeath()) - { - takeScreenshot("Death " + format(new Date())); - } - } - - @Subscribe - public void onPlayerLootReceived(final PlayerLootReceived playerLootReceived) - { - if (config.screenshotKills()) - { - final Player player = playerLootReceived.getPlayer(); - final String name = player.getName(); - String fileName = "Kill " + name + " " + format(new Date()); - takeScreenshot(fileName); - } - } - - @Subscribe - public void onChatMessage(ChatMessage event) - { - if (event.getType() != ChatMessageType.GAMEMESSAGE && event.getType() != ChatMessageType.SPAM && event.getType() != ChatMessageType.TRADE) - { - return; - } - - String chatMessage = event.getMessage(); - - if (chatMessage.contains("You have completed") && chatMessage.contains("Treasure")) - { - Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); - if (m.find()) - { - clueNumber = Integer.valueOf(m.group()); - clueType = chatMessage.substring(chatMessage.lastIndexOf(m.group()) + m.group().length() + 1, chatMessage.indexOf("Treasure") - 1); - return; - } - } - - if (chatMessage.startsWith("Your Barrows chest count is")) - { - Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); - if (m.find()) - { - barrowsNumber = Integer.valueOf(m.group()); - return; - } - } - - if (chatMessage.startsWith("Your completed Chambers of Xeric count is:")) - { - Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); - if (m.find()) - { - chambersOfXericNumber = Integer.valueOf(m.group()); - return; - } - } - - if (chatMessage.startsWith("Your completed Chambers of Xeric Challenge Mode count is:")) - { - Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); - if (m.find()) - { - chambersOfXericChallengeNumber = Integer.valueOf(m.group()); - return; - } - } - - if (chatMessage.startsWith("Your completed Theatre of Blood count is:")) - { - Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); - if (m.find()) - { - theatreOfBloodNumber = Integer.valueOf(m.group()); - return; - } - } - - if (config.screenshotPet() && PET_MESSAGES.stream().anyMatch(chatMessage::contains)) - { - String fileName = "Pet " + format(new Date()); - takeScreenshot(fileName); - } - - if (config.screenshotBossKills() ) - { - Matcher m = BOSSKILL_MESSAGE_PATTERN.matcher(chatMessage); - if (m.matches()) - { - String bossName = m.group(1); - String bossKillcount = m.group(2); - String fileName = bossName + "(" + bossKillcount + ")"; - takeScreenshot(fileName); - } - } - - if (config.screenshotValuableDrop()) - { - Matcher m = VALUABLE_DROP_PATTERN.matcher(chatMessage); - if (m.matches()) - { - String valuableDropName = m.group(1); - String fileName = "Valuable drop " + valuableDropName + " " + format(new Date()); - takeScreenshot(fileName); - } - } - - if (config.screenshotUntradeableDrop()) - { - Matcher m = UNTRADEABLE_DROP_PATTERN.matcher(chatMessage); - if (m.matches()) - { - String untradeableDropName = m.group(1); - String fileName = "Untradeable drop " + untradeableDropName + " " + format(new Date()); - takeScreenshot(fileName); - } - } - - if (config.screenshotDuels()) - { - Matcher m = DUEL_END_PATTERN.matcher(chatMessage); - if (m.find()) - { - String result = m.group(1); - String count = m.group(2); - String fileName = "Duel " + result + " (" + count + ")"; - takeScreenshot(fileName); - } - } - } - - @Subscribe - public void onWidgetLoaded(WidgetLoaded event) - { - String fileName; - int groupId = event.getGroupId(); - - switch (groupId) - { - case QUEST_COMPLETED_GROUP_ID: - case CLUE_SCROLL_REWARD_GROUP_ID: - case CHAMBERS_OF_XERIC_REWARD_GROUP_ID: - case THEATRE_OF_BLOOD_REWARD_GROUP_ID: - case BARROWS_REWARD_GROUP_ID: - if (!config.screenshotRewards()) - { - return; - } - break; - case LEVEL_UP_GROUP_ID: - case DIALOG_SPRITE_GROUP_ID: - if (!config.screenshotLevels()) - { - return; - } - break; - case KINGDOM_GROUP_ID: - if (!config.screenshotKingdom()) - { - return; - } - break; - } - - switch (groupId) - { - case KINGDOM_GROUP_ID: - { - fileName = "Kingdom " + LocalDate.now(); - takeScreenshot(fileName); - break; - } - case CHAMBERS_OF_XERIC_REWARD_GROUP_ID: - { - if (chambersOfXericNumber != null) - { - fileName = "Chambers of Xeric(" + chambersOfXericNumber + ")"; - chambersOfXericNumber = null; - break; - } - else if (chambersOfXericChallengeNumber != null) - { - fileName = "Chambers of Xeric Challenge Mode(" + chambersOfXericChallengeNumber + ")"; - chambersOfXericChallengeNumber = null; - break; - } - else - { - return; - } - } - case THEATRE_OF_BLOOD_REWARD_GROUP_ID: - { - if (theatreOfBloodNumber == null) - { - return; - } - - fileName = "Theatre of Blood(" + theatreOfBloodNumber + ")"; - theatreOfBloodNumber = null; - break; - } - case BARROWS_REWARD_GROUP_ID: - { - if (barrowsNumber == null) - { - return; - } - - fileName = "Barrows(" + barrowsNumber + ")"; - barrowsNumber = null; - break; - } - case LEVEL_UP_GROUP_ID: - case DIALOG_SPRITE_GROUP_ID: - case QUEST_COMPLETED_GROUP_ID: - { - // level up widget gets loaded prior to the text being set, so wait until the next tick - shouldTakeScreenshot = true; - return; - } - case CLUE_SCROLL_REWARD_GROUP_ID: - { - if (clueType == null || clueNumber == null) - { - return; - } - - fileName = Character.toUpperCase(clueType.charAt(0)) + clueType.substring(1) + "(" + clueNumber + ")"; - clueType = null; - clueNumber = null; - break; - } - default: - return; - } - - takeScreenshot(fileName); - } - - /** - * Receives a WidgetInfo pointing to the middle widget of the level-up dialog, - * and parses it into a shortened string for filename usage. - * - * @param levelUpLevel WidgetInfo pointing to the required text widget, - * with the format "Your Skill (level is/are) now 99." - * @return Shortened string in the format "Skill(99)" - */ - String parseLevelUpWidget(WidgetInfo levelUpLevel) - { - Widget levelChild = client.getWidget(levelUpLevel); - if (levelChild == null) - { - return null; - } - - Matcher m = LEVEL_UP_PATTERN.matcher(levelChild.getText()); - if (!m.matches()) - { - return null; - } - - String skillName = m.group(1); - String skillLevel = m.group(2); - return skillName + "(" + skillLevel + ")"; - } - - /** - * Saves a screenshot of the client window to the screenshot folder as a PNG, - * and optionally uploads it to an image-hosting service. - * - * @param fileName Filename to use, without file extension. - */ - private void takeScreenshot(String fileName) - { - if (client.getGameState() == GameState.LOGIN_SCREEN) - { - // Prevent the screenshot from being captured - log.info("Login screenshot prevented"); - return; - } - - Consumer imageCallback = (img) -> - { - // This callback is on the game thread, move to executor thread - executor.submit(() -> takeScreenshot(fileName, img)); - }; - - if (config.displayDate()) - { - screenshotOverlay.queueForTimestamp(imageCallback); - } - else - { - drawManager.requestNextFrameListener(imageCallback); - } - } - - private void takeScreenshot(String fileName, Image image) - { - BufferedImage screenshot = config.includeFrame() - ? new BufferedImage(clientUi.getWidth(), clientUi.getHeight(), BufferedImage.TYPE_INT_ARGB) - : new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); - - Graphics graphics = screenshot.getGraphics(); - - int gameOffsetX = 0; - int gameOffsetY = 0; - - if (config.includeFrame()) - { - // Draw the client frame onto the screenshot - try - { - SwingUtilities.invokeAndWait(() -> clientUi.paint(graphics)); - } - catch (InterruptedException | InvocationTargetException e) - { - log.warn("unable to paint client UI on screenshot", e); - } - - // Evaluate the position of the game inside the frame - final Point canvasOffset = clientUi.getCanvasOffset(); - gameOffsetX = canvasOffset.getX(); - gameOffsetY = canvasOffset.getY(); - } - - // Draw the game onto the screenshot - graphics.drawImage(image, gameOffsetX, gameOffsetY, null); - - File playerFolder; - if (client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) - { - final EnumSet worldTypes = client.getWorldType(); - final boolean dmm = worldTypes.contains(WorldType.DEADMAN); - final boolean sdmm = worldTypes.contains(WorldType.SEASONAL_DEADMAN); - final boolean dmmt = worldTypes.contains(WorldType.DEADMAN_TOURNAMENT); - final boolean isDmmWorld = dmm || sdmm || dmmt; - - String playerDir = client.getLocalPlayer().getName(); - if (isDmmWorld) - { - playerDir += "-Deadman"; - } - playerFolder = new File(SCREENSHOT_DIR, playerDir); - } - else - { - playerFolder = SCREENSHOT_DIR; - } - - playerFolder.mkdirs(); - - try - { - File screenshotFile = new File(playerFolder, fileName + ".png"); - - ImageIO.write(screenshot, "PNG", screenshotFile); - - if (config.uploadScreenshot()) - { - uploadScreenshot(screenshotFile); - } - else if (config.notifyWhenTaken()) - { - notifier.notify("A screenshot was saved to " + screenshotFile, TrayIcon.MessageType.INFO); - } - } - catch (IOException ex) - { - log.warn("error writing screenshot", ex); - } - } - - /** - * Uploads a screenshot to the Imgur image-hosting service, - * and copies the image link to the clipboard. - * - * @param screenshotFile Image file to upload. - * @throws IOException Thrown if the file cannot be read. - */ - private void uploadScreenshot(File screenshotFile) throws IOException - { - String json = RuneLiteAPI.GSON.toJson(new ImageUploadRequest(screenshotFile)); - - Request request = new Request.Builder() - .url(IMGUR_IMAGE_UPLOAD_URL) - .addHeader("Authorization", "Client-ID " + IMGUR_CLIENT_ID) - .post(RequestBody.create(JSON, json)) - .build(); - - RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() - { - @Override - public void onFailure(Call call, IOException ex) - { - log.warn("error uploading screenshot", ex); - } - - @Override - public void onResponse(Call call, Response response) throws IOException - { - try (InputStream in = response.body().byteStream()) - { - ImageUploadResponse imageUploadResponse = RuneLiteAPI.GSON - .fromJson(new InputStreamReader(in), ImageUploadResponse.class); - - if (imageUploadResponse.isSuccess()) - { - String link = imageUploadResponse.getData().getLink(); - - StringSelection selection = new StringSelection(link); - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - clipboard.setContents(selection, selection); - - if (config.notifyWhenTaken()) - { - notifier.notify("A screenshot was uploaded and inserted into your clipboard!", TrayIcon.MessageType.INFO); - } - } - } - } - }); - } - - @VisibleForTesting - int getClueNumber() - { - return clueNumber; - } - - @VisibleForTesting - String getClueType() - { - return clueType; - } - - @VisibleForTesting - int getBarrowsNumber() - { - return barrowsNumber; - } - - @VisibleForTesting - int getChambersOfXericNumber() - { - return chambersOfXericNumber; - } - - @VisibleForTesting - int getChambersOfXericChallengeNumber() - { - return chambersOfXericChallengeNumber; - } - - @VisibleForTesting - int gettheatreOfBloodNumber() - { - return theatreOfBloodNumber; - } -} +/* + * Copyright (c) 2018, Lotto + * 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.screenshot; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Provides; +import java.awt.Desktop; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.TrayIcon; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.Date; +import java.util.EnumSet; +import java.util.concurrent.ScheduledExecutorService; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.imageio.ImageIO; +import javax.inject.Inject; +import javax.swing.SwingUtilities; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Player; +import net.runelite.api.Point; +import net.runelite.api.SpriteID; +import net.runelite.api.WorldType; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.LocalPlayerDeath; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import static net.runelite.api.widgets.WidgetID.BARROWS_REWARD_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.CLUE_SCROLL_REWARD_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.DIALOG_SPRITE_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.KINGDOM_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.LEVEL_UP_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.QUEST_COMPLETED_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.THEATRE_OF_BLOOD_REWARD_GROUP_ID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.Notifier; +import static net.runelite.client.RuneLite.SCREENSHOT_DIR; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.PlayerLootReceived; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.screenshot.imgur.ImageUploadRequest; +import net.runelite.client.plugins.screenshot.imgur.ImageUploadResponse; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.ClientUI; +import net.runelite.client.ui.DrawManager; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.HotkeyListener; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.Text; +import net.runelite.http.api.RuneLiteAPI; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +@PluginDescriptor( + name = "Screenshot", + description = "Enable the manual and automatic taking of screenshots", + tags = {"external", "images", "imgur", "integration", "notifications"} +) +@Slf4j +public class ScreenshotPlugin extends Plugin +{ + private static final String IMGUR_CLIENT_ID = "30d71e5f6860809"; + private static final HttpUrl IMGUR_IMAGE_UPLOAD_URL = HttpUrl.parse("https://api.imgur.com/3/image"); + private static final MediaType JSON = MediaType.parse("application/json"); + + private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); + + private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)"); + private static final Pattern LEVEL_UP_PATTERN = Pattern.compile(".*Your ([a-zA-Z]+) (?:level is|are)? now (\\d+)\\."); + private static final Pattern BOSSKILL_MESSAGE_PATTERN = Pattern.compile("Your (.+) kill count is: (\\d+)."); + private static final Pattern VALUABLE_DROP_PATTERN = Pattern.compile(".*Valuable drop: ([^<>]+)(?:)?"); + private static final Pattern UNTRADEABLE_DROP_PATTERN = Pattern.compile(".*Untradeable drop: ([^<>]+)(?:)?"); + private static final Pattern DUEL_END_PATTERN = Pattern.compile("You have now (won|lost) ([0-9]+) duels?\\."); + private static final ImmutableList PET_MESSAGES = ImmutableList.of("You have a funny feeling like you're being followed", + "You feel something weird sneaking into your backpack", + "You have a funny feeling like you would have been followed"); + + static String format(Date date) + { + synchronized (TIME_FORMAT) + { + return TIME_FORMAT.format(date); + } + } + + private String clueType; + private Integer clueNumber; + + private Integer barrowsNumber; + + private Integer chambersOfXericNumber; + + private Integer chambersOfXericChallengeNumber; + + private Integer theatreOfBloodNumber; + + private boolean shouldTakeScreenshot; + + @Inject + private ScreenshotConfig config; + + @Inject + private OverlayManager overlayManager; + + @Inject + private ScreenshotOverlay screenshotOverlay; + + @Inject + private Notifier notifier; + + @Inject + private Client client; + + @Inject + private ClientUI clientUi; + + @Inject + private ClientToolbar clientToolbar; + + @Inject + private DrawManager drawManager; + + @Inject + private ScheduledExecutorService executor; + + @Inject + private KeyManager keyManager; + + @Inject + private SpriteManager spriteManager; + + @Getter(AccessLevel.PACKAGE) + private BufferedImage reportButton; + + private NavigationButton titleBarButton; + + private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.hotkey()) + { + @Override + public void hotkeyPressed() + { + takeScreenshot(format(new Date())); + } + }; + + @Provides + ScreenshotConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(ScreenshotConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(screenshotOverlay); + SCREENSHOT_DIR.mkdirs(); + keyManager.registerKeyListener(hotkeyListener); + + final BufferedImage iconImage = ImageUtil.getResourceStreamFromClass(getClass(), "screenshot.png"); + + titleBarButton = NavigationButton.builder() + .tab(false) + .tooltip("Take screenshot") + .icon(iconImage) + .onClick(() -> takeScreenshot(format(new Date()))) + .popup(ImmutableMap + .builder() + .put("Open screenshot folder...", () -> + { + try + { + Desktop.getDesktop().open(SCREENSHOT_DIR); + } + catch (IOException ex) + { + log.warn("Error opening screenshot dir", ex); + } + }) + .build()) + .build(); + + clientToolbar.addNavigation(titleBarButton); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(screenshotOverlay); + clientToolbar.removeNavigation(titleBarButton); + keyManager.unregisterKeyListener(hotkeyListener); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState() == GameState.LOGGED_IN + && reportButton == null) + { + reportButton = spriteManager.getSprite(SpriteID.CHATBOX_REPORT_BUTTON, 0); + } + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (!shouldTakeScreenshot) + { + return; + } + + shouldTakeScreenshot = false; + + String fileName = null; + if (client.getWidget(WidgetInfo.LEVEL_UP_LEVEL) != null) + { + fileName = parseLevelUpWidget(WidgetInfo.LEVEL_UP_LEVEL); + } + else if (client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT) != null) + { + fileName = parseLevelUpWidget(WidgetInfo.DIALOG_SPRITE_TEXT); + } + else if (client.getWidget(WidgetInfo.QUEST_COMPLETED_NAME_TEXT) != null) + { + // "You have completed The Corsair Curse!" + String text = client.getWidget(WidgetInfo.QUEST_COMPLETED_NAME_TEXT).getText(); + fileName = "Quest(" + text.substring(19, text.length() - 1) + ")"; + } + + if (fileName != null) + { + takeScreenshot(fileName); + } + } + + @Subscribe + public void onLocalPlayerDeath(LocalPlayerDeath death) + { + if (config.screenshotPlayerDeath()) + { + takeScreenshot("Death " + format(new Date())); + } + } + + @Subscribe + public void onPlayerLootReceived(final PlayerLootReceived playerLootReceived) + { + if (config.screenshotKills()) + { + final Player player = playerLootReceived.getPlayer(); + final String name = player.getName(); + String fileName = "Kill " + name + " " + format(new Date()); + takeScreenshot(fileName); + } + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (event.getType() != ChatMessageType.GAMEMESSAGE && event.getType() != ChatMessageType.SPAM && event.getType() != ChatMessageType.TRADE) + { + return; + } + + String chatMessage = event.getMessage(); + + if (chatMessage.contains("You have completed") && chatMessage.contains("Treasure")) + { + Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); + if (m.find()) + { + clueNumber = Integer.valueOf(m.group()); + clueType = chatMessage.substring(chatMessage.lastIndexOf(m.group()) + m.group().length() + 1, chatMessage.indexOf("Treasure") - 1); + return; + } + } + + if (chatMessage.startsWith("Your Barrows chest count is")) + { + Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); + if (m.find()) + { + barrowsNumber = Integer.valueOf(m.group()); + return; + } + } + + if (chatMessage.startsWith("Your completed Chambers of Xeric count is:")) + { + Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); + if (m.find()) + { + chambersOfXericNumber = Integer.valueOf(m.group()); + return; + } + } + + if (chatMessage.startsWith("Your completed Chambers of Xeric Challenge Mode count is:")) + { + Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); + if (m.find()) + { + chambersOfXericChallengeNumber = Integer.valueOf(m.group()); + return; + } + } + + if (chatMessage.startsWith("Your completed Theatre of Blood count is:")) + { + Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); + if (m.find()) + { + theatreOfBloodNumber = Integer.valueOf(m.group()); + return; + } + } + + if (config.screenshotPet() && PET_MESSAGES.stream().anyMatch(chatMessage::contains)) + { + String fileName = "Pet " + format(new Date()); + takeScreenshot(fileName); + } + + if (config.screenshotBossKills()) + { + Matcher m = BOSSKILL_MESSAGE_PATTERN.matcher(chatMessage); + if (m.matches()) + { + String bossName = m.group(1); + String bossKillcount = m.group(2); + String fileName = bossName + "(" + bossKillcount + ")"; + takeScreenshot(fileName); + } + } + + if (config.screenshotValuableDrop()) + { + Matcher m = VALUABLE_DROP_PATTERN.matcher(chatMessage); + if (m.matches()) + { + String valuableDropName = m.group(1); + String fileName = "Valuable drop " + valuableDropName + " " + format(new Date()); + takeScreenshot(fileName); + } + } + + if (config.screenshotUntradeableDrop()) + { + Matcher m = UNTRADEABLE_DROP_PATTERN.matcher(chatMessage); + if (m.matches()) + { + String untradeableDropName = m.group(1); + String fileName = "Untradeable drop " + untradeableDropName + " " + format(new Date()); + takeScreenshot(fileName); + } + } + + if (config.screenshotDuels()) + { + Matcher m = DUEL_END_PATTERN.matcher(chatMessage); + if (m.find()) + { + String result = m.group(1); + String count = m.group(2); + String fileName = "Duel " + result + " (" + count + ")"; + takeScreenshot(fileName); + } + } + } + + @Subscribe + public void onWidgetLoaded(WidgetLoaded event) + { + String fileName; + int groupId = event.getGroupId(); + + switch (groupId) + { + case QUEST_COMPLETED_GROUP_ID: + case CLUE_SCROLL_REWARD_GROUP_ID: + case CHAMBERS_OF_XERIC_REWARD_GROUP_ID: + case THEATRE_OF_BLOOD_REWARD_GROUP_ID: + case BARROWS_REWARD_GROUP_ID: + if (!config.screenshotRewards()) + { + return; + } + break; + case LEVEL_UP_GROUP_ID: + case DIALOG_SPRITE_GROUP_ID: + if (!config.screenshotLevels()) + { + return; + } + break; + case KINGDOM_GROUP_ID: + if (!config.screenshotKingdom()) + { + return; + } + break; + } + + switch (groupId) + { + case KINGDOM_GROUP_ID: + { + fileName = "Kingdom " + LocalDate.now(); + takeScreenshot(fileName); + break; + } + case CHAMBERS_OF_XERIC_REWARD_GROUP_ID: + { + if (chambersOfXericNumber != null) + { + fileName = "Chambers of Xeric(" + chambersOfXericNumber + ")"; + chambersOfXericNumber = null; + break; + } + else if (chambersOfXericChallengeNumber != null) + { + fileName = "Chambers of Xeric Challenge Mode(" + chambersOfXericChallengeNumber + ")"; + chambersOfXericChallengeNumber = null; + break; + } + else + { + return; + } + } + case THEATRE_OF_BLOOD_REWARD_GROUP_ID: + { + if (theatreOfBloodNumber == null) + { + return; + } + + fileName = "Theatre of Blood(" + theatreOfBloodNumber + ")"; + theatreOfBloodNumber = null; + break; + } + case BARROWS_REWARD_GROUP_ID: + { + if (barrowsNumber == null) + { + return; + } + + fileName = "Barrows(" + barrowsNumber + ")"; + barrowsNumber = null; + break; + } + case LEVEL_UP_GROUP_ID: + case DIALOG_SPRITE_GROUP_ID: + case QUEST_COMPLETED_GROUP_ID: + { + // level up widget gets loaded prior to the text being set, so wait until the next tick + shouldTakeScreenshot = true; + return; + } + case CLUE_SCROLL_REWARD_GROUP_ID: + { + if (clueType == null || clueNumber == null) + { + return; + } + + fileName = Character.toUpperCase(clueType.charAt(0)) + clueType.substring(1) + "(" + clueNumber + ")"; + clueType = null; + clueNumber = null; + break; + } + default: + return; + } + + takeScreenshot(fileName); + } + + /** + * Receives a WidgetInfo pointing to the middle widget of the level-up dialog, + * and parses it into a shortened string for filename usage. + * + * @param levelUpLevel WidgetInfo pointing to the required text widget, + * with the format "Your Skill (level is/are) now 99." + * @return Shortened string in the format "Skill(99)" + */ + String parseLevelUpWidget(WidgetInfo levelUpLevel) + { + Widget levelChild = client.getWidget(levelUpLevel); + if (levelChild == null) + { + return null; + } + + Matcher m = LEVEL_UP_PATTERN.matcher(levelChild.getText()); + if (!m.matches()) + { + return null; + } + + String skillName = m.group(1); + String skillLevel = m.group(2); + return skillName + "(" + skillLevel + ")"; + } + + /** + * Saves a screenshot of the client window to the screenshot folder as a PNG, + * and optionally uploads it to an image-hosting service. + * + * @param fileName Filename to use, without file extension. + */ + private void takeScreenshot(String fileName) + { + if (client.getGameState() == GameState.LOGIN_SCREEN) + { + // Prevent the screenshot from being captured + log.info("Login screenshot prevented"); + return; + } + + Consumer imageCallback = (img) -> + { + // This callback is on the game thread, move to executor thread + executor.submit(() -> takeScreenshot(fileName, img)); + }; + + if (config.displayDate()) + { + screenshotOverlay.queueForTimestamp(imageCallback); + } + else + { + drawManager.requestNextFrameListener(imageCallback); + } + } + + private void takeScreenshot(String fileName, Image image) + { + BufferedImage screenshot = config.includeFrame() + ? new BufferedImage(clientUi.getWidth(), clientUi.getHeight(), BufferedImage.TYPE_INT_ARGB) + : new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); + + Graphics graphics = screenshot.getGraphics(); + + int gameOffsetX = 0; + int gameOffsetY = 0; + + if (config.includeFrame()) + { + // Draw the client frame onto the screenshot + try + { + SwingUtilities.invokeAndWait(() -> clientUi.paint(graphics)); + } + catch (InterruptedException | InvocationTargetException e) + { + log.warn("unable to paint client UI on screenshot", e); + } + + // Evaluate the position of the game inside the frame + final Point canvasOffset = clientUi.getCanvasOffset(); + gameOffsetX = canvasOffset.getX(); + gameOffsetY = canvasOffset.getY(); + } + + // Draw the game onto the screenshot + graphics.drawImage(image, gameOffsetX, gameOffsetY, null); + + File playerFolder; + if (client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) + { + final EnumSet worldTypes = client.getWorldType(); + final boolean dmm = worldTypes.contains(WorldType.DEADMAN); + final boolean sdmm = worldTypes.contains(WorldType.SEASONAL_DEADMAN); + final boolean dmmt = worldTypes.contains(WorldType.DEADMAN_TOURNAMENT); + final boolean isDmmWorld = dmm || sdmm || dmmt; + + String playerDir = client.getLocalPlayer().getName(); + if (isDmmWorld) + { + playerDir += "-Deadman"; + } + playerFolder = new File(SCREENSHOT_DIR, playerDir); + } + else + { + playerFolder = SCREENSHOT_DIR; + } + + playerFolder.mkdirs(); + + try + { + File screenshotFile = new File(playerFolder, fileName + ".png"); + + ImageIO.write(screenshot, "PNG", screenshotFile); + + if (config.uploadScreenshot()) + { + uploadScreenshot(screenshotFile); + } + else if (config.notifyWhenTaken()) + { + notifier.notify("A screenshot was saved to " + screenshotFile, TrayIcon.MessageType.INFO); + } + } + catch (IOException ex) + { + log.warn("error writing screenshot", ex); + } + } + + /** + * Uploads a screenshot to the Imgur image-hosting service, + * and copies the image link to the clipboard. + * + * @param screenshotFile Image file to upload. + * @throws IOException Thrown if the file cannot be read. + */ + private void uploadScreenshot(File screenshotFile) throws IOException + { + String json = RuneLiteAPI.GSON.toJson(new ImageUploadRequest(screenshotFile)); + + Request request = new Request.Builder() + .url(IMGUR_IMAGE_UPLOAD_URL) + .addHeader("Authorization", "Client-ID " + IMGUR_CLIENT_ID) + .post(RequestBody.create(JSON, json)) + .build(); + + RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException ex) + { + log.warn("error uploading screenshot", ex); + } + + @Override + public void onResponse(Call call, Response response) throws IOException + { + try (InputStream in = response.body().byteStream()) + { + ImageUploadResponse imageUploadResponse = RuneLiteAPI.GSON + .fromJson(new InputStreamReader(in), ImageUploadResponse.class); + + if (imageUploadResponse.isSuccess()) + { + String link = imageUploadResponse.getData().getLink(); + + StringSelection selection = new StringSelection(link); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(selection, selection); + + if (config.notifyWhenTaken()) + { + notifier.notify("A screenshot was uploaded and inserted into your clipboard!", TrayIcon.MessageType.INFO); + } + } + } + } + }); + } + + @VisibleForTesting + int getClueNumber() + { + return clueNumber; + } + + @VisibleForTesting + String getClueType() + { + return clueType; + } + + @VisibleForTesting + int getBarrowsNumber() + { + return barrowsNumber; + } + + @VisibleForTesting + int getChambersOfXericNumber() + { + return chambersOfXericNumber; + } + + @VisibleForTesting + int getChambersOfXericChallengeNumber() + { + return chambersOfXericChallengeNumber; + } + + @VisibleForTesting + int gettheatreOfBloodNumber() + { + return theatreOfBloodNumber; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java index dfd21986ba..049dd866b7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2018, Plinko60 - * 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.shiftwalker; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("shiftwalkhere") -public interface ShiftWalkerConfig extends Config -{ - - @ConfigItem( - keyName = "shiftWalkEverything", - name = "Walk Under Everything", - description = "Enable this option when you do not want to interact with anything while Shift is pressed. " + - "If Walk Here is an option it will be the action taken." - ) - default boolean shiftWalkEverything() - { - return true; - } - - @ConfigItem( - keyName = "shiftWalkBoxTraps", - name = "Walk Under Box Traps", - description = "Press \"Shift\" to be able to walk under instead of picking up a Box Trap." - ) - default boolean shiftWalkBoxTraps() - { - return true; - } - - @ConfigItem( - keyName = "shiftWalkAttackOption", - name = "Walk Under Attack Options", - description = "Press \"Shift\" to be able to walk instead of attacking. Make sure Left Click Attack is on." - ) - default boolean shiftWalkAttackOption() - { - return true; - } - -} +/* + * Copyright (c) 2018, Plinko60 + * 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.shiftwalker; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("shiftwalkhere") +public interface ShiftWalkerConfig extends Config +{ + + @ConfigItem( + keyName = "shiftWalkEverything", + name = "Walk Under Everything", + description = "Enable this option when you do not want to interact with anything while Shift is pressed. " + + "If Walk Here is an option it will be the action taken." + ) + default boolean shiftWalkEverything() + { + return true; + } + + @ConfigItem( + keyName = "shiftWalkBoxTraps", + name = "Walk Under Box Traps", + description = "Press \"Shift\" to be able to walk under instead of picking up a Box Trap." + ) + default boolean shiftWalkBoxTraps() + { + return true; + } + + @ConfigItem( + keyName = "shiftWalkAttackOption", + name = "Walk Under Attack Options", + description = "Press \"Shift\" to be able to walk instead of attacking. Make sure Left Click Attack is on." + ) + default boolean shiftWalkAttackOption() + { + return true; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java index 677f30357d..9c1cb5b521 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java @@ -1,61 +1,60 @@ -/* - * Copyright (c) 2018, Plinko60 - * 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.shiftwalker; - -import net.runelite.client.input.KeyListener; - -import javax.inject.Inject; -import java.awt.event.KeyEvent; - -public class ShiftWalkerInputListener implements KeyListener -{ - - @Inject - private ShiftWalkerPlugin plugin; - - @Override - public void keyTyped(KeyEvent event) - { - - } - - @Override - public void keyPressed(KeyEvent event) - { - if (event.getKeyCode() == KeyEvent.VK_SHIFT) - { - plugin.setHotKeyPressed(true); - } - } - - @Override - public void keyReleased(KeyEvent event) - { - if (event.getKeyCode() == KeyEvent.VK_SHIFT) - { - plugin.setHotKeyPressed(false); - } - } -} +/* + * Copyright (c) 2018, Plinko60 + * 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.shiftwalker; + +import java.awt.event.KeyEvent; +import javax.inject.Inject; +import net.runelite.client.input.KeyListener; + +public class ShiftWalkerInputListener implements KeyListener +{ + + @Inject + private ShiftWalkerPlugin plugin; + + @Override + public void keyTyped(KeyEvent event) + { + + } + + @Override + public void keyPressed(KeyEvent event) + { + if (event.getKeyCode() == KeyEvent.VK_SHIFT) + { + plugin.setHotKeyPressed(true); + } + } + + @Override + public void keyReleased(KeyEvent event) + { + if (event.getKeyCode() == KeyEvent.VK_SHIFT) + { + plugin.setHotKeyPressed(false); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java index fde27f5faf..ca460e98a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java @@ -25,9 +25,13 @@ package net.runelite.client.plugins.shiftwalker; import com.google.inject.Provides; +import javax.inject.Inject; import lombok.Setter; -import net.runelite.api.*; -import net.runelite.api.events.*; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.MenuEntry; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.events.MenuEntryAdded; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyManager; @@ -36,8 +40,6 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.util.Text; -import javax.inject.Inject; - /** * Shift Walker Plugin. Credit to MenuEntrySwapperPlugin for code some code structure used here. */ @@ -46,7 +48,7 @@ import javax.inject.Inject; description = "Use Shift to toggle the Walk Here menu option. While pressed you will Walk rather than interact with objects.", tags = {"npcs", "items", "objects"}, enabledByDefault = false, - type = PluginType.UTILITY + type = PluginType.UTILITY ) public class ShiftWalkerPlugin extends Plugin { @@ -101,6 +103,7 @@ public class ShiftWalkerPlugin extends Plugin /** * Event when a new menu entry was added. + * * @param event {@link MenuEntryAdded}. */ @Subscribe @@ -127,7 +130,7 @@ public class ShiftWalkerPlugin extends Plugin stripEntries(); } else if (config.shiftWalkBoxTraps() && ShiftWalkerGroups.BOX_TRAP_TARGETS.contains(target) - && ShiftWalkerGroups.BOX_TRAP_KEYWORDS.contains(pOptionToReplace)) + && ShiftWalkerGroups.BOX_TRAP_KEYWORDS.contains(pOptionToReplace)) { //swap(pOptionToReplace); //Swap only on box traps stripEntries(); @@ -143,16 +146,19 @@ public class ShiftWalkerPlugin extends Plugin * Strip everything except "Walk here" * Other way was unconventional because if there was multiple targets in the menu entry it wouldn't swap correctly */ - private void stripEntries() { + private void stripEntries() + { MenuEntry walkkHereEntry = null; - for (MenuEntry entry : client.getMenuEntries()) { + for (MenuEntry entry : client.getMenuEntries()) + { if ("Walk here".equals(entry.getOption())) { walkkHereEntry = entry; } } - if (walkkHereEntry != null) { + if (walkkHereEntry != null) + { MenuEntry[] newEntries = new MenuEntry[1]; newEntries[0] = walkkHereEntry; client.setMenuEntries(newEntries); @@ -161,6 +167,7 @@ public class ShiftWalkerPlugin extends Plugin /** * Swaps menu entries if the entries could be found. This places Walk Here where the top level menu option was. + * * @param pOptionToReplace The String containing the Menu Option that needs to be replaced. IE: "Attack", "Chop Down". */ private void swap(String pOptionToReplace) // Swap isn't currently used, and I don't know what's going on here so leaving for now @@ -183,7 +190,8 @@ public class ShiftWalkerPlugin extends Plugin /** * Finds the index of the menu that contains the verbiage we are looking for. - * @param pMenuEntries The list of {@link MenuEntry}s. + * + * @param pMenuEntries The list of {@link MenuEntry}s. * @param pMenuEntryToSearchFor The Option in the menu to search for. * @return The index location or null if it was not found. */ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/BankedCalculator.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/BankedCalculator.java index a0f0da78a5..790890bf39 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/BankedCalculator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/BankedCalculator.java @@ -1,666 +1,675 @@ -/* - * 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.plugins.skillcalculator; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.Experience; -import net.runelite.api.Skill; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.skillcalculator.banked.CriticalItem; -import net.runelite.client.plugins.skillcalculator.banked.beans.Activity; -import net.runelite.client.plugins.skillcalculator.banked.beans.SecondaryItem; -import net.runelite.client.plugins.skillcalculator.banked.ui.CriticalItemPanel; -import net.runelite.client.plugins.skillcalculator.beans.SkillDataBonus; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.DynamicGridLayout; -import net.runelite.client.ui.FontManager; - -@Slf4j -public class BankedCalculator extends JPanel -{ - private static final DecimalFormat XP_FORMAT_COMMA = new DecimalFormat("#,###.#"); - - private final SkillCalculatorPanel parent; - private final Client client; - private final UICalculatorInputArea uiInput; - private final SkillCalculatorConfig config; - private final ItemManager itemManager; - - private final CacheSkillData skillData = new CacheSkillData(); - private final List bonusCheckBoxes = new ArrayList<>(); - - // UI Input data - private float xpFactor = 1.0f; - private CalculatorType currentCalc; - private Skill currentSkill; - - private double totalBankedXp = 0.0f; - private JLabel totalLabel = new JLabel(); - private JPanel detailConfigContainer; - private JPanel detailContainer; - - // Banked Experience magic - private Map bankMap = new HashMap<>(); - private Map categoryMap = new HashMap<>(); // Check if CriticalItem Category is enabled - private Map panelMap = new HashMap<>(); - private Map criticalMap = new HashMap<>(); // Quantity of CriticalItem inside bankMap - private Map activityMap = new HashMap<>(); // Selected Activity used for calculating xp - private Map linkedMap = new HashMap<>(); // ItemID of item that links to the CriticalItem - - BankedCalculator( - SkillCalculatorPanel parent, - Client client, - UICalculatorInputArea uiInput, - SkillCalculatorConfig config, - ItemManager itemManager) - { - this.parent = parent; - this.client = client; - this.uiInput = uiInput; - this.config = config; - this.itemManager = itemManager; - - setLayout(new DynamicGridLayout(0, 1, 0, 5)); - - detailContainer = new JPanel(); - detailContainer.setLayout(new BoxLayout(detailContainer, BoxLayout.Y_AXIS)); - - detailConfigContainer = new JPanel(); - detailConfigContainer.setLayout(new BoxLayout(detailConfigContainer, BoxLayout.Y_AXIS)); - } - - private void reset() - { - criticalMap.clear(); - linkedMap.clear(); - xpFactor = 1f; - } - - /** - * Update target Xp and Level inputs to match current Xp + total banked XP - */ - private void syncInputFields() - { - // Update Target XP & Level to include total banked xp - int newTotal = (int) (uiInput.getCurrentXPInput() + totalBankedXp); - uiInput.setTargetXPInput(newTotal); - uiInput.setTargetLevelInput(Experience.getLevelForXp(newTotal)); - } - - /* - * Banked Experience Logic - */ - - /** - * Shows the Banked Xp tab for the CalculatorType - * @param calculatorType Selected Calculator Type - */ - void openBanked(CalculatorType calculatorType) - { - // clean slate for creating the required panel - removeAll(); - reset(); - if (calculatorType.getSkill() != currentSkill) - { - // Only clear Category and Activity map on skill change. - activityMap.clear(); - categoryMap.clear(); - } - currentCalc = calculatorType; - currentSkill = calculatorType.getSkill(); - bankMap = parent.getBankMap(); - - uiInput.setCurrentLevelInput(client.getRealSkillLevel(currentSkill)); - uiInput.setCurrentXPInput(client.getSkillExperience(currentSkill)); - - // Only adds Banked Experience portion if enabled for this SkillCalc and have seen their bank - if (!calculatorType.isBankedXpFlag()) - { - add(new JLabel("

Banked Experience is not enabled for this skill.
", JLabel.CENTER)); - } - else if (bankMap.size() <= 0) - { - add(new JLabel( "Please visit a bank!", JLabel.CENTER)); - } - else - { - // Prevent editing of the target level/exp since we automagically adjust them - uiInput.getUiFieldTargetLevel().setEditable(false); - uiInput.getUiFieldTargetXP().setEditable(false); - - // Now we can actually show the Banked Experience Panel - // Adds Config Options for this panel - renderBankedXpOptions(); - - renderBonusXpOptions(); - - // sprite 202 - calculatedBankedMaps(); - - // Calculate total banked experience and create detail container - refreshDetailContainer(); - - // Add back all necessary content - add(detailConfigContainer); - add(totalLabel); - add(detailContainer); - } - - revalidate(); - repaint(); - - // Update the input fields. - syncInputFields(); - } - - /** - * Add the config options for toggling each Item Category - */ - private void renderBankedXpOptions() - { - Set categories = CriticalItem.getSkillCategories(currentSkill); - if (categories == null) - { - return; - } - - add(new JLabel("Configs:")); - - for (String category : categories) - { - JPanel uiOption = new JPanel(new BorderLayout()); - JLabel uiLabel = new JLabel(category); - JCheckBox uiCheckbox = new JCheckBox(); - - uiLabel.setForeground(Color.WHITE); - uiLabel.setFont(FontManager.getRunescapeSmallFont()); - - uiOption.setBorder(BorderFactory.createEmptyBorder(3, 7, 3, 0)); - uiOption.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - // Everything is enabled by default - uiCheckbox.setSelected(true); - categoryMap.put(category, true); - - // Adjust Total Banked XP check-state of the box. - uiCheckbox.addActionListener(e -> toggleCategory(category, uiCheckbox.isSelected())); - uiCheckbox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR); - - uiOption.add(uiLabel, BorderLayout.WEST); - uiOption.add(uiCheckbox, BorderLayout.EAST); - - add(uiOption); - add(Box.createRigidArea(new Dimension(0, 5))); - } - } - - /** - * Used to toggle Categories of Items inside the Banked Xp tab - * @param category Category Name - * @param enabled is enabled - */ - private void toggleCategory(String category, boolean enabled) - { - categoryMap.put(category, enabled); - refreshDetailContainer(); - } - - - /** - * Creates the Maps used for easy access when calculating Banked Xp - */ - private void calculatedBankedMaps() - { - // Grab all CriticalItems for this skill - ArrayList items = CriticalItem.getBySkillName(currentSkill); - - // Loop over all Critical Items for this skill and determine how many are in the bank - for (CriticalItem item : items) - { - Integer qty = bankMap.get(item.getItemID()); - if (qty != null && qty > 0) - { - if (criticalMap.containsKey(item)) - { - criticalMap.put(item, criticalMap.get(item) + qty); - } - else - { - criticalMap.put(item, qty); - } - - // Ensure the item this is linked to maps back to us. - if (item.getLinkedItemId() != -1) - { - CriticalItem i = CriticalItem.getByItemId(item.getLinkedItemId()); - if (i != null) - { - linkedMap.put(i, item.getItemID()); - } - } - } - } - } - - /** - * Populates the detailContainer with the necessary CriticalItemPanels - */ - private void refreshDetailContainer() - { - detailContainer.removeAll(); - panelMap.clear(); - - Map map = getBankedXpBreakdown(); - for (Map.Entry entry : map.entrySet()) - { - CriticalItem item = entry.getKey(); - createItemPanel(item); - } - - detailContainer.revalidate(); - detailContainer.repaint(); - - calculateBankedXpTotal(); - } - - /** - * Creates an Individual Item Panel if it should be displayed - * @param item CriticalItem this information is tied too - */ - private void createItemPanel(CriticalItem item) - { - // Category Included? - if (categoryMap.get(item.getCategory())) - { - // Get possible activities limited to current level - List activities = Activity.getByCriticalItem(item, uiInput.getCurrentLevelInput()); - - // Check if this should count as another item. - if (item.getLinkedItemId() != -1) - { - // Ensure the linked item panel is created even if there are none in bank. - CriticalItem linked = CriticalItem.getByItemId(item.getLinkedItemId()); - if (!criticalMap.containsKey(linked)) - { - createItemPanel(linked); - } - - // One activity and rewards no xp ignore. - if (activities.size() == 1) - { - if (activities.get(0).getXp() <= 0) - { - return; - } - } - } - - // If it doesn't have any activities ignore it in the breakdown. - if (activities.size() <= 0) - { - return; - } - // Either this item has multiple activities or the single activity rewards xp, create the item panel. - - // Determine xp rate for this item - Activity a = getSelectedActivity(item); - double activityXp = a == null ? 0 : a.getXp(); - double xp = activityXp * (item.isIgnoreBonus() ? 1.0f : xpFactor); - int amount = 0; - - // If it has linked items figure out the working total. - Map links = getLinkedTotalMap(item); - for (Integer num : links.values()) - { - amount += num; - } - - // Actually create the panel displaying banked experience for this item - CriticalItemPanel panel = new CriticalItemPanel(this, itemManager, item, xp, amount, links); - - // Limit to Banked Secondaries - if (config.limitedBankedSecondaries() && a != null) - { - panel.updateAmount(limitToActivitySecondaries(a, amount), true); - panel.recalculate(); - } - panelMap.put(item, panel); - detailContainer.add(panel); - } - - } - - /** - * Return the Activity the player selected for this Item. Defaults to First activity - * @param i CriticalItem to check for - * @return selected Activity - */ - public Activity getSelectedActivity(CriticalItem i) - { - // Pull from memory if available - Activity a = activityMap.get(i); - if (a != null) - { - return a; - } - - // If not in memory select the first Activity and add to memory - List activities = Activity.getByCriticalItem(i); - if (activities.size() == 0) - { - // If you can't find an activity it means this item must link to one and give 0 xp - return null; - } - - Activity selected = activities.get(0); - activityMap.put(i, selected); - return selected; - } - - /** - * Creates a Map of Item ID and QTY for this Skill by Category. Keeps order for better UI display - * @return Map of Item ID and QTY for this Skill by Category - */ - private Map getBankedXpBreakdown() - { - Map map = new LinkedHashMap<>(); - - for (String category : CriticalItem.getSkillCategories(currentSkill)) - { - ArrayList items = CriticalItem.getItemsForSkillCategories(currentSkill, category); - for (CriticalItem item : items) - { - Integer amount = bankMap.get(item.getItemID()); - if (amount != null && amount > 0) - { - map.put(item, amount); - } - } - } - - return map; - } - - /** - * Used to select an Activity for an item - * @param i CriticalItem - * @param a Activity selected - */ - public void activitySelected(CriticalItem i, Activity a) - { - // This is triggered on every click so don't update if activity didn't actually change - Activity cur = activityMap.get(i); - if (cur == a) - { - return; - } - - // Update selected activity in map - activityMap.put(i, a); - - // If had a previous selection and this item links to another check for item prevention change. - // If there are changes adjust the Linked panel quantity as well - if (cur != null && i.getLinkedItemId() != -1) - { - if (cur.isPreventLinked() != a.isPreventLinked()) - { - CriticalItem linked = CriticalItem.getByItemId(i.getLinkedItemId()); - CriticalItemPanel l = panelMap.get(linked); - if (l != null) - { - l.updateLinkedMap(getLinkedTotalMap(linked)); - int amount = config.limitedBankedSecondaries() ? limitToActivitySecondaries(a, l.getAmount()) : l.getAmount(); - l.updateAmount(amount, false); - l.recalculate(); - } - } - } - - // Total banked experience - CriticalItemPanel p = panelMap.get(i); - if (p != null) - { - p.updateLinkedMap(getLinkedTotalMap(i)); - int amount = config.limitedBankedSecondaries() ? limitToActivitySecondaries(a, p.getAmount()) : p.getAmount(); - p.updateAmount(amount, true); - p.updateXp(a.getXp() * (i.isIgnoreBonus() ? 1.0f : xpFactor)); - } - - // Update total banked xp value based on updated panels - calculateBankedXpTotal(); - } - - private Map getLinkedTotalMap(CriticalItem i) - { - return getLinkedTotalMap(i, true); - } - - /** - * Creates a Map of CriticalItem and Qty for all items that link to the passed CriticalItem - * @param i CriticalItem to base Map off of - * @param first Since this is called recursively we want to ensure the original CriticalItem is always added - * @return Map of Linked CriticalItems and their Qty - */ - private Map getLinkedTotalMap(CriticalItem i, boolean first) - { - Map map = new LinkedHashMap<>(); - if (!categoryMap.get(i.getCategory())) - { - return map; - } - - // This item has an activity selected and its preventing linked functionality? - Activity selected = activityMap.get(i); - if (selected != null && selected.isPreventLinked()) - { - // If initial request is for this item - if (!first) - { - return map; - } - } - - // Add self to map - int amount = criticalMap.getOrDefault(i, 0); - if (amount > 0) - { - map.put(i, amount); - } - - // This item doesn't link to anything, all done. - if (linkedMap.get(i) == null) - { - return map; - } - - CriticalItem item = CriticalItem.getByItemId(linkedMap.get(i)); - if (item == null) - { - log.warn("Error finding Critical Item for Item ID: {}", linkedMap.get(i)); - return map; - } - - map.putAll(getLinkedTotalMap(item, false)); - - return map; - } - - /** - * SkillCalculatorPlugin sends the Bank Map when the bank contents change - * @param map Map of Item IDs and Quantity - */ - void updateBankMap(Map map) - { - boolean oldMapFlag = (bankMap.size() <= 0); - bankMap = map; - // Refresh entire panel if old map was empty - if (oldMapFlag) - { - CalculatorType calc = CalculatorType.getBySkill(currentSkill); - SwingUtilities.invokeLater(() -> openBanked(calc)); - return; - } - - // recalculate all data related to banked experience except for activity selections - criticalMap.clear(); - linkedMap.clear(); - calculatedBankedMaps(); - - // Update the Total XP banked and the details panel - SwingUtilities.invokeLater(this::refreshDetailContainer); - } - - /** - * Loops over all ItemPanels too sum their total xp and updates the label with the new value - */ - private void calculateBankedXpTotal() - { - double total = 0.0; - for (CriticalItemPanel p : panelMap.values()) - { - total += p.getTotal(); - } - - totalBankedXp = total; - - syncBankedXp(); - } - - /** - * Used to update the UI to reflect the new Banked XP amount - */ - private void syncBankedXp() - { - totalLabel.setText("Total Banked xp: " + XP_FORMAT_COMMA.format(totalBankedXp)); - - syncInputFields(); - - revalidate(); - repaint(); - } - - /** - * Check Bank for Activity Secondaries and Limits to possible Activity amounts - * @param a Selected Activity - * @param possible Amount of Critical Item available - * @return possible Limited to Banked Secondaries - */ - private int limitToActivitySecondaries(Activity a, int possible) - { - for (SecondaryItem i : a.getSecondaries()) - { - int banked = bankMap.getOrDefault(i.getId(), 0); - int newPossible = banked / i.getQty(); - possible = newPossible < possible ? newPossible : possible; - } - - return possible; - } - - /** - * Renders the Xp Modifier options - */ - - private void renderBonusXpOptions() - { - SkillDataBonus[] bonuses = skillData.getSkillData(currentCalc.getDataFile()).getBonuses(); - if (bonuses != null) - { - add(new JLabel("Bonus Experience:")); - for (SkillDataBonus bonus : bonuses) - { - JPanel checkboxPanel = buildCheckboxPanel(bonus); - - add(checkboxPanel); - add(Box.createRigidArea(new Dimension(0, 5))); - } - } - } - - private JPanel buildCheckboxPanel(SkillDataBonus bonus) - { - JPanel uiOption = new JPanel(new BorderLayout()); - JLabel uiLabel = new JLabel(bonus.getName()); - JCheckBox uiCheckbox = new JCheckBox(); - - uiLabel.setForeground(Color.WHITE); - uiLabel.setFont(FontManager.getRunescapeSmallFont()); - - uiOption.setBorder(BorderFactory.createEmptyBorder(3, 7, 3, 0)); - uiOption.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - // Adjust XP bonus depending on check-state of the boxes. - uiCheckbox.addActionListener(event -> adjustCheckboxes(uiCheckbox, bonus)); - - uiCheckbox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR); - - uiOption.add(uiLabel, BorderLayout.WEST); - uiOption.add(uiCheckbox, BorderLayout.EAST); - bonusCheckBoxes.add(uiCheckbox); - - return uiOption; - } - - private void adjustCheckboxes(JCheckBox target, SkillDataBonus bonus) - { - adjustXPBonus(0); - bonusCheckBoxes.forEach(otherSelectedCheckbox -> - { - if (otherSelectedCheckbox != target) - { - otherSelectedCheckbox.setSelected(false); - } - }); - - if (target.isSelected()) - { - adjustXPBonus(bonus.getValue()); - } - } - - private void adjustXPBonus(float value) - { - xpFactor = 1f + value; - refreshDetailContainer(); - } +/* + * 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.plugins.skillcalculator; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.Experience; +import net.runelite.api.Skill; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.skillcalculator.banked.CriticalItem; +import net.runelite.client.plugins.skillcalculator.banked.beans.Activity; +import net.runelite.client.plugins.skillcalculator.banked.beans.SecondaryItem; +import net.runelite.client.plugins.skillcalculator.banked.ui.CriticalItemPanel; +import net.runelite.client.plugins.skillcalculator.beans.SkillDataBonus; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.DynamicGridLayout; +import net.runelite.client.ui.FontManager; + +@Slf4j +public class BankedCalculator extends JPanel +{ + private static final DecimalFormat XP_FORMAT_COMMA = new DecimalFormat("#,###.#"); + + private final SkillCalculatorPanel parent; + private final Client client; + private final UICalculatorInputArea uiInput; + private final SkillCalculatorConfig config; + private final ItemManager itemManager; + + private final CacheSkillData skillData = new CacheSkillData(); + private final List bonusCheckBoxes = new ArrayList<>(); + + // UI Input data + private float xpFactor = 1.0f; + private CalculatorType currentCalc; + private Skill currentSkill; + + private double totalBankedXp = 0.0f; + private JLabel totalLabel = new JLabel(); + private JPanel detailConfigContainer; + private JPanel detailContainer; + + // Banked Experience magic + private Map bankMap = new HashMap<>(); + private Map categoryMap = new HashMap<>(); // Check if CriticalItem Category is enabled + private Map panelMap = new HashMap<>(); + private Map criticalMap = new HashMap<>(); // Quantity of CriticalItem inside bankMap + private Map activityMap = new HashMap<>(); // Selected Activity used for calculating xp + private Map linkedMap = new HashMap<>(); // ItemID of item that links to the CriticalItem + + BankedCalculator( + SkillCalculatorPanel parent, + Client client, + UICalculatorInputArea uiInput, + SkillCalculatorConfig config, + ItemManager itemManager) + { + this.parent = parent; + this.client = client; + this.uiInput = uiInput; + this.config = config; + this.itemManager = itemManager; + + setLayout(new DynamicGridLayout(0, 1, 0, 5)); + + detailContainer = new JPanel(); + detailContainer.setLayout(new BoxLayout(detailContainer, BoxLayout.Y_AXIS)); + + detailConfigContainer = new JPanel(); + detailConfigContainer.setLayout(new BoxLayout(detailConfigContainer, BoxLayout.Y_AXIS)); + } + + private void reset() + { + criticalMap.clear(); + linkedMap.clear(); + xpFactor = 1f; + } + + /** + * Update target Xp and Level inputs to match current Xp + total banked XP + */ + private void syncInputFields() + { + // Update Target XP & Level to include total banked xp + int newTotal = (int) (uiInput.getCurrentXPInput() + totalBankedXp); + uiInput.setTargetXPInput(newTotal); + uiInput.setTargetLevelInput(Experience.getLevelForXp(newTotal)); + } + + /* + * Banked Experience Logic + */ + + /** + * Shows the Banked Xp tab for the CalculatorType + * + * @param calculatorType Selected Calculator Type + */ + void openBanked(CalculatorType calculatorType) + { + // clean slate for creating the required panel + removeAll(); + reset(); + if (calculatorType.getSkill() != currentSkill) + { + // Only clear Category and Activity map on skill change. + activityMap.clear(); + categoryMap.clear(); + } + currentCalc = calculatorType; + currentSkill = calculatorType.getSkill(); + bankMap = parent.getBankMap(); + + uiInput.setCurrentLevelInput(client.getRealSkillLevel(currentSkill)); + uiInput.setCurrentXPInput(client.getSkillExperience(currentSkill)); + + // Only adds Banked Experience portion if enabled for this SkillCalc and have seen their bank + if (!calculatorType.isBankedXpFlag()) + { + add(new JLabel("
Banked Experience is not enabled for this skill.
", JLabel.CENTER)); + } + else if (bankMap.size() <= 0) + { + add(new JLabel("Please visit a bank!", JLabel.CENTER)); + } + else + { + // Prevent editing of the target level/exp since we automagically adjust them + uiInput.getUiFieldTargetLevel().setEditable(false); + uiInput.getUiFieldTargetXP().setEditable(false); + + // Now we can actually show the Banked Experience Panel + // Adds Config Options for this panel + renderBankedXpOptions(); + + renderBonusXpOptions(); + + // sprite 202 + calculatedBankedMaps(); + + // Calculate total banked experience and create detail container + refreshDetailContainer(); + + // Add back all necessary content + add(detailConfigContainer); + add(totalLabel); + add(detailContainer); + } + + revalidate(); + repaint(); + + // Update the input fields. + syncInputFields(); + } + + /** + * Add the config options for toggling each Item Category + */ + private void renderBankedXpOptions() + { + Set categories = CriticalItem.getSkillCategories(currentSkill); + if (categories == null) + { + return; + } + + add(new JLabel("Configs:")); + + for (String category : categories) + { + JPanel uiOption = new JPanel(new BorderLayout()); + JLabel uiLabel = new JLabel(category); + JCheckBox uiCheckbox = new JCheckBox(); + + uiLabel.setForeground(Color.WHITE); + uiLabel.setFont(FontManager.getRunescapeSmallFont()); + + uiOption.setBorder(BorderFactory.createEmptyBorder(3, 7, 3, 0)); + uiOption.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + // Everything is enabled by default + uiCheckbox.setSelected(true); + categoryMap.put(category, true); + + // Adjust Total Banked XP check-state of the box. + uiCheckbox.addActionListener(e -> toggleCategory(category, uiCheckbox.isSelected())); + uiCheckbox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR); + + uiOption.add(uiLabel, BorderLayout.WEST); + uiOption.add(uiCheckbox, BorderLayout.EAST); + + add(uiOption); + add(Box.createRigidArea(new Dimension(0, 5))); + } + } + + /** + * Used to toggle Categories of Items inside the Banked Xp tab + * + * @param category Category Name + * @param enabled is enabled + */ + private void toggleCategory(String category, boolean enabled) + { + categoryMap.put(category, enabled); + refreshDetailContainer(); + } + + + /** + * Creates the Maps used for easy access when calculating Banked Xp + */ + private void calculatedBankedMaps() + { + // Grab all CriticalItems for this skill + ArrayList items = CriticalItem.getBySkillName(currentSkill); + + // Loop over all Critical Items for this skill and determine how many are in the bank + for (CriticalItem item : items) + { + Integer qty = bankMap.get(item.getItemID()); + if (qty != null && qty > 0) + { + if (criticalMap.containsKey(item)) + { + criticalMap.put(item, criticalMap.get(item) + qty); + } + else + { + criticalMap.put(item, qty); + } + + // Ensure the item this is linked to maps back to us. + if (item.getLinkedItemId() != -1) + { + CriticalItem i = CriticalItem.getByItemId(item.getLinkedItemId()); + if (i != null) + { + linkedMap.put(i, item.getItemID()); + } + } + } + } + } + + /** + * Populates the detailContainer with the necessary CriticalItemPanels + */ + private void refreshDetailContainer() + { + detailContainer.removeAll(); + panelMap.clear(); + + Map map = getBankedXpBreakdown(); + for (Map.Entry entry : map.entrySet()) + { + CriticalItem item = entry.getKey(); + createItemPanel(item); + } + + detailContainer.revalidate(); + detailContainer.repaint(); + + calculateBankedXpTotal(); + } + + /** + * Creates an Individual Item Panel if it should be displayed + * + * @param item CriticalItem this information is tied too + */ + private void createItemPanel(CriticalItem item) + { + // Category Included? + if (categoryMap.get(item.getCategory())) + { + // Get possible activities limited to current level + List activities = Activity.getByCriticalItem(item, uiInput.getCurrentLevelInput()); + + // Check if this should count as another item. + if (item.getLinkedItemId() != -1) + { + // Ensure the linked item panel is created even if there are none in bank. + CriticalItem linked = CriticalItem.getByItemId(item.getLinkedItemId()); + if (!criticalMap.containsKey(linked)) + { + createItemPanel(linked); + } + + // One activity and rewards no xp ignore. + if (activities.size() == 1) + { + if (activities.get(0).getXp() <= 0) + { + return; + } + } + } + + // If it doesn't have any activities ignore it in the breakdown. + if (activities.size() <= 0) + { + return; + } + // Either this item has multiple activities or the single activity rewards xp, create the item panel. + + // Determine xp rate for this item + Activity a = getSelectedActivity(item); + double activityXp = a == null ? 0 : a.getXp(); + double xp = activityXp * (item.isIgnoreBonus() ? 1.0f : xpFactor); + int amount = 0; + + // If it has linked items figure out the working total. + Map links = getLinkedTotalMap(item); + for (Integer num : links.values()) + { + amount += num; + } + + // Actually create the panel displaying banked experience for this item + CriticalItemPanel panel = new CriticalItemPanel(this, itemManager, item, xp, amount, links); + + // Limit to Banked Secondaries + if (config.limitedBankedSecondaries() && a != null) + { + panel.updateAmount(limitToActivitySecondaries(a, amount), true); + panel.recalculate(); + } + panelMap.put(item, panel); + detailContainer.add(panel); + } + + } + + /** + * Return the Activity the player selected for this Item. Defaults to First activity + * + * @param i CriticalItem to check for + * @return selected Activity + */ + public Activity getSelectedActivity(CriticalItem i) + { + // Pull from memory if available + Activity a = activityMap.get(i); + if (a != null) + { + return a; + } + + // If not in memory select the first Activity and add to memory + List activities = Activity.getByCriticalItem(i); + if (activities.size() == 0) + { + // If you can't find an activity it means this item must link to one and give 0 xp + return null; + } + + Activity selected = activities.get(0); + activityMap.put(i, selected); + return selected; + } + + /** + * Creates a Map of Item ID and QTY for this Skill by Category. Keeps order for better UI display + * + * @return Map of Item ID and QTY for this Skill by Category + */ + private Map getBankedXpBreakdown() + { + Map map = new LinkedHashMap<>(); + + for (String category : CriticalItem.getSkillCategories(currentSkill)) + { + ArrayList items = CriticalItem.getItemsForSkillCategories(currentSkill, category); + for (CriticalItem item : items) + { + Integer amount = bankMap.get(item.getItemID()); + if (amount != null && amount > 0) + { + map.put(item, amount); + } + } + } + + return map; + } + + /** + * Used to select an Activity for an item + * + * @param i CriticalItem + * @param a Activity selected + */ + public void activitySelected(CriticalItem i, Activity a) + { + // This is triggered on every click so don't update if activity didn't actually change + Activity cur = activityMap.get(i); + if (cur == a) + { + return; + } + + // Update selected activity in map + activityMap.put(i, a); + + // If had a previous selection and this item links to another check for item prevention change. + // If there are changes adjust the Linked panel quantity as well + if (cur != null && i.getLinkedItemId() != -1) + { + if (cur.isPreventLinked() != a.isPreventLinked()) + { + CriticalItem linked = CriticalItem.getByItemId(i.getLinkedItemId()); + CriticalItemPanel l = panelMap.get(linked); + if (l != null) + { + l.updateLinkedMap(getLinkedTotalMap(linked)); + int amount = config.limitedBankedSecondaries() ? limitToActivitySecondaries(a, l.getAmount()) : l.getAmount(); + l.updateAmount(amount, false); + l.recalculate(); + } + } + } + + // Total banked experience + CriticalItemPanel p = panelMap.get(i); + if (p != null) + { + p.updateLinkedMap(getLinkedTotalMap(i)); + int amount = config.limitedBankedSecondaries() ? limitToActivitySecondaries(a, p.getAmount()) : p.getAmount(); + p.updateAmount(amount, true); + p.updateXp(a.getXp() * (i.isIgnoreBonus() ? 1.0f : xpFactor)); + } + + // Update total banked xp value based on updated panels + calculateBankedXpTotal(); + } + + private Map getLinkedTotalMap(CriticalItem i) + { + return getLinkedTotalMap(i, true); + } + + /** + * Creates a Map of CriticalItem and Qty for all items that link to the passed CriticalItem + * + * @param i CriticalItem to base Map off of + * @param first Since this is called recursively we want to ensure the original CriticalItem is always added + * @return Map of Linked CriticalItems and their Qty + */ + private Map getLinkedTotalMap(CriticalItem i, boolean first) + { + Map map = new LinkedHashMap<>(); + if (!categoryMap.get(i.getCategory())) + { + return map; + } + + // This item has an activity selected and its preventing linked functionality? + Activity selected = activityMap.get(i); + if (selected != null && selected.isPreventLinked()) + { + // If initial request is for this item + if (!first) + { + return map; + } + } + + // Add self to map + int amount = criticalMap.getOrDefault(i, 0); + if (amount > 0) + { + map.put(i, amount); + } + + // This item doesn't link to anything, all done. + if (linkedMap.get(i) == null) + { + return map; + } + + CriticalItem item = CriticalItem.getByItemId(linkedMap.get(i)); + if (item == null) + { + log.warn("Error finding Critical Item for Item ID: {}", linkedMap.get(i)); + return map; + } + + map.putAll(getLinkedTotalMap(item, false)); + + return map; + } + + /** + * SkillCalculatorPlugin sends the Bank Map when the bank contents change + * + * @param map Map of Item IDs and Quantity + */ + void updateBankMap(Map map) + { + boolean oldMapFlag = (bankMap.size() <= 0); + bankMap = map; + // Refresh entire panel if old map was empty + if (oldMapFlag) + { + CalculatorType calc = CalculatorType.getBySkill(currentSkill); + SwingUtilities.invokeLater(() -> openBanked(calc)); + return; + } + + // recalculate all data related to banked experience except for activity selections + criticalMap.clear(); + linkedMap.clear(); + calculatedBankedMaps(); + + // Update the Total XP banked and the details panel + SwingUtilities.invokeLater(this::refreshDetailContainer); + } + + /** + * Loops over all ItemPanels too sum their total xp and updates the label with the new value + */ + private void calculateBankedXpTotal() + { + double total = 0.0; + for (CriticalItemPanel p : panelMap.values()) + { + total += p.getTotal(); + } + + totalBankedXp = total; + + syncBankedXp(); + } + + /** + * Used to update the UI to reflect the new Banked XP amount + */ + private void syncBankedXp() + { + totalLabel.setText("Total Banked xp: " + XP_FORMAT_COMMA.format(totalBankedXp)); + + syncInputFields(); + + revalidate(); + repaint(); + } + + /** + * Check Bank for Activity Secondaries and Limits to possible Activity amounts + * + * @param a Selected Activity + * @param possible Amount of Critical Item available + * @return possible Limited to Banked Secondaries + */ + private int limitToActivitySecondaries(Activity a, int possible) + { + for (SecondaryItem i : a.getSecondaries()) + { + int banked = bankMap.getOrDefault(i.getId(), 0); + int newPossible = banked / i.getQty(); + possible = newPossible < possible ? newPossible : possible; + } + + return possible; + } + + /** + * Renders the Xp Modifier options + */ + + private void renderBonusXpOptions() + { + SkillDataBonus[] bonuses = skillData.getSkillData(currentCalc.getDataFile()).getBonuses(); + if (bonuses != null) + { + add(new JLabel("Bonus Experience:")); + for (SkillDataBonus bonus : bonuses) + { + JPanel checkboxPanel = buildCheckboxPanel(bonus); + + add(checkboxPanel); + add(Box.createRigidArea(new Dimension(0, 5))); + } + } + } + + private JPanel buildCheckboxPanel(SkillDataBonus bonus) + { + JPanel uiOption = new JPanel(new BorderLayout()); + JLabel uiLabel = new JLabel(bonus.getName()); + JCheckBox uiCheckbox = new JCheckBox(); + + uiLabel.setForeground(Color.WHITE); + uiLabel.setFont(FontManager.getRunescapeSmallFont()); + + uiOption.setBorder(BorderFactory.createEmptyBorder(3, 7, 3, 0)); + uiOption.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + // Adjust XP bonus depending on check-state of the boxes. + uiCheckbox.addActionListener(event -> adjustCheckboxes(uiCheckbox, bonus)); + + uiCheckbox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR); + + uiOption.add(uiLabel, BorderLayout.WEST); + uiOption.add(uiCheckbox, BorderLayout.EAST); + bonusCheckBoxes.add(uiCheckbox); + + return uiOption; + } + + private void adjustCheckboxes(JCheckBox target, SkillDataBonus bonus) + { + adjustXPBonus(0); + bonusCheckBoxes.forEach(otherSelectedCheckbox -> + { + if (otherSelectedCheckbox != target) + { + otherSelectedCheckbox.setSelected(false); + } + }); + + if (target.isSelected()) + { + adjustXPBonus(bonus.getValue()); + } + } + + private void adjustXPBonus(float value) + { + xpFactor = 1f + value; + refreshDetailContainer(); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java index 35fc1b2029..ea7af8bbca 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java @@ -1,487 +1,488 @@ -/* - * Copyright (c) 2018, Kruithne - * Copyright (c) 2018, Psikoi - * 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.skillcalculator; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.Experience; -import net.runelite.api.Skill; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.plugins.skillcalculator.beans.SkillData; -import net.runelite.client.plugins.skillcalculator.beans.SkillDataBonus; -import net.runelite.client.plugins.skillcalculator.beans.SkillDataEntry; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.DynamicGridLayout; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.ui.components.IconTextField; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; - -class SkillCalculator extends JPanel -{ - private static final int MAX_XP = 200_000_000; - private static final DecimalFormat XP_FORMAT = new DecimalFormat("#.#"); - - private final UICalculatorInputArea uiInput; - private final Client client; - private final SpriteManager spriteManager; - private final ItemManager itemManager; - private final List uiActionSlots = new ArrayList<>(); - private final CacheSkillData cacheSkillData = new CacheSkillData(); - @Getter(AccessLevel.PACKAGE) - private final UICombinedActionSlot combinedActionSlot; - @Getter(AccessLevel.PACKAGE) - private final ArrayList combinedActionSlots = new ArrayList<>(); - private final List bonusCheckBoxes = new ArrayList<>(); - private final IconTextField searchBar = new IconTextField(); - - private SkillData skillData; - private int currentLevel = 1; - private int currentXP = Experience.getXpForLevel(currentLevel); - private int targetLevel = currentLevel + 1; - private int targetXP = Experience.getXpForLevel(targetLevel); - private float xpFactor = 1.0f; - private float lastBonus = 0.0f; - private CalculatorType calculatorType; - - SkillCalculator(Client client, UICalculatorInputArea uiInput, SpriteManager spriteManager, ItemManager itemManager) - { - this.client = client; - this.uiInput = uiInput; - this.spriteManager = spriteManager; - this.itemManager = itemManager; - - combinedActionSlot = new UICombinedActionSlot(spriteManager); - - searchBar.setIcon(IconTextField.Icon.SEARCH); - searchBar.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH - 20, 30)); - searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR); - searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR); - searchBar.addKeyListener(e -> onSearch()); - - setLayout(new DynamicGridLayout(0, 1, 0, 5)); - - // Register listeners on the input fields and then move on to the next related text field - uiInput.getUiFieldCurrentLevel().addActionListener(e -> - { - onFieldCurrentLevelUpdated(); - uiInput.getUiFieldTargetLevel().requestFocusInWindow(); - }); - - uiInput.getUiFieldCurrentXP().addActionListener(e -> - { - onFieldCurrentXPUpdated(); - uiInput.getUiFieldTargetXP().requestFocusInWindow(); - }); - - uiInput.getUiFieldTargetLevel().addActionListener(e -> onFieldTargetLevelUpdated()); - uiInput.getUiFieldTargetXP().addActionListener(e -> onFieldTargetXPUpdated()); - } - - void openCalculator(CalculatorType calculatorType) - { - this.calculatorType = calculatorType; - - // Load the skill data. - skillData = cacheSkillData.getSkillData(calculatorType.getDataFile()); - - // Reset the XP factor, removing bonuses. - xpFactor = 1.0f; - - // Update internal skill/XP values. - updateInternalValues(); - - // BankedCalculator prevents these from being editable so just ensure they are editable. - uiInput.getUiFieldTargetLevel().setEditable(true); - uiInput.getUiFieldTargetXP().setEditable(true); - - // Remove all components (action slots) from this panel. - removeAll(); - - // Clear the search bar - searchBar.setText(null); - - // Clear the search bar - searchBar.setText(null); - - // Add in checkboxes for available skill bonuses. - renderBonusOptions(); - - // Add the combined action slot. - add(combinedActionSlot); - - // Add the search bar - add(searchBar); - - // Create action slots for the skill actions. - renderActionSlots(); - - // Update the input fields. - updateInputFields(); - } - - private void updateInternalValues() - { - updateCurrentValues(); - updateTargetValues(); - } - - private void updateCurrentValues() - { - currentXP = client.getSkillExperience(calculatorType.getSkill()); - currentLevel = Experience.getLevelForXp(currentXP); - } - private void updateTargetValues() - { - targetLevel = enforceSkillBounds(currentLevel + 1); - targetXP = Experience.getXpForLevel(targetLevel); - } - - private void updateCombinedAction() - { - int size = combinedActionSlots.size(); - if (size > 1) - { - combinedActionSlot.setTitle(size + " actions selected"); - } - else if (size == 1) - { - combinedActionSlot.setTitle("1 action selected"); - } - else - { - combinedActionSlot.setTitle("No action selected"); - combinedActionSlot.setText("Shift-click to select multiple"); - return; - } - - int actionCount = 0; - int neededXP = targetXP - currentXP; - double xp = 0; - - for (UIActionSlot slot : combinedActionSlots) - { - xp += slot.getValue(); - } - - if (neededXP > 0) - { - assert xp != 0; - actionCount = (int) Math.ceil(neededXP / xp); - } - - combinedActionSlot.setText(formatXPActionString(xp, actionCount, "exp - ")); - } - - private void clearCombinedSlots() - { - for (UIActionSlot slot : combinedActionSlots) - { - slot.setSelected(false); - } - - combinedActionSlots.clear(); - } - - private void renderBonusOptions() - { - if (skillData.getBonuses() != null) - { - List uiCheckBoxList = new ArrayList<>(); - lastBonus = 0.0f; - - for (SkillDataBonus bonus : skillData.getBonuses()) - { - Pair> combinedCheckboxPanel = buildCheckboxPanel(bonus, uiCheckBoxList); - JPanel checkboxPanel = combinedCheckboxPanel.getKey(); - uiCheckBoxList = combinedCheckboxPanel.getValue(); - - add(checkboxPanel); - } - - add(Box.createRigidArea(new Dimension(0, 5))); - } - } - - private Pair> buildCheckboxPanel(SkillDataBonus bonus, List uiCheckBoxList) - { - JPanel uiOption = new JPanel(new BorderLayout()); - JLabel uiLabel = new JLabel(bonus.getName()); - JCheckBox uiCheckbox = new JCheckBox(); - - uiLabel.setForeground(Color.WHITE); - uiLabel.setFont(FontManager.getRunescapeSmallFont()); - - uiOption.setBorder(BorderFactory.createEmptyBorder(3, 7, 3, 0)); - uiOption.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - JCheckBox uiCheckBox = new JCheckBox(); - uiCheckBox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR); - uiCheckBox.addActionListener(e -> - { - if (uiCheckBox.isSelected()) - { - adjustXPBonus(uiCheckBox.isSelected(), bonus.getValue()); - lastBonus = bonus.getValue(); - - for (JCheckBox checkBox : uiCheckBoxList) - { - if (checkBox != uiCheckBox) - { - checkBox.setSelected(false); - } - } - } - else if (xpFactor > 1.0) - { - xpFactor = 1.0f; - lastBonus = 0.0f; - calculate(); - } - - updateCombinedAction(); - }); - - uiCheckBoxList.add(uiCheckBox); - - uiOption.add(uiCheckBox, BorderLayout.EAST); - - uiOption.add(uiLabel, BorderLayout.WEST); - bonusCheckBoxes.add(uiCheckbox); - - return new ImmutablePair<>(uiOption, uiCheckBoxList); - } - - private void renderActionSlots() - { - // Wipe the list of references to the slot components. - uiActionSlots.clear(); - - // Create new components for the action slots. - for (SkillDataEntry action : skillData.getActions()) - { - JLabel uiIcon = new JLabel(); - - if (action.getIcon() != null) - { - itemManager.getImage(action.getIcon()).addTo(uiIcon); - } - else if (action.getSprite() != null) - { - spriteManager.addSpriteTo(uiIcon, action.getSprite(), 0); - } - - UIActionSlot slot = new UIActionSlot(action, uiIcon); - uiActionSlots.add(slot); // Keep our own reference. - add(slot); // Add component to the panel. - - slot.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent e) - { - if (!e.isShiftDown()) - { - clearCombinedSlots(); - } - - if (slot.isSelected()) - { - combinedActionSlots.remove(slot); - } - else - { - combinedActionSlots.add(slot); - } - - slot.setSelected(!slot.isSelected()); - updateCombinedAction(); - } - }); - } - - // Refresh the rendering of this panel. - revalidate(); - repaint(); - } - - private void calculate() - { - for (UIActionSlot slot : uiActionSlots) - { - int actionCount = 0; - int neededXP = targetXP - currentXP; - SkillDataEntry action = slot.getAction(); - double xp = (action.isIgnoreBonus()) ? action.getXp() : action.getXp() * xpFactor; - - if (neededXP > 0) - { - actionCount = (int) Math.ceil(neededXP / xp); - } - - slot.setText("Lvl. " + action.getLevel() + " (" + formatXPActionString(xp, actionCount, "exp) - ")); - slot.setAvailable(currentLevel >= action.getLevel()); - slot.setOverlapping(action.getLevel() < targetLevel); - slot.setValue(xp); - } - - updateCombinedAction(); - } - - private String formatXPActionString(double xp, int actionCount, String expExpression) - { - return XP_FORMAT.format(xp) + expExpression + NumberFormat.getIntegerInstance().format(actionCount) + (actionCount > 1 ? " actions" : " action"); - } - - private void updateInputFields() - { - if (targetXP < currentXP) - { - targetLevel = enforceSkillBounds(currentLevel + 1); - targetXP = Experience.getXpForLevel(targetLevel); - } - - uiInput.setCurrentLevelInput(currentLevel); - uiInput.setCurrentXPInput(currentXP); - uiInput.setTargetLevelInput(targetLevel); - uiInput.setTargetXPInput(targetXP); - calculate(); - } - - private void adjustXPBonus(boolean addBonus, float value) - { - clearLastBonus(); - xpFactor += addBonus ? value : -value; - calculate(); - } - - private void clearLastBonus() - { - xpFactor -= lastBonus; - calculate(); - } - - private void onFieldCurrentLevelUpdated() - { - currentLevel = enforceSkillBounds(uiInput.getCurrentLevelInput()); - currentXP = Experience.getXpForLevel(currentLevel); - updateInputFields(); - } - - private void onFieldCurrentXPUpdated() - { - currentXP = enforceXPBounds(uiInput.getCurrentXPInput()); - currentLevel = Experience.getLevelForXp(currentXP); - updateInputFields(); - } - - private void onFieldTargetLevelUpdated() - { - targetLevel = enforceSkillBounds(uiInput.getTargetLevelInput()); - targetXP = Experience.getXpForLevel(targetLevel); - updateInputFields(); - } - - private void onFieldTargetXPUpdated() - { - targetXP = enforceXPBounds(uiInput.getTargetXPInput()); - targetLevel = Experience.getLevelForXp(targetXP); - updateInputFields(); - } - - private static int enforceSkillBounds(int input) - { - return Math.min(Experience.MAX_VIRT_LEVEL, Math.max(1, input)); - } - - private static int enforceXPBounds(int input) - { - return Math.min(MAX_XP, Math.max(0, input)); - } - - private void onSearch() - { - //only show slots that match our search text - uiActionSlots.forEach(slot -> - { - if (slotContainsText(slot, searchBar.getText())) - { - super.add(slot); - } - else - { - super.remove(slot); - } - - revalidate(); - }); - } - - private boolean slotContainsText(UIActionSlot slot, String text) - { - return slot.getAction().getName().toLowerCase().contains(text.toLowerCase()); - } - - /** - * Updates the current skill calculator (if present) - *

- * This method is invoked by the {@link SkillCalculatorPlugin} event subscriber - * when an {@link ExperienceChanged} object is posted to the event bus - */ - void updateSkillCalculator(Skill skill) - { - // If the user has selected a calculator, update its fields - Optional.ofNullable(calculatorType).ifPresent(calc -> - { - if (skill.equals(calculatorType.getSkill())) - { - // Update our model "current" values - updateCurrentValues(); - - // Update the UI to reflect our new model - updateInputFields(); - } - }); - } +/* + * Copyright (c) 2018, Kruithne + * Copyright (c) 2018, Psikoi + * 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.skillcalculator; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Experience; +import net.runelite.api.Skill; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.plugins.skillcalculator.beans.SkillData; +import net.runelite.client.plugins.skillcalculator.beans.SkillDataBonus; +import net.runelite.client.plugins.skillcalculator.beans.SkillDataEntry; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.DynamicGridLayout; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.IconTextField; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +class SkillCalculator extends JPanel +{ + private static final int MAX_XP = 200_000_000; + private static final DecimalFormat XP_FORMAT = new DecimalFormat("#.#"); + + private final UICalculatorInputArea uiInput; + private final Client client; + private final SpriteManager spriteManager; + private final ItemManager itemManager; + private final List uiActionSlots = new ArrayList<>(); + private final CacheSkillData cacheSkillData = new CacheSkillData(); + @Getter(AccessLevel.PACKAGE) + private final UICombinedActionSlot combinedActionSlot; + @Getter(AccessLevel.PACKAGE) + private final ArrayList combinedActionSlots = new ArrayList<>(); + private final List bonusCheckBoxes = new ArrayList<>(); + private final IconTextField searchBar = new IconTextField(); + + private SkillData skillData; + private int currentLevel = 1; + private int currentXP = Experience.getXpForLevel(currentLevel); + private int targetLevel = currentLevel + 1; + private int targetXP = Experience.getXpForLevel(targetLevel); + private float xpFactor = 1.0f; + private float lastBonus = 0.0f; + private CalculatorType calculatorType; + + SkillCalculator(Client client, UICalculatorInputArea uiInput, SpriteManager spriteManager, ItemManager itemManager) + { + this.client = client; + this.uiInput = uiInput; + this.spriteManager = spriteManager; + this.itemManager = itemManager; + + combinedActionSlot = new UICombinedActionSlot(spriteManager); + + searchBar.setIcon(IconTextField.Icon.SEARCH); + searchBar.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH - 20, 30)); + searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR); + searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR); + searchBar.addKeyListener(e -> onSearch()); + + setLayout(new DynamicGridLayout(0, 1, 0, 5)); + + // Register listeners on the input fields and then move on to the next related text field + uiInput.getUiFieldCurrentLevel().addActionListener(e -> + { + onFieldCurrentLevelUpdated(); + uiInput.getUiFieldTargetLevel().requestFocusInWindow(); + }); + + uiInput.getUiFieldCurrentXP().addActionListener(e -> + { + onFieldCurrentXPUpdated(); + uiInput.getUiFieldTargetXP().requestFocusInWindow(); + }); + + uiInput.getUiFieldTargetLevel().addActionListener(e -> onFieldTargetLevelUpdated()); + uiInput.getUiFieldTargetXP().addActionListener(e -> onFieldTargetXPUpdated()); + } + + void openCalculator(CalculatorType calculatorType) + { + this.calculatorType = calculatorType; + + // Load the skill data. + skillData = cacheSkillData.getSkillData(calculatorType.getDataFile()); + + // Reset the XP factor, removing bonuses. + xpFactor = 1.0f; + + // Update internal skill/XP values. + updateInternalValues(); + + // BankedCalculator prevents these from being editable so just ensure they are editable. + uiInput.getUiFieldTargetLevel().setEditable(true); + uiInput.getUiFieldTargetXP().setEditable(true); + + // Remove all components (action slots) from this panel. + removeAll(); + + // Clear the search bar + searchBar.setText(null); + + // Clear the search bar + searchBar.setText(null); + + // Add in checkboxes for available skill bonuses. + renderBonusOptions(); + + // Add the combined action slot. + add(combinedActionSlot); + + // Add the search bar + add(searchBar); + + // Create action slots for the skill actions. + renderActionSlots(); + + // Update the input fields. + updateInputFields(); + } + + private void updateInternalValues() + { + updateCurrentValues(); + updateTargetValues(); + } + + private void updateCurrentValues() + { + currentXP = client.getSkillExperience(calculatorType.getSkill()); + currentLevel = Experience.getLevelForXp(currentXP); + } + + private void updateTargetValues() + { + targetLevel = enforceSkillBounds(currentLevel + 1); + targetXP = Experience.getXpForLevel(targetLevel); + } + + private void updateCombinedAction() + { + int size = combinedActionSlots.size(); + if (size > 1) + { + combinedActionSlot.setTitle(size + " actions selected"); + } + else if (size == 1) + { + combinedActionSlot.setTitle("1 action selected"); + } + else + { + combinedActionSlot.setTitle("No action selected"); + combinedActionSlot.setText("Shift-click to select multiple"); + return; + } + + int actionCount = 0; + int neededXP = targetXP - currentXP; + double xp = 0; + + for (UIActionSlot slot : combinedActionSlots) + { + xp += slot.getValue(); + } + + if (neededXP > 0) + { + assert xp != 0; + actionCount = (int) Math.ceil(neededXP / xp); + } + + combinedActionSlot.setText(formatXPActionString(xp, actionCount, "exp - ")); + } + + private void clearCombinedSlots() + { + for (UIActionSlot slot : combinedActionSlots) + { + slot.setSelected(false); + } + + combinedActionSlots.clear(); + } + + private void renderBonusOptions() + { + if (skillData.getBonuses() != null) + { + List uiCheckBoxList = new ArrayList<>(); + lastBonus = 0.0f; + + for (SkillDataBonus bonus : skillData.getBonuses()) + { + Pair> combinedCheckboxPanel = buildCheckboxPanel(bonus, uiCheckBoxList); + JPanel checkboxPanel = combinedCheckboxPanel.getKey(); + uiCheckBoxList = combinedCheckboxPanel.getValue(); + + add(checkboxPanel); + } + + add(Box.createRigidArea(new Dimension(0, 5))); + } + } + + private Pair> buildCheckboxPanel(SkillDataBonus bonus, List uiCheckBoxList) + { + JPanel uiOption = new JPanel(new BorderLayout()); + JLabel uiLabel = new JLabel(bonus.getName()); + JCheckBox uiCheckbox = new JCheckBox(); + + uiLabel.setForeground(Color.WHITE); + uiLabel.setFont(FontManager.getRunescapeSmallFont()); + + uiOption.setBorder(BorderFactory.createEmptyBorder(3, 7, 3, 0)); + uiOption.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + JCheckBox uiCheckBox = new JCheckBox(); + uiCheckBox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR); + uiCheckBox.addActionListener(e -> + { + if (uiCheckBox.isSelected()) + { + adjustXPBonus(uiCheckBox.isSelected(), bonus.getValue()); + lastBonus = bonus.getValue(); + + for (JCheckBox checkBox : uiCheckBoxList) + { + if (checkBox != uiCheckBox) + { + checkBox.setSelected(false); + } + } + } + else if (xpFactor > 1.0) + { + xpFactor = 1.0f; + lastBonus = 0.0f; + calculate(); + } + + updateCombinedAction(); + }); + + uiCheckBoxList.add(uiCheckBox); + + uiOption.add(uiCheckBox, BorderLayout.EAST); + + uiOption.add(uiLabel, BorderLayout.WEST); + bonusCheckBoxes.add(uiCheckbox); + + return new ImmutablePair<>(uiOption, uiCheckBoxList); + } + + private void renderActionSlots() + { + // Wipe the list of references to the slot components. + uiActionSlots.clear(); + + // Create new components for the action slots. + for (SkillDataEntry action : skillData.getActions()) + { + JLabel uiIcon = new JLabel(); + + if (action.getIcon() != null) + { + itemManager.getImage(action.getIcon()).addTo(uiIcon); + } + else if (action.getSprite() != null) + { + spriteManager.addSpriteTo(uiIcon, action.getSprite(), 0); + } + + UIActionSlot slot = new UIActionSlot(action, uiIcon); + uiActionSlots.add(slot); // Keep our own reference. + add(slot); // Add component to the panel. + + slot.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent e) + { + if (!e.isShiftDown()) + { + clearCombinedSlots(); + } + + if (slot.isSelected()) + { + combinedActionSlots.remove(slot); + } + else + { + combinedActionSlots.add(slot); + } + + slot.setSelected(!slot.isSelected()); + updateCombinedAction(); + } + }); + } + + // Refresh the rendering of this panel. + revalidate(); + repaint(); + } + + private void calculate() + { + for (UIActionSlot slot : uiActionSlots) + { + int actionCount = 0; + int neededXP = targetXP - currentXP; + SkillDataEntry action = slot.getAction(); + double xp = (action.isIgnoreBonus()) ? action.getXp() : action.getXp() * xpFactor; + + if (neededXP > 0) + { + actionCount = (int) Math.ceil(neededXP / xp); + } + + slot.setText("Lvl. " + action.getLevel() + " (" + formatXPActionString(xp, actionCount, "exp) - ")); + slot.setAvailable(currentLevel >= action.getLevel()); + slot.setOverlapping(action.getLevel() < targetLevel); + slot.setValue(xp); + } + + updateCombinedAction(); + } + + private String formatXPActionString(double xp, int actionCount, String expExpression) + { + return XP_FORMAT.format(xp) + expExpression + NumberFormat.getIntegerInstance().format(actionCount) + (actionCount > 1 ? " actions" : " action"); + } + + private void updateInputFields() + { + if (targetXP < currentXP) + { + targetLevel = enforceSkillBounds(currentLevel + 1); + targetXP = Experience.getXpForLevel(targetLevel); + } + + uiInput.setCurrentLevelInput(currentLevel); + uiInput.setCurrentXPInput(currentXP); + uiInput.setTargetLevelInput(targetLevel); + uiInput.setTargetXPInput(targetXP); + calculate(); + } + + private void adjustXPBonus(boolean addBonus, float value) + { + clearLastBonus(); + xpFactor += addBonus ? value : -value; + calculate(); + } + + private void clearLastBonus() + { + xpFactor -= lastBonus; + calculate(); + } + + private void onFieldCurrentLevelUpdated() + { + currentLevel = enforceSkillBounds(uiInput.getCurrentLevelInput()); + currentXP = Experience.getXpForLevel(currentLevel); + updateInputFields(); + } + + private void onFieldCurrentXPUpdated() + { + currentXP = enforceXPBounds(uiInput.getCurrentXPInput()); + currentLevel = Experience.getLevelForXp(currentXP); + updateInputFields(); + } + + private void onFieldTargetLevelUpdated() + { + targetLevel = enforceSkillBounds(uiInput.getTargetLevelInput()); + targetXP = Experience.getXpForLevel(targetLevel); + updateInputFields(); + } + + private void onFieldTargetXPUpdated() + { + targetXP = enforceXPBounds(uiInput.getTargetXPInput()); + targetLevel = Experience.getLevelForXp(targetXP); + updateInputFields(); + } + + private static int enforceSkillBounds(int input) + { + return Math.min(Experience.MAX_VIRT_LEVEL, Math.max(1, input)); + } + + private static int enforceXPBounds(int input) + { + return Math.min(MAX_XP, Math.max(0, input)); + } + + private void onSearch() + { + //only show slots that match our search text + uiActionSlots.forEach(slot -> + { + if (slotContainsText(slot, searchBar.getText())) + { + super.add(slot); + } + else + { + super.remove(slot); + } + + revalidate(); + }); + } + + private boolean slotContainsText(UIActionSlot slot, String text) + { + return slot.getAction().getName().toLowerCase().contains(text.toLowerCase()); + } + + /** + * Updates the current skill calculator (if present) + *

+ * This method is invoked by the {@link SkillCalculatorPlugin} event subscriber + * when an {@link ExperienceChanged} object is posted to the event bus + */ + void updateSkillCalculator(Skill skill) + { + // If the user has selected a calculator, update its fields + Optional.ofNullable(calculatorType).ifPresent(calc -> + { + if (skill.equals(calculatorType.getSkill())) + { + // Update our model "current" values + updateCurrentValues(); + + // Update the UI to reflect our new model + updateInputFields(); + } + }); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorConfig.java index ce8a4c2ddd..0a1d8e5ce9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorConfig.java @@ -1,55 +1,55 @@ -/* - * 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.plugins.skillcalculator; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("skillCalculator") -public interface SkillCalculatorConfig extends Config -{ - @ConfigItem( - keyName = "showBankedXp", - name = "Show Banked xp Tab", - description = "Shows the Banked xp tab inside the Calculator Panel", - position = 0 - ) - default boolean showBankedXp() - { - return true; - } - - @ConfigItem( - keyName = "limitedBankedSecondaries", - name = "Limit Banked xp to Secondaries", - description = "Limits the Banked xp shown based on secondaries banked as well", - position = 1 - ) - default boolean limitedBankedSecondaries() - { - return false; - } +/* + * 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.plugins.skillcalculator; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("skillCalculator") +public interface SkillCalculatorConfig extends Config +{ + @ConfigItem( + keyName = "showBankedXp", + name = "Show Banked xp Tab", + description = "Shows the Banked xp tab inside the Calculator Panel", + position = 0 + ) + default boolean showBankedXp() + { + return true; + } + + @ConfigItem( + keyName = "limitedBankedSecondaries", + name = "Limit Banked xp to Secondaries", + description = "Limits the Banked xp shown based on secondaries banked as well", + position = 1 + ) + default boolean limitedBankedSecondaries() + { + return false; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorPanel.java index 30ab0b8486..939bd70b74 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculatorPanel.java @@ -1,243 +1,243 @@ -/* - * Copyright (c) 2018, Kruithne - * Copyright (c) 2018, Psikoi - * 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.plugins.skillcalculator; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import javax.swing.ImageIcon; -import javax.swing.JScrollPane; -import javax.swing.SwingUtilities; -import javax.swing.border.EmptyBorder; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.Skill; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.ui.components.materialtabs.MaterialTab; -import net.runelite.client.ui.components.materialtabs.MaterialTabGroup; - -@Slf4j -class SkillCalculatorPanel extends PluginPanel -{ - private final SkillCalculator uiCalculator; - private final SkillIconManager iconManager; - private final SkillCalculatorConfig config; - private final BankedCalculator bankedCalculator; - - private CalculatorType currentCalc; - private final MaterialTabGroup skillGroup; - private final MaterialTabGroup tabGroup; - private String currentTab; - private ArrayList tabs = new ArrayList<>(); - @Getter - private Map bankMap = new HashMap<>(); - private GridBagConstraints c; - - SkillCalculatorPanel(SkillIconManager iconManager, Client client, SkillCalculatorConfig config, SpriteManager spriteManager, ItemManager itemManager) - { - super(); - getScrollPane().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - - this.iconManager = iconManager; - this.config = config; - - setBorder(new EmptyBorder(10, 10, 10, 10)); - setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.gridx = 0; - c.gridy = 0; - - skillGroup = new MaterialTabGroup(); - skillGroup.setLayout(new GridLayout(0, 6, 7, 7)); - - addCalculatorButtons(); - - final UICalculatorInputArea uiInput = new UICalculatorInputArea(); - uiInput.setBorder(new EmptyBorder(15, 0, 15, 0)); - uiInput.setBackground(ColorScheme.DARK_GRAY_COLOR); - uiCalculator = new SkillCalculator(client, uiInput, spriteManager, itemManager); - - bankedCalculator = new BankedCalculator(this, client, uiInput, config, itemManager); - - tabGroup = new MaterialTabGroup(); - tabGroup.setBorder(new EmptyBorder(0, 0, 10, 0)); - - addTabButtons(); - - add(skillGroup, c); - c.gridy++; - - add(uiInput, c); - c.gridy++; - - add(tabGroup, c); - c.gridy++; - - add(uiCalculator, c); - } - - private void addCalculatorButtons() - { - for (CalculatorType calculatorType : CalculatorType.values()) - { - ImageIcon icon = new ImageIcon(iconManager.getSkillImage(calculatorType.getSkill(), true)); - MaterialTab tab = new MaterialTab(icon, skillGroup, null); - tab.setOnSelectEvent(() -> - { - if (currentCalc == calculatorType) - { - return true; - } - currentCalc = calculatorType; - selectedTab(currentTab, true); - return true; - }); - - skillGroup.addTab(tab); - } - } - - private void addTabButtons() - { - tabGroup.removeAll(); - tabs.clear(); - - tabs.add("Calculator"); - if (config.showBankedXp()) - { - tabs.add("Banked Xp"); - } - // Only show if both options are visible - tabGroup.setVisible(tabs.size() > 1); - - tabGroup.setLayout(new GridLayout(0, tabs.size(), 7, 7)); - - for (String s : tabs) - { - MaterialTab matTab = new MaterialTab(s, tabGroup, null); - - matTab.setHorizontalAlignment(SwingUtilities.CENTER); - - // Ensure Background is applied - matTab.setOpaque(true); - matTab.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - // When Clicked - matTab.setOnSelectEvent(() -> - { - selectedTab(s, false); - return true; - }); - - tabGroup.addTab(matTab); - } - - MaterialTab selected = tabGroup.getTab(0); - if (tabs.contains(currentTab)) - { - selected = tabGroup.getTab(tabs.indexOf(currentTab)); - } - - tabGroup.select(selected); - currentTab = selected.getText(); - } - - private void selectedTab(String s, boolean force) - { - // Do not refresh the panel if they clicked the same tab, unless they selected a new skill - if (Objects.equals(currentTab, s) && !force) - { - return; - } - - currentTab = s; - - // Only open a panel if a skill is selected - if (currentCalc == null) - { - return; - } - - switch (s) - { - case "Calculator": - remove(bankedCalculator); - add(uiCalculator, c); - uiCalculator.openCalculator(currentCalc); - break; - case "Banked Xp": - remove(uiCalculator); - add(bankedCalculator, c); - bankedCalculator.openBanked(currentCalc); - break; - } - - this.revalidate(); - this.repaint(); - } - - // Refresh entire panel - void refreshPanel() - { - // Recreate Tabs (in case of Config change) and selects the first tab - addTabButtons(); - - // Ensure reload - selectedTab(currentTab, true); - - this.revalidate(); - this.repaint(); - } - - // Wrapper function for updating SkillCalculator's bankMap - void updateBankMap(Map bank) - { - bankMap = bank; - if (currentCalc != null & currentTab.equals("Banked Xp")) - { - bankedCalculator.updateBankMap(bankMap); - } - } - - void updateSkillCalculator(Skill skill) - { - uiCalculator.updateSkillCalculator(skill); - } +/* + * Copyright (c) 2018, Kruithne + * Copyright (c) 2018, Psikoi + * 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.plugins.skillcalculator; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import javax.swing.ImageIcon; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.Skill; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SkillIconManager; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.materialtabs.MaterialTab; +import net.runelite.client.ui.components.materialtabs.MaterialTabGroup; + +@Slf4j +class SkillCalculatorPanel extends PluginPanel +{ + private final SkillCalculator uiCalculator; + private final SkillIconManager iconManager; + private final SkillCalculatorConfig config; + private final BankedCalculator bankedCalculator; + + private CalculatorType currentCalc; + private final MaterialTabGroup skillGroup; + private final MaterialTabGroup tabGroup; + private String currentTab; + private ArrayList tabs = new ArrayList<>(); + @Getter + private Map bankMap = new HashMap<>(); + private GridBagConstraints c; + + SkillCalculatorPanel(SkillIconManager iconManager, Client client, SkillCalculatorConfig config, SpriteManager spriteManager, ItemManager itemManager) + { + super(); + getScrollPane().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + + this.iconManager = iconManager; + this.config = config; + + setBorder(new EmptyBorder(10, 10, 10, 10)); + setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 0; + c.gridy = 0; + + skillGroup = new MaterialTabGroup(); + skillGroup.setLayout(new GridLayout(0, 6, 7, 7)); + + addCalculatorButtons(); + + final UICalculatorInputArea uiInput = new UICalculatorInputArea(); + uiInput.setBorder(new EmptyBorder(15, 0, 15, 0)); + uiInput.setBackground(ColorScheme.DARK_GRAY_COLOR); + uiCalculator = new SkillCalculator(client, uiInput, spriteManager, itemManager); + + bankedCalculator = new BankedCalculator(this, client, uiInput, config, itemManager); + + tabGroup = new MaterialTabGroup(); + tabGroup.setBorder(new EmptyBorder(0, 0, 10, 0)); + + addTabButtons(); + + add(skillGroup, c); + c.gridy++; + + add(uiInput, c); + c.gridy++; + + add(tabGroup, c); + c.gridy++; + + add(uiCalculator, c); + } + + private void addCalculatorButtons() + { + for (CalculatorType calculatorType : CalculatorType.values()) + { + ImageIcon icon = new ImageIcon(iconManager.getSkillImage(calculatorType.getSkill(), true)); + MaterialTab tab = new MaterialTab(icon, skillGroup, null); + tab.setOnSelectEvent(() -> + { + if (currentCalc == calculatorType) + { + return true; + } + currentCalc = calculatorType; + selectedTab(currentTab, true); + return true; + }); + + skillGroup.addTab(tab); + } + } + + private void addTabButtons() + { + tabGroup.removeAll(); + tabs.clear(); + + tabs.add("Calculator"); + if (config.showBankedXp()) + { + tabs.add("Banked Xp"); + } + // Only show if both options are visible + tabGroup.setVisible(tabs.size() > 1); + + tabGroup.setLayout(new GridLayout(0, tabs.size(), 7, 7)); + + for (String s : tabs) + { + MaterialTab matTab = new MaterialTab(s, tabGroup, null); + + matTab.setHorizontalAlignment(SwingUtilities.CENTER); + + // Ensure Background is applied + matTab.setOpaque(true); + matTab.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + // When Clicked + matTab.setOnSelectEvent(() -> + { + selectedTab(s, false); + return true; + }); + + tabGroup.addTab(matTab); + } + + MaterialTab selected = tabGroup.getTab(0); + if (tabs.contains(currentTab)) + { + selected = tabGroup.getTab(tabs.indexOf(currentTab)); + } + + tabGroup.select(selected); + currentTab = selected.getText(); + } + + private void selectedTab(String s, boolean force) + { + // Do not refresh the panel if they clicked the same tab, unless they selected a new skill + if (Objects.equals(currentTab, s) && !force) + { + return; + } + + currentTab = s; + + // Only open a panel if a skill is selected + if (currentCalc == null) + { + return; + } + + switch (s) + { + case "Calculator": + remove(bankedCalculator); + add(uiCalculator, c); + uiCalculator.openCalculator(currentCalc); + break; + case "Banked Xp": + remove(uiCalculator); + add(bankedCalculator, c); + bankedCalculator.openBanked(currentCalc); + break; + } + + this.revalidate(); + this.repaint(); + } + + // Refresh entire panel + void refreshPanel() + { + // Recreate Tabs (in case of Config change) and selects the first tab + addTabButtons(); + + // Ensure reload + selectedTab(currentTab, true); + + this.revalidate(); + this.repaint(); + } + + // Wrapper function for updating SkillCalculator's bankMap + void updateBankMap(Map bank) + { + bankMap = bank; + if (currentCalc != null & currentTab.equals("Banked Xp")) + { + bankedCalculator.updateBankMap(bankMap); + } + } + + void updateSkillCalculator(Skill skill) + { + uiCalculator.updateSkillCalculator(skill); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/CriticalItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/CriticalItem.java index 9cc6633746..8e5e0334c3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/CriticalItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/CriticalItem.java @@ -1,408 +1,417 @@ -/* - * 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.plugins.skillcalculator.banked; - -import lombok.Getter; -import net.runelite.api.ItemComposition; -import net.runelite.api.ItemID; -import net.runelite.api.Skill; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import net.runelite.client.game.ItemManager; - -public enum CriticalItem -{ - /** - * Construction Items - */ - // Planks - PLANK(ItemID.PLANK, "Planks", Skill.CONSTRUCTION), - OAK_PLANK(ItemID.OAK_PLANK, "Planks", Skill.CONSTRUCTION), - TEAK_PLANK(ItemID.TEAK_PLANK, "Planks", Skill.CONSTRUCTION), - MAHOGANY_PLANK(ItemID.MAHOGANY_PLANK, "Planks", Skill.CONSTRUCTION), - // Logs - LOGS(ItemID.LOGS, "Logs", Skill.CONSTRUCTION, ItemID.PLANK), - OAK_LOGS(ItemID.OAK_LOGS, "Logs", Skill.CONSTRUCTION, ItemID.OAK_PLANK), - TEAK_LOGS(ItemID.TEAK_LOGS, "Logs", Skill.CONSTRUCTION, ItemID.TEAK_PLANK), - MAHOGANY_LOGS(ItemID.MAHOGANY_LOGS, "Logs", Skill.CONSTRUCTION, ItemID.MAHOGANY_PLANK), - - /** - * Herblore Items - */ - // Grimy Herbs - GRIMY_GUAM_LEAF(ItemID.GRIMY_GUAM_LEAF, "Grimy Herbs", Skill.HERBLORE, ItemID.GUAM_LEAF), - GRIMY_MARRENTILL(ItemID.GRIMY_MARRENTILL, "Grimy Herbs", Skill.HERBLORE, ItemID.MARRENTILL), - GRIMY_TARROMIN(ItemID.GRIMY_TARROMIN, "Grimy Herbs", Skill.HERBLORE, ItemID.TARROMIN), - GRIMY_HARRALANDER(ItemID.GRIMY_HARRALANDER, "Grimy Herbs", Skill.HERBLORE, ItemID.HARRALANDER), - GRIMY_RANARR_WEED(ItemID.GRIMY_RANARR_WEED, "Grimy Herbs", Skill.HERBLORE, ItemID.RANARR_WEED), - GRIMY_TOADFLAX(ItemID.GRIMY_TOADFLAX, "Grimy Herbs", Skill.HERBLORE, ItemID.TOADFLAX), - GRIMY_IRIT_LEAF(ItemID.GRIMY_IRIT_LEAF, "Grimy Herbs", Skill.HERBLORE, ItemID.IRIT_LEAF), - GRIMY_AVANTOE(ItemID.GRIMY_AVANTOE, "Grimy Herbs", Skill.HERBLORE, ItemID.AVANTOE), - GRIMY_KWUARM(ItemID.GRIMY_KWUARM, "Grimy Herbs", Skill.HERBLORE, ItemID.KWUARM), - GRIMY_SNAPDRAGON(ItemID.GRIMY_SNAPDRAGON, "Grimy Herbs", Skill.HERBLORE, ItemID.SNAPDRAGON), - GRIMY_CADANTINE(ItemID.GRIMY_CADANTINE, "Grimy Herbs", Skill.HERBLORE, ItemID.CADANTINE), - GRIMY_LANTADYME(ItemID.GRIMY_LANTADYME, "Grimy Herbs", Skill.HERBLORE, ItemID.LANTADYME), - GRIMY_DWARF_WEED(ItemID.GRIMY_DWARF_WEED, "Grimy Herbs", Skill.HERBLORE, ItemID.DWARF_WEED), - GRIMY_TORSTOL(ItemID.GRIMY_TORSTOL, "Grimy Herbs", Skill.HERBLORE, ItemID.TORSTOL), - // Clean Herbs - GUAM_LEAF(ItemID.GUAM_LEAF, "Cleaned Herbs", Skill.HERBLORE, ItemID.GUAM_POTION_UNF), - MARRENTILL(ItemID.MARRENTILL, "Cleaned Herbs", Skill.HERBLORE, ItemID.MARRENTILL_POTION_UNF), - TARROMIN(ItemID.TARROMIN, "Cleaned Herbs", Skill.HERBLORE, ItemID.TARROMIN_POTION_UNF), - HARRALANDER(ItemID.HARRALANDER, "Cleaned Herbs", Skill.HERBLORE, ItemID.HARRALANDER_POTION_UNF), - RANARR_WEED(ItemID.RANARR_WEED, "Cleaned Herbs", Skill.HERBLORE, ItemID.RANARR_POTION_UNF), - TOADFLAX(ItemID.TOADFLAX, "Cleaned Herbs", Skill.HERBLORE, ItemID.TOADFLAX_POTION_UNF), - IRIT_LEAF(ItemID.IRIT_LEAF, "Cleaned Herbs", Skill.HERBLORE, ItemID.IRIT_POTION_UNF), - AVANTOE(ItemID.AVANTOE, "Cleaned Herbs", Skill.HERBLORE, ItemID.AVANTOE_POTION_UNF), - KWUARM(ItemID.KWUARM, "Cleaned Herbs", Skill.HERBLORE, ItemID.KWUARM_POTION_UNF), - SNAPDRAGON(ItemID.SNAPDRAGON, "Cleaned Herbs", Skill.HERBLORE, ItemID.SNAPDRAGON_POTION_UNF), - CADANTINE(ItemID.CADANTINE, "Cleaned Herbs", Skill.HERBLORE, ItemID.CADANTINE_POTION_UNF), - LANTADYME(ItemID.LANTADYME, "Cleaned Herbs", Skill.HERBLORE, ItemID.LANTADYME_POTION_UNF), - DWARF_WEED(ItemID.DWARF_WEED, "Cleaned Herbs", Skill.HERBLORE, ItemID.DWARF_WEED_POTION_UNF), - TORSTOL(ItemID.TORSTOL, "Cleaned Herbs", Skill.HERBLORE, ItemID.TORSTOL_POTION_UNF), - // Unfinished Potions - GUAM_LEAF_POTION_UNF(ItemID.GUAM_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - MARRENTILL_POTION_UNF(ItemID.MARRENTILL_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - TARROMIN_POTION_UNF(ItemID.TARROMIN_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - HARRALANDER_POTION_UNF(ItemID.HARRALANDER_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - RANARR_POTION_UNF(ItemID.RANARR_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - TOADFLAX_POTION_UNF(ItemID.TOADFLAX_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - IRIT_POTION_UNF(ItemID.IRIT_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - AVANTOE_POTION_UNF(ItemID.AVANTOE_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - KWUARM_POTION_UNF(ItemID.KWUARM_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - SNAPDRAGON_POTION_UNF(ItemID.SNAPDRAGON_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - CADANTINE_POTION_UNF(ItemID.CADANTINE_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - LANTADYME_POTION_UNF(ItemID.LANTADYME_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - DWARF_WEED_POTION_UNF(ItemID.DWARF_WEED_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - TORSTOL_POTION_UNF(ItemID.TORSTOL_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), - - /** - * Prayer Items - */ - // Bones - BONES(ItemID.BONES, "Bones", Skill.PRAYER), - WOLF_BONES(ItemID.WOLF_BONES, "Bones", Skill.PRAYER), - BURNT_BONES(ItemID.BURNT_BONES, "Bones", Skill.PRAYER), - MONKEY_BONES(ItemID.MONKEY_BONES, "Bones", Skill.PRAYER), - BAT_BONES(ItemID.BAT_BONES, "Bones", Skill.PRAYER), - JOGRE_BONES(ItemID.JOGRE_BONES, "Bones", Skill.PRAYER), - BIG_BONES(ItemID.BIG_BONES, "Bones", Skill.PRAYER), - ZOGRE_BONES(ItemID.ZOGRE_BONES, "Bones", Skill.PRAYER), - SHAIKAHAN_BONES(ItemID.SHAIKAHAN_BONES, "Bones", Skill.PRAYER), - BABYDRAGON_BONES(ItemID.BABYDRAGON_BONES, "Bones", Skill.PRAYER), - WYVERN_BONES(ItemID.WYVERN_BONES, "Bones", Skill.PRAYER), - DRAGON_BONES(ItemID.DRAGON_BONES, "Bones", Skill.PRAYER), - FAYRG_BONES(ItemID.FAYRG_BONES, "Bones", Skill.PRAYER), - LAVA_DRAGON_BONES(ItemID.LAVA_DRAGON_BONES, "Bones", Skill.PRAYER), - RAURG_BONES(ItemID.RAURG_BONES, "Bones", Skill.PRAYER), - DAGANNOTH_BONES(ItemID.DAGANNOTH_BONES, "Bones", Skill.PRAYER), - OURG_BONES(ItemID.OURG_BONES, "Bones", Skill.PRAYER), - SUPERIOR_DRAGON_BONES(ItemID.SUPERIOR_DRAGON_BONES, "Bones", Skill.PRAYER), - // Shade Remains (Pyre Logs) - LOAR_REMAINS(ItemID.LOAR_REMAINS, "Shades", Skill.PRAYER, true), - PHRIN_REMAINS(ItemID.PHRIN_REMAINS, "Shades", Skill.PRAYER, true), - RIYL_REMAINS(ItemID.RIYL_REMAINS, "Shades", Skill.PRAYER, true), - ASYN_REMAINS(ItemID.ASYN_REMAINS, "Shades", Skill.PRAYER, true), - FIYR_REMAINS(ItemID.FIYR_REMAINS, "Shades", Skill.PRAYER, true), - // Ensouled Heads - ENSOULED_GOBLIN_HEAD(ItemID.ENSOULED_GOBLIN_HEAD_13448, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_MONKEY_HEAD(ItemID.ENSOULED_MONKEY_HEAD_13451, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_IMP_HEAD(ItemID.ENSOULED_IMP_HEAD_13454, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_MINOTAUR_HEAD(ItemID.ENSOULED_MINOTAUR_HEAD_13457, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_SCORPION_HEAD(ItemID.ENSOULED_SCORPION_HEAD_13460, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_BEAR_HEAD(ItemID.ENSOULED_BEAR_HEAD_13463, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_UNICORN_HEAD(ItemID.ENSOULED_UNICORN_HEAD_13466, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_DOG_HEAD(ItemID.ENSOULED_DOG_HEAD_13469, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_CHAOS_DRUID_HEAD(ItemID.ENSOULED_CHAOS_DRUID_HEAD_13472, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_GIANT_HEAD(ItemID.ENSOULED_GIANT_HEAD_13475, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_OGRE_HEAD(ItemID.ENSOULED_OGRE_HEAD_13478, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_ELF_HEAD(ItemID.ENSOULED_ELF_HEAD_13481, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_TROLL_HEAD(ItemID.ENSOULED_TROLL_HEAD_13484, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_HORROR_HEAD(ItemID.ENSOULED_HORROR_HEAD_13487, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_KALPHITE_HEAD(ItemID.ENSOULED_KALPHITE_HEAD_13490, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_DAGANNOTH_HEAD(ItemID.ENSOULED_DAGANNOTH_HEAD_13493, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_BLOODVELD_HEAD(ItemID.ENSOULED_BLOODVELD_HEAD_13496, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_TZHAAR_HEAD(ItemID.ENSOULED_TZHAAR_HEAD_13499, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_DEMON_HEAD(ItemID.ENSOULED_DEMON_HEAD_13502, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_AVIANSIE_HEAD(ItemID.ENSOULED_AVIANSIE_HEAD_13505, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_ABYSSAL_HEAD(ItemID.ENSOULED_ABYSSAL_HEAD_13508, "Ensouled Heads", Skill.PRAYER, true), - ENSOULED_DRAGON_HEAD(ItemID.ENSOULED_DRAGON_HEAD_13511, "Ensouled Heads", Skill.PRAYER, true), - - /** - * Cooking Items - */ - RAW_HERRING(ItemID.RAW_HERRING, "Fish", Skill.COOKING), - RAW_MACKEREL(ItemID.RAW_MACKEREL, "Fish", Skill.COOKING), - RAW_TROUT(ItemID.RAW_TROUT, "Fish", Skill.COOKING), - RAW_COD(ItemID.RAW_COD, "Fish", Skill.COOKING), - RAW_PIKE(ItemID.RAW_PIKE, "Fish", Skill.COOKING), - RAW_SALMON(ItemID.RAW_SALMON, "Fish", Skill.COOKING), - RAW_TUNA(ItemID.RAW_TUNA, "Fish", Skill.COOKING), - RAW_KARAMBWAN(ItemID.RAW_KARAMBWAN, "Fish", Skill.COOKING), - RAW_LOBSTER(ItemID.RAW_LOBSTER, "Fish", Skill.COOKING), - RAW_BASS(ItemID.RAW_BASS, "Fish", Skill.COOKING), - RAW_SWORDFISH(ItemID.RAW_SWORDFISH, "Fish", Skill.COOKING), - RAW_MONKFISH(ItemID.RAW_MONKFISH, "Fish", Skill.COOKING), - RAW_SHARK(ItemID.RAW_SHARK, "Fish", Skill.COOKING), - RAW_SEA_TURTLE(ItemID.RAW_SEA_TURTLE, "Fish", Skill.COOKING), - RAW_ANGLERFISH(ItemID.RAW_ANGLERFISH, "Fish", Skill.COOKING), - RAW_DARK_CRAB(ItemID.RAW_DARK_CRAB, "Fish", Skill.COOKING), - RAW_MANTA_RAY(ItemID.RAW_MANTA_RAY, "Fish", Skill.COOKING), - - GRAPES(ItemID.GRAPES, "Other", Skill.COOKING), - - /** - * Crafting Items - */ - WOOL(ItemID.WOOL, "Misc", Skill.CRAFTING), - FLAX(ItemID.FLAX, "Misc", Skill.CRAFTING), - MOLTEN_GLASS(ItemID.MOLTEN_GLASS, "Misc", Skill.CRAFTING), - BATTLESTAFF(ItemID.BATTLESTAFF, "Misc", Skill.CRAFTING), - - // D'hide/Dragon Leather - GREEN_DRAGONHIDE(ItemID.GREEN_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.GREEN_DRAGON_LEATHER), - GREEN_DRAGON_LEATHER(ItemID.GREEN_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), - BLUE_DRAGONHIDE(ItemID.BLUE_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.BLUE_DRAGON_LEATHER), - BLUE_DRAGON_LEATHER(ItemID.BLUE_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), - RED_DRAGONHIDE(ItemID.RED_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.RED_DRAGON_LEATHER), - RED_DRAGON_LEATHER(ItemID.RED_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), - BLACK_DRAGONHIDE(ItemID.BLACK_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.BLACK_DRAGON_LEATHER), - BLACK_DRAGON_LEATHER(ItemID.BLACK_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), - - // Uncut Gems - UNCUT_OPAL(ItemID.UNCUT_OPAL, "Gems", Skill.CRAFTING, ItemID.OPAL), - UNCUT_JADE(ItemID.UNCUT_JADE, "Gems", Skill.CRAFTING, ItemID.JADE), - UNCUT_RED_TOPAZ(ItemID.UNCUT_RED_TOPAZ, "Gems", Skill.CRAFTING, ItemID.RED_TOPAZ), - UNCUT_SAPPHIRE(ItemID.UNCUT_SAPPHIRE, "Gems", Skill.CRAFTING, ItemID.SAPPHIRE), - UNCUT_EMERALD(ItemID.UNCUT_EMERALD, "Gems", Skill.CRAFTING, ItemID.EMERALD), - UNCUT_RUBY(ItemID.UNCUT_RUBY, "Gems", Skill.CRAFTING, ItemID.RUBY), - UNCUT_DIAMOND(ItemID.UNCUT_DIAMOND, "Gems", Skill.CRAFTING, ItemID.DIAMOND), - UNCUT_DRAGONSTONE(ItemID.UNCUT_DRAGONSTONE, "Gems", Skill.CRAFTING, ItemID.DRAGONSTONE), - UNCUT_ONYX(ItemID.UNCUT_ONYX, "Gems", Skill.CRAFTING, ItemID.ONYX), - UNCUT_ZENYTE(ItemID.UNCUT_ZENYTE, "Gems", Skill.CRAFTING, ItemID.ZENYTE), - - // Cut Gems - OPAL(ItemID.OPAL, "Gems", Skill.CRAFTING), - JADE(ItemID.JADE, "Gems", Skill.CRAFTING), - RED_TOPAZ(ItemID.RED_TOPAZ, "Gems", Skill.CRAFTING), - SAPPHIRE(ItemID.SAPPHIRE, "Gems", Skill.CRAFTING), - EMERALD(ItemID.EMERALD, "Gems", Skill.CRAFTING), - RUBY(ItemID.RUBY, "Gems", Skill.CRAFTING), - DIAMOND(ItemID.DIAMOND, "Gems", Skill.CRAFTING), - DRAGONSTONE(ItemID.DRAGONSTONE, "Gems", Skill.CRAFTING), - ONYX(ItemID.ONYX, "Gems", Skill.CRAFTING), - ZENYTE(ItemID.ZENYTE, "Gems", Skill.CRAFTING), - - /** - * Smithing Items - */ - - // Ores - IRON_ORE(ItemID.IRON_ORE, "Ore", Skill.SMITHING), - SILVER_ORE(ItemID.SILVER_ORE, "Ore", Skill.SMITHING), - GOLD_ORE(ItemID.GOLD_ORE, "Ore", Skill.SMITHING), - MITHRIL_ORE(ItemID.MITHRIL_ORE, "Ore", Skill.SMITHING), - ADAMANTITE_ORE(ItemID.ADAMANTITE_ORE, "Ore", Skill.SMITHING), - RUNITE_ORE(ItemID.RUNITE_ORE, "Ore", Skill.SMITHING), - - // Bars - BRONZE_BAR(ItemID.BRONZE_BAR, "Bars", Skill.SMITHING), - IRON_BAR(ItemID.IRON_BAR, "Bars", Skill.SMITHING), - STEEL_BAR(ItemID.STEEL_BAR, "Bars", Skill.SMITHING), - MITHRIL_BAR(ItemID.MITHRIL_BAR, "Bars", Skill.SMITHING), - ADAMANTITE_BAR(ItemID.ADAMANTITE_BAR, "Bars", Skill.SMITHING), - RUNITE_BAR(ItemID.RUNITE_BAR, "Bars", Skill.SMITHING), - - /** - * Farming Items - */ - // Seeds - ACORN(ItemID.ACORN, "Seeds", Skill.FARMING), - WILLOW_SEED(ItemID.WILLOW_SEED, "Seeds", Skill.FARMING), - MAPLE_SEED(ItemID.MAPLE_SEED, "Seeds", Skill.FARMING), - YEW_SEED(ItemID.YEW_SEED, "Seeds", Skill.FARMING), - MAGIC_SEED(ItemID.MAGIC_SEED, "Seeds", Skill.FARMING), - APPLE_TREE_SEED(ItemID.APPLE_TREE_SEED, "Seeds", Skill.FARMING), - BANANA_TREE_SEED(ItemID.BANANA_TREE_SEED, "Seeds", Skill.FARMING), - ORANGE_TREE_SEED(ItemID.ORANGE_TREE_SEED, "Seeds", Skill.FARMING), - CURRY_TREE_SEED(ItemID.CURRY_TREE_SEED, "Seeds", Skill.FARMING), - PINEAPPLE_SEED(ItemID.PINEAPPLE_SEED, "Seeds", Skill.FARMING), - PAPAYA_TREE_SEED(ItemID.PAPAYA_TREE_SEED, "Seeds", Skill.FARMING), - PALM_TREE_SEED(ItemID.PALM_TREE_SEED, "Seeds", Skill.FARMING), - CALQUAT_TREE_SEED(ItemID.CALQUAT_TREE_SEED, "Seeds", Skill.FARMING), - TEAK_SEED(ItemID.TEAK_SEED, "Seeds", Skill.FARMING), - MAHOGANY_SEED(ItemID.MAHOGANY_SEED, "Seeds", Skill.FARMING), - SPIRIT_SEED(ItemID.SPIRIT_SEED, "Seeds", Skill.FARMING), - - // Saplings - OAK_SAPLING(ItemID.OAK_SAPLING, "Saplings", Skill.FARMING, ItemID.ACORN), - WILLOW_SAPLING(ItemID.WILLOW_SAPLING, "Saplings", Skill.FARMING, ItemID.WILLOW_SEED), - MAPLE_SAPLING(ItemID.MAPLE_SAPLING, "Saplings", Skill.FARMING, ItemID.MAPLE_SEED), - YEW_SAPLING(ItemID.YEW_SAPLING, "Saplings", Skill.FARMING, ItemID.YEW_SEED), - MAGIC_SAPLING(ItemID.MAGIC_SAPLING, "Saplings", Skill.FARMING, ItemID.MAGIC_SEED), - APPLE_TREE_SAPLING(ItemID.APPLE_SAPLING, "Saplings", Skill.FARMING, ItemID.APPLE_TREE_SEED), - BANANA_TREE_SAPLING(ItemID.BANANA_SAPLING, "Saplings", Skill.FARMING, ItemID.BANANA_TREE_SEED), - ORANGE_TREE_SAPLING(ItemID.ORANGE_SAPLING, "Saplings", Skill.FARMING, ItemID.ORANGE_TREE_SEED), - CURRY_TREE_SAPLING(ItemID.CURRY_SAPLING, "Saplings", Skill.FARMING, ItemID.CURRY_TREE_SEED), - PINEAPPLE_SAPLING(ItemID.PINEAPPLE_SAPLING, "Saplings", Skill.FARMING, ItemID.PINEAPPLE_SEED), - PAPAYA_TREE_SAPLING(ItemID.PAPAYA_SAPLING, "Saplings", Skill.FARMING, ItemID.PAPAYA_TREE_SEED), - PALM_TREE_SAPLING(ItemID.PALM_SAPLING, "Saplings", Skill.FARMING, ItemID.PALM_TREE_SEED), - CALQUAT_TREE_SAPLING(ItemID.CALQUAT_SAPLING, "Saplings", Skill.FARMING, ItemID.CALQUAT_TREE_SEED), - TEAK_SAPLING(ItemID.TEAK_SAPLING, "Saplings", Skill.FARMING, ItemID.TEAK_SEED), - MAHOGANY_SAPLING(ItemID.MAHOGANY_SAPLING, "Saplings", Skill.FARMING, ItemID.MAHOGANY_SEED), - SPIRIT_SAPLING(ItemID.SPIRIT_SAPLING, "Saplings", Skill.FARMING, ItemID.SPIRIT_SEED), - ; - - @Getter - private final int itemID; - @Getter - private final String category; - @Getter - private final Skill skill; - - /** - * Should be operated on and then treated like this item or does nothing if null. - * Used mostly for things like herblore where you want Grimy, Clean, and UNF to count for creating potions. - * To do this GRIMY links to CLEAN which links to UNFINISHED which links to null - */ - @Getter - private final int linkedItemId; - - @Getter - private boolean ignoreBonus; - - @Getter - private ItemComposition composition; - - CriticalItem(int itemID, String category, Skill skill, int linkedItem) - { - this.itemID = itemID; - this.category = category; - this.skill = skill; - this.linkedItemId = linkedItem; - this.composition = null; - this.ignoreBonus = false; - } - - CriticalItem(int itemID, String category, Skill skill) - { - this(itemID, category, skill, -1); - } - - CriticalItem(int itemID, String category, Skill skill, boolean ignoreBonusXp) - { - this(itemID, category, skill, -1); - this.ignoreBonus = ignoreBonusXp; - } - - // Builds a Map to reduce looping frequency - private static Map> buildSkillItemMap() - { - Map> map = new HashMap<>(); - for (CriticalItem item : values()) - { - map.computeIfAbsent(item.getSkill(), e -> new ArrayList<>()).add(item); - } - - return map; - } - private static final Map> bySkillName = buildSkillItemMap(); - public static ArrayList getBySkillName(Skill skill) - { - return bySkillName.get(skill); - } - - // Builds a Map to reduce looping frequency - private static Map> buildSkillCategoryMap() - { - Map> map = new HashMap<>(); - for (CriticalItem item : values()) - { - map.computeIfAbsent(item.getSkill(), k -> new HashSet<>()).add(item.category); - } - - return map; - } - private static final Map> bySkillCategory = buildSkillCategoryMap(); - public static Set getSkillCategories(Skill skill) - { - return bySkillCategory.get(skill); - } - - // Builds a Map to reduce looping frequency - private static Map> buildItemSkillCategoryMap() - { - Map> map = new HashMap<>(); - for (CriticalItem item : values()) - { - String key = item.getCategory() + item.skill.getName(); - map.computeIfAbsent(key, e -> new ArrayList<>()).add(item); - } - - return map; - } - private static final Map> itemsBySkillCategory = buildItemSkillCategoryMap(); - public static ArrayList getItemsForSkillCategories(Skill skill, String category) - { - return itemsBySkillCategory.get(category + skill.getName()); - } - - // Builds a Map to reduce looping frequency - private static Map buildItemsByIdMap() - { - Map map = new HashMap<>(); - for (CriticalItem item : values()) - { - map.put(item.getItemID(), item); - } - - return map; - } - private static final Map itemsById = buildItemsByIdMap(); - public static CriticalItem getByItemId(int id) - { - return itemsById.get(id); - } - - /** - * Attaches the Item Composition to each Critical Item on client initial load - * @param m ItemManager - */ - public static void prepareItemCompositions(ItemManager m) - { - for (CriticalItem i : values()) - { - i.composition = m.getItemComposition(i.getItemID()); - } - } - - @Override - public String toString() - { - return "CriticalItem=(name=" + this.name() + ",id=" + this.itemID + ",category=" + this.category + ")"; - } -} +/* + * 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.plugins.skillcalculator.banked; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import lombok.Getter; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemID; +import net.runelite.api.Skill; +import net.runelite.client.game.ItemManager; + +public enum CriticalItem +{ + /** + * Construction Items + */ + // Planks + PLANK(ItemID.PLANK, "Planks", Skill.CONSTRUCTION), + OAK_PLANK(ItemID.OAK_PLANK, "Planks", Skill.CONSTRUCTION), + TEAK_PLANK(ItemID.TEAK_PLANK, "Planks", Skill.CONSTRUCTION), + MAHOGANY_PLANK(ItemID.MAHOGANY_PLANK, "Planks", Skill.CONSTRUCTION), + // Logs + LOGS(ItemID.LOGS, "Logs", Skill.CONSTRUCTION, ItemID.PLANK), + OAK_LOGS(ItemID.OAK_LOGS, "Logs", Skill.CONSTRUCTION, ItemID.OAK_PLANK), + TEAK_LOGS(ItemID.TEAK_LOGS, "Logs", Skill.CONSTRUCTION, ItemID.TEAK_PLANK), + MAHOGANY_LOGS(ItemID.MAHOGANY_LOGS, "Logs", Skill.CONSTRUCTION, ItemID.MAHOGANY_PLANK), + + /** + * Herblore Items + */ + // Grimy Herbs + GRIMY_GUAM_LEAF(ItemID.GRIMY_GUAM_LEAF, "Grimy Herbs", Skill.HERBLORE, ItemID.GUAM_LEAF), + GRIMY_MARRENTILL(ItemID.GRIMY_MARRENTILL, "Grimy Herbs", Skill.HERBLORE, ItemID.MARRENTILL), + GRIMY_TARROMIN(ItemID.GRIMY_TARROMIN, "Grimy Herbs", Skill.HERBLORE, ItemID.TARROMIN), + GRIMY_HARRALANDER(ItemID.GRIMY_HARRALANDER, "Grimy Herbs", Skill.HERBLORE, ItemID.HARRALANDER), + GRIMY_RANARR_WEED(ItemID.GRIMY_RANARR_WEED, "Grimy Herbs", Skill.HERBLORE, ItemID.RANARR_WEED), + GRIMY_TOADFLAX(ItemID.GRIMY_TOADFLAX, "Grimy Herbs", Skill.HERBLORE, ItemID.TOADFLAX), + GRIMY_IRIT_LEAF(ItemID.GRIMY_IRIT_LEAF, "Grimy Herbs", Skill.HERBLORE, ItemID.IRIT_LEAF), + GRIMY_AVANTOE(ItemID.GRIMY_AVANTOE, "Grimy Herbs", Skill.HERBLORE, ItemID.AVANTOE), + GRIMY_KWUARM(ItemID.GRIMY_KWUARM, "Grimy Herbs", Skill.HERBLORE, ItemID.KWUARM), + GRIMY_SNAPDRAGON(ItemID.GRIMY_SNAPDRAGON, "Grimy Herbs", Skill.HERBLORE, ItemID.SNAPDRAGON), + GRIMY_CADANTINE(ItemID.GRIMY_CADANTINE, "Grimy Herbs", Skill.HERBLORE, ItemID.CADANTINE), + GRIMY_LANTADYME(ItemID.GRIMY_LANTADYME, "Grimy Herbs", Skill.HERBLORE, ItemID.LANTADYME), + GRIMY_DWARF_WEED(ItemID.GRIMY_DWARF_WEED, "Grimy Herbs", Skill.HERBLORE, ItemID.DWARF_WEED), + GRIMY_TORSTOL(ItemID.GRIMY_TORSTOL, "Grimy Herbs", Skill.HERBLORE, ItemID.TORSTOL), + // Clean Herbs + GUAM_LEAF(ItemID.GUAM_LEAF, "Cleaned Herbs", Skill.HERBLORE, ItemID.GUAM_POTION_UNF), + MARRENTILL(ItemID.MARRENTILL, "Cleaned Herbs", Skill.HERBLORE, ItemID.MARRENTILL_POTION_UNF), + TARROMIN(ItemID.TARROMIN, "Cleaned Herbs", Skill.HERBLORE, ItemID.TARROMIN_POTION_UNF), + HARRALANDER(ItemID.HARRALANDER, "Cleaned Herbs", Skill.HERBLORE, ItemID.HARRALANDER_POTION_UNF), + RANARR_WEED(ItemID.RANARR_WEED, "Cleaned Herbs", Skill.HERBLORE, ItemID.RANARR_POTION_UNF), + TOADFLAX(ItemID.TOADFLAX, "Cleaned Herbs", Skill.HERBLORE, ItemID.TOADFLAX_POTION_UNF), + IRIT_LEAF(ItemID.IRIT_LEAF, "Cleaned Herbs", Skill.HERBLORE, ItemID.IRIT_POTION_UNF), + AVANTOE(ItemID.AVANTOE, "Cleaned Herbs", Skill.HERBLORE, ItemID.AVANTOE_POTION_UNF), + KWUARM(ItemID.KWUARM, "Cleaned Herbs", Skill.HERBLORE, ItemID.KWUARM_POTION_UNF), + SNAPDRAGON(ItemID.SNAPDRAGON, "Cleaned Herbs", Skill.HERBLORE, ItemID.SNAPDRAGON_POTION_UNF), + CADANTINE(ItemID.CADANTINE, "Cleaned Herbs", Skill.HERBLORE, ItemID.CADANTINE_POTION_UNF), + LANTADYME(ItemID.LANTADYME, "Cleaned Herbs", Skill.HERBLORE, ItemID.LANTADYME_POTION_UNF), + DWARF_WEED(ItemID.DWARF_WEED, "Cleaned Herbs", Skill.HERBLORE, ItemID.DWARF_WEED_POTION_UNF), + TORSTOL(ItemID.TORSTOL, "Cleaned Herbs", Skill.HERBLORE, ItemID.TORSTOL_POTION_UNF), + // Unfinished Potions + GUAM_LEAF_POTION_UNF(ItemID.GUAM_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + MARRENTILL_POTION_UNF(ItemID.MARRENTILL_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + TARROMIN_POTION_UNF(ItemID.TARROMIN_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + HARRALANDER_POTION_UNF(ItemID.HARRALANDER_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + RANARR_POTION_UNF(ItemID.RANARR_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + TOADFLAX_POTION_UNF(ItemID.TOADFLAX_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + IRIT_POTION_UNF(ItemID.IRIT_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + AVANTOE_POTION_UNF(ItemID.AVANTOE_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + KWUARM_POTION_UNF(ItemID.KWUARM_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + SNAPDRAGON_POTION_UNF(ItemID.SNAPDRAGON_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + CADANTINE_POTION_UNF(ItemID.CADANTINE_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + LANTADYME_POTION_UNF(ItemID.LANTADYME_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + DWARF_WEED_POTION_UNF(ItemID.DWARF_WEED_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + TORSTOL_POTION_UNF(ItemID.TORSTOL_POTION_UNF, "Unfinished Potions", Skill.HERBLORE), + + /** + * Prayer Items + */ + // Bones + BONES(ItemID.BONES, "Bones", Skill.PRAYER), + WOLF_BONES(ItemID.WOLF_BONES, "Bones", Skill.PRAYER), + BURNT_BONES(ItemID.BURNT_BONES, "Bones", Skill.PRAYER), + MONKEY_BONES(ItemID.MONKEY_BONES, "Bones", Skill.PRAYER), + BAT_BONES(ItemID.BAT_BONES, "Bones", Skill.PRAYER), + JOGRE_BONES(ItemID.JOGRE_BONES, "Bones", Skill.PRAYER), + BIG_BONES(ItemID.BIG_BONES, "Bones", Skill.PRAYER), + ZOGRE_BONES(ItemID.ZOGRE_BONES, "Bones", Skill.PRAYER), + SHAIKAHAN_BONES(ItemID.SHAIKAHAN_BONES, "Bones", Skill.PRAYER), + BABYDRAGON_BONES(ItemID.BABYDRAGON_BONES, "Bones", Skill.PRAYER), + WYVERN_BONES(ItemID.WYVERN_BONES, "Bones", Skill.PRAYER), + DRAGON_BONES(ItemID.DRAGON_BONES, "Bones", Skill.PRAYER), + FAYRG_BONES(ItemID.FAYRG_BONES, "Bones", Skill.PRAYER), + LAVA_DRAGON_BONES(ItemID.LAVA_DRAGON_BONES, "Bones", Skill.PRAYER), + RAURG_BONES(ItemID.RAURG_BONES, "Bones", Skill.PRAYER), + DAGANNOTH_BONES(ItemID.DAGANNOTH_BONES, "Bones", Skill.PRAYER), + OURG_BONES(ItemID.OURG_BONES, "Bones", Skill.PRAYER), + SUPERIOR_DRAGON_BONES(ItemID.SUPERIOR_DRAGON_BONES, "Bones", Skill.PRAYER), + // Shade Remains (Pyre Logs) + LOAR_REMAINS(ItemID.LOAR_REMAINS, "Shades", Skill.PRAYER, true), + PHRIN_REMAINS(ItemID.PHRIN_REMAINS, "Shades", Skill.PRAYER, true), + RIYL_REMAINS(ItemID.RIYL_REMAINS, "Shades", Skill.PRAYER, true), + ASYN_REMAINS(ItemID.ASYN_REMAINS, "Shades", Skill.PRAYER, true), + FIYR_REMAINS(ItemID.FIYR_REMAINS, "Shades", Skill.PRAYER, true), + // Ensouled Heads + ENSOULED_GOBLIN_HEAD(ItemID.ENSOULED_GOBLIN_HEAD_13448, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_MONKEY_HEAD(ItemID.ENSOULED_MONKEY_HEAD_13451, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_IMP_HEAD(ItemID.ENSOULED_IMP_HEAD_13454, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_MINOTAUR_HEAD(ItemID.ENSOULED_MINOTAUR_HEAD_13457, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_SCORPION_HEAD(ItemID.ENSOULED_SCORPION_HEAD_13460, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_BEAR_HEAD(ItemID.ENSOULED_BEAR_HEAD_13463, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_UNICORN_HEAD(ItemID.ENSOULED_UNICORN_HEAD_13466, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_DOG_HEAD(ItemID.ENSOULED_DOG_HEAD_13469, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_CHAOS_DRUID_HEAD(ItemID.ENSOULED_CHAOS_DRUID_HEAD_13472, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_GIANT_HEAD(ItemID.ENSOULED_GIANT_HEAD_13475, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_OGRE_HEAD(ItemID.ENSOULED_OGRE_HEAD_13478, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_ELF_HEAD(ItemID.ENSOULED_ELF_HEAD_13481, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_TROLL_HEAD(ItemID.ENSOULED_TROLL_HEAD_13484, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_HORROR_HEAD(ItemID.ENSOULED_HORROR_HEAD_13487, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_KALPHITE_HEAD(ItemID.ENSOULED_KALPHITE_HEAD_13490, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_DAGANNOTH_HEAD(ItemID.ENSOULED_DAGANNOTH_HEAD_13493, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_BLOODVELD_HEAD(ItemID.ENSOULED_BLOODVELD_HEAD_13496, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_TZHAAR_HEAD(ItemID.ENSOULED_TZHAAR_HEAD_13499, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_DEMON_HEAD(ItemID.ENSOULED_DEMON_HEAD_13502, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_AVIANSIE_HEAD(ItemID.ENSOULED_AVIANSIE_HEAD_13505, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_ABYSSAL_HEAD(ItemID.ENSOULED_ABYSSAL_HEAD_13508, "Ensouled Heads", Skill.PRAYER, true), + ENSOULED_DRAGON_HEAD(ItemID.ENSOULED_DRAGON_HEAD_13511, "Ensouled Heads", Skill.PRAYER, true), + + /** + * Cooking Items + */ + RAW_HERRING(ItemID.RAW_HERRING, "Fish", Skill.COOKING), + RAW_MACKEREL(ItemID.RAW_MACKEREL, "Fish", Skill.COOKING), + RAW_TROUT(ItemID.RAW_TROUT, "Fish", Skill.COOKING), + RAW_COD(ItemID.RAW_COD, "Fish", Skill.COOKING), + RAW_PIKE(ItemID.RAW_PIKE, "Fish", Skill.COOKING), + RAW_SALMON(ItemID.RAW_SALMON, "Fish", Skill.COOKING), + RAW_TUNA(ItemID.RAW_TUNA, "Fish", Skill.COOKING), + RAW_KARAMBWAN(ItemID.RAW_KARAMBWAN, "Fish", Skill.COOKING), + RAW_LOBSTER(ItemID.RAW_LOBSTER, "Fish", Skill.COOKING), + RAW_BASS(ItemID.RAW_BASS, "Fish", Skill.COOKING), + RAW_SWORDFISH(ItemID.RAW_SWORDFISH, "Fish", Skill.COOKING), + RAW_MONKFISH(ItemID.RAW_MONKFISH, "Fish", Skill.COOKING), + RAW_SHARK(ItemID.RAW_SHARK, "Fish", Skill.COOKING), + RAW_SEA_TURTLE(ItemID.RAW_SEA_TURTLE, "Fish", Skill.COOKING), + RAW_ANGLERFISH(ItemID.RAW_ANGLERFISH, "Fish", Skill.COOKING), + RAW_DARK_CRAB(ItemID.RAW_DARK_CRAB, "Fish", Skill.COOKING), + RAW_MANTA_RAY(ItemID.RAW_MANTA_RAY, "Fish", Skill.COOKING), + + GRAPES(ItemID.GRAPES, "Other", Skill.COOKING), + + /** + * Crafting Items + */ + WOOL(ItemID.WOOL, "Misc", Skill.CRAFTING), + FLAX(ItemID.FLAX, "Misc", Skill.CRAFTING), + MOLTEN_GLASS(ItemID.MOLTEN_GLASS, "Misc", Skill.CRAFTING), + BATTLESTAFF(ItemID.BATTLESTAFF, "Misc", Skill.CRAFTING), + + // D'hide/Dragon Leather + GREEN_DRAGONHIDE(ItemID.GREEN_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.GREEN_DRAGON_LEATHER), + GREEN_DRAGON_LEATHER(ItemID.GREEN_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), + BLUE_DRAGONHIDE(ItemID.BLUE_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.BLUE_DRAGON_LEATHER), + BLUE_DRAGON_LEATHER(ItemID.BLUE_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), + RED_DRAGONHIDE(ItemID.RED_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.RED_DRAGON_LEATHER), + RED_DRAGON_LEATHER(ItemID.RED_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), + BLACK_DRAGONHIDE(ItemID.BLACK_DRAGONHIDE, "D'hide", Skill.CRAFTING, ItemID.BLACK_DRAGON_LEATHER), + BLACK_DRAGON_LEATHER(ItemID.BLACK_DRAGON_LEATHER, "D'hide", Skill.CRAFTING), + + // Uncut Gems + UNCUT_OPAL(ItemID.UNCUT_OPAL, "Gems", Skill.CRAFTING, ItemID.OPAL), + UNCUT_JADE(ItemID.UNCUT_JADE, "Gems", Skill.CRAFTING, ItemID.JADE), + UNCUT_RED_TOPAZ(ItemID.UNCUT_RED_TOPAZ, "Gems", Skill.CRAFTING, ItemID.RED_TOPAZ), + UNCUT_SAPPHIRE(ItemID.UNCUT_SAPPHIRE, "Gems", Skill.CRAFTING, ItemID.SAPPHIRE), + UNCUT_EMERALD(ItemID.UNCUT_EMERALD, "Gems", Skill.CRAFTING, ItemID.EMERALD), + UNCUT_RUBY(ItemID.UNCUT_RUBY, "Gems", Skill.CRAFTING, ItemID.RUBY), + UNCUT_DIAMOND(ItemID.UNCUT_DIAMOND, "Gems", Skill.CRAFTING, ItemID.DIAMOND), + UNCUT_DRAGONSTONE(ItemID.UNCUT_DRAGONSTONE, "Gems", Skill.CRAFTING, ItemID.DRAGONSTONE), + UNCUT_ONYX(ItemID.UNCUT_ONYX, "Gems", Skill.CRAFTING, ItemID.ONYX), + UNCUT_ZENYTE(ItemID.UNCUT_ZENYTE, "Gems", Skill.CRAFTING, ItemID.ZENYTE), + + // Cut Gems + OPAL(ItemID.OPAL, "Gems", Skill.CRAFTING), + JADE(ItemID.JADE, "Gems", Skill.CRAFTING), + RED_TOPAZ(ItemID.RED_TOPAZ, "Gems", Skill.CRAFTING), + SAPPHIRE(ItemID.SAPPHIRE, "Gems", Skill.CRAFTING), + EMERALD(ItemID.EMERALD, "Gems", Skill.CRAFTING), + RUBY(ItemID.RUBY, "Gems", Skill.CRAFTING), + DIAMOND(ItemID.DIAMOND, "Gems", Skill.CRAFTING), + DRAGONSTONE(ItemID.DRAGONSTONE, "Gems", Skill.CRAFTING), + ONYX(ItemID.ONYX, "Gems", Skill.CRAFTING), + ZENYTE(ItemID.ZENYTE, "Gems", Skill.CRAFTING), + + /** + * Smithing Items + */ + + // Ores + IRON_ORE(ItemID.IRON_ORE, "Ore", Skill.SMITHING), + SILVER_ORE(ItemID.SILVER_ORE, "Ore", Skill.SMITHING), + GOLD_ORE(ItemID.GOLD_ORE, "Ore", Skill.SMITHING), + MITHRIL_ORE(ItemID.MITHRIL_ORE, "Ore", Skill.SMITHING), + ADAMANTITE_ORE(ItemID.ADAMANTITE_ORE, "Ore", Skill.SMITHING), + RUNITE_ORE(ItemID.RUNITE_ORE, "Ore", Skill.SMITHING), + + // Bars + BRONZE_BAR(ItemID.BRONZE_BAR, "Bars", Skill.SMITHING), + IRON_BAR(ItemID.IRON_BAR, "Bars", Skill.SMITHING), + STEEL_BAR(ItemID.STEEL_BAR, "Bars", Skill.SMITHING), + MITHRIL_BAR(ItemID.MITHRIL_BAR, "Bars", Skill.SMITHING), + ADAMANTITE_BAR(ItemID.ADAMANTITE_BAR, "Bars", Skill.SMITHING), + RUNITE_BAR(ItemID.RUNITE_BAR, "Bars", Skill.SMITHING), + + /** + * Farming Items + */ + // Seeds + ACORN(ItemID.ACORN, "Seeds", Skill.FARMING), + WILLOW_SEED(ItemID.WILLOW_SEED, "Seeds", Skill.FARMING), + MAPLE_SEED(ItemID.MAPLE_SEED, "Seeds", Skill.FARMING), + YEW_SEED(ItemID.YEW_SEED, "Seeds", Skill.FARMING), + MAGIC_SEED(ItemID.MAGIC_SEED, "Seeds", Skill.FARMING), + APPLE_TREE_SEED(ItemID.APPLE_TREE_SEED, "Seeds", Skill.FARMING), + BANANA_TREE_SEED(ItemID.BANANA_TREE_SEED, "Seeds", Skill.FARMING), + ORANGE_TREE_SEED(ItemID.ORANGE_TREE_SEED, "Seeds", Skill.FARMING), + CURRY_TREE_SEED(ItemID.CURRY_TREE_SEED, "Seeds", Skill.FARMING), + PINEAPPLE_SEED(ItemID.PINEAPPLE_SEED, "Seeds", Skill.FARMING), + PAPAYA_TREE_SEED(ItemID.PAPAYA_TREE_SEED, "Seeds", Skill.FARMING), + PALM_TREE_SEED(ItemID.PALM_TREE_SEED, "Seeds", Skill.FARMING), + CALQUAT_TREE_SEED(ItemID.CALQUAT_TREE_SEED, "Seeds", Skill.FARMING), + TEAK_SEED(ItemID.TEAK_SEED, "Seeds", Skill.FARMING), + MAHOGANY_SEED(ItemID.MAHOGANY_SEED, "Seeds", Skill.FARMING), + SPIRIT_SEED(ItemID.SPIRIT_SEED, "Seeds", Skill.FARMING), + + // Saplings + OAK_SAPLING(ItemID.OAK_SAPLING, "Saplings", Skill.FARMING, ItemID.ACORN), + WILLOW_SAPLING(ItemID.WILLOW_SAPLING, "Saplings", Skill.FARMING, ItemID.WILLOW_SEED), + MAPLE_SAPLING(ItemID.MAPLE_SAPLING, "Saplings", Skill.FARMING, ItemID.MAPLE_SEED), + YEW_SAPLING(ItemID.YEW_SAPLING, "Saplings", Skill.FARMING, ItemID.YEW_SEED), + MAGIC_SAPLING(ItemID.MAGIC_SAPLING, "Saplings", Skill.FARMING, ItemID.MAGIC_SEED), + APPLE_TREE_SAPLING(ItemID.APPLE_SAPLING, "Saplings", Skill.FARMING, ItemID.APPLE_TREE_SEED), + BANANA_TREE_SAPLING(ItemID.BANANA_SAPLING, "Saplings", Skill.FARMING, ItemID.BANANA_TREE_SEED), + ORANGE_TREE_SAPLING(ItemID.ORANGE_SAPLING, "Saplings", Skill.FARMING, ItemID.ORANGE_TREE_SEED), + CURRY_TREE_SAPLING(ItemID.CURRY_SAPLING, "Saplings", Skill.FARMING, ItemID.CURRY_TREE_SEED), + PINEAPPLE_SAPLING(ItemID.PINEAPPLE_SAPLING, "Saplings", Skill.FARMING, ItemID.PINEAPPLE_SEED), + PAPAYA_TREE_SAPLING(ItemID.PAPAYA_SAPLING, "Saplings", Skill.FARMING, ItemID.PAPAYA_TREE_SEED), + PALM_TREE_SAPLING(ItemID.PALM_SAPLING, "Saplings", Skill.FARMING, ItemID.PALM_TREE_SEED), + CALQUAT_TREE_SAPLING(ItemID.CALQUAT_SAPLING, "Saplings", Skill.FARMING, ItemID.CALQUAT_TREE_SEED), + TEAK_SAPLING(ItemID.TEAK_SAPLING, "Saplings", Skill.FARMING, ItemID.TEAK_SEED), + MAHOGANY_SAPLING(ItemID.MAHOGANY_SAPLING, "Saplings", Skill.FARMING, ItemID.MAHOGANY_SEED), + SPIRIT_SAPLING(ItemID.SPIRIT_SAPLING, "Saplings", Skill.FARMING, ItemID.SPIRIT_SEED), + ; + + @Getter + private final int itemID; + @Getter + private final String category; + @Getter + private final Skill skill; + + /** + * Should be operated on and then treated like this item or does nothing if null. + * Used mostly for things like herblore where you want Grimy, Clean, and UNF to count for creating potions. + * To do this GRIMY links to CLEAN which links to UNFINISHED which links to null + */ + @Getter + private final int linkedItemId; + + @Getter + private boolean ignoreBonus; + + @Getter + private ItemComposition composition; + + CriticalItem(int itemID, String category, Skill skill, int linkedItem) + { + this.itemID = itemID; + this.category = category; + this.skill = skill; + this.linkedItemId = linkedItem; + this.composition = null; + this.ignoreBonus = false; + } + + CriticalItem(int itemID, String category, Skill skill) + { + this(itemID, category, skill, -1); + } + + CriticalItem(int itemID, String category, Skill skill, boolean ignoreBonusXp) + { + this(itemID, category, skill, -1); + this.ignoreBonus = ignoreBonusXp; + } + + // Builds a Map to reduce looping frequency + private static Map> buildSkillItemMap() + { + Map> map = new HashMap<>(); + for (CriticalItem item : values()) + { + map.computeIfAbsent(item.getSkill(), e -> new ArrayList<>()).add(item); + } + + return map; + } + + private static final Map> bySkillName = buildSkillItemMap(); + + public static ArrayList getBySkillName(Skill skill) + { + return bySkillName.get(skill); + } + + // Builds a Map to reduce looping frequency + private static Map> buildSkillCategoryMap() + { + Map> map = new HashMap<>(); + for (CriticalItem item : values()) + { + map.computeIfAbsent(item.getSkill(), k -> new HashSet<>()).add(item.category); + } + + return map; + } + + private static final Map> bySkillCategory = buildSkillCategoryMap(); + + public static Set getSkillCategories(Skill skill) + { + return bySkillCategory.get(skill); + } + + // Builds a Map to reduce looping frequency + private static Map> buildItemSkillCategoryMap() + { + Map> map = new HashMap<>(); + for (CriticalItem item : values()) + { + String key = item.getCategory() + item.skill.getName(); + map.computeIfAbsent(key, e -> new ArrayList<>()).add(item); + } + + return map; + } + + private static final Map> itemsBySkillCategory = buildItemSkillCategoryMap(); + + public static ArrayList getItemsForSkillCategories(Skill skill, String category) + { + return itemsBySkillCategory.get(category + skill.getName()); + } + + // Builds a Map to reduce looping frequency + private static Map buildItemsByIdMap() + { + Map map = new HashMap<>(); + for (CriticalItem item : values()) + { + map.put(item.getItemID(), item); + } + + return map; + } + + private static final Map itemsById = buildItemsByIdMap(); + + public static CriticalItem getByItemId(int id) + { + return itemsById.get(id); + } + + /** + * Attaches the Item Composition to each Critical Item on client initial load + * + * @param m ItemManager + */ + public static void prepareItemCompositions(ItemManager m) + { + for (CriticalItem i : values()) + { + i.composition = m.getItemComposition(i.getItemID()); + } + } + + @Override + public String toString() + { + return "CriticalItem=(name=" + this.name() + ",id=" + this.itemID + ",category=" + this.category + ")"; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/beans/Activity.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/beans/Activity.java index 7d82ad720b..e855742667 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/beans/Activity.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/beans/Activity.java @@ -1,408 +1,411 @@ -/* - * 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.plugins.skillcalculator.banked.beans; - -import lombok.Getter; -import net.runelite.api.ItemID; -import net.runelite.api.Skill; -import net.runelite.client.plugins.skillcalculator.banked.CriticalItem; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -@Getter -public enum Activity -{ - /** - * Herblore Activities - */ - // Creating Potions - // Guam - GUAM_POTION_UNF(ItemID.GUAM_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.GUAM_LEAF, ActivitySecondaries.UNFINISHED_POTION), - GUAM_TAR(ItemID.GUAM_TAR, "Guam tar", Skill.HERBLORE, 19, 30, CriticalItem.GUAM_LEAF, ActivitySecondaries.SWAMP_TAR, true), - - ATTACK_POTION(ItemID.ATTACK_POTION4, "Attack Potion", Skill.HERBLORE, 3, 25, CriticalItem.GUAM_LEAF_POTION_UNF, ActivitySecondaries.ATTACK_POTION), - // Marrentil - MARRENTILL_POTION_UNF(ItemID.MARRENTILL_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.MARRENTILL, ActivitySecondaries.UNFINISHED_POTION), - MARRENTILL_TAR(ItemID.MARRENTILL_TAR, "Marrentill tar", Skill.HERBLORE, 31, 42.5, CriticalItem.MARRENTILL, ActivitySecondaries.SWAMP_TAR, true), - - ANTIPOISON(ItemID.ANTIPOISON4, "Antipoison", Skill.HERBLORE, 5, 37.5, CriticalItem.MARRENTILL_POTION_UNF, ActivitySecondaries.ANTIPOISON), - // Tarromin - TARROMIN_POTION_UNF(ItemID.TARROMIN_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.TARROMIN, ActivitySecondaries.UNFINISHED_POTION), - TARROMIN_TAR(ItemID.TARROMIN_TAR, "Tarromin tar", Skill.HERBLORE, 39, 55, CriticalItem.TARROMIN, ActivitySecondaries.SWAMP_TAR, true), - - STRENGTH_POTION(ItemID.STRENGTH_POTION4, "Strength potion", Skill.HERBLORE, 12, 50, CriticalItem.TARROMIN_POTION_UNF, ActivitySecondaries.STRENGTH_POTION), - SERUM_207(ItemID.SERUM_207_4, "Serum 207", Skill.HERBLORE, 15, 50, CriticalItem.TARROMIN_POTION_UNF, ActivitySecondaries.SERUM_207), - // Harralander - HARRALANDER_POTION_UNF(ItemID.HARRALANDER_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.HARRALANDER, ActivitySecondaries.UNFINISHED_POTION), - HARRALANDER_TAR(ItemID.HARRALANDER_TAR, "Harralander tar", Skill.HERBLORE, 44, 72.5, CriticalItem.HARRALANDER, ActivitySecondaries.SWAMP_TAR, true), - - COMPOST_POTION(ItemID.COMPOST_POTION4, "Compost potion", Skill.HERBLORE, 21, 60, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.COMPOST_POTION), - RESTORE_POTION(ItemID.RESTORE_POTION4, "Restore potion", Skill.HERBLORE, 22, 62.5, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.RESTORE_POTION), - ENERGY_POTION(ItemID.ENERGY_POTION4, "Energy potion", Skill.HERBLORE, 26, 67.5, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.ENERGY_POTION), - COMBAT_POTION(ItemID.COMBAT_POTION4, "Combat potion", Skill.HERBLORE, 36, 84, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.COMBAT_POTION), - // Ranarr Weed - DEFENCE_POTION(ItemID.DEFENCE_POTION4, "Defence potion", Skill.HERBLORE, 30, 75, CriticalItem.RANARR_POTION_UNF, ActivitySecondaries.DEFENCE_POTION), - PRAYER_POTION(ItemID.PRAYER_POTION4, "Prayer potion", Skill.HERBLORE, 38, 87.5, CriticalItem.RANARR_POTION_UNF, ActivitySecondaries.PRAYER_POTION), - // Toadflax - AGILITY_POTION(ItemID.AGILITY_POTION4, "Agility potion", Skill.HERBLORE, 34, 80, CriticalItem.TOADFLAX_POTION_UNF, ActivitySecondaries.AGILITY_POTION), - SARADOMIN_BREW(ItemID.SARADOMIN_BREW4, "Saradomin brew", Skill.HERBLORE, 81, 180, CriticalItem.TOADFLAX_POTION_UNF, ActivitySecondaries.SARADOMIN_BREW), - // Irit - SUPER_ATTACK(ItemID.SUPER_ATTACK4, "Super attack", Skill.HERBLORE, 45, 100, CriticalItem.IRIT_POTION_UNF, ActivitySecondaries.SUPER_ATTACK), - SUPERANTIPOISON(ItemID.SUPERANTIPOISON4, "Superantipoison", Skill.HERBLORE, 48, 106.3, CriticalItem.IRIT_POTION_UNF, ActivitySecondaries.SUPERANTIPOISON), - // Avantoe - FISHING_POTION(ItemID.FISHING_POTION4, "Fishing potion", Skill.HERBLORE, 50, 112.5, CriticalItem.AVANTOE_POTION_UNF, ActivitySecondaries.FISHING_POTION), - SUPER_ENERGY_POTION(ItemID.SUPER_ENERGY3_20549, "Super energy potion", Skill.HERBLORE, 52, 117.5, CriticalItem.AVANTOE_POTION_UNF, ActivitySecondaries.SUPER_ENERGY_POTION), - HUNTER_POTION(ItemID.HUNTER_POTION4, "Hunter potion", Skill.HERBLORE, 53, 120, CriticalItem.AVANTOE_POTION_UNF, ActivitySecondaries.HUNTER_POTION), - // Kwuarm - SUPER_STRENGTH(ItemID.SUPER_STRENGTH4, "Super strength", Skill.HERBLORE, 55, 125, CriticalItem.KWUARM_POTION_UNF, ActivitySecondaries.SUPER_STRENGTH), - // Snapdragon - SUPER_RESTORE(ItemID.SUPER_RESTORE4, "Super restore", Skill.HERBLORE, 63, 142.5, CriticalItem.SNAPDRAGON_POTION_UNF, ActivitySecondaries.SUPER_RESTORE), - SANFEW_SERUM(ItemID.SANFEW_SERUM4, "Sanfew serum", Skill.HERBLORE, 65, 160, CriticalItem.SNAPDRAGON_POTION_UNF, ActivitySecondaries.SANFEW_SERUM), - // Cadantine - SUPER_DEFENCE_POTION(ItemID.SUPER_DEFENCE4, "Super defence", Skill.HERBLORE, 66, 150, CriticalItem.CADANTINE_POTION_UNF, ActivitySecondaries.SUPER_DEFENCE_POTION), - // Lantadyme - ANTIFIRE_POTION(ItemID.ANTIFIRE_POTION4, "Anti-fire potion", Skill.HERBLORE, 69, 157.5, CriticalItem.LANTADYME_POTION_UNF, ActivitySecondaries.ANTIFIRE_POTION), - MAGIC_POTION(ItemID.MAGIC_POTION4, "Magic potion", Skill.HERBLORE, 76, 172.5, CriticalItem.LANTADYME_POTION_UNF, ActivitySecondaries.MAGIC_POTION), - // Dwarf Weed - RANGING_POTION(ItemID.RANGING_POTION4, "Ranging potion", Skill.HERBLORE, 72, 162.5, CriticalItem.DWARF_WEED_POTION_UNF, ActivitySecondaries.RANGING_POTION), - // Torstol - TORSTOL_POTION_UNF(ItemID.TORSTOL_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 78, 0, CriticalItem.TORSTOL, ActivitySecondaries.UNFINISHED_POTION), - SUPER_COMBAT_POTION(ItemID.SUPER_COMBAT_POTION4, "Super combat", Skill.HERBLORE, 90, 150, CriticalItem.TORSTOL, ActivitySecondaries.SUPER_COMBAT_POTION, true), - ANTIVENOM_PLUS(ItemID.ANTIVENOM4_12913, "Anti-venom+", Skill.HERBLORE, 94, 125, CriticalItem.TORSTOL, ActivitySecondaries.ANTIVENOM_PLUS, true), - - ZAMORAK_BREW(ItemID.ZAMORAK_BREW4, "Zamorak brew", Skill.HERBLORE, 78, 175, CriticalItem.TORSTOL_POTION_UNF, ActivitySecondaries.ZAMORAK_BREW), - - // Cleaning Grimy Herbs - CLEAN_GUAM(ItemID.GUAM_LEAF, "Clean guam", Skill.HERBLORE, 3, 2.5, CriticalItem.GRIMY_GUAM_LEAF), - CLEAN_MARRENTILL(ItemID.MARRENTILL, "Clean marrentill", Skill.HERBLORE, 5, 3.8, CriticalItem.GRIMY_MARRENTILL), - CLEAN_TARROMIN(ItemID.TARROMIN, "Clean tarromin", Skill.HERBLORE, 11, 5, CriticalItem.GRIMY_TARROMIN), - CLEAN_HARRALANDER(ItemID.HARRALANDER, "Clean harralander", Skill.HERBLORE, 20, 6.3, CriticalItem.GRIMY_HARRALANDER), - CLEAN_RANARR_WEED(ItemID.RANARR_WEED, "Clean ranarr weed", Skill.HERBLORE, 25, 7.5, CriticalItem.GRIMY_RANARR_WEED), - CLEAN_TOADFLAX(ItemID.TOADFLAX, "Clean toadflax", Skill.HERBLORE, 30, 8, CriticalItem.GRIMY_TOADFLAX), - CLEAN_IRIT_LEAF(ItemID.IRIT_LEAF, "Clean irit leaf", Skill.HERBLORE, 40, 8.8, CriticalItem.GRIMY_IRIT_LEAF), - CLEAN_AVANTOE(ItemID.AVANTOE, "Clean avantoe", Skill.HERBLORE, 48, 10, CriticalItem.GRIMY_AVANTOE), - CLEAN_KWUARM(ItemID.KWUARM, "Clean kwuarm", Skill.HERBLORE, 54, 11.3, CriticalItem.GRIMY_KWUARM), - CLEAN_SNAPDRAGON(ItemID.SNAPDRAGON, "Clean snapdragon", Skill.HERBLORE, 59, 11.8, CriticalItem.GRIMY_SNAPDRAGON), - CLEAN_CADANTINE(ItemID.CADANTINE, "Clean cadantine", Skill.HERBLORE, 65, 12.5, CriticalItem.GRIMY_CADANTINE), - CLEAN_LANTADYME(ItemID.LANTADYME, "Clean lantadyme", Skill.HERBLORE, 67, 13.1, CriticalItem.GRIMY_LANTADYME), - CLEAN_DWARF_WEED(ItemID.DWARF_WEED, "Clean dwarf weed", Skill.HERBLORE, 70, 13.8, CriticalItem.GRIMY_DWARF_WEED), - CLEAN_TORSTOL(ItemID.TORSTOL, "Clean torstol", Skill.HERBLORE, 75, 15, CriticalItem.GRIMY_TORSTOL), - - /** - * Construction Options - */ - PLANKS(ItemID.PLANK , "Normal Plank Products", Skill.CONSTRUCTION, 1, 29, CriticalItem.PLANK), - OAK_PLANKS(ItemID.OAK_PLANK, "Normal Oak Products", Skill.CONSTRUCTION, 1, 60, CriticalItem.OAK_PLANK), - TEAK_PLANKS(ItemID.TEAK_PLANK, "Normal Teak Products", Skill.CONSTRUCTION, 1, 90, CriticalItem.TEAK_PLANK), - MYTHICAL_CAPE(ItemID.MYTHICAL_CAPE, "Mythical Cape Rakes", Skill.CONSTRUCTION, 1, 123.33, CriticalItem.TEAK_PLANK), - MAHOGANY_PLANKS(ItemID.MAHOGANY_PLANK, "Normal Mahogany Products", Skill.CONSTRUCTION, 1, 140, CriticalItem.MAHOGANY_PLANK), - - /** - * Prayer Options - */ - BONES(ItemID.BONES, "Bones", Skill.PRAYER, 1, 4.5, CriticalItem.BONES), - WOLF_BONES(ItemID.WOLF_BONES, "Bones", Skill.PRAYER, 1, 4.5, CriticalItem.WOLF_BONES), - BURNT_BONES(ItemID.BURNT_BONES, "Bones", Skill.PRAYER, 1, 4.5, CriticalItem.BURNT_BONES), - MONKEY_BONES(ItemID.MONKEY_BONES, "Bones", Skill.PRAYER, 1, 5.0, CriticalItem.MONKEY_BONES), - BAT_BONES(ItemID.BAT_BONES, "Bones", Skill.PRAYER, 1, 5.3, CriticalItem.BAT_BONES), - JOGRE_BONES(ItemID.JOGRE_BONES, "Bones", Skill.PRAYER, 1, 15.0, CriticalItem.JOGRE_BONES), - BIG_BONES(ItemID.BIG_BONES, "Bones", Skill.PRAYER, 1, 15.0, CriticalItem.BIG_BONES), - ZOGRE_BONES(ItemID.ZOGRE_BONES, "Bones", Skill.PRAYER, 1, 22.5, CriticalItem.ZOGRE_BONES), - SHAIKAHAN_BONES(ItemID.SHAIKAHAN_BONES, "Bones", Skill.PRAYER, 1, 25.0, CriticalItem.SHAIKAHAN_BONES), - BABYDRAGON_BONES(ItemID.BABYDRAGON_BONES, "Bones", Skill.PRAYER, 1, 30.0, CriticalItem.BABYDRAGON_BONES), - WYVERN_BONES(ItemID.WYVERN_BONES, "Bones", Skill.PRAYER, 1, 72.0, CriticalItem.WYVERN_BONES), - DRAGON_BONES(ItemID.DRAGON_BONES, "Bones", Skill.PRAYER, 1, 72.0, CriticalItem.DRAGON_BONES), - FAYRG_BONES(ItemID.FAYRG_BONES, "Bones", Skill.PRAYER, 1, 84.0, CriticalItem.FAYRG_BONES), - LAVA_DRAGON_BONES(ItemID.LAVA_DRAGON_BONES, "Bones", Skill.PRAYER, 1, 85.0, CriticalItem.LAVA_DRAGON_BONES), - RAURG_BONES(ItemID.RAURG_BONES, "Bones", Skill.PRAYER, 1, 96.0, CriticalItem.RAURG_BONES), - DAGANNOTH_BONES(ItemID.DAGANNOTH_BONES, "Bones", Skill.PRAYER, 1, 125.0, CriticalItem.DAGANNOTH_BONES), - OURG_BONES(ItemID.OURG_BONES, "Bones", Skill.PRAYER, 1, 140.0, CriticalItem.OURG_BONES), - SUPERIOR_DRAGON_BONES(ItemID.SUPERIOR_DRAGON_BONES, "Bones", Skill.PRAYER, 1, 150.0, CriticalItem.SUPERIOR_DRAGON_BONES), - // Shade Remains (Pyre Logs) - LOAR_REMAINS(ItemID.LOAR_REMAINS, "Shades", Skill.PRAYER, 1, 33.0, CriticalItem.LOAR_REMAINS), - PHRIN_REMAINS(ItemID.PHRIN_REMAINS, "Shades", Skill.PRAYER, 1, 46.5, CriticalItem.PHRIN_REMAINS), - RIYL_REMAINS(ItemID.RIYL_REMAINS, "Shades", Skill.PRAYER, 1, 59.5, CriticalItem.RIYL_REMAINS), - ASYN_REMAINS(ItemID.ASYN_REMAINS, "Shades", Skill.PRAYER, 1, 82.5, CriticalItem.ASYN_REMAINS), - FIYR_REMAINS(ItemID.FIYR_REMAINS, "Shades", Skill.PRAYER, 1, 84.0, CriticalItem.FIYR_REMAINS), - // Ensouled Heads - ENSOULED_GOBLIN_HEAD(ItemID.ENSOULED_GOBLIN_HEAD_13448, "Ensouled Heads", Skill.PRAYER, 1, 130.0, CriticalItem.ENSOULED_GOBLIN_HEAD), - ENSOULED_MONKEY_HEAD(ItemID.ENSOULED_MONKEY_HEAD_13451, "Ensouled Heads", Skill.PRAYER, 1, 182.0, CriticalItem.ENSOULED_MONKEY_HEAD), - ENSOULED_IMP_HEAD(ItemID.ENSOULED_IMP_HEAD_13454, "Ensouled Heads", Skill.PRAYER, 1, 286.0, CriticalItem.ENSOULED_IMP_HEAD), - ENSOULED_MINOTAUR_HEAD(ItemID.ENSOULED_MINOTAUR_HEAD_13457, "Ensouled Heads", Skill.PRAYER, 1, 364.0, CriticalItem.ENSOULED_MINOTAUR_HEAD), - ENSOULED_SCORPION_HEAD(ItemID.ENSOULED_SCORPION_HEAD_13460, "Ensouled Heads", Skill.PRAYER, 1, 454.0, CriticalItem.ENSOULED_SCORPION_HEAD), - ENSOULED_BEAR_HEAD(ItemID.ENSOULED_BEAR_HEAD_13463, "Ensouled Heads", Skill.PRAYER, 1, 480.0, CriticalItem.ENSOULED_BEAR_HEAD), - ENSOULED_UNICORN_HEAD(ItemID.ENSOULED_UNICORN_HEAD_13466, "Ensouled Heads", Skill.PRAYER, 1, 494.0, CriticalItem.ENSOULED_UNICORN_HEAD), - ENSOULED_DOG_HEAD(ItemID.ENSOULED_DOG_HEAD_13469, "Ensouled Heads", Skill.PRAYER, 1, 520.0, CriticalItem.ENSOULED_DOG_HEAD), - ENSOULED_CHAOS_DRUID_HEAD(ItemID.ENSOULED_CHAOS_DRUID_HEAD_13472, "Ensouled Heads", Skill.PRAYER, 1, 584.0, CriticalItem.ENSOULED_CHAOS_DRUID_HEAD), - ENSOULED_GIANT_HEAD(ItemID.ENSOULED_GIANT_HEAD_13475, "Ensouled Heads", Skill.PRAYER, 1, 650.0, CriticalItem.ENSOULED_GIANT_HEAD), - ENSOULED_OGRE_HEAD(ItemID.ENSOULED_OGRE_HEAD_13478, "Ensouled Heads", Skill.PRAYER, 1, 716.0, CriticalItem.ENSOULED_OGRE_HEAD), - ENSOULED_ELF_HEAD(ItemID.ENSOULED_ELF_HEAD_13481, "Ensouled Heads", Skill.PRAYER, 1, 754.0, CriticalItem.ENSOULED_ELF_HEAD), - ENSOULED_TROLL_HEAD(ItemID.ENSOULED_TROLL_HEAD_13484, "Ensouled Heads", Skill.PRAYER, 1, 780.0, CriticalItem.ENSOULED_TROLL_HEAD), - ENSOULED_HORROR_HEAD(ItemID.ENSOULED_HORROR_HEAD_13487, "Ensouled Heads", Skill.PRAYER, 1, 832.0, CriticalItem.ENSOULED_HORROR_HEAD), - ENSOULED_KALPHITE_HEAD(ItemID.ENSOULED_KALPHITE_HEAD_13490, "Ensouled Heads", Skill.PRAYER, 1, 884.0, CriticalItem.ENSOULED_KALPHITE_HEAD), - ENSOULED_DAGANNOTH_HEAD(ItemID.ENSOULED_DAGANNOTH_HEAD_13493, "Ensouled Heads", Skill.PRAYER, 1, 936.0, CriticalItem.ENSOULED_DAGANNOTH_HEAD), - ENSOULED_BLOODVELD_HEAD(ItemID.ENSOULED_BLOODVELD_HEAD_13496, "Ensouled Heads", Skill.PRAYER, 1, 1040.0, CriticalItem.ENSOULED_BLOODVELD_HEAD), - ENSOULED_TZHAAR_HEAD(ItemID.ENSOULED_TZHAAR_HEAD_13499, "Ensouled Heads", Skill.PRAYER, 1, 1104.0, CriticalItem.ENSOULED_TZHAAR_HEAD), - ENSOULED_DEMON_HEAD(ItemID.ENSOULED_DEMON_HEAD_13502, "Ensouled Heads", Skill.PRAYER, 1, 1170.0, CriticalItem.ENSOULED_DEMON_HEAD), - ENSOULED_AVIANSIE_HEAD(ItemID.ENSOULED_AVIANSIE_HEAD_13505, "Ensouled Heads", Skill.PRAYER, 1, 1234.0, CriticalItem.ENSOULED_AVIANSIE_HEAD), - ENSOULED_ABYSSAL_HEAD(ItemID.ENSOULED_ABYSSAL_HEAD_13508, "Ensouled Heads", Skill.PRAYER, 1, 1300.0, CriticalItem.ENSOULED_ABYSSAL_HEAD), - ENSOULED_DRAGON_HEAD(ItemID.ENSOULED_DRAGON_HEAD_13511, "Ensouled Heads", Skill.PRAYER, 1, 1560.0, CriticalItem.ENSOULED_DRAGON_HEAD), - - /* - * Cooking Items - */ - RAW_HERRING(ItemID.RAW_HERRING, "Fish", Skill.COOKING, 5, 50.0, CriticalItem.RAW_HERRING), - RAW_MACKEREL(ItemID.RAW_MACKEREL, "Fish", Skill.COOKING, 10, 60.0, CriticalItem.RAW_MACKEREL), - RAW_TROUT(ItemID.RAW_TROUT, "Fish", Skill.COOKING, 15, 70.0, CriticalItem.RAW_TROUT), - RAW_COD(ItemID.RAW_COD, "Fish", Skill.COOKING, 18, 75.0, CriticalItem.RAW_COD), - RAW_PIKE(ItemID.RAW_PIKE, "Fish", Skill.COOKING, 20, 80.0, CriticalItem.RAW_PIKE), - RAW_SALMON(ItemID.RAW_SALMON, "Fish", Skill.COOKING, 25, 90.0, CriticalItem.RAW_SALMON), - RAW_TUNA(ItemID.RAW_TUNA, "Fish", Skill.COOKING, 30, 100.0, CriticalItem.RAW_TUNA), - RAW_KARAMBWAN(ItemID.RAW_KARAMBWAN, "Fish", Skill.COOKING, 30, 190.0, CriticalItem.RAW_KARAMBWAN), - RAW_LOBSTER(ItemID.RAW_LOBSTER, "Fish", Skill.COOKING, 40, 120.0, CriticalItem.RAW_LOBSTER), - RAW_BASS(ItemID.RAW_BASS, "Fish", Skill.COOKING, 43, 130.0, CriticalItem.RAW_BASS), - RAW_SWORDFISH(ItemID.RAW_SWORDFISH, "Fish", Skill.COOKING, 45, 140.0, CriticalItem.RAW_SWORDFISH), - RAW_MONKFISH(ItemID.RAW_MONKFISH, "Fish", Skill.COOKING, 62, 150.0, CriticalItem.RAW_MONKFISH), - RAW_SHARK(ItemID.RAW_SHARK, "Fish", Skill.COOKING, 80, 210.0, CriticalItem.RAW_SHARK), - RAW_SEA_TURTLE(ItemID.RAW_SEA_TURTLE, "Fish", Skill.COOKING, 82, 211.3, CriticalItem.RAW_SEA_TURTLE), - RAW_ANGLERFISH(ItemID.RAW_ANGLERFISH, "Fish", Skill.COOKING, 84, 230.0, CriticalItem.RAW_ANGLERFISH), - RAW_DARK_CRAB(ItemID.RAW_DARK_CRAB, "Fish", Skill.COOKING, 90, 215.0, CriticalItem.RAW_DARK_CRAB), - RAW_MANTA_RAY(ItemID.RAW_MANTA_RAY, "Fish", Skill.COOKING, 91, 216.2, CriticalItem.RAW_MANTA_RAY), - - WINE(ItemID.JUG_OF_WINE, "Other", Skill.COOKING, 35, 200, CriticalItem.GRAPES, ActivitySecondaries.JUG_OF_WATER), - - /* - * Crafting Items - */ - // Spinning - BALL_OF_WOOL(ItemID.WOOL, "Misc", Skill.CRAFTING, 1, 2.5, CriticalItem.WOOL), - BOW_STRING(ItemID.BOW_STRING, "Misc", Skill.CRAFTING, 1, 15, CriticalItem.FLAX), - // Glass Blowing - BEER_GLASS(ItemID.BEER_GLASS, "Beer Glass", Skill.CRAFTING, 1, 17.5, CriticalItem.MOLTEN_GLASS), - CANDLE_LANTERN(ItemID.CANDLE_LANTERN, "Candle Lantern", Skill.CRAFTING, 4, 19, CriticalItem.MOLTEN_GLASS), - OIL_LAMP(ItemID.OIL_LAMP, "Oil Lamp", Skill.CRAFTING, 12, 25, CriticalItem.MOLTEN_GLASS), - VIAL(ItemID.VIAL, "Vial", Skill.CRAFTING, 33, 35, CriticalItem.MOLTEN_GLASS), - EMPTY_FISHBOWL(ItemID.EMPTY_FISHBOWL, "Empty fishbowl", Skill.CRAFTING, 42, 42.5, CriticalItem.MOLTEN_GLASS), - UNPOWERED_ORB(ItemID.UNPOWERED_ORB, "Unpowered orb", Skill.CRAFTING, 46, 52.5, CriticalItem.MOLTEN_GLASS), - LANTERN_LENS(ItemID.LANTERN_LENS, "Lantern lens", Skill.CRAFTING, 49, 55, CriticalItem.MOLTEN_GLASS), - LIGHT_ORB(ItemID.LIGHT_ORB, "Light orb", Skill.CRAFTING, 87, 70, CriticalItem.MOLTEN_GLASS), - // D'hide/Dragon Leather - GREEN_DRAGON_LEATHER(ItemID.GREEN_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 57, 62.0, CriticalItem.GREEN_DRAGON_LEATHER), - BLUE_DRAGON_LEATHER(ItemID.BLUE_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 66, 70.0, CriticalItem.BLUE_DRAGON_LEATHER), - RED_DRAGON_LEATHER(ItemID.RED_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 73, 78.0, CriticalItem.RED_DRAGON_LEATHER), - BLACK_DRAGON_LEATHER(ItemID.BLACK_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 79, 86.0, CriticalItem.BLACK_DRAGON_LEATHER), - // Uncut Gems - UNCUT_OPAL(ItemID.UNCUT_OPAL, "Gems", Skill.CRAFTING, 1, 15.0, CriticalItem.UNCUT_OPAL), - UNCUT_JADE(ItemID.UNCUT_JADE, "Gems", Skill.CRAFTING, 13, 20.0, CriticalItem.UNCUT_JADE), - UNCUT_RED_TOPAZ(ItemID.UNCUT_RED_TOPAZ, "Gems", Skill.CRAFTING, 16, 25.0, CriticalItem.UNCUT_RED_TOPAZ), - UNCUT_SAPPHIRE(ItemID.UNCUT_SAPPHIRE, "Gems", Skill.CRAFTING, 20, 50.0, CriticalItem.UNCUT_SAPPHIRE), - UNCUT_EMERALD(ItemID.UNCUT_EMERALD, "Gems", Skill.CRAFTING, 27, 67.5, CriticalItem.UNCUT_EMERALD), - UNCUT_RUBY(ItemID.UNCUT_RUBY, "Gems", Skill.CRAFTING, 34, 85, CriticalItem.UNCUT_RUBY), - UNCUT_DIAMOND(ItemID.UNCUT_DIAMOND, "Gems", Skill.CRAFTING, 43, 107.5, CriticalItem.UNCUT_DIAMOND), - UNCUT_DRAGONSTONE(ItemID.UNCUT_DRAGONSTONE, "Gems", Skill.CRAFTING, 55, 137.5, CriticalItem.UNCUT_DRAGONSTONE), - UNCUT_ONYX(ItemID.UNCUT_ONYX, "Gems", Skill.CRAFTING, 67, 167.5, CriticalItem.UNCUT_ONYX), - UNCUT_ZENYTE(ItemID.UNCUT_ZENYTE, "Gems", Skill.CRAFTING, 89, 200.0, CriticalItem.UNCUT_ZENYTE), - // Silver Jewelery - OPAL_RING(ItemID.OPAL_RING, "Opal ring", Skill.CRAFTING, 1 , 10, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), - OPAL_NECKLACE(ItemID.OPAL_NECKLACE, "Opal necklace", Skill.CRAFTING, 16 , 35, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), - OPAL_BRACELET(ItemID.OPAL_BRACELET, "Opal bracelet", Skill.CRAFTING, 22 , 45, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), - OPAL_AMULET(ItemID.OPAL_AMULET, "Opal amulet", Skill.CRAFTING, 27 , 55, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), - JADE_RING(ItemID.JADE_RING, "Jade ring", Skill.CRAFTING, 13 , 32, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), - JADE_NECKLACE(ItemID.JADE_NECKLACE, "Jade necklace", Skill.CRAFTING, 25 , 54, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), - JADE_BRACELET(ItemID.JADE_BRACELET, "Jade bracelet", Skill.CRAFTING, 29 , 60, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), - JADE_AMULET(ItemID.JADE_AMULET, "Jade amulet", Skill.CRAFTING, 34 , 70, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), - TOPAZ_RING(ItemID.TOPAZ_RING, "Topaz ring", Skill.CRAFTING, 16 , 35, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), - TOPAZ_NECKLACE(ItemID.TOPAZ_NECKLACE, "Topaz necklace", Skill.CRAFTING, 32 , 70, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), - TOPAZ_BRACELET(ItemID.TOPAZ_BRACELET, "Topaz bracelet", Skill.CRAFTING, 38 , 75, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), - TOPAZ_AMULET(ItemID.TOPAZ_AMULET, "Topaz amulet", Skill.CRAFTING, 45 , 80, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), - // Gold Jewelery - SAPPHIRE_RING(ItemID.SAPPHIRE_RING, "Sapphire ring", Skill.CRAFTING, 20 , 40, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), - SAPPHIRE_NECKLACE(ItemID.SAPPHIRE_NECKLACE, "Sapphire necklace", Skill.CRAFTING, 22 , 55, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), - SAPPHIRE_BRACELET(ItemID.SAPPHIRE_BRACELET, "Sapphire bracelet", Skill.CRAFTING, 23 , 60, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), - SAPPHIRE_AMULET(ItemID.SAPPHIRE_AMULET, "Sapphire amulet", Skill.CRAFTING, 24 , 65, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), - EMERALD_RING(ItemID.EMERALD_RING, "Emerald ring", Skill.CRAFTING, 27 , 55, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), - EMERALD_NECKLACE(ItemID.EMERALD_NECKLACE, "Emerald necklace", Skill.CRAFTING, 29 , 60, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), - EMERALD_BRACELET(ItemID.EMERALD_BRACELET, "Emerald bracelet", Skill.CRAFTING, 30 , 65, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), - EMERALD_AMULET(ItemID.EMERALD_AMULET, "Emerald amulet", Skill.CRAFTING, 31 , 70, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), - RUBY_RING(ItemID.RUBY_RING, "Ruby ring", Skill.CRAFTING, 34 , 70, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), - RUBY_NECKLACE(ItemID.RUBY_NECKLACE, "Ruby necklace", Skill.CRAFTING, 40 , 75, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), - RUBY_BRACELET(ItemID.RUBY_BRACELET, "Ruby bracelet", Skill.CRAFTING, 42 , 80, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), - RUBY_AMULET(ItemID.RUBY_AMULET, "Ruby amulet", Skill.CRAFTING, 50 , 85, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), - DIAMOND_RING(ItemID.DIAMOND_RING, "Diamond ring", Skill.CRAFTING, 43 , 85, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), - DIAMOND_NECKLACE(ItemID.DIAMOND_NECKLACE, "Diamond necklace", Skill.CRAFTING, 56 , 90, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), - DIAMOND_BRACELET(ItemID.DIAMOND_BRACELET, "Diamond bracelet", Skill.CRAFTING, 58 , 95, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), - DIAMOND_AMULET(ItemID.DIAMOND_AMULET, "Diamond amulet", Skill.CRAFTING, 70 , 100, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), - DRAGONSTONE_RING(ItemID.DRAGONSTONE_RING, "Dragonstone ring", Skill.CRAFTING, 55 , 100, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), - DRAGON_NECKLACE(ItemID.DRAGON_NECKLACE, "Dragon necklace", Skill.CRAFTING, 72 , 105, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), - DRAGONSTONE_BRACELET(ItemID.DRAGONSTONE_BRACELET, "Dragonstone bracelet", Skill.CRAFTING, 74 , 110, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), - DRAGONSTONE_AMULET(ItemID.DRAGONSTONE_AMULET, "Dragonstone amulet", Skill.CRAFTING, 80 , 150, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), - ONYX_RING(ItemID.ONYX_RING, "Onyx ring", Skill.CRAFTING, 67 , 115, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), - ONYX_NECKLACE(ItemID.ONYX_NECKLACE, "Onyx necklace", Skill.CRAFTING, 82 , 120, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), - REGEN_BRACELET(ItemID.REGEN_BRACELET, "Regen bracelet", Skill.CRAFTING, 84 , 125, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), - ONYX_AMULET(ItemID.ONYX_AMULET, "Onyx amulet", Skill.CRAFTING, 90 , 165, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), - ZENYTE_RING(ItemID.ZENYTE_RING, "Zenyte ring", Skill.CRAFTING, 89 , 150, CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), - ZENYTE_NECKLACE(ItemID.ZENYTE_NECKLACE, "Zenyte necklace", Skill.CRAFTING, 92 , 165, CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), - ZENYTE_BRACELET(ItemID.ZENYTE_BRACELET, "Zenyte bracelet", Skill.CRAFTING, 95 , 180, CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), - ZENYTE_AMULET(ItemID.ZENYTE_AMULET, "Zenyte amulet", Skill.CRAFTING, 98 , 200 , CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), - // Battle Staves - WATER_BATTLESTAFF(ItemID.WATER_BATTLESTAFF, "Water battlestaff", Skill.CRAFTING, 54, 100, CriticalItem.BATTLESTAFF, ActivitySecondaries.WATER_ORB), - EARTH_BATTLESTAFF(ItemID.EARTH_BATTLESTAFF, "Earth battlestaff", Skill.CRAFTING, 58, 112.5, CriticalItem.BATTLESTAFF, ActivitySecondaries.EARTH_ORB), - FIRE_BATTLESTAFF(ItemID.FIRE_BATTLESTAFF, "Fire battlestaff", Skill.CRAFTING, 62, 125, CriticalItem.BATTLESTAFF, ActivitySecondaries.FIRE_ORB), - AIR_BATTLESTAFF(ItemID.AIR_BATTLESTAFF, "Air battlestaff", Skill.CRAFTING, 66, 137.5, CriticalItem.BATTLESTAFF, ActivitySecondaries.AIR_ORB), - - /* - * Smithing Items - */ - - // Smelting ores (Furnace) - IRON_ORE(ItemID.IRON_BAR, "Iron Bars", Skill.SMITHING, 15, 12.5, CriticalItem.IRON_ORE, ActivitySecondaries.COAL_ORE), - STEEL_ORE(ItemID.STEEL_BAR, "Steel Bars", Skill.SMITHING, 30, 17.5, CriticalItem.IRON_ORE, ActivitySecondaries.COAL_ORE_2), - SILVER_ORE(ItemID.SILVER_ORE, "Bar", Skill.SMITHING, 20, 13.67, CriticalItem.SILVER_ORE), - GOLD_ORE(ItemID.GOLD_BAR, "Regular exp", Skill.SMITHING, 40, 22.5, CriticalItem.GOLD_ORE), - GOLD_ORE_GAUNTLETS(ItemID.GOLDSMITH_GAUNTLETS, "Goldsmith Gauntlets", Skill.SMITHING, 40, 56.2, CriticalItem.GOLD_ORE), - MITHRIL_ORE(ItemID.MITHRIL_ORE, "Bar", Skill.SMITHING, 50, 30, CriticalItem.MITHRIL_ORE, ActivitySecondaries.COAL_ORE_4), - ADAMANTITE_ORE(ItemID.ADAMANTITE_ORE, "Bar", Skill.SMITHING, 70, 37.5, CriticalItem.ADAMANTITE_ORE, ActivitySecondaries.COAL_ORE_6), - RUNITE_ORE(ItemID.RUNITE_ORE, "Bar", Skill.SMITHING, 85, 50, CriticalItem.RUNITE_ORE, ActivitySecondaries.COAL_ORE_8), - - // Smelting bars (Anvil) - BRONZE_BAR(ItemID.BRONZE_BAR, "Bars", Skill.SMITHING, 1, 12.5, CriticalItem.BRONZE_BAR), - IRON_BAR(ItemID.IRON_BAR, "Bars", Skill.SMITHING, 15, 25.0, CriticalItem.IRON_BAR), - STEEL_BAR(ItemID.STEEL_BAR, "Steel Products", Skill.SMITHING, 30, 37.5, CriticalItem.STEEL_BAR), - CANNONBALLS(ItemID.CANNONBALL, "Cannonballs", Skill.SMITHING, 35, 25.5, CriticalItem.STEEL_BAR), - MITHRIL_BAR(ItemID.MITHRIL_BAR, "Bars", Skill.SMITHING, 50, 50.0, CriticalItem.MITHRIL_BAR), - ADAMANTITE_BAR(ItemID.ADAMANTITE_BAR, "Bars", Skill.SMITHING, 70, 62.5, CriticalItem.ADAMANTITE_BAR), - RUNITE_BAR(ItemID.RUNITE_BAR, "Bars", Skill.SMITHING, 85, 75.0, CriticalItem.RUNITE_BAR), - - /** - * Farming Items - */ - ACORN(ItemID.ACORN, "Seeds", Skill.FARMING, 15, 481.3, CriticalItem.ACORN), - WILLOW_SEED(ItemID.WILLOW_SEED, "Seeds", Skill.FARMING, 30, 1481.5, CriticalItem.WILLOW_SEED), - MAPLE_SEED(ItemID.MAPLE_SEED, "Seeds", Skill.FARMING, 45, 3448.4, CriticalItem.MAPLE_SEED), - YEW_SEED(ItemID.YEW_SEED, "Seeds", Skill.FARMING, 60, 7150.9, CriticalItem.YEW_SEED), - MAGIC_SEED(ItemID.MAGIC_SEED, "Seeds", Skill.FARMING, 75, 13913.8, CriticalItem.MAGIC_SEED), - APPLE_TREE_SEED(ItemID.APPLE_TREE_SEED, "Seeds", Skill.FARMING, 27, 1272.5, CriticalItem.APPLE_TREE_SEED), - BANANA_TREE_SEED(ItemID.BANANA_TREE_SEED, "Seeds", Skill.FARMING, 33, 1841.5, CriticalItem.BANANA_TREE_SEED), - ORANGE_TREE_SEED(ItemID.ORANGE_TREE_SEED, "Seeds", Skill.FARMING, 39, 2586.7, CriticalItem.ORANGE_TREE_SEED), - CURRY_TREE_SEED(ItemID.CURRY_TREE_SEED, "Seeds", Skill.FARMING, 42, 3036.9, CriticalItem.CURRY_TREE_SEED), - PINEAPPLE_SEED(ItemID.PINEAPPLE_SEED, "Seeds", Skill.FARMING, 51, 4791.7, CriticalItem.PINEAPPLE_SEED), - PAPAYA_TREE_SEED(ItemID.PAPAYA_TREE_SEED, "Seeds", Skill.FARMING, 57, 6380.4, CriticalItem.PAPAYA_TREE_SEED), - PALM_TREE_SEED(ItemID.PALM_TREE_SEED, "Seeds", Skill.FARMING, 68, 10509.6, CriticalItem.PALM_TREE_SEED), - CALQUAT_TREE_SEED(ItemID.CALQUAT_TREE_SEED, "Seeds", Skill.FARMING, 72, 12516.5, CriticalItem.CALQUAT_TREE_SEED), - TEAK_SEED(ItemID.TEAK_SEED, "Seeds", Skill.FARMING, 35, 7325, CriticalItem.TEAK_SEED), - MAHOGANY_SEED(ItemID.MAHOGANY_SEED, "Seeds", Skill.FARMING, 55, 15783, CriticalItem.MAHOGANY_SEED), - SPIRIT_SEED(ItemID.SPIRIT_SEED, "Seeds", Skill.FARMING, 83, 19500, CriticalItem.SPIRIT_SEED), - ; - - private final int icon; - private final String name; - private final Skill skill; - private final int level; - private final double xp; - private final SecondaryItem[] secondaries; - private final CriticalItem criticalItem; - private final boolean preventLinked; - - Activity(int Icon, String name, Skill skill, int level, double xp, CriticalItem criticalItem) - { - this.icon = Icon; - this.name = name; - this.skill = skill; - this.level = level; - this.xp = xp; - this.criticalItem = criticalItem; - this.secondaries = new SecondaryItem[0]; - this.preventLinked = false; - } - - Activity(int Icon, String name, Skill skill, int level, double xp, CriticalItem criticalItem, ActivitySecondaries secondaries) - { - this.icon = Icon; - this.name = name; - this.skill = skill; - this.level = level; - this.xp = xp; - this.criticalItem = criticalItem; - this.secondaries = secondaries == null ? new SecondaryItem[0] : secondaries.getItems(); - this.preventLinked = false; - } - - Activity(int Icon, String name, Skill skill, int level, double xp, CriticalItem criticalItem, ActivitySecondaries secondaries, boolean preventLinked) - { - this.icon = Icon; - this.name = name; - this.skill = skill; - this.level = level; - this.xp = xp; - this.criticalItem = criticalItem; - this.secondaries = secondaries == null ? new SecondaryItem[0] : secondaries.getItems(); - this.preventLinked = preventLinked; - } - - // Builds a Map to reduce looping frequency - private static Map> buildItemMap() - { - Map> map = new HashMap<>(); - for (Activity item : values()) - { - map.computeIfAbsent(item.getCriticalItem(), e -> new ArrayList()).add(item); - } - - return map; - } - private static final Map> byCriticalItem = buildItemMap(); - public static ArrayList getByCriticalItem(CriticalItem item) - { - - return byCriticalItem.getOrDefault(item, new ArrayList<>()); - } - - /** - * Get all Activities for this CriticalItem - * @param item CriticalItem to check for - * @param limitLevel Level to check Activitiy requirements against. -1 or 0 value disables limits - * @return an empty list if no activities - */ - public static ArrayList getByCriticalItem(CriticalItem item, int limitLevel) - { - ArrayList activities = getByCriticalItem(item); - ArrayList l = new ArrayList<>(); - if (limitLevel <= 0) - { - return l; - } - - for (Activity a : activities) - { - if (!(a.getLevel() > limitLevel)) - { - l.add(a); - } - } - - return l; - } -} +/* + * 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.plugins.skillcalculator.banked.beans; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import net.runelite.api.ItemID; +import net.runelite.api.Skill; +import net.runelite.client.plugins.skillcalculator.banked.CriticalItem; + +@Getter +public enum Activity +{ + /** + * Herblore Activities + */ + // Creating Potions + // Guam + GUAM_POTION_UNF(ItemID.GUAM_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.GUAM_LEAF, ActivitySecondaries.UNFINISHED_POTION), + GUAM_TAR(ItemID.GUAM_TAR, "Guam tar", Skill.HERBLORE, 19, 30, CriticalItem.GUAM_LEAF, ActivitySecondaries.SWAMP_TAR, true), + + ATTACK_POTION(ItemID.ATTACK_POTION4, "Attack Potion", Skill.HERBLORE, 3, 25, CriticalItem.GUAM_LEAF_POTION_UNF, ActivitySecondaries.ATTACK_POTION), + // Marrentil + MARRENTILL_POTION_UNF(ItemID.MARRENTILL_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.MARRENTILL, ActivitySecondaries.UNFINISHED_POTION), + MARRENTILL_TAR(ItemID.MARRENTILL_TAR, "Marrentill tar", Skill.HERBLORE, 31, 42.5, CriticalItem.MARRENTILL, ActivitySecondaries.SWAMP_TAR, true), + + ANTIPOISON(ItemID.ANTIPOISON4, "Antipoison", Skill.HERBLORE, 5, 37.5, CriticalItem.MARRENTILL_POTION_UNF, ActivitySecondaries.ANTIPOISON), + // Tarromin + TARROMIN_POTION_UNF(ItemID.TARROMIN_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.TARROMIN, ActivitySecondaries.UNFINISHED_POTION), + TARROMIN_TAR(ItemID.TARROMIN_TAR, "Tarromin tar", Skill.HERBLORE, 39, 55, CriticalItem.TARROMIN, ActivitySecondaries.SWAMP_TAR, true), + + STRENGTH_POTION(ItemID.STRENGTH_POTION4, "Strength potion", Skill.HERBLORE, 12, 50, CriticalItem.TARROMIN_POTION_UNF, ActivitySecondaries.STRENGTH_POTION), + SERUM_207(ItemID.SERUM_207_4, "Serum 207", Skill.HERBLORE, 15, 50, CriticalItem.TARROMIN_POTION_UNF, ActivitySecondaries.SERUM_207), + // Harralander + HARRALANDER_POTION_UNF(ItemID.HARRALANDER_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 1, 0, CriticalItem.HARRALANDER, ActivitySecondaries.UNFINISHED_POTION), + HARRALANDER_TAR(ItemID.HARRALANDER_TAR, "Harralander tar", Skill.HERBLORE, 44, 72.5, CriticalItem.HARRALANDER, ActivitySecondaries.SWAMP_TAR, true), + + COMPOST_POTION(ItemID.COMPOST_POTION4, "Compost potion", Skill.HERBLORE, 21, 60, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.COMPOST_POTION), + RESTORE_POTION(ItemID.RESTORE_POTION4, "Restore potion", Skill.HERBLORE, 22, 62.5, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.RESTORE_POTION), + ENERGY_POTION(ItemID.ENERGY_POTION4, "Energy potion", Skill.HERBLORE, 26, 67.5, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.ENERGY_POTION), + COMBAT_POTION(ItemID.COMBAT_POTION4, "Combat potion", Skill.HERBLORE, 36, 84, CriticalItem.HARRALANDER_POTION_UNF, ActivitySecondaries.COMBAT_POTION), + // Ranarr Weed + DEFENCE_POTION(ItemID.DEFENCE_POTION4, "Defence potion", Skill.HERBLORE, 30, 75, CriticalItem.RANARR_POTION_UNF, ActivitySecondaries.DEFENCE_POTION), + PRAYER_POTION(ItemID.PRAYER_POTION4, "Prayer potion", Skill.HERBLORE, 38, 87.5, CriticalItem.RANARR_POTION_UNF, ActivitySecondaries.PRAYER_POTION), + // Toadflax + AGILITY_POTION(ItemID.AGILITY_POTION4, "Agility potion", Skill.HERBLORE, 34, 80, CriticalItem.TOADFLAX_POTION_UNF, ActivitySecondaries.AGILITY_POTION), + SARADOMIN_BREW(ItemID.SARADOMIN_BREW4, "Saradomin brew", Skill.HERBLORE, 81, 180, CriticalItem.TOADFLAX_POTION_UNF, ActivitySecondaries.SARADOMIN_BREW), + // Irit + SUPER_ATTACK(ItemID.SUPER_ATTACK4, "Super attack", Skill.HERBLORE, 45, 100, CriticalItem.IRIT_POTION_UNF, ActivitySecondaries.SUPER_ATTACK), + SUPERANTIPOISON(ItemID.SUPERANTIPOISON4, "Superantipoison", Skill.HERBLORE, 48, 106.3, CriticalItem.IRIT_POTION_UNF, ActivitySecondaries.SUPERANTIPOISON), + // Avantoe + FISHING_POTION(ItemID.FISHING_POTION4, "Fishing potion", Skill.HERBLORE, 50, 112.5, CriticalItem.AVANTOE_POTION_UNF, ActivitySecondaries.FISHING_POTION), + SUPER_ENERGY_POTION(ItemID.SUPER_ENERGY3_20549, "Super energy potion", Skill.HERBLORE, 52, 117.5, CriticalItem.AVANTOE_POTION_UNF, ActivitySecondaries.SUPER_ENERGY_POTION), + HUNTER_POTION(ItemID.HUNTER_POTION4, "Hunter potion", Skill.HERBLORE, 53, 120, CriticalItem.AVANTOE_POTION_UNF, ActivitySecondaries.HUNTER_POTION), + // Kwuarm + SUPER_STRENGTH(ItemID.SUPER_STRENGTH4, "Super strength", Skill.HERBLORE, 55, 125, CriticalItem.KWUARM_POTION_UNF, ActivitySecondaries.SUPER_STRENGTH), + // Snapdragon + SUPER_RESTORE(ItemID.SUPER_RESTORE4, "Super restore", Skill.HERBLORE, 63, 142.5, CriticalItem.SNAPDRAGON_POTION_UNF, ActivitySecondaries.SUPER_RESTORE), + SANFEW_SERUM(ItemID.SANFEW_SERUM4, "Sanfew serum", Skill.HERBLORE, 65, 160, CriticalItem.SNAPDRAGON_POTION_UNF, ActivitySecondaries.SANFEW_SERUM), + // Cadantine + SUPER_DEFENCE_POTION(ItemID.SUPER_DEFENCE4, "Super defence", Skill.HERBLORE, 66, 150, CriticalItem.CADANTINE_POTION_UNF, ActivitySecondaries.SUPER_DEFENCE_POTION), + // Lantadyme + ANTIFIRE_POTION(ItemID.ANTIFIRE_POTION4, "Anti-fire potion", Skill.HERBLORE, 69, 157.5, CriticalItem.LANTADYME_POTION_UNF, ActivitySecondaries.ANTIFIRE_POTION), + MAGIC_POTION(ItemID.MAGIC_POTION4, "Magic potion", Skill.HERBLORE, 76, 172.5, CriticalItem.LANTADYME_POTION_UNF, ActivitySecondaries.MAGIC_POTION), + // Dwarf Weed + RANGING_POTION(ItemID.RANGING_POTION4, "Ranging potion", Skill.HERBLORE, 72, 162.5, CriticalItem.DWARF_WEED_POTION_UNF, ActivitySecondaries.RANGING_POTION), + // Torstol + TORSTOL_POTION_UNF(ItemID.TORSTOL_POTION_UNF, "Unfinished Potion", Skill.HERBLORE, 78, 0, CriticalItem.TORSTOL, ActivitySecondaries.UNFINISHED_POTION), + SUPER_COMBAT_POTION(ItemID.SUPER_COMBAT_POTION4, "Super combat", Skill.HERBLORE, 90, 150, CriticalItem.TORSTOL, ActivitySecondaries.SUPER_COMBAT_POTION, true), + ANTIVENOM_PLUS(ItemID.ANTIVENOM4_12913, "Anti-venom+", Skill.HERBLORE, 94, 125, CriticalItem.TORSTOL, ActivitySecondaries.ANTIVENOM_PLUS, true), + + ZAMORAK_BREW(ItemID.ZAMORAK_BREW4, "Zamorak brew", Skill.HERBLORE, 78, 175, CriticalItem.TORSTOL_POTION_UNF, ActivitySecondaries.ZAMORAK_BREW), + + // Cleaning Grimy Herbs + CLEAN_GUAM(ItemID.GUAM_LEAF, "Clean guam", Skill.HERBLORE, 3, 2.5, CriticalItem.GRIMY_GUAM_LEAF), + CLEAN_MARRENTILL(ItemID.MARRENTILL, "Clean marrentill", Skill.HERBLORE, 5, 3.8, CriticalItem.GRIMY_MARRENTILL), + CLEAN_TARROMIN(ItemID.TARROMIN, "Clean tarromin", Skill.HERBLORE, 11, 5, CriticalItem.GRIMY_TARROMIN), + CLEAN_HARRALANDER(ItemID.HARRALANDER, "Clean harralander", Skill.HERBLORE, 20, 6.3, CriticalItem.GRIMY_HARRALANDER), + CLEAN_RANARR_WEED(ItemID.RANARR_WEED, "Clean ranarr weed", Skill.HERBLORE, 25, 7.5, CriticalItem.GRIMY_RANARR_WEED), + CLEAN_TOADFLAX(ItemID.TOADFLAX, "Clean toadflax", Skill.HERBLORE, 30, 8, CriticalItem.GRIMY_TOADFLAX), + CLEAN_IRIT_LEAF(ItemID.IRIT_LEAF, "Clean irit leaf", Skill.HERBLORE, 40, 8.8, CriticalItem.GRIMY_IRIT_LEAF), + CLEAN_AVANTOE(ItemID.AVANTOE, "Clean avantoe", Skill.HERBLORE, 48, 10, CriticalItem.GRIMY_AVANTOE), + CLEAN_KWUARM(ItemID.KWUARM, "Clean kwuarm", Skill.HERBLORE, 54, 11.3, CriticalItem.GRIMY_KWUARM), + CLEAN_SNAPDRAGON(ItemID.SNAPDRAGON, "Clean snapdragon", Skill.HERBLORE, 59, 11.8, CriticalItem.GRIMY_SNAPDRAGON), + CLEAN_CADANTINE(ItemID.CADANTINE, "Clean cadantine", Skill.HERBLORE, 65, 12.5, CriticalItem.GRIMY_CADANTINE), + CLEAN_LANTADYME(ItemID.LANTADYME, "Clean lantadyme", Skill.HERBLORE, 67, 13.1, CriticalItem.GRIMY_LANTADYME), + CLEAN_DWARF_WEED(ItemID.DWARF_WEED, "Clean dwarf weed", Skill.HERBLORE, 70, 13.8, CriticalItem.GRIMY_DWARF_WEED), + CLEAN_TORSTOL(ItemID.TORSTOL, "Clean torstol", Skill.HERBLORE, 75, 15, CriticalItem.GRIMY_TORSTOL), + + /** + * Construction Options + */ + PLANKS(ItemID.PLANK, "Normal Plank Products", Skill.CONSTRUCTION, 1, 29, CriticalItem.PLANK), + OAK_PLANKS(ItemID.OAK_PLANK, "Normal Oak Products", Skill.CONSTRUCTION, 1, 60, CriticalItem.OAK_PLANK), + TEAK_PLANKS(ItemID.TEAK_PLANK, "Normal Teak Products", Skill.CONSTRUCTION, 1, 90, CriticalItem.TEAK_PLANK), + MYTHICAL_CAPE(ItemID.MYTHICAL_CAPE, "Mythical Cape Rakes", Skill.CONSTRUCTION, 1, 123.33, CriticalItem.TEAK_PLANK), + MAHOGANY_PLANKS(ItemID.MAHOGANY_PLANK, "Normal Mahogany Products", Skill.CONSTRUCTION, 1, 140, CriticalItem.MAHOGANY_PLANK), + + /** + * Prayer Options + */ + BONES(ItemID.BONES, "Bones", Skill.PRAYER, 1, 4.5, CriticalItem.BONES), + WOLF_BONES(ItemID.WOLF_BONES, "Bones", Skill.PRAYER, 1, 4.5, CriticalItem.WOLF_BONES), + BURNT_BONES(ItemID.BURNT_BONES, "Bones", Skill.PRAYER, 1, 4.5, CriticalItem.BURNT_BONES), + MONKEY_BONES(ItemID.MONKEY_BONES, "Bones", Skill.PRAYER, 1, 5.0, CriticalItem.MONKEY_BONES), + BAT_BONES(ItemID.BAT_BONES, "Bones", Skill.PRAYER, 1, 5.3, CriticalItem.BAT_BONES), + JOGRE_BONES(ItemID.JOGRE_BONES, "Bones", Skill.PRAYER, 1, 15.0, CriticalItem.JOGRE_BONES), + BIG_BONES(ItemID.BIG_BONES, "Bones", Skill.PRAYER, 1, 15.0, CriticalItem.BIG_BONES), + ZOGRE_BONES(ItemID.ZOGRE_BONES, "Bones", Skill.PRAYER, 1, 22.5, CriticalItem.ZOGRE_BONES), + SHAIKAHAN_BONES(ItemID.SHAIKAHAN_BONES, "Bones", Skill.PRAYER, 1, 25.0, CriticalItem.SHAIKAHAN_BONES), + BABYDRAGON_BONES(ItemID.BABYDRAGON_BONES, "Bones", Skill.PRAYER, 1, 30.0, CriticalItem.BABYDRAGON_BONES), + WYVERN_BONES(ItemID.WYVERN_BONES, "Bones", Skill.PRAYER, 1, 72.0, CriticalItem.WYVERN_BONES), + DRAGON_BONES(ItemID.DRAGON_BONES, "Bones", Skill.PRAYER, 1, 72.0, CriticalItem.DRAGON_BONES), + FAYRG_BONES(ItemID.FAYRG_BONES, "Bones", Skill.PRAYER, 1, 84.0, CriticalItem.FAYRG_BONES), + LAVA_DRAGON_BONES(ItemID.LAVA_DRAGON_BONES, "Bones", Skill.PRAYER, 1, 85.0, CriticalItem.LAVA_DRAGON_BONES), + RAURG_BONES(ItemID.RAURG_BONES, "Bones", Skill.PRAYER, 1, 96.0, CriticalItem.RAURG_BONES), + DAGANNOTH_BONES(ItemID.DAGANNOTH_BONES, "Bones", Skill.PRAYER, 1, 125.0, CriticalItem.DAGANNOTH_BONES), + OURG_BONES(ItemID.OURG_BONES, "Bones", Skill.PRAYER, 1, 140.0, CriticalItem.OURG_BONES), + SUPERIOR_DRAGON_BONES(ItemID.SUPERIOR_DRAGON_BONES, "Bones", Skill.PRAYER, 1, 150.0, CriticalItem.SUPERIOR_DRAGON_BONES), + // Shade Remains (Pyre Logs) + LOAR_REMAINS(ItemID.LOAR_REMAINS, "Shades", Skill.PRAYER, 1, 33.0, CriticalItem.LOAR_REMAINS), + PHRIN_REMAINS(ItemID.PHRIN_REMAINS, "Shades", Skill.PRAYER, 1, 46.5, CriticalItem.PHRIN_REMAINS), + RIYL_REMAINS(ItemID.RIYL_REMAINS, "Shades", Skill.PRAYER, 1, 59.5, CriticalItem.RIYL_REMAINS), + ASYN_REMAINS(ItemID.ASYN_REMAINS, "Shades", Skill.PRAYER, 1, 82.5, CriticalItem.ASYN_REMAINS), + FIYR_REMAINS(ItemID.FIYR_REMAINS, "Shades", Skill.PRAYER, 1, 84.0, CriticalItem.FIYR_REMAINS), + // Ensouled Heads + ENSOULED_GOBLIN_HEAD(ItemID.ENSOULED_GOBLIN_HEAD_13448, "Ensouled Heads", Skill.PRAYER, 1, 130.0, CriticalItem.ENSOULED_GOBLIN_HEAD), + ENSOULED_MONKEY_HEAD(ItemID.ENSOULED_MONKEY_HEAD_13451, "Ensouled Heads", Skill.PRAYER, 1, 182.0, CriticalItem.ENSOULED_MONKEY_HEAD), + ENSOULED_IMP_HEAD(ItemID.ENSOULED_IMP_HEAD_13454, "Ensouled Heads", Skill.PRAYER, 1, 286.0, CriticalItem.ENSOULED_IMP_HEAD), + ENSOULED_MINOTAUR_HEAD(ItemID.ENSOULED_MINOTAUR_HEAD_13457, "Ensouled Heads", Skill.PRAYER, 1, 364.0, CriticalItem.ENSOULED_MINOTAUR_HEAD), + ENSOULED_SCORPION_HEAD(ItemID.ENSOULED_SCORPION_HEAD_13460, "Ensouled Heads", Skill.PRAYER, 1, 454.0, CriticalItem.ENSOULED_SCORPION_HEAD), + ENSOULED_BEAR_HEAD(ItemID.ENSOULED_BEAR_HEAD_13463, "Ensouled Heads", Skill.PRAYER, 1, 480.0, CriticalItem.ENSOULED_BEAR_HEAD), + ENSOULED_UNICORN_HEAD(ItemID.ENSOULED_UNICORN_HEAD_13466, "Ensouled Heads", Skill.PRAYER, 1, 494.0, CriticalItem.ENSOULED_UNICORN_HEAD), + ENSOULED_DOG_HEAD(ItemID.ENSOULED_DOG_HEAD_13469, "Ensouled Heads", Skill.PRAYER, 1, 520.0, CriticalItem.ENSOULED_DOG_HEAD), + ENSOULED_CHAOS_DRUID_HEAD(ItemID.ENSOULED_CHAOS_DRUID_HEAD_13472, "Ensouled Heads", Skill.PRAYER, 1, 584.0, CriticalItem.ENSOULED_CHAOS_DRUID_HEAD), + ENSOULED_GIANT_HEAD(ItemID.ENSOULED_GIANT_HEAD_13475, "Ensouled Heads", Skill.PRAYER, 1, 650.0, CriticalItem.ENSOULED_GIANT_HEAD), + ENSOULED_OGRE_HEAD(ItemID.ENSOULED_OGRE_HEAD_13478, "Ensouled Heads", Skill.PRAYER, 1, 716.0, CriticalItem.ENSOULED_OGRE_HEAD), + ENSOULED_ELF_HEAD(ItemID.ENSOULED_ELF_HEAD_13481, "Ensouled Heads", Skill.PRAYER, 1, 754.0, CriticalItem.ENSOULED_ELF_HEAD), + ENSOULED_TROLL_HEAD(ItemID.ENSOULED_TROLL_HEAD_13484, "Ensouled Heads", Skill.PRAYER, 1, 780.0, CriticalItem.ENSOULED_TROLL_HEAD), + ENSOULED_HORROR_HEAD(ItemID.ENSOULED_HORROR_HEAD_13487, "Ensouled Heads", Skill.PRAYER, 1, 832.0, CriticalItem.ENSOULED_HORROR_HEAD), + ENSOULED_KALPHITE_HEAD(ItemID.ENSOULED_KALPHITE_HEAD_13490, "Ensouled Heads", Skill.PRAYER, 1, 884.0, CriticalItem.ENSOULED_KALPHITE_HEAD), + ENSOULED_DAGANNOTH_HEAD(ItemID.ENSOULED_DAGANNOTH_HEAD_13493, "Ensouled Heads", Skill.PRAYER, 1, 936.0, CriticalItem.ENSOULED_DAGANNOTH_HEAD), + ENSOULED_BLOODVELD_HEAD(ItemID.ENSOULED_BLOODVELD_HEAD_13496, "Ensouled Heads", Skill.PRAYER, 1, 1040.0, CriticalItem.ENSOULED_BLOODVELD_HEAD), + ENSOULED_TZHAAR_HEAD(ItemID.ENSOULED_TZHAAR_HEAD_13499, "Ensouled Heads", Skill.PRAYER, 1, 1104.0, CriticalItem.ENSOULED_TZHAAR_HEAD), + ENSOULED_DEMON_HEAD(ItemID.ENSOULED_DEMON_HEAD_13502, "Ensouled Heads", Skill.PRAYER, 1, 1170.0, CriticalItem.ENSOULED_DEMON_HEAD), + ENSOULED_AVIANSIE_HEAD(ItemID.ENSOULED_AVIANSIE_HEAD_13505, "Ensouled Heads", Skill.PRAYER, 1, 1234.0, CriticalItem.ENSOULED_AVIANSIE_HEAD), + ENSOULED_ABYSSAL_HEAD(ItemID.ENSOULED_ABYSSAL_HEAD_13508, "Ensouled Heads", Skill.PRAYER, 1, 1300.0, CriticalItem.ENSOULED_ABYSSAL_HEAD), + ENSOULED_DRAGON_HEAD(ItemID.ENSOULED_DRAGON_HEAD_13511, "Ensouled Heads", Skill.PRAYER, 1, 1560.0, CriticalItem.ENSOULED_DRAGON_HEAD), + + /* + * Cooking Items + */ + RAW_HERRING(ItemID.RAW_HERRING, "Fish", Skill.COOKING, 5, 50.0, CriticalItem.RAW_HERRING), + RAW_MACKEREL(ItemID.RAW_MACKEREL, "Fish", Skill.COOKING, 10, 60.0, CriticalItem.RAW_MACKEREL), + RAW_TROUT(ItemID.RAW_TROUT, "Fish", Skill.COOKING, 15, 70.0, CriticalItem.RAW_TROUT), + RAW_COD(ItemID.RAW_COD, "Fish", Skill.COOKING, 18, 75.0, CriticalItem.RAW_COD), + RAW_PIKE(ItemID.RAW_PIKE, "Fish", Skill.COOKING, 20, 80.0, CriticalItem.RAW_PIKE), + RAW_SALMON(ItemID.RAW_SALMON, "Fish", Skill.COOKING, 25, 90.0, CriticalItem.RAW_SALMON), + RAW_TUNA(ItemID.RAW_TUNA, "Fish", Skill.COOKING, 30, 100.0, CriticalItem.RAW_TUNA), + RAW_KARAMBWAN(ItemID.RAW_KARAMBWAN, "Fish", Skill.COOKING, 30, 190.0, CriticalItem.RAW_KARAMBWAN), + RAW_LOBSTER(ItemID.RAW_LOBSTER, "Fish", Skill.COOKING, 40, 120.0, CriticalItem.RAW_LOBSTER), + RAW_BASS(ItemID.RAW_BASS, "Fish", Skill.COOKING, 43, 130.0, CriticalItem.RAW_BASS), + RAW_SWORDFISH(ItemID.RAW_SWORDFISH, "Fish", Skill.COOKING, 45, 140.0, CriticalItem.RAW_SWORDFISH), + RAW_MONKFISH(ItemID.RAW_MONKFISH, "Fish", Skill.COOKING, 62, 150.0, CriticalItem.RAW_MONKFISH), + RAW_SHARK(ItemID.RAW_SHARK, "Fish", Skill.COOKING, 80, 210.0, CriticalItem.RAW_SHARK), + RAW_SEA_TURTLE(ItemID.RAW_SEA_TURTLE, "Fish", Skill.COOKING, 82, 211.3, CriticalItem.RAW_SEA_TURTLE), + RAW_ANGLERFISH(ItemID.RAW_ANGLERFISH, "Fish", Skill.COOKING, 84, 230.0, CriticalItem.RAW_ANGLERFISH), + RAW_DARK_CRAB(ItemID.RAW_DARK_CRAB, "Fish", Skill.COOKING, 90, 215.0, CriticalItem.RAW_DARK_CRAB), + RAW_MANTA_RAY(ItemID.RAW_MANTA_RAY, "Fish", Skill.COOKING, 91, 216.2, CriticalItem.RAW_MANTA_RAY), + + WINE(ItemID.JUG_OF_WINE, "Other", Skill.COOKING, 35, 200, CriticalItem.GRAPES, ActivitySecondaries.JUG_OF_WATER), + + /* + * Crafting Items + */ + // Spinning + BALL_OF_WOOL(ItemID.WOOL, "Misc", Skill.CRAFTING, 1, 2.5, CriticalItem.WOOL), + BOW_STRING(ItemID.BOW_STRING, "Misc", Skill.CRAFTING, 1, 15, CriticalItem.FLAX), + // Glass Blowing + BEER_GLASS(ItemID.BEER_GLASS, "Beer Glass", Skill.CRAFTING, 1, 17.5, CriticalItem.MOLTEN_GLASS), + CANDLE_LANTERN(ItemID.CANDLE_LANTERN, "Candle Lantern", Skill.CRAFTING, 4, 19, CriticalItem.MOLTEN_GLASS), + OIL_LAMP(ItemID.OIL_LAMP, "Oil Lamp", Skill.CRAFTING, 12, 25, CriticalItem.MOLTEN_GLASS), + VIAL(ItemID.VIAL, "Vial", Skill.CRAFTING, 33, 35, CriticalItem.MOLTEN_GLASS), + EMPTY_FISHBOWL(ItemID.EMPTY_FISHBOWL, "Empty fishbowl", Skill.CRAFTING, 42, 42.5, CriticalItem.MOLTEN_GLASS), + UNPOWERED_ORB(ItemID.UNPOWERED_ORB, "Unpowered orb", Skill.CRAFTING, 46, 52.5, CriticalItem.MOLTEN_GLASS), + LANTERN_LENS(ItemID.LANTERN_LENS, "Lantern lens", Skill.CRAFTING, 49, 55, CriticalItem.MOLTEN_GLASS), + LIGHT_ORB(ItemID.LIGHT_ORB, "Light orb", Skill.CRAFTING, 87, 70, CriticalItem.MOLTEN_GLASS), + // D'hide/Dragon Leather + GREEN_DRAGON_LEATHER(ItemID.GREEN_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 57, 62.0, CriticalItem.GREEN_DRAGON_LEATHER), + BLUE_DRAGON_LEATHER(ItemID.BLUE_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 66, 70.0, CriticalItem.BLUE_DRAGON_LEATHER), + RED_DRAGON_LEATHER(ItemID.RED_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 73, 78.0, CriticalItem.RED_DRAGON_LEATHER), + BLACK_DRAGON_LEATHER(ItemID.BLACK_DRAGON_LEATHER, "D'hide", Skill.CRAFTING, 79, 86.0, CriticalItem.BLACK_DRAGON_LEATHER), + // Uncut Gems + UNCUT_OPAL(ItemID.UNCUT_OPAL, "Gems", Skill.CRAFTING, 1, 15.0, CriticalItem.UNCUT_OPAL), + UNCUT_JADE(ItemID.UNCUT_JADE, "Gems", Skill.CRAFTING, 13, 20.0, CriticalItem.UNCUT_JADE), + UNCUT_RED_TOPAZ(ItemID.UNCUT_RED_TOPAZ, "Gems", Skill.CRAFTING, 16, 25.0, CriticalItem.UNCUT_RED_TOPAZ), + UNCUT_SAPPHIRE(ItemID.UNCUT_SAPPHIRE, "Gems", Skill.CRAFTING, 20, 50.0, CriticalItem.UNCUT_SAPPHIRE), + UNCUT_EMERALD(ItemID.UNCUT_EMERALD, "Gems", Skill.CRAFTING, 27, 67.5, CriticalItem.UNCUT_EMERALD), + UNCUT_RUBY(ItemID.UNCUT_RUBY, "Gems", Skill.CRAFTING, 34, 85, CriticalItem.UNCUT_RUBY), + UNCUT_DIAMOND(ItemID.UNCUT_DIAMOND, "Gems", Skill.CRAFTING, 43, 107.5, CriticalItem.UNCUT_DIAMOND), + UNCUT_DRAGONSTONE(ItemID.UNCUT_DRAGONSTONE, "Gems", Skill.CRAFTING, 55, 137.5, CriticalItem.UNCUT_DRAGONSTONE), + UNCUT_ONYX(ItemID.UNCUT_ONYX, "Gems", Skill.CRAFTING, 67, 167.5, CriticalItem.UNCUT_ONYX), + UNCUT_ZENYTE(ItemID.UNCUT_ZENYTE, "Gems", Skill.CRAFTING, 89, 200.0, CriticalItem.UNCUT_ZENYTE), + // Silver Jewelery + OPAL_RING(ItemID.OPAL_RING, "Opal ring", Skill.CRAFTING, 1, 10, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), + OPAL_NECKLACE(ItemID.OPAL_NECKLACE, "Opal necklace", Skill.CRAFTING, 16, 35, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), + OPAL_BRACELET(ItemID.OPAL_BRACELET, "Opal bracelet", Skill.CRAFTING, 22, 45, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), + OPAL_AMULET(ItemID.OPAL_AMULET, "Opal amulet", Skill.CRAFTING, 27, 55, CriticalItem.OPAL, ActivitySecondaries.SILVER_BAR), + JADE_RING(ItemID.JADE_RING, "Jade ring", Skill.CRAFTING, 13, 32, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), + JADE_NECKLACE(ItemID.JADE_NECKLACE, "Jade necklace", Skill.CRAFTING, 25, 54, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), + JADE_BRACELET(ItemID.JADE_BRACELET, "Jade bracelet", Skill.CRAFTING, 29, 60, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), + JADE_AMULET(ItemID.JADE_AMULET, "Jade amulet", Skill.CRAFTING, 34, 70, CriticalItem.JADE, ActivitySecondaries.SILVER_BAR), + TOPAZ_RING(ItemID.TOPAZ_RING, "Topaz ring", Skill.CRAFTING, 16, 35, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), + TOPAZ_NECKLACE(ItemID.TOPAZ_NECKLACE, "Topaz necklace", Skill.CRAFTING, 32, 70, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), + TOPAZ_BRACELET(ItemID.TOPAZ_BRACELET, "Topaz bracelet", Skill.CRAFTING, 38, 75, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), + TOPAZ_AMULET(ItemID.TOPAZ_AMULET, "Topaz amulet", Skill.CRAFTING, 45, 80, CriticalItem.RED_TOPAZ, ActivitySecondaries.SILVER_BAR), + // Gold Jewelery + SAPPHIRE_RING(ItemID.SAPPHIRE_RING, "Sapphire ring", Skill.CRAFTING, 20, 40, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), + SAPPHIRE_NECKLACE(ItemID.SAPPHIRE_NECKLACE, "Sapphire necklace", Skill.CRAFTING, 22, 55, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), + SAPPHIRE_BRACELET(ItemID.SAPPHIRE_BRACELET, "Sapphire bracelet", Skill.CRAFTING, 23, 60, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), + SAPPHIRE_AMULET(ItemID.SAPPHIRE_AMULET, "Sapphire amulet", Skill.CRAFTING, 24, 65, CriticalItem.SAPPHIRE, ActivitySecondaries.GOLD_BAR), + EMERALD_RING(ItemID.EMERALD_RING, "Emerald ring", Skill.CRAFTING, 27, 55, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), + EMERALD_NECKLACE(ItemID.EMERALD_NECKLACE, "Emerald necklace", Skill.CRAFTING, 29, 60, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), + EMERALD_BRACELET(ItemID.EMERALD_BRACELET, "Emerald bracelet", Skill.CRAFTING, 30, 65, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), + EMERALD_AMULET(ItemID.EMERALD_AMULET, "Emerald amulet", Skill.CRAFTING, 31, 70, CriticalItem.EMERALD, ActivitySecondaries.GOLD_BAR), + RUBY_RING(ItemID.RUBY_RING, "Ruby ring", Skill.CRAFTING, 34, 70, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), + RUBY_NECKLACE(ItemID.RUBY_NECKLACE, "Ruby necklace", Skill.CRAFTING, 40, 75, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), + RUBY_BRACELET(ItemID.RUBY_BRACELET, "Ruby bracelet", Skill.CRAFTING, 42, 80, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), + RUBY_AMULET(ItemID.RUBY_AMULET, "Ruby amulet", Skill.CRAFTING, 50, 85, CriticalItem.RUBY, ActivitySecondaries.GOLD_BAR), + DIAMOND_RING(ItemID.DIAMOND_RING, "Diamond ring", Skill.CRAFTING, 43, 85, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), + DIAMOND_NECKLACE(ItemID.DIAMOND_NECKLACE, "Diamond necklace", Skill.CRAFTING, 56, 90, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), + DIAMOND_BRACELET(ItemID.DIAMOND_BRACELET, "Diamond bracelet", Skill.CRAFTING, 58, 95, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), + DIAMOND_AMULET(ItemID.DIAMOND_AMULET, "Diamond amulet", Skill.CRAFTING, 70, 100, CriticalItem.DIAMOND, ActivitySecondaries.GOLD_BAR), + DRAGONSTONE_RING(ItemID.DRAGONSTONE_RING, "Dragonstone ring", Skill.CRAFTING, 55, 100, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), + DRAGON_NECKLACE(ItemID.DRAGON_NECKLACE, "Dragon necklace", Skill.CRAFTING, 72, 105, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), + DRAGONSTONE_BRACELET(ItemID.DRAGONSTONE_BRACELET, "Dragonstone bracelet", Skill.CRAFTING, 74, 110, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), + DRAGONSTONE_AMULET(ItemID.DRAGONSTONE_AMULET, "Dragonstone amulet", Skill.CRAFTING, 80, 150, CriticalItem.DRAGONSTONE, ActivitySecondaries.GOLD_BAR), + ONYX_RING(ItemID.ONYX_RING, "Onyx ring", Skill.CRAFTING, 67, 115, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), + ONYX_NECKLACE(ItemID.ONYX_NECKLACE, "Onyx necklace", Skill.CRAFTING, 82, 120, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), + REGEN_BRACELET(ItemID.REGEN_BRACELET, "Regen bracelet", Skill.CRAFTING, 84, 125, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), + ONYX_AMULET(ItemID.ONYX_AMULET, "Onyx amulet", Skill.CRAFTING, 90, 165, CriticalItem.ONYX, ActivitySecondaries.GOLD_BAR), + ZENYTE_RING(ItemID.ZENYTE_RING, "Zenyte ring", Skill.CRAFTING, 89, 150, CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), + ZENYTE_NECKLACE(ItemID.ZENYTE_NECKLACE, "Zenyte necklace", Skill.CRAFTING, 92, 165, CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), + ZENYTE_BRACELET(ItemID.ZENYTE_BRACELET, "Zenyte bracelet", Skill.CRAFTING, 95, 180, CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), + ZENYTE_AMULET(ItemID.ZENYTE_AMULET, "Zenyte amulet", Skill.CRAFTING, 98, 200, CriticalItem.ZENYTE, ActivitySecondaries.GOLD_BAR), + // Battle Staves + WATER_BATTLESTAFF(ItemID.WATER_BATTLESTAFF, "Water battlestaff", Skill.CRAFTING, 54, 100, CriticalItem.BATTLESTAFF, ActivitySecondaries.WATER_ORB), + EARTH_BATTLESTAFF(ItemID.EARTH_BATTLESTAFF, "Earth battlestaff", Skill.CRAFTING, 58, 112.5, CriticalItem.BATTLESTAFF, ActivitySecondaries.EARTH_ORB), + FIRE_BATTLESTAFF(ItemID.FIRE_BATTLESTAFF, "Fire battlestaff", Skill.CRAFTING, 62, 125, CriticalItem.BATTLESTAFF, ActivitySecondaries.FIRE_ORB), + AIR_BATTLESTAFF(ItemID.AIR_BATTLESTAFF, "Air battlestaff", Skill.CRAFTING, 66, 137.5, CriticalItem.BATTLESTAFF, ActivitySecondaries.AIR_ORB), + + /* + * Smithing Items + */ + + // Smelting ores (Furnace) + IRON_ORE(ItemID.IRON_BAR, "Iron Bars", Skill.SMITHING, 15, 12.5, CriticalItem.IRON_ORE, ActivitySecondaries.COAL_ORE), + STEEL_ORE(ItemID.STEEL_BAR, "Steel Bars", Skill.SMITHING, 30, 17.5, CriticalItem.IRON_ORE, ActivitySecondaries.COAL_ORE_2), + SILVER_ORE(ItemID.SILVER_ORE, "Bar", Skill.SMITHING, 20, 13.67, CriticalItem.SILVER_ORE), + GOLD_ORE(ItemID.GOLD_BAR, "Regular exp", Skill.SMITHING, 40, 22.5, CriticalItem.GOLD_ORE), + GOLD_ORE_GAUNTLETS(ItemID.GOLDSMITH_GAUNTLETS, "Goldsmith Gauntlets", Skill.SMITHING, 40, 56.2, CriticalItem.GOLD_ORE), + MITHRIL_ORE(ItemID.MITHRIL_ORE, "Bar", Skill.SMITHING, 50, 30, CriticalItem.MITHRIL_ORE, ActivitySecondaries.COAL_ORE_4), + ADAMANTITE_ORE(ItemID.ADAMANTITE_ORE, "Bar", Skill.SMITHING, 70, 37.5, CriticalItem.ADAMANTITE_ORE, ActivitySecondaries.COAL_ORE_6), + RUNITE_ORE(ItemID.RUNITE_ORE, "Bar", Skill.SMITHING, 85, 50, CriticalItem.RUNITE_ORE, ActivitySecondaries.COAL_ORE_8), + + // Smelting bars (Anvil) + BRONZE_BAR(ItemID.BRONZE_BAR, "Bars", Skill.SMITHING, 1, 12.5, CriticalItem.BRONZE_BAR), + IRON_BAR(ItemID.IRON_BAR, "Bars", Skill.SMITHING, 15, 25.0, CriticalItem.IRON_BAR), + STEEL_BAR(ItemID.STEEL_BAR, "Steel Products", Skill.SMITHING, 30, 37.5, CriticalItem.STEEL_BAR), + CANNONBALLS(ItemID.CANNONBALL, "Cannonballs", Skill.SMITHING, 35, 25.5, CriticalItem.STEEL_BAR), + MITHRIL_BAR(ItemID.MITHRIL_BAR, "Bars", Skill.SMITHING, 50, 50.0, CriticalItem.MITHRIL_BAR), + ADAMANTITE_BAR(ItemID.ADAMANTITE_BAR, "Bars", Skill.SMITHING, 70, 62.5, CriticalItem.ADAMANTITE_BAR), + RUNITE_BAR(ItemID.RUNITE_BAR, "Bars", Skill.SMITHING, 85, 75.0, CriticalItem.RUNITE_BAR), + + /** + * Farming Items + */ + ACORN(ItemID.ACORN, "Seeds", Skill.FARMING, 15, 481.3, CriticalItem.ACORN), + WILLOW_SEED(ItemID.WILLOW_SEED, "Seeds", Skill.FARMING, 30, 1481.5, CriticalItem.WILLOW_SEED), + MAPLE_SEED(ItemID.MAPLE_SEED, "Seeds", Skill.FARMING, 45, 3448.4, CriticalItem.MAPLE_SEED), + YEW_SEED(ItemID.YEW_SEED, "Seeds", Skill.FARMING, 60, 7150.9, CriticalItem.YEW_SEED), + MAGIC_SEED(ItemID.MAGIC_SEED, "Seeds", Skill.FARMING, 75, 13913.8, CriticalItem.MAGIC_SEED), + APPLE_TREE_SEED(ItemID.APPLE_TREE_SEED, "Seeds", Skill.FARMING, 27, 1272.5, CriticalItem.APPLE_TREE_SEED), + BANANA_TREE_SEED(ItemID.BANANA_TREE_SEED, "Seeds", Skill.FARMING, 33, 1841.5, CriticalItem.BANANA_TREE_SEED), + ORANGE_TREE_SEED(ItemID.ORANGE_TREE_SEED, "Seeds", Skill.FARMING, 39, 2586.7, CriticalItem.ORANGE_TREE_SEED), + CURRY_TREE_SEED(ItemID.CURRY_TREE_SEED, "Seeds", Skill.FARMING, 42, 3036.9, CriticalItem.CURRY_TREE_SEED), + PINEAPPLE_SEED(ItemID.PINEAPPLE_SEED, "Seeds", Skill.FARMING, 51, 4791.7, CriticalItem.PINEAPPLE_SEED), + PAPAYA_TREE_SEED(ItemID.PAPAYA_TREE_SEED, "Seeds", Skill.FARMING, 57, 6380.4, CriticalItem.PAPAYA_TREE_SEED), + PALM_TREE_SEED(ItemID.PALM_TREE_SEED, "Seeds", Skill.FARMING, 68, 10509.6, CriticalItem.PALM_TREE_SEED), + CALQUAT_TREE_SEED(ItemID.CALQUAT_TREE_SEED, "Seeds", Skill.FARMING, 72, 12516.5, CriticalItem.CALQUAT_TREE_SEED), + TEAK_SEED(ItemID.TEAK_SEED, "Seeds", Skill.FARMING, 35, 7325, CriticalItem.TEAK_SEED), + MAHOGANY_SEED(ItemID.MAHOGANY_SEED, "Seeds", Skill.FARMING, 55, 15783, CriticalItem.MAHOGANY_SEED), + SPIRIT_SEED(ItemID.SPIRIT_SEED, "Seeds", Skill.FARMING, 83, 19500, CriticalItem.SPIRIT_SEED), + ; + + private final int icon; + private final String name; + private final Skill skill; + private final int level; + private final double xp; + private final SecondaryItem[] secondaries; + private final CriticalItem criticalItem; + private final boolean preventLinked; + + Activity(int Icon, String name, Skill skill, int level, double xp, CriticalItem criticalItem) + { + this.icon = Icon; + this.name = name; + this.skill = skill; + this.level = level; + this.xp = xp; + this.criticalItem = criticalItem; + this.secondaries = new SecondaryItem[0]; + this.preventLinked = false; + } + + Activity(int Icon, String name, Skill skill, int level, double xp, CriticalItem criticalItem, ActivitySecondaries secondaries) + { + this.icon = Icon; + this.name = name; + this.skill = skill; + this.level = level; + this.xp = xp; + this.criticalItem = criticalItem; + this.secondaries = secondaries == null ? new SecondaryItem[0] : secondaries.getItems(); + this.preventLinked = false; + } + + Activity(int Icon, String name, Skill skill, int level, double xp, CriticalItem criticalItem, ActivitySecondaries secondaries, boolean preventLinked) + { + this.icon = Icon; + this.name = name; + this.skill = skill; + this.level = level; + this.xp = xp; + this.criticalItem = criticalItem; + this.secondaries = secondaries == null ? new SecondaryItem[0] : secondaries.getItems(); + this.preventLinked = preventLinked; + } + + // Builds a Map to reduce looping frequency + private static Map> buildItemMap() + { + Map> map = new HashMap<>(); + for (Activity item : values()) + { + map.computeIfAbsent(item.getCriticalItem(), e -> new ArrayList()).add(item); + } + + return map; + } + + private static final Map> byCriticalItem = buildItemMap(); + + public static ArrayList getByCriticalItem(CriticalItem item) + { + + return byCriticalItem.getOrDefault(item, new ArrayList<>()); + } + + /** + * Get all Activities for this CriticalItem + * + * @param item CriticalItem to check for + * @param limitLevel Level to check Activitiy requirements against. -1 or 0 value disables limits + * @return an empty list if no activities + */ + public static ArrayList getByCriticalItem(CriticalItem item, int limitLevel) + { + ArrayList activities = getByCriticalItem(item); + ArrayList l = new ArrayList<>(); + if (limitLevel <= 0) + { + return l; + } + + for (Activity a : activities) + { + if (!(a.getLevel() > limitLevel)) + { + l.add(a); + } + } + + return l; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/ui/CriticalItemPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/ui/CriticalItemPanel.java index 7214956e80..ddb324e7b0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/ui/CriticalItemPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/banked/ui/CriticalItemPanel.java @@ -1,401 +1,400 @@ -/* - * 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.plugins.skillcalculator.banked.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Image; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import javax.imageio.ImageIO; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.border.MatteBorder; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.game.AsyncBufferedImage; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.skillcalculator.BankedCalculator; -import net.runelite.client.plugins.skillcalculator.banked.CriticalItem; -import net.runelite.client.plugins.skillcalculator.banked.beans.Activity; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.components.materialtabs.MaterialTab; -import net.runelite.client.ui.components.materialtabs.MaterialTabGroup; -import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; -import net.runelite.client.util.StackFormatter; - -public class CriticalItemPanel extends JPanel -{ - private static final Dimension ICON_SIZE = new Dimension(36, 36); - private static final DecimalFormat FORMAT_COMMA = new DecimalFormat("#,###.#"); - - private static final BufferedImage ICON_SETTINGS; - - private static final Border PANEL_BORDER = new EmptyBorder(3, 0, 3, 0); - private final static Color BACKGROUND_COLOR = ColorScheme.DARKER_GRAY_COLOR; - private final static Color BUTTON_HOVER_COLOR = ColorScheme.DARKER_GRAY_HOVER_COLOR; - - static - { - BufferedImage i1; - try - { - synchronized (ImageIO.class) - { - i1 = ImageIO.read(BankedCalculator.class.getResourceAsStream("view-more-white.png")); - } - } - catch (IOException e) - { - throw new RuntimeException(e); - } - ICON_SETTINGS = i1; - } - - private final BankedCalculator bankedCalculator; - private final CriticalItem item; - private final ItemManager itemManager; - private double xp; - @Getter - private int amount; - @Getter - private double total; - private Map linkedMap; - private JShadowedLabel labelValue; - - private final JPanel infoContainer; - private final JLabel image; - private boolean infoVisibility = false; - - public CriticalItemPanel(BankedCalculator bankedCalculator, ItemManager itemManager, CriticalItem item, double xp, int amount, Map linkedMap) - { - this.bankedCalculator = bankedCalculator; - this.item = item; - this.xp = xp; - this.amount = amount; - this.total = xp * amount; - this.itemManager = itemManager; - this.linkedMap = linkedMap; - - this.setLayout(new GridBagLayout()); - this.setBorder(PANEL_BORDER); - this.setBackground(ColorScheme.DARK_GRAY_COLOR); - this.setVisible(this.amount > 0); - - infoContainer = new JPanel(); - infoContainer.setLayout(new GridBagLayout()); - infoContainer.setVisible(false); - infoContainer.setBackground(BACKGROUND_COLOR); - infoContainer.setBorder(new MatteBorder(1, 0, 0, 0, Color.GRAY)); - - // Icon - AsyncBufferedImage icon = itemManager.getImage(item.getItemID(), amount, item.getComposition().isStackable() || amount > 1); - image = new JLabel(); - image.setMinimumSize(ICON_SIZE); - image.setMaximumSize(ICON_SIZE); - image.setPreferredSize(ICON_SIZE); - image.setHorizontalAlignment(SwingConstants.CENTER); - image.setBorder(new EmptyBorder(0, 8, 0, 0)); - - Runnable resize = () -> - image.setIcon(new ImageIcon(icon.getScaledInstance((int)ICON_SIZE.getWidth(), (int)ICON_SIZE.getHeight(), Image.SCALE_SMOOTH))); - icon.onChanged(resize); - resize.run(); - - // Container for Info - JPanel uiInfo = new JPanel(new GridLayout(2, 1)); - uiInfo.setBorder(new EmptyBorder(0, 5, 0, 0)); - uiInfo.setBackground(BACKGROUND_COLOR); - - JShadowedLabel labelName = new JShadowedLabel(item.getComposition().getName()); - labelName.setForeground(Color.WHITE); - labelName.setVerticalAlignment(SwingUtilities.BOTTOM); - - labelValue = new JShadowedLabel(); - labelValue.setFont(FontManager.getRunescapeSmallFont()); - labelValue.setVerticalAlignment(SwingUtilities.TOP); - updateXp(xp); - - uiInfo.add(labelName); - uiInfo.add(labelValue); - - // Settings Button - JLabel settingsButton = new JLabel(); - settingsButton.setBorder(new EmptyBorder(0, 5, 0, 5)); - settingsButton.setIcon(new ImageIcon(ICON_SETTINGS)); - settingsButton.setOpaque(true); - settingsButton.setBackground(BACKGROUND_COLOR); - - settingsButton.addMouseListener(new MouseAdapter() - { - @Override - public void mouseEntered(MouseEvent e) - { - settingsButton.setBackground(BUTTON_HOVER_COLOR); - } - - @Override - public void mouseExited(MouseEvent e) - { - settingsButton.setBackground(BACKGROUND_COLOR); - } - - @Override - public void mouseClicked(MouseEvent e) - { - toggleInfo(); - } - }); - - // Create and append elements to container panel - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.setBackground(BACKGROUND_COLOR); - - panel.add(image, BorderLayout.LINE_START); - panel.add(uiInfo, BorderLayout.CENTER); - - // Only add button if has activity selection options or linked items - List activities = Activity.getByCriticalItem(item); - // If linked map has 1 item and it isn't this item still show breakdown (cleaned herbs into unfinished) - if ( (linkedMap.size() > 1 || (linkedMap.size() == 1 && linkedMap.get(item) == null)) - || activities.size() > 1) - { - panel.add(settingsButton, BorderLayout.LINE_END); - } - - panel.setToolTipText("" + item.getComposition().getName() - + "
xp: " + xp - + "
Total: " + StackFormatter.quantityToStackSize((long) total) + " 1 || (linkedMap.size() == 1 && linkedMap.get(item) == null)) - { - JLabel l = new JLabel("Item Breakdown"); - l.setBorder(new EmptyBorder(3, 0, 3, 0)); - l.setHorizontalAlignment(JLabel.CENTER); - infoContainer.add(l, c); - c.gridy++; - - JPanel con = new JPanel(); - con.setLayout(new GridBagLayout()); - con.setBackground(BACKGROUND_COLOR); - for (Map.Entry e : linkedMap.entrySet()) - { - // Icon - AsyncBufferedImage icon = itemManager.getImage(e.getKey().getItemID(), e.getValue(), e.getKey().getComposition().isStackable() || e.getValue() > 1); - JLabel image = new JLabel(); - image.setMinimumSize(ICON_SIZE); - image.setMaximumSize(ICON_SIZE); - image.setPreferredSize(ICON_SIZE); - image.setHorizontalAlignment(SwingConstants.CENTER); - image.setBorder(new EmptyBorder(0, 8, 0, 0)); - - Runnable resize = () -> - image.setIcon(new ImageIcon(icon.getScaledInstance((int)ICON_SIZE.getWidth(), (int)ICON_SIZE.getHeight(), Image.SCALE_SMOOTH))); - icon.onChanged(resize); - resize.run(); - - image.setToolTipText(e.getKey().getComposition().getName()); - - con.add(image, c); - c.gridx++; - } - c.gridx = 0; - infoContainer.add(con, c); - } - - } - - private JPanel createActivitiesPanel() - { - ArrayList activities = Activity.getByCriticalItem(item); - if (activities == null || activities.size() == 1) - { - return null; - } - - JPanel p = new JPanel(); - p.setBackground(BACKGROUND_COLOR); - p.setLayout(new BorderLayout()); - - JLabel label = new JLabel("Possible training methods"); - - MaterialTabGroup group = new MaterialTabGroup(); - group.setLayout(new GridLayout(0, 6, 0, 2)); - group.setBorder(new MatteBorder(1, 1, 1, 1, Color.BLACK)); - - Activity selected = this.bankedCalculator.getSelectedActivity(this.item); - boolean s = false; - - for (Activity option : activities) - { - AsyncBufferedImage icon = itemManager.getImage(option.getIcon()); - MaterialTab matTab = new MaterialTab("", group, null); - matTab.setHorizontalAlignment(SwingUtilities.RIGHT); - matTab.setToolTipText(option.getName()); - - Runnable resize = () -> - matTab.setIcon(new ImageIcon(icon.getScaledInstance(24, 24, Image.SCALE_SMOOTH))); - icon.onChanged(resize); - resize.run(); - - group.addTab(matTab); - - // Select first option by default - if (!s) - { - s = true; - group.select(matTab); - } - - // Select the option if its their selected activity - if (option.equals(selected)) - { - group.select(matTab); - } - - // Add click event handler now to prevent above code from triggering it. - matTab.setOnSelectEvent(() -> - { - bankedCalculator.activitySelected(item, option); - return true; - }); - } - - p.add(label, BorderLayout.NORTH); - p.add(group, BorderLayout.SOUTH); - - return p; - } - - public void updateXp(double newXpRate) - { - xp = newXpRate; - total = xp * amount; - labelValue.setText(FORMAT_COMMA.format(total) + "xp"); - } - - public void updateAmount(int newAmount, boolean forceVisible) - { - this.setVisible(newAmount > 0 || forceVisible); - this.amount = newAmount; - AsyncBufferedImage icon = itemManager.getImage(item.getItemID(), amount, item.getComposition().isStackable() || amount > 1); - Runnable resize = () -> - image.setIcon(new ImageIcon(icon.getScaledInstance((int)ICON_SIZE.getWidth(), (int)ICON_SIZE.getHeight(), Image.SCALE_SMOOTH))); - icon.onChanged(resize); - resize.run(); - } - - public void updateLinkedMap(Map newLinkedMap) - { - this.linkedMap = newLinkedMap; - - int sum = 0; - for (Integer v : newLinkedMap.values()) - { - sum += v; - } - this.updateAmount(sum, false); - - this.updateXp(xp); - - // Refresh info panel if visible - if (infoVisibility) - { - createInfoPanel(); - } - } - - public void recalculate() - { - updateXp(xp); - } -} +/* + * 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.plugins.skillcalculator.banked.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.border.MatteBorder; +import lombok.Getter; +import net.runelite.client.game.AsyncBufferedImage; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.skillcalculator.BankedCalculator; +import net.runelite.client.plugins.skillcalculator.banked.CriticalItem; +import net.runelite.client.plugins.skillcalculator.banked.beans.Activity; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.components.materialtabs.MaterialTab; +import net.runelite.client.ui.components.materialtabs.MaterialTabGroup; +import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; +import net.runelite.client.util.StackFormatter; + +public class CriticalItemPanel extends JPanel +{ + private static final Dimension ICON_SIZE = new Dimension(36, 36); + private static final DecimalFormat FORMAT_COMMA = new DecimalFormat("#,###.#"); + + private static final BufferedImage ICON_SETTINGS; + + private static final Border PANEL_BORDER = new EmptyBorder(3, 0, 3, 0); + private final static Color BACKGROUND_COLOR = ColorScheme.DARKER_GRAY_COLOR; + private final static Color BUTTON_HOVER_COLOR = ColorScheme.DARKER_GRAY_HOVER_COLOR; + + static + { + BufferedImage i1; + try + { + synchronized (ImageIO.class) + { + i1 = ImageIO.read(BankedCalculator.class.getResourceAsStream("view-more-white.png")); + } + } + catch (IOException e) + { + throw new RuntimeException(e); + } + ICON_SETTINGS = i1; + } + + private final BankedCalculator bankedCalculator; + private final CriticalItem item; + private final ItemManager itemManager; + private double xp; + @Getter + private int amount; + @Getter + private double total; + private Map linkedMap; + private JShadowedLabel labelValue; + + private final JPanel infoContainer; + private final JLabel image; + private boolean infoVisibility = false; + + public CriticalItemPanel(BankedCalculator bankedCalculator, ItemManager itemManager, CriticalItem item, double xp, int amount, Map linkedMap) + { + this.bankedCalculator = bankedCalculator; + this.item = item; + this.xp = xp; + this.amount = amount; + this.total = xp * amount; + this.itemManager = itemManager; + this.linkedMap = linkedMap; + + this.setLayout(new GridBagLayout()); + this.setBorder(PANEL_BORDER); + this.setBackground(ColorScheme.DARK_GRAY_COLOR); + this.setVisible(this.amount > 0); + + infoContainer = new JPanel(); + infoContainer.setLayout(new GridBagLayout()); + infoContainer.setVisible(false); + infoContainer.setBackground(BACKGROUND_COLOR); + infoContainer.setBorder(new MatteBorder(1, 0, 0, 0, Color.GRAY)); + + // Icon + AsyncBufferedImage icon = itemManager.getImage(item.getItemID(), amount, item.getComposition().isStackable() || amount > 1); + image = new JLabel(); + image.setMinimumSize(ICON_SIZE); + image.setMaximumSize(ICON_SIZE); + image.setPreferredSize(ICON_SIZE); + image.setHorizontalAlignment(SwingConstants.CENTER); + image.setBorder(new EmptyBorder(0, 8, 0, 0)); + + Runnable resize = () -> + image.setIcon(new ImageIcon(icon.getScaledInstance((int) ICON_SIZE.getWidth(), (int) ICON_SIZE.getHeight(), Image.SCALE_SMOOTH))); + icon.onChanged(resize); + resize.run(); + + // Container for Info + JPanel uiInfo = new JPanel(new GridLayout(2, 1)); + uiInfo.setBorder(new EmptyBorder(0, 5, 0, 0)); + uiInfo.setBackground(BACKGROUND_COLOR); + + JShadowedLabel labelName = new JShadowedLabel(item.getComposition().getName()); + labelName.setForeground(Color.WHITE); + labelName.setVerticalAlignment(SwingUtilities.BOTTOM); + + labelValue = new JShadowedLabel(); + labelValue.setFont(FontManager.getRunescapeSmallFont()); + labelValue.setVerticalAlignment(SwingUtilities.TOP); + updateXp(xp); + + uiInfo.add(labelName); + uiInfo.add(labelValue); + + // Settings Button + JLabel settingsButton = new JLabel(); + settingsButton.setBorder(new EmptyBorder(0, 5, 0, 5)); + settingsButton.setIcon(new ImageIcon(ICON_SETTINGS)); + settingsButton.setOpaque(true); + settingsButton.setBackground(BACKGROUND_COLOR); + + settingsButton.addMouseListener(new MouseAdapter() + { + @Override + public void mouseEntered(MouseEvent e) + { + settingsButton.setBackground(BUTTON_HOVER_COLOR); + } + + @Override + public void mouseExited(MouseEvent e) + { + settingsButton.setBackground(BACKGROUND_COLOR); + } + + @Override + public void mouseClicked(MouseEvent e) + { + toggleInfo(); + } + }); + + // Create and append elements to container panel + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setBackground(BACKGROUND_COLOR); + + panel.add(image, BorderLayout.LINE_START); + panel.add(uiInfo, BorderLayout.CENTER); + + // Only add button if has activity selection options or linked items + List activities = Activity.getByCriticalItem(item); + // If linked map has 1 item and it isn't this item still show breakdown (cleaned herbs into unfinished) + if ((linkedMap.size() > 1 || (linkedMap.size() == 1 && linkedMap.get(item) == null)) + || activities.size() > 1) + { + panel.add(settingsButton, BorderLayout.LINE_END); + } + + panel.setToolTipText("" + item.getComposition().getName() + + "
xp: " + xp + + "
Total: " + StackFormatter.quantityToStackSize((long) total) + " 1 || (linkedMap.size() == 1 && linkedMap.get(item) == null)) + { + JLabel l = new JLabel("Item Breakdown"); + l.setBorder(new EmptyBorder(3, 0, 3, 0)); + l.setHorizontalAlignment(JLabel.CENTER); + infoContainer.add(l, c); + c.gridy++; + + JPanel con = new JPanel(); + con.setLayout(new GridBagLayout()); + con.setBackground(BACKGROUND_COLOR); + for (Map.Entry e : linkedMap.entrySet()) + { + // Icon + AsyncBufferedImage icon = itemManager.getImage(e.getKey().getItemID(), e.getValue(), e.getKey().getComposition().isStackable() || e.getValue() > 1); + JLabel image = new JLabel(); + image.setMinimumSize(ICON_SIZE); + image.setMaximumSize(ICON_SIZE); + image.setPreferredSize(ICON_SIZE); + image.setHorizontalAlignment(SwingConstants.CENTER); + image.setBorder(new EmptyBorder(0, 8, 0, 0)); + + Runnable resize = () -> + image.setIcon(new ImageIcon(icon.getScaledInstance((int) ICON_SIZE.getWidth(), (int) ICON_SIZE.getHeight(), Image.SCALE_SMOOTH))); + icon.onChanged(resize); + resize.run(); + + image.setToolTipText(e.getKey().getComposition().getName()); + + con.add(image, c); + c.gridx++; + } + c.gridx = 0; + infoContainer.add(con, c); + } + + } + + private JPanel createActivitiesPanel() + { + ArrayList activities = Activity.getByCriticalItem(item); + if (activities == null || activities.size() == 1) + { + return null; + } + + JPanel p = new JPanel(); + p.setBackground(BACKGROUND_COLOR); + p.setLayout(new BorderLayout()); + + JLabel label = new JLabel("Possible training methods"); + + MaterialTabGroup group = new MaterialTabGroup(); + group.setLayout(new GridLayout(0, 6, 0, 2)); + group.setBorder(new MatteBorder(1, 1, 1, 1, Color.BLACK)); + + Activity selected = this.bankedCalculator.getSelectedActivity(this.item); + boolean s = false; + + for (Activity option : activities) + { + AsyncBufferedImage icon = itemManager.getImage(option.getIcon()); + MaterialTab matTab = new MaterialTab("", group, null); + matTab.setHorizontalAlignment(SwingUtilities.RIGHT); + matTab.setToolTipText(option.getName()); + + Runnable resize = () -> + matTab.setIcon(new ImageIcon(icon.getScaledInstance(24, 24, Image.SCALE_SMOOTH))); + icon.onChanged(resize); + resize.run(); + + group.addTab(matTab); + + // Select first option by default + if (!s) + { + s = true; + group.select(matTab); + } + + // Select the option if its their selected activity + if (option.equals(selected)) + { + group.select(matTab); + } + + // Add click event handler now to prevent above code from triggering it. + matTab.setOnSelectEvent(() -> + { + bankedCalculator.activitySelected(item, option); + return true; + }); + } + + p.add(label, BorderLayout.NORTH); + p.add(group, BorderLayout.SOUTH); + + return p; + } + + public void updateXp(double newXpRate) + { + xp = newXpRate; + total = xp * amount; + labelValue.setText(FORMAT_COMMA.format(total) + "xp"); + } + + public void updateAmount(int newAmount, boolean forceVisible) + { + this.setVisible(newAmount > 0 || forceVisible); + this.amount = newAmount; + AsyncBufferedImage icon = itemManager.getImage(item.getItemID(), amount, item.getComposition().isStackable() || amount > 1); + Runnable resize = () -> + image.setIcon(new ImageIcon(icon.getScaledInstance((int) ICON_SIZE.getWidth(), (int) ICON_SIZE.getHeight(), Image.SCALE_SMOOTH))); + icon.onChanged(resize); + resize.run(); + } + + public void updateLinkedMap(Map newLinkedMap) + { + this.linkedMap = newLinkedMap; + + int sum = 0; + for (Integer v : newLinkedMap.values()) + { + sum += v; + } + this.updateAmount(sum, false); + + this.updateXp(xp); + + // Refresh info panel if visible + if (infoVisibility) + { + createInfoPanel(); + } + } + + public void recalculate() + { + updateXp(xp); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/KnapsackSolver.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/KnapsackSolver.java index e00bef4443..b97e2aa21f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/KnapsackSolver.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/KnapsackSolver.java @@ -30,7 +30,7 @@ import java.util.List; public class KnapsackSolver { - private List reconstructItemsInSack(int [] [] sackMatrix, List items, int i, int w) + private List reconstructItemsInSack(int[][] sackMatrix, List items, int i, int w) { if (i == 0) { @@ -39,7 +39,7 @@ public class KnapsackSolver if (sackMatrix[i][w] > sackMatrix[i - 1][w]) { List list = reconstructItemsInSack(sackMatrix, items, - i - 1, w - items.get(i - 1)); + i - 1, w - items.get(i - 1)); list.add(items.get(i - 1)); return list; } @@ -53,20 +53,20 @@ public class KnapsackSolver { int itemCount = items.size(); - int[] [] sackMatrix = new int[itemCount + 1] [maxWeight + 1]; + int[][] sackMatrix = new int[itemCount + 1][maxWeight + 1]; for (int i = 1; i <= itemCount; i++) { for (int j = 0; j <= maxWeight; j++) { if (items.get(i - 1) > j) { - sackMatrix[i] [j] = sackMatrix[i - 1] [j]; + sackMatrix[i][j] = sackMatrix[i - 1][j]; } else { - sackMatrix[i] [j] = Math.max( - sackMatrix[i - 1] [j], - sackMatrix[i - 1] [j - items.get(i - 1)] + items.get(i - 1) + sackMatrix[i][j] = Math.max( + sackMatrix[i - 1][j], + sackMatrix[i - 1][j - items.get(i - 1)] + items.get(i - 1) ); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java index a9da3d2040..3f44d26d0e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java @@ -140,29 +140,29 @@ public class SlayerPlugin extends Plugin // Superiors @VisibleForTesting static List SUPERIOR_SLAYER_MONSTERS = Arrays.asList( - "crushing hand", - "chasm crawler", - "screaming banshee", - "screaming twisted banshee", - "giant rockslug", - "cockathrice", - "flaming pyrelord", - "monstrous basilisk", - "malevolent mage", - "insatiable bloodveld", - "insatiable mutated bloodveld", - "vitreous jelly", - "vitreous warped jelly", - "cave abomination", - "abhorrent spectre", - "repugnant spectre", - "choke devil", - "king kurask", - "marble gargoyle", - "nechryarch", - "greater abyssal demon", - "night beast", - "nuclear smoke devil"); + "crushing hand", + "chasm crawler", + "screaming banshee", + "screaming twisted banshee", + "giant rockslug", + "cockathrice", + "flaming pyrelord", + "monstrous basilisk", + "malevolent mage", + "insatiable bloodveld", + "insatiable mutated bloodveld", + "vitreous jelly", + "vitreous warped jelly", + "cave abomination", + "abhorrent spectre", + "repugnant spectre", + "choke devil", + "king kurask", + "marble gargoyle", + "nechryarch", + "greater abyssal demon", + "night beast", + "nuclear smoke devil"); @Inject private ClientToolbar clientToolbar; @@ -408,7 +408,7 @@ public class SlayerPlugin extends Plugin debugString.append(", "); } log.debug("Estimating kc of xp drop " + gains + " for presences {" + - debugString.toString() + "}"); + debugString.toString() + "}"); // first determine potential xp drops given by all npcs that died this tick by grabbing the slayer xp // info from the map made out of the data in slayer_xp.json @@ -429,7 +429,7 @@ public class SlayerPlugin extends Plugin debugString.append(", "); } log.debug("Determined xp drop " + gains + " can be made of {" + debugString.toString() - + "}"); + + "}"); // we can attempt to determine exactly how many npcs died to give this amount of xp // by using a solver for the knapsack problem @@ -443,8 +443,8 @@ public class SlayerPlugin extends Plugin // and xp drops can have a single number after the decimal point int tenFudgedGains = fudgedGains * 10; List potentialXpDropsAsInts = potentialXpDrops.stream() - .map(xpDrop -> (int) (xpDrop * 10)) - .collect(Collectors.toCollection(ArrayList::new)); + .map(xpDrop -> (int) (xpDrop * 10)) + .collect(Collectors.toCollection(ArrayList::new)); KnapsackSolver solver = new KnapsackSolver(); @@ -593,7 +593,7 @@ public class SlayerPlugin extends Plugin log.debug("Last certain amount was " + currentTask.getLastCertainAmount() + " so error rate is " + currentTask.getAmount() + " in " + currentTask.getLastCertainAmount()); - setTask("", 0, 0, true, 0); + setTask("", 0, 0, true, 0); return; } @@ -625,7 +625,7 @@ public class SlayerPlugin extends Plugin if (bracerProgress.find()) { final int taskAmount = Integer.parseInt(bracerProgress.group(1)); - setTask(currentTask.getTaskName(), taskAmount, currentTask.getInitialAmount(), false, taskAmount); + setTask(currentTask.getTaskName(), taskAmount, currentTask.getInitialAmount(), false, taskAmount); // Avoid race condition (combat brace message goes through first before XP drop) currentTask.setAmount(currentTask.getAmount() + 1); @@ -700,7 +700,8 @@ public class SlayerPlugin extends Plugin @Subscribe public void onInteractingChanged(InteractingChanged event) { - if (client.getLocalPlayer() == null) { + if (client.getLocalPlayer() == null) + { return; } final Actor interacting = client.getLocalPlayer().getInteracting(); @@ -780,7 +781,7 @@ public class SlayerPlugin extends Plugin private boolean doubleTroubleExtraKill() { return WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID() == GROTESQUE_GUARDIANS_REGION && - SlayerUnlock.GROTESQUE_GARDIAN_DOUBLE_COUNT.isEnabled(client); + SlayerUnlock.GROTESQUE_GARDIAN_DOUBLE_COUNT.isEnabled(client); } // checks if any contiguous subsequence of seq0 exactly matches the String toMatch @@ -810,10 +811,8 @@ public class SlayerPlugin extends Plugin if (composition != null) { List actions = Arrays.asList(composition.getActions()); - if (actions.contains("Attack") || actions.contains("Pick") || actions.contains("Poke")) //Pick action is for zygomite-fungi - { - return true; - } + //Pick action is for zygomite-fungi + return actions.contains("Attack") || actions.contains("Pick") || actions.contains("Poke"); } return false; @@ -940,7 +939,7 @@ public class SlayerPlugin extends Plugin isNewAssignment ? 0 : currentTask.getElapsedKills(), isNewAssignment ? 0 : currentTask.getElapsedXp(), amt, initAmt, lastCertainAmt, location, name, - isNewAssignment ? true : currentTask.isPaused()); + isNewAssignment || currentTask.isPaused()); if (panel != null) { panel.updateCurrentTask(true, currentTask.isPaused(), currentTask, isNewAssignment); @@ -994,7 +993,7 @@ public class SlayerPlugin extends Plugin { taskTooltip += "
" + ColorUtil.wrapWithColorTag("Start:", Color.YELLOW) - + " " + currentTask.getInitialAmount() ; + + " " + currentTask.getInitialAmount(); } counter = new TaskCounter(taskImg, this, currentTask.getAmount()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java index 06684bab67..d40f7955b5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java @@ -102,7 +102,8 @@ public class SlayerTaskPanel extends PluginPanel playBtn.setIcon(PLAY); playBtn.setToolTipText("Resume the current slayer task"); - playBtn.addMouseListener(new MouseAdapter() { + playBtn.addMouseListener(new MouseAdapter() + { @Override public void mousePressed(MouseEvent mouseEvent) { @@ -137,13 +138,15 @@ public class SlayerTaskPanel extends PluginPanel pauseBtn.setIcon(PAUSE); pauseBtn.setToolTipText("Pause the current slayer task"); - pauseBtn.addMouseListener(new MouseAdapter() { + pauseBtn.addMouseListener(new MouseAdapter() + { @Override public void mousePressed(MouseEvent mouseEvent) { slayerPlugin.setPaused(true); changePauseState(true); } + @Override public void mouseExited(MouseEvent mouseEvent) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerXpDropLookup.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerXpDropLookup.java index 8973f92bef..a3e3898390 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerXpDropLookup.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerXpDropLookup.java @@ -52,26 +52,26 @@ public class SlayerXpDropLookup * Finds the xp for a given npc using the xp + combat level data provided * from the JSON - since scrapping from the wiki isn't perfectly accurate * we make some estimations - * + *

* precondition is that xpCombatLevel array is non-null - if it is null * we can simply return -1 to indicate no slayer xp because this npc * has no associated xpCombatLevel array - * + *

* 1. first check to see if anywhere in the xp + combat level data this - * creature name give slayer xp - if it doesn't just return -1 and - * be done with this - if it does give slayer xp then continue + * creature name give slayer xp - if it doesn't just return -1 and + * be done with this - if it does give slayer xp then continue * 2. now check to see if we can find the xp for this combat level where - * that xp is greater than 0. note that we don't just find the xp for - * this combat level - this is because for some monsters the wiki - * only has slayer xp data for some combat levels and has it unknown - * for the other combat levels. this way we only return the combat level - * related xp data for a monster if it is know + * that xp is greater than 0. note that we don't just find the xp for + * this combat level - this is because for some monsters the wiki + * only has slayer xp data for some combat levels and has it unknown + * for the other combat levels. this way we only return the combat level + * related xp data for a monster if it is know * 3. finally if the slayer xp data for the monster was unknown for the given - * level we estimate the slayer xp by using one of the slayer xps for a level - * that does have xp given + * level we estimate the slayer xp by using one of the slayer xps for a level + * that does have xp given * 4. note that if a monster gives no slayer xp for any level it will return - * -1 so we don't accidentally misscount non-slayer targets dying as giving - * slayer xp + * -1 so we don't accidentally misscount non-slayer targets dying as giving + * slayer xp * * @param npc the npc we are estimating slayer xp for * @return our best guess for the slayer xp for this npc @@ -99,7 +99,7 @@ public class SlayerXpDropLookup for (int i = 0; i < xpCombatLevel.size() - 1; i += 2) { if (Math.abs(xpCombatLevel.get(i + 1) - npc.getCombatLevel()) < EPSILON - && xpCombatLevel.get(i) > 0) + && xpCombatLevel.get(i) > 0) { foundCombatLevel = true; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java index 84fa4d8773..08d9d97cd0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java @@ -107,7 +107,7 @@ class TargetWeaknessOverlay extends Overlay return -1; } - return (int)((maxHealth * healthRatio / healthScale) + 0.5f); + return (int) ((maxHealth * healthRatio / healthScale) + 0.5f); } private void renderTargetItem(Graphics2D graphics, NPC actor, BufferedImage image) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java index da2c473f0c..5c32ba6e73 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java @@ -26,12 +26,11 @@ package net.runelite.client.plugins.slayer; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import static java.util.Arrays.asList; import java.util.Collections; import java.util.List; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap; import java.util.Map; import lombok.Getter; import net.runelite.api.ItemID; @@ -103,7 +102,7 @@ enum Task CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", ItemID.FEDORA), CROCODILES("Crocodiles", ItemID.SWAMP_LIZARD), DAGANNOTH("Dagannoth", ItemID.DAGANNOTH, - asList("Dagannoth Rex", "Dagannoth Prime", "Dagannoth Supreme"), Collections.emptyList()), + asList("Dagannoth Rex", "Dagannoth Prime", "Dagannoth Supreme"), Collections.emptyList()), DAGANNOTH_KINGS("Dagannoth Kings", ItemID.PET_DAGANNOTH_PRIME, asList("Dagannoth Rex", "Dagannoth Prime", "Dagannoth Supreme"), Collections.emptyList()), DARK_BEASTS("Dark beasts", ItemID.DARK_BEAST, @@ -311,7 +310,7 @@ enum Task this.checkAsTokens = true; } - Task(String name, int itemSpriteId, List targetNames, List npcIds, int weaknessThreshold, int weaknessItem) + Task(String name, int itemSpriteId, List targetNames, List npcIds, int weaknessThreshold, int weaknessItem) { Preconditions.checkArgument(itemSpriteId >= 0); this.name = name; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskData.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskData.java index 3e2cec384a..9a641a7a87 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskData.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskData.java @@ -6,7 +6,7 @@ import lombok.Data; @Data @AllArgsConstructor -@Builder(toBuilder=true) +@Builder(toBuilder = true) public class TaskData { private long elapsedTime; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/QuestGuideLinks.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/QuestGuideLinks.java index c61fa5e81c..5d18ff9110 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/QuestGuideLinks.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/QuestGuideLinks.java @@ -1,207 +1,217 @@ package net.runelite.client.plugins.slayermusiq; -import net.runelite.client.util.LinkBrowser; import net.runelite.api.ChatMessageType; -import net.runelite.api.events.ChatMessage; import net.runelite.client.chat.ChatColorType; import net.runelite.client.chat.ChatMessageBuilder; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.QueuedMessage; +import net.runelite.client.util.LinkBrowser; -public class QuestGuideLinks { - private static final Link[] QUEST_GUIDE_LINKS = { - // Free Quests - new Link("Cook's Assistant", "https://www.youtube.com/watch?v=ehmtDRelj3c"), - new Link("Romeo & Juliet", "https://www.youtube.com/watch?v=rH_biWSNWVY"), - new Link("Demon Slayer", "https://www.youtube.com/watch?v=hgACrzJSiQk"), - new Link("Shield of Arrav", "https://www.youtube.com/watch?v=a_imLDKUdzg"), - new Link("Sheep Shearer", "https://www.youtube.com/watch?v=XFG3aNwK68s"), - new Link("The Restless Ghost", "https://www.youtube.com/watch?v=UkWNcsG_pXM"), - new Link("Ernest the Chicken", "https://www.youtube.com/watch?v=cq8NIVhSqh4"), - new Link("Vampire Slayer", "https://www.youtube.com/watch?v=FcEuxsDJWCU"), - new Link("Imp Catcher", "https://www.youtube.com/watch?v=LHgnl0FbOzk"), - new Link("Prince Ali Rescue", "https://www.youtube.com/watch?v=hrSPl1GfFaw"), - new Link("Doric's Quest", "https://www.youtube.com/watch?v=5TYyxHU27a4"), - new Link("Black Knights' Fortress", "https://www.youtube.com/watch?v=aekoZi3f9cU"), - new Link("Witch's Potion", "https://www.youtube.com/watch?v=XV4i5sPUvXo"), - new Link("The Knight's Sword", "https://www.youtube.com/watch?v=UkBWaI0rOqE"), - new Link("Goblin Diplomacy", "https://www.youtube.com/watch?v=P9BKOb_dLoY"), - new Link("Pirate's Treasure", "https://www.youtube.com/watch?v=zcD87PQW8Qk"), - new Link("Dragon Slayer", "https://www.youtube.com/watch?v=bMtCjlFOaBI"), - new Link("Rune Mysteries", "https://www.youtube.com/watch?v=l8ZhaN8uoS0"), - new Link("Misthalin Mystery", "https://www.youtube.com/watch?v=QlFqVAobAlQ"), - new Link("The Corsair Curse", "https://www.youtube.com/watch?v=wi7mUAHExz4"), - new Link("X Marks the Spot", "https://www.youtube.com/watch?v=GhRgvEG5jxQ"), - // Members Quests - new Link("Druidic Ritual", "https://www.youtube.com/watch?v=QIfU6HSmH4w"), - new Link("Lost City", "https://www.youtube.com/watch?v=T-kQNUSjFZI"), - new Link("Witch's House", "https://www.youtube.com/watch?v=TLsg7Wa-LUA"), - new Link("Merlin's Crystal", "https://www.youtube.com/watch?v=ESX-qriNtCE"), - new Link("Heroes' Quest", "https://www.youtube.com/watch?v=hK2N0WLKviE"), - new Link("Scorpion Catcher", "https://www.youtube.com/watch?v=xpqdec7_ZWg"), - new Link("Family Crest", "https://www.youtube.com/watch?v=0mk_Cgjr738"), - new Link("Monk's Friend", "https://www.youtube.com/watch?v=avi4y4G3Hcw"), - new Link("Temple of Ikov", "https://www.youtube.com/watch?v=5K7jDgr_4Z4"), - new Link("Clock Tower", "https://www.youtube.com/watch?v=GUCkkQFzyDw"), - new Link("Holy Grail", "https://www.youtube.com/watch?v=cgXoV1QlYco"), - new Link("Tree Gnome Village", "https://www.youtube.com/watch?v=T6Su__yuyRI"), - new Link("Fight Arena", "https://www.youtube.com/watch?v=4Nqjep2E5pw"), - new Link("Hazeel Cult", "https://www.youtube.com/watch?v=2_fhFJW6cNY"), - new Link("Sheep Herder", "https://www.youtube.com/watch?v=akC9FeYCG1Q"), - new Link("Plague City", "https://www.youtube.com/watch?v=Hf2wQQZL5CU"), - new Link("Waterfall Quest", "https://www.youtube.com/watch?v=xWBSnGkQTi4"), - new Link("Jungle Potion", "https://www.youtube.com/watch?v=xqLKsFz08As"), - new Link("The Grand Tree", "https://www.youtube.com/watch?v=N5e_Jus_E-Y"), - new Link("Underground Pass", "https://www.youtube.com/watch?v=5klGJg1wY8k"), - new Link("Observatory Quest", "https://www.youtube.com/watch?v=yxa9B6svv44"), - new Link("Watchtower", "https://www.youtube.com/watch?v=Vb10GoYP7FE"), - new Link("Dwarf Cannon", "https://www.youtube.com/watch?v=pROFg5jcCR0"), - new Link("Murder Mystery", "https://www.youtube.com/watch?v=P1IDGCA2f9o"), - new Link("The Dig Site", "https://www.youtube.com/watch?v=TOdcWV4MzuU"), - new Link("Gertrude's Cat", "https://www.youtube.com/watch?v=g7S09wA8EAY"), - new Link("Legends' Quest", "https://www.youtube.com/watch?v=Lid8enDEF_U"), - new Link("Death Plateau", "https://www.youtube.com/watch?v=SIQFmTvnb6w"), - new Link("Big Chompy Bird Hunting", "https://www.youtube.com/watch?v=s2fytMOHJXI"), - new Link("Elemental Workshop I", "https://www.youtube.com/watch?v=tbZD2RDqvfQ"), - new Link("Nature Spirit", "https://www.youtube.com/watch?v=Enf8vUWb5o0"), - new Link("Priest in Peril", "https://www.youtube.com/watch?v=fyYri6wUQIU"), - new Link("Regicide", "https://www.youtube.com/watch?v=KkWM-ok3C4Y"), - new Link("Tai Bwo Wannai Trio", "https://www.youtube.com/watch?v=Mdair5mvZL0"), - new Link("Troll Stronghold", "https://www.youtube.com/watch?v=zqmUs-f3AKA"), - new Link("Horror from the Deep", "https://www.youtube.com/watch?v=9htK8kb6DR8"), - new Link("Throne of Miscellania", "https://www.youtube.com/watch?v=fzGMnv2skBE"), - new Link("Monkey Madness I", "https://www.youtube.com/watch?v=VnoRfeBnPFA"), - new Link("Haunted Mine", "https://www.youtube.com/watch?v=cIc6loJHm9Q"), - new Link("Troll Romance", "https://www.youtube.com/watch?v=j2zifZVu7Gc"), - new Link("In Search of the Myreque", "https://www.youtube.com/watch?v=5nmYFHdAXAQ"), - new Link("Creature of Fenkenstrain", "https://www.youtube.com/watch?v=swqUVIs7B7M"), - new Link("Roving Elves", "https://www.youtube.com/watch?v=J3qf9DnT9cA"), - new Link("One Small Favour", "https://www.youtube.com/watch?v=ix_0-W3e9ps"), - new Link("Mountain Daughter", "https://www.youtube.com/watch?v=HETx_LX7aiY"), - new Link("Between a Rock...", "https://www.youtube.com/watch?v=cB11I45EGgA"), - new Link("The Golem", "https://www.youtube.com/watch?v=qpEHpiO6lLw"), - new Link("Desert Treasure", "https://www.youtube.com/watch?v=BuIqulIsICo"), - new Link("Icthlarin's Little Helper", "https://www.youtube.com/watch?v=wpNKm8_vUOM"), - new Link("Tears of Guthix", "https://www.youtube.com/watch?v=EMonDNI0uPk"), - new Link("The Lost Tribe", "https://www.youtube.com/watch?v=spZErjRnCdc"), - new Link("The Giant Dwarf", "https://www.youtube.com/watch?v=Z7PsGpOYgxY"), - new Link("Recruitment Drive", "https://www.youtube.com/watch?v=sOuzMpA_xtw"), - new Link("Mourning's Ends Part I", "https://www.youtube.com/watch?v=vuzAdk-h3c0"), - new Link("Garden of Tranquillity", "https://www.youtube.com/watch?v=7hbCzYnLCsQ"), - new Link("A Tail of Two Cats", "https://www.youtube.com/watch?v=SgN9Yw_YqHk"), - new Link("Wanted!", "https://www.youtube.com/watch?v=ZHZAKDCfXGs"), - new Link("Mourning's Ends Part II", "https://www.youtube.com/watch?v=FK5sLogGbU8"), - new Link("Rum Deal", "https://www.youtube.com/watch?v=I14CIu5x2S8"), - new Link("Shadow of the Storm", "https://www.youtube.com/watch?v=5ZvWd3XCQjI"), - new Link("Ratcatchers", "https://www.youtube.com/watch?v=s7G22fEuhTc"), - new Link("Spirits of the Elid", "https://www.youtube.com/watch?v=A1zAX55hZC0"), - new Link("Devious Minds", "https://www.youtube.com/watch?v=_UtlFmrWt1w"), - new Link("Enakhra's Lament", "https://www.youtube.com/watch?v=Y3kEIPYVaVE"), - new Link("Cabin Fever", "https://www.youtube.com/watch?v=k5DtxNXhOaw"), - new Link("Fairytale I - Growing Pains", "https://www.youtube.com/watch?v=cfGI9qFOmsg"), - new Link("Recipe for Disaster", "https://www.youtube.com/watch?v=hrAyyInJaTA"), - new Link("In Aid of the Myreque", "https://www.youtube.com/watch?v=O2Ru2NmuTaA"), - new Link("A Soul's Bane", "https://www.youtube.com/watch?v=dp8dp79qp6I"), - new Link("Rag and Bone Man", "https://www.youtube.com/watch?v=3owXSeN56W8"), - new Link("Swan Song", "https://www.youtube.com/watch?v=IpmERThXv2g"), - new Link("Royal Trouble", "https://www.youtube.com/watch?v=bVWUlKzNXEg"), - new Link("Death to the Dorgeshuun", "https://www.youtube.com/watch?v=2XJHuLhig98"), - new Link("Fairytale II - Cure a Queen", "https://www.youtube.com/watch?v=P6KkRk4_e3U"), - new Link("Lunar Diplomacy", "https://www.youtube.com/watch?v=vmeSKb7IBgQ"), - new Link("The Eyes of Glouphrie", "https://www.youtube.com/watch?v=0YCPwmZcxKA"), - new Link("Darkness of Hallowvale", "https://www.youtube.com/watch?v=QziKl99qdtU"), - new Link("Elemental Workshop II", "https://www.youtube.com/watch?v=Bb4E7ecIgv0"), - new Link("My Arm's Big Adventure", "https://www.youtube.com/watch?v=xa1KWOewgYA"), - new Link("Enlightened Journey", "https://www.youtube.com/watch?v=XAPthC8d7k0"), - new Link("Eagles' Peak", "https://www.youtube.com/watch?v=KDxIrrwXp7U"), - new Link("Animal Magnetism", "https://www.youtube.com/watch?v=kUyjXA7TaFU"), - new Link("Contact!", "https://www.youtube.com/watch?v=czn-yWABBWs"), - new Link("Cold War", "https://www.youtube.com/watch?v=0m1KpP-qKWI"), - new Link("The Fremennik Isles", "https://www.youtube.com/watch?v=EvxhiOWmraY"), - new Link("The Great Brain Robbery", "https://www.youtube.com/watch?v=ImHFASuNUN8"), - new Link("What Lies Below", "https://www.youtube.com/watch?v=f_9nVMGTtuo"), - new Link("Olaf's Quest", "https://www.youtube.com/watch?v=mXV5bM1NFMM"), - new Link("Dream Mentor", "https://www.youtube.com/watch?v=XDLUu0Kf0sE"), - new Link("Grim Tales", "https://www.youtube.com/watch?v=dFB0Q6v8Apw"), - new Link("King's Ransom", "https://www.youtube.com/watch?v=UJz9ZfF3uCY"), - new Link("Shilo Village", "https://www.youtube.com/watch?v=bDvBi8FT-QI"), - new Link("Biohazard", "https://www.youtube.com/watch?v=n9k87LwOGMk"), - new Link("Tower of Life", "https://www.youtube.com/watch?v=KReMcWpeY3k"), - new Link("Rag and Bone Man II", "https://www.youtube.com/watch?v=KGdHiDDUX_U"), - new Link("Zogre Flesh Eaters", "https://www.youtube.com/watch?v=vzm4949kXP4"), - new Link("Monkey Madness II", "https://www.youtube.com/watch?v=ykE5LbjABaI"), - new Link("Client of Kourend", "https://www.youtube.com/watch?v=Y-KIHF-cL9w"), - new Link("The Queen of Thieves", "https://www.youtube.com/watch?v=W94zFZVrHkQ"), - new Link("Bone Voyage", "https://www.youtube.com/watch?v=-VTR4p8kPmI"), - new Link("Dragon Slayer II", "https://www.youtube.com/watch?v=4BMb3Zwzk_U"), - new Link("The Depths of Despair", "https://www.youtube.com/watch?v=CaVUk2eAsKs"), - new Link("A Taste of Hope", "https://www.youtube.com/watch?v=VjdgEIizdSc"), - new Link("Tale of the Righteous", "https://www.youtube.com/watch?v=99yiv0tPl58"), - new Link("Making Friends with My Arm", "https://www.youtube.com/watch?v=DltzzhIsM_Q"), - new Link("The Ascent of Arceuus", "https://www.youtube.com/watch?v=4VQnfrv6S18"), - new Link("The Forsaken Tower", "https://www.youtube.com/watch?v=con0sXl5NBY"), - new Link("Fishing Contest", "https://www.youtube.com/watch?v=XYSv37A_l5w"), - new Link("Tribal Totem", "https://www.youtube.com/watch?v=XkUEIjr886M"), - new Link("Sea Slug", "https://www.youtube.com/watch?v=oOZVfa5SkVQ"), - new Link("The Tourist Trap", "https://www.youtube.com/watch?v=0bmSCCepMvo"), - new Link("Eadgar's Ruse", "https://www.youtube.com/watch?v=aVQ3DjTElXg"), - new Link("Shades of Mort'ton", "https://www.youtube.com/watch?v=eF05R8OMxgg"), - new Link("The Fremennik Trials", "https://www.youtube.com/watch?v=YUIvEgcvl5c"), - new Link("Ghosts Ahoy", "https://www.youtube.com/watch?v=aNBkLOywDfM"), - new Link("The Feud", "https://www.youtube.com/watch?v=nlBSc9IUklA"), - new Link("Forgettable Tale...", "https://www.youtube.com/watch?v=3HvFd6AxNU0"), - new Link("Making History", "https://www.youtube.com/watch?v=bOTGi2zAuhs"), - new Link("The Hand in the Sand", "https://www.youtube.com/watch?v=gdNLcZ-l1Lw"), - new Link("The Slug Menace", "https://www.youtube.com/watch?v=BRQbdr3JEZ8"), - new Link("Another Slice of H.A.M.", "https://www.youtube.com/watch?v=Yq3db7827Lk") - }; +class QuestGuideLinks +{ + private static final Link[] QUEST_GUIDE_LINKS = { + // Free Quests + new Link("Cook's Assistant", "https://www.youtube.com/watch?v=ehmtDRelj3c"), + new Link("Romeo & Juliet", "https://www.youtube.com/watch?v=rH_biWSNWVY"), + new Link("Demon Slayer", "https://www.youtube.com/watch?v=hgACrzJSiQk"), + new Link("Shield of Arrav", "https://www.youtube.com/watch?v=a_imLDKUdzg"), + new Link("Sheep Shearer", "https://www.youtube.com/watch?v=XFG3aNwK68s"), + new Link("The Restless Ghost", "https://www.youtube.com/watch?v=UkWNcsG_pXM"), + new Link("Ernest the Chicken", "https://www.youtube.com/watch?v=cq8NIVhSqh4"), + new Link("Vampire Slayer", "https://www.youtube.com/watch?v=FcEuxsDJWCU"), + new Link("Imp Catcher", "https://www.youtube.com/watch?v=LHgnl0FbOzk"), + new Link("Prince Ali Rescue", "https://www.youtube.com/watch?v=hrSPl1GfFaw"), + new Link("Doric's Quest", "https://www.youtube.com/watch?v=5TYyxHU27a4"), + new Link("Black Knights' Fortress", "https://www.youtube.com/watch?v=aekoZi3f9cU"), + new Link("Witch's Potion", "https://www.youtube.com/watch?v=XV4i5sPUvXo"), + new Link("The Knight's Sword", "https://www.youtube.com/watch?v=UkBWaI0rOqE"), + new Link("Goblin Diplomacy", "https://www.youtube.com/watch?v=P9BKOb_dLoY"), + new Link("Pirate's Treasure", "https://www.youtube.com/watch?v=zcD87PQW8Qk"), + new Link("Dragon Slayer", "https://www.youtube.com/watch?v=bMtCjlFOaBI"), + new Link("Rune Mysteries", "https://www.youtube.com/watch?v=l8ZhaN8uoS0"), + new Link("Misthalin Mystery", "https://www.youtube.com/watch?v=QlFqVAobAlQ"), + new Link("The Corsair Curse", "https://www.youtube.com/watch?v=wi7mUAHExz4"), + new Link("X Marks the Spot", "https://www.youtube.com/watch?v=GhRgvEG5jxQ"), + // Members Quests + new Link("Druidic Ritual", "https://www.youtube.com/watch?v=QIfU6HSmH4w"), + new Link("Lost City", "https://www.youtube.com/watch?v=T-kQNUSjFZI"), + new Link("Witch's House", "https://www.youtube.com/watch?v=TLsg7Wa-LUA"), + new Link("Merlin's Crystal", "https://www.youtube.com/watch?v=ESX-qriNtCE"), + new Link("Heroes' Quest", "https://www.youtube.com/watch?v=hK2N0WLKviE"), + new Link("Scorpion Catcher", "https://www.youtube.com/watch?v=xpqdec7_ZWg"), + new Link("Family Crest", "https://www.youtube.com/watch?v=0mk_Cgjr738"), + new Link("Monk's Friend", "https://www.youtube.com/watch?v=avi4y4G3Hcw"), + new Link("Temple of Ikov", "https://www.youtube.com/watch?v=5K7jDgr_4Z4"), + new Link("Clock Tower", "https://www.youtube.com/watch?v=GUCkkQFzyDw"), + new Link("Holy Grail", "https://www.youtube.com/watch?v=cgXoV1QlYco"), + new Link("Tree Gnome Village", "https://www.youtube.com/watch?v=T6Su__yuyRI"), + new Link("Fight Arena", "https://www.youtube.com/watch?v=4Nqjep2E5pw"), + new Link("Hazeel Cult", "https://www.youtube.com/watch?v=2_fhFJW6cNY"), + new Link("Sheep Herder", "https://www.youtube.com/watch?v=akC9FeYCG1Q"), + new Link("Plague City", "https://www.youtube.com/watch?v=Hf2wQQZL5CU"), + new Link("Waterfall Quest", "https://www.youtube.com/watch?v=xWBSnGkQTi4"), + new Link("Jungle Potion", "https://www.youtube.com/watch?v=xqLKsFz08As"), + new Link("The Grand Tree", "https://www.youtube.com/watch?v=N5e_Jus_E-Y"), + new Link("Underground Pass", "https://www.youtube.com/watch?v=5klGJg1wY8k"), + new Link("Observatory Quest", "https://www.youtube.com/watch?v=yxa9B6svv44"), + new Link("Watchtower", "https://www.youtube.com/watch?v=Vb10GoYP7FE"), + new Link("Dwarf Cannon", "https://www.youtube.com/watch?v=pROFg5jcCR0"), + new Link("Murder Mystery", "https://www.youtube.com/watch?v=P1IDGCA2f9o"), + new Link("The Dig Site", "https://www.youtube.com/watch?v=TOdcWV4MzuU"), + new Link("Gertrude's Cat", "https://www.youtube.com/watch?v=g7S09wA8EAY"), + new Link("Legends' Quest", "https://www.youtube.com/watch?v=Lid8enDEF_U"), + new Link("Death Plateau", "https://www.youtube.com/watch?v=SIQFmTvnb6w"), + new Link("Big Chompy Bird Hunting", "https://www.youtube.com/watch?v=s2fytMOHJXI"), + new Link("Elemental Workshop I", "https://www.youtube.com/watch?v=tbZD2RDqvfQ"), + new Link("Nature Spirit", "https://www.youtube.com/watch?v=Enf8vUWb5o0"), + new Link("Priest in Peril", "https://www.youtube.com/watch?v=fyYri6wUQIU"), + new Link("Regicide", "https://www.youtube.com/watch?v=KkWM-ok3C4Y"), + new Link("Tai Bwo Wannai Trio", "https://www.youtube.com/watch?v=Mdair5mvZL0"), + new Link("Troll Stronghold", "https://www.youtube.com/watch?v=zqmUs-f3AKA"), + new Link("Horror from the Deep", "https://www.youtube.com/watch?v=9htK8kb6DR8"), + new Link("Throne of Miscellania", "https://www.youtube.com/watch?v=fzGMnv2skBE"), + new Link("Monkey Madness I", "https://www.youtube.com/watch?v=VnoRfeBnPFA"), + new Link("Haunted Mine", "https://www.youtube.com/watch?v=cIc6loJHm9Q"), + new Link("Troll Romance", "https://www.youtube.com/watch?v=j2zifZVu7Gc"), + new Link("In Search of the Myreque", "https://www.youtube.com/watch?v=5nmYFHdAXAQ"), + new Link("Creature of Fenkenstrain", "https://www.youtube.com/watch?v=swqUVIs7B7M"), + new Link("Roving Elves", "https://www.youtube.com/watch?v=J3qf9DnT9cA"), + new Link("One Small Favour", "https://www.youtube.com/watch?v=ix_0-W3e9ps"), + new Link("Mountain Daughter", "https://www.youtube.com/watch?v=HETx_LX7aiY"), + new Link("Between a Rock...", "https://www.youtube.com/watch?v=cB11I45EGgA"), + new Link("The Golem", "https://www.youtube.com/watch?v=qpEHpiO6lLw"), + new Link("Desert Treasure", "https://www.youtube.com/watch?v=BuIqulIsICo"), + new Link("Icthlarin's Little Helper", "https://www.youtube.com/watch?v=wpNKm8_vUOM"), + new Link("Tears of Guthix", "https://www.youtube.com/watch?v=EMonDNI0uPk"), + new Link("The Lost Tribe", "https://www.youtube.com/watch?v=spZErjRnCdc"), + new Link("The Giant Dwarf", "https://www.youtube.com/watch?v=Z7PsGpOYgxY"), + new Link("Recruitment Drive", "https://www.youtube.com/watch?v=sOuzMpA_xtw"), + new Link("Mourning's Ends Part I", "https://www.youtube.com/watch?v=vuzAdk-h3c0"), + new Link("Garden of Tranquillity", "https://www.youtube.com/watch?v=7hbCzYnLCsQ"), + new Link("A Tail of Two Cats", "https://www.youtube.com/watch?v=SgN9Yw_YqHk"), + new Link("Wanted!", "https://www.youtube.com/watch?v=ZHZAKDCfXGs"), + new Link("Mourning's Ends Part II", "https://www.youtube.com/watch?v=FK5sLogGbU8"), + new Link("Rum Deal", "https://www.youtube.com/watch?v=I14CIu5x2S8"), + new Link("Shadow of the Storm", "https://www.youtube.com/watch?v=5ZvWd3XCQjI"), + new Link("Ratcatchers", "https://www.youtube.com/watch?v=s7G22fEuhTc"), + new Link("Spirits of the Elid", "https://www.youtube.com/watch?v=A1zAX55hZC0"), + new Link("Devious Minds", "https://www.youtube.com/watch?v=_UtlFmrWt1w"), + new Link("Enakhra's Lament", "https://www.youtube.com/watch?v=Y3kEIPYVaVE"), + new Link("Cabin Fever", "https://www.youtube.com/watch?v=k5DtxNXhOaw"), + new Link("Fairytale I - Growing Pains", "https://www.youtube.com/watch?v=cfGI9qFOmsg"), + new Link("Recipe for Disaster", "https://www.youtube.com/watch?v=hrAyyInJaTA"), + new Link("In Aid of the Myreque", "https://www.youtube.com/watch?v=O2Ru2NmuTaA"), + new Link("A Soul's Bane", "https://www.youtube.com/watch?v=dp8dp79qp6I"), + new Link("Rag and Bone Man", "https://www.youtube.com/watch?v=3owXSeN56W8"), + new Link("Swan Song", "https://www.youtube.com/watch?v=IpmERThXv2g"), + new Link("Royal Trouble", "https://www.youtube.com/watch?v=bVWUlKzNXEg"), + new Link("Death to the Dorgeshuun", "https://www.youtube.com/watch?v=2XJHuLhig98"), + new Link("Fairytale II - Cure a Queen", "https://www.youtube.com/watch?v=P6KkRk4_e3U"), + new Link("Lunar Diplomacy", "https://www.youtube.com/watch?v=vmeSKb7IBgQ"), + new Link("The Eyes of Glouphrie", "https://www.youtube.com/watch?v=0YCPwmZcxKA"), + new Link("Darkness of Hallowvale", "https://www.youtube.com/watch?v=QziKl99qdtU"), + new Link("Elemental Workshop II", "https://www.youtube.com/watch?v=Bb4E7ecIgv0"), + new Link("My Arm's Big Adventure", "https://www.youtube.com/watch?v=xa1KWOewgYA"), + new Link("Enlightened Journey", "https://www.youtube.com/watch?v=XAPthC8d7k0"), + new Link("Eagles' Peak", "https://www.youtube.com/watch?v=KDxIrrwXp7U"), + new Link("Animal Magnetism", "https://www.youtube.com/watch?v=kUyjXA7TaFU"), + new Link("Contact!", "https://www.youtube.com/watch?v=czn-yWABBWs"), + new Link("Cold War", "https://www.youtube.com/watch?v=0m1KpP-qKWI"), + new Link("The Fremennik Isles", "https://www.youtube.com/watch?v=EvxhiOWmraY"), + new Link("The Great Brain Robbery", "https://www.youtube.com/watch?v=ImHFASuNUN8"), + new Link("What Lies Below", "https://www.youtube.com/watch?v=f_9nVMGTtuo"), + new Link("Olaf's Quest", "https://www.youtube.com/watch?v=mXV5bM1NFMM"), + new Link("Dream Mentor", "https://www.youtube.com/watch?v=XDLUu0Kf0sE"), + new Link("Grim Tales", "https://www.youtube.com/watch?v=dFB0Q6v8Apw"), + new Link("King's Ransom", "https://www.youtube.com/watch?v=UJz9ZfF3uCY"), + new Link("Shilo Village", "https://www.youtube.com/watch?v=bDvBi8FT-QI"), + new Link("Biohazard", "https://www.youtube.com/watch?v=n9k87LwOGMk"), + new Link("Tower of Life", "https://www.youtube.com/watch?v=KReMcWpeY3k"), + new Link("Rag and Bone Man II", "https://www.youtube.com/watch?v=KGdHiDDUX_U"), + new Link("Zogre Flesh Eaters", "https://www.youtube.com/watch?v=vzm4949kXP4"), + new Link("Monkey Madness II", "https://www.youtube.com/watch?v=ykE5LbjABaI"), + new Link("Client of Kourend", "https://www.youtube.com/watch?v=Y-KIHF-cL9w"), + new Link("The Queen of Thieves", "https://www.youtube.com/watch?v=W94zFZVrHkQ"), + new Link("Bone Voyage", "https://www.youtube.com/watch?v=-VTR4p8kPmI"), + new Link("Dragon Slayer II", "https://www.youtube.com/watch?v=4BMb3Zwzk_U"), + new Link("The Depths of Despair", "https://www.youtube.com/watch?v=CaVUk2eAsKs"), + new Link("A Taste of Hope", "https://www.youtube.com/watch?v=VjdgEIizdSc"), + new Link("Tale of the Righteous", "https://www.youtube.com/watch?v=99yiv0tPl58"), + new Link("Making Friends with My Arm", "https://www.youtube.com/watch?v=DltzzhIsM_Q"), + new Link("The Ascent of Arceuus", "https://www.youtube.com/watch?v=4VQnfrv6S18"), + new Link("The Forsaken Tower", "https://www.youtube.com/watch?v=con0sXl5NBY"), + new Link("Fishing Contest", "https://www.youtube.com/watch?v=XYSv37A_l5w"), + new Link("Tribal Totem", "https://www.youtube.com/watch?v=XkUEIjr886M"), + new Link("Sea Slug", "https://www.youtube.com/watch?v=oOZVfa5SkVQ"), + new Link("The Tourist Trap", "https://www.youtube.com/watch?v=0bmSCCepMvo"), + new Link("Eadgar's Ruse", "https://www.youtube.com/watch?v=aVQ3DjTElXg"), + new Link("Shades of Mort'ton", "https://www.youtube.com/watch?v=eF05R8OMxgg"), + new Link("The Fremennik Trials", "https://www.youtube.com/watch?v=YUIvEgcvl5c"), + new Link("Ghosts Ahoy", "https://www.youtube.com/watch?v=aNBkLOywDfM"), + new Link("The Feud", "https://www.youtube.com/watch?v=nlBSc9IUklA"), + new Link("Forgettable Tale...", "https://www.youtube.com/watch?v=3HvFd6AxNU0"), + new Link("Making History", "https://www.youtube.com/watch?v=bOTGi2zAuhs"), + new Link("The Hand in the Sand", "https://www.youtube.com/watch?v=gdNLcZ-l1Lw"), + new Link("The Slug Menace", "https://www.youtube.com/watch?v=BRQbdr3JEZ8"), + new Link("Another Slice of H.A.M.", "https://www.youtube.com/watch?v=Yq3db7827Lk") + }; - private static class Link { + private static class Link + { - private String questName; - private String url; + private String questName; + private String url; - public Link(String questName, String url) { - this.questName = questName; - this.url = url; - } + Link(String questName, String url) + { + this.questName = questName; + this.url = url; + } - public String getQuestName() { - return questName; - } + String getQuestName() + { + return questName; + } - public void openURL() { - LinkBrowser.browse(this.url); - } + void openURL() + { + LinkBrowser.browse(this.url); + } - } + } - private static boolean openGuide(String questName) { - for (Link link : QUEST_GUIDE_LINKS) { - if (link.getQuestName().equals(questName)) { - link.openURL(); - return true; - } - } - return false; - } + private static boolean openGuide(String questName) + { + for (Link link : QUEST_GUIDE_LINKS) + { + if (link.getQuestName().equals(questName)) + { + link.openURL(); + return true; + } + } + return false; + } - private static void logQuestNotFoundError(String questName, ChatMessageManager chatMessageManager) { - String chatMessage = new ChatMessageBuilder() - .append(ChatColorType.HIGHLIGHT) - .append("Could not find Slayermusiq1 guide for " + questName) - .build(); + private static void logQuestNotFoundError(String questName, ChatMessageManager chatMessageManager) + { + String chatMessage = new ChatMessageBuilder() + .append(ChatColorType.HIGHLIGHT) + .append("Could not find Slayermusiq1 guide for " + questName) + .build(); - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.GAMEMESSAGE) - .runeLiteFormattedMessage(chatMessage) - .build()); - } + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.GAMEMESSAGE) + .runeLiteFormattedMessage(chatMessage) + .build()); + } - public static void tryOpenGuide(String questName, ChatMessageManager chatMessageManager) { - boolean success = openGuide(questName); - if (!success) { - logQuestNotFoundError(questName, chatMessageManager); - } - } + static void tryOpenGuide(String questName, ChatMessageManager chatMessageManager) + { + boolean success = openGuide(questName); + if (!success) + { + logQuestNotFoundError(questName, chatMessageManager); + } + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/SlayermusiqPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/SlayermusiqPlugin.java index d828eadd57..d8bca0ca18 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/SlayermusiqPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayermusiq/SlayermusiqPlugin.java @@ -51,30 +51,22 @@ */ package net.runelite.client.plugins.slayermusiq; -import com.google.inject.Provides; import com.google.common.primitives.Ints; -import java.awt.Dimension; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import javax.inject.Inject; -import javax.swing.SwingUtilities; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; -import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.util.Text; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.util.Text; @PluginDescriptor( name = "Slayermusiq1 Guides", @@ -118,7 +110,8 @@ public class SlayermusiqPlugin extends Plugin public void onMenuEntryAdded(MenuEntryAdded event) { int widgetID = event.getActionParam1(); - if (Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) && "Read Journal:".equals(event.getOption())) { + if (Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) && "Read Journal:".equals(event.getOption())) + { MenuEntry[] menuEntries = client.getMenuEntries(); MenuEntry newMenuEntry = createSlayermusiqOptionMenuEntry(event); @@ -130,15 +123,18 @@ public class SlayermusiqPlugin extends Plugin } @Subscribe - private void onMenuOptionClicked(MenuOptionClicked ev) { - if (ev.getMenuAction() == MenuAction.RUNELITE && ev.getMenuOption().equals(MENUOP_SLAYERMUSIQ)) { + private void onMenuOptionClicked(MenuOptionClicked ev) + { + if (ev.getMenuAction() == MenuAction.RUNELITE && ev.getMenuOption().equals(MENUOP_SLAYERMUSIQ)) + { ev.consume(); String quest = Text.removeTags(ev.getMenuTarget()); QuestGuideLinks.tryOpenGuide(quest, chatMessageManager); } } - private MenuEntry createSlayermusiqOptionMenuEntry(MenuEntryAdded event) { + private MenuEntry createSlayermusiqOptionMenuEntry(MenuEntryAdded event) + { int widgetIndex = event.getActionParam0(); int widgetID = event.getActionParam1(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java index 7a49c00144..7b140dbd61 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingOverlay.java @@ -79,16 +79,16 @@ class SmeltingOverlay extends Overlay if (isSmelting() || Duration.between(session.getLastItemSmelted(), Instant.now()).getSeconds() < SMELT_TIMEOUT) { panelComponent.getChildren().add(TitleComponent.builder() - .text("Smelting") - .color(Color.GREEN) - .build()); + .text("Smelting") + .color(Color.GREEN) + .build()); } else { panelComponent.getChildren().add(TitleComponent.builder() - .text("NOT smelting") - .color(Color.RED) - .build()); + .text("NOT smelting") + .color(Color.RED) + .build()); } int actions = xpTrackerService.getActions(Skill.SMITHING); @@ -97,23 +97,23 @@ class SmeltingOverlay extends Overlay if (plugin.getSession().getBarsSmelted() > 0) { panelComponent.getChildren().add(LineComponent.builder() - .left("Bars:") - .right(Integer.toString(session.getBarsSmelted())) - .build()); + .left("Bars:") + .right(Integer.toString(session.getBarsSmelted())) + .build()); } if (plugin.getSession().getCannonBallsSmelted() > 0) { panelComponent.getChildren().add(LineComponent.builder() - .left("Cannonballs:") - .right(Integer.toString(session.getCannonBallsSmelted())) - .build()); + .left("Cannonballs:") + .right(Integer.toString(session.getCannonBallsSmelted())) + .build()); } if (actions > 2) { panelComponent.getChildren().add(LineComponent.builder() - .left("Actions/hr:") - .right(Integer.toString(xpTrackerService.getActionsHr(Skill.SMITHING))) - .build()); + .left("Actions/hr:") + .right(Integer.toString(xpTrackerService.getActionsHr(Skill.SMITHING))) + .build()); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/specbar/SpecBarPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/specbar/SpecBarPlugin.java index 7630f0292a..64622943b8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/specbar/SpecBarPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/specbar/SpecBarPlugin.java @@ -1,75 +1,74 @@ -package net.runelite.client.plugins.specbar; - -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.WidgetHiddenChanged; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetID; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginManager; -import net.runelite.client.plugins.PluginType; - -@PluginDescriptor( - name = "Spec Bar", - description = "Adds a spec bar to every weapon", - tags = {"spec bar", "special attack", "spec", "bar", "pklite"}, - enabledByDefault = false, - type = PluginType.PVP -) -public class SpecBarPlugin extends Plugin -{ - - @Inject - private Client client; - - @Override - protected void startUp() throws Exception - { - } - - @Override - protected void shutDown() throws Exception - { - } - - @Subscribe - private void onWidgetHiddenChanged(WidgetHiddenChanged event) - { - if (WidgetInfo.TO_GROUP(event.getWidget().getId()) == WidgetID.COMBAT_GROUP_ID) - { - hideSpecBar(); - } - } - - @Subscribe - private void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState().equals(GameState.LOGGING_IN)) - { - hideSpecBar(); - } - - } - - /** - * Displays the special attack bar - */ - private void hideSpecBar() - { - try - { - Widget specBar = client.getWidget(WidgetInfo.COMBAT_SPECIAL_ATTACK); - specBar.setHidden(false); - specBar.revalidate(); - } - catch (NullPointerException e) - { - // Stops the nulls that occur before the spec bar is loaded by player equipping a spec wep - } - } -} +package net.runelite.client.plugins.specbar; + +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.WidgetHiddenChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; + +@PluginDescriptor( + name = "Spec Bar", + description = "Adds a spec bar to every weapon", + tags = {"spec bar", "special attack", "spec", "bar", "pklite"}, + enabledByDefault = false, + type = PluginType.PVP +) +public class SpecBarPlugin extends Plugin +{ + + @Inject + private Client client; + + @Override + protected void startUp() throws Exception + { + } + + @Override + protected void shutDown() throws Exception + { + } + + @Subscribe + private void onWidgetHiddenChanged(WidgetHiddenChanged event) + { + if (WidgetInfo.TO_GROUP(event.getWidget().getId()) == WidgetID.COMBAT_GROUP_ID) + { + hideSpecBar(); + } + } + + @Subscribe + private void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState().equals(GameState.LOGGING_IN)) + { + hideSpecBar(); + } + + } + + /** + * Displays the special attack bar + */ + private void hideSpecBar() + { + try + { + Widget specBar = client.getWidget(WidgetInfo.COMBAT_SPECIAL_ATTACK); + specBar.setHidden(false); + specBar.revalidate(); + } + catch (NullPointerException e) + { + // Stops the nulls that occur before the spec bar is loaded by player equipping a spec wep + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/spellbook/SpellbookPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/spellbook/SpellbookPlugin.java index eaaa975c40..7184f341fe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/spellbook/SpellbookPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/spellbook/SpellbookPlugin.java @@ -78,10 +78,11 @@ public class SpellbookPlugin extends Plugin private static final String MENU_TARGET = "Reordering"; private static final WidgetMenuOption FIXED_MAGIC_TAB_LOCK = new WidgetMenuOption(LOCK, MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_MAGIC_TAB); private static final WidgetMenuOption FIXED_MAGIC_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_MAGIC_TAB); - private static final WidgetMenuOption RESIZABLE_MAGIC_TAB_LOCK = new WidgetMenuOption(LOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_MAGIC_TAB); - private static final WidgetMenuOption RESIZABLE_MAGIC_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_MAGIC_TAB); - private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_MAGIC_TAB_LOCK = new WidgetMenuOption(LOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_MAGIC_TAB); - private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_MAGIC_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_MAGIC_TAB); + private static final WidgetMenuOption RESIZABLE_MAGIC_TAB_LOCK = new WidgetMenuOption(LOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_MAGIC_TAB); + private static final WidgetMenuOption RESIZABLE_MAGIC_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_MAGIC_TAB); + private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_MAGIC_TAB_LOCK = new WidgetMenuOption(LOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_MAGIC_TAB); + private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_MAGIC_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_MAGIC_TAB); + private enum WordFilterMode { CONTAINS, @@ -382,9 +383,9 @@ public class SpellbookPlugin extends Plugin int widget = iStack[iStackSize - 1]; int visCount = (int) spells.values().stream() - .map(Spell::getName) - .filter(s -> isUnfiltered(s, tmp)) - .count(); + .map(Spell::getName) + .filter(s -> isUnfiltered(s, tmp)) + .count(); if (visCount > 20 || visCount == 0) { @@ -437,7 +438,9 @@ public class SpellbookPlugin extends Plugin } // CHECKSTYLE:OFF - Collection gson = GSON.fromJson(cfg, new TypeToken>(){}.getType()); + Collection gson = GSON.fromJson(cfg, new TypeToken>() + { + }.getType()); // CHECKSTYLE:ON gson.stream().filter(Objects::nonNull).forEach(s -> spells.put(s.getWidget(), s)); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsPlugin.java index e32895d910..bb7b766e50 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsPlugin.java @@ -1,132 +1,132 @@ -/* - * Copyright (c) 2018, Jos - * 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.statusbars; - -import java.time.Duration; -import java.time.Instant; -import java.util.Arrays; -import java.util.List; -import javax.inject.Inject; -import com.google.inject.Provides; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.Actor; -import net.runelite.api.Client; -import net.runelite.api.NPC; -import net.runelite.api.NPCComposition; -import net.runelite.api.events.GameTick; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDependency; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.itemstats.ItemStatPlugin; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "Status Bars", - description = "Draws status bars next to players inventory showing current HP & Prayer and healing amounts", - enabledByDefault = false -) -@PluginDependency(ItemStatPlugin.class) -public class StatusBarsPlugin extends Plugin -{ - @Inject - private StatusBarsOverlay overlay; - - @Inject - private OverlayManager overlayManager; - - @Inject - private Client client; - - @Inject - private StatusBarsConfig config; - - @Getter(AccessLevel.PACKAGE) - private Instant lastCombatAction; - - @Override - protected void startUp() throws Exception - { - } - - void updateLastCombatAction() - { - this.lastCombatAction = Instant.now(); - } - - @Subscribe - public void onGameTick(GameTick gameTick) - { - if (!config.toggleRestorationBars()) - { - overlayManager.add(overlay); - return; - } - else - { - hideStatusBar(); - } - } - - private void hideStatusBar() - { - final Actor interacting = client.getLocalPlayer().getInteracting(); - final boolean isNpc = interacting instanceof NPC; - final int combatTimeout = config.hideStatusBarDelay(); - - if (isNpc) - { - final NPC npc = (NPC) interacting; - final NPCComposition npcComposition = npc.getComposition(); - final List npcMenuActions = Arrays.asList(npcComposition.getActions()); - if (npcMenuActions.contains("Attack") && config.toggleRestorationBars()) - { - updateLastCombatAction(); - overlayManager.add(overlay); - } - } - else if (lastCombatAction != null) - { - if (Duration.between(getLastCombatAction(), Instant.now()).getSeconds() > combatTimeout) - { - overlayManager.remove(overlay); - } - } - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - } - - @Provides - StatusBarsConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(StatusBarsConfig.class); - } -} +/* + * Copyright (c) 2018, Jos + * 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.statusbars; + +import com.google.inject.Provides; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; +import net.runelite.api.events.GameTick; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDependency; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.itemstats.ItemStatPlugin; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Status Bars", + description = "Draws status bars next to players inventory showing current HP & Prayer and healing amounts", + enabledByDefault = false +) +@PluginDependency(ItemStatPlugin.class) +public class StatusBarsPlugin extends Plugin +{ + @Inject + private StatusBarsOverlay overlay; + + @Inject + private OverlayManager overlayManager; + + @Inject + private Client client; + + @Inject + private StatusBarsConfig config; + + @Getter(AccessLevel.PACKAGE) + private Instant lastCombatAction; + + @Override + protected void startUp() throws Exception + { + } + + void updateLastCombatAction() + { + this.lastCombatAction = Instant.now(); + } + + @Subscribe + public void onGameTick(GameTick gameTick) + { + if (!config.toggleRestorationBars()) + { + overlayManager.add(overlay); + return; + } + else + { + hideStatusBar(); + } + } + + private void hideStatusBar() + { + final Actor interacting = client.getLocalPlayer().getInteracting(); + final boolean isNpc = interacting instanceof NPC; + final int combatTimeout = config.hideStatusBarDelay(); + + if (isNpc) + { + final NPC npc = (NPC) interacting; + final NPCComposition npcComposition = npc.getComposition(); + final List npcMenuActions = Arrays.asList(npcComposition.getActions()); + if (npcMenuActions.contains("Attack") && config.toggleRestorationBars()) + { + updateLastCombatAction(); + overlayManager.add(overlay); + } + } + else if (lastCombatAction != null) + { + if (Duration.between(getLastCombatAction(), Instant.now()).getSeconds() > combatTimeout) + { + overlayManager.remove(overlay); + } + } + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + } + + @Provides + StatusBarsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(StatusBarsConfig.class); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/Viewport.java b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/Viewport.java index 737cda9df0..298ba7ea3e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/Viewport.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/Viewport.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2018, Jos - * 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.statusbars; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import net.runelite.api.Point; -import net.runelite.api.widgets.WidgetInfo; - -@Getter -@AllArgsConstructor -enum Viewport -{ - RESIZED_BOX(WidgetInfo.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX, WidgetInfo.RESIZABLE_VIEWPORT_INTERFACE_CONTAINER, - new Point(20, -4), new Point( 0, -4)), - RESIZED_BOTTOM(WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INTERFACE_CONTAINER, - new Point(61, 8), new Point(35, -12)), - FIXED(WidgetInfo.FIXED_VIEWPORT, WidgetInfo.FIXED_VIEWPORT_INTERFACE_CONTAINER, - new Point(20, -4), new Point(0, -4)); - - private WidgetInfo container; - private WidgetInfo viewport; - private Point offsetLeft; - private Point offsetRight; -} +/* + * Copyright (c) 2018, Jos + * 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.statusbars; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.runelite.api.Point; +import net.runelite.api.widgets.WidgetInfo; + +@Getter +@AllArgsConstructor +enum Viewport +{ + RESIZED_BOX(WidgetInfo.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX, WidgetInfo.RESIZABLE_VIEWPORT_INTERFACE_CONTAINER, + new Point(20, -4), new Point(0, -4)), + RESIZED_BOTTOM(WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INTERFACE_CONTAINER, + new Point(61, 8), new Point(35, -12)), + FIXED(WidgetInfo.FIXED_VIEWPORT, WidgetInfo.FIXED_VIEWPORT_INTERFACE_CONTAINER, + new Point(20, -4), new Point(0, -4)); + + private WidgetInfo container; + private WidgetInfo viewport; + private Point offsetLeft; + private Point offsetRight; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseListener.java index c99fa20950..00bfba3d8b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseListener.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2018, Lotto - * 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 HOLDER 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.stretchedmode; - -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.MouseEvent; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.client.input.MouseListener; - -public class TranslateMouseListener implements MouseListener -{ - private final Client client; - - @Inject - public TranslateMouseListener(Client client) - { - this.client = client; - } - - @Override - public MouseEvent mouseClicked(MouseEvent mouseEvent) - { - return translateEvent(mouseEvent); - } - - @Override - public MouseEvent mousePressed(MouseEvent mouseEvent) - { - return translateEvent(mouseEvent); - } - - @Override - public MouseEvent mouseReleased(MouseEvent mouseEvent) - { - return translateEvent(mouseEvent); - } - - @Override - public MouseEvent mouseEntered(MouseEvent mouseEvent) - { - return translateEvent(mouseEvent); - } - - @Override - public MouseEvent mouseExited(MouseEvent mouseEvent) - { - return translateEvent(mouseEvent); - } - - @Override - public MouseEvent mouseDragged(MouseEvent mouseEvent) - { - return translateEvent(mouseEvent); - } - - @Override - public MouseEvent mouseMoved(MouseEvent mouseEvent) - { - return translateEvent(mouseEvent); - } - - private MouseEvent translateEvent(MouseEvent e) - { - Dimension stretchedDimensions = client.getStretchedDimensions(); - Dimension realDimensions = client.getRealDimensions(); - - int newX = (int) (e.getX() / (stretchedDimensions.width / realDimensions.getWidth())); - int newY = (int) (e.getY() / (stretchedDimensions.height / realDimensions.getHeight())); - - return new MouseEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiersEx(), - newX, newY, e.getClickCount(), e.isPopupTrigger(), e.getButton()); - } -} +/* + * Copyright (c) 2018, Lotto + * 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 HOLDER 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.stretchedmode; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.MouseEvent; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.client.input.MouseListener; + +public class TranslateMouseListener implements MouseListener +{ + private final Client client; + + @Inject + public TranslateMouseListener(Client client) + { + this.client = client; + } + + @Override + public MouseEvent mouseClicked(MouseEvent mouseEvent) + { + return translateEvent(mouseEvent); + } + + @Override + public MouseEvent mousePressed(MouseEvent mouseEvent) + { + return translateEvent(mouseEvent); + } + + @Override + public MouseEvent mouseReleased(MouseEvent mouseEvent) + { + return translateEvent(mouseEvent); + } + + @Override + public MouseEvent mouseEntered(MouseEvent mouseEvent) + { + return translateEvent(mouseEvent); + } + + @Override + public MouseEvent mouseExited(MouseEvent mouseEvent) + { + return translateEvent(mouseEvent); + } + + @Override + public MouseEvent mouseDragged(MouseEvent mouseEvent) + { + return translateEvent(mouseEvent); + } + + @Override + public MouseEvent mouseMoved(MouseEvent mouseEvent) + { + return translateEvent(mouseEvent); + } + + private MouseEvent translateEvent(MouseEvent e) + { + Dimension stretchedDimensions = client.getStretchedDimensions(); + Dimension realDimensions = client.getRealDimensions(); + + int newX = (int) (e.getX() / (stretchedDimensions.width / realDimensions.getWidth())); + int newY = (int) (e.getY() / (stretchedDimensions.height / realDimensions.getHeight())); + + return new MouseEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiersEx(), + newX, newY, e.getClickCount(), e.isPopupTrigger(), e.getButton()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseWheelListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseWheelListener.java index 1dc12886f5..475a1a4bd4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseWheelListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/TranslateMouseWheelListener.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2018, Lotto - * 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 HOLDER 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.stretchedmode; - -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.MouseWheelEvent; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.client.input.MouseWheelListener; - -public class TranslateMouseWheelListener implements MouseWheelListener -{ - private final Client client; - - @Inject - public TranslateMouseWheelListener(Client client) - { - this.client = client; - } - - @Override - public MouseWheelEvent mouseWheelMoved(MouseWheelEvent event) - { - return translateEvent(event); - } - - private MouseWheelEvent translateEvent(MouseWheelEvent e) - { - Dimension stretchedDimensions = client.getStretchedDimensions(); - Dimension realDimensions = client.getRealDimensions(); - - int newX = (int) (e.getX() / (stretchedDimensions.width / realDimensions.getWidth())); - int newY = (int) (e.getY() / (stretchedDimensions.height / realDimensions.getHeight())); - - return new MouseWheelEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), newX, newY, - e.getClickCount(), e.isPopupTrigger(), e.getScrollType(), e.getScrollAmount(), e.getWheelRotation()); - } -} +/* + * Copyright (c) 2018, Lotto + * 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 HOLDER 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.stretchedmode; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.MouseWheelEvent; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.client.input.MouseWheelListener; + +public class TranslateMouseWheelListener implements MouseWheelListener +{ + private final Client client; + + @Inject + public TranslateMouseWheelListener(Client client) + { + this.client = client; + } + + @Override + public MouseWheelEvent mouseWheelMoved(MouseWheelEvent event) + { + return translateEvent(event); + } + + private MouseWheelEvent translateEvent(MouseWheelEvent e) + { + Dimension stretchedDimensions = client.getStretchedDimensions(); + Dimension realDimensions = client.getRealDimensions(); + + int newX = (int) (e.getX() / (stretchedDimensions.width / realDimensions.getWidth())); + int newY = (int) (e.getY() / (stretchedDimensions.height / realDimensions.getHeight())); + + return new MouseWheelEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), newX, newY, + e.getClickCount(), e.isPopupTrigger(), e.getScrollType(), e.getScrollAmount(), e.getWheelRotation()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ActionType.java b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ActionType.java index df28bce3b5..c7624dea38 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ActionType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ActionType.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2018, Davis Cook - * Copyright (c) 2018, Daddy Dozer - * 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.suppliestracker; - -/** - * Type of action performed in a menu - */ -public enum ActionType -{ - CONSUMABLE, TELEPORT, CAST; +/* + * Copyright (c) 2018, Davis Cook + * Copyright (c) 2018, Daddy Dozer + * 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.suppliestracker; + +/** + * Type of action performed in a menu + */ +public enum ActionType +{ + CONSUMABLE, TELEPORT, CAST } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ItemType.java b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ItemType.java index 8479937589..1d5e5a7137 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ItemType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/ItemType.java @@ -1,77 +1,78 @@ -/* - * Copyright (c) 2018, Davis Cook - * Copyright (c) 2018, Daddy Dozer - * 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.suppliestracker; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * The potential types that supplies can be along with a categorization function - * that assigns the supplies to these categories - */ -@AllArgsConstructor -public enum ItemType -{ - FOOD("Food"), - POTION("Potions"), - RUNE("Runes"), - AMMO("Ammo"), - TELEPORT("Teleports"); - - @Getter - private String label; - - /** - * Takes an item and determines what ItemType it should categorize into - * @param item the item to determine category for - * @return our best guess for what category this item goes into - * note that if the guess is wrong (per say) it won't break anything because it will be - * consistently wrong but it could have an item that is clearly not food in the food section - */ - public static ItemType categorize(SuppliesTrackerItem item) - { - if (item.getName().contains("(4)")) - { - return ItemType.POTION; - } - if (item.getName().toLowerCase().contains("bolt") || item.getName().toLowerCase().contains("dart") - || item.getName().toLowerCase().contains("arrow") || item.getName().toLowerCase().contains("javelin") - || item.getName().toLowerCase().contains("knive") || item.getName().toLowerCase().contains("throwing") - || item.getName().toLowerCase().contains("zulrah's scale") || item.getName().toLowerCase().contains("cannonball")) - { - return ItemType.AMMO; - } - if (item.getName().contains("rune")) - { - return ItemType.RUNE; - } - if (item.getName().toLowerCase().contains("teleport")) - { - return ItemType.TELEPORT; - } - return ItemType.FOOD; - } -} +/* + * Copyright (c) 2018, Davis Cook + * Copyright (c) 2018, Daddy Dozer + * 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.suppliestracker; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * The potential types that supplies can be along with a categorization function + * that assigns the supplies to these categories + */ +@AllArgsConstructor +public enum ItemType +{ + FOOD("Food"), + POTION("Potions"), + RUNE("Runes"), + AMMO("Ammo"), + TELEPORT("Teleports"); + + @Getter + private String label; + + /** + * Takes an item and determines what ItemType it should categorize into + * + * @param item the item to determine category for + * @return our best guess for what category this item goes into + * note that if the guess is wrong (per say) it won't break anything because it will be + * consistently wrong but it could have an item that is clearly not food in the food section + */ + public static ItemType categorize(SuppliesTrackerItem item) + { + if (item.getName().contains("(4)")) + { + return ItemType.POTION; + } + if (item.getName().toLowerCase().contains("bolt") || item.getName().toLowerCase().contains("dart") + || item.getName().toLowerCase().contains("arrow") || item.getName().toLowerCase().contains("javelin") + || item.getName().toLowerCase().contains("knive") || item.getName().toLowerCase().contains("throwing") + || item.getName().toLowerCase().contains("zulrah's scale") || item.getName().toLowerCase().contains("cannonball")) + { + return ItemType.AMMO; + } + if (item.getName().contains("rune")) + { + return ItemType.RUNE; + } + if (item.getName().toLowerCase().contains("teleport")) + { + return ItemType.TELEPORT; + } + return ItemType.FOOD; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesBox.java index c758250c3b..5313462bae 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesBox.java @@ -1,344 +1,375 @@ -/* - * Copyright (c) 2018, Davis Cook - * Copyright (c) 2018, Daddy Dozer - * 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.suppliestracker; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.GridLayout; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.SwingConstants; -import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; -import lombok.Getter; -import static net.runelite.api.ItemID.*; -import net.runelite.client.game.AsyncBufferedImage; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.util.StackFormatter; -import net.runelite.client.util.Text; -import net.runelite.http.api.item.ItemPrice; - -class SuppliesBox extends JPanel -{ - private static final int ITEMS_PER_ROW = 5; - - private final JPanel itemContainer = new JPanel(); - private final JLabel priceLabel = new JLabel(); - private final JLabel subTitleLabel = new JLabel(); - private final ItemManager itemManager; - @Getter(AccessLevel.PACKAGE) - private final String id; - private final SuppliesTrackerPlugin plugin; - private final SuppliesTrackerPanel panel; - - @Getter - private final List trackedItems = new ArrayList<>(); - - private long totalPrice; - - @Getter - private final ItemType type; - - SuppliesBox(final ItemManager itemManager, final String id, - final SuppliesTrackerPlugin plugin, final SuppliesTrackerPanel panel, - final ItemType type) - { - this.id = id; - this.itemManager = itemManager; - this.plugin = plugin; - this.panel = panel; - this.type = type; - - setLayout(new BorderLayout(0, 1)); - setBorder(new EmptyBorder(5, 0, 0, 0)); - - final JPanel logTitle = new JPanel(new BorderLayout(5, 0)); - logTitle.setBorder(new EmptyBorder(7, 7, 7, 7)); - logTitle.setBackground(ColorScheme.DARKER_GRAY_COLOR.darker()); - - final JLabel titleLabel = new JLabel(Text.removeTags(id)); - titleLabel.setFont(FontManager.getRunescapeSmallFont()); - titleLabel.setForeground(Color.WHITE); - - logTitle.add(titleLabel, BorderLayout.WEST); - - subTitleLabel.setFont(FontManager.getRunescapeSmallFont()); - subTitleLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - logTitle.add(subTitleLabel, BorderLayout.CENTER); - - priceLabel.setFont(FontManager.getRunescapeSmallFont()); - priceLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - logTitle.add(priceLabel, BorderLayout.EAST); - - add(logTitle, BorderLayout.NORTH); - add(itemContainer, BorderLayout.CENTER); - - // Create popup menu - final JPopupMenu popupMenu = new JPopupMenu(); - popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); - setComponentPopupMenu(popupMenu); - - // Create reset menu - final JMenuItem reset = new JMenuItem("Reset Category"); - reset.addActionListener(e -> - { - for (SuppliesTrackerItem item : trackedItems) - { - plugin.clearItem(item.getId()); - } - clearAll(); - rebuild(); - panel.updateOverall(); - }); - - popupMenu.add(reset); - - setVisible(false); - } - - void update(SuppliesTrackerItem item) - { - trackedItems.removeIf(r -> r.getId() == item.getId()); - trackedItems.add(item); - setVisible(trackedItems.size() > 0); - } - - private void remove(SuppliesTrackerItem item) - { - trackedItems.removeIf(r -> r.getId() == item.getId()); - plugin.clearItem(item.getId()); - setVisible(trackedItems.size() > 0); - } - - void clearAll() - { - trackedItems.clear(); - setVisible(false); - } - - long getTotalSupplies() - { - long totalSupplies = 0; - for (SuppliesTrackerItem item : trackedItems) - { - totalSupplies += item.getQuantity(); - } - return totalSupplies; - } - - long getTotalPrice() - { - return totalPrice; - } - - void rebuild() - { - buildItems(); - - priceLabel.setText(StackFormatter.quantityToStackSize(totalPrice) + " gp"); - priceLabel.setToolTipText(StackFormatter.formatNumber(totalPrice) + " gp"); - - final long supplies = getTotalSupplies(); - if (supplies > 0) - { - subTitleLabel.setText("x " + supplies); - } - else - { - subTitleLabel.setText(""); - } - - validate(); - repaint(); - } - - private void buildItems() - { - final List items = new ArrayList<>(trackedItems); - totalPrice = 0; - - for (SuppliesTrackerItem item : items) - { - totalPrice += item.getPrice(); - } - - items.sort((i1, i2) -> Long.compare(i2.getPrice(), i1.getPrice())); - - // calculates how many rows need to be displayed to fit all item - final int rowSize = ((items.size() % ITEMS_PER_ROW == 0) ? 0 : 1) + items.size() / ITEMS_PER_ROW; - - itemContainer.removeAll(); - itemContainer.setLayout(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1)); - - for (int i = 0; i < rowSize * ITEMS_PER_ROW; i++) - { - final JPanel slotContainer = new JPanel(); - slotContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - if (i < items.size()) - { - final SuppliesTrackerItem item = items.get(i); - final JLabel imageLabel = new JLabel(); - imageLabel.setToolTipText(buildToolTip(item)); - imageLabel.setVerticalAlignment(SwingConstants.CENTER); - imageLabel.setHorizontalAlignment(SwingConstants.CENTER); - - AsyncBufferedImage itemImage = itemManager.getImage(getModifiedItemId(item.getName(), item.getId()), item.getQuantity(), item.getQuantity() > 1); - itemImage.addTo(imageLabel); - slotContainer.add(imageLabel); - - // create popup menu - final JPopupMenu popupMenu = new JPopupMenu(); - popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); - slotContainer.setComponentPopupMenu(popupMenu); - - final JMenuItem reset = new JMenuItem("Reset"); - reset.addActionListener(e -> - { - remove(item); - rebuild(); - panel.updateOverall(); - }); - - popupMenu.add(reset); - } - itemContainer.add(slotContainer); - } - itemContainer.repaint(); - } - - private int getModifiedItemId(String name, int itemId) - { - if (SuppliesTrackerPlugin.isPotion(name)) - { - return getSingleDose(name); - } - if (SuppliesTrackerPlugin.isCake(name, itemId)) - { - return getSlice(itemId); - } - if (SuppliesTrackerPlugin.isPizzaPie(name)) - { - return getHalf(itemId); - } - - return itemId; - } - - //Switches full cake ids to get the image for slice - private int getSlice(int itemId) - { - switch (itemId) - { - case CAKE: - itemId = SLICE_OF_CAKE; - break; - case CHOCOLATE_CAKE: - itemId = CHOCOLATE_SLICE; - break; - } - return itemId; - } - - //Switches full pizza and pie ids to get the image for half - private int getHalf(int itemId) - { - switch (itemId) - { - case ANCHOVY_PIZZA: - itemId = _12_ANCHOVY_PIZZA; - break; - case MEAT_PIZZA: - itemId = _12_MEAT_PIZZA; - break; - case PINEAPPLE_PIZZA: - itemId = _12_PINEAPPLE_PIZZA; - break; - case PLAIN_PIZZA: - itemId = _12_PLAIN_PIZZA; - break; - case REDBERRY_PIE: - itemId = HALF_A_REDBERRY_PIE; - break; - case GARDEN_PIE: - itemId = HALF_A_GARDEN_PIE; - break; - case SUMMER_PIE: - itemId = HALF_A_SUMMER_PIE; - break; - case FISH_PIE: - itemId = HALF_A_FISH_PIE; - break; - case BOTANICAL_PIE: - itemId = HALF_A_BOTANICAL_PIE; - break; - case MUSHROOM_PIE: - itemId = HALF_A_MUSHROOM_PIE; - break; - case ADMIRAL_PIE: - itemId = HALF_AN_ADMIRAL_PIE; - break; - case WILD_PIE: - itemId = HALF_A_WILD_PIE; - break; - case APPLE_PIE: - itemId = HALF_AN_APPLE_PIE; - break; - case MEAT_PIE: - itemId = HALF_A_MEAT_PIE; - break; - - } - return itemId; - } - - private int getSingleDose(String name) - { - String nameModified = name.replace("(4)", "(1)"); - int itemId = 0; - List itemList = itemManager.search(nameModified); - for (ItemPrice item: itemList) - { - itemId = item.getId(); - } - return itemId; - } - - private static String buildToolTip(SuppliesTrackerItem item) - { - final String name = item.getName(); - final int quantity = item.getQuantity(); - final long price = item.getPrice(); - return name + " x " + quantity + " (" + StackFormatter.quantityToStackSize(price) + ") "; - } - -} +/* + * Copyright (c) 2018, Davis Cook + * Copyright (c) 2018, Daddy Dozer + * 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.suppliestracker; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingConstants; +import javax.swing.border.EmptyBorder; +import lombok.AccessLevel; +import lombok.Getter; +import static net.runelite.api.ItemID.ADMIRAL_PIE; +import static net.runelite.api.ItemID.ANCHOVY_PIZZA; +import static net.runelite.api.ItemID.APPLE_PIE; +import static net.runelite.api.ItemID.BOTANICAL_PIE; +import static net.runelite.api.ItemID.CAKE; +import static net.runelite.api.ItemID.CHOCOLATE_CAKE; +import static net.runelite.api.ItemID.CHOCOLATE_SLICE; +import static net.runelite.api.ItemID.FISH_PIE; +import static net.runelite.api.ItemID.GARDEN_PIE; +import static net.runelite.api.ItemID.HALF_AN_ADMIRAL_PIE; +import static net.runelite.api.ItemID.HALF_AN_APPLE_PIE; +import static net.runelite.api.ItemID.HALF_A_BOTANICAL_PIE; +import static net.runelite.api.ItemID.HALF_A_FISH_PIE; +import static net.runelite.api.ItemID.HALF_A_GARDEN_PIE; +import static net.runelite.api.ItemID.HALF_A_MEAT_PIE; +import static net.runelite.api.ItemID.HALF_A_MUSHROOM_PIE; +import static net.runelite.api.ItemID.HALF_A_REDBERRY_PIE; +import static net.runelite.api.ItemID.HALF_A_SUMMER_PIE; +import static net.runelite.api.ItemID.HALF_A_WILD_PIE; +import static net.runelite.api.ItemID.MEAT_PIE; +import static net.runelite.api.ItemID.MEAT_PIZZA; +import static net.runelite.api.ItemID.MUSHROOM_PIE; +import static net.runelite.api.ItemID.PINEAPPLE_PIZZA; +import static net.runelite.api.ItemID.PLAIN_PIZZA; +import static net.runelite.api.ItemID.REDBERRY_PIE; +import static net.runelite.api.ItemID.SLICE_OF_CAKE; +import static net.runelite.api.ItemID.SUMMER_PIE; +import static net.runelite.api.ItemID.WILD_PIE; +import static net.runelite.api.ItemID._12_ANCHOVY_PIZZA; +import static net.runelite.api.ItemID._12_MEAT_PIZZA; +import static net.runelite.api.ItemID._12_PINEAPPLE_PIZZA; +import static net.runelite.api.ItemID._12_PLAIN_PIZZA; +import net.runelite.client.game.AsyncBufferedImage; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.util.StackFormatter; +import net.runelite.client.util.Text; +import net.runelite.http.api.item.ItemPrice; + +class SuppliesBox extends JPanel +{ + private static final int ITEMS_PER_ROW = 5; + + private final JPanel itemContainer = new JPanel(); + private final JLabel priceLabel = new JLabel(); + private final JLabel subTitleLabel = new JLabel(); + private final ItemManager itemManager; + @Getter(AccessLevel.PACKAGE) + private final String id; + private final SuppliesTrackerPlugin plugin; + private final SuppliesTrackerPanel panel; + + @Getter + private final List trackedItems = new ArrayList<>(); + + private long totalPrice; + + @Getter + private final ItemType type; + + SuppliesBox(final ItemManager itemManager, final String id, + final SuppliesTrackerPlugin plugin, final SuppliesTrackerPanel panel, + final ItemType type) + { + this.id = id; + this.itemManager = itemManager; + this.plugin = plugin; + this.panel = panel; + this.type = type; + + setLayout(new BorderLayout(0, 1)); + setBorder(new EmptyBorder(5, 0, 0, 0)); + + final JPanel logTitle = new JPanel(new BorderLayout(5, 0)); + logTitle.setBorder(new EmptyBorder(7, 7, 7, 7)); + logTitle.setBackground(ColorScheme.DARKER_GRAY_COLOR.darker()); + + final JLabel titleLabel = new JLabel(Text.removeTags(id)); + titleLabel.setFont(FontManager.getRunescapeSmallFont()); + titleLabel.setForeground(Color.WHITE); + + logTitle.add(titleLabel, BorderLayout.WEST); + + subTitleLabel.setFont(FontManager.getRunescapeSmallFont()); + subTitleLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + logTitle.add(subTitleLabel, BorderLayout.CENTER); + + priceLabel.setFont(FontManager.getRunescapeSmallFont()); + priceLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + logTitle.add(priceLabel, BorderLayout.EAST); + + add(logTitle, BorderLayout.NORTH); + add(itemContainer, BorderLayout.CENTER); + + // Create popup menu + final JPopupMenu popupMenu = new JPopupMenu(); + popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); + setComponentPopupMenu(popupMenu); + + // Create reset menu + final JMenuItem reset = new JMenuItem("Reset Category"); + reset.addActionListener(e -> + { + for (SuppliesTrackerItem item : trackedItems) + { + plugin.clearItem(item.getId()); + } + clearAll(); + rebuild(); + panel.updateOverall(); + }); + + popupMenu.add(reset); + + setVisible(false); + } + + void update(SuppliesTrackerItem item) + { + trackedItems.removeIf(r -> r.getId() == item.getId()); + trackedItems.add(item); + setVisible(trackedItems.size() > 0); + } + + private void remove(SuppliesTrackerItem item) + { + trackedItems.removeIf(r -> r.getId() == item.getId()); + plugin.clearItem(item.getId()); + setVisible(trackedItems.size() > 0); + } + + void clearAll() + { + trackedItems.clear(); + setVisible(false); + } + + long getTotalSupplies() + { + long totalSupplies = 0; + for (SuppliesTrackerItem item : trackedItems) + { + totalSupplies += item.getQuantity(); + } + return totalSupplies; + } + + long getTotalPrice() + { + return totalPrice; + } + + void rebuild() + { + buildItems(); + + priceLabel.setText(StackFormatter.quantityToStackSize(totalPrice) + " gp"); + priceLabel.setToolTipText(StackFormatter.formatNumber(totalPrice) + " gp"); + + final long supplies = getTotalSupplies(); + if (supplies > 0) + { + subTitleLabel.setText("x " + supplies); + } + else + { + subTitleLabel.setText(""); + } + + validate(); + repaint(); + } + + private void buildItems() + { + final List items = new ArrayList<>(trackedItems); + totalPrice = 0; + + for (SuppliesTrackerItem item : items) + { + totalPrice += item.getPrice(); + } + + items.sort((i1, i2) -> Long.compare(i2.getPrice(), i1.getPrice())); + + // calculates how many rows need to be displayed to fit all item + final int rowSize = ((items.size() % ITEMS_PER_ROW == 0) ? 0 : 1) + items.size() / ITEMS_PER_ROW; + + itemContainer.removeAll(); + itemContainer.setLayout(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1)); + + for (int i = 0; i < rowSize * ITEMS_PER_ROW; i++) + { + final JPanel slotContainer = new JPanel(); + slotContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + if (i < items.size()) + { + final SuppliesTrackerItem item = items.get(i); + final JLabel imageLabel = new JLabel(); + imageLabel.setToolTipText(buildToolTip(item)); + imageLabel.setVerticalAlignment(SwingConstants.CENTER); + imageLabel.setHorizontalAlignment(SwingConstants.CENTER); + + AsyncBufferedImage itemImage = itemManager.getImage(getModifiedItemId(item.getName(), item.getId()), item.getQuantity(), item.getQuantity() > 1); + itemImage.addTo(imageLabel); + slotContainer.add(imageLabel); + + // create popup menu + final JPopupMenu popupMenu = new JPopupMenu(); + popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); + slotContainer.setComponentPopupMenu(popupMenu); + + final JMenuItem reset = new JMenuItem("Reset"); + reset.addActionListener(e -> + { + remove(item); + rebuild(); + panel.updateOverall(); + }); + + popupMenu.add(reset); + } + itemContainer.add(slotContainer); + } + itemContainer.repaint(); + } + + private int getModifiedItemId(String name, int itemId) + { + if (SuppliesTrackerPlugin.isPotion(name)) + { + return getSingleDose(name); + } + if (SuppliesTrackerPlugin.isCake(name, itemId)) + { + return getSlice(itemId); + } + if (SuppliesTrackerPlugin.isPizzaPie(name)) + { + return getHalf(itemId); + } + + return itemId; + } + + //Switches full cake ids to get the image for slice + private int getSlice(int itemId) + { + switch (itemId) + { + case CAKE: + itemId = SLICE_OF_CAKE; + break; + case CHOCOLATE_CAKE: + itemId = CHOCOLATE_SLICE; + break; + } + return itemId; + } + + //Switches full pizza and pie ids to get the image for half + private int getHalf(int itemId) + { + switch (itemId) + { + case ANCHOVY_PIZZA: + itemId = _12_ANCHOVY_PIZZA; + break; + case MEAT_PIZZA: + itemId = _12_MEAT_PIZZA; + break; + case PINEAPPLE_PIZZA: + itemId = _12_PINEAPPLE_PIZZA; + break; + case PLAIN_PIZZA: + itemId = _12_PLAIN_PIZZA; + break; + case REDBERRY_PIE: + itemId = HALF_A_REDBERRY_PIE; + break; + case GARDEN_PIE: + itemId = HALF_A_GARDEN_PIE; + break; + case SUMMER_PIE: + itemId = HALF_A_SUMMER_PIE; + break; + case FISH_PIE: + itemId = HALF_A_FISH_PIE; + break; + case BOTANICAL_PIE: + itemId = HALF_A_BOTANICAL_PIE; + break; + case MUSHROOM_PIE: + itemId = HALF_A_MUSHROOM_PIE; + break; + case ADMIRAL_PIE: + itemId = HALF_AN_ADMIRAL_PIE; + break; + case WILD_PIE: + itemId = HALF_A_WILD_PIE; + break; + case APPLE_PIE: + itemId = HALF_AN_APPLE_PIE; + break; + case MEAT_PIE: + itemId = HALF_A_MEAT_PIE; + break; + + } + return itemId; + } + + private int getSingleDose(String name) + { + String nameModified = name.replace("(4)", "(1)"); + int itemId = 0; + List itemList = itemManager.search(nameModified); + for (ItemPrice item : itemList) + { + itemId = item.getId(); + } + return itemId; + } + + private static String buildToolTip(SuppliesTrackerItem item) + { + final String name = item.getName(); + final int quantity = item.getQuantity(); + final long price = item.getPrice(); + return name + " x " + quantity + " (" + StackFormatter.quantityToStackSize(price) + ") "; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPanel.java index 8568eabbc2..dd7660393b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPanel.java @@ -1,209 +1,212 @@ -/* - * Copyright (c) 2018, Psikoi - * Copyright (c) 2018, Tomas Slusny - * Copyright (c) 2018, Daddy Dozer - * 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.suppliestracker; - -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.border.EmptyBorder; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.ui.components.PluginErrorPanel; -import net.runelite.client.util.ColorUtil; -import net.runelite.client.util.StackFormatter; - - -class SuppliesTrackerPanel extends PluginPanel -{ - private static final String HTML_LABEL_TEMPLATE = - "%s%s"; - - // Handle loot logs - private final JPanel logsContainer = new JPanel(); - - private final List boxList = new ArrayList<>(); - - private final PluginErrorPanel errorPanel = new PluginErrorPanel(); - - // Handle overall session data - private final JPanel overallPanel = new JPanel(); - private final JLabel overallSuppliesUsedLabel = new JLabel(); - private final JLabel overallCostLabel = new JLabel(); - private final JLabel overallIcon = new JLabel(); - private int overallSuppliesUsed; - private int overallCost; - - SuppliesTrackerPanel(final ItemManager itemManager, SuppliesTrackerPlugin plugin) - { - setBorder(new EmptyBorder(6, 6, 6, 6)); - setBackground(ColorScheme.DARK_GRAY_COLOR); - setLayout(new BorderLayout()); - - // Create layout panel for wrapping - final JPanel layoutPanel = new JPanel(); - layoutPanel.setLayout(new BoxLayout(layoutPanel, BoxLayout.Y_AXIS)); - add(layoutPanel, BorderLayout.NORTH); - - // Create panel that will contain overall data - overallPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); - overallPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - overallPanel.setLayout(new BorderLayout()); - overallPanel.setVisible(true); - - // Add icon and contents - final JPanel overallInfo = new JPanel(); - overallInfo.setBackground(ColorScheme.DARKER_GRAY_COLOR); - overallInfo.setLayout(new GridLayout(2, 1)); - overallInfo.setBorder(new EmptyBorder(0, 10, 0, 0)); - overallSuppliesUsedLabel.setFont(FontManager.getRunescapeSmallFont()); - overallCostLabel.setFont(FontManager.getRunescapeSmallFont()); - overallInfo.add(overallSuppliesUsedLabel); - overallInfo.add(overallCostLabel); - overallPanel.add(overallIcon, BorderLayout.WEST); - overallPanel.add(overallInfo, BorderLayout.CENTER); - - for (ItemType type : ItemType.values()) - { - SuppliesBox newBox = new SuppliesBox(itemManager, type.getLabel(), plugin, this, type); - logsContainer.add(newBox); - boxList.add(newBox); - } - - // Create reset all menu - final JMenuItem reset = new JMenuItem("Reset All"); - reset.addActionListener(e -> - { - overallSuppliesUsed = 0; - overallCost = 0; - plugin.clearSupplies(); - for (SuppliesBox box : boxList) - { - box.clearAll(); - } - updateOverall(); - logsContainer.repaint(); - }); - - // Create popup menu - final JPopupMenu popupMenu = new JPopupMenu(); - popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); - popupMenu.add(reset); - overallPanel.setComponentPopupMenu(popupMenu); - - // Create Supply Rows wrapper - logsContainer.setLayout(new BoxLayout(logsContainer, BoxLayout.Y_AXIS)); - layoutPanel.add(overallPanel); - layoutPanel.add(logsContainer); - - errorPanel.setContent("Supply trackers", "You have not used any supplies yet."); - add(errorPanel); - overallPanel.setVisible(false); - } - - /** - * loads an img to the icon on the header - * @param img the img for the header icon - */ - void loadHeaderIcon(BufferedImage img) - { - overallIcon.setIcon(new ImageIcon(img)); - } - - /** - * convert key value pair to html formatting needed to display nicely - * @param key key - * @param value value - * @return key: value in html - */ - private static String htmlLabel(String key, long value) - { - final String valueStr = StackFormatter.quantityToStackSize(value); - return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); - } - - /** - * Add an item to the supply panel by placing it into the correct box - * @param item the item to add - */ - void addItem(SuppliesTrackerItem item) - { - ItemType category = ItemType.categorize(item); - for (SuppliesBox box : boxList) - { - if (box.getType() == category) - { - box.update(item); - box.rebuild(); - break; - } - } - updateOverall(); - } - - /** - * Updates overall stats to calculate overall used and overall cost from - * the info in each box - */ - void updateOverall() - { - overallSuppliesUsed = 0; - for (SuppliesBox box : boxList) - { - overallSuppliesUsed += box.getTotalSupplies(); - } - - overallCost = 0; - for (SuppliesBox box : boxList) - { - overallCost += box.getTotalPrice(); - } - - overallSuppliesUsedLabel.setText(htmlLabel("Total Supplies: ", overallSuppliesUsed)); - overallCostLabel.setText(htmlLabel("Total Cost: ", overallCost)); - - if (overallSuppliesUsed <= 0) - { - add(errorPanel); - overallPanel.setVisible(false); - } - else - { - remove(errorPanel); - overallPanel.setVisible(true); - } - } -} +/* + * Copyright (c) 2018, Psikoi + * Copyright (c) 2018, Tomas Slusny + * Copyright (c) 2018, Daddy Dozer + * 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.suppliestracker; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.border.EmptyBorder; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.PluginErrorPanel; +import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.StackFormatter; + + +class SuppliesTrackerPanel extends PluginPanel +{ + private static final String HTML_LABEL_TEMPLATE = + "%s%s"; + + // Handle loot logs + private final JPanel logsContainer = new JPanel(); + + private final List boxList = new ArrayList<>(); + + private final PluginErrorPanel errorPanel = new PluginErrorPanel(); + + // Handle overall session data + private final JPanel overallPanel = new JPanel(); + private final JLabel overallSuppliesUsedLabel = new JLabel(); + private final JLabel overallCostLabel = new JLabel(); + private final JLabel overallIcon = new JLabel(); + private int overallSuppliesUsed; + private int overallCost; + + SuppliesTrackerPanel(final ItemManager itemManager, SuppliesTrackerPlugin plugin) + { + setBorder(new EmptyBorder(6, 6, 6, 6)); + setBackground(ColorScheme.DARK_GRAY_COLOR); + setLayout(new BorderLayout()); + + // Create layout panel for wrapping + final JPanel layoutPanel = new JPanel(); + layoutPanel.setLayout(new BoxLayout(layoutPanel, BoxLayout.Y_AXIS)); + add(layoutPanel, BorderLayout.NORTH); + + // Create panel that will contain overall data + overallPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + overallPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + overallPanel.setLayout(new BorderLayout()); + overallPanel.setVisible(true); + + // Add icon and contents + final JPanel overallInfo = new JPanel(); + overallInfo.setBackground(ColorScheme.DARKER_GRAY_COLOR); + overallInfo.setLayout(new GridLayout(2, 1)); + overallInfo.setBorder(new EmptyBorder(0, 10, 0, 0)); + overallSuppliesUsedLabel.setFont(FontManager.getRunescapeSmallFont()); + overallCostLabel.setFont(FontManager.getRunescapeSmallFont()); + overallInfo.add(overallSuppliesUsedLabel); + overallInfo.add(overallCostLabel); + overallPanel.add(overallIcon, BorderLayout.WEST); + overallPanel.add(overallInfo, BorderLayout.CENTER); + + for (ItemType type : ItemType.values()) + { + SuppliesBox newBox = new SuppliesBox(itemManager, type.getLabel(), plugin, this, type); + logsContainer.add(newBox); + boxList.add(newBox); + } + + // Create reset all menu + final JMenuItem reset = new JMenuItem("Reset All"); + reset.addActionListener(e -> + { + overallSuppliesUsed = 0; + overallCost = 0; + plugin.clearSupplies(); + for (SuppliesBox box : boxList) + { + box.clearAll(); + } + updateOverall(); + logsContainer.repaint(); + }); + + // Create popup menu + final JPopupMenu popupMenu = new JPopupMenu(); + popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); + popupMenu.add(reset); + overallPanel.setComponentPopupMenu(popupMenu); + + // Create Supply Rows wrapper + logsContainer.setLayout(new BoxLayout(logsContainer, BoxLayout.Y_AXIS)); + layoutPanel.add(overallPanel); + layoutPanel.add(logsContainer); + + errorPanel.setContent("Supply trackers", "You have not used any supplies yet."); + add(errorPanel); + overallPanel.setVisible(false); + } + + /** + * loads an img to the icon on the header + * + * @param img the img for the header icon + */ + void loadHeaderIcon(BufferedImage img) + { + overallIcon.setIcon(new ImageIcon(img)); + } + + /** + * convert key value pair to html formatting needed to display nicely + * + * @param key key + * @param value value + * @return key: value in html + */ + private static String htmlLabel(String key, long value) + { + final String valueStr = StackFormatter.quantityToStackSize(value); + return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); + } + + /** + * Add an item to the supply panel by placing it into the correct box + * + * @param item the item to add + */ + void addItem(SuppliesTrackerItem item) + { + ItemType category = ItemType.categorize(item); + for (SuppliesBox box : boxList) + { + if (box.getType() == category) + { + box.update(item); + box.rebuild(); + break; + } + } + updateOverall(); + } + + /** + * Updates overall stats to calculate overall used and overall cost from + * the info in each box + */ + void updateOverall() + { + overallSuppliesUsed = 0; + for (SuppliesBox box : boxList) + { + overallSuppliesUsed += box.getTotalSupplies(); + } + + overallCost = 0; + for (SuppliesBox box : boxList) + { + overallCost += box.getTotalPrice(); + } + + overallSuppliesUsedLabel.setText(htmlLabel("Total Supplies: ", overallSuppliesUsed)); + overallCostLabel.setText(htmlLabel("Total Cost: ", overallCost)); + + if (overallSuppliesUsed <= 0) + { + add(errorPanel); + overallPanel.setVisible(false); + } + else + { + remove(errorPanel); + overallPanel.setVisible(true); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPlugin.java index 653792dc86..c758da9357 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/suppliestracker/SuppliesTrackerPlugin.java @@ -1,777 +1,897 @@ -/* - * Copyright (c) 2018, Psikoi - * Copyright (c) 2018, Adam - * Copyright (c) 2018, Sir Girion - * Copyright (c) 2018, Davis Cook - * Copyright (c) 2018, Daddy Dozer - * 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.suppliestracker; - - -import com.google.inject.Provides; -import java.awt.image.BufferedImage; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.List; -import java.util.Random; -import java.util.regex.Pattern; -import javax.inject.Inject; -import javax.swing.SwingUtilities; -import lombok.extern.slf4j.Slf4j; -import static net.runelite.api.AnimationID.BLOWPIPE_ATTACK; -import static net.runelite.api.AnimationID.HIGH_LEVEL_MAGIC_ATTACK; -import static net.runelite.api.AnimationID.LOW_LEVEL_MAGIC_ATTACK; -import net.runelite.api.Client; -import net.runelite.api.EquipmentInventorySlot; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemComposition; -import net.runelite.api.ItemContainer; -import net.runelite.api.ItemID; -import static net.runelite.api.ItemID.*; -import net.runelite.api.Player; -import net.runelite.api.VarPlayer; -import net.runelite.api.events.AnimationChanged; -import net.runelite.api.events.CannonballFired; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.ItemContainerChanged; -import net.runelite.api.events.MenuOptionClicked; -import net.runelite.api.events.VarbitChanged; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import static net.runelite.client.plugins.suppliestracker.ActionType.CAST; -import static net.runelite.client.plugins.suppliestracker.ActionType.CONSUMABLE; -import static net.runelite.client.plugins.suppliestracker.ActionType.TELEPORT; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.util.ImageUtil; -import net.runelite.http.api.item.ItemPrice; - - -@PluginDescriptor( - name = "Supplies Used Tracker", - description = "Tracks supplies used during the session", - tags = {"cost"}, - type = PluginType.UTILITY, - enabledByDefault = false -) -@Slf4j -public class SuppliesTrackerPlugin extends Plugin -{ - private static final String POTION_PATTERN = "[(]\\d[)]"; - - private static final String EAT_PATTERN = "^eat"; - private static final String DRINK_PATTERN = "^drink"; - private static final String TELEPORT_PATTERN = "^teleport"; - private static final String TELETAB_PATTERN = "^break"; - private static final String SPELL_PATTERN = "^cast|^grand\\sexchange|^outside|^seers|^yanille"; - - private static final int EQUIPMENT_MAINHAND_SLOT = EquipmentInventorySlot.WEAPON.getSlotIdx(); - private static final int EQUIPMENT_AMMO_SLOT = EquipmentInventorySlot.AMMO.getSlotIdx(); - private static final int EQUIPMENT_CAPE_SLOT = EquipmentInventorySlot.CAPE.getSlotIdx(); - - private static final double NO_AVAS_PERCENT = 1.0; - private static final double ASSEMBLER_PERCENT = 0.20; - private static final double ACCUMULATOR_PERCENT = 0.28; - private static final double ATTRACTOR_PERCENT = 0.40; - - private static final int BLOWPIPE_TICKS_RAPID_PVM = 2; - private static final int BLOWPIPE_TICKS_RAPID_PVP = 3; - private static final int BLOWPIPE_TICKS_NORMAL_PVM = 3; - private static final int BLOWPIPE_TICKS_NORMAL_PVP = 4; - - private static final double SCALES_PERCENT = 0.66; - - private static final int POTION_DOSES = 4, CAKE_DOSES = 3, PIZZA_PIE_DOSES = 2; - - private static final Random random = new Random(); - - private static final int[] THROWING_IDS = new int[]{BRONZE_DART, IRON_DART, STEEL_DART, BLACK_DART, MITHRIL_DART, ADAMANT_DART, RUNE_DART, DRAGON_DART, BRONZE_KNIFE, IRON_KNIFE, STEEL_KNIFE, BLACK_KNIFE, MITHRIL_KNIFE, ADAMANT_KNIFE, RUNE_KNIFE, BRONZE_THROWNAXE, IRON_THROWNAXE, STEEL_THROWNAXE, MITHRIL_THROWNAXE, ADAMANT_THROWNAXE, RUNE_THROWNAXE, DRAGON_KNIFE, DRAGON_KNIFE_22812, DRAGON_KNIFE_22814, DRAGON_KNIFEP_22808, DRAGON_KNIFEP_22810, DRAGON_KNIFEP , DRAGON_THROWNAXE, CHINCHOMPA_10033, RED_CHINCHOMPA_10034, BLACK_CHINCHOMPA}; - private static final int[] RUNE_IDS = new int[]{AIR_RUNE, WATER_RUNE, EARTH_RUNE, MIND_RUNE, BODY_RUNE, COSMIC_RUNE, CHAOS_RUNE, NATURE_RUNE, LAW_RUNE, DEATH_RUNE, ASTRAL_RUNE, BLOOD_RUNE, SOUL_RUNE, WRATH_RUNE, MIST_RUNE, DUST_RUNE, MUD_RUNE, SMOKE_RUNE, STEAM_RUNE, LAVA_RUNE}; - - //Hold Supply Data - private static HashMap suppliesEntry = new HashMap<>(); - private ItemContainer old; - private Deque actionStack = new ArrayDeque<>(); - private int ammoId = 0; - private int ammoAmount = 0; - private int thrownId = 0; - private int thrownAmount = 0; - private boolean ammoLoaded = false; - private boolean throwingAmmoLoaded = false; - private boolean mainHandThrowing = false; - private int mainHand = 0; - private SuppliesTrackerPanel panel; - private NavigationButton navButton; - private String[] RAIDS_CONSUMABLES = new String[]{"xeric's", "elder", "twisted", "revitalisation", "overload", "prayer enhance", "pysk", "suphi", "leckish", "brawk", "mycil", "roqed", "kyren", "guanic", "prael", "giral", "phluxia", "kryket", "murng", "psykk"}; - - private int attackStyleVarbit = -1; - private int ticks = 0; - private int ticksInAnimation; - - @Inject - private ClientToolbar clientToolbar; - - @Inject - private ItemManager itemManager; - - @Inject - private SuppliesTrackerConfig config; - - @Inject - private Client client; - - - @Override - protected void startUp() throws Exception - { - panel = new SuppliesTrackerPanel(itemManager, this); - final BufferedImage header = ImageUtil.getResourceStreamFromClass(getClass(), "panel_icon.png"); - panel.loadHeaderIcon(header); - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "panel_icon.png"); - - navButton = NavigationButton.builder() - .tooltip("Supplies Tracker") - .icon(icon) - .priority(5) - .panel(panel) - .build(); - - clientToolbar.addNavigation(navButton); - } - - @Override - protected void shutDown() - { - clientToolbar.removeNavigation(navButton); - } - - @Provides - SuppliesTrackerConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(SuppliesTrackerConfig.class); - } - - @Subscribe - public void onGameTick(GameTick tick) - { - Player player = client.getLocalPlayer(); - if (player.getAnimation() == BLOWPIPE_ATTACK) - { - ticks++; - } - if (ticks == ticksInAnimation && (player.getAnimation() == BLOWPIPE_ATTACK)) - { - double ava_percent = getAccumulatorPercent(); - // randomize the usage of supplies since we CANNOT actually get real supplies used - if (random.nextDouble() <= ava_percent) - { - buildEntries(config.blowpipeAmmo().getDartID()); - - } - if (random.nextDouble() <= SCALES_PERCENT) - { - buildEntries(ZULRAHS_SCALES); - } - ticks = 0; - } - } - - /** - * checks the player's cape slot to determine what percent of their darts are lost - * - where lost means either break or drop to floor - * @return the percent lost - */ - private double getAccumulatorPercent() - { - double percent = NO_AVAS_PERCENT; - ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); - if (equipment != null && equipment.getItems().length > EQUIPMENT_CAPE_SLOT) - { - int capeID = equipment.getItems()[EQUIPMENT_CAPE_SLOT].getId(); - switch (capeID) - { - case AVAS_ASSEMBLER: - case ASSEMBLER_MAX_CAPE: - percent = ASSEMBLER_PERCENT; - break; - case AVAS_ACCUMULATOR: - case ACCUMULATOR_MAX_CAPE: - // TODO: the ranging cape can be used as an attractor so this could be wrong - case RANGING_CAPE: - percent = ACCUMULATOR_PERCENT; - break; - case AVAS_ATTRACTOR: - percent = ATTRACTOR_PERCENT; - break; - } - } - return percent; - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - if (attackStyleVarbit == -1 || attackStyleVarbit != client.getVar(VarPlayer.ATTACK_STYLE)) - { - attackStyleVarbit = client.getVar(VarPlayer.ATTACK_STYLE); - if (attackStyleVarbit == 0 || attackStyleVarbit == 3) - { - ticksInAnimation = BLOWPIPE_TICKS_NORMAL_PVM; - if (client.getLocalPlayer() != null && - client.getLocalPlayer().getInteracting() instanceof Player) { - ticksInAnimation = BLOWPIPE_TICKS_NORMAL_PVP; - } - } - else if (attackStyleVarbit == 1) - { - ticksInAnimation = BLOWPIPE_TICKS_RAPID_PVM; - if (client.getLocalPlayer() != null && - client.getLocalPlayer().getInteracting() instanceof Player) { - ticksInAnimation = BLOWPIPE_TICKS_RAPID_PVP; - } - } - } - } - - /** - * Checks for changes between the provided inventories in runes specifically to add those runes - * to the supply tracker - * - * we can't in general just check for when inventory slots change but this method is only run - * immediately after the player performs a cast animation or cast menu click/entry - * @param itemContainer the new inventory - * @param oldInv the old inventory - */ - private void checkUsedRunes(ItemContainer itemContainer, Item[] oldInv) - { - try - { - for (int i = 0; i < itemContainer.getItems().length; i++) - { - Item newItem = itemContainer.getItems()[i]; - Item oldItem = oldInv[i]; - boolean isRune = false; - for (int runeId : RUNE_IDS) - { - if (oldItem.getId() == runeId) - { - isRune = true; - } - } - if (isRune && (newItem.getId() != oldItem.getId() || newItem.getQuantity() != oldItem.getQuantity())) - { - int quantity = oldItem.getQuantity(); - if (newItem.getId() == oldItem.getId()) - { - quantity -= newItem.getQuantity(); - } - buildEntries(oldItem.getId(), quantity); - } - } - } - catch (IndexOutOfBoundsException ignored) {} - } - - @Subscribe - public void onCannonballFired(CannonballFired cannonballFired) - { - buildEntries(CANNONBALL); - } - - @Subscribe - public void onAnimationChanged(AnimationChanged animationChanged) - { - if (animationChanged.getActor() == client.getLocalPlayer()) - { - if (animationChanged.getActor().getAnimation() == HIGH_LEVEL_MAGIC_ATTACK) - { - //Trident of the seas - if (mainHand == TRIDENT_OF_THE_SEAS || mainHand == TRIDENT_OF_THE_SEAS_E || mainHand == TRIDENT_OF_THE_SEAS_FULL ) - { - buildEntries(CHAOS_RUNE); - buildEntries(DEATH_RUNE); - buildEntries(FIRE_RUNE, 5); - buildEntries(COINS_995, 10); - } - //Trident of the swamp - else if (mainHand == TRIDENT_OF_THE_SWAMP_E || mainHand == TRIDENT_OF_THE_SWAMP || mainHand == UNCHARGED_TOXIC_TRIDENT_E || mainHand == UNCHARGED_TOXIC_TRIDENT) - { - buildEntries(CHAOS_RUNE); - buildEntries(DEATH_RUNE); - buildEntries(FIRE_RUNE, 5); - buildEntries(ZULRAHS_SCALES); - } - //Sang Staff - else if (mainHand == SANGUINESTI_STAFF || mainHand == SANGUINESTI_STAFF_UNCHARGED) - { - buildEntries(BLOOD_RUNE, 3); - } - else - { - old = client.getItemContainer(InventoryID.INVENTORY); - - if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> - a.getType() == CAST)) - { - MenuAction newAction = new MenuAction(CAST, old.getItems()); - actionStack.push(newAction); - } - } - } - else if (animationChanged.getActor().getAnimation() == LOW_LEVEL_MAGIC_ATTACK) - { - old = client.getItemContainer(InventoryID.INVENTORY); - - if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> - a.getType() == CAST)) - { - MenuAction newAction = new MenuAction(CAST, old.getItems()); - actionStack.push(newAction); - } - } - } - } - - @Subscribe - public void onItemContainerChanged(ItemContainerChanged itemContainerChanged) - { - ItemContainer itemContainer = itemContainerChanged.getItemContainer(); - - if (itemContainer == client.getItemContainer(InventoryID.INVENTORY) && old != null && !actionStack.isEmpty()) - { - while (!actionStack.isEmpty()) - { - MenuAction frame = actionStack.pop(); - ActionType type = frame.getType(); - MenuAction.ItemAction itemFrame; - Item[] oldInv = frame.getOldInventory(); - switch (type) - { - case CONSUMABLE: - itemFrame = (MenuAction.ItemAction) frame; - int nextItem = itemFrame.getItemID(); - int nextSlot = itemFrame.getSlot(); - if (itemContainer.getItems()[nextSlot].getId() != oldInv[nextSlot].getId()) - { - buildEntries(nextItem); - } - break; - case TELEPORT: - itemFrame = (MenuAction.ItemAction) frame; - int teleid = itemFrame.getItemID(); - int slot = itemFrame.getSlot(); - if (itemContainer.getItems()[slot].getId() != oldInv[slot].getId() || itemContainer.getItems()[slot].getQuantity() != oldInv[slot].getQuantity()) - { - buildEntries(teleid); - } - break; - case CAST: - checkUsedRunes(itemContainer, oldInv); - break; - } - } - } - - if (itemContainer == client.getItemContainer(InventoryID.EQUIPMENT)) - { - //set mainhand for trident tracking - if (itemContainer.getItems().length > EQUIPMENT_MAINHAND_SLOT) - { - mainHand = itemContainer.getItems()[EQUIPMENT_MAINHAND_SLOT].getId(); - net.runelite.api.Item mainHandItem = itemContainer.getItems()[EQUIPMENT_MAINHAND_SLOT]; - for (int throwingIDs: THROWING_IDS) - { - if (mainHand == throwingIDs) - { - mainHandThrowing = true; - break; - } - else - { - mainHandThrowing = false; - } - } - if (mainHandThrowing) - { - if (throwingAmmoLoaded) - { - if (thrownId == mainHandItem.getId()) - { - if (thrownAmount - 1 == mainHandItem.getQuantity()) - { - buildEntries(mainHandItem.getId()); - thrownAmount = mainHandItem.getQuantity(); - } - else - { - thrownAmount = mainHandItem.getQuantity(); - } - } - else - { - thrownId = mainHandItem.getId(); - thrownAmount = mainHandItem.getQuantity(); - } - } - else - { - thrownId = mainHandItem.getId(); - thrownAmount = mainHandItem.getQuantity(); - throwingAmmoLoaded = true; - } - } - } - //Ammo tracking - if (itemContainer.getItems().length > EQUIPMENT_AMMO_SLOT) - { - net.runelite.api.Item ammoSlot = itemContainer.getItems()[EQUIPMENT_AMMO_SLOT]; - if (ammoSlot != null) - { - if (ammoLoaded) - { - if (ammoId == ammoSlot.getId()) - { - if (ammoAmount - 1 == ammoSlot.getQuantity()) - { - buildEntries(ammoSlot.getId()); - ammoAmount = ammoSlot.getQuantity(); - } - else - { - ammoAmount = ammoSlot.getQuantity(); - } - } - else - { - ammoId = ammoSlot.getId(); - ammoAmount = ammoSlot.getQuantity(); - } - } - else - { - ammoId = ammoSlot.getId(); - ammoAmount = ammoSlot.getQuantity(); - ammoLoaded = true; - } - } - } - - } - } - - @Subscribe - public void onMenuOptionClicked(final MenuOptionClicked event) - { - // Uses stacks to push/pop for tick eating - // Create pattern to find eat/drink at beginning - Pattern eatPattern = Pattern.compile(EAT_PATTERN); - Pattern drinkPattern = Pattern.compile(DRINK_PATTERN); - if (eatPattern.matcher(event.getMenuTarget().toLowerCase()).find() || drinkPattern.matcher(event.getMenuTarget().toLowerCase()).find()) - { - if (actionStack.stream().noneMatch(a -> - { - if (a instanceof MenuAction.ItemAction) - { - MenuAction.ItemAction i = (MenuAction.ItemAction) a; - return i.getItemID() == event.getId(); - } - return false; - })) - { - old = client.getItemContainer(InventoryID.INVENTORY); - int slot = event.getActionParam(); - if (old.getItems() != null) - { - int pushItem = old.getItems()[event.getActionParam()].getId(); - MenuAction newAction = new MenuAction.ItemAction(CONSUMABLE, old.getItems(), pushItem, slot); - actionStack.push(newAction); - } - } - } - - // Create pattern for teleport scrolls and tabs - Pattern teleportPattern = Pattern.compile(TELEPORT_PATTERN); - Pattern teletabPattern = Pattern.compile(TELETAB_PATTERN); - if (teleportPattern.matcher(event.getMenuTarget().toLowerCase()).find() || - teletabPattern.matcher(event.getMenuTarget().toLowerCase()).find()) - { - old = client.getItemContainer(InventoryID.INVENTORY); - - // Makes stack only contains one teleport type to stop from adding multiple of one teleport - if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> - a.getType() == TELEPORT)) - { - int teleid = event.getId(); - MenuAction newAction = new MenuAction.ItemAction(TELEPORT, old.getItems(), teleid, event.getActionParam()); - actionStack.push(newAction); - } - } - - // Create pattern for spell cast - Pattern spellPattern = Pattern.compile(SPELL_PATTERN); - // note that here we look at the menuOption not menuTarget b/c the option for all spells is cast - // but the target differs based on each spell name - if (spellPattern.matcher(event.getMenuOption().toLowerCase()).find()) - { - old = client.getItemContainer(InventoryID.INVENTORY); - - if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> - a.getType() == CAST)) - { - MenuAction newAction = new MenuAction(CAST, old.getItems()); - actionStack.push(newAction); - } - } - } - - /** - * Checks if item name is potion - * @param name the name of the item - * @return if the item is a potion - i.e. has a (1) (2) (3) or (4) in the name - */ - static boolean isPotion(String name) - { - return name.contains("(4)") || name.contains("(3)") || name.contains("(2)") || name.contains("(1)"); - } - - /** - * Checks if item name is pizza or pie - * @param name the name of the item - * @return if the item is a pizza or a pie - i.e. has pizza or pie in the name - */ - static boolean isPizzaPie(String name) - { - return name.toLowerCase().contains("pizza") || name.toLowerCase().contains(" pie"); - } - - static boolean isCake(String name, int itemId) - { - return name.toLowerCase().contains("cake") || itemId == ItemID.CHOCOLATE_SLICE; - } - - /** - * correct prices for potions, pizzas pies, and cakes - * tracker tracks each dose of a potion/pizza/pie/cake as an entire one - * so must divide price by total amount of doses in each - * this is necessary b/c the most correct/accurate price for these resources is the - * full price not the 1-dose price - * @param name the item name - * @param itemId the item id - * @param price the current calculated price - * @return the price modified by the number of doses - */ - private long scalePriceByDoses(String name, int itemId, long price) - { - if (isPotion(name)) - { - return price / POTION_DOSES; - } - if (isPizzaPie(name)) - { - return price / PIZZA_PIE_DOSES; - } - if (isCake(name, itemId)) - { - return price / CAKE_DOSES; - } - return price; - } - - /** - * Add an item to the supply tracker (with 1 count for that item) - * @param itemId the id of the item - */ - private void buildEntries(int itemId) - { - buildEntries(itemId, 1); - } - - /** - * Add an item to the supply tracker - * @param itemId the id of the item - * @param count the amount of the item to add to the tracker - */ - private void buildEntries(int itemId, int count) - { - final ItemComposition itemComposition = itemManager.getItemComposition(itemId); - String name = itemComposition.getName(); - long calculatedPrice; - - for (String raidsConsumables: RAIDS_CONSUMABLES) - { - if (name.toLowerCase().contains(raidsConsumables)) return; - } - - // convert potions, pizzas/pies, and cakes to their full equivalents - // e.g. a half pizza becomes full pizza, 3 dose potion becomes 4, etc... - if (isPotion(name)) - { - name = name.replaceAll(POTION_PATTERN, "(4)"); - itemId = getPotionID(name); - } - if (isPizzaPie(name)) - { - itemId = getFullVersionItemID(itemId); - name = itemManager.getItemComposition(itemId).getName(); - } - if (isCake(name, itemId)) - { - itemId = getFullVersionItemID(itemId); - name = itemManager.getItemComposition(itemId).getName(); - } - - int newQuantity; - if (suppliesEntry.containsKey(itemId)) - { - newQuantity = suppliesEntry.get(itemId).getQuantity() + count; - } - else - { - newQuantity = count; - } - - // calculate price for amount of doses used - calculatedPrice = ((long) itemManager.getItemPrice(itemId)) * ((long) newQuantity); - calculatedPrice = scalePriceByDoses(name, itemId, calculatedPrice); - - // write the new quantity and calculated price for this entry - SuppliesTrackerItem newEntry = new SuppliesTrackerItem( - itemId, - name, - newQuantity, - calculatedPrice); - - suppliesEntry.put(itemId, newEntry); - SwingUtilities.invokeLater(() -> - panel.addItem(newEntry)); - } - - /** - * reset all item stacks - */ - void clearSupplies() - { - suppliesEntry.clear(); - } - - /** - * reset an individual item stack - * @param itemId the id of the item stack - */ - void clearItem(int itemId) - { - suppliesEntry.remove(itemId); - } - - /** - * Gets the item id that matches the provided name within the itemManager - * @param name the given name - * @return the item id for this name - */ - private int getPotionID(String name) - { - int itemId = 0; - - List items = itemManager.search(name); - for (ItemPrice item: items) - { - if (item.getName().contains(name)) - { - itemId = item.getId(); - } - } - return itemId; - } - - /** - * Takes the item id of a partial item (e.g. 1 dose potion, 1/2 a pizza, etc...) and returns - * the corresponding full item - * @param itemId the partial item id - * @return the full item id - */ - private int getFullVersionItemID(int itemId) - { - switch (itemId) - { - case _12_ANCHOVY_PIZZA: - itemId = ANCHOVY_PIZZA; - break; - case _12_MEAT_PIZZA: - itemId = MEAT_PIZZA; - break; - case _12_PINEAPPLE_PIZZA: - itemId = PINEAPPLE_PIZZA; - break; - case _12_PLAIN_PIZZA: - itemId = PLAIN_PIZZA; - break; - case HALF_A_REDBERRY_PIE: - itemId = REDBERRY_PIE; - break; - case HALF_A_GARDEN_PIE: - itemId = GARDEN_PIE; - break; - case HALF_A_SUMMER_PIE: - itemId = SUMMER_PIE; - break; - case HALF_A_FISH_PIE: - itemId = FISH_PIE; - break; - case HALF_A_BOTANICAL_PIE: - itemId = BOTANICAL_PIE; - break; - case HALF_A_MUSHROOM_PIE: - itemId = MUSHROOM_PIE; - break; - case HALF_AN_ADMIRAL_PIE: - itemId = ADMIRAL_PIE; - break; - case HALF_A_WILD_PIE: - itemId = WILD_PIE; - break; - case HALF_AN_APPLE_PIE: - itemId = APPLE_PIE; - break; - case HALF_A_MEAT_PIE: - itemId = MEAT_PIE; - break; - // note behavior of case means both below cases return CAKE - case _23_CAKE: - case SLICE_OF_CAKE: - itemId = CAKE; - break; - case _23_CHOCOLATE_CAKE: - case CHOCOLATE_SLICE: - itemId = CHOCOLATE_CAKE; - break; - } - return itemId; - } -} +/* + * Copyright (c) 2018, Psikoi + * Copyright (c) 2018, Adam + * Copyright (c) 2018, Sir Girion + * Copyright (c) 2018, Davis Cook + * Copyright (c) 2018, Daddy Dozer + * 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.suppliestracker; + + +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Random; +import java.util.regex.Pattern; +import javax.inject.Inject; +import javax.swing.SwingUtilities; +import lombok.extern.slf4j.Slf4j; +import static net.runelite.api.AnimationID.BLOWPIPE_ATTACK; +import static net.runelite.api.AnimationID.HIGH_LEVEL_MAGIC_ATTACK; +import static net.runelite.api.AnimationID.LOW_LEVEL_MAGIC_ATTACK; +import net.runelite.api.Client; +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; +import static net.runelite.api.ItemID.ACCUMULATOR_MAX_CAPE; +import static net.runelite.api.ItemID.ADAMANT_DART; +import static net.runelite.api.ItemID.ADAMANT_KNIFE; +import static net.runelite.api.ItemID.ADAMANT_THROWNAXE; +import static net.runelite.api.ItemID.ADMIRAL_PIE; +import static net.runelite.api.ItemID.AIR_RUNE; +import static net.runelite.api.ItemID.ANCHOVY_PIZZA; +import static net.runelite.api.ItemID.APPLE_PIE; +import static net.runelite.api.ItemID.ASSEMBLER_MAX_CAPE; +import static net.runelite.api.ItemID.ASTRAL_RUNE; +import static net.runelite.api.ItemID.AVAS_ACCUMULATOR; +import static net.runelite.api.ItemID.AVAS_ASSEMBLER; +import static net.runelite.api.ItemID.AVAS_ATTRACTOR; +import static net.runelite.api.ItemID.BLACK_CHINCHOMPA; +import static net.runelite.api.ItemID.BLACK_DART; +import static net.runelite.api.ItemID.BLACK_KNIFE; +import static net.runelite.api.ItemID.BLOOD_RUNE; +import static net.runelite.api.ItemID.BODY_RUNE; +import static net.runelite.api.ItemID.BOTANICAL_PIE; +import static net.runelite.api.ItemID.BRONZE_DART; +import static net.runelite.api.ItemID.BRONZE_KNIFE; +import static net.runelite.api.ItemID.BRONZE_THROWNAXE; +import static net.runelite.api.ItemID.CAKE; +import static net.runelite.api.ItemID.CANNONBALL; +import static net.runelite.api.ItemID.CHAOS_RUNE; +import static net.runelite.api.ItemID.CHINCHOMPA_10033; +import static net.runelite.api.ItemID.CHOCOLATE_CAKE; +import static net.runelite.api.ItemID.CHOCOLATE_SLICE; +import static net.runelite.api.ItemID.COINS_995; +import static net.runelite.api.ItemID.COSMIC_RUNE; +import static net.runelite.api.ItemID.DEATH_RUNE; +import static net.runelite.api.ItemID.DRAGON_DART; +import static net.runelite.api.ItemID.DRAGON_KNIFE; +import static net.runelite.api.ItemID.DRAGON_KNIFEP; +import static net.runelite.api.ItemID.DRAGON_KNIFEP_22808; +import static net.runelite.api.ItemID.DRAGON_KNIFEP_22810; +import static net.runelite.api.ItemID.DRAGON_KNIFE_22812; +import static net.runelite.api.ItemID.DRAGON_KNIFE_22814; +import static net.runelite.api.ItemID.DRAGON_THROWNAXE; +import static net.runelite.api.ItemID.DUST_RUNE; +import static net.runelite.api.ItemID.EARTH_RUNE; +import static net.runelite.api.ItemID.FIRE_RUNE; +import static net.runelite.api.ItemID.FISH_PIE; +import static net.runelite.api.ItemID.GARDEN_PIE; +import static net.runelite.api.ItemID.HALF_AN_ADMIRAL_PIE; +import static net.runelite.api.ItemID.HALF_AN_APPLE_PIE; +import static net.runelite.api.ItemID.HALF_A_BOTANICAL_PIE; +import static net.runelite.api.ItemID.HALF_A_FISH_PIE; +import static net.runelite.api.ItemID.HALF_A_GARDEN_PIE; +import static net.runelite.api.ItemID.HALF_A_MEAT_PIE; +import static net.runelite.api.ItemID.HALF_A_MUSHROOM_PIE; +import static net.runelite.api.ItemID.HALF_A_REDBERRY_PIE; +import static net.runelite.api.ItemID.HALF_A_SUMMER_PIE; +import static net.runelite.api.ItemID.HALF_A_WILD_PIE; +import static net.runelite.api.ItemID.IRON_DART; +import static net.runelite.api.ItemID.IRON_KNIFE; +import static net.runelite.api.ItemID.IRON_THROWNAXE; +import static net.runelite.api.ItemID.LAVA_RUNE; +import static net.runelite.api.ItemID.LAW_RUNE; +import static net.runelite.api.ItemID.MEAT_PIE; +import static net.runelite.api.ItemID.MEAT_PIZZA; +import static net.runelite.api.ItemID.MIND_RUNE; +import static net.runelite.api.ItemID.MIST_RUNE; +import static net.runelite.api.ItemID.MITHRIL_DART; +import static net.runelite.api.ItemID.MITHRIL_KNIFE; +import static net.runelite.api.ItemID.MITHRIL_THROWNAXE; +import static net.runelite.api.ItemID.MUD_RUNE; +import static net.runelite.api.ItemID.MUSHROOM_PIE; +import static net.runelite.api.ItemID.NATURE_RUNE; +import static net.runelite.api.ItemID.PINEAPPLE_PIZZA; +import static net.runelite.api.ItemID.PLAIN_PIZZA; +import static net.runelite.api.ItemID.RANGING_CAPE; +import static net.runelite.api.ItemID.REDBERRY_PIE; +import static net.runelite.api.ItemID.RED_CHINCHOMPA_10034; +import static net.runelite.api.ItemID.RUNE_DART; +import static net.runelite.api.ItemID.RUNE_KNIFE; +import static net.runelite.api.ItemID.RUNE_THROWNAXE; +import static net.runelite.api.ItemID.SANGUINESTI_STAFF; +import static net.runelite.api.ItemID.SANGUINESTI_STAFF_UNCHARGED; +import static net.runelite.api.ItemID.SLICE_OF_CAKE; +import static net.runelite.api.ItemID.SMOKE_RUNE; +import static net.runelite.api.ItemID.SOUL_RUNE; +import static net.runelite.api.ItemID.STEAM_RUNE; +import static net.runelite.api.ItemID.STEEL_DART; +import static net.runelite.api.ItemID.STEEL_KNIFE; +import static net.runelite.api.ItemID.STEEL_THROWNAXE; +import static net.runelite.api.ItemID.SUMMER_PIE; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SEAS; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SEAS_E; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SEAS_FULL; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SWAMP; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SWAMP_E; +import static net.runelite.api.ItemID.UNCHARGED_TOXIC_TRIDENT; +import static net.runelite.api.ItemID.UNCHARGED_TOXIC_TRIDENT_E; +import static net.runelite.api.ItemID.WATER_RUNE; +import static net.runelite.api.ItemID.WILD_PIE; +import static net.runelite.api.ItemID.WRATH_RUNE; +import static net.runelite.api.ItemID.ZULRAHS_SCALES; +import static net.runelite.api.ItemID._12_ANCHOVY_PIZZA; +import static net.runelite.api.ItemID._12_MEAT_PIZZA; +import static net.runelite.api.ItemID._12_PINEAPPLE_PIZZA; +import static net.runelite.api.ItemID._12_PLAIN_PIZZA; +import static net.runelite.api.ItemID._23_CAKE; +import static net.runelite.api.ItemID._23_CHOCOLATE_CAKE; +import net.runelite.api.Player; +import net.runelite.api.VarPlayer; +import net.runelite.api.events.AnimationChanged; +import net.runelite.api.events.CannonballFired; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.ItemContainerChanged; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.VarbitChanged; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import static net.runelite.client.plugins.suppliestracker.ActionType.CAST; +import static net.runelite.client.plugins.suppliestracker.ActionType.CONSUMABLE; +import static net.runelite.client.plugins.suppliestracker.ActionType.TELEPORT; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.ImageUtil; +import net.runelite.http.api.item.ItemPrice; + + +@PluginDescriptor( + name = "Supplies Used Tracker", + description = "Tracks supplies used during the session", + tags = {"cost"}, + type = PluginType.UTILITY, + enabledByDefault = false +) +@Slf4j +public class SuppliesTrackerPlugin extends Plugin +{ + private static final String POTION_PATTERN = "[(]\\d[)]"; + + private static final String EAT_PATTERN = "^eat"; + private static final String DRINK_PATTERN = "^drink"; + private static final String TELEPORT_PATTERN = "^teleport"; + private static final String TELETAB_PATTERN = "^break"; + private static final String SPELL_PATTERN = "^cast|^grand\\sexchange|^outside|^seers|^yanille"; + + private static final int EQUIPMENT_MAINHAND_SLOT = EquipmentInventorySlot.WEAPON.getSlotIdx(); + private static final int EQUIPMENT_AMMO_SLOT = EquipmentInventorySlot.AMMO.getSlotIdx(); + private static final int EQUIPMENT_CAPE_SLOT = EquipmentInventorySlot.CAPE.getSlotIdx(); + + private static final double NO_AVAS_PERCENT = 1.0; + private static final double ASSEMBLER_PERCENT = 0.20; + private static final double ACCUMULATOR_PERCENT = 0.28; + private static final double ATTRACTOR_PERCENT = 0.40; + + private static final int BLOWPIPE_TICKS_RAPID_PVM = 2; + private static final int BLOWPIPE_TICKS_RAPID_PVP = 3; + private static final int BLOWPIPE_TICKS_NORMAL_PVM = 3; + private static final int BLOWPIPE_TICKS_NORMAL_PVP = 4; + + private static final double SCALES_PERCENT = 0.66; + + private static final int POTION_DOSES = 4, CAKE_DOSES = 3, PIZZA_PIE_DOSES = 2; + + private static final Random random = new Random(); + + private static final int[] THROWING_IDS = new int[]{BRONZE_DART, IRON_DART, STEEL_DART, BLACK_DART, MITHRIL_DART, ADAMANT_DART, RUNE_DART, DRAGON_DART, BRONZE_KNIFE, IRON_KNIFE, STEEL_KNIFE, BLACK_KNIFE, MITHRIL_KNIFE, ADAMANT_KNIFE, RUNE_KNIFE, BRONZE_THROWNAXE, IRON_THROWNAXE, STEEL_THROWNAXE, MITHRIL_THROWNAXE, ADAMANT_THROWNAXE, RUNE_THROWNAXE, DRAGON_KNIFE, DRAGON_KNIFE_22812, DRAGON_KNIFE_22814, DRAGON_KNIFEP_22808, DRAGON_KNIFEP_22810, DRAGON_KNIFEP, DRAGON_THROWNAXE, CHINCHOMPA_10033, RED_CHINCHOMPA_10034, BLACK_CHINCHOMPA}; + private static final int[] RUNE_IDS = new int[]{AIR_RUNE, WATER_RUNE, EARTH_RUNE, MIND_RUNE, BODY_RUNE, COSMIC_RUNE, CHAOS_RUNE, NATURE_RUNE, LAW_RUNE, DEATH_RUNE, ASTRAL_RUNE, BLOOD_RUNE, SOUL_RUNE, WRATH_RUNE, MIST_RUNE, DUST_RUNE, MUD_RUNE, SMOKE_RUNE, STEAM_RUNE, LAVA_RUNE}; + + //Hold Supply Data + private static HashMap suppliesEntry = new HashMap<>(); + private ItemContainer old; + private Deque actionStack = new ArrayDeque<>(); + private int ammoId = 0; + private int ammoAmount = 0; + private int thrownId = 0; + private int thrownAmount = 0; + private boolean ammoLoaded = false; + private boolean throwingAmmoLoaded = false; + private boolean mainHandThrowing = false; + private int mainHand = 0; + private SuppliesTrackerPanel panel; + private NavigationButton navButton; + private String[] RAIDS_CONSUMABLES = new String[]{"xeric's", "elder", "twisted", "revitalisation", "overload", "prayer enhance", "pysk", "suphi", "leckish", "brawk", "mycil", "roqed", "kyren", "guanic", "prael", "giral", "phluxia", "kryket", "murng", "psykk"}; + + private int attackStyleVarbit = -1; + private int ticks = 0; + private int ticksInAnimation; + + @Inject + private ClientToolbar clientToolbar; + + @Inject + private ItemManager itemManager; + + @Inject + private SuppliesTrackerConfig config; + + @Inject + private Client client; + + + @Override + protected void startUp() throws Exception + { + panel = new SuppliesTrackerPanel(itemManager, this); + final BufferedImage header = ImageUtil.getResourceStreamFromClass(getClass(), "panel_icon.png"); + panel.loadHeaderIcon(header); + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "panel_icon.png"); + + navButton = NavigationButton.builder() + .tooltip("Supplies Tracker") + .icon(icon) + .priority(5) + .panel(panel) + .build(); + + clientToolbar.addNavigation(navButton); + } + + @Override + protected void shutDown() + { + clientToolbar.removeNavigation(navButton); + } + + @Provides + SuppliesTrackerConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(SuppliesTrackerConfig.class); + } + + @Subscribe + public void onGameTick(GameTick tick) + { + Player player = client.getLocalPlayer(); + if (player.getAnimation() == BLOWPIPE_ATTACK) + { + ticks++; + } + if (ticks == ticksInAnimation && (player.getAnimation() == BLOWPIPE_ATTACK)) + { + double ava_percent = getAccumulatorPercent(); + // randomize the usage of supplies since we CANNOT actually get real supplies used + if (random.nextDouble() <= ava_percent) + { + buildEntries(config.blowpipeAmmo().getDartID()); + + } + if (random.nextDouble() <= SCALES_PERCENT) + { + buildEntries(ZULRAHS_SCALES); + } + ticks = 0; + } + } + + /** + * checks the player's cape slot to determine what percent of their darts are lost + * - where lost means either break or drop to floor + * + * @return the percent lost + */ + private double getAccumulatorPercent() + { + double percent = NO_AVAS_PERCENT; + ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); + if (equipment != null && equipment.getItems().length > EQUIPMENT_CAPE_SLOT) + { + int capeID = equipment.getItems()[EQUIPMENT_CAPE_SLOT].getId(); + switch (capeID) + { + case AVAS_ASSEMBLER: + case ASSEMBLER_MAX_CAPE: + percent = ASSEMBLER_PERCENT; + break; + case AVAS_ACCUMULATOR: + case ACCUMULATOR_MAX_CAPE: + // TODO: the ranging cape can be used as an attractor so this could be wrong + case RANGING_CAPE: + percent = ACCUMULATOR_PERCENT; + break; + case AVAS_ATTRACTOR: + percent = ATTRACTOR_PERCENT; + break; + } + } + return percent; + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + if (attackStyleVarbit == -1 || attackStyleVarbit != client.getVar(VarPlayer.ATTACK_STYLE)) + { + attackStyleVarbit = client.getVar(VarPlayer.ATTACK_STYLE); + if (attackStyleVarbit == 0 || attackStyleVarbit == 3) + { + ticksInAnimation = BLOWPIPE_TICKS_NORMAL_PVM; + if (client.getLocalPlayer() != null && + client.getLocalPlayer().getInteracting() instanceof Player) + { + ticksInAnimation = BLOWPIPE_TICKS_NORMAL_PVP; + } + } + else if (attackStyleVarbit == 1) + { + ticksInAnimation = BLOWPIPE_TICKS_RAPID_PVM; + if (client.getLocalPlayer() != null && + client.getLocalPlayer().getInteracting() instanceof Player) + { + ticksInAnimation = BLOWPIPE_TICKS_RAPID_PVP; + } + } + } + } + + /** + * Checks for changes between the provided inventories in runes specifically to add those runes + * to the supply tracker + *

+ * we can't in general just check for when inventory slots change but this method is only run + * immediately after the player performs a cast animation or cast menu click/entry + * + * @param itemContainer the new inventory + * @param oldInv the old inventory + */ + private void checkUsedRunes(ItemContainer itemContainer, Item[] oldInv) + { + try + { + for (int i = 0; i < itemContainer.getItems().length; i++) + { + Item newItem = itemContainer.getItems()[i]; + Item oldItem = oldInv[i]; + boolean isRune = false; + for (int runeId : RUNE_IDS) + { + if (oldItem.getId() == runeId) + { + isRune = true; + } + } + if (isRune && (newItem.getId() != oldItem.getId() || newItem.getQuantity() != oldItem.getQuantity())) + { + int quantity = oldItem.getQuantity(); + if (newItem.getId() == oldItem.getId()) + { + quantity -= newItem.getQuantity(); + } + buildEntries(oldItem.getId(), quantity); + } + } + } + catch (IndexOutOfBoundsException ignored) + { + } + } + + @Subscribe + public void onCannonballFired(CannonballFired cannonballFired) + { + buildEntries(CANNONBALL); + } + + @Subscribe + public void onAnimationChanged(AnimationChanged animationChanged) + { + if (animationChanged.getActor() == client.getLocalPlayer()) + { + if (animationChanged.getActor().getAnimation() == HIGH_LEVEL_MAGIC_ATTACK) + { + //Trident of the seas + if (mainHand == TRIDENT_OF_THE_SEAS || mainHand == TRIDENT_OF_THE_SEAS_E || mainHand == TRIDENT_OF_THE_SEAS_FULL) + { + buildEntries(CHAOS_RUNE); + buildEntries(DEATH_RUNE); + buildEntries(FIRE_RUNE, 5); + buildEntries(COINS_995, 10); + } + //Trident of the swamp + else if (mainHand == TRIDENT_OF_THE_SWAMP_E || mainHand == TRIDENT_OF_THE_SWAMP || mainHand == UNCHARGED_TOXIC_TRIDENT_E || mainHand == UNCHARGED_TOXIC_TRIDENT) + { + buildEntries(CHAOS_RUNE); + buildEntries(DEATH_RUNE); + buildEntries(FIRE_RUNE, 5); + buildEntries(ZULRAHS_SCALES); + } + //Sang Staff + else if (mainHand == SANGUINESTI_STAFF || mainHand == SANGUINESTI_STAFF_UNCHARGED) + { + buildEntries(BLOOD_RUNE, 3); + } + else + { + old = client.getItemContainer(InventoryID.INVENTORY); + + if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> + a.getType() == CAST)) + { + MenuAction newAction = new MenuAction(CAST, old.getItems()); + actionStack.push(newAction); + } + } + } + else if (animationChanged.getActor().getAnimation() == LOW_LEVEL_MAGIC_ATTACK) + { + old = client.getItemContainer(InventoryID.INVENTORY); + + if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> + a.getType() == CAST)) + { + MenuAction newAction = new MenuAction(CAST, old.getItems()); + actionStack.push(newAction); + } + } + } + } + + @Subscribe + public void onItemContainerChanged(ItemContainerChanged itemContainerChanged) + { + ItemContainer itemContainer = itemContainerChanged.getItemContainer(); + + if (itemContainer == client.getItemContainer(InventoryID.INVENTORY) && old != null && !actionStack.isEmpty()) + { + while (!actionStack.isEmpty()) + { + MenuAction frame = actionStack.pop(); + ActionType type = frame.getType(); + MenuAction.ItemAction itemFrame; + Item[] oldInv = frame.getOldInventory(); + switch (type) + { + case CONSUMABLE: + itemFrame = (MenuAction.ItemAction) frame; + int nextItem = itemFrame.getItemID(); + int nextSlot = itemFrame.getSlot(); + if (itemContainer.getItems()[nextSlot].getId() != oldInv[nextSlot].getId()) + { + buildEntries(nextItem); + } + break; + case TELEPORT: + itemFrame = (MenuAction.ItemAction) frame; + int teleid = itemFrame.getItemID(); + int slot = itemFrame.getSlot(); + if (itemContainer.getItems()[slot].getId() != oldInv[slot].getId() || itemContainer.getItems()[slot].getQuantity() != oldInv[slot].getQuantity()) + { + buildEntries(teleid); + } + break; + case CAST: + checkUsedRunes(itemContainer, oldInv); + break; + } + } + } + + if (itemContainer == client.getItemContainer(InventoryID.EQUIPMENT)) + { + //set mainhand for trident tracking + if (itemContainer.getItems().length > EQUIPMENT_MAINHAND_SLOT) + { + mainHand = itemContainer.getItems()[EQUIPMENT_MAINHAND_SLOT].getId(); + net.runelite.api.Item mainHandItem = itemContainer.getItems()[EQUIPMENT_MAINHAND_SLOT]; + for (int throwingIDs : THROWING_IDS) + { + if (mainHand == throwingIDs) + { + mainHandThrowing = true; + break; + } + else + { + mainHandThrowing = false; + } + } + if (mainHandThrowing) + { + if (throwingAmmoLoaded) + { + if (thrownId == mainHandItem.getId()) + { + if (thrownAmount - 1 == mainHandItem.getQuantity()) + { + buildEntries(mainHandItem.getId()); + thrownAmount = mainHandItem.getQuantity(); + } + else + { + thrownAmount = mainHandItem.getQuantity(); + } + } + else + { + thrownId = mainHandItem.getId(); + thrownAmount = mainHandItem.getQuantity(); + } + } + else + { + thrownId = mainHandItem.getId(); + thrownAmount = mainHandItem.getQuantity(); + throwingAmmoLoaded = true; + } + } + } + //Ammo tracking + if (itemContainer.getItems().length > EQUIPMENT_AMMO_SLOT) + { + net.runelite.api.Item ammoSlot = itemContainer.getItems()[EQUIPMENT_AMMO_SLOT]; + if (ammoSlot != null) + { + if (ammoLoaded) + { + if (ammoId == ammoSlot.getId()) + { + if (ammoAmount - 1 == ammoSlot.getQuantity()) + { + buildEntries(ammoSlot.getId()); + ammoAmount = ammoSlot.getQuantity(); + } + else + { + ammoAmount = ammoSlot.getQuantity(); + } + } + else + { + ammoId = ammoSlot.getId(); + ammoAmount = ammoSlot.getQuantity(); + } + } + else + { + ammoId = ammoSlot.getId(); + ammoAmount = ammoSlot.getQuantity(); + ammoLoaded = true; + } + } + } + + } + } + + @Subscribe + public void onMenuOptionClicked(final MenuOptionClicked event) + { + // Uses stacks to push/pop for tick eating + // Create pattern to find eat/drink at beginning + Pattern eatPattern = Pattern.compile(EAT_PATTERN); + Pattern drinkPattern = Pattern.compile(DRINK_PATTERN); + if (eatPattern.matcher(event.getMenuTarget().toLowerCase()).find() || drinkPattern.matcher(event.getMenuTarget().toLowerCase()).find()) + { + if (actionStack.stream().noneMatch(a -> + { + if (a instanceof MenuAction.ItemAction) + { + MenuAction.ItemAction i = (MenuAction.ItemAction) a; + return i.getItemID() == event.getId(); + } + return false; + })) + { + old = client.getItemContainer(InventoryID.INVENTORY); + int slot = event.getActionParam(); + if (old.getItems() != null) + { + int pushItem = old.getItems()[event.getActionParam()].getId(); + MenuAction newAction = new MenuAction.ItemAction(CONSUMABLE, old.getItems(), pushItem, slot); + actionStack.push(newAction); + } + } + } + + // Create pattern for teleport scrolls and tabs + Pattern teleportPattern = Pattern.compile(TELEPORT_PATTERN); + Pattern teletabPattern = Pattern.compile(TELETAB_PATTERN); + if (teleportPattern.matcher(event.getMenuTarget().toLowerCase()).find() || + teletabPattern.matcher(event.getMenuTarget().toLowerCase()).find()) + { + old = client.getItemContainer(InventoryID.INVENTORY); + + // Makes stack only contains one teleport type to stop from adding multiple of one teleport + if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> + a.getType() == TELEPORT)) + { + int teleid = event.getId(); + MenuAction newAction = new MenuAction.ItemAction(TELEPORT, old.getItems(), teleid, event.getActionParam()); + actionStack.push(newAction); + } + } + + // Create pattern for spell cast + Pattern spellPattern = Pattern.compile(SPELL_PATTERN); + // note that here we look at the menuOption not menuTarget b/c the option for all spells is cast + // but the target differs based on each spell name + if (spellPattern.matcher(event.getMenuOption().toLowerCase()).find()) + { + old = client.getItemContainer(InventoryID.INVENTORY); + + if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a -> + a.getType() == CAST)) + { + MenuAction newAction = new MenuAction(CAST, old.getItems()); + actionStack.push(newAction); + } + } + } + + /** + * Checks if item name is potion + * + * @param name the name of the item + * @return if the item is a potion - i.e. has a (1) (2) (3) or (4) in the name + */ + static boolean isPotion(String name) + { + return name.contains("(4)") || name.contains("(3)") || name.contains("(2)") || name.contains("(1)"); + } + + /** + * Checks if item name is pizza or pie + * + * @param name the name of the item + * @return if the item is a pizza or a pie - i.e. has pizza or pie in the name + */ + static boolean isPizzaPie(String name) + { + return name.toLowerCase().contains("pizza") || name.toLowerCase().contains(" pie"); + } + + static boolean isCake(String name, int itemId) + { + return name.toLowerCase().contains("cake") || itemId == ItemID.CHOCOLATE_SLICE; + } + + /** + * correct prices for potions, pizzas pies, and cakes + * tracker tracks each dose of a potion/pizza/pie/cake as an entire one + * so must divide price by total amount of doses in each + * this is necessary b/c the most correct/accurate price for these resources is the + * full price not the 1-dose price + * + * @param name the item name + * @param itemId the item id + * @param price the current calculated price + * @return the price modified by the number of doses + */ + private long scalePriceByDoses(String name, int itemId, long price) + { + if (isPotion(name)) + { + return price / POTION_DOSES; + } + if (isPizzaPie(name)) + { + return price / PIZZA_PIE_DOSES; + } + if (isCake(name, itemId)) + { + return price / CAKE_DOSES; + } + return price; + } + + /** + * Add an item to the supply tracker (with 1 count for that item) + * + * @param itemId the id of the item + */ + private void buildEntries(int itemId) + { + buildEntries(itemId, 1); + } + + /** + * Add an item to the supply tracker + * + * @param itemId the id of the item + * @param count the amount of the item to add to the tracker + */ + private void buildEntries(int itemId, int count) + { + final ItemComposition itemComposition = itemManager.getItemComposition(itemId); + String name = itemComposition.getName(); + long calculatedPrice; + + for (String raidsConsumables : RAIDS_CONSUMABLES) + { + if (name.toLowerCase().contains(raidsConsumables)) + { + return; + } + } + + // convert potions, pizzas/pies, and cakes to their full equivalents + // e.g. a half pizza becomes full pizza, 3 dose potion becomes 4, etc... + if (isPotion(name)) + { + name = name.replaceAll(POTION_PATTERN, "(4)"); + itemId = getPotionID(name); + } + if (isPizzaPie(name)) + { + itemId = getFullVersionItemID(itemId); + name = itemManager.getItemComposition(itemId).getName(); + } + if (isCake(name, itemId)) + { + itemId = getFullVersionItemID(itemId); + name = itemManager.getItemComposition(itemId).getName(); + } + + int newQuantity; + if (suppliesEntry.containsKey(itemId)) + { + newQuantity = suppliesEntry.get(itemId).getQuantity() + count; + } + else + { + newQuantity = count; + } + + // calculate price for amount of doses used + calculatedPrice = ((long) itemManager.getItemPrice(itemId)) * ((long) newQuantity); + calculatedPrice = scalePriceByDoses(name, itemId, calculatedPrice); + + // write the new quantity and calculated price for this entry + SuppliesTrackerItem newEntry = new SuppliesTrackerItem( + itemId, + name, + newQuantity, + calculatedPrice); + + suppliesEntry.put(itemId, newEntry); + SwingUtilities.invokeLater(() -> + panel.addItem(newEntry)); + } + + /** + * reset all item stacks + */ + void clearSupplies() + { + suppliesEntry.clear(); + } + + /** + * reset an individual item stack + * + * @param itemId the id of the item stack + */ + void clearItem(int itemId) + { + suppliesEntry.remove(itemId); + } + + /** + * Gets the item id that matches the provided name within the itemManager + * + * @param name the given name + * @return the item id for this name + */ + private int getPotionID(String name) + { + int itemId = 0; + + List items = itemManager.search(name); + for (ItemPrice item : items) + { + if (item.getName().contains(name)) + { + itemId = item.getId(); + } + } + return itemId; + } + + /** + * Takes the item id of a partial item (e.g. 1 dose potion, 1/2 a pizza, etc...) and returns + * the corresponding full item + * + * @param itemId the partial item id + * @return the full item id + */ + private int getFullVersionItemID(int itemId) + { + switch (itemId) + { + case _12_ANCHOVY_PIZZA: + itemId = ANCHOVY_PIZZA; + break; + case _12_MEAT_PIZZA: + itemId = MEAT_PIZZA; + break; + case _12_PINEAPPLE_PIZZA: + itemId = PINEAPPLE_PIZZA; + break; + case _12_PLAIN_PIZZA: + itemId = PLAIN_PIZZA; + break; + case HALF_A_REDBERRY_PIE: + itemId = REDBERRY_PIE; + break; + case HALF_A_GARDEN_PIE: + itemId = GARDEN_PIE; + break; + case HALF_A_SUMMER_PIE: + itemId = SUMMER_PIE; + break; + case HALF_A_FISH_PIE: + itemId = FISH_PIE; + break; + case HALF_A_BOTANICAL_PIE: + itemId = BOTANICAL_PIE; + break; + case HALF_A_MUSHROOM_PIE: + itemId = MUSHROOM_PIE; + break; + case HALF_AN_ADMIRAL_PIE: + itemId = ADMIRAL_PIE; + break; + case HALF_A_WILD_PIE: + itemId = WILD_PIE; + break; + case HALF_AN_APPLE_PIE: + itemId = APPLE_PIE; + break; + case HALF_A_MEAT_PIE: + itemId = MEAT_PIE; + break; + // note behavior of case means both below cases return CAKE + case _23_CAKE: + case SLICE_OF_CAKE: + itemId = CAKE; + break; + case _23_CHOCOLATE_CAKE: + case CHOCOLATE_SLICE: + itemId = CHOCOLATE_CAKE; + break; + } + return itemId; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/Obstacles.java b/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/Obstacles.java index b26823c4a8..43e82d076b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/Obstacles.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/Obstacles.java @@ -1,131 +1,217 @@ -/* - * Copyright (c) 2018, Shaun Dreclin - * 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.tarnslair; - -import com.google.common.collect.Sets; -import java.util.Set; -import static net.runelite.api.NullObjectID.NULL_20575; -import static net.runelite.api.ObjectID.*; - -class Obstacles -{ - static final Set STAIRCASE_IDS = Sets.newHashSet( - PASSAGEWAY_15770, /*Wall staircase*/ - PASSAGEWAY_15771, /*Wall staircase*/ - PASSAGEWAY_15772, /*Wall staircase*/ - PASSAGEWAY_15773, /*Wall staircase*/ - PASSAGEWAY_15774, /*Wall staircase*/ - PASSAGEWAY_16129, /*Wall staircase*/ - PASSAGEWAY_16130, /*Wall staircase*/ - PASSAGEWAY_16131, /*Wall staircase*/ - PASSAGEWAY_16132, /*Wall staircase*/ - PASSAGEWAY_16133, /*Wall staircase*/ - PASSAGEWAY_16134, /*Wall staircase*/ - PASSAGEWAY_18307, /*Wall staircase*/ - PASSAGEWAY_18308, /*Wall staircase*/ - PASSAGEWAY_18309, /*Wall staircase*/ - PASSAGEWAY_18310, /*Wall staircase*/ - PASSAGEWAY_18311, /*Wall staircase*/ - PASSAGEWAY_20488, /*Wall staircase*/ - PASSAGEWAY_20489, /*Wall staircase*/ - PASSAGEWAY_20490, /*Wall staircase*/ - PASSAGEWAY_20491, /*Wall staircase*/ - PASSAGEWAY_20492, /*Wall staircase*/ - PASSAGEWAY_20493, /*Wall staircase*/ - PASSAGEWAY_20495, /*Wall staircase*/ - PASSAGEWAY_20497, /*Wall staircase*/ - PASSAGEWAY_20498, /*Wall staircase*/ - PASSAGEWAY_20499, /*Wall staircase*/ - PASSAGEWAY_20500, /*Wall staircase*/ - PASSAGEWAY_20501, /*Wall staircase*/ - PASSAGEWAY_20502, /*Wall staircase*/ - PASSAGEWAY_20503, /*Wall staircase*/ - PASSAGEWAY_20504, /*Wall staircase*/ - PASSAGEWAY_20505, /*Wall staircase*/ - PASSAGEWAY_20506, /*Wall staircase*/ - PASSAGEWAY_20506, /*Wall staircase*/ - PASSAGEWAY_20507, /*Wall staircase*/ - PASSAGEWAY_20509, /*Wall staircase*/ - PASSAGEWAY_20510, /*Wall staircase*/ - PASSAGEWAY_20511, /*Wall staircase*/ - PASSAGEWAY_20512, /*Wall staircase*/ - PASSAGEWAY_20513, /*Wall staircase*/ - PASSAGEWAY_20514, /*Wall staircase*/ - PASSAGEWAY_20515, /*Wall staircase*/ - PASSAGEWAY_20516, /*Wall staircase*/ - PASSAGEWAY_20517, /*Wall staircase*/ - PASSAGEWAY_20518, /*Wall staircase*/ - PASSAGEWAY_20519, /*Wall staircase*/ - PASSAGEWAY_20520, /*Wall staircase*/ - PASSAGEWAY_20521, /*Wall staircase*/ - PASSAGEWAY_20522, /*Wall staircase*/ - PASSAGEWAY_20523, /*Wall staircase*/ - PASSAGEWAY_20524, /*Wall staircase*/ - PASSAGEWAY_20525, /*Wall staircase*/ - PASSAGEWAY_20526, /*Wall staircase*/ - PASSAGEWAY_20527, /*Wall staircase*/ - PASSAGEWAY_20528, /*Wall staircase*/ - PASSAGEWAY_20529, /*Wall staircase*/ - PASSAGEWAY_20530, /*Wall staircase*/ - PASSAGEWAY_20531, /*Wall staircase*/ - PASSAGEWAY_20532, /*Wall staircase*/ - PASSAGEWAY_20533, /*Wall staircase*/ - PASSAGEWAY_20534, /*Wall staircase*/ - PASSAGEWAY_20535, /*Wall staircase*/ - PASSAGEWAY_20536, /*Wall staircase*/ - PASSAGEWAY_20537, /*Wall staircase*/ - PASSAGEWAY_20538, /*Wall staircase*/ - PASSAGEWAY_20539, /*Wall staircase*/ - STAIRS_17098, /*Floor staircase*/ - STAIRS_17099, /*Floor staircase*/ - STAIRS_18973, /*Floor staircase*/ - STAIRS_18974 /*Floor staircase*/ - ); - - static final Set WALL_TRAP_IDS = Sets.newHashSet( - WALL_20590, /*Wall spikes*/ - WALL_20592, /*Wall spikes*/ - WALL_20594, /*Wall spikes*/ - WALL_20596, /*Wall spikes*/ - WALL_20588, /*Wall spikes*/ - WALL_20613, /*Wall pusher*/ - WALL_20615, /*Wall pusher*/ - WALL_20616, /*Wall pusher*/ - WALL_20618, /*Wall pusher*/ - HANGING_LOG_20571, /*Hanging log*/ - HANGING_LOG_20572, /*Hanging log*/ - HANGING_LOG_20573, /*Hanging log*/ - HANGING_LOG_20574 /*Hanging log*/ - ); - - static final Set FLOOR_TRAP_IDS = Sets.newHashSet( - FLOOR_20583, /*Floor spikes*/ - FLOOR_20584, /*Floor spikes*/ - NULL_20575, /*Floor spikes (visible)*/ - FLOOR_20628, /*Trapdoor*/ - FLOOR_20634, /*Floor button*/ - FLOOR_20636 /*Floor button*/ - ); -} +/* + * Copyright (c) 2018, Shaun Dreclin + * 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.tarnslair; + +import com.google.common.collect.Sets; +import java.util.Set; +import static net.runelite.api.NullObjectID.NULL_20575; +import static net.runelite.api.ObjectID.FLOOR_20583; +import static net.runelite.api.ObjectID.FLOOR_20584; +import static net.runelite.api.ObjectID.FLOOR_20628; +import static net.runelite.api.ObjectID.FLOOR_20634; +import static net.runelite.api.ObjectID.FLOOR_20636; +import static net.runelite.api.ObjectID.HANGING_LOG_20571; +import static net.runelite.api.ObjectID.HANGING_LOG_20572; +import static net.runelite.api.ObjectID.HANGING_LOG_20573; +import static net.runelite.api.ObjectID.HANGING_LOG_20574; +import static net.runelite.api.ObjectID.PASSAGEWAY_15770; +import static net.runelite.api.ObjectID.PASSAGEWAY_15771; +import static net.runelite.api.ObjectID.PASSAGEWAY_15772; +import static net.runelite.api.ObjectID.PASSAGEWAY_15773; +import static net.runelite.api.ObjectID.PASSAGEWAY_15774; +import static net.runelite.api.ObjectID.PASSAGEWAY_16129; +import static net.runelite.api.ObjectID.PASSAGEWAY_16130; +import static net.runelite.api.ObjectID.PASSAGEWAY_16131; +import static net.runelite.api.ObjectID.PASSAGEWAY_16132; +import static net.runelite.api.ObjectID.PASSAGEWAY_16133; +import static net.runelite.api.ObjectID.PASSAGEWAY_16134; +import static net.runelite.api.ObjectID.PASSAGEWAY_18307; +import static net.runelite.api.ObjectID.PASSAGEWAY_18308; +import static net.runelite.api.ObjectID.PASSAGEWAY_18309; +import static net.runelite.api.ObjectID.PASSAGEWAY_18310; +import static net.runelite.api.ObjectID.PASSAGEWAY_18311; +import static net.runelite.api.ObjectID.PASSAGEWAY_20488; +import static net.runelite.api.ObjectID.PASSAGEWAY_20489; +import static net.runelite.api.ObjectID.PASSAGEWAY_20490; +import static net.runelite.api.ObjectID.PASSAGEWAY_20491; +import static net.runelite.api.ObjectID.PASSAGEWAY_20492; +import static net.runelite.api.ObjectID.PASSAGEWAY_20493; +import static net.runelite.api.ObjectID.PASSAGEWAY_20495; +import static net.runelite.api.ObjectID.PASSAGEWAY_20497; +import static net.runelite.api.ObjectID.PASSAGEWAY_20498; +import static net.runelite.api.ObjectID.PASSAGEWAY_20499; +import static net.runelite.api.ObjectID.PASSAGEWAY_20500; +import static net.runelite.api.ObjectID.PASSAGEWAY_20501; +import static net.runelite.api.ObjectID.PASSAGEWAY_20502; +import static net.runelite.api.ObjectID.PASSAGEWAY_20503; +import static net.runelite.api.ObjectID.PASSAGEWAY_20504; +import static net.runelite.api.ObjectID.PASSAGEWAY_20505; +import static net.runelite.api.ObjectID.PASSAGEWAY_20506; +import static net.runelite.api.ObjectID.PASSAGEWAY_20507; +import static net.runelite.api.ObjectID.PASSAGEWAY_20509; +import static net.runelite.api.ObjectID.PASSAGEWAY_20510; +import static net.runelite.api.ObjectID.PASSAGEWAY_20511; +import static net.runelite.api.ObjectID.PASSAGEWAY_20512; +import static net.runelite.api.ObjectID.PASSAGEWAY_20513; +import static net.runelite.api.ObjectID.PASSAGEWAY_20514; +import static net.runelite.api.ObjectID.PASSAGEWAY_20515; +import static net.runelite.api.ObjectID.PASSAGEWAY_20516; +import static net.runelite.api.ObjectID.PASSAGEWAY_20517; +import static net.runelite.api.ObjectID.PASSAGEWAY_20518; +import static net.runelite.api.ObjectID.PASSAGEWAY_20519; +import static net.runelite.api.ObjectID.PASSAGEWAY_20520; +import static net.runelite.api.ObjectID.PASSAGEWAY_20521; +import static net.runelite.api.ObjectID.PASSAGEWAY_20522; +import static net.runelite.api.ObjectID.PASSAGEWAY_20523; +import static net.runelite.api.ObjectID.PASSAGEWAY_20524; +import static net.runelite.api.ObjectID.PASSAGEWAY_20525; +import static net.runelite.api.ObjectID.PASSAGEWAY_20526; +import static net.runelite.api.ObjectID.PASSAGEWAY_20527; +import static net.runelite.api.ObjectID.PASSAGEWAY_20528; +import static net.runelite.api.ObjectID.PASSAGEWAY_20529; +import static net.runelite.api.ObjectID.PASSAGEWAY_20530; +import static net.runelite.api.ObjectID.PASSAGEWAY_20531; +import static net.runelite.api.ObjectID.PASSAGEWAY_20532; +import static net.runelite.api.ObjectID.PASSAGEWAY_20533; +import static net.runelite.api.ObjectID.PASSAGEWAY_20534; +import static net.runelite.api.ObjectID.PASSAGEWAY_20535; +import static net.runelite.api.ObjectID.PASSAGEWAY_20536; +import static net.runelite.api.ObjectID.PASSAGEWAY_20537; +import static net.runelite.api.ObjectID.PASSAGEWAY_20538; +import static net.runelite.api.ObjectID.PASSAGEWAY_20539; +import static net.runelite.api.ObjectID.STAIRS_17098; +import static net.runelite.api.ObjectID.STAIRS_17099; +import static net.runelite.api.ObjectID.STAIRS_18973; +import static net.runelite.api.ObjectID.STAIRS_18974; +import static net.runelite.api.ObjectID.WALL_20588; +import static net.runelite.api.ObjectID.WALL_20590; +import static net.runelite.api.ObjectID.WALL_20592; +import static net.runelite.api.ObjectID.WALL_20594; +import static net.runelite.api.ObjectID.WALL_20596; +import static net.runelite.api.ObjectID.WALL_20613; +import static net.runelite.api.ObjectID.WALL_20615; +import static net.runelite.api.ObjectID.WALL_20616; +import static net.runelite.api.ObjectID.WALL_20618; + +class Obstacles +{ + static final Set STAIRCASE_IDS = Sets.newHashSet( + PASSAGEWAY_15770, /*Wall staircase*/ + PASSAGEWAY_15771, /*Wall staircase*/ + PASSAGEWAY_15772, /*Wall staircase*/ + PASSAGEWAY_15773, /*Wall staircase*/ + PASSAGEWAY_15774, /*Wall staircase*/ + PASSAGEWAY_16129, /*Wall staircase*/ + PASSAGEWAY_16130, /*Wall staircase*/ + PASSAGEWAY_16131, /*Wall staircase*/ + PASSAGEWAY_16132, /*Wall staircase*/ + PASSAGEWAY_16133, /*Wall staircase*/ + PASSAGEWAY_16134, /*Wall staircase*/ + PASSAGEWAY_18307, /*Wall staircase*/ + PASSAGEWAY_18308, /*Wall staircase*/ + PASSAGEWAY_18309, /*Wall staircase*/ + PASSAGEWAY_18310, /*Wall staircase*/ + PASSAGEWAY_18311, /*Wall staircase*/ + PASSAGEWAY_20488, /*Wall staircase*/ + PASSAGEWAY_20489, /*Wall staircase*/ + PASSAGEWAY_20490, /*Wall staircase*/ + PASSAGEWAY_20491, /*Wall staircase*/ + PASSAGEWAY_20492, /*Wall staircase*/ + PASSAGEWAY_20493, /*Wall staircase*/ + PASSAGEWAY_20495, /*Wall staircase*/ + PASSAGEWAY_20497, /*Wall staircase*/ + PASSAGEWAY_20498, /*Wall staircase*/ + PASSAGEWAY_20499, /*Wall staircase*/ + PASSAGEWAY_20500, /*Wall staircase*/ + PASSAGEWAY_20501, /*Wall staircase*/ + PASSAGEWAY_20502, /*Wall staircase*/ + PASSAGEWAY_20503, /*Wall staircase*/ + PASSAGEWAY_20504, /*Wall staircase*/ + PASSAGEWAY_20505, /*Wall staircase*/ + PASSAGEWAY_20506, /*Wall staircase*/ + PASSAGEWAY_20506, /*Wall staircase*/ + PASSAGEWAY_20507, /*Wall staircase*/ + PASSAGEWAY_20509, /*Wall staircase*/ + PASSAGEWAY_20510, /*Wall staircase*/ + PASSAGEWAY_20511, /*Wall staircase*/ + PASSAGEWAY_20512, /*Wall staircase*/ + PASSAGEWAY_20513, /*Wall staircase*/ + PASSAGEWAY_20514, /*Wall staircase*/ + PASSAGEWAY_20515, /*Wall staircase*/ + PASSAGEWAY_20516, /*Wall staircase*/ + PASSAGEWAY_20517, /*Wall staircase*/ + PASSAGEWAY_20518, /*Wall staircase*/ + PASSAGEWAY_20519, /*Wall staircase*/ + PASSAGEWAY_20520, /*Wall staircase*/ + PASSAGEWAY_20521, /*Wall staircase*/ + PASSAGEWAY_20522, /*Wall staircase*/ + PASSAGEWAY_20523, /*Wall staircase*/ + PASSAGEWAY_20524, /*Wall staircase*/ + PASSAGEWAY_20525, /*Wall staircase*/ + PASSAGEWAY_20526, /*Wall staircase*/ + PASSAGEWAY_20527, /*Wall staircase*/ + PASSAGEWAY_20528, /*Wall staircase*/ + PASSAGEWAY_20529, /*Wall staircase*/ + PASSAGEWAY_20530, /*Wall staircase*/ + PASSAGEWAY_20531, /*Wall staircase*/ + PASSAGEWAY_20532, /*Wall staircase*/ + PASSAGEWAY_20533, /*Wall staircase*/ + PASSAGEWAY_20534, /*Wall staircase*/ + PASSAGEWAY_20535, /*Wall staircase*/ + PASSAGEWAY_20536, /*Wall staircase*/ + PASSAGEWAY_20537, /*Wall staircase*/ + PASSAGEWAY_20538, /*Wall staircase*/ + PASSAGEWAY_20539, /*Wall staircase*/ + STAIRS_17098, /*Floor staircase*/ + STAIRS_17099, /*Floor staircase*/ + STAIRS_18973, /*Floor staircase*/ + STAIRS_18974 /*Floor staircase*/ + ); + + static final Set WALL_TRAP_IDS = Sets.newHashSet( + WALL_20590, /*Wall spikes*/ + WALL_20592, /*Wall spikes*/ + WALL_20594, /*Wall spikes*/ + WALL_20596, /*Wall spikes*/ + WALL_20588, /*Wall spikes*/ + WALL_20613, /*Wall pusher*/ + WALL_20615, /*Wall pusher*/ + WALL_20616, /*Wall pusher*/ + WALL_20618, /*Wall pusher*/ + HANGING_LOG_20571, /*Hanging log*/ + HANGING_LOG_20572, /*Hanging log*/ + HANGING_LOG_20573, /*Hanging log*/ + HANGING_LOG_20574 /*Hanging log*/ + ); + + static final Set FLOOR_TRAP_IDS = Sets.newHashSet( + FLOOR_20583, /*Floor spikes*/ + FLOOR_20584, /*Floor spikes*/ + NULL_20575, /*Floor spikes (visible)*/ + FLOOR_20628, /*Trapdoor*/ + FLOOR_20634, /*Floor button*/ + FLOOR_20636 /*Floor button*/ + ); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java index 103129d64f..45a7b10a87 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java @@ -1,126 +1,126 @@ -/* - * Copyright (c) 2017, Devin French - * 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.teamcapes; - -import com.google.inject.Provides; -import java.time.temporal.ChronoUnit; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.Player; -import net.runelite.client.config.ConfigManager; -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; - -@PluginDescriptor( - name = "Team Capes", - description = "Show the different team capes in your area and the amount of each", - tags = {"overlay", "players"}, - enabledByDefault = false -) -public class TeamCapesPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private OverlayManager overlayManager; - - @Inject - private TeamCapesOverlay overlay; - - // Hashmap of team capes: Key is the teamCape #, Value is the count of teamcapes in the area. - private Map teams = new HashMap<>(); - - @Provides - TeamCapesConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(TeamCapesConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - teams.clear(); - } - - @Schedule( - period = 1800, - unit = ChronoUnit.MILLIS - ) - public void update() - { - if (client.getGameState() != GameState.LOGGED_IN) - { - return; - } - List players = client.getPlayers(); - teams.clear(); - for (Player player : players) - { - int team = player.getTeam(); - if (team > 0) - { - if (teams.containsKey(team)) - { - teams.put(team, teams.get(team) + 1); - } - else - { - teams.put(team, 1); - } - } - } - - // Sort teams by value in descending order and then by key in ascending order, limited to 5 entries - teams = teams.entrySet().stream() - .sorted( - Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()) - .thenComparingInt(Map.Entry::getKey) - ) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); - } - - public Map getTeams() - { - return teams; - } - -} +/* + * Copyright (c) 2017, Devin French + * 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.teamcapes; + +import com.google.inject.Provides; +import java.time.temporal.ChronoUnit; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Player; +import net.runelite.client.config.ConfigManager; +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; + +@PluginDescriptor( + name = "Team Capes", + description = "Show the different team capes in your area and the amount of each", + tags = {"overlay", "players"}, + enabledByDefault = false +) +public class TeamCapesPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private TeamCapesOverlay overlay; + + // Hashmap of team capes: Key is the teamCape #, Value is the count of teamcapes in the area. + private Map teams = new HashMap<>(); + + @Provides + TeamCapesConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(TeamCapesConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + teams.clear(); + } + + @Schedule( + period = 1800, + unit = ChronoUnit.MILLIS + ) + public void update() + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + List players = client.getPlayers(); + teams.clear(); + for (Player player : players) + { + int team = player.getTeam(); + if (team > 0) + { + if (teams.containsKey(team)) + { + teams.put(team, teams.get(team) + 1); + } + else + { + teams.put(team, 1); + } + } + } + + // Sort teams by value in descending order and then by key in ascending order, limited to 5 entries + teams = teams.entrySet().stream() + .sorted( + Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()) + .thenComparingInt(Map.Entry::getKey) + ) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); + } + + public Map getTeams() + { + return teams; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java index de80c99739..d33084be37 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java @@ -3,7 +3,6 @@ package net.runelite.client.plugins.tickcounter; import java.awt.Dimension; import java.awt.Graphics2D; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; import java.util.Map.Entry; import javax.inject.Inject; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java index 889feb3bba..2d1c8b16e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java @@ -74,7 +74,41 @@ import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import static net.runelite.client.plugins.timers.GameIndicator.VENGEANCE_ACTIVE; -import static net.runelite.client.plugins.timers.GameTimer.*; +import static net.runelite.client.plugins.timers.GameTimer.ABYSSAL_SIRE_STUN; +import static net.runelite.client.plugins.timers.GameTimer.ANTIFIRE; +import static net.runelite.client.plugins.timers.GameTimer.ANTIPOISON; +import static net.runelite.client.plugins.timers.GameTimer.ANTIVENOM; +import static net.runelite.client.plugins.timers.GameTimer.BIND; +import static net.runelite.client.plugins.timers.GameTimer.CANNON; +import static net.runelite.client.plugins.timers.GameTimer.CHARGE; +import static net.runelite.client.plugins.timers.GameTimer.DMM_FULLTB; +import static net.runelite.client.plugins.timers.GameTimer.DMM_HALFTB; +import static net.runelite.client.plugins.timers.GameTimer.ENTANGLE; +import static net.runelite.client.plugins.timers.GameTimer.EXANTIFIRE; +import static net.runelite.client.plugins.timers.GameTimer.EXSUPERANTIFIRE; +import static net.runelite.client.plugins.timers.GameTimer.FULLTB; +import static net.runelite.client.plugins.timers.GameTimer.GOD_WARS_ALTAR; +import static net.runelite.client.plugins.timers.GameTimer.HALFBIND; +import static net.runelite.client.plugins.timers.GameTimer.HALFENTANGLE; +import static net.runelite.client.plugins.timers.GameTimer.HALFSNARE; +import static net.runelite.client.plugins.timers.GameTimer.HALFTB; +import static net.runelite.client.plugins.timers.GameTimer.HOME_TELEPORT; +import static net.runelite.client.plugins.timers.GameTimer.ICEBARRAGE; +import static net.runelite.client.plugins.timers.GameTimer.ICEBLITZ; +import static net.runelite.client.plugins.timers.GameTimer.ICEBURST; +import static net.runelite.client.plugins.timers.GameTimer.ICERUSH; +import static net.runelite.client.plugins.timers.GameTimer.IMBUEDHEART; +import static net.runelite.client.plugins.timers.GameTimer.MAGICIMBUE; +import static net.runelite.client.plugins.timers.GameTimer.MINIGAME_TELEPORT; +import static net.runelite.client.plugins.timers.GameTimer.OVERLOAD; +import static net.runelite.client.plugins.timers.GameTimer.OVERLOAD_RAID; +import static net.runelite.client.plugins.timers.GameTimer.PRAYER_ENHANCE; +import static net.runelite.client.plugins.timers.GameTimer.SKULL; +import static net.runelite.client.plugins.timers.GameTimer.SNARE; +import static net.runelite.client.plugins.timers.GameTimer.STAFF_OF_THE_DEAD; +import static net.runelite.client.plugins.timers.GameTimer.STAMINA; +import static net.runelite.client.plugins.timers.GameTimer.SUPERANTIFIRE; +import static net.runelite.client.plugins.timers.GameTimer.VENGEANCE; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; @PluginDescriptor( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java index f736c49fef..633d548750 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java @@ -1,150 +1,150 @@ -/* - * Copyright (c) 2018, Daniel Teo - * 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.timetracking; - -import com.google.common.collect.ImmutableMap; -import java.awt.Color; -import java.awt.GridLayout; -import java.time.Instant; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Stream; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.timetracking.clocks.ClockManager; -import net.runelite.client.plugins.timetracking.farming.FarmingTracker; -import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker; -import net.runelite.client.ui.ColorScheme; - -class OverviewTabPanel extends TabContentPanel -{ - private final TimeTrackingConfig config; - private final FarmingTracker farmingTracker; - private final BirdHouseTracker birdHouseTracker; - private final ClockManager clockManager; - - private final OverviewItemPanel timerOverview; - private final OverviewItemPanel stopwatchOverview; - private final Map farmingOverviews; - private final OverviewItemPanel birdHouseOverview; - - OverviewTabPanel(ItemManager itemManager, TimeTrackingConfig config, TimeTrackingPanel pluginPanel, - FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) - { - this.config = config; - this.farmingTracker = farmingTracker; - this.birdHouseTracker = birdHouseTracker; - this.clockManager = clockManager; - - setLayout(new GridLayout(0, 1, 0, 8)); - setBackground(ColorScheme.DARK_GRAY_COLOR); - - timerOverview = new OverviewItemPanel(itemManager, pluginPanel, Tab.CLOCK, "Timers"); - add(timerOverview); - - stopwatchOverview = new OverviewItemPanel(itemManager, pluginPanel, Tab.CLOCK, "Stopwatches"); - add(stopwatchOverview); - - birdHouseOverview = new OverviewItemPanel(itemManager, pluginPanel, Tab.BIRD_HOUSE, "Bird Houses"); - add(birdHouseOverview); - - farmingOverviews = Stream.of(Tab.FARMING_TABS) - .filter(v -> v != Tab.OVERVIEW) - .collect(ImmutableMap.toImmutableMap( - Function.identity(), - t -> - { - OverviewItemPanel p = new OverviewItemPanel(itemManager, pluginPanel, t, t.getName()); - add(p); - return p; - } - )); - } - - @Override - public int getUpdateInterval() - { - return 50; // 10 seconds - } - - @Override - public void update() - { - final long timers = clockManager.getActiveTimerCount(); - final long stopwatches = clockManager.getActiveStopwatchCount(); - - if (timers == 0) - { - timerOverview.updateStatus("No active timers", Color.GRAY); - } - else - { - timerOverview.updateStatus(timers + " active timer" + (timers == 1 ? "" : "s"), ColorScheme.PROGRESS_COMPLETE_COLOR); - } - - if (stopwatches == 0) - { - stopwatchOverview.updateStatus("No active stopwatches", Color.GRAY); - } - else - { - stopwatchOverview.updateStatus(stopwatches + " active stopwatch" + (stopwatches == 1 ? "" : "es"), ColorScheme.PROGRESS_COMPLETE_COLOR); - } - - farmingOverviews.forEach((patchType, panel) -> - updateItemPanel(panel, farmingTracker.getSummary(patchType), farmingTracker.getCompletionTime(patchType))); - - updateItemPanel(birdHouseOverview, birdHouseTracker.getSummary(), birdHouseTracker.getCompletionTime()); - } - - private void updateItemPanel(OverviewItemPanel panel, SummaryState summary, long completionTime) - { - switch (summary) - { - case COMPLETED: - case IN_PROGRESS: - { - long duration = completionTime - Instant.now().getEpochSecond(); - - if (duration <= 0) - { - panel.updateStatus("Ready", ColorScheme.PROGRESS_COMPLETE_COLOR); - } - else - { - panel.updateStatus("Ready " + getFormattedEstimate(duration, config.estimateRelative()), Color.GRAY); - } - - break; - } - case EMPTY: - panel.updateStatus("Empty", Color.GRAY); - break; - case UNKNOWN: - default: - panel.updateStatus("Unknown", Color.GRAY); - break; - } - } -} +/* + * Copyright (c) 2018, Daniel Teo + * 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.timetracking; + +import com.google.common.collect.ImmutableMap; +import java.awt.Color; +import java.awt.GridLayout; +import java.time.Instant; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.clocks.ClockManager; +import net.runelite.client.plugins.timetracking.farming.FarmingTracker; +import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker; +import net.runelite.client.ui.ColorScheme; + +class OverviewTabPanel extends TabContentPanel +{ + private final TimeTrackingConfig config; + private final FarmingTracker farmingTracker; + private final BirdHouseTracker birdHouseTracker; + private final ClockManager clockManager; + + private final OverviewItemPanel timerOverview; + private final OverviewItemPanel stopwatchOverview; + private final Map farmingOverviews; + private final OverviewItemPanel birdHouseOverview; + + OverviewTabPanel(ItemManager itemManager, TimeTrackingConfig config, TimeTrackingPanel pluginPanel, + FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) + { + this.config = config; + this.farmingTracker = farmingTracker; + this.birdHouseTracker = birdHouseTracker; + this.clockManager = clockManager; + + setLayout(new GridLayout(0, 1, 0, 8)); + setBackground(ColorScheme.DARK_GRAY_COLOR); + + timerOverview = new OverviewItemPanel(itemManager, pluginPanel, Tab.CLOCK, "Timers"); + add(timerOverview); + + stopwatchOverview = new OverviewItemPanel(itemManager, pluginPanel, Tab.CLOCK, "Stopwatches"); + add(stopwatchOverview); + + birdHouseOverview = new OverviewItemPanel(itemManager, pluginPanel, Tab.BIRD_HOUSE, "Bird Houses"); + add(birdHouseOverview); + + farmingOverviews = Stream.of(Tab.FARMING_TABS) + .filter(v -> v != Tab.OVERVIEW) + .collect(ImmutableMap.toImmutableMap( + Function.identity(), + t -> + { + OverviewItemPanel p = new OverviewItemPanel(itemManager, pluginPanel, t, t.getName()); + add(p); + return p; + } + )); + } + + @Override + public int getUpdateInterval() + { + return 50; // 10 seconds + } + + @Override + public void update() + { + final long timers = clockManager.getActiveTimerCount(); + final long stopwatches = clockManager.getActiveStopwatchCount(); + + if (timers == 0) + { + timerOverview.updateStatus("No active timers", Color.GRAY); + } + else + { + timerOverview.updateStatus(timers + " active timer" + (timers == 1 ? "" : "s"), ColorScheme.PROGRESS_COMPLETE_COLOR); + } + + if (stopwatches == 0) + { + stopwatchOverview.updateStatus("No active stopwatches", Color.GRAY); + } + else + { + stopwatchOverview.updateStatus(stopwatches + " active stopwatch" + (stopwatches == 1 ? "" : "es"), ColorScheme.PROGRESS_COMPLETE_COLOR); + } + + farmingOverviews.forEach((patchType, panel) -> + updateItemPanel(panel, farmingTracker.getSummary(patchType), farmingTracker.getCompletionTime(patchType))); + + updateItemPanel(birdHouseOverview, birdHouseTracker.getSummary(), birdHouseTracker.getCompletionTime()); + } + + private void updateItemPanel(OverviewItemPanel panel, SummaryState summary, long completionTime) + { + switch (summary) + { + case COMPLETED: + case IN_PROGRESS: + { + long duration = completionTime - Instant.now().getEpochSecond(); + + if (duration <= 0) + { + panel.updateStatus("Ready", ColorScheme.PROGRESS_COMPLETE_COLOR); + } + else + { + panel.updateStatus("Ready " + getFormattedEstimate(duration, config.estimateRelative()), Color.GRAY); + } + + break; + } + case EMPTY: + panel.updateStatus("Empty", Color.GRAY); + break; + case UNKNOWN: + default: + panel.updateStatus("Unknown", Color.GRAY); + break; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java index 6deb64e30c..54b863f4b0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java @@ -1,178 +1,178 @@ -/* - * Copyright (c) 2018 Abex - * Copyright (c) 2018, Psikoi - * 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.timetracking; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.Image; -import java.awt.image.BufferedImage; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.Nullable; -import javax.swing.ImageIcon; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.SwingUtilities; -import javax.swing.border.EmptyBorder; -import net.runelite.client.game.AsyncBufferedImage; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.timetracking.clocks.ClockManager; -import net.runelite.client.plugins.timetracking.farming.FarmingTracker; -import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.ui.components.materialtabs.MaterialTab; -import net.runelite.client.ui.components.materialtabs.MaterialTabGroup; - -class TimeTrackingPanel extends PluginPanel -{ - private final ItemManager itemManager; - private final TimeTrackingConfig config; - - /* This is the panel the tabs' respective panels will be displayed on. */ - private final JPanel display = new JPanel(); - private final Map uiTabs = new HashMap<>(); - private final MaterialTabGroup tabGroup = new MaterialTabGroup(display); - - private boolean active; - - @Nullable - private TabContentPanel activeTabPanel = null; - - TimeTrackingPanel(ItemManager itemManager, TimeTrackingConfig config, - FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) - { - super(false); - - this.itemManager = itemManager; - this.config = config; - - setLayout(new BorderLayout()); - setBackground(ColorScheme.DARK_GRAY_COLOR); - - display.setBorder(new EmptyBorder(10, 10, 8, 10)); - - tabGroup.setLayout(new GridLayout(0, 6, 7, 7)); - tabGroup.setBorder(new EmptyBorder(10, 10, 0, 10)); - - add(tabGroup, BorderLayout.NORTH); - add(display, BorderLayout.CENTER); - - addTab(Tab.OVERVIEW, new OverviewTabPanel(itemManager, config, this, farmingTracker, birdHouseTracker, clockManager)); - addTab(Tab.CLOCK, clockManager.getClockTabPanel()); - addTab(Tab.BIRD_HOUSE, birdHouseTracker.createBirdHouseTabPanel()); - - for (Tab tab : Tab.FARMING_TABS) - { - addTab(tab, farmingTracker.createTabPanel(tab)); - } - } - - private void addTab(Tab tab, TabContentPanel tabContentPanel) - { - JPanel wrapped = new JPanel(new BorderLayout()); - wrapped.add(tabContentPanel, BorderLayout.NORTH); - wrapped.setBackground(ColorScheme.DARK_GRAY_COLOR); - - JScrollPane scroller = new JScrollPane(wrapped); - scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scroller.getVerticalScrollBar().setPreferredSize(new Dimension(16, 0)); - scroller.getVerticalScrollBar().setBorder(new EmptyBorder(0, 9, 0, 0)); - scroller.setBackground(ColorScheme.DARK_GRAY_COLOR); - - // Use a placeholder icon until the async image gets loaded - MaterialTab materialTab = new MaterialTab(new ImageIcon(), tabGroup, scroller); - materialTab.setPreferredSize(new Dimension(30, 27)); - materialTab.setName(tab.getName()); - materialTab.setToolTipText(tab.getName()); - - AsyncBufferedImage icon = itemManager.getImage(tab.getItemID()); - Runnable resize = () -> - { - BufferedImage subIcon = icon.getSubimage(0, 0, 32, 32); - materialTab.setIcon(new ImageIcon(subIcon.getScaledInstance(24, 24, Image.SCALE_SMOOTH))); - }; - icon.onChanged(resize); - resize.run(); - - materialTab.setOnSelectEvent(() -> - { - config.setActiveTab(tab); - activeTabPanel = tabContentPanel; - - tabContentPanel.update(); - return true; - }); - - uiTabs.put(tab, materialTab); - tabGroup.addTab(materialTab); - - if (config.activeTab() == tab) - { - tabGroup.select(materialTab); - } - } - - void switchTab(Tab tab) - { - tabGroup.select(uiTabs.get(tab)); - } - - /** - * Gets the update interval of the active tab panel, in units of 200 milliseconds. - */ - int getUpdateInterval() - { - return activeTabPanel == null ? Integer.MAX_VALUE : activeTabPanel.getUpdateInterval(); - } - - /** - * Updates the active tab panel, if this plugin panel is displayed. - */ - void update() - { - if (!active || activeTabPanel == null) - { - return; - } - - SwingUtilities.invokeLater(activeTabPanel::update); - } - - @Override - public void onActivate() - { - active = true; - update(); - } - - @Override - public void onDeactivate() - { - active = false; - } -} +/* + * Copyright (c) 2018 Abex + * Copyright (c) 2018, Psikoi + * 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.timetracking; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; +import net.runelite.client.game.AsyncBufferedImage; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.clocks.ClockManager; +import net.runelite.client.plugins.timetracking.farming.FarmingTracker; +import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.materialtabs.MaterialTab; +import net.runelite.client.ui.components.materialtabs.MaterialTabGroup; + +class TimeTrackingPanel extends PluginPanel +{ + private final ItemManager itemManager; + private final TimeTrackingConfig config; + + /* This is the panel the tabs' respective panels will be displayed on. */ + private final JPanel display = new JPanel(); + private final Map uiTabs = new HashMap<>(); + private final MaterialTabGroup tabGroup = new MaterialTabGroup(display); + + private boolean active; + + @Nullable + private TabContentPanel activeTabPanel = null; + + TimeTrackingPanel(ItemManager itemManager, TimeTrackingConfig config, + FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) + { + super(false); + + this.itemManager = itemManager; + this.config = config; + + setLayout(new BorderLayout()); + setBackground(ColorScheme.DARK_GRAY_COLOR); + + display.setBorder(new EmptyBorder(10, 10, 8, 10)); + + tabGroup.setLayout(new GridLayout(0, 6, 7, 7)); + tabGroup.setBorder(new EmptyBorder(10, 10, 0, 10)); + + add(tabGroup, BorderLayout.NORTH); + add(display, BorderLayout.CENTER); + + addTab(Tab.OVERVIEW, new OverviewTabPanel(itemManager, config, this, farmingTracker, birdHouseTracker, clockManager)); + addTab(Tab.CLOCK, clockManager.getClockTabPanel()); + addTab(Tab.BIRD_HOUSE, birdHouseTracker.createBirdHouseTabPanel()); + + for (Tab tab : Tab.FARMING_TABS) + { + addTab(tab, farmingTracker.createTabPanel(tab)); + } + } + + private void addTab(Tab tab, TabContentPanel tabContentPanel) + { + JPanel wrapped = new JPanel(new BorderLayout()); + wrapped.add(tabContentPanel, BorderLayout.NORTH); + wrapped.setBackground(ColorScheme.DARK_GRAY_COLOR); + + JScrollPane scroller = new JScrollPane(wrapped); + scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scroller.getVerticalScrollBar().setPreferredSize(new Dimension(16, 0)); + scroller.getVerticalScrollBar().setBorder(new EmptyBorder(0, 9, 0, 0)); + scroller.setBackground(ColorScheme.DARK_GRAY_COLOR); + + // Use a placeholder icon until the async image gets loaded + MaterialTab materialTab = new MaterialTab(new ImageIcon(), tabGroup, scroller); + materialTab.setPreferredSize(new Dimension(30, 27)); + materialTab.setName(tab.getName()); + materialTab.setToolTipText(tab.getName()); + + AsyncBufferedImage icon = itemManager.getImage(tab.getItemID()); + Runnable resize = () -> + { + BufferedImage subIcon = icon.getSubimage(0, 0, 32, 32); + materialTab.setIcon(new ImageIcon(subIcon.getScaledInstance(24, 24, Image.SCALE_SMOOTH))); + }; + icon.onChanged(resize); + resize.run(); + + materialTab.setOnSelectEvent(() -> + { + config.setActiveTab(tab); + activeTabPanel = tabContentPanel; + + tabContentPanel.update(); + return true; + }); + + uiTabs.put(tab, materialTab); + tabGroup.addTab(materialTab); + + if (config.activeTab() == tab) + { + tabGroup.select(materialTab); + } + } + + void switchTab(Tab tab) + { + tabGroup.select(uiTabs.get(tab)); + } + + /** + * Gets the update interval of the active tab panel, in units of 200 milliseconds. + */ + int getUpdateInterval() + { + return activeTabPanel == null ? Integer.MAX_VALUE : activeTabPanel.getUpdateInterval(); + } + + /** + * Updates the active tab panel, if this plugin panel is displayed. + */ + void update() + { + if (!active || activeTabPanel == null) + { + return; + } + + SwingUtilities.invokeLater(activeTabPanel::update); + } + + @Override + public void onActivate() + { + active = true; + update(); + } + + @Override + public void onDeactivate() + { + active = false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java index aa4027b98e..3d6d926126 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java @@ -1,309 +1,309 @@ -/* - * Copyright (c) 2018 Abex - * 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.timetracking.farming; - -import com.google.inject.Inject; -import com.google.inject.Singleton; -import java.time.Instant; -import java.util.EnumMap; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; -import net.runelite.api.Client; -import net.runelite.api.Varbits; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.vars.Autoweed; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.timetracking.SummaryState; -import net.runelite.client.plugins.timetracking.Tab; -import net.runelite.client.plugins.timetracking.TimeTrackingConfig; - -@Singleton -public class FarmingTracker -{ - private final Client client; - private final ItemManager itemManager; - private final ConfigManager configManager; - private final TimeTrackingConfig config; - private final FarmingWorld farmingWorld; - - private final Map summaries = new EnumMap<>(Tab.class); - - /** - * The time at which all patches of a particular type will be ready to be harvested, - * or {@code -1} if we have no data about any patch of the given type. - */ - private final Map completionTimes = new EnumMap<>(Tab.class); - - @Inject - private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, - TimeTrackingConfig config, FarmingWorld farmingWorld) - { - this.client = client; - this.itemManager = itemManager; - this.configManager = configManager; - this.config = config; - this.farmingWorld = farmingWorld; - } - - - public FarmingTabPanel createTabPanel(Tab tab) - { - return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab)); - } - - /** - * Updates tracker data for the current region. Returns true if any data was changed. - */ - public boolean updateData(WorldPoint location) - { - boolean changed = false; - - { - String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername(); - String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED)); - if (!autoweed.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED))) - { - configManager.setConfiguration(group, TimeTrackingConfig.AUTOWEED, autoweed); - changed = true; - } - } - - FarmingRegion region = farmingWorld.getRegions().get(location.getRegionID()); - if (region != null && region.isInBounds(location)) - { - // Write config with new varbits - // timetracking...=: - String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + region.getRegionID(); - long unixNow = Instant.now().getEpochSecond(); - for (FarmingPatch patch : region.getPatches()) - { - // Write the config value if it doesn't match what is current, or it is more than 5 minutes old - Varbits varbit = patch.getVarbit(); - String key = Integer.toString(varbit.getId()); - String strVarbit = Integer.toString(client.getVar(varbit)); - String storedValue = configManager.getConfiguration(group, key); - - if (storedValue != null) - { - String[] parts = storedValue.split(":"); - if (parts.length == 2 && parts[0].equals(strVarbit)) - { - long unixTime = 0; - try - { - unixTime = Long.parseLong(parts[1]); - } - catch (NumberFormatException e) - { - // ignored - } - if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime) - { - continue; - } - } - } - - String value = strVarbit + ":" + unixNow; - configManager.setConfiguration(group, key, value); - changed = true; - } - } - - if (changed) - { - updateCompletionTime(); - } - - return changed; - } - - @Nullable - public PatchPrediction predictPatch(FarmingPatch patch) - { - long unixNow = Instant.now().getEpochSecond(); - - boolean autoweed; - { - String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername(); - autoweed = Integer.toString(Autoweed.ON.ordinal()) - .equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED)); - } - - String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + patch.getRegion().getRegionID(); - String key = Integer.toString(patch.getVarbit().getId()); - String storedValue = configManager.getConfiguration(group, key); - - if (storedValue == null) - { - return null; - } - - long unixTime = 0; - int value = 0; - { - String[] parts = storedValue.split(":"); - if (parts.length == 2) - { - try - { - value = Integer.parseInt(parts[0]); - unixTime = Long.parseLong(parts[1]); - } - catch (NumberFormatException e) - { - } - } - } - - if (unixTime <= 0) - { - return null; - } - - PatchState state = patch.getImplementation().forVarbitValue(value); - - int stage = state.getStage(); - int stages = state.getStages(); - int tickrate = state.getTickRate() * 60; - - if (autoweed && state.getProduce() == Produce.WEEDS) - { - stage = 0; - stages = 1; - tickrate = 0; - } - - long doneEstimate = 0; - if (tickrate > 0) - { - long tickNow = (unixNow + (5 * 60)) / tickrate; - long tickTime = (unixTime + (5 * 60)) / tickrate; - int delta = (int) (tickNow - tickTime); - - doneEstimate = ((stages - 1 - stage) + tickTime) * tickrate + (5 * 60); - - stage += delta; - if (stage >= stages) - { - stage = stages - 1; - } - } - - return new PatchPrediction( - state.getProduce(), - state.getCropState(), - doneEstimate, - stage, - stages - ); - } - - public void loadCompletionTimes() - { - summaries.clear(); - completionTimes.clear(); - updateCompletionTime(); - } - - public SummaryState getSummary(Tab patchType) - { - SummaryState summary = summaries.get(patchType); - return summary == null ? SummaryState.UNKNOWN : summary; - } - - /** - * Gets the overall completion time for the given patch type. - * - * @see #completionTimes - */ - public long getCompletionTime(Tab patchType) - { - Long completionTime = completionTimes.get(patchType); - return completionTime == null ? -1 : completionTime; - } - - /** - * Updates the overall completion time for the given patch type. - * - * @see #completionTimes - */ - private void updateCompletionTime() - { - for (Map.Entry> tab : farmingWorld.getTabs().entrySet()) - { - long maxCompletionTime = 0; - boolean allUnknown = true; - boolean allEmpty = true; - - for (FarmingPatch patch : tab.getValue()) - { - PatchPrediction prediction = predictPatch(patch); - if (prediction == null || prediction.getProduce().getItemID() < 0) - { - continue; // unknown state - } - - allUnknown = false; - - if (prediction.getProduce() != Produce.WEEDS && prediction.getProduce() != Produce.SCARECROW) - { - allEmpty = false; - - // update max duration if this patch takes longer to grow - maxCompletionTime = Math.max(maxCompletionTime, prediction.getDoneEstimate()); - } - } - - final SummaryState state; - final long completionTime; - - if (allUnknown) - { - state = SummaryState.UNKNOWN; - completionTime = -1L; - } - else if (allEmpty) - { - state = SummaryState.EMPTY; - completionTime = -1L; - } - else if (maxCompletionTime <= Instant.now().getEpochSecond()) - { - state = SummaryState.COMPLETED; - completionTime = 0; - } - else - { - state = SummaryState.IN_PROGRESS; - completionTime = maxCompletionTime; - } - summaries.put(tab.getKey(), state); - completionTimes.put(tab.getKey(), completionTime); - } - } -} +/* + * Copyright (c) 2018 Abex + * 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.timetracking.farming; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.time.Instant; +import java.util.EnumMap; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; +import net.runelite.api.Client; +import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.vars.Autoweed; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.SummaryState; +import net.runelite.client.plugins.timetracking.Tab; +import net.runelite.client.plugins.timetracking.TimeTrackingConfig; + +@Singleton +public class FarmingTracker +{ + private final Client client; + private final ItemManager itemManager; + private final ConfigManager configManager; + private final TimeTrackingConfig config; + private final FarmingWorld farmingWorld; + + private final Map summaries = new EnumMap<>(Tab.class); + + /** + * The time at which all patches of a particular type will be ready to be harvested, + * or {@code -1} if we have no data about any patch of the given type. + */ + private final Map completionTimes = new EnumMap<>(Tab.class); + + @Inject + private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, + TimeTrackingConfig config, FarmingWorld farmingWorld) + { + this.client = client; + this.itemManager = itemManager; + this.configManager = configManager; + this.config = config; + this.farmingWorld = farmingWorld; + } + + + public FarmingTabPanel createTabPanel(Tab tab) + { + return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab)); + } + + /** + * Updates tracker data for the current region. Returns true if any data was changed. + */ + public boolean updateData(WorldPoint location) + { + boolean changed = false; + + { + String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername(); + String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED)); + if (!autoweed.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED))) + { + configManager.setConfiguration(group, TimeTrackingConfig.AUTOWEED, autoweed); + changed = true; + } + } + + FarmingRegion region = farmingWorld.getRegions().get(location.getRegionID()); + if (region != null && region.isInBounds(location)) + { + // Write config with new varbits + // timetracking...=: + String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + region.getRegionID(); + long unixNow = Instant.now().getEpochSecond(); + for (FarmingPatch patch : region.getPatches()) + { + // Write the config value if it doesn't match what is current, or it is more than 5 minutes old + Varbits varbit = patch.getVarbit(); + String key = Integer.toString(varbit.getId()); + String strVarbit = Integer.toString(client.getVar(varbit)); + String storedValue = configManager.getConfiguration(group, key); + + if (storedValue != null) + { + String[] parts = storedValue.split(":"); + if (parts.length == 2 && parts[0].equals(strVarbit)) + { + long unixTime = 0; + try + { + unixTime = Long.parseLong(parts[1]); + } + catch (NumberFormatException e) + { + // ignored + } + if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime) + { + continue; + } + } + } + + String value = strVarbit + ":" + unixNow; + configManager.setConfiguration(group, key, value); + changed = true; + } + } + + if (changed) + { + updateCompletionTime(); + } + + return changed; + } + + @Nullable + public PatchPrediction predictPatch(FarmingPatch patch) + { + long unixNow = Instant.now().getEpochSecond(); + + boolean autoweed; + { + String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername(); + autoweed = Integer.toString(Autoweed.ON.ordinal()) + .equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED)); + } + + String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + patch.getRegion().getRegionID(); + String key = Integer.toString(patch.getVarbit().getId()); + String storedValue = configManager.getConfiguration(group, key); + + if (storedValue == null) + { + return null; + } + + long unixTime = 0; + int value = 0; + { + String[] parts = storedValue.split(":"); + if (parts.length == 2) + { + try + { + value = Integer.parseInt(parts[0]); + unixTime = Long.parseLong(parts[1]); + } + catch (NumberFormatException e) + { + } + } + } + + if (unixTime <= 0) + { + return null; + } + + PatchState state = patch.getImplementation().forVarbitValue(value); + + int stage = state.getStage(); + int stages = state.getStages(); + int tickrate = state.getTickRate() * 60; + + if (autoweed && state.getProduce() == Produce.WEEDS) + { + stage = 0; + stages = 1; + tickrate = 0; + } + + long doneEstimate = 0; + if (tickrate > 0) + { + long tickNow = (unixNow + (5 * 60)) / tickrate; + long tickTime = (unixTime + (5 * 60)) / tickrate; + int delta = (int) (tickNow - tickTime); + + doneEstimate = ((stages - 1 - stage) + tickTime) * tickrate + (5 * 60); + + stage += delta; + if (stage >= stages) + { + stage = stages - 1; + } + } + + return new PatchPrediction( + state.getProduce(), + state.getCropState(), + doneEstimate, + stage, + stages + ); + } + + public void loadCompletionTimes() + { + summaries.clear(); + completionTimes.clear(); + updateCompletionTime(); + } + + public SummaryState getSummary(Tab patchType) + { + SummaryState summary = summaries.get(patchType); + return summary == null ? SummaryState.UNKNOWN : summary; + } + + /** + * Gets the overall completion time for the given patch type. + * + * @see #completionTimes + */ + public long getCompletionTime(Tab patchType) + { + Long completionTime = completionTimes.get(patchType); + return completionTime == null ? -1 : completionTime; + } + + /** + * Updates the overall completion time for the given patch type. + * + * @see #completionTimes + */ + private void updateCompletionTime() + { + for (Map.Entry> tab : farmingWorld.getTabs().entrySet()) + { + long maxCompletionTime = 0; + boolean allUnknown = true; + boolean allEmpty = true; + + for (FarmingPatch patch : tab.getValue()) + { + PatchPrediction prediction = predictPatch(patch); + if (prediction == null || prediction.getProduce().getItemID() < 0) + { + continue; // unknown state + } + + allUnknown = false; + + if (prediction.getProduce() != Produce.WEEDS && prediction.getProduce() != Produce.SCARECROW) + { + allEmpty = false; + + // update max duration if this patch takes longer to grow + maxCompletionTime = Math.max(maxCompletionTime, prediction.getDoneEstimate()); + } + } + + final SummaryState state; + final long completionTime; + + if (allUnknown) + { + state = SummaryState.UNKNOWN; + completionTime = -1L; + } + else if (allEmpty) + { + state = SummaryState.EMPTY; + completionTime = -1L; + } + else if (maxCompletionTime <= Instant.now().getEpochSecond()) + { + state = SummaryState.COMPLETED; + completionTime = 0; + } + else + { + state = SummaryState.IN_PROGRESS; + completionTime = maxCompletionTime; + } + summaries.put(tab.getKey(), state); + completionTimes.put(tab.getKey(), completionTime); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java index c61b952cee..bef011cea4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java @@ -1,253 +1,254 @@ -/* - * Copyright (c) 2018 Abex - * Copyright (c) 2018, Daniel Teo - * 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.timetracking.hunter; - -import com.google.common.collect.ImmutableSet; -import com.google.inject.Inject; -import com.google.inject.Singleton; -import java.time.Duration; -import java.time.Instant; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.Notifier; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.timetracking.SummaryState; -import net.runelite.client.plugins.timetracking.TimeTrackingConfig; - -@Singleton -public class BirdHouseTracker -{ - // average time taken to harvest 10 birds, in seconds - static final int BIRD_HOUSE_DURATION = (int) Duration.ofMinutes(50).getSeconds(); - - private static ImmutableSet FOSSIL_ISLAND_REGIONS = ImmutableSet.of(14650, 14651, 14652, 14906, 14907, 15162, 15163); - - private final Client client; - private final ItemManager itemManager; - private final ConfigManager configManager; - private final TimeTrackingConfig config; - private final Notifier notifier; - - @Getter(AccessLevel.PACKAGE) - private final ConcurrentMap birdHouseData = new ConcurrentHashMap<>(); - - @Getter - private SummaryState summary = SummaryState.UNKNOWN; - - /** - * The time at which all the bird houses will be ready to be dismantled, - * or {@code -1} if we have no data about any of the bird house spaces. - */ - @Getter - private long completionTime = -1; - - @Inject - private BirdHouseTracker(Client client, ItemManager itemManager, ConfigManager configManager, - TimeTrackingConfig config, Notifier notifier) - { - this.client = client; - this.itemManager = itemManager; - this.configManager = configManager; - this.config = config; - this.notifier = notifier; - } - - public BirdHouseTabPanel createBirdHouseTabPanel() - { - return new BirdHouseTabPanel(itemManager, this, config); - } - - public void loadFromConfig() - { - birdHouseData.clear(); - - final String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + TimeTrackingConfig.BIRD_HOUSE; - - for (BirdHouseSpace space : BirdHouseSpace.values()) - { - String key = Integer.toString(space.getVarp().getId()); - String storedValue = configManager.getConfiguration(group, key); - - if (storedValue != null) - { - String[] parts = storedValue.split(":"); - if (parts.length == 2) - { - try - { - int varp = Integer.parseInt(parts[0]); - long timestamp = Long.parseLong(parts[1]); - birdHouseData.put(space, new BirdHouseData(space, varp, timestamp)); - } - catch (NumberFormatException e) - { - // ignored - } - } - } - } - - updateCompletionTime(); - } - - /** - * Updates tracker data if player is within range of any bird house. Returns true if any data was changed. - */ - public boolean updateData(WorldPoint location) - { - boolean changed = false; - - if (FOSSIL_ISLAND_REGIONS.contains(location.getRegionID()) && location.getPlane() == 0) - { - final Map newData = new HashMap<>(); - final long currentTime = Instant.now().getEpochSecond(); - int removalCount = 0; - - for (BirdHouseSpace space : BirdHouseSpace.values()) - { - int varp = client.getVar(space.getVarp()); - BirdHouseData oldData = birdHouseData.get(space); - int oldVarp = oldData == null ? -1 : oldData.getVarp(); - - // update data if there isn't one, or if the varp doesn't match - if (varp != oldVarp) - { - newData.put(space, new BirdHouseData(space, varp, currentTime)); - changed = true; - } - - if (varp <= 0 && oldVarp > 0) - { - removalCount++; - } - } - - // Prevent the resetting of bird house data that could occur if the varps have not been updated yet - // after the player enters the region. We assume that players would generally have 3 or 4 bird houses - // built at any time, and that dropping from 3/4 to 0 built bird houses is not normally possible. - if (removalCount > 2) - { - return false; - } - - if (changed) - { - birdHouseData.putAll(newData); - updateCompletionTime(); - saveToConfig(newData); - } - } - - return changed; - } - - /** - * Checks if the bird houses have become ready to be dismantled, - * and sends a notification if required. - */ - public boolean checkCompletion() - { - if (summary == SummaryState.IN_PROGRESS && completionTime < Instant.now().getEpochSecond()) - { - summary = SummaryState.COMPLETED; - completionTime = 0; - - if (config.birdHouseNotification()) - { - notifier.notify("Your bird houses are ready to be dismantled."); - } - - return true; - } - - return false; - } - - /** - * Updates the overall completion time of the bird houses. - * @see #completionTime - */ - private void updateCompletionTime() - { - if (birdHouseData.isEmpty()) - { - summary = SummaryState.UNKNOWN; - completionTime = -1; - return; - } - - boolean allEmpty = true; - long maxCompletionTime = 0; - for (BirdHouseData data : birdHouseData.values()) - { - final BirdHouseState state = BirdHouseState.fromVarpValue(data.getVarp()); - - if (state != BirdHouseState.EMPTY) - { - allEmpty = false; - } - - if (state == BirdHouseState.SEEDED) - { - maxCompletionTime = Math.max(maxCompletionTime, data.getTimestamp() + BIRD_HOUSE_DURATION); - } - } - - if (allEmpty) - { - summary = SummaryState.EMPTY; - completionTime = 0; - } - else if (maxCompletionTime <= Instant.now().getEpochSecond()) - { - summary = SummaryState.COMPLETED; - completionTime = 0; - } - else - { - summary = SummaryState.IN_PROGRESS; - completionTime = maxCompletionTime; - } - } - - private void saveToConfig(Map updatedData) - { - final String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + TimeTrackingConfig.BIRD_HOUSE; - - for (BirdHouseData data : updatedData.values()) - { - String key = Integer.toString(data.getSpace().getVarp().getId()); - configManager.setConfiguration(group, key, data.getVarp() + ":" + data.getTimestamp()); - } - } -} +/* + * Copyright (c) 2018 Abex + * Copyright (c) 2018, Daniel Teo + * 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.timetracking.hunter; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.time.Duration; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.SummaryState; +import net.runelite.client.plugins.timetracking.TimeTrackingConfig; + +@Singleton +public class BirdHouseTracker +{ + // average time taken to harvest 10 birds, in seconds + static final int BIRD_HOUSE_DURATION = (int) Duration.ofMinutes(50).getSeconds(); + + private static ImmutableSet FOSSIL_ISLAND_REGIONS = ImmutableSet.of(14650, 14651, 14652, 14906, 14907, 15162, 15163); + + private final Client client; + private final ItemManager itemManager; + private final ConfigManager configManager; + private final TimeTrackingConfig config; + private final Notifier notifier; + + @Getter(AccessLevel.PACKAGE) + private final ConcurrentMap birdHouseData = new ConcurrentHashMap<>(); + + @Getter + private SummaryState summary = SummaryState.UNKNOWN; + + /** + * The time at which all the bird houses will be ready to be dismantled, + * or {@code -1} if we have no data about any of the bird house spaces. + */ + @Getter + private long completionTime = -1; + + @Inject + private BirdHouseTracker(Client client, ItemManager itemManager, ConfigManager configManager, + TimeTrackingConfig config, Notifier notifier) + { + this.client = client; + this.itemManager = itemManager; + this.configManager = configManager; + this.config = config; + this.notifier = notifier; + } + + public BirdHouseTabPanel createBirdHouseTabPanel() + { + return new BirdHouseTabPanel(itemManager, this, config); + } + + public void loadFromConfig() + { + birdHouseData.clear(); + + final String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + TimeTrackingConfig.BIRD_HOUSE; + + for (BirdHouseSpace space : BirdHouseSpace.values()) + { + String key = Integer.toString(space.getVarp().getId()); + String storedValue = configManager.getConfiguration(group, key); + + if (storedValue != null) + { + String[] parts = storedValue.split(":"); + if (parts.length == 2) + { + try + { + int varp = Integer.parseInt(parts[0]); + long timestamp = Long.parseLong(parts[1]); + birdHouseData.put(space, new BirdHouseData(space, varp, timestamp)); + } + catch (NumberFormatException e) + { + // ignored + } + } + } + } + + updateCompletionTime(); + } + + /** + * Updates tracker data if player is within range of any bird house. Returns true if any data was changed. + */ + public boolean updateData(WorldPoint location) + { + boolean changed = false; + + if (FOSSIL_ISLAND_REGIONS.contains(location.getRegionID()) && location.getPlane() == 0) + { + final Map newData = new HashMap<>(); + final long currentTime = Instant.now().getEpochSecond(); + int removalCount = 0; + + for (BirdHouseSpace space : BirdHouseSpace.values()) + { + int varp = client.getVar(space.getVarp()); + BirdHouseData oldData = birdHouseData.get(space); + int oldVarp = oldData == null ? -1 : oldData.getVarp(); + + // update data if there isn't one, or if the varp doesn't match + if (varp != oldVarp) + { + newData.put(space, new BirdHouseData(space, varp, currentTime)); + changed = true; + } + + if (varp <= 0 && oldVarp > 0) + { + removalCount++; + } + } + + // Prevent the resetting of bird house data that could occur if the varps have not been updated yet + // after the player enters the region. We assume that players would generally have 3 or 4 bird houses + // built at any time, and that dropping from 3/4 to 0 built bird houses is not normally possible. + if (removalCount > 2) + { + return false; + } + + if (changed) + { + birdHouseData.putAll(newData); + updateCompletionTime(); + saveToConfig(newData); + } + } + + return changed; + } + + /** + * Checks if the bird houses have become ready to be dismantled, + * and sends a notification if required. + */ + public boolean checkCompletion() + { + if (summary == SummaryState.IN_PROGRESS && completionTime < Instant.now().getEpochSecond()) + { + summary = SummaryState.COMPLETED; + completionTime = 0; + + if (config.birdHouseNotification()) + { + notifier.notify("Your bird houses are ready to be dismantled."); + } + + return true; + } + + return false; + } + + /** + * Updates the overall completion time of the bird houses. + * + * @see #completionTime + */ + private void updateCompletionTime() + { + if (birdHouseData.isEmpty()) + { + summary = SummaryState.UNKNOWN; + completionTime = -1; + return; + } + + boolean allEmpty = true; + long maxCompletionTime = 0; + for (BirdHouseData data : birdHouseData.values()) + { + final BirdHouseState state = BirdHouseState.fromVarpValue(data.getVarp()); + + if (state != BirdHouseState.EMPTY) + { + allEmpty = false; + } + + if (state == BirdHouseState.SEEDED) + { + maxCompletionTime = Math.max(maxCompletionTime, data.getTimestamp() + BIRD_HOUSE_DURATION); + } + } + + if (allEmpty) + { + summary = SummaryState.EMPTY; + completionTime = 0; + } + else if (maxCompletionTime <= Instant.now().getEpochSecond()) + { + summary = SummaryState.COMPLETED; + completionTime = 0; + } + else + { + summary = SummaryState.IN_PROGRESS; + completionTime = maxCompletionTime; + } + } + + private void saveToConfig(Map updatedData) + { + final String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + TimeTrackingConfig.BIRD_HOUSE; + + for (BirdHouseData data : updatedData.values()) + { + String key = Integer.toString(data.getSpace().getVarp().getId()); + configManager.setConfiguration(group, key, data.getVarp() + ":" + data.getTimestamp()); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tobdamagecount/DamageCounterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/tobdamagecount/DamageCounterPlugin.java index 2225ebde17..1228ebca02 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tobdamagecount/DamageCounterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tobdamagecount/DamageCounterPlugin.java @@ -1,358 +1,360 @@ -/* - * Copyright (c) 2018, Bryan Chau(RSN:Laura Brehm) - * 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.tobdamagecount; - -import javax.inject.Inject; -import java.text.DecimalFormat; - -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.NPC; -import net.runelite.api.NpcID; -import net.runelite.api.Skill; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Actor; -import net.runelite.api.Player; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.HitsplatApplied; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.NpcDespawned; -import net.runelite.api.events.LocalPlayerDeath; -import net.runelite.client.chat.ChatColorType; -import net.runelite.client.chat.ChatMessageBuilder; -import net.runelite.client.chat.ChatMessageManager; -import net.runelite.client.chat.QueuedMessage; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.PluginType; - - -@PluginDescriptor( - name = "ToB Damage Counter", - description = "Gives you an estimation damage on a boss and taken after the fight is done" + - "the damage will be posted in the chat", - tags = {"combat", "npcs", "tob", "damage"}, - type = PluginType.PVM, - enabledByDefault = false -) - -public class DamageCounterPlugin extends Plugin -{ - private int currentWorld = -1; - private int DamageCount = 0; - private int currenthpxp = -1; // checking the current hp xp so be easier to find - private String BossName = null; //to ID the boss to calculate the damage - private int DamageTaken = 0; - private boolean status = true; //default boolean alive = true, dead = false - //formatting the number for damage taken and dealt with to look beeter - private static final DecimalFormat DAMAGEFORMAT = new DecimalFormat("#,###"); - private static final double XP_RATIO = 1.3333; - private static final double BOSS_MODIFIER = 1.05; - private static final int MAIDENHP = 3500; - private static final int BLOATHP = 2000; - private static final int NYLOHP = 2500; - private static final int SOTHP = 4000; - private static final int XARPUSHP = 5080; - private static final int VERZIKHP = 8500; - private static final boolean ALIVE = true; // - private static final boolean DEAD = false; //if they're dead they cannot "recreate" the message of being alive - //locations at ToB - private static final int MAIDEN_REGION = 12613; - private static final int MAIDEN_REGION_1 = 12869; - private static final int BLOAT_REGION = 13125; - private static final int NYLOCAS_REGION = 13122; - private static final int SOTETSEG_REGION = 13123; - private static final int SOTETSEG_REGION2 = 13379; - private static final int XARPUS_REGION = 12612; - private static final int VERZIK_REGION = 12611; - private static final int[] ToB_Region = {MAIDEN_REGION, MAIDEN_REGION_1, BLOAT_REGION, NYLOCAS_REGION, - SOTETSEG_REGION, SOTETSEG_REGION2, XARPUS_REGION, VERZIK_REGION}; - //setting up the array for a check list - private static int[] NPCARRAY = {NpcID.THE_MAIDEN_OF_SUGADINTI, NpcID.THE_MAIDEN_OF_SUGADINTI_8361, - NpcID.THE_MAIDEN_OF_SUGADINTI_8362, NpcID.THE_MAIDEN_OF_SUGADINTI_8363, NpcID.THE_MAIDEN_OF_SUGADINTI_8364, - NpcID.THE_MAIDEN_OF_SUGADINTI_8365, NpcID.PESTILENT_BLOAT, NpcID.NYLOCAS_VASILIAS, - NpcID.NYLOCAS_VASILIAS_8355, NpcID.NYLOCAS_VASILIAS_8356, NpcID.NYLOCAS_VASILIAS_8357, NpcID.SOTETSEG, - NpcID.SOTETSEG_8388, NpcID.XARPUS, NpcID.XARPUS_8339, NpcID.XARPUS_8340, NpcID.XARPUS_8341, - NpcID.VERZIK_VITUR, NpcID.VERZIK_VITUR_8369, NpcID.VERZIK_VITUR_8370, NpcID.VERZIK_VITUR_8371, - NpcID.VERZIK_VITUR_8372, NpcID.VERZIK_VITUR_8373, NpcID.VERZIK_VITUR_8374, NpcID.VERZIK_VITUR_8375}; - - private int[] HEALTHARRAY = {MAIDENHP, NYLOHP, VERZIKHP}; - - @Inject - private Client client; - @Inject - private ChatMessageManager chatMessangerManager; - //every game tick it will go through methods - @Subscribe - private void onGameTick(GameTick tick) - { - if (client.getGameState() != GameState.LOGGED_IN) - { - ResetCounter(); - return; - } - checkInterAction(); - DamageCounting(); - currenthpxp = client.getSkillExperience(Skill.HITPOINTS); - } - //checks for npcID and put the boss name into a string be easier to ID it - //once the boss is found it will never check it - private void checkInterAction() - { - Player localPlayer = client.getLocalPlayer(); - Actor interacting = localPlayer.getInteracting(); - if (client.getGameState() == GameState.LOGGED_IN) - { - if (BossName == null) - { - if (interacting instanceof NPC) - { - int interactingId = ((NPC) interacting).getId(); - String interactingName = interacting.getName(); - for (int aNPCARRAY : NPCARRAY) - { - if (aNPCARRAY == interactingId) - { - BossName = interactingName; - } - } - } - } - } - } - - @Subscribe - //if you hop it will reset the counter - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGGED_IN) - { - if (currentWorld == -1) - { - currentWorld = client.getWorld(); - } - else if (currentWorld != client.getWorld()) - { - currentWorld = client.getWorld(); - ResetCounter(); - } - } - } - - //grabbing the xp and calculating the damage - private int XPtoDamage() - { - int NewXp; - double damageOutput = 0; - int XPdrop; - if (currenthpxp != -1) - { - XPdrop = client.getSkillExperience(Skill.HITPOINTS); - NewXp = XPdrop - currenthpxp; - currenthpxp = -1; - damageOutput = NewXp / XP_RATIO; - } - //returns the damage you have done - return (int) Math.floor(damageOutput); - } - - //adding up the damage for the print message checks every tick(aka attack tick) - private void DamageCounting() - { - Player localPlayer = client.getLocalPlayer(); - Actor interacting = localPlayer.getInteracting(); - if (client.getGameState() == GameState.LOGGED_IN) - { - if (interacting instanceof NPC) - { - String interactingName = interacting.getName(); - int NPC = ((NPC) interacting).getId(); - if (interactingName.equals(BossName)) - { - DamageCount += (XPtoDamage() * BOSS_MODIFIER); - - } - } - } - } - - - @Subscribe - //will add the damage that you have taken from the current boss fight - private void onHitsplatApplied(HitsplatApplied Hit) - { - if (Hit.getActor().equals(client.getLocalPlayer())) - { - DamageTaken += Hit.getHitsplat().getAmount(); - } - - } - - //will check for the monster if it died works only on ToB Bosses - /*Verzik has three phases so the program will add up all the damage and prints it into one message - because every time she phases she "dies" so making sure the counter doesn't print out the damage for phase 1, 2, - and 3. - */ - @Subscribe - public void onNpcDespawned(NpcDespawned npc) - { - NPC actor = npc.getNpc(); - double Percent = calculatePercent(WorldPoint.fromLocalInstance(client, - client.getLocalPlayer().getLocalLocation()).getRegionID()); - if (actor.isDead() && actor.getId() == NpcID.VERZIK_VITUR_8375 && status) - { - DamagePrint(actor, Percent); - ResetCounter(); - } - else if (actor.isDead() && actor.getName().equals(BossName) && actor.getId() != NpcID.VERZIK_VITUR_8374 && - actor.getId() != NpcID.VERZIK_VITUR_8372 && actor.getId() != NpcID.VERZIK_VITUR_8370 && - status) - { - DamagePrint(actor, Percent); - ResetCounter(); - } - //will reset the counter after the boss dies and if you died during the fight - else if (actor.isDead() && actor.getName().equals(BossName) && !status) - { - ResetCounter(); - } - } - - private double calculatePercent(int id) - { - double percent = 0; - if (DamageCount != 0) { - if (id == MAIDEN_REGION || id == MAIDEN_REGION_1) - { - percent = (DamageCount / (double) MAIDENHP) * 100; - } - else if (id == BLOAT_REGION) - { - percent = (DamageCount / (double) BLOATHP) * 100; - } - else if (id == NYLOCAS_REGION) - { - percent = (DamageCount / (double) NYLOHP) * 100; - } - else if (id == SOTETSEG_REGION || id == SOTETSEG_REGION2) - { - percent = (DamageCount / (double) SOTHP) * 100; - } - else if (id == XARPUS_REGION) - { - percent = (DamageCount / (double) XARPUSHP) * 100; - } - else if (id == VERZIK_REGION) - { - percent = (DamageCount / (double) VERZIKHP) * 100; - } - } - return percent; - } - - //just reset the counter for the next fight and status - private void ResetCounter() - { - DamageCount = 0; - DamageTaken = 0; - BossName = null; - status = ALIVE; - } - - //print out the damage after the boss have died - //prevent people from spectating to get the damage message, it is impossible for them to get damage - private void DamagePrint(NPC actor, double percent) - { - String MessageDamage; - if (percent >= 50) - { - MessageDamage = "Well done carrying the team!" + - "WOWIE!! You did" + DAMAGEFORMAT.format(DamageCount) + " damage to " + - actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; - } - else if (percent >= 25) - { - MessageDamage = "Well done carrying some dead weight in your team! " + - "Awesome! You did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + - actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; - } - else if (percent >= 1) - { - MessageDamage = "Well done everyone is pulling their weight! " + - "You did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + - actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; - } - else - { - MessageDamage = "Didn't do much" + - "Fucking leech did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + - actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; - } - - sendChatMessage(MessageDamage); - String MessageTaken = "You have taken " + DAMAGEFORMAT.format(DamageTaken) + " damage from this fight!"; - sendChatMessage(MessageTaken); - } - - @Subscribe - //whenever you have died in tob you will get a death message with damage - // made sure the message works at ToB area or else it will message every where - private void onLocalPlayerDeath(LocalPlayerDeath death) - { - String DeathMessage = "You have died! You did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + - BossName + "!"; - String MessageTaken = "You have taken " + DAMAGEFORMAT.format(DamageTaken) + " damage from this fight!"; - for (int i = 0; i < ToB_Region.length; i++) - { - if (WorldPoint.fromLocalInstance(client, - client.getLocalPlayer().getLocalLocation()).getRegionID() == ToB_Region[i]) - { - sendChatMessage(DeathMessage); - sendChatMessage(MessageTaken); - ResetCounter(); - //status will become "dead" after you died in the fight - status = DEAD; - } - } - } - - //sends a message saying this "You have done XYZ damage to boss name! or the death message - // "Well done! you have done your best, you have done XYZ damage to boss name - private void sendChatMessage(String chatMessage) - { - final String message = new ChatMessageBuilder() - .append(ChatColorType.HIGHLIGHT) - .append(chatMessage) - .build(); - chatMessangerManager.queue( - QueuedMessage.builder() - .type(ChatMessageType.CONSOLE) - .runeLiteFormattedMessage(message) - .build()); - } +/* + * Copyright (c) 2018, Bryan Chau(RSN:Laura Brehm) + * 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.tobdamagecount; + +import java.text.DecimalFormat; +import javax.inject.Inject; +import net.runelite.api.Actor; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.NPC; +import net.runelite.api.NpcID; +import net.runelite.api.Player; +import net.runelite.api.Skill; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.HitsplatApplied; +import net.runelite.api.events.LocalPlayerDeath; +import net.runelite.api.events.NpcDespawned; +import net.runelite.client.chat.ChatColorType; +import net.runelite.client.chat.ChatMessageBuilder; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.chat.QueuedMessage; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; + + +@PluginDescriptor( + name = "ToB Damage Counter", + description = "Gives you an estimation damage on a boss and taken after the fight is done" + + "the damage will be posted in the chat", + tags = {"combat", "npcs", "tob", "damage"}, + type = PluginType.PVM, + enabledByDefault = false +) + +public class DamageCounterPlugin extends Plugin +{ + private int currentWorld = -1; + private int DamageCount = 0; + private int currenthpxp = -1; // checking the current hp xp so be easier to find + private String BossName = null; //to ID the boss to calculate the damage + private int DamageTaken = 0; + private boolean status = true; //default boolean alive = true, dead = false + //formatting the number for damage taken and dealt with to look beeter + private static final DecimalFormat DAMAGEFORMAT = new DecimalFormat("#,###"); + private static final double XP_RATIO = 1.3333; + private static final double BOSS_MODIFIER = 1.05; + private static final int MAIDENHP = 3500; + private static final int BLOATHP = 2000; + private static final int NYLOHP = 2500; + private static final int SOTHP = 4000; + private static final int XARPUSHP = 5080; + private static final int VERZIKHP = 8500; + private static final boolean ALIVE = true; // + private static final boolean DEAD = false; //if they're dead they cannot "recreate" the message of being alive + //locations at ToB + private static final int MAIDEN_REGION = 12613; + private static final int MAIDEN_REGION_1 = 12869; + private static final int BLOAT_REGION = 13125; + private static final int NYLOCAS_REGION = 13122; + private static final int SOTETSEG_REGION = 13123; + private static final int SOTETSEG_REGION2 = 13379; + private static final int XARPUS_REGION = 12612; + private static final int VERZIK_REGION = 12611; + private static final int[] ToB_Region = {MAIDEN_REGION, MAIDEN_REGION_1, BLOAT_REGION, NYLOCAS_REGION, + SOTETSEG_REGION, SOTETSEG_REGION2, XARPUS_REGION, VERZIK_REGION}; + //setting up the array for a check list + private static int[] NPCARRAY = {NpcID.THE_MAIDEN_OF_SUGADINTI, NpcID.THE_MAIDEN_OF_SUGADINTI_8361, + NpcID.THE_MAIDEN_OF_SUGADINTI_8362, NpcID.THE_MAIDEN_OF_SUGADINTI_8363, NpcID.THE_MAIDEN_OF_SUGADINTI_8364, + NpcID.THE_MAIDEN_OF_SUGADINTI_8365, NpcID.PESTILENT_BLOAT, NpcID.NYLOCAS_VASILIAS, + NpcID.NYLOCAS_VASILIAS_8355, NpcID.NYLOCAS_VASILIAS_8356, NpcID.NYLOCAS_VASILIAS_8357, NpcID.SOTETSEG, + NpcID.SOTETSEG_8388, NpcID.XARPUS, NpcID.XARPUS_8339, NpcID.XARPUS_8340, NpcID.XARPUS_8341, + NpcID.VERZIK_VITUR, NpcID.VERZIK_VITUR_8369, NpcID.VERZIK_VITUR_8370, NpcID.VERZIK_VITUR_8371, + NpcID.VERZIK_VITUR_8372, NpcID.VERZIK_VITUR_8373, NpcID.VERZIK_VITUR_8374, NpcID.VERZIK_VITUR_8375}; + + private int[] HEALTHARRAY = {MAIDENHP, NYLOHP, VERZIKHP}; + + @Inject + private Client client; + @Inject + private ChatMessageManager chatMessangerManager; + + //every game tick it will go through methods + @Subscribe + private void onGameTick(GameTick tick) + { + if (client.getGameState() != GameState.LOGGED_IN) + { + ResetCounter(); + return; + } + checkInterAction(); + DamageCounting(); + currenthpxp = client.getSkillExperience(Skill.HITPOINTS); + } + + //checks for npcID and put the boss name into a string be easier to ID it + //once the boss is found it will never check it + private void checkInterAction() + { + Player localPlayer = client.getLocalPlayer(); + Actor interacting = localPlayer.getInteracting(); + if (client.getGameState() == GameState.LOGGED_IN) + { + if (BossName == null) + { + if (interacting instanceof NPC) + { + int interactingId = ((NPC) interacting).getId(); + String interactingName = interacting.getName(); + for (int aNPCARRAY : NPCARRAY) + { + if (aNPCARRAY == interactingId) + { + BossName = interactingName; + } + } + } + } + } + } + + @Subscribe + //if you hop it will reset the counter + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState() == GameState.LOGGED_IN) + { + if (currentWorld == -1) + { + currentWorld = client.getWorld(); + } + else if (currentWorld != client.getWorld()) + { + currentWorld = client.getWorld(); + ResetCounter(); + } + } + } + + //grabbing the xp and calculating the damage + private int XPtoDamage() + { + int NewXp; + double damageOutput = 0; + int XPdrop; + if (currenthpxp != -1) + { + XPdrop = client.getSkillExperience(Skill.HITPOINTS); + NewXp = XPdrop - currenthpxp; + currenthpxp = -1; + damageOutput = NewXp / XP_RATIO; + } + //returns the damage you have done + return (int) Math.floor(damageOutput); + } + + //adding up the damage for the print message checks every tick(aka attack tick) + private void DamageCounting() + { + Player localPlayer = client.getLocalPlayer(); + Actor interacting = localPlayer.getInteracting(); + if (client.getGameState() == GameState.LOGGED_IN) + { + if (interacting instanceof NPC) + { + String interactingName = interacting.getName(); + int NPC = ((NPC) interacting).getId(); + if (interactingName.equals(BossName)) + { + DamageCount += (XPtoDamage() * BOSS_MODIFIER); + + } + } + } + } + + + @Subscribe + //will add the damage that you have taken from the current boss fight + private void onHitsplatApplied(HitsplatApplied Hit) + { + if (Hit.getActor().equals(client.getLocalPlayer())) + { + DamageTaken += Hit.getHitsplat().getAmount(); + } + + } + + //will check for the monster if it died works only on ToB Bosses + /*Verzik has three phases so the program will add up all the damage and prints it into one message + because every time she phases she "dies" so making sure the counter doesn't print out the damage for phase 1, 2, + and 3. + */ + @Subscribe + public void onNpcDespawned(NpcDespawned npc) + { + NPC actor = npc.getNpc(); + double Percent = calculatePercent(WorldPoint.fromLocalInstance(client, + client.getLocalPlayer().getLocalLocation()).getRegionID()); + if (actor.isDead() && actor.getId() == NpcID.VERZIK_VITUR_8375 && status) + { + DamagePrint(actor, Percent); + ResetCounter(); + } + else if (actor.isDead() && actor.getName().equals(BossName) && actor.getId() != NpcID.VERZIK_VITUR_8374 && + actor.getId() != NpcID.VERZIK_VITUR_8372 && actor.getId() != NpcID.VERZIK_VITUR_8370 && + status) + { + DamagePrint(actor, Percent); + ResetCounter(); + } + //will reset the counter after the boss dies and if you died during the fight + else if (actor.isDead() && actor.getName().equals(BossName) && !status) + { + ResetCounter(); + } + } + + private double calculatePercent(int id) + { + double percent = 0; + if (DamageCount != 0) + { + if (id == MAIDEN_REGION || id == MAIDEN_REGION_1) + { + percent = (DamageCount / (double) MAIDENHP) * 100; + } + else if (id == BLOAT_REGION) + { + percent = (DamageCount / (double) BLOATHP) * 100; + } + else if (id == NYLOCAS_REGION) + { + percent = (DamageCount / (double) NYLOHP) * 100; + } + else if (id == SOTETSEG_REGION || id == SOTETSEG_REGION2) + { + percent = (DamageCount / (double) SOTHP) * 100; + } + else if (id == XARPUS_REGION) + { + percent = (DamageCount / (double) XARPUSHP) * 100; + } + else if (id == VERZIK_REGION) + { + percent = (DamageCount / (double) VERZIKHP) * 100; + } + } + return percent; + } + + //just reset the counter for the next fight and status + private void ResetCounter() + { + DamageCount = 0; + DamageTaken = 0; + BossName = null; + status = ALIVE; + } + + //print out the damage after the boss have died + //prevent people from spectating to get the damage message, it is impossible for them to get damage + private void DamagePrint(NPC actor, double percent) + { + String MessageDamage; + if (percent >= 50) + { + MessageDamage = "Well done carrying the team!" + + "WOWIE!! You did" + DAMAGEFORMAT.format(DamageCount) + " damage to " + + actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; + } + else if (percent >= 25) + { + MessageDamage = "Well done carrying some dead weight in your team! " + + "Awesome! You did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + + actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; + } + else if (percent >= 1) + { + MessageDamage = "Well done everyone is pulling their weight! " + + "You did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + + actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; + } + else + { + MessageDamage = "Didn't do much" + + "Fucking leech did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + + actor.getName() + "! You did %" + String.format("%.2f", percent) + " of the damage"; + } + + sendChatMessage(MessageDamage); + String MessageTaken = "You have taken " + DAMAGEFORMAT.format(DamageTaken) + " damage from this fight!"; + sendChatMessage(MessageTaken); + } + + @Subscribe + //whenever you have died in tob you will get a death message with damage + // made sure the message works at ToB area or else it will message every where + private void onLocalPlayerDeath(LocalPlayerDeath death) + { + String DeathMessage = "You have died! You did " + DAMAGEFORMAT.format(DamageCount) + " damage to " + + BossName + "!"; + String MessageTaken = "You have taken " + DAMAGEFORMAT.format(DamageTaken) + " damage from this fight!"; + for (int i = 0; i < ToB_Region.length; i++) + { + if (WorldPoint.fromLocalInstance(client, + client.getLocalPlayer().getLocalLocation()).getRegionID() == ToB_Region[i]) + { + sendChatMessage(DeathMessage); + sendChatMessage(MessageTaken); + ResetCounter(); + //status will become "dead" after you died in the fight + status = DEAD; + } + } + } + + //sends a message saying this "You have done XYZ damage to boss name! or the death message + // "Well done! you have done your best, you have done XYZ damage to boss name + private void sendChatMessage(String chatMessage) + { + final String message = new ChatMessageBuilder() + .append(ChatColorType.HIGHLIGHT) + .append(chatMessage) + .build(); + chatMessangerManager.queue( + QueuedMessage.builder() + .type(ChatMessageType.CONSOLE) + .runeLiteFormattedMessage(message) + .build()); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/twitch/irc/Message.java b/runelite-client/src/main/java/net/runelite/client/plugins/twitch/irc/Message.java index 604b7a2b46..9b4587cd37 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/twitch/irc/Message.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/twitch/irc/Message.java @@ -1,108 +1,111 @@ -/* - * Copyright (c) 2018, Adam - * 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.twitch.irc; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.Getter; - -@Getter -class Message -{ - private final Map tags = new HashMap<>(); - private String source; - private String command; - private String[] arguments; - - public static Message parse(String in) - { - Message message = new Message(); - if (in.startsWith("@")) - { - String[] tags = in.substring(1) - .split(";"); - for (String tag : tags) - { - int eq = tag.indexOf('='); - if (eq == -1) continue; - - String key = tag.substring(0, eq); - String value = tag.substring(eq + 1) - .replace("\\:", ";") - .replace("\\s", " ") - .replace("\\\\", "\\") - .replace("\\r", "\r") - .replace("\\n", "\n"); - - message.tags.put(key, value); - } - - int sp = in.indexOf(' '); - in = in.substring(sp + 1); - } - - if (in.startsWith(":")) - { - int sp = in.indexOf(' '); - message.source = in.substring(1, sp); - - in = in.substring(sp + 1); - } - - int sp = in.indexOf(' '); - if (sp == -1) - { - message.command = in; - message.arguments = new String[0]; - return message; - } - - message.command = in.substring(0, sp); - - String args = in.substring(sp + 1); - List argList = new ArrayList<>(); - do - { - String arg; - if (args.startsWith(":")) - { - arg = args.substring(1); - sp = -1; - } - else - { - sp = args.indexOf(' '); - arg = sp == -1 ? args : args.substring(0, sp); - } - args = args.substring(sp + 1); - argList.add(arg); - } while (sp != -1); - - message.arguments = argList.toArray(new String[0]); - return message; - } -} +/* + * Copyright (c) 2018, Adam + * 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.twitch.irc; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.Getter; + +@Getter +class Message +{ + private final Map tags = new HashMap<>(); + private String source; + private String command; + private String[] arguments; + + public static Message parse(String in) + { + Message message = new Message(); + if (in.startsWith("@")) + { + String[] tags = in.substring(1) + .split(";"); + for (String tag : tags) + { + int eq = tag.indexOf('='); + if (eq == -1) + { + continue; + } + + String key = tag.substring(0, eq); + String value = tag.substring(eq + 1) + .replace("\\:", ";") + .replace("\\s", " ") + .replace("\\\\", "\\") + .replace("\\r", "\r") + .replace("\\n", "\n"); + + message.tags.put(key, value); + } + + int sp = in.indexOf(' '); + in = in.substring(sp + 1); + } + + if (in.startsWith(":")) + { + int sp = in.indexOf(' '); + message.source = in.substring(1, sp); + + in = in.substring(sp + 1); + } + + int sp = in.indexOf(' '); + if (sp == -1) + { + message.command = in; + message.arguments = new String[0]; + return message; + } + + message.command = in.substring(0, sp); + + String args = in.substring(sp + 1); + List argList = new ArrayList<>(); + do + { + String arg; + if (args.startsWith(":")) + { + arg = args.substring(1); + sp = -1; + } + else + { + sp = args.indexOf(' '); + arg = sp == -1 ? args : args.substring(0, sp); + } + args = args.substring(sp + 1); + argList.add(arg); + } while (sp != -1); + + message.arguments = argList.toArray(new String[0]); + return message; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardOverlay.java index 88b8207336..e81b96b6df 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardOverlay.java @@ -1,142 +1,140 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.vanguards; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; - -import net.runelite.api.Actor; -import net.runelite.api.NPC; -import net.runelite.api.Player; -import net.runelite.api.Client; -import net.runelite.client.game.NPCManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -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.plugins.opponentinfo.OpponentInfoPlugin; -//import net.runelite.client.plugins.opponentinfo.OpponentInfoOverlay; - -import javax.inject.Inject; - -public class VanguardOverlay extends Overlay { - - private VanguardPlugin plugin; - private final PanelComponent panelComponent = new PanelComponent(); - - private static final int MAGE_VANGUARD_ID = 7529; - private static final int RANGE_VANGUARD_ID = 7528; - private static final int MELEE_VANGUARD_ID = 7527; - //private final NPCManager npcManager; - - private int mageHp = -1; - private float magePercent = 0; - - private int rangeHp = -1; - private float rangePercent = 0; - - private int meleeHp = -1; - private float meleePercent = 0; - - public String right_mage_str, right_range_str, right_melee_str = ""; - - @Inject - private Client client; - - - @Inject - public VanguardOverlay(VanguardPlugin plugin) { - super(plugin);//? - this.plugin = plugin; - - setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT); - //this.opponentInfoPlugin = opponentInfoPlugin; - } - - @Override - public Dimension render(Graphics2D graphics) - { - Player p = client.getLocalPlayer(); //local player aka me - Actor opponent = p.getInteracting(); //get entity i am interacting with - //how to find its Id since it's an Actor not NPC specifically - //if(opponent.getName().equals("Vanguard") && opponent.getHealth() > 0)//might wana double check the name - //{ - if(opponent instanceof NPC) - { - int id = ((NPC) opponent).getId(); - String name = opponent.getName(); - - if(id == MAGE_VANGUARD_ID) //maybe check name.equals("Vanguard") - { - magePercent = (float)opponent.getHealthRatio() / opponent.getHealth() * 100; - mageHp = (int)magePercent; - right_mage_str = Integer.toString(mageHp); - System.out.println("mager"); - } - else if (id == RANGE_VANGUARD_ID) - { - rangePercent = (float)opponent.getHealthRatio() / opponent.getHealth() * 100; - rangeHp = (int)rangePercent; - right_range_str = Integer.toString(rangeHp); - - System.out.println("ranger"); - } - else if (id == MELEE_VANGUARD_ID) - { - meleePercent = (float)opponent.getHealthRatio()/opponent.getHealth() * 100; - meleeHp = (int)meleePercent; - right_melee_str = Integer.toString(meleeHp); - - - System.out.println("meleer"); - } - } - //} - - - //if (opponent == null) { - //} - - - panelComponent.getChildren().clear(); - String overlayTitle = "Vanguard HP"; - //title - panelComponent.getChildren().add(TitleComponent.builder().text(overlayTitle).color(Color.RED).build()); - - //size (width) - panelComponent.setPreferredSize(new Dimension(graphics.getFontMetrics().stringWidth(overlayTitle) + 30, 0)); - - panelComponent.getChildren().add(LineComponent.builder().left("Mage:").right(right_mage_str).build()); - - panelComponent.getChildren().add(LineComponent.builder().left("Range:").right(right_range_str).build()); - - panelComponent.getChildren().add(LineComponent.builder().left("Melee:").right(right_melee_str).build()); - - return panelComponent.render(graphics); - } +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.vanguards; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +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.plugins.opponentinfo.OpponentInfoOverlay; + +public class VanguardOverlay extends Overlay +{ + + private VanguardPlugin plugin; + private final PanelComponent panelComponent = new PanelComponent(); + + private static final int MAGE_VANGUARD_ID = 7529; + private static final int RANGE_VANGUARD_ID = 7528; + private static final int MELEE_VANGUARD_ID = 7527; + //private final NPCManager npcManager; + + private int mageHp = -1; + private float magePercent = 0; + + private int rangeHp = -1; + private float rangePercent = 0; + + private int meleeHp = -1; + private float meleePercent = 0; + + public String right_mage_str, right_range_str, right_melee_str = ""; + + @Inject + private Client client; + + + @Inject + public VanguardOverlay(VanguardPlugin plugin) + { + super(plugin);//? + this.plugin = plugin; + + setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT); + //this.opponentInfoPlugin = opponentInfoPlugin; + } + + @Override + public Dimension render(Graphics2D graphics) + { + Player p = client.getLocalPlayer(); //local player aka me + Actor opponent = p.getInteracting(); //get entity i am interacting with + //how to find its Id since it's an Actor not NPC specifically + //if(opponent.getName().equals("Vanguard") && opponent.getHealth() > 0)//might wana double check the name + //{ + if (opponent instanceof NPC) + { + int id = ((NPC) opponent).getId(); + String name = opponent.getName(); + + if (id == MAGE_VANGUARD_ID) //maybe check name.equals("Vanguard") + { + magePercent = (float) opponent.getHealthRatio() / opponent.getHealth() * 100; + mageHp = (int) magePercent; + right_mage_str = Integer.toString(mageHp); + System.out.println("mager"); + } + else if (id == RANGE_VANGUARD_ID) + { + rangePercent = (float) opponent.getHealthRatio() / opponent.getHealth() * 100; + rangeHp = (int) rangePercent; + right_range_str = Integer.toString(rangeHp); + + System.out.println("ranger"); + } + else if (id == MELEE_VANGUARD_ID) + { + meleePercent = (float) opponent.getHealthRatio() / opponent.getHealth() * 100; + meleeHp = (int) meleePercent; + right_melee_str = Integer.toString(meleeHp); + + + System.out.println("meleer"); + } + } + //} + + + //if (opponent == null) { + //} + + + panelComponent.getChildren().clear(); + String overlayTitle = "Vanguard HP"; + //title + panelComponent.getChildren().add(TitleComponent.builder().text(overlayTitle).color(Color.RED).build()); + + //size (width) + panelComponent.setPreferredSize(new Dimension(graphics.getFontMetrics().stringWidth(overlayTitle) + 30, 0)); + + panelComponent.getChildren().add(LineComponent.builder().left("Mage:").right(right_mage_str).build()); + + panelComponent.getChildren().add(LineComponent.builder().left("Range:").right(right_range_str).build()); + + panelComponent.getChildren().add(LineComponent.builder().left("Melee:").right(right_melee_str).build()); + + return panelComponent.render(graphics); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardPlugin.java index 44c4818ba6..59f0f36b85 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/vanguards/VanguardPlugin.java @@ -1,69 +1,70 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.vanguards; - -import javax.inject.Inject; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name= "Vanguard HP Overlay", - description= "tracks HP of all three vanguards", - tags= {"overlay", "vangs", "cox"}, - enabledByDefault = false, - type = PluginType.PVM -) -public class VanguardPlugin extends Plugin { - private static final int MAGE_VANGUARD_ID = 7526; //i think - private static final int RANGE_VANGUARD_ID = 7527; - private static final int MELEE_VANGUARD_ID = 7528; - - - @Inject - private OverlayManager overlayManager; - - @Inject - private VanguardOverlay overlay; - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - overlay.right_mage_str = "-"; - overlay.right_range_str = "-"; - overlay.right_melee_str = "-"; - } - - -} - +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.vanguards; + +import javax.inject.Inject; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "Vanguard HP Overlay", + description = "tracks HP of all three vanguards", + tags = {"overlay", "vangs", "cox"}, + enabledByDefault = false, + type = PluginType.PVM +) +public class VanguardPlugin extends Plugin +{ + private static final int MAGE_VANGUARD_ID = 7526; //i think + private static final int RANGE_VANGUARD_ID = 7527; + private static final int MELEE_VANGUARD_ID = 7528; + + + @Inject + private OverlayManager overlayManager; + + @Inject + private VanguardOverlay overlay; + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + overlay.right_mage_str = "-"; + overlay.right_range_str = "-"; + overlay.right_melee_str = "-"; + } + + +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/vetion/VetionPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/vetion/VetionPlugin.java index 6e03740426..a17bef71c6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/vetion/VetionPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/vetion/VetionPlugin.java @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.vetion; -import com.google.inject.Provides; import java.time.Instant; import java.util.HashMap; import java.util.Map; @@ -32,9 +31,7 @@ import javax.inject.Inject; import lombok.Getter; import net.runelite.api.Actor; import net.runelite.api.AnimationID; -import net.runelite.api.Client; import net.runelite.api.events.AnimationChanged; -import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java index 736599eea1..f627e45dc4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java @@ -28,7 +28,18 @@ import com.google.inject.Provides; import java.awt.Color; import javax.inject.Inject; import net.runelite.api.Client; -import static net.runelite.api.MenuAction.*; +import static net.runelite.api.MenuAction.FOLLOW; +import static net.runelite.api.MenuAction.ITEM_USE_ON_PLAYER; +import static net.runelite.api.MenuAction.PLAYER_EIGTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FIFTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FIRST_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FOURTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SECOND_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SEVENTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SIXTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_THIRD_OPTION; +import static net.runelite.api.MenuAction.SPELL_CAST_ON_PLAYER; +import static net.runelite.api.MenuAction.TRADE; import net.runelite.api.MenuEntry; import net.runelite.api.Player; import net.runelite.api.events.MenuEntryAdded; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java index f975021369..a60a389674 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java @@ -1,210 +1,206 @@ -/*' - * Copyright (c) 2018, Adam - * Copyright (c) 2018, Abexlry - * 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.wasdcamera; - -import com.google.inject.Provides; -import java.awt.Color; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.IconID; -import net.runelite.api.VarClientInt; -import net.runelite.api.VarClientStr; -import net.runelite.api.Varbits; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.util.ColorUtil; - -@PluginDescriptor( - name = "WASD Camera", - description = "Allows use of WASD keys for camera movement with 'Press Enter to Chat'", - tags = {"enter", "chat"}, - enabledByDefault = false -) -public class WASDCameraPlugin extends Plugin -{ - private static final String PRESS_ENTER_TO_CHAT = "Press Enter to Chat..."; - private static final String SCRIPT_EVENT_SET_CHATBOX_INPUT = "setChatboxInput"; - private static final String SCRIPT_EVENT_BLOCK_CHAT_INPUT = "blockChatInput"; - - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private KeyManager keyManager; - - @Inject - private WASDCameraListener inputListener; - - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private boolean typing; - - @Override - protected void startUp() throws Exception - { - typing = false; - keyManager.registerKeyListener(inputListener); - - clientThread.invoke(() -> - { - if (client.getGameState() == GameState.LOGGED_IN) - { - lockChat(); - } - }); - } - - @Override - protected void shutDown() throws Exception - { - clientThread.invoke(() -> - { - if (client.getGameState() == GameState.LOGGED_IN) - { - unlockChat(); - } - }); - - keyManager.unregisterKeyListener(inputListener); - } - - @Provides - WASDCameraConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(WASDCameraConfig.class); - } - - boolean chatboxFocused() - { - Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); - if (chatboxParent == null || chatboxParent.getOnKeyListener() == null) - { - return false; - } - - // the search box on the world map can be focused, and chat input goes there, even - // though the chatbox still has its key listener. - Widget worldMapSearch = client.getWidget(WidgetInfo.WORLD_MAP_SEARCH); - if (worldMapSearch != null && client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) == 1) - { - return false; - } - - return true; - } - - @Subscribe - public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent) - { - switch (scriptCallbackEvent.getEventName()) - { - case SCRIPT_EVENT_SET_CHATBOX_INPUT: - Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); - if (chatboxInput != null) - { - if (chatboxFocused() && !typing) - { - chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT); - } - } - break; - case SCRIPT_EVENT_BLOCK_CHAT_INPUT: - if (!typing) - { - int[] intStack = client.getIntStack(); - int intStackSize = client.getIntStackSize(); - intStack[intStackSize - 1] = 1; - } - break; - } - } - - void lockChat() - { - Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); - if (chatboxParent != null && chatboxParent.getOnKeyListener() != null) - { - Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); - if (chatboxInput != null) - { - chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT); - } - } - } - - void unlockChat() - { - Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); - if (chatboxParent != null) - { - Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); - if (chatboxInput != null) - { - if (client.getGameState() == GameState.LOGGED_IN) - { - final boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1; - final Color textColor = isChatboxTransparent ? JagexColors.CHAT_TYPED_TEXT_TRANSPARENT_BACKGROUND : JagexColors.CHAT_TYPED_TEXT_OPAQUE_BACKGROUND; - chatboxInput.setText(getPlayerNameWithIcon() + ": " + ColorUtil.wrapWithColorTag(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT) + "*", textColor)); - } - } - } - } - - private String getPlayerNameWithIcon() - { - IconID icon; - switch (client.getAccountType()) - { - case IRONMAN: - icon = IconID.IRONMAN; - break; - case ULTIMATE_IRONMAN: - icon = IconID.ULTIMATE_IRONMAN; - break; - case HARDCORE_IRONMAN: - icon = IconID.HARDCORE_IRONMAN; - break; - default: - return client.getLocalPlayer().getName(); - } - return icon + client.getLocalPlayer().getName(); - } -} +/*' + * Copyright (c) 2018, Adam + * Copyright (c) 2018, Abexlry + * 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.wasdcamera; + +import com.google.inject.Provides; +import java.awt.Color; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.IconID; +import net.runelite.api.VarClientInt; +import net.runelite.api.VarClientStr; +import net.runelite.api.Varbits; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.util.ColorUtil; + +@PluginDescriptor( + name = "WASD Camera", + description = "Allows use of WASD keys for camera movement with 'Press Enter to Chat'", + tags = {"enter", "chat"}, + enabledByDefault = false +) +public class WASDCameraPlugin extends Plugin +{ + private static final String PRESS_ENTER_TO_CHAT = "Press Enter to Chat..."; + private static final String SCRIPT_EVENT_SET_CHATBOX_INPUT = "setChatboxInput"; + private static final String SCRIPT_EVENT_BLOCK_CHAT_INPUT = "blockChatInput"; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private KeyManager keyManager; + + @Inject + private WASDCameraListener inputListener; + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean typing; + + @Override + protected void startUp() throws Exception + { + typing = false; + keyManager.registerKeyListener(inputListener); + + clientThread.invoke(() -> + { + if (client.getGameState() == GameState.LOGGED_IN) + { + lockChat(); + } + }); + } + + @Override + protected void shutDown() throws Exception + { + clientThread.invoke(() -> + { + if (client.getGameState() == GameState.LOGGED_IN) + { + unlockChat(); + } + }); + + keyManager.unregisterKeyListener(inputListener); + } + + @Provides + WASDCameraConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(WASDCameraConfig.class); + } + + boolean chatboxFocused() + { + Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); + if (chatboxParent == null || chatboxParent.getOnKeyListener() == null) + { + return false; + } + + // the search box on the world map can be focused, and chat input goes there, even + // though the chatbox still has its key listener. + Widget worldMapSearch = client.getWidget(WidgetInfo.WORLD_MAP_SEARCH); + return worldMapSearch == null || client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) != 1; + + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent) + { + switch (scriptCallbackEvent.getEventName()) + { + case SCRIPT_EVENT_SET_CHATBOX_INPUT: + Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); + if (chatboxInput != null) + { + if (chatboxFocused() && !typing) + { + chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT); + } + } + break; + case SCRIPT_EVENT_BLOCK_CHAT_INPUT: + if (!typing) + { + int[] intStack = client.getIntStack(); + int intStackSize = client.getIntStackSize(); + intStack[intStackSize - 1] = 1; + } + break; + } + } + + void lockChat() + { + Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); + if (chatboxParent != null && chatboxParent.getOnKeyListener() != null) + { + Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); + if (chatboxInput != null) + { + chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT); + } + } + } + + void unlockChat() + { + Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); + if (chatboxParent != null) + { + Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); + if (chatboxInput != null) + { + if (client.getGameState() == GameState.LOGGED_IN) + { + final boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1; + final Color textColor = isChatboxTransparent ? JagexColors.CHAT_TYPED_TEXT_TRANSPARENT_BACKGROUND : JagexColors.CHAT_TYPED_TEXT_OPAQUE_BACKGROUND; + chatboxInput.setText(getPlayerNameWithIcon() + ": " + ColorUtil.wrapWithColorTag(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT) + "*", textColor)); + } + } + } + } + + private String getPlayerNameWithIcon() + { + IconID icon; + switch (client.getAccountType()) + { + case IRONMAN: + icon = IconID.IRONMAN; + break; + case ULTIMATE_IRONMAN: + icon = IconID.ULTIMATE_IRONMAN; + break; + case HARDCORE_IRONMAN: + icon = IconID.HARDCORE_IRONMAN; + break; + default: + return client.getLocalPlayer().getName(); + } + return icon + client.getLocalPlayer().getName(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersConfig.java index 57542c9771..4645107069 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersConfig.java @@ -1,7 +1,5 @@ package net.runelite.client.plugins.whalewatchers; -import java.awt.Color; -import net.runelite.client.config.Alpha; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersGloryOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersGloryOverlay.java index 035433e280..b15b87c431 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersGloryOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersGloryOverlay.java @@ -15,7 +15,6 @@ import java.awt.Graphics2D; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.ItemID; -import net.runelite.api.kit.KitType; import net.runelite.client.game.AsyncBufferedImage; import net.runelite.client.game.ItemManager; import net.runelite.client.ui.overlay.Overlay; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersOverlay.java index af2be6cb8a..1354054295 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersOverlay.java @@ -85,7 +85,7 @@ public class WhaleWatchersOverlay extends Overlay else { panelComponent.getChildren().clear(); - + } return panelComponent.render(graphics); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java index 84bd388644..0ed7fe4e0b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java @@ -149,14 +149,7 @@ public class WhaleWatchersPlugin extends Plugin { final int amuletID = ObjectUtils.defaultIfNull(client.getLocalPlayer() .getPlayerComposition().getEquipmentId(KitType.AMULET), 0); - if (amuletID == ItemID.AMULET_OF_GLORY) - { - displayGloryOverlay = true; - } - else - { - displayGloryOverlay = false; - } + displayGloryOverlay = amuletID == ItemID.AMULET_OF_GLORY; } else { @@ -254,6 +247,7 @@ public class WhaleWatchersPlugin extends Plugin /** * Checks to see if client is attacking another player + * * @return returns true if they are, false otherwise */ private boolean isAttackingPlayer() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersProtOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersProtOverlay.java index 2b025b1063..ecfc3c3b37 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersProtOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersProtOverlay.java @@ -1,4 +1,3 @@ - /******************************************************************************* * Copyright (c) 2019. PKLite * Redistributions and modifications of this software are permitted as long as this notice remains in its original unmodified state at the top of this file. diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersSmiteableOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersSmiteableOverlay.java index 55b0ef23c7..4be28dce80 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersSmiteableOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersSmiteableOverlay.java @@ -1,4 +1,3 @@ - /******************************************************************************* * Copyright (c) 2019. PKLite * Redistributions and modifications of this software are permitted as long as this notice remains in its original unmodified state at the top of this file. @@ -59,7 +58,7 @@ public class WhaleWatchersSmiteableOverlay extends Overlay .build()); panelComponent.setPreferredSize(new Dimension(graphics.getFontMetrics().stringWidth(subText) - + 20 , 0)); + + 20, 0)); } else { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java index ef3b91f9a0..37814ade62 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java @@ -1,306 +1,306 @@ -/* - * Copyright (c) 2018 Abex - * 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.wiki; - -import com.google.common.collect.ImmutableList; -import com.google.common.reflect.TypeToken; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import com.google.inject.Inject; -import java.awt.event.KeyEvent; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import javax.inject.Named; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetPositionMode; -import net.runelite.api.widgets.WidgetSizeMode; -import net.runelite.api.widgets.WidgetTextAlignment; -import net.runelite.api.widgets.WidgetType; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.game.chatbox.ChatboxPanelManager; -import net.runelite.client.game.chatbox.ChatboxTextInput; -import net.runelite.client.util.LinkBrowser; -import net.runelite.http.api.RuneLiteAPI; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.HttpUrl; -import okhttp3.Request; -import okhttp3.Response; - -@Slf4j -public class WikiSearchChatboxTextInput extends ChatboxTextInput -{ - private static final int LINE_HEIGHT = 20; - private static final int CHATBOX_HEIGHT = 120; - private static final int MAX_NUM_PREDICTIONS = (CHATBOX_HEIGHT / LINE_HEIGHT) - 2; // 1 title, 1 edit - - private static final int PREDICTION_DEBOUNCE_DELAY_MS = 200; - - private final ChatboxPanelManager chatboxPanelManager; - private final Gson gson = new Gson(); - - private Future runningRequest = null; - private List predictions = ImmutableList.of(); - - private int selectedPrediction = -1; - private String offPrediction = null; - - @Inject - public WikiSearchChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread, - ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode) - { - super(chatboxPanelManager, clientThread); - this.chatboxPanelManager = chatboxPanelManager; - - lines(1); - prompt("OSRS Wiki Search"); - onDone(string -> - { - if (string != null && string.length() > 0) - { - search(string); - } - }); - onChanged(searchString -> - { - selectedPrediction = -1; - Future rr = runningRequest; - if (rr != null) - { - rr.cancel(false); - } - if (searchString.length() <= 1) - { - runningRequest = null; - clientThread.invokeLater(() -> - { - predictions = ImmutableList.of(); - update(); - }); - return; - } - runningRequest = scheduledExecutorService.schedule(() -> - { - HttpUrl url = WikiPlugin.WIKI_API.newBuilder() - .addQueryParameter("action", "opensearch") - .addQueryParameter("search", searchString) - .addQueryParameter("redirects", "resolve") - .addQueryParameter("format", "json") - .addQueryParameter("warningsaserror", Boolean.toString(developerMode)) - .build(); - - Request req = new Request.Builder() - .url(url) - .build(); - - RuneLiteAPI.CLIENT.newCall(req).enqueue(new Callback() - { - @Override - public void onFailure(Call call, IOException e) - { - log.warn("error searching wiki", e); - } - - @Override - public void onResponse(Call call, Response response) throws IOException - { - String body = response.body().string(); - try - { - JsonArray jar = new JsonParser().parse(body).getAsJsonArray(); - List apredictions = gson.fromJson(jar.get(1), new TypeToken>() - { - }.getType()); - - if (apredictions.size() > MAX_NUM_PREDICTIONS) - { - apredictions = apredictions.subList(0, MAX_NUM_PREDICTIONS); - } - - final List bpredictions = apredictions; - - clientThread.invokeLater(() -> - { - predictions = bpredictions; - update(); - }); - } - catch (JsonParseException | IllegalStateException | IndexOutOfBoundsException e) - { - log.warn("error parsing wiki response {}", body, e); - } - finally - { - response.close(); - } - } - }); - - runningRequest = null; - }, PREDICTION_DEBOUNCE_DELAY_MS, TimeUnit.MILLISECONDS); - }); - } - - @Override - protected void update() - { - Widget container = chatboxPanelManager.getContainerWidget(); - container.deleteAllChildren(); - - Widget promptWidget = container.createChild(-1, WidgetType.TEXT); - promptWidget.setText(getPrompt()); - promptWidget.setTextColor(0x800000); - promptWidget.setFontId(getFontID()); - promptWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - promptWidget.setOriginalX(0); - promptWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - promptWidget.setOriginalY(5); - promptWidget.setOriginalHeight(LINE_HEIGHT); - promptWidget.setXTextAlignment(WidgetTextAlignment.CENTER); - promptWidget.setYTextAlignment(WidgetTextAlignment.CENTER); - promptWidget.setWidthMode(WidgetSizeMode.MINUS); - promptWidget.revalidate(); - - buildEdit(0, 5 + LINE_HEIGHT, container.getWidth(), LINE_HEIGHT); - - Widget separator = container.createChild(-1, WidgetType.LINE); - separator.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - separator.setOriginalX(0); - separator.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - separator.setOriginalY(4 + (LINE_HEIGHT * 2)); - separator.setOriginalHeight(0); - separator.setOriginalWidth(16); - separator.setWidthMode(WidgetSizeMode.MINUS); - separator.revalidate(); - - for (int i = 0; i < predictions.size(); i++) - { - String pred = predictions.get(i); - int y = 6 + (LINE_HEIGHT * (2 + i)); - - Widget bg = container.createChild(-1, WidgetType.RECTANGLE); - bg.setTextColor(0x4444DD); - bg.setFilled(true); - bg.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - bg.setOriginalX(1); - bg.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - bg.setOriginalY(y); - bg.setOriginalHeight(LINE_HEIGHT); - bg.setOriginalWidth(16); - bg.setWidthMode(WidgetSizeMode.MINUS); - bg.revalidate(); - bg.setName("" + pred); - bg.setAction(0, "Open"); - bg.setHasListener(true); - bg.setOnOpListener((JavaScriptCallback) ev -> search(pred)); - - Widget text = container.createChild(-1, WidgetType.TEXT); - text.setText(pred); - text.setFontId(getFontID()); - text.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - text.setOriginalX(0); - text.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - text.setOriginalY(y); - text.setOriginalHeight(LINE_HEIGHT); - text.setXTextAlignment(WidgetTextAlignment.CENTER); - text.setYTextAlignment(WidgetTextAlignment.CENTER); - text.setWidthMode(WidgetSizeMode.MINUS); - text.revalidate(); - - if (i == selectedPrediction) - { - text.setTextColor(0xFFFFFF); - } - else - { - bg.setOpacity(255); - text.setTextColor(0x000000); - bg.setOnMouseRepeatListener((JavaScriptCallback) ev -> text.setTextColor(0xFFFFFF)); - bg.setOnMouseLeaveListener((JavaScriptCallback) ev -> text.setTextColor(0x000000)); - } - } - } - - @Override - public void keyPressed(KeyEvent ev) - { - switch (ev.getKeyCode()) - { - case KeyEvent.VK_UP: - ev.consume(); - if (selectedPrediction > -1) - { - selectedPrediction--; - if (selectedPrediction == -1) - { - value(offPrediction); - } - else - { - value(predictions.get(selectedPrediction)); - } - } - break; - case KeyEvent.VK_DOWN: - ev.consume(); - - if (selectedPrediction == -1) - { - offPrediction = getValue(); - } - - selectedPrediction++; - if (selectedPrediction >= predictions.size()) - { - selectedPrediction = predictions.size() - 1; - } - - if (selectedPrediction != -1) - { - value(predictions.get(selectedPrediction)); - } - break; - default: - super.keyPressed(ev); - } - } - - private void search(String search) - { - LinkBrowser.browse(WikiPlugin.WIKI_BASE.newBuilder() - .addQueryParameter("search", search) - .addQueryParameter(WikiPlugin.UTM_SORUCE_KEY, WikiPlugin.UTM_SORUCE_VALUE) - .build() - .toString()); - chatboxPanelManager.close(); - } -} +/* + * Copyright (c) 2018 Abex + * 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.wiki; + +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.inject.Inject; +import java.awt.event.KeyEvent; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.inject.Named; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.game.chatbox.ChatboxPanelManager; +import net.runelite.client.game.chatbox.ChatboxTextInput; +import net.runelite.client.util.LinkBrowser; +import net.runelite.http.api.RuneLiteAPI; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; + +@Slf4j +public class WikiSearchChatboxTextInput extends ChatboxTextInput +{ + private static final int LINE_HEIGHT = 20; + private static final int CHATBOX_HEIGHT = 120; + private static final int MAX_NUM_PREDICTIONS = (CHATBOX_HEIGHT / LINE_HEIGHT) - 2; // 1 title, 1 edit + + private static final int PREDICTION_DEBOUNCE_DELAY_MS = 200; + + private final ChatboxPanelManager chatboxPanelManager; + private final Gson gson = new Gson(); + + private Future runningRequest = null; + private List predictions = ImmutableList.of(); + + private int selectedPrediction = -1; + private String offPrediction = null; + + @Inject + public WikiSearchChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread, + ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode) + { + super(chatboxPanelManager, clientThread); + this.chatboxPanelManager = chatboxPanelManager; + + lines(1); + prompt("OSRS Wiki Search"); + onDone(string -> + { + if (string != null && string.length() > 0) + { + search(string); + } + }); + onChanged(searchString -> + { + selectedPrediction = -1; + Future rr = runningRequest; + if (rr != null) + { + rr.cancel(false); + } + if (searchString.length() <= 1) + { + runningRequest = null; + clientThread.invokeLater(() -> + { + predictions = ImmutableList.of(); + update(); + }); + return; + } + runningRequest = scheduledExecutorService.schedule(() -> + { + HttpUrl url = WikiPlugin.WIKI_API.newBuilder() + .addQueryParameter("action", "opensearch") + .addQueryParameter("search", searchString) + .addQueryParameter("redirects", "resolve") + .addQueryParameter("format", "json") + .addQueryParameter("warningsaserror", Boolean.toString(developerMode)) + .build(); + + Request req = new Request.Builder() + .url(url) + .build(); + + RuneLiteAPI.CLIENT.newCall(req).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException e) + { + log.warn("error searching wiki", e); + } + + @Override + public void onResponse(Call call, Response response) throws IOException + { + String body = response.body().string(); + try + { + JsonArray jar = new JsonParser().parse(body).getAsJsonArray(); + List apredictions = gson.fromJson(jar.get(1), new TypeToken>() + { + }.getType()); + + if (apredictions.size() > MAX_NUM_PREDICTIONS) + { + apredictions = apredictions.subList(0, MAX_NUM_PREDICTIONS); + } + + final List bpredictions = apredictions; + + clientThread.invokeLater(() -> + { + predictions = bpredictions; + update(); + }); + } + catch (JsonParseException | IllegalStateException | IndexOutOfBoundsException e) + { + log.warn("error parsing wiki response {}", body, e); + } + finally + { + response.close(); + } + } + }); + + runningRequest = null; + }, PREDICTION_DEBOUNCE_DELAY_MS, TimeUnit.MILLISECONDS); + }); + } + + @Override + protected void update() + { + Widget container = chatboxPanelManager.getContainerWidget(); + container.deleteAllChildren(); + + Widget promptWidget = container.createChild(-1, WidgetType.TEXT); + promptWidget.setText(getPrompt()); + promptWidget.setTextColor(0x800000); + promptWidget.setFontId(getFontID()); + promptWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + promptWidget.setOriginalX(0); + promptWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + promptWidget.setOriginalY(5); + promptWidget.setOriginalHeight(LINE_HEIGHT); + promptWidget.setXTextAlignment(WidgetTextAlignment.CENTER); + promptWidget.setYTextAlignment(WidgetTextAlignment.CENTER); + promptWidget.setWidthMode(WidgetSizeMode.MINUS); + promptWidget.revalidate(); + + buildEdit(0, 5 + LINE_HEIGHT, container.getWidth(), LINE_HEIGHT); + + Widget separator = container.createChild(-1, WidgetType.LINE); + separator.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + separator.setOriginalX(0); + separator.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + separator.setOriginalY(4 + (LINE_HEIGHT * 2)); + separator.setOriginalHeight(0); + separator.setOriginalWidth(16); + separator.setWidthMode(WidgetSizeMode.MINUS); + separator.revalidate(); + + for (int i = 0; i < predictions.size(); i++) + { + String pred = predictions.get(i); + int y = 6 + (LINE_HEIGHT * (2 + i)); + + Widget bg = container.createChild(-1, WidgetType.RECTANGLE); + bg.setTextColor(0x4444DD); + bg.setFilled(true); + bg.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + bg.setOriginalX(1); + bg.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + bg.setOriginalY(y); + bg.setOriginalHeight(LINE_HEIGHT); + bg.setOriginalWidth(16); + bg.setWidthMode(WidgetSizeMode.MINUS); + bg.revalidate(); + bg.setName("" + pred); + bg.setAction(0, "Open"); + bg.setHasListener(true); + bg.setOnOpListener((JavaScriptCallback) ev -> search(pred)); + + Widget text = container.createChild(-1, WidgetType.TEXT); + text.setText(pred); + text.setFontId(getFontID()); + text.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + text.setOriginalX(0); + text.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + text.setOriginalY(y); + text.setOriginalHeight(LINE_HEIGHT); + text.setXTextAlignment(WidgetTextAlignment.CENTER); + text.setYTextAlignment(WidgetTextAlignment.CENTER); + text.setWidthMode(WidgetSizeMode.MINUS); + text.revalidate(); + + if (i == selectedPrediction) + { + text.setTextColor(0xFFFFFF); + } + else + { + bg.setOpacity(255); + text.setTextColor(0x000000); + bg.setOnMouseRepeatListener((JavaScriptCallback) ev -> text.setTextColor(0xFFFFFF)); + bg.setOnMouseLeaveListener((JavaScriptCallback) ev -> text.setTextColor(0x000000)); + } + } + } + + @Override + public void keyPressed(KeyEvent ev) + { + switch (ev.getKeyCode()) + { + case KeyEvent.VK_UP: + ev.consume(); + if (selectedPrediction > -1) + { + selectedPrediction--; + if (selectedPrediction == -1) + { + value(offPrediction); + } + else + { + value(predictions.get(selectedPrediction)); + } + } + break; + case KeyEvent.VK_DOWN: + ev.consume(); + + if (selectedPrediction == -1) + { + offPrediction = getValue(); + } + + selectedPrediction++; + if (selectedPrediction >= predictions.size()) + { + selectedPrediction = predictions.size() - 1; + } + + if (selectedPrediction != -1) + { + value(predictions.get(selectedPrediction)); + } + break; + default: + super.keyPressed(ev); + } + } + + private void search(String search) + { + LinkBrowser.browse(WikiPlugin.WIKI_BASE.newBuilder() + .addQueryParameter("search", search) + .addQueryParameter(WikiPlugin.UTM_SORUCE_KEY, WikiPlugin.UTM_SORUCE_VALUE) + .build() + .toString()); + chatboxPanelManager.close(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsConfig.java index 91545b3074..f7365e32e1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsConfig.java @@ -6,7 +6,7 @@ * Written by PKLite(ST0NEWALL, others) , 2019 * */ - + package net.runelite.client.plugins.wildernesslocations; import net.runelite.client.config.Config; @@ -17,7 +17,7 @@ import net.runelite.client.config.Keybind; @ConfigGroup("wildernesslocations") public interface WildernessLocationsConfig extends Config { - + @ConfigItem( keyName = "drawOverlay", name = "Draw Overlay", @@ -28,7 +28,7 @@ public interface WildernessLocationsConfig extends Config { return true; } - + @ConfigItem( keyName = "keybind", name = "Send to CC", @@ -39,5 +39,5 @@ public interface WildernessLocationsConfig extends Config { return Keybind.NOT_SET; } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsOverlay.java index 8bae506748..41ad66e7d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsOverlay.java @@ -6,13 +6,12 @@ * Written by PKLite(ST0NEWALL, others) , 2019 * */ - + package net.runelite.client.plugins.wildernesslocations; import java.awt.Dimension; import java.awt.Graphics2D; import javax.inject.Inject; -import net.runelite.api.Client; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @@ -23,7 +22,7 @@ public class WildernessLocationsOverlay extends Overlay { private final WildernessLocationsPlugin plugin; private TextComponent textComponent; - + @Inject private WildernessLocationsConfig wildyConfig; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java index bce9a3ef15..ea770dadda 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java @@ -1,126 +1,126 @@ -/* - * Copyright (c) 2018, Lotto - * 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.worldhopper; - -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.Keybind; - -@ConfigGroup(WorldHopperConfig.GROUP) -public interface WorldHopperConfig extends Config -{ - String GROUP = "worldhopper"; - - @ConfigItem( - keyName = "previousKey", - name = "Quick-hop previous", - description = "When you press this key you'll hop to the previous world", - position = 0 - ) - default Keybind previousKey() - { - return new Keybind(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); - } - - @ConfigItem( - keyName = "nextKey", - name = "Quick-hop next", - description = "When you press this key you'll hop to the next world", - position = 1 - ) - default Keybind nextKey() - { - return new Keybind(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); - } - - @ConfigItem( - keyName = "quickhopOutOfDanger", - name = "Quick-hop out of dangerous worlds", - description = "Don't hop to a PVP/high risk world when quick-hopping", - position = 2 - ) - default boolean quickhopOutOfDanger() - { - return true; - } - - @ConfigItem( - keyName = "showSidebar", - name = "Show world hopper sidebar", - description = "Show sidebar containing all worlds that mimics in-game interface", - position = 3 - ) - default boolean showSidebar() - { - return true; - } - - @ConfigItem( - keyName = "ping", - name = "Show world ping", - description = "Shows ping to each game world", - position = 4 - ) - default boolean ping() - { - return true; - } - - @ConfigItem( - keyName = "showMessage", - name = "Show world hop message in chat", - description = "Shows what world is being hopped to in the chat", - position = 5 - ) - default boolean showWorldHopMessage() - { - return true; - } - - @ConfigItem( - keyName = "subscriptionFilter", - name = "Show subscription types", - description = "Only show free worlds, member worlds, or both types of worlds in sidebar", - position = 6 - ) - default SubscriptionFilterMode subscriptionFilter() - { - return SubscriptionFilterMode.BOTH; - } - - @ConfigItem( - keyName = "showHistory", - name = "Show history tab", - description = "Shows the history tab", - position = 7 - ) - default boolean showHistory() - { - return true; - } -} +/* + * Copyright (c) 2018, Lotto + * 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.worldhopper; + +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Keybind; + +@ConfigGroup(WorldHopperConfig.GROUP) +public interface WorldHopperConfig extends Config +{ + String GROUP = "worldhopper"; + + @ConfigItem( + keyName = "previousKey", + name = "Quick-hop previous", + description = "When you press this key you'll hop to the previous world", + position = 0 + ) + default Keybind previousKey() + { + return new Keybind(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + } + + @ConfigItem( + keyName = "nextKey", + name = "Quick-hop next", + description = "When you press this key you'll hop to the next world", + position = 1 + ) + default Keybind nextKey() + { + return new Keybind(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + } + + @ConfigItem( + keyName = "quickhopOutOfDanger", + name = "Quick-hop out of dangerous worlds", + description = "Don't hop to a PVP/high risk world when quick-hopping", + position = 2 + ) + default boolean quickhopOutOfDanger() + { + return true; + } + + @ConfigItem( + keyName = "showSidebar", + name = "Show world hopper sidebar", + description = "Show sidebar containing all worlds that mimics in-game interface", + position = 3 + ) + default boolean showSidebar() + { + return true; + } + + @ConfigItem( + keyName = "ping", + name = "Show world ping", + description = "Shows ping to each game world", + position = 4 + ) + default boolean ping() + { + return true; + } + + @ConfigItem( + keyName = "showMessage", + name = "Show world hop message in chat", + description = "Shows what world is being hopped to in the chat", + position = 5 + ) + default boolean showWorldHopMessage() + { + return true; + } + + @ConfigItem( + keyName = "subscriptionFilter", + name = "Show subscription types", + description = "Only show free worlds, member worlds, or both types of worlds in sidebar", + position = 6 + ) + default SubscriptionFilterMode subscriptionFilter() + { + return SubscriptionFilterMode.BOTH; + } + + @ConfigItem( + keyName = "showHistory", + name = "Show history tab", + description = "Shows the history tab", + position = 7 + ) + default boolean showHistory() + { + return true; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index 64a7806666..33852bc40f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -75,13 +75,13 @@ import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.util.ping.Ping; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.ExecutorServiceExceptionLogger; import net.runelite.client.util.HotkeyListener; import net.runelite.client.util.Text; import net.runelite.client.util.WorldUtil; +import net.runelite.client.util.ping.Ping; import net.runelite.http.api.worlds.World; import net.runelite.http.api.worlds.WorldClient; import net.runelite.http.api.worlds.WorldResult; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java index 28f299ed0e..acfd4b25ea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java @@ -1,645 +1,644 @@ -/* - * Copyright (c) 2018, Psikoi - * 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.worldhopper; - -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridLayout; -import java.awt.GridBagLayout; -import java.awt.Color; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.List; -import java.util.ArrayList; -import java.util.Map; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.HashMap; -import java.util.stream.Collectors; -import javax.swing.JPanel; -import javax.swing.JButton; -import javax.swing.JTabbedPane; -import javax.swing.border.Border; -import javax.swing.BorderFactory; -import javax.swing.SwingUtilities; -import lombok.AccessLevel; -import lombok.Setter; - -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.DynamicGridLayout; -import net.runelite.client.ui.PluginPanel; -import net.runelite.http.api.worlds.World; -import net.runelite.http.api.worlds.WorldType; - -@Slf4j -class WorldSwitcherPanel extends PluginPanel -{ - private static final Color ODD_ROW = new Color(44, 44, 44); - - private static final int WORLD_COLUMN_WIDTH = 60; - private static final int PLAYERS_COLUMN_WIDTH = 40; - private static final int PING_COLUMN_WIDTH = 47; - - private final JPanel headerContainer; - private final JPanel headerHistContainer; - private final JPanel listContainer = new JPanel(); - private final JPanel histContainer = new JPanel(); - - private WorldTableHeader worldHeader; - private WorldTableHeader playersHeader; - private WorldTableHeader activityHeader; - private WorldTableHeader pingHeader; - - private WorldOrder orderIndex = WorldOrder.WORLD; - private boolean ascendingOrder = true; - - private ArrayList rows = new ArrayList<>(); - private ArrayList histRows = new ArrayList<>(); - private WorldHopperPlugin plugin; - @Setter(AccessLevel.PACKAGE) - private SubscriptionFilterMode filterMode; - - WorldSwitcherPanel(WorldHopperPlugin plugin) - { - this.plugin = plugin; - - setBorder(null); - setLayout(new DynamicGridLayout(0, 1)); - - headerContainer = buildHeader(); - headerHistContainer = buildHistoryHeader(); - - listContainer.setLayout(new GridLayout(0, 1)); - histContainer.setLayout(new GridLayout(0, 1)); - - updateLayout(); - } - - void updateLayout() - { - if (this.getComponentCount() > 0) - { - for (Component c : this.getComponents()) - { - this.remove(c); - } - } - - if (plugin.showHistory()) - { - Component tabs = createTabs(); - add(tabs); - } - else - { - add(headerContainer); - add(listContainer); - } - } - - void switchCurrentHighlight(int newWorld, int lastWorld) - { - for (WorldTableRow row : rows) - { - if (row.getWorld().getId() == newWorld) - { - row.recolour(true); - } - else if (row.getWorld().getId() == lastWorld) - { - row.recolour(false); - } - } - - for (WorldTableRow row : histRows) - { - if (row.getWorld().getId() == newWorld) - { - row.recolour(true); - } - else if (row.getWorld().getId() == lastWorld) - { - row.recolour(false); - } - } - } - - void updateListData(Map worldData) - { - for (WorldTableRow worldTableRow : rows) - { - World world = worldTableRow.getWorld(); - Integer playerCount = worldData.get(world.getId()); - if (playerCount != null) - { - worldTableRow.updatePlayerCount(playerCount); - } - } - - for (WorldTableRow worldTableRow : histRows) - { - World world = worldTableRow.getWorld(); - Integer playerCount = worldData.get(world.getId()); - if (playerCount != null) - { - worldTableRow.updatePlayerCount(playerCount); - } - } - - // If the list is being ordered by player count, then it has to be re-painted - // to properly display the new data - if (orderIndex == WorldOrder.PLAYERS) - { - updateList(); - } - } - - void updatePing(int world, int ping) - { - for (WorldTableRow worldTableRow : rows) - { - if (worldTableRow.getWorld().getId() == world) - { - worldTableRow.setPing(ping); - - // If the panel is sorted by ping, re-sort it - if (orderIndex == WorldOrder.PING) - { - updateList(); - } - break; - } - } - - for (WorldTableRow worldTableRow : histRows) - { - if (worldTableRow.getWorld().getId() == world) - { - worldTableRow.setPing(ping); - - // If the panel is sorted by ping, re-sort it - if (orderIndex == WorldOrder.PING) - { - updateList(); - } - break; - } - } - } - - void hidePing() - { - for (WorldTableRow worldTableRow : rows) - { - worldTableRow.hidePing(); - } - - for (WorldTableRow worldTableRow : histRows) - { - worldTableRow.hidePing(); - } - } - - void showPing() - { - for (WorldTableRow worldTableRow : rows) - { - worldTableRow.showPing(); - } - - for (WorldTableRow worldTableRow : histRows) - { - worldTableRow.showPing(); - } - } - - void updateList() - { - rows.sort((r1, r2) -> - { - switch (orderIndex) - { - case PING: - return Integer.compare(r1.getPing(), r2.getPing()) * (ascendingOrder ? 1 : -1); - case WORLD: - return Integer.compare(r1.getWorld().getId(), r2.getWorld().getId()) * (ascendingOrder ? 1 : -1); - case PLAYERS: - return Integer.compare(r1.getUpdatedPlayerCount(), r2.getUpdatedPlayerCount()) * (ascendingOrder ? 1 : -1); - case ACTIVITY: - return r1.getWorld().getActivity().compareTo(r2.getWorld().getActivity()) * -1 * (ascendingOrder ? 1 : -1); - default: - return 0; - } - }); - - // Leave empty activity worlds on the bottom of the list - if (orderIndex == WorldOrder.ACTIVITY) - { - rows.sort((r1, r2) -> r1.getWorld().getActivity().equals("-") ? 1 : -1); - } - - rows.sort((r1, r2) -> - { - boolean b1 = plugin.isFavorite(r1.getWorld()); - boolean b2 = plugin.isFavorite(r2.getWorld()); - return Boolean.compare(b2, b1); - }); - - listContainer.removeAll(); - histContainer.removeAll(); - - Map history = plugin.getHistory(); - Map matchedHist = new HashMap<>(); - for (int i = 0; i < rows.size(); i++) - { - WorldTableRow row = rows.get(i); - row.setBackground(i % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); - listContainer.add(row); - - String worldNum = String.valueOf(row.getWorld().getId()); - if (history.containsKey(worldNum)) - { - // Add toa list that we can sort later - matchedHist.put(worldNum, history.get(worldNum)); - } - } - - // Sort by ascending - matchedHist = matchedHist.entrySet().stream() - .sorted(Map.Entry.comparingByValue().reversed()) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, - (e1, e2) -> e1, LinkedHashMap::new)); - - // Add matched rows to history list - Iterator it = matchedHist.entrySet().iterator(); - int histRowCount = 0; - while (it.hasNext()) - { - Map.Entry pair = (Map.Entry)it.next(); - for (WorldTableRow r : rows) - { - WorldTableRow histRow = r; - histRow.setBackground(histRowCount % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); - if (String.valueOf(r.getWorld().getId()).equals(pair.getKey())) - { - histContainer.add(r); - histRowCount++; - break; - } - } - it.remove(); - } - - listContainer.revalidate(); - listContainer.repaint(); - histContainer.revalidate(); - histContainer.repaint(); - } - - Component createTabs() - { - // Constraints for GB Layout - GridBagConstraints listConst = new GridBagConstraints(); - listConst.gridx = 0; - listConst.gridy = 1; - listConst.fill = GridBagConstraints.HORIZONTAL; - GridBagConstraints headConst = new GridBagConstraints(); - headConst.gridx = 0; - headConst.gridy = 0; - headConst.fill = GridBagConstraints.HORIZONTAL; - GridBagConstraints resetConst = new GridBagConstraints(); - resetConst.gridx = 0; - resetConst.gridy = 2; - resetConst.fill = GridBagConstraints.HORIZONTAL; - - // Border so that the scrollbar doesn't go over ping - Border paddingBorder = BorderFactory.createEmptyBorder(0, 0, 0, 5); - - // Clear history button - JButton resetBtn = new JButton("Clear History"); - resetBtn.addActionListener(e -> - { - plugin.clearHistory(); - plugin.addToHistory(); - updateList(); - }); - - // World Selector page - JPanel worldPanel = new JPanel(); - worldPanel.setBorder(paddingBorder); - worldPanel.setLayout(new GridBagLayout()); - worldPanel.add(headerContainer, headConst); - worldPanel.add(listContainer, listConst); - - // History page - JPanel histPanel = new JPanel(); - histPanel.setBorder(paddingBorder); - histPanel.setLayout(new GridBagLayout()); - histPanel.add(headerHistContainer, headConst); - histPanel.add(histContainer, listConst); - histPanel.add(resetBtn, resetConst); - - JTabbedPane worldTabs = new JTabbedPane(); - worldTabs.setName("tabs"); - worldTabs.addTab("Worlds", worldPanel); - worldTabs.addTab("History", histPanel); - - // This is a fix for preventing stretching of WorldTableRows - worldTabs.addChangeListener(e -> - { - switch (worldTabs.getSelectedIndex()) - { - case 0: - histPanel.remove(histContainer); - if (worldPanel.getComponentCount() < 2) - { - worldPanel.add(listContainer, listConst); - } - break; - case 1: - worldPanel.remove(listContainer); - if (histPanel.getComponentCount() < 3) - { - histPanel.add(histContainer, listConst); - } - break; - } - }); - - return worldTabs; - } - - void updateFavoriteMenu(int world, boolean favorite) - { - for (WorldTableRow row : rows) - { - if (row.getWorld().getId() == world) - { - row.setFavoriteMenu(favorite); - } - } - - for (WorldTableRow row : histRows) - { - if (row.getWorld().getId() == world) - { - row.setFavoriteMenu(favorite); - } - } - } - - void resetAllFavoriteMenus() - { - for (WorldTableRow row : rows) - { - row.setFavoriteMenu(false); - } - - for (WorldTableRow row : histRows) - { - row.setFavoriteMenu(false); - } - } - - void populate(List worlds) - { - Map pingHistory = new HashMap<>(); - - for (WorldTableRow row : rows) - { - pingHistory.put(row.getWorld().getId(), row.getPing()); - } - - rows.clear(); - - for (int i = 0; i < worlds.size(); i++) - { - World world = worlds.get(i); - - switch (filterMode) - { - case FREE: - if (world.getTypes().contains(WorldType.MEMBERS)) - { - continue; - } - break; - case MEMBERS: - if (!world.getTypes().contains(WorldType.MEMBERS)) - { - continue; - } - break; - } - - Integer ping = pingHistory.getOrDefault(world.getId(), 0); - rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld() && plugin.getLastWorld() != 0, plugin.isFavorite(world), ping)); - } - - updateList(); - } - - private void orderBy(WorldOrder order) - { - pingHeader.highlight(false, ascendingOrder); - worldHeader.highlight(false, ascendingOrder); - playersHeader.highlight(false, ascendingOrder); - activityHeader.highlight(false, ascendingOrder); - - switch (order) - { - case PING: - pingHeader.highlight(true, ascendingOrder); - break; - case WORLD: - worldHeader.highlight(true, ascendingOrder); - break; - case PLAYERS: - playersHeader.highlight(true, ascendingOrder); - break; - case ACTIVITY: - activityHeader.highlight(true, ascendingOrder); - break; - } - - orderIndex = order; - updateList(); - } - - /** - * Builds the entire table header. - */ - private JPanel buildHistoryHeader() - { - JPanel header = new JPanel(new BorderLayout()); - JPanel leftSide = new JPanel(new BorderLayout()); - JPanel rightSide = new JPanel(new BorderLayout()); - - WorldTableHeader pingHeader = new WorldTableHeader("Ping", false, ascendingOrder, plugin::refresh); - pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); - - WorldTableHeader worldHeader = new WorldTableHeader("World", false, ascendingOrder, plugin::refresh); - worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); - - WorldTableHeader playersHeader = new WorldTableHeader("#", false, ascendingOrder, plugin::refresh); - playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); - - WorldTableHeader activityHeader = new WorldTableHeader("Activity", false, ascendingOrder, plugin::refresh); - - leftSide.add(worldHeader, BorderLayout.WEST); - leftSide.add(playersHeader, BorderLayout.CENTER); - - rightSide.add(activityHeader, BorderLayout.CENTER); - rightSide.add(pingHeader, BorderLayout.EAST); - - header.add(leftSide, BorderLayout.WEST); - header.add(rightSide, BorderLayout.CENTER); - - return header; - } - - private JPanel buildHeader() - { - JPanel header = new JPanel(new BorderLayout()); - JPanel leftSide = new JPanel(new BorderLayout()); - JPanel rightSide = new JPanel(new BorderLayout()); - - pingHeader = new WorldTableHeader("Ping", orderIndex == WorldOrder.PING, ascendingOrder, plugin::refresh); - pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); - pingHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.PING || !ascendingOrder; - orderBy(WorldOrder.PING); - } - }); - - worldHeader = new WorldTableHeader("World", orderIndex == WorldOrder.WORLD, ascendingOrder, plugin::refresh); - worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); - worldHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.WORLD || !ascendingOrder; - orderBy(WorldOrder.WORLD); - } - }); - - playersHeader = new WorldTableHeader("#", orderIndex == WorldOrder.PLAYERS, ascendingOrder, plugin::refresh); - playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); - playersHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.PLAYERS || !ascendingOrder; - orderBy(WorldOrder.PLAYERS); - } - }); - - activityHeader = new WorldTableHeader("Activity", orderIndex == WorldOrder.ACTIVITY, ascendingOrder, plugin::refresh); - activityHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.ACTIVITY || !ascendingOrder; - orderBy(WorldOrder.ACTIVITY); - } - }); - - leftSide.add(worldHeader, BorderLayout.WEST); - leftSide.add(playersHeader, BorderLayout.CENTER); - - rightSide.add(activityHeader, BorderLayout.CENTER); - rightSide.add(pingHeader, BorderLayout.EAST); - - header.add(leftSide, BorderLayout.WEST); - header.add(rightSide, BorderLayout.CENTER); - - return header; - } - - /** - * Builds a table row, that displays the world's information. - */ - private WorldTableRow buildRow(World world, boolean stripe, boolean current, boolean favorite, Integer ping) - { - WorldTableRow row = new WorldTableRow(world, current, favorite, - world1 -> - { - plugin.hopTo(world1); - }, - (world12, add) -> - { - if (add) - { - plugin.addToFavorites(world12); - } - else - { - plugin.removeFromFavorites(world12); - } - - updateList(); - } - ); - row.setBackground(stripe ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); - return row; - } - - /** - * Enumerates the multiple ordering options for the world list. - */ - private enum WorldOrder - { - WORLD, - PLAYERS, - ACTIVITY, - PING - } -} +/* + * Copyright (c) 2018, Psikoi + * 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.worldhopper; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import lombok.AccessLevel; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.DynamicGridLayout; +import net.runelite.client.ui.PluginPanel; +import net.runelite.http.api.worlds.World; +import net.runelite.http.api.worlds.WorldType; + +@Slf4j +class WorldSwitcherPanel extends PluginPanel +{ + private static final Color ODD_ROW = new Color(44, 44, 44); + + private static final int WORLD_COLUMN_WIDTH = 60; + private static final int PLAYERS_COLUMN_WIDTH = 40; + private static final int PING_COLUMN_WIDTH = 47; + + private final JPanel headerContainer; + private final JPanel headerHistContainer; + private final JPanel listContainer = new JPanel(); + private final JPanel histContainer = new JPanel(); + + private WorldTableHeader worldHeader; + private WorldTableHeader playersHeader; + private WorldTableHeader activityHeader; + private WorldTableHeader pingHeader; + + private WorldOrder orderIndex = WorldOrder.WORLD; + private boolean ascendingOrder = true; + + private ArrayList rows = new ArrayList<>(); + private ArrayList histRows = new ArrayList<>(); + private WorldHopperPlugin plugin; + @Setter(AccessLevel.PACKAGE) + private SubscriptionFilterMode filterMode; + + WorldSwitcherPanel(WorldHopperPlugin plugin) + { + this.plugin = plugin; + + setBorder(null); + setLayout(new DynamicGridLayout(0, 1)); + + headerContainer = buildHeader(); + headerHistContainer = buildHistoryHeader(); + + listContainer.setLayout(new GridLayout(0, 1)); + histContainer.setLayout(new GridLayout(0, 1)); + + updateLayout(); + } + + void updateLayout() + { + if (this.getComponentCount() > 0) + { + for (Component c : this.getComponents()) + { + this.remove(c); + } + } + + if (plugin.showHistory()) + { + Component tabs = createTabs(); + add(tabs); + } + else + { + add(headerContainer); + add(listContainer); + } + } + + void switchCurrentHighlight(int newWorld, int lastWorld) + { + for (WorldTableRow row : rows) + { + if (row.getWorld().getId() == newWorld) + { + row.recolour(true); + } + else if (row.getWorld().getId() == lastWorld) + { + row.recolour(false); + } + } + + for (WorldTableRow row : histRows) + { + if (row.getWorld().getId() == newWorld) + { + row.recolour(true); + } + else if (row.getWorld().getId() == lastWorld) + { + row.recolour(false); + } + } + } + + void updateListData(Map worldData) + { + for (WorldTableRow worldTableRow : rows) + { + World world = worldTableRow.getWorld(); + Integer playerCount = worldData.get(world.getId()); + if (playerCount != null) + { + worldTableRow.updatePlayerCount(playerCount); + } + } + + for (WorldTableRow worldTableRow : histRows) + { + World world = worldTableRow.getWorld(); + Integer playerCount = worldData.get(world.getId()); + if (playerCount != null) + { + worldTableRow.updatePlayerCount(playerCount); + } + } + + // If the list is being ordered by player count, then it has to be re-painted + // to properly display the new data + if (orderIndex == WorldOrder.PLAYERS) + { + updateList(); + } + } + + void updatePing(int world, int ping) + { + for (WorldTableRow worldTableRow : rows) + { + if (worldTableRow.getWorld().getId() == world) + { + worldTableRow.setPing(ping); + + // If the panel is sorted by ping, re-sort it + if (orderIndex == WorldOrder.PING) + { + updateList(); + } + break; + } + } + + for (WorldTableRow worldTableRow : histRows) + { + if (worldTableRow.getWorld().getId() == world) + { + worldTableRow.setPing(ping); + + // If the panel is sorted by ping, re-sort it + if (orderIndex == WorldOrder.PING) + { + updateList(); + } + break; + } + } + } + + void hidePing() + { + for (WorldTableRow worldTableRow : rows) + { + worldTableRow.hidePing(); + } + + for (WorldTableRow worldTableRow : histRows) + { + worldTableRow.hidePing(); + } + } + + void showPing() + { + for (WorldTableRow worldTableRow : rows) + { + worldTableRow.showPing(); + } + + for (WorldTableRow worldTableRow : histRows) + { + worldTableRow.showPing(); + } + } + + void updateList() + { + rows.sort((r1, r2) -> + { + switch (orderIndex) + { + case PING: + return Integer.compare(r1.getPing(), r2.getPing()) * (ascendingOrder ? 1 : -1); + case WORLD: + return Integer.compare(r1.getWorld().getId(), r2.getWorld().getId()) * (ascendingOrder ? 1 : -1); + case PLAYERS: + return Integer.compare(r1.getUpdatedPlayerCount(), r2.getUpdatedPlayerCount()) * (ascendingOrder ? 1 : -1); + case ACTIVITY: + return r1.getWorld().getActivity().compareTo(r2.getWorld().getActivity()) * -1 * (ascendingOrder ? 1 : -1); + default: + return 0; + } + }); + + // Leave empty activity worlds on the bottom of the list + if (orderIndex == WorldOrder.ACTIVITY) + { + rows.sort((r1, r2) -> r1.getWorld().getActivity().equals("-") ? 1 : -1); + } + + rows.sort((r1, r2) -> + { + boolean b1 = plugin.isFavorite(r1.getWorld()); + boolean b2 = plugin.isFavorite(r2.getWorld()); + return Boolean.compare(b2, b1); + }); + + listContainer.removeAll(); + histContainer.removeAll(); + + Map history = plugin.getHistory(); + Map matchedHist = new HashMap<>(); + for (int i = 0; i < rows.size(); i++) + { + WorldTableRow row = rows.get(i); + row.setBackground(i % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); + listContainer.add(row); + + String worldNum = String.valueOf(row.getWorld().getId()); + if (history.containsKey(worldNum)) + { + // Add toa list that we can sort later + matchedHist.put(worldNum, history.get(worldNum)); + } + } + + // Sort by ascending + matchedHist = matchedHist.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, + (e1, e2) -> e1, LinkedHashMap::new)); + + // Add matched rows to history list + Iterator it = matchedHist.entrySet().iterator(); + int histRowCount = 0; + while (it.hasNext()) + { + Map.Entry pair = (Map.Entry) it.next(); + for (WorldTableRow r : rows) + { + WorldTableRow histRow = r; + histRow.setBackground(histRowCount % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); + if (String.valueOf(r.getWorld().getId()).equals(pair.getKey())) + { + histContainer.add(r); + histRowCount++; + break; + } + } + it.remove(); + } + + listContainer.revalidate(); + listContainer.repaint(); + histContainer.revalidate(); + histContainer.repaint(); + } + + Component createTabs() + { + // Constraints for GB Layout + GridBagConstraints listConst = new GridBagConstraints(); + listConst.gridx = 0; + listConst.gridy = 1; + listConst.fill = GridBagConstraints.HORIZONTAL; + GridBagConstraints headConst = new GridBagConstraints(); + headConst.gridx = 0; + headConst.gridy = 0; + headConst.fill = GridBagConstraints.HORIZONTAL; + GridBagConstraints resetConst = new GridBagConstraints(); + resetConst.gridx = 0; + resetConst.gridy = 2; + resetConst.fill = GridBagConstraints.HORIZONTAL; + + // Border so that the scrollbar doesn't go over ping + Border paddingBorder = BorderFactory.createEmptyBorder(0, 0, 0, 5); + + // Clear history button + JButton resetBtn = new JButton("Clear History"); + resetBtn.addActionListener(e -> + { + plugin.clearHistory(); + plugin.addToHistory(); + updateList(); + }); + + // World Selector page + JPanel worldPanel = new JPanel(); + worldPanel.setBorder(paddingBorder); + worldPanel.setLayout(new GridBagLayout()); + worldPanel.add(headerContainer, headConst); + worldPanel.add(listContainer, listConst); + + // History page + JPanel histPanel = new JPanel(); + histPanel.setBorder(paddingBorder); + histPanel.setLayout(new GridBagLayout()); + histPanel.add(headerHistContainer, headConst); + histPanel.add(histContainer, listConst); + histPanel.add(resetBtn, resetConst); + + JTabbedPane worldTabs = new JTabbedPane(); + worldTabs.setName("tabs"); + worldTabs.addTab("Worlds", worldPanel); + worldTabs.addTab("History", histPanel); + + // This is a fix for preventing stretching of WorldTableRows + worldTabs.addChangeListener(e -> + { + switch (worldTabs.getSelectedIndex()) + { + case 0: + histPanel.remove(histContainer); + if (worldPanel.getComponentCount() < 2) + { + worldPanel.add(listContainer, listConst); + } + break; + case 1: + worldPanel.remove(listContainer); + if (histPanel.getComponentCount() < 3) + { + histPanel.add(histContainer, listConst); + } + break; + } + }); + + return worldTabs; + } + + void updateFavoriteMenu(int world, boolean favorite) + { + for (WorldTableRow row : rows) + { + if (row.getWorld().getId() == world) + { + row.setFavoriteMenu(favorite); + } + } + + for (WorldTableRow row : histRows) + { + if (row.getWorld().getId() == world) + { + row.setFavoriteMenu(favorite); + } + } + } + + void resetAllFavoriteMenus() + { + for (WorldTableRow row : rows) + { + row.setFavoriteMenu(false); + } + + for (WorldTableRow row : histRows) + { + row.setFavoriteMenu(false); + } + } + + void populate(List worlds) + { + Map pingHistory = new HashMap<>(); + + for (WorldTableRow row : rows) + { + pingHistory.put(row.getWorld().getId(), row.getPing()); + } + + rows.clear(); + + for (int i = 0; i < worlds.size(); i++) + { + World world = worlds.get(i); + + switch (filterMode) + { + case FREE: + if (world.getTypes().contains(WorldType.MEMBERS)) + { + continue; + } + break; + case MEMBERS: + if (!world.getTypes().contains(WorldType.MEMBERS)) + { + continue; + } + break; + } + + Integer ping = pingHistory.getOrDefault(world.getId(), 0); + rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld() && plugin.getLastWorld() != 0, plugin.isFavorite(world), ping)); + } + + updateList(); + } + + private void orderBy(WorldOrder order) + { + pingHeader.highlight(false, ascendingOrder); + worldHeader.highlight(false, ascendingOrder); + playersHeader.highlight(false, ascendingOrder); + activityHeader.highlight(false, ascendingOrder); + + switch (order) + { + case PING: + pingHeader.highlight(true, ascendingOrder); + break; + case WORLD: + worldHeader.highlight(true, ascendingOrder); + break; + case PLAYERS: + playersHeader.highlight(true, ascendingOrder); + break; + case ACTIVITY: + activityHeader.highlight(true, ascendingOrder); + break; + } + + orderIndex = order; + updateList(); + } + + /** + * Builds the entire table header. + */ + private JPanel buildHistoryHeader() + { + JPanel header = new JPanel(new BorderLayout()); + JPanel leftSide = new JPanel(new BorderLayout()); + JPanel rightSide = new JPanel(new BorderLayout()); + + WorldTableHeader pingHeader = new WorldTableHeader("Ping", false, ascendingOrder, plugin::refresh); + pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); + + WorldTableHeader worldHeader = new WorldTableHeader("World", false, ascendingOrder, plugin::refresh); + worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); + + WorldTableHeader playersHeader = new WorldTableHeader("#", false, ascendingOrder, plugin::refresh); + playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); + + WorldTableHeader activityHeader = new WorldTableHeader("Activity", false, ascendingOrder, plugin::refresh); + + leftSide.add(worldHeader, BorderLayout.WEST); + leftSide.add(playersHeader, BorderLayout.CENTER); + + rightSide.add(activityHeader, BorderLayout.CENTER); + rightSide.add(pingHeader, BorderLayout.EAST); + + header.add(leftSide, BorderLayout.WEST); + header.add(rightSide, BorderLayout.CENTER); + + return header; + } + + private JPanel buildHeader() + { + JPanel header = new JPanel(new BorderLayout()); + JPanel leftSide = new JPanel(new BorderLayout()); + JPanel rightSide = new JPanel(new BorderLayout()); + + pingHeader = new WorldTableHeader("Ping", orderIndex == WorldOrder.PING, ascendingOrder, plugin::refresh); + pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); + pingHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.PING || !ascendingOrder; + orderBy(WorldOrder.PING); + } + }); + + worldHeader = new WorldTableHeader("World", orderIndex == WorldOrder.WORLD, ascendingOrder, plugin::refresh); + worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); + worldHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.WORLD || !ascendingOrder; + orderBy(WorldOrder.WORLD); + } + }); + + playersHeader = new WorldTableHeader("#", orderIndex == WorldOrder.PLAYERS, ascendingOrder, plugin::refresh); + playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); + playersHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.PLAYERS || !ascendingOrder; + orderBy(WorldOrder.PLAYERS); + } + }); + + activityHeader = new WorldTableHeader("Activity", orderIndex == WorldOrder.ACTIVITY, ascendingOrder, plugin::refresh); + activityHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.ACTIVITY || !ascendingOrder; + orderBy(WorldOrder.ACTIVITY); + } + }); + + leftSide.add(worldHeader, BorderLayout.WEST); + leftSide.add(playersHeader, BorderLayout.CENTER); + + rightSide.add(activityHeader, BorderLayout.CENTER); + rightSide.add(pingHeader, BorderLayout.EAST); + + header.add(leftSide, BorderLayout.WEST); + header.add(rightSide, BorderLayout.CENTER); + + return header; + } + + /** + * Builds a table row, that displays the world's information. + */ + private WorldTableRow buildRow(World world, boolean stripe, boolean current, boolean favorite, Integer ping) + { + WorldTableRow row = new WorldTableRow(world, current, favorite, + world1 -> + { + plugin.hopTo(world1); + }, + (world12, add) -> + { + if (add) + { + plugin.addToFavorites(world12); + } + else + { + plugin.removeFromFavorites(world12); + } + + updateList(); + } + ); + row.setBackground(stripe ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); + return row; + } + + /** + * Enumerates the multiple ordering options for the world list. + */ + private enum WorldOrder + { + WORLD, + PLAYERS, + ACTIVITY, + PING + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableHeader.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableHeader.java index 2b62fa4d88..2d7ef01406 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableHeader.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableHeader.java @@ -31,7 +31,12 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import javax.annotation.Nonnull; -import javax.swing.*; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import net.runelite.client.ui.ColorScheme; @@ -116,7 +121,7 @@ class WorldTableHeader extends JPanel add(textLabel, BorderLayout.WEST); add(arrowLabel, BorderLayout.EAST); -} + } /** * The labels inherit the parent's mouse listeners. diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java index a450c36b89..6dd39ccfeb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java @@ -98,7 +98,7 @@ class WorldTableRow extends JPanel this.updatedPlayerCount = world.getPlayers(); this. - setLayout(new BorderLayout()); + setLayout(new BorderLayout()); setBorder(new EmptyBorder(2, 0, 2, 0)); addMouseListener(new MouseAdapter() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java index c99979f103..724f83753d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import net.runelite.client.game.AgilityShortcut; - -class AgilityShortcutPoint extends WorldMapPoint -{ - AgilityShortcutPoint(AgilityShortcut data, BufferedImage icon, boolean showTooltip) - { - super(data.getWorldMapLocation(), icon); - - if (showTooltip) - { - setTooltip(data.getTooltip()); - } - } -} +/* + * Copyright (c) 2018, Morgan Lewis + * 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 HOLDER 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.worldmap; + +import java.awt.image.BufferedImage; +import net.runelite.client.game.AgilityShortcut; +import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; + +class AgilityShortcutPoint extends WorldMapPoint +{ + AgilityShortcutPoint(AgilityShortcut data, BufferedImage icon, boolean showTooltip) + { + super(data.getWorldMapLocation(), icon); + + if (showTooltip) + { + setTooltip(data.getTooltip()); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartPoint.java index 14f1842f62..bf62004c59 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartPoint.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2018, John James Hamilton - * 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 HOLDER 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.worldmap; - -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import java.awt.image.BufferedImage; - -class QuestStartPoint extends WorldMapPoint -{ - QuestStartPoint(QuestStartLocation data, BufferedImage icon) - { - super(data.getLocation(), icon); - - setTooltip(data.getTooltip()); - } -} +/* + * Copyright (c) 2018, John James Hamilton + * 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 HOLDER 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.worldmap; + +import java.awt.image.BufferedImage; +import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; + +class QuestStartPoint extends WorldMapPoint +{ + QuestStartPoint(QuestStartLocation data, BufferedImage icon) + { + super(data.getLocation(), icon); + + setTooltip(data.getTooltip()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreePoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreePoint.java index 0dd42013bd..1d4155c4d0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreePoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreePoint.java @@ -1,44 +1,43 @@ -/* - * Copyright (c) 2018, Spedwards - * 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 HOLDER 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.worldmap; - -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -import java.awt.image.BufferedImage; - -class RareTreePoint extends WorldMapPoint -{ - RareTreePoint(WorldPoint point, String tooltip, BufferedImage icon, boolean showTooltip) - { - super(point, icon); - - if (showTooltip) - { - setTooltip(tooltip); - } - } -} +/* + * Copyright (c) 2018, Spedwards + * 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 HOLDER 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.worldmap; + +import java.awt.image.BufferedImage; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; + +class RareTreePoint extends WorldMapPoint +{ + RareTreePoint(WorldPoint point, String tooltip, BufferedImage icon, boolean showTooltip) + { + super(point, icon); + + if (showTooltip) + { + setTooltip(tooltip); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java index b877be8810..b8bb51e3f3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java @@ -72,46 +72,46 @@ enum TeleportLocationData APE_ATOLL_ARCEUUS(TeleportType.ARCEUUS_MAGIC, "Ape Atoll", 90, new WorldPoint(2770, 2703, 0), "ape_atoll_teleport_icon_arceuus.png"), // Jewellery - BARBARIAN_ASSAULT(TeleportType.JEWELLERY, "Games Necklace" , "Barbarian Assault", new WorldPoint(2520, 3571, 0), "games_necklace_teleport_icon.png"), - BURTHORPE_GAMES_ROOM(TeleportType.JEWELLERY, "Games Necklace" , "Burthorpe Games Room", new WorldPoint(2898, 3554, 0), "games_necklace_teleport_icon.png"), - TEARS_OF_GUTHIX(TeleportType.JEWELLERY, "Games Necklace" , "Tears of Guthix", new WorldPoint(3245, 9500, 0), "games_necklace_teleport_icon.png"), - CORPOREAL_BEAST(TeleportType.JEWELLERY, "Games Necklace" , "Corporeal Beast", new WorldPoint(2967, 4384, 0), "games_necklace_teleport_icon.png"), - WINTERTODT_CAMP(TeleportType.JEWELLERY, "Games Necklace" , "Wintertodt Camp", new WorldPoint(1624, 3938, 0), "games_necklace_teleport_icon.png"), - DUEL_ARENA(TeleportType.JEWELLERY, "Ring of Dueling" , "Duel Arena", new WorldPoint(3315, 3235, 0), "ring_of_dueling_teleport_icon.png"), - CLAN_WARS(TeleportType.JEWELLERY, "Ring of Dueling" , "Clan Wars", new WorldPoint(3387, 3158, 0), "ring_of_dueling_teleport_icon.png"), - CASTLE_WARS(TeleportType.JEWELLERY, "Ring of Dueling" , "Castle Wars", new WorldPoint(2441, 3091, 0), "ring_of_dueling_teleport_icon.png"), - WARRIORS_GUILD(TeleportType.JEWELLERY, "Combat Bracelet" , "Warriors' Guild", new WorldPoint(2883, 3549, 0), "combat_bracelet_teleport_icon.png"), - CHAMPIONS_GUILD(TeleportType.JEWELLERY, "Combat Bracelet" , "Champions' Guild", new WorldPoint(3189, 3368, 0), "combat_bracelet_teleport_icon.png"), - EDGEVILLE_MONASTERY(TeleportType.JEWELLERY, "Combat Bracelet" , "Edgeville Monastery", new WorldPoint(3053, 3487, 0), "combat_bracelet_teleport_icon.png"), - RANGING_GUILD(TeleportType.JEWELLERY, "Combat Bracelet" , "Ranging Guild", new WorldPoint(2654, 3441, 0), "combat_bracelet_teleport_icon.png"), - FISHING_GUILD_NECK(TeleportType.JEWELLERY, "Skills Necklace" , "Fishing Guild", new WorldPoint(2613, 3390, 0), "skills_necklace_teleport_icon.png"), - MINING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Mining Guild", new WorldPoint(3049, 9762, 0), "skills_necklace_teleport_icon.png"), - CRAFTING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Crafting Guild", new WorldPoint(2934, 3294, 0), "skills_necklace_teleport_icon.png"), - COOKING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Cooking Guild", new WorldPoint(3145, 3438, 0), "skills_necklace_teleport_icon.png"), - WOODCUTTING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Woodcutting Guild", new WorldPoint(1662, 3505, 0), "skills_necklace_teleport_icon.png"), - FARMING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Farming Guild", new WorldPoint(1249, 3717, 0), "skills_necklace_teleport_icon.png"), - EDGEVILLE(TeleportType.JEWELLERY, "Amulet of Glory" , "Edgeville", new WorldPoint(3087, 3496, 0), "amulet_of_glory_teleport_icon.png"), - KARAMJA(TeleportType.JEWELLERY, "Amulet of Glory" , "Karamja", new WorldPoint(2918, 3176, 0), "amulet_of_glory_teleport_icon.png"), - DRAYNOR_VILLAGE(TeleportType.JEWELLERY, "Amulet of Glory" , "Draynor Village", new WorldPoint(3105, 3251, 0), "amulet_of_glory_teleport_icon.png"), - AL_KHARID(TeleportType.JEWELLERY, "Amulet of Glory" , "Al-Kharid", new WorldPoint(3293, 3163, 0), "amulet_of_glory_teleport_icon.png"), - MISCELLANIA(TeleportType.JEWELLERY, "Ring of Wealth" , "Miscellania", new WorldPoint(2535, 3862, 0), "ring_of_wealth_teleport_icon.png"), - GRAND_EXCHANGE(TeleportType.JEWELLERY, "Ring of Wealth" , "Grand Exchange", new WorldPoint(3162, 3480, 0), "ring_of_wealth_teleport_icon.png"), - FALADOR_PARK(TeleportType.JEWELLERY, "Ring of Wealth" , "Falador Park", new WorldPoint(2995, 3375, 0), "ring_of_wealth_teleport_icon.png"), - DONDAKAN(TeleportType.JEWELLERY, "Ring of Wealth" , "Dondakan", new WorldPoint(2831, 10165, 0), "ring_of_wealth_teleport_icon.png"), - SLAYER_TOWER(TeleportType.JEWELLERY, "Slayer Ring" , "Slayer Tower", new WorldPoint(3429, 3531, 0), "slayer_ring_teleport_icon.png"), - FREMENNIK_SLAYER_DUNGEON(TeleportType.JEWELLERY, "Slayer Ring" , "Fremennik Slayer Dungeon", new WorldPoint(2800, 9998, 0), "slayer_ring_teleport_icon.png"), - TARNS_LAIR(TeleportType.JEWELLERY, "Slayer Ring" , "Tarn's Lair", new WorldPoint(3187, 4601, 0), "slayer_ring_teleport_icon.png"), - STRONGHOLD_SLAYER_CAVE(TeleportType.JEWELLERY, "Slayer Ring" , "Stronghold Slayer Cave", new WorldPoint(2433, 3421, 0), "slayer_ring_teleport_icon.png"), - DARK_BEASTS(TeleportType.JEWELLERY, "Slayer Ring" , "Dark Beasts", new WorldPoint(2028, 4638, 0), "slayer_ring_teleport_icon.png"), - DIGSITE(TeleportType.JEWELLERY, "Digsite Pendant" , "Digsite", new WorldPoint(3339, 3445, 0), "digsite_pendant_teleport_icon.png"), - HOUSE_ON_THE_HILL(TeleportType.JEWELLERY, "Digsite Pendant" , "House on the Hill", new WorldPoint(3763, 3869, 0), "digsite_pendant_teleport_icon.png"), - LITHKREN(TeleportType.JEWELLERY, "Digsite Pendant" , "Lithkren", new WorldPoint(3547, 10456, 0), "digsite_pendant_teleport_icon.png"), - WIZARDS_TOWER(TeleportType.JEWELLERY, "Necklace of Passage" , "Wizards' Tower", new WorldPoint(3114, 3181, 0), "necklace_of_passage_teleport_icon.png"), - JORRALS_OUTPOST(TeleportType.JEWELLERY, "Necklace of Passage" , "Jorral's Outpost", new WorldPoint(2431, 3348, 0), "necklace_of_passage_teleport_icon.png"), - DESERT_EAGLE_STATION(TeleportType.JEWELLERY, "Necklace of Passage" , "Desert eagle station of the eagle transport system", new WorldPoint(3406, 3157, 0), "necklace_of_passage_teleport_icon.png"), - CHAOS_TEMPLE(TeleportType.JEWELLERY, "Burning Amulet" , "Chaos Temple (lvl 15)", new WorldPoint(3234, 3637, 0), "burning_amulet_teleport_icon.png"), - BANDIT_CAMP(TeleportType.JEWELLERY, "Burning Amulet" , "Bandit Camp (lvl 17)", new WorldPoint(3038, 3651, 0), "burning_amulet_teleport_icon.png"), - LAVA_MAZE(TeleportType.JEWELLERY, "Burning Amulet" , "Lava Maze (lvl 41)", new WorldPoint(3028, 3840, 0), "burning_amulet_teleport_icon.png"), + BARBARIAN_ASSAULT(TeleportType.JEWELLERY, "Games Necklace", "Barbarian Assault", new WorldPoint(2520, 3571, 0), "games_necklace_teleport_icon.png"), + BURTHORPE_GAMES_ROOM(TeleportType.JEWELLERY, "Games Necklace", "Burthorpe Games Room", new WorldPoint(2898, 3554, 0), "games_necklace_teleport_icon.png"), + TEARS_OF_GUTHIX(TeleportType.JEWELLERY, "Games Necklace", "Tears of Guthix", new WorldPoint(3245, 9500, 0), "games_necklace_teleport_icon.png"), + CORPOREAL_BEAST(TeleportType.JEWELLERY, "Games Necklace", "Corporeal Beast", new WorldPoint(2967, 4384, 0), "games_necklace_teleport_icon.png"), + WINTERTODT_CAMP(TeleportType.JEWELLERY, "Games Necklace", "Wintertodt Camp", new WorldPoint(1624, 3938, 0), "games_necklace_teleport_icon.png"), + DUEL_ARENA(TeleportType.JEWELLERY, "Ring of Dueling", "Duel Arena", new WorldPoint(3315, 3235, 0), "ring_of_dueling_teleport_icon.png"), + CLAN_WARS(TeleportType.JEWELLERY, "Ring of Dueling", "Clan Wars", new WorldPoint(3387, 3158, 0), "ring_of_dueling_teleport_icon.png"), + CASTLE_WARS(TeleportType.JEWELLERY, "Ring of Dueling", "Castle Wars", new WorldPoint(2441, 3091, 0), "ring_of_dueling_teleport_icon.png"), + WARRIORS_GUILD(TeleportType.JEWELLERY, "Combat Bracelet", "Warriors' Guild", new WorldPoint(2883, 3549, 0), "combat_bracelet_teleport_icon.png"), + CHAMPIONS_GUILD(TeleportType.JEWELLERY, "Combat Bracelet", "Champions' Guild", new WorldPoint(3189, 3368, 0), "combat_bracelet_teleport_icon.png"), + EDGEVILLE_MONASTERY(TeleportType.JEWELLERY, "Combat Bracelet", "Edgeville Monastery", new WorldPoint(3053, 3487, 0), "combat_bracelet_teleport_icon.png"), + RANGING_GUILD(TeleportType.JEWELLERY, "Combat Bracelet", "Ranging Guild", new WorldPoint(2654, 3441, 0), "combat_bracelet_teleport_icon.png"), + FISHING_GUILD_NECK(TeleportType.JEWELLERY, "Skills Necklace", "Fishing Guild", new WorldPoint(2613, 3390, 0), "skills_necklace_teleport_icon.png"), + MINING_GUILD(TeleportType.JEWELLERY, "Skills Necklace", "Mining Guild", new WorldPoint(3049, 9762, 0), "skills_necklace_teleport_icon.png"), + CRAFTING_GUILD(TeleportType.JEWELLERY, "Skills Necklace", "Crafting Guild", new WorldPoint(2934, 3294, 0), "skills_necklace_teleport_icon.png"), + COOKING_GUILD(TeleportType.JEWELLERY, "Skills Necklace", "Cooking Guild", new WorldPoint(3145, 3438, 0), "skills_necklace_teleport_icon.png"), + WOODCUTTING_GUILD(TeleportType.JEWELLERY, "Skills Necklace", "Woodcutting Guild", new WorldPoint(1662, 3505, 0), "skills_necklace_teleport_icon.png"), + FARMING_GUILD(TeleportType.JEWELLERY, "Skills Necklace", "Farming Guild", new WorldPoint(1249, 3717, 0), "skills_necklace_teleport_icon.png"), + EDGEVILLE(TeleportType.JEWELLERY, "Amulet of Glory", "Edgeville", new WorldPoint(3087, 3496, 0), "amulet_of_glory_teleport_icon.png"), + KARAMJA(TeleportType.JEWELLERY, "Amulet of Glory", "Karamja", new WorldPoint(2918, 3176, 0), "amulet_of_glory_teleport_icon.png"), + DRAYNOR_VILLAGE(TeleportType.JEWELLERY, "Amulet of Glory", "Draynor Village", new WorldPoint(3105, 3251, 0), "amulet_of_glory_teleport_icon.png"), + AL_KHARID(TeleportType.JEWELLERY, "Amulet of Glory", "Al-Kharid", new WorldPoint(3293, 3163, 0), "amulet_of_glory_teleport_icon.png"), + MISCELLANIA(TeleportType.JEWELLERY, "Ring of Wealth", "Miscellania", new WorldPoint(2535, 3862, 0), "ring_of_wealth_teleport_icon.png"), + GRAND_EXCHANGE(TeleportType.JEWELLERY, "Ring of Wealth", "Grand Exchange", new WorldPoint(3162, 3480, 0), "ring_of_wealth_teleport_icon.png"), + FALADOR_PARK(TeleportType.JEWELLERY, "Ring of Wealth", "Falador Park", new WorldPoint(2995, 3375, 0), "ring_of_wealth_teleport_icon.png"), + DONDAKAN(TeleportType.JEWELLERY, "Ring of Wealth", "Dondakan", new WorldPoint(2831, 10165, 0), "ring_of_wealth_teleport_icon.png"), + SLAYER_TOWER(TeleportType.JEWELLERY, "Slayer Ring", "Slayer Tower", new WorldPoint(3429, 3531, 0), "slayer_ring_teleport_icon.png"), + FREMENNIK_SLAYER_DUNGEON(TeleportType.JEWELLERY, "Slayer Ring", "Fremennik Slayer Dungeon", new WorldPoint(2800, 9998, 0), "slayer_ring_teleport_icon.png"), + TARNS_LAIR(TeleportType.JEWELLERY, "Slayer Ring", "Tarn's Lair", new WorldPoint(3187, 4601, 0), "slayer_ring_teleport_icon.png"), + STRONGHOLD_SLAYER_CAVE(TeleportType.JEWELLERY, "Slayer Ring", "Stronghold Slayer Cave", new WorldPoint(2433, 3421, 0), "slayer_ring_teleport_icon.png"), + DARK_BEASTS(TeleportType.JEWELLERY, "Slayer Ring", "Dark Beasts", new WorldPoint(2028, 4638, 0), "slayer_ring_teleport_icon.png"), + DIGSITE(TeleportType.JEWELLERY, "Digsite Pendant", "Digsite", new WorldPoint(3339, 3445, 0), "digsite_pendant_teleport_icon.png"), + HOUSE_ON_THE_HILL(TeleportType.JEWELLERY, "Digsite Pendant", "House on the Hill", new WorldPoint(3763, 3869, 0), "digsite_pendant_teleport_icon.png"), + LITHKREN(TeleportType.JEWELLERY, "Digsite Pendant", "Lithkren", new WorldPoint(3547, 10456, 0), "digsite_pendant_teleport_icon.png"), + WIZARDS_TOWER(TeleportType.JEWELLERY, "Necklace of Passage", "Wizards' Tower", new WorldPoint(3114, 3181, 0), "necklace_of_passage_teleport_icon.png"), + JORRALS_OUTPOST(TeleportType.JEWELLERY, "Necklace of Passage", "Jorral's Outpost", new WorldPoint(2431, 3348, 0), "necklace_of_passage_teleport_icon.png"), + DESERT_EAGLE_STATION(TeleportType.JEWELLERY, "Necklace of Passage", "Desert eagle station of the eagle transport system", new WorldPoint(3406, 3157, 0), "necklace_of_passage_teleport_icon.png"), + CHAOS_TEMPLE(TeleportType.JEWELLERY, "Burning Amulet", "Chaos Temple (lvl 15)", new WorldPoint(3234, 3637, 0), "burning_amulet_teleport_icon.png"), + BANDIT_CAMP(TeleportType.JEWELLERY, "Burning Amulet", "Bandit Camp (lvl 17)", new WorldPoint(3038, 3651, 0), "burning_amulet_teleport_icon.png"), + LAVA_MAZE(TeleportType.JEWELLERY, "Burning Amulet", "Lava Maze (lvl 41)", new WorldPoint(3028, 3840, 0), "burning_amulet_teleport_icon.png"), // Misc XERICS_LOOKOUT(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Lookout", new WorldPoint(1576, 3528, 0), "xerics_talisman_teleport_icon.png"), @@ -127,7 +127,7 @@ enum TeleportLocationData RELLEKKKA_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Rellekka", new WorldPoint(2664, 3643, 0), "enchanted_lyre_teleport_icon.png"), WATERBIRTH_ISLAND_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Waterbirth Island", new WorldPoint(2550, 3756, 0), "enchanted_lyre_teleport_icon.png"), NEITIZNOT_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Neitiznot", new WorldPoint(2336, 3801, 0), "enchanted_lyre_teleport_icon.png"), - JATIZSO_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Jatizso", new WorldPoint(2409, 3809, 0), "enchanted_lyre_teleport_icon.png"), + JATIZSO_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Jatizso", new WorldPoint(2409, 3809, 0), "enchanted_lyre_teleport_icon.png"), WEISS_ICY_BASALT(TeleportType.OTHER, "Icy Basalt", "Weiss", new WorldPoint(2846, 3940, 0), "icy_basalt_teleport_icon.png"), TROLL_STRONGHOLD_STONY_BASALT(TeleportType.OTHER, "Stony Basalt", "Troll Stronghold", new WorldPoint(2838, 3693, 0), "stony_basalt_teleport_icon.png"), KHAREDSTS_MEMOIRS_HOSIDIUS(TeleportType.OTHER, "Kharedst's Memoirs", "Lunch by the Lancalliums (Hosidius)", new WorldPoint(1713, 3612, 0), "kharedsts_memoirs_teleport_icon.png"), @@ -150,19 +150,19 @@ enum TeleportLocationData // Achievement Diary ARDOUGNE_CLOAK_MONASTERY(TeleportType.OTHER, "Ardougne Cloak", "Monastery", new WorldPoint(2606, 3222, 0), "ardougne_cloak_icon.png"), ARDOUGNE_CLOAK_FARM(TeleportType.OTHER, "Ardougne Cloak", "Farm", new WorldPoint(2673, 3375, 0), "ardougne_cloak_icon.png"), - EXPLORERS_RING(TeleportType.OTHER, "Explorer's Ring", new WorldPoint(3052, 3292, 0), "explorers_ring_icon.png"), + EXPLORERS_RING(TeleportType.OTHER, "Explorer's Ring", new WorldPoint(3052, 3292, 0), "explorers_ring_icon.png"), KARAMJA_GLOVES_GEM_MINE(TeleportType.OTHER, "Karamja Gloves", "Gem Mine (Underground)", new WorldPoint(2827, 2997, 0), "karamja_gloves_icon.png"), KARAMJA_GLOVES_DURADEL(TeleportType.OTHER, "Karamja Gloves", "Duradel", new WorldPoint(2870, 2981, 0), "karamja_gloves_icon.png"), DESERT_AMULET_NARDAH(TeleportType.OTHER, "Desert Amulet", "Nardah", new WorldPoint(3432, 2914, 0), "desert_amulet_icon.png"), DESERT_AMULKT_KALPHITE_CAVE(TeleportType.OTHER, "Desert Amulet", "Kalphite Cave", new WorldPoint(3322, 3122, 0), "desert_amulet_icon.png"), MORYTANIA_LEGS_SLIME_PIT(TeleportType.OTHER, "Morytania Legs", "Slime Pit (Underground)", new WorldPoint(3654, 3516, 0), "morytania_legs_icon.png"), MORYTANIA_LEGS_BURGH_DE_ROTT(TeleportType.OTHER, "Morytania Legs", "Burgh de Rott", new WorldPoint(3482, 3231, 0), "morytania_legs_icon.png"), - FREMENNIK_SEA_BOOTS(TeleportType.OTHER, "Fremennik Sea Boots", new WorldPoint(2640, 3675, 0), "fremennik_boots_icon.png"), - KANDARIN_HEADGEAR(TeleportType.OTHER, "Kandarin Headgear", new WorldPoint(2729, 3411, 0), "kandarin_headgear_icon.png"), + FREMENNIK_SEA_BOOTS(TeleportType.OTHER, "Fremennik Sea Boots", new WorldPoint(2640, 3675, 0), "fremennik_boots_icon.png"), + KANDARIN_HEADGEAR(TeleportType.OTHER, "Kandarin Headgear", new WorldPoint(2729, 3411, 0), "kandarin_headgear_icon.png"), WILDERNESS_SWORD(TeleportType.OTHER, "Wilderness Sword", new WorldPoint(3377, 3891, 0), "wilderness_sword_icon.png"), - WESTERN_BANNER(TeleportType.OTHER, "Western Banner", new WorldPoint(2329, 3685, 0), "western_banner_icon.png"), - RADAS_BLESSING_MOUNT_KARUULM(TeleportType.OTHER, "Rada's Blessing", new WorldPoint(1311, 3795, 0), "radas_blessing_icon.png"), - RADAS_BLESSING_WOODLANG(TeleportType.OTHER, "Rada's Blessing", new WorldPoint(1553, 3454, 0), "radas_blessing_icon.png"), + WESTERN_BANNER(TeleportType.OTHER, "Western Banner", new WorldPoint(2329, 3685, 0), "western_banner_icon.png"), + RADAS_BLESSING_MOUNT_KARUULM(TeleportType.OTHER, "Rada's Blessing", new WorldPoint(1311, 3795, 0), "radas_blessing_icon.png"), + RADAS_BLESSING_WOODLANG(TeleportType.OTHER, "Rada's Blessing", new WorldPoint(1553, 3454, 0), "radas_blessing_icon.png"), // Scrolls DIGSITE_SCROLL(TeleportType.SCROLL, "Digsite Teleport", new WorldPoint(3324, 3412, 0), "scroll_teleport_icon.png"), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPoint.java index 57fce253e9..fc868331b1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPoint.java @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2019, Kyle Sergio - * Copyright (c) 2019, Bryce Altomare - * Copyright (c) 2019, Kyle Stead - * 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 HOLDER 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.worldmap; - -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import java.awt.image.BufferedImage; - -class TransportationPoint extends WorldMapPoint -{ - TransportationPoint(TransportationPointLocation data, BufferedImage icon) - { - super(data.getLocation(), icon); - setTooltip(data.getTooltip()); - } -} +/* + * Copyright (c) 2019, Kyle Sergio + * Copyright (c) 2019, Bryce Altomare + * Copyright (c) 2019, Kyle Stead + * 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 HOLDER 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.worldmap; + +import java.awt.image.BufferedImage; +import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; + +class TransportationPoint extends WorldMapPoint +{ + TransportationPoint(TransportationPointLocation data, BufferedImage icon) + { + super(data.getLocation(), icon); + setTooltip(data.getTooltip()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java index 54bd7adfdc..9e045e4f1a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java @@ -1,193 +1,193 @@ -/* - * Copyright (c) 2019, Kyle Sergio - * Copyright (c) 2019, Bryce Altomare - * Copyright (c) 2019, Kyle Stead - * 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 HOLDER 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.worldmap; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import net.runelite.api.coords.WorldPoint; - -@Getter -@AllArgsConstructor -enum TransportationPointLocation -{ - //Ships - ARDOUGNE_TO_BRIMHAVEN("Ship to Brimhaven", new WorldPoint(2675, 3275, 0)), - ARDOUGNE_TO_FISHINGPLAT("Ship to Fishing Platform", new WorldPoint(2722, 3304, 0)), - BRIMHAVEN_TO_ARDOUGNE("Ship to Ardougne", new WorldPoint(2772, 3234, 0)), - CATHERBY_TO_KEEP_LE_FAYE("Ship to Keep Le Faye", new WorldPoint(2804, 3421, 0)), - CORSAIR_TO_RIMMINGTON("Ship to Rimmington", new WorldPoint(2577, 2839, 0)), - DRAGONTOOTH_TO_PHASMATYS("Ship to Port Phasmatys", new WorldPoint(3791, 3561, 0)), - DIGSITE_TO_FOSSIL("Ship to Fossil Island", new WorldPoint(3361, 3448, 0)), - ENTRANA_TO_PORTSARIM("Ship to Port Sarim", new WorldPoint(2833, 3334, 0)), - FISHINGPLAT_TO_ARDOUGNE("Ship to Ardougne", new WorldPoint(2779, 3271, 0)), - HARMLESS_TO_PORT_PHASMATYS("Ship to Port Phasmatys", new WorldPoint(3682, 2951, 0)), - ICEBERG_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2657, 3988, 0)), - ISLAND_TO_APE_ATOLL("Ship to Ape Atoll", new WorldPoint(2891, 2726, 0)), - JATIZSO_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2420, 3780, 0)), - KARAMJA_TO_PORT_SARIM("Ship to Port Sarim", new WorldPoint(2955, 3144, 0)), - KARAMJA_TO_PORT_KHAZARD("Ship to Port Khazard", new WorldPoint(2763, 2957, 0)), - LANDSEND_TO_PORTSARIM_PORTPISCARILIUS("Ship to Port Sarim/Port Piscarilius", new WorldPoint(1503, 3398, 0)), - LUNAR_ISLE_TO_PIRATES_COVE("Ship to Pirates' Cove", new WorldPoint(2137, 3899, 0)), - MISCELLANIA_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2579, 3846, 0)), - NEITIZNOT_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2310, 3779, 0)), - PESTCONTROL_TO_PORTSARIM("Ship to Port Sarim", new WorldPoint(2659, 2675, 0)), - PIRATES_COVE_TO_LUNAR_ISLE("Ship to Lunar Isle", new WorldPoint(2223, 3796, 0)), - PIRATES_COVE_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2212, 3794, 0)), - PORT_PHASMATYS_TO_DRAGONTOOTH("Ship to Dragontooth Island", new WorldPoint(3703, 3487, 0)), - PORT_PHASMATYS_TO_HARMLESS("Ship to Mos Le'Harmless", new WorldPoint(3709, 3497, 0)), - PORT_PISCARILIUS_TO_PORTSARIM_LANDSEND("Ship to Port Sarim/Land's End", new WorldPoint(1823, 3692, 0)), - PORTSARIM_TO_GREAT_KOUREND("Ship to Great Kourend", new WorldPoint(3054, 3244, 0)), - PORTSARIM_TO_ENTRANA("Ship to Entrana", new WorldPoint(3046, 3233, 0)), - PORTSARIM_TO_KARAMJA("Ship to Karamja", new WorldPoint(3029, 3218, 0)), - PORTSARIM_TO_CRANDOR("Ship to Crandor", new WorldPoint(3045, 3205, 0)), - PORTSARIM_TO_PEST_CONTROL("Ship to Pest Control", new WorldPoint(3039, 3201, 0)), - RELLEKKA_TO_JATIZSO_NEITIZNOT("Ship to Jatizso/Neitiznot", new WorldPoint(2639, 3710, 0)), - RELLEKKA_TO_MISCELLANIA("Ship to Miscellania", new WorldPoint(2627, 3692, 0)), - RELLEKKA_TO_WATERBIRTH("Ship to Waterbirth", new WorldPoint(2621, 3683, 0)), - RELLEKKA_TO_WEISS_ICEBERG("Ship to Weiss/Iceberg", new WorldPoint(2707, 3735, 0)), - RELLEKKA_TO_UNGAEL("Ship to Ungael", new WorldPoint(2638, 3698, 0)), - RIMMINGTON_TO_CORSAIR_COVE("Ship to Corsair Cove", new WorldPoint(2909, 3227, 0 )), - WATERBIRTH_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2549, 3758, 0)), - WEISS_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2847, 3967, 0)), - UNGAEL_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2276, 4034, 0)), - - //Row Boats - ROW_BOAT_BATTLEFRONT("Rowboat to Molch/Molch Island/Shayzien", new WorldPoint(1383, 3663, 0)), - ROW_BOAT_BRAIN_DEATH("Rowboat to Port Phasmatys", new WorldPoint(2161, 5117, 0)), - ROW_BOAT_BURGH_DE_ROTT("Rowboat to Meiyerditch", new WorldPoint(3522, 3168, 0)), - ROW_BOAT_CRABCLAW("Rowboat to Hosidius", new WorldPoint(1780, 3417, 0)), - ROW_BOAT_DIVING_ISLAND("Rowboat to Barge/Camp/North of Island", new WorldPoint(3764, 3901, 0)), - ROW_BOAT_FISHING_GUILD("Rowboat to Hemenster", new WorldPoint(2598, 3426, 0)), - ROW_BOAT_GNOME_STRONGHOLD("Rowboat to Fishing Colony", new WorldPoint(2368, 3487, 0)), - ROW_BOAT_FISHING_COLONY("Rowboat to Gnome Stronghold", new WorldPoint(2356, 3641, 0)), - ROW_BOAT_HEMENSTER("Rowboat to Fishing Guild", new WorldPoint(2613, 3439, 0)), - ROW_BOAT_HOSIDIUS("Rowboat to Crabclaw Isle", new WorldPoint(1779, 3457, 0)), - ROW_BOAT_LITHKREN("Rowboat to Mushroom Forest", new WorldPoint(3582, 3973, 0)), - ROW_BOAT_LUMBRIDGE("Rowboat to Misthalin Mystery", new WorldPoint(3238, 3141, 0)), - ROW_BOAT_MOLCH("Rowboat to Molch Island/Shayzien/Battlefront", new WorldPoint(1343, 3646, 0)), - ROW_BOAT_MOLCH_ISLAND("Rowboat to Molch/Shayzien/Battlefront", new WorldPoint(1368, 3641, 0)), - ROW_BOAT_MORT("Rowboat to Mort Myre", new WorldPoint(3518, 3284, 0)), - ROW_BOAT_MORT_SWAMP("Rowboat to Mort'ton", new WorldPoint(3498, 3380, 0)), - ROW_BOAT_MUSEUM_CAMP("Rowboat to Barge/Digsite/North of Island", new WorldPoint(3723, 3807, 0)), - ROW_BOAT_MUSHROOM_FOREST_WEST("Rowboat to Lithkren", new WorldPoint(3659, 3849, 0)), - ROW_BOAT_MUSHROOM_FOREST_NE("Rowboat to Barge/Camp/Sea", new WorldPoint(3733, 3894, 0)), - ROW_BOAT_PORT_PHASMATYS_NORTH("Rowboat to Slepe", new WorldPoint(3670, 3545, 0)), - ROW_BOAT_PORT_PHASMATYS_EAST("Rowboat to Braindeath Island", new WorldPoint(3680, 3538, 0)), - ROW_BOAT_SHAYZIEN("Rowboat to Molch/Molch Island/Battlefront", new WorldPoint(1405, 3612, 0)), - ROW_BOAT_SLEPE("Rowboat to Port Phasmatys", new WorldPoint(3661, 3279, 0)), - OGRE_BOAT_FELDIP("Ogre Boat to Karamja", new WorldPoint(2653, 2964, 0)), - OGRE_BOAT_KARAMJA("Ogre Boat to Feldip", new WorldPoint(2757, 3085, 0)), - - //Charter ships - CHARTER_BRIMHAVEN("Charter Ship", new WorldPoint(2760, 3238, 0)), - CHARTER_CATHERBY("Charter Ship", new WorldPoint(2791, 3415, 0)), - CHARTER_CORSAIR_("Charter Ship", new WorldPoint(2589, 2851, 0)), - CHARTER_KARAMJA_NORTH("Charter Ship", new WorldPoint(2954, 3159, 0)), - CHARTER_KARAMJA_EAST("Charter Ship", new WorldPoint(2999, 3032, 0)), - CHARTER_KHAZARD("Charter Ship", new WorldPoint(2673, 3143, 0)), - CHARTER_MOSLE_HARMLESS("Charter Ship", new WorldPoint(3669, 2931, 0)), - CHARTER_PORT_PHASMATYS("Charter Ship", new WorldPoint(3702, 3503, 0)), - CHARTER_PORTSARIM("Charter Ship", new WorldPoint(3037, 3191, 0)), - CHARTER_TYRAS("Charter Ship", new WorldPoint(2141, 3123, 0)), - - //Minecarts/Carts - MINE_CART_ARCEUUS("Minecart", new WorldPoint(1673, 3832, 0)), - MINE_CART_GRANDEXCHANGE("Minecart to Keldagrim", new WorldPoint(3139, 3504, 0)), - MINE_CART_HOSIDIUS("Minecart", new WorldPoint(1656, 3542, 0)), - MINE_CART_KELDAGRIM("Minecart", new WorldPoint(2908, 10170, 0)), - MINE_CART_LOVAKENGJ("Minecart", new WorldPoint(1524, 3721, 0)), - MINE_CART_PORT_PISCARILIUS("Minecart", new WorldPoint(1760, 3708, 0)), - MINE_CART_QUIDAMORTEM("Minecart", new WorldPoint(1253, 3550, 0)), - MINE_CART_SHAYZIEN("Minecart", new WorldPoint(1586, 3622, 0)), - MINE_CART_TAVERLEY_UNDERGROUND("Minecart", new WorldPoint(2874, 9870, 0)), - CART_TO_BRIMHAVEN("Cart to Brimhaven", new WorldPoint(2833, 2958, 0)), - CART_TO_SHILO("Cart to Shilo", new WorldPoint(2780, 3214, 0)), - - //Canoes - CANOE_BARBVILLAGE("Canoe", new WorldPoint(3111, 3409, 0)), - CANOE_CHAMPIONSGUILD("Canoe", new WorldPoint(3202, 3344, 0)), - CANOE_EDGEVILLE("Canoe", new WorldPoint(3130, 3509, 0)), - CANOE_LUMBRIDGE("Canoe", new WorldPoint(3241, 3238, 0)), - - //Gnome Gliders - GNOME_GLIDER_KHARID("Gnome Glider", new WorldPoint(3278, 3213, 0)), - GNOME_GLIDER_APE_ATOLL("Gnome Glider", new WorldPoint(2712, 2804, 0)), - GNOME_GLIDER_KARAMJA("Gnome Glider", new WorldPoint(2971, 2974, 0)), - GNOME_GLIDER_FELDIP("Gnome Glider", new WorldPoint(2540, 2969, 0)), - GNOME_GLIDER_GNOMESTRONGHOLD("Gnome Glider", new WorldPoint(2460, 3502, 0)), - GNOME_GLIDER_WHITEWOLF("Gnome Glider", new WorldPoint(2845, 3501, 0)), - - //Balloons - BALLOON_VARROCK("Hot Air Balloon", new WorldPoint(3298, 3480, 0)), - BALLOON_YANILLE("Hot Air Balloon", new WorldPoint(2458, 3108, 0)), - BALLOON_GNOMESTRONGHOLD("Hot Air Balloon", new WorldPoint(2478, 3459, 0)), - BALLOON_TAVERLEY("Hot Air Balloon", new WorldPoint(2936, 3422, 0)), - BALLOON_FALADOR("Hot Air Balloon", new WorldPoint(2921, 3301, 0)), - - //Spirit Tree - SPIRITTREE_ARDOUGNE("Spirit Tree", new WorldPoint(2554, 3259, 0)), - SPIRITTREE_CORSAIR("Spirit Tree", new WorldPoint(2485, 2850, 0)), - SPIRITTREE_GNOMESTRONGHOLD("Spirit Tree", new WorldPoint(2459, 3446, 0)), - SPIRITTREE_GNOMEVILLAGE("Spirit Tree", new WorldPoint(2538, 3166, 0)), - SPIRITTREE_GRANDEXCHANGE("Spirit Tree", new WorldPoint(3184, 3510, 0)), - - //Carpets - CARPET_KHARID("Carpet to Bedabin/Pollnivneach/Uzer", new WorldPoint(3311, 3107, 0)), - CARPET_BEDABIN("Carpet to Shantay Pass", new WorldPoint(3183, 3042, 0)), - CARPET_POLLNIVNEACH_NORTH("Carpet to Shantay Pass", new WorldPoint(3351, 3001, 0)), - CARPET_POLLNIVNEACH_SOUTH("Carpet to Nardah/Sophanem/Menaphos", new WorldPoint(3345, 2943, 0)), - CARPET_NARDAH("Carpet to Pollnivneach", new WorldPoint(3399, 2916, 0)), - CARPET_SOPHANEM("Carpet to Pollnivneach", new WorldPoint(3288, 2814, 0)), - CARPET_MENAPHOS("Carpet to Pollnivneach", new WorldPoint(3244, 2812, 0)), - CARPET_UZER("Carpet to Shantay Pass", new WorldPoint(3468, 3111, 0)), - - //Teleports - TELEPORT_ARCHIVE_FROM_ARCEUUS("Teleport to Library Archive", new WorldPoint(1623, 3808, 0)), - TELEPORT_HARMLESS_FROM_HARMONY("Teleport to Mos Le'Harmless", new WorldPoint(3784, 2828, 0)), - TELEPORT_RUNE_ARDOUGNE("Teleport to Rune Essence", new WorldPoint(2681, 3325, 0)), - TELEPORT_RUNE_YANILLE("Teleport to Rune Essence", new WorldPoint(2592, 3089, 0)), - TELEPORT_SORCERESS_GARDEN("Teleport to Sorceress's Garden", new WorldPoint(3320, 3141, 0)), - - //Other - ALTER_KOUREND_UNDERGROUND("Altar to Skotizo", new WorldPoint(1662, 10047, 0)), - FAIRY_RING_ZANARIS_TO_KHARID("Fairy Ring to Al Kharid", new WorldPoint(2483, 4471, 0)), - FAIRY_RING_ZANARIS_TO_SHACK("Fairy Ring to Shack", new WorldPoint(2451, 4471, 0)), - MOUNTAIN_GUIDE_QUIDAMORTEM("Mountain Guide", new WorldPoint(1275, 3559, 0)), - MOUNTAIN_GUIDE_WALL("Mountain Guide", new WorldPoint(1400, 3538, 0)), - MUSHTREE_MUSHROOM_FOREST("Mushtree", new WorldPoint(3674, 3871, 0)), - MUSHTREE_TAR_SWAMP("Mushtree", new WorldPoint(3676, 3755, 0)), - MUSHTREE_VERDANT_VALLEY("Mushtree", new WorldPoint(3757, 3756, 0)), - MYTHS_GUILD_PORTAL("Portal to Guilds", new WorldPoint(2456, 2856, 0)), - TRAIN_KELDAGRIM("Railway Station", new WorldPoint(2941, 10179, 0)), - WILDERNESS_LEVER_ARDOUGNE("Wilderness Lever", new WorldPoint(2559, 3309, 0)), - WILDERNESS_LEVER_EDGEVILLE("Wilderness Lever", new WorldPoint(3088, 3474, 0)), - WILDERNESS_LEVER_WILDERNESS("Wilderness Lever", new WorldPoint(3154, 3924, 0)); - - private final String tooltip; - private final WorldPoint location; -} +/* + * Copyright (c) 2019, Kyle Sergio + * Copyright (c) 2019, Bryce Altomare + * Copyright (c) 2019, Kyle Stead + * 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 HOLDER 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.worldmap; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.runelite.api.coords.WorldPoint; + +@Getter +@AllArgsConstructor +enum TransportationPointLocation +{ + //Ships + ARDOUGNE_TO_BRIMHAVEN("Ship to Brimhaven", new WorldPoint(2675, 3275, 0)), + ARDOUGNE_TO_FISHINGPLAT("Ship to Fishing Platform", new WorldPoint(2722, 3304, 0)), + BRIMHAVEN_TO_ARDOUGNE("Ship to Ardougne", new WorldPoint(2772, 3234, 0)), + CATHERBY_TO_KEEP_LE_FAYE("Ship to Keep Le Faye", new WorldPoint(2804, 3421, 0)), + CORSAIR_TO_RIMMINGTON("Ship to Rimmington", new WorldPoint(2577, 2839, 0)), + DRAGONTOOTH_TO_PHASMATYS("Ship to Port Phasmatys", new WorldPoint(3791, 3561, 0)), + DIGSITE_TO_FOSSIL("Ship to Fossil Island", new WorldPoint(3361, 3448, 0)), + ENTRANA_TO_PORTSARIM("Ship to Port Sarim", new WorldPoint(2833, 3334, 0)), + FISHINGPLAT_TO_ARDOUGNE("Ship to Ardougne", new WorldPoint(2779, 3271, 0)), + HARMLESS_TO_PORT_PHASMATYS("Ship to Port Phasmatys", new WorldPoint(3682, 2951, 0)), + ICEBERG_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2657, 3988, 0)), + ISLAND_TO_APE_ATOLL("Ship to Ape Atoll", new WorldPoint(2891, 2726, 0)), + JATIZSO_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2420, 3780, 0)), + KARAMJA_TO_PORT_SARIM("Ship to Port Sarim", new WorldPoint(2955, 3144, 0)), + KARAMJA_TO_PORT_KHAZARD("Ship to Port Khazard", new WorldPoint(2763, 2957, 0)), + LANDSEND_TO_PORTSARIM_PORTPISCARILIUS("Ship to Port Sarim/Port Piscarilius", new WorldPoint(1503, 3398, 0)), + LUNAR_ISLE_TO_PIRATES_COVE("Ship to Pirates' Cove", new WorldPoint(2137, 3899, 0)), + MISCELLANIA_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2579, 3846, 0)), + NEITIZNOT_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2310, 3779, 0)), + PESTCONTROL_TO_PORTSARIM("Ship to Port Sarim", new WorldPoint(2659, 2675, 0)), + PIRATES_COVE_TO_LUNAR_ISLE("Ship to Lunar Isle", new WorldPoint(2223, 3796, 0)), + PIRATES_COVE_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2212, 3794, 0)), + PORT_PHASMATYS_TO_DRAGONTOOTH("Ship to Dragontooth Island", new WorldPoint(3703, 3487, 0)), + PORT_PHASMATYS_TO_HARMLESS("Ship to Mos Le'Harmless", new WorldPoint(3709, 3497, 0)), + PORT_PISCARILIUS_TO_PORTSARIM_LANDSEND("Ship to Port Sarim/Land's End", new WorldPoint(1823, 3692, 0)), + PORTSARIM_TO_GREAT_KOUREND("Ship to Great Kourend", new WorldPoint(3054, 3244, 0)), + PORTSARIM_TO_ENTRANA("Ship to Entrana", new WorldPoint(3046, 3233, 0)), + PORTSARIM_TO_KARAMJA("Ship to Karamja", new WorldPoint(3029, 3218, 0)), + PORTSARIM_TO_CRANDOR("Ship to Crandor", new WorldPoint(3045, 3205, 0)), + PORTSARIM_TO_PEST_CONTROL("Ship to Pest Control", new WorldPoint(3039, 3201, 0)), + RELLEKKA_TO_JATIZSO_NEITIZNOT("Ship to Jatizso/Neitiznot", new WorldPoint(2639, 3710, 0)), + RELLEKKA_TO_MISCELLANIA("Ship to Miscellania", new WorldPoint(2627, 3692, 0)), + RELLEKKA_TO_WATERBIRTH("Ship to Waterbirth", new WorldPoint(2621, 3683, 0)), + RELLEKKA_TO_WEISS_ICEBERG("Ship to Weiss/Iceberg", new WorldPoint(2707, 3735, 0)), + RELLEKKA_TO_UNGAEL("Ship to Ungael", new WorldPoint(2638, 3698, 0)), + RIMMINGTON_TO_CORSAIR_COVE("Ship to Corsair Cove", new WorldPoint(2909, 3227, 0)), + WATERBIRTH_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2549, 3758, 0)), + WEISS_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2847, 3967, 0)), + UNGAEL_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2276, 4034, 0)), + + //Row Boats + ROW_BOAT_BATTLEFRONT("Rowboat to Molch/Molch Island/Shayzien", new WorldPoint(1383, 3663, 0)), + ROW_BOAT_BRAIN_DEATH("Rowboat to Port Phasmatys", new WorldPoint(2161, 5117, 0)), + ROW_BOAT_BURGH_DE_ROTT("Rowboat to Meiyerditch", new WorldPoint(3522, 3168, 0)), + ROW_BOAT_CRABCLAW("Rowboat to Hosidius", new WorldPoint(1780, 3417, 0)), + ROW_BOAT_DIVING_ISLAND("Rowboat to Barge/Camp/North of Island", new WorldPoint(3764, 3901, 0)), + ROW_BOAT_FISHING_GUILD("Rowboat to Hemenster", new WorldPoint(2598, 3426, 0)), + ROW_BOAT_GNOME_STRONGHOLD("Rowboat to Fishing Colony", new WorldPoint(2368, 3487, 0)), + ROW_BOAT_FISHING_COLONY("Rowboat to Gnome Stronghold", new WorldPoint(2356, 3641, 0)), + ROW_BOAT_HEMENSTER("Rowboat to Fishing Guild", new WorldPoint(2613, 3439, 0)), + ROW_BOAT_HOSIDIUS("Rowboat to Crabclaw Isle", new WorldPoint(1779, 3457, 0)), + ROW_BOAT_LITHKREN("Rowboat to Mushroom Forest", new WorldPoint(3582, 3973, 0)), + ROW_BOAT_LUMBRIDGE("Rowboat to Misthalin Mystery", new WorldPoint(3238, 3141, 0)), + ROW_BOAT_MOLCH("Rowboat to Molch Island/Shayzien/Battlefront", new WorldPoint(1343, 3646, 0)), + ROW_BOAT_MOLCH_ISLAND("Rowboat to Molch/Shayzien/Battlefront", new WorldPoint(1368, 3641, 0)), + ROW_BOAT_MORT("Rowboat to Mort Myre", new WorldPoint(3518, 3284, 0)), + ROW_BOAT_MORT_SWAMP("Rowboat to Mort'ton", new WorldPoint(3498, 3380, 0)), + ROW_BOAT_MUSEUM_CAMP("Rowboat to Barge/Digsite/North of Island", new WorldPoint(3723, 3807, 0)), + ROW_BOAT_MUSHROOM_FOREST_WEST("Rowboat to Lithkren", new WorldPoint(3659, 3849, 0)), + ROW_BOAT_MUSHROOM_FOREST_NE("Rowboat to Barge/Camp/Sea", new WorldPoint(3733, 3894, 0)), + ROW_BOAT_PORT_PHASMATYS_NORTH("Rowboat to Slepe", new WorldPoint(3670, 3545, 0)), + ROW_BOAT_PORT_PHASMATYS_EAST("Rowboat to Braindeath Island", new WorldPoint(3680, 3538, 0)), + ROW_BOAT_SHAYZIEN("Rowboat to Molch/Molch Island/Battlefront", new WorldPoint(1405, 3612, 0)), + ROW_BOAT_SLEPE("Rowboat to Port Phasmatys", new WorldPoint(3661, 3279, 0)), + OGRE_BOAT_FELDIP("Ogre Boat to Karamja", new WorldPoint(2653, 2964, 0)), + OGRE_BOAT_KARAMJA("Ogre Boat to Feldip", new WorldPoint(2757, 3085, 0)), + + //Charter ships + CHARTER_BRIMHAVEN("Charter Ship", new WorldPoint(2760, 3238, 0)), + CHARTER_CATHERBY("Charter Ship", new WorldPoint(2791, 3415, 0)), + CHARTER_CORSAIR_("Charter Ship", new WorldPoint(2589, 2851, 0)), + CHARTER_KARAMJA_NORTH("Charter Ship", new WorldPoint(2954, 3159, 0)), + CHARTER_KARAMJA_EAST("Charter Ship", new WorldPoint(2999, 3032, 0)), + CHARTER_KHAZARD("Charter Ship", new WorldPoint(2673, 3143, 0)), + CHARTER_MOSLE_HARMLESS("Charter Ship", new WorldPoint(3669, 2931, 0)), + CHARTER_PORT_PHASMATYS("Charter Ship", new WorldPoint(3702, 3503, 0)), + CHARTER_PORTSARIM("Charter Ship", new WorldPoint(3037, 3191, 0)), + CHARTER_TYRAS("Charter Ship", new WorldPoint(2141, 3123, 0)), + + //Minecarts/Carts + MINE_CART_ARCEUUS("Minecart", new WorldPoint(1673, 3832, 0)), + MINE_CART_GRANDEXCHANGE("Minecart to Keldagrim", new WorldPoint(3139, 3504, 0)), + MINE_CART_HOSIDIUS("Minecart", new WorldPoint(1656, 3542, 0)), + MINE_CART_KELDAGRIM("Minecart", new WorldPoint(2908, 10170, 0)), + MINE_CART_LOVAKENGJ("Minecart", new WorldPoint(1524, 3721, 0)), + MINE_CART_PORT_PISCARILIUS("Minecart", new WorldPoint(1760, 3708, 0)), + MINE_CART_QUIDAMORTEM("Minecart", new WorldPoint(1253, 3550, 0)), + MINE_CART_SHAYZIEN("Minecart", new WorldPoint(1586, 3622, 0)), + MINE_CART_TAVERLEY_UNDERGROUND("Minecart", new WorldPoint(2874, 9870, 0)), + CART_TO_BRIMHAVEN("Cart to Brimhaven", new WorldPoint(2833, 2958, 0)), + CART_TO_SHILO("Cart to Shilo", new WorldPoint(2780, 3214, 0)), + + //Canoes + CANOE_BARBVILLAGE("Canoe", new WorldPoint(3111, 3409, 0)), + CANOE_CHAMPIONSGUILD("Canoe", new WorldPoint(3202, 3344, 0)), + CANOE_EDGEVILLE("Canoe", new WorldPoint(3130, 3509, 0)), + CANOE_LUMBRIDGE("Canoe", new WorldPoint(3241, 3238, 0)), + + //Gnome Gliders + GNOME_GLIDER_KHARID("Gnome Glider", new WorldPoint(3278, 3213, 0)), + GNOME_GLIDER_APE_ATOLL("Gnome Glider", new WorldPoint(2712, 2804, 0)), + GNOME_GLIDER_KARAMJA("Gnome Glider", new WorldPoint(2971, 2974, 0)), + GNOME_GLIDER_FELDIP("Gnome Glider", new WorldPoint(2540, 2969, 0)), + GNOME_GLIDER_GNOMESTRONGHOLD("Gnome Glider", new WorldPoint(2460, 3502, 0)), + GNOME_GLIDER_WHITEWOLF("Gnome Glider", new WorldPoint(2845, 3501, 0)), + + //Balloons + BALLOON_VARROCK("Hot Air Balloon", new WorldPoint(3298, 3480, 0)), + BALLOON_YANILLE("Hot Air Balloon", new WorldPoint(2458, 3108, 0)), + BALLOON_GNOMESTRONGHOLD("Hot Air Balloon", new WorldPoint(2478, 3459, 0)), + BALLOON_TAVERLEY("Hot Air Balloon", new WorldPoint(2936, 3422, 0)), + BALLOON_FALADOR("Hot Air Balloon", new WorldPoint(2921, 3301, 0)), + + //Spirit Tree + SPIRITTREE_ARDOUGNE("Spirit Tree", new WorldPoint(2554, 3259, 0)), + SPIRITTREE_CORSAIR("Spirit Tree", new WorldPoint(2485, 2850, 0)), + SPIRITTREE_GNOMESTRONGHOLD("Spirit Tree", new WorldPoint(2459, 3446, 0)), + SPIRITTREE_GNOMEVILLAGE("Spirit Tree", new WorldPoint(2538, 3166, 0)), + SPIRITTREE_GRANDEXCHANGE("Spirit Tree", new WorldPoint(3184, 3510, 0)), + + //Carpets + CARPET_KHARID("Carpet to Bedabin/Pollnivneach/Uzer", new WorldPoint(3311, 3107, 0)), + CARPET_BEDABIN("Carpet to Shantay Pass", new WorldPoint(3183, 3042, 0)), + CARPET_POLLNIVNEACH_NORTH("Carpet to Shantay Pass", new WorldPoint(3351, 3001, 0)), + CARPET_POLLNIVNEACH_SOUTH("Carpet to Nardah/Sophanem/Menaphos", new WorldPoint(3345, 2943, 0)), + CARPET_NARDAH("Carpet to Pollnivneach", new WorldPoint(3399, 2916, 0)), + CARPET_SOPHANEM("Carpet to Pollnivneach", new WorldPoint(3288, 2814, 0)), + CARPET_MENAPHOS("Carpet to Pollnivneach", new WorldPoint(3244, 2812, 0)), + CARPET_UZER("Carpet to Shantay Pass", new WorldPoint(3468, 3111, 0)), + + //Teleports + TELEPORT_ARCHIVE_FROM_ARCEUUS("Teleport to Library Archive", new WorldPoint(1623, 3808, 0)), + TELEPORT_HARMLESS_FROM_HARMONY("Teleport to Mos Le'Harmless", new WorldPoint(3784, 2828, 0)), + TELEPORT_RUNE_ARDOUGNE("Teleport to Rune Essence", new WorldPoint(2681, 3325, 0)), + TELEPORT_RUNE_YANILLE("Teleport to Rune Essence", new WorldPoint(2592, 3089, 0)), + TELEPORT_SORCERESS_GARDEN("Teleport to Sorceress's Garden", new WorldPoint(3320, 3141, 0)), + + //Other + ALTER_KOUREND_UNDERGROUND("Altar to Skotizo", new WorldPoint(1662, 10047, 0)), + FAIRY_RING_ZANARIS_TO_KHARID("Fairy Ring to Al Kharid", new WorldPoint(2483, 4471, 0)), + FAIRY_RING_ZANARIS_TO_SHACK("Fairy Ring to Shack", new WorldPoint(2451, 4471, 0)), + MOUNTAIN_GUIDE_QUIDAMORTEM("Mountain Guide", new WorldPoint(1275, 3559, 0)), + MOUNTAIN_GUIDE_WALL("Mountain Guide", new WorldPoint(1400, 3538, 0)), + MUSHTREE_MUSHROOM_FOREST("Mushtree", new WorldPoint(3674, 3871, 0)), + MUSHTREE_TAR_SWAMP("Mushtree", new WorldPoint(3676, 3755, 0)), + MUSHTREE_VERDANT_VALLEY("Mushtree", new WorldPoint(3757, 3756, 0)), + MYTHS_GUILD_PORTAL("Portal to Guilds", new WorldPoint(2456, 2856, 0)), + TRAIN_KELDAGRIM("Railway Station", new WorldPoint(2941, 10179, 0)), + WILDERNESS_LEVER_ARDOUGNE("Wilderness Lever", new WorldPoint(2559, 3309, 0)), + WILDERNESS_LEVER_EDGEVILLE("Wilderness Lever", new WorldPoint(3088, 3474, 0)), + WILDERNESS_LEVER_WILDERNESS("Wilderness Lever", new WorldPoint(3154, 3924, 0)); + + private final String tooltip; + private final WorldPoint location; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java index 5fd38d5ff2..4392a64a54 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java @@ -1,274 +1,274 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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 HOLDER 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.worldmap; - -import com.google.inject.Inject; -import com.google.inject.Provides; -import java.awt.image.BufferedImage; -import java.util.Arrays; -import net.runelite.api.Client; -import net.runelite.api.Experience; -import net.runelite.api.Skill; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.ExperienceChanged; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.AgilityShortcut; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; -import net.runelite.client.util.ImageUtil; - -@PluginDescriptor( - name = "World Map", - description = "Enhance the world map to display additional information", - tags = {"agility", "fairy", "farming", "rings", "teleports"} -) -public class WorldMapPlugin extends Plugin -{ - static final BufferedImage BLANK_ICON; - private static final BufferedImage FAIRY_TRAVEL_ICON; - private static final BufferedImage NOPE_ICON; - - static final String CONFIG_KEY = "worldmap"; - static final String CONFIG_KEY_FAIRY_RING_TOOLTIPS = "fairyRingTooltips"; - static final String CONFIG_KEY_FAIRY_RING_ICON = "fairyRingIcon"; - static final String CONFIG_KEY_AGILITY_SHORTCUT_TOOLTIPS = "agilityShortcutTooltips"; - static final String CONFIG_KEY_AGILITY_SHORTCUT_LEVEL_ICON = "agilityShortcutIcon"; - static final String CONFIG_KEY_NORMAL_TELEPORT_ICON = "standardSpellbookIcon"; - static final String CONFIG_KEY_ANCIENT_TELEPORT_ICON = "ancientSpellbookIcon"; - static final String CONFIG_KEY_LUNAR_TELEPORT_ICON = "lunarSpellbookIcon"; - static final String CONFIG_KEY_ARCEUUS_TELEPORT_ICON = "arceuusSpellbookIcon"; - static final String CONFIG_KEY_JEWELLERY_TELEPORT_ICON = "jewelleryIcon"; - static final String CONFIG_KEY_SCROLL_TELEPORT_ICON = "scrollIcon"; - static final String CONFIG_KEY_MISC_TELEPORT_ICON = "miscellaneousTeleportIcon"; - static final String CONFIG_KEY_QUEST_START_TOOLTIPS = "questStartTooltips"; - static final String CONFIG_KEY_MINIGAME_TOOLTIP = "minigameTooltip"; - static final String CONFIG_KEY_FARMING_PATCH_TOOLTIPS = "farmingpatchTooltips"; - static final String CONFIG_KEY_RARE_TREE_TOOLTIPS = "rareTreeTooltips"; - static final String CONFIG_KEY_RARE_TREE_LEVEL_ICON = "rareTreeIcon"; - static final String CONFIG_KEY_TRANSPORATION_TELEPORT_TOOLTIPS = "transportationTooltips"; - - static - { - //A size of 17 gives us a buffer when triggering tooltips - final int iconBufferSize = 17; - - BLANK_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB); - - FAIRY_TRAVEL_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB); - final BufferedImage fairyTravelIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "fairy_ring_travel.png"); - FAIRY_TRAVEL_ICON.getGraphics().drawImage(fairyTravelIcon, 1, 1, null); - - NOPE_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB); - final BufferedImage nopeImage = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "nope_icon.png"); - NOPE_ICON.getGraphics().drawImage(nopeImage, 1, 1, null); - } - - @Inject - private Client client; - - @Inject - private WorldMapConfig config; - - @Inject - private WorldMapPointManager worldMapPointManager; - - private int agilityLevel = 0; - private int woodcuttingLevel = 0; - - @Provides - WorldMapConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(WorldMapConfig.class); - } - - @Override - protected void startUp() throws Exception - { - agilityLevel = client.getRealSkillLevel(Skill.AGILITY); - woodcuttingLevel = client.getRealSkillLevel(Skill.WOODCUTTING); - updateShownIcons(); - } - - @Override - protected void shutDown() throws Exception - { - worldMapPointManager.removeIf(FairyRingPoint.class::isInstance); - worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance); - worldMapPointManager.removeIf(QuestStartPoint.class::isInstance); - worldMapPointManager.removeIf(TeleportPoint.class::isInstance); - worldMapPointManager.removeIf(TransportationPoint.class::isInstance); - worldMapPointManager.removeIf(MinigamePoint.class::isInstance); - worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance); - worldMapPointManager.removeIf(RareTreePoint.class::isInstance); - agilityLevel = 0; - woodcuttingLevel = 0; - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (!event.getGroup().equals(CONFIG_KEY)) - { - return; - } - - updateShownIcons(); - } - - @Subscribe - public void onExperienceChanged(ExperienceChanged event) - { - if (event.getSkill() == Skill.AGILITY) - { - int newAgilityLevel = Experience.getLevelForXp(client.getSkillExperience(Skill.AGILITY)); - if (newAgilityLevel != agilityLevel) - { - agilityLevel = newAgilityLevel; - updateAgilityIcons(); - } - } - - if (event.getSkill() == Skill.WOODCUTTING) - { - int newWoodcutLevel = Experience.getLevelForXp(client.getSkillExperience(Skill.WOODCUTTING)); - if (newWoodcutLevel != woodcuttingLevel) - { - woodcuttingLevel = newWoodcutLevel; - updateRareTreeIcons(); - } - } - } - - private void updateAgilityIcons() - { - worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance); - - if (config.agilityShortcutLevelIcon() || config.agilityShortcutTooltips()) - { - Arrays.stream(AgilityShortcut.values()) - .filter(value -> value.getWorldMapLocation() != null) - .map(value -> new AgilityShortcutPoint(value, - agilityLevel > 0 && config.agilityShortcutLevelIcon() && value.getLevel() > agilityLevel ? NOPE_ICON : BLANK_ICON, - config.agilityShortcutTooltips())) - .forEach(worldMapPointManager::add); - } - } - - private void updateRareTreeIcons() - { - worldMapPointManager.removeIf(RareTreePoint.class::isInstance); - - if (config.rareTreeLevelIcon() || config.rareTreeTooltips()) - { - Arrays.stream(RareTreeLocation.values()).forEach(rareTree -> - Arrays.stream(rareTree.getLocations()) - .map(point -> new RareTreePoint(point, - rareTree.getTooltip(), - woodcuttingLevel > 0 && config.rareTreeLevelIcon() && - rareTree.getLevelReq() > woodcuttingLevel ? NOPE_ICON : BLANK_ICON, - config.rareTreeTooltips())) - .forEach(worldMapPointManager::add)); - } - } - - private void updateShownIcons() - { - updateAgilityIcons(); - updateRareTreeIcons(); - - worldMapPointManager.removeIf(FairyRingPoint.class::isInstance); - if (config.fairyRingIcon() || config.fairyRingTooltips()) - { - Arrays.stream(FairyRingLocation.values()) - .map(value -> new FairyRingPoint(value, - config.fairyRingIcon() ? FAIRY_TRAVEL_ICON : BLANK_ICON, - config.fairyRingTooltips())) - .forEach(worldMapPointManager::add); - } - - worldMapPointManager.removeIf(MinigamePoint.class::isInstance); - if (config.minigameTooltip()) - { - Arrays.stream(MinigameLocation.values()) - .map(value -> new MinigamePoint(value, BLANK_ICON)) - .forEach(worldMapPointManager::add); - } - - worldMapPointManager.removeIf(QuestStartPoint.class::isInstance); - if (config.questStartTooltips()) - { - Arrays.stream(QuestStartLocation.values()) - .map(value -> new QuestStartPoint(value, BLANK_ICON)) - .forEach(worldMapPointManager::add); - } - - worldMapPointManager.removeIf(TransportationPoint.class::isInstance); - if (config.transportationTeleportTooltips()) - { - Arrays.stream(TransportationPointLocation.values()) - .map(value -> new TransportationPoint(value, BLANK_ICON)) - .forEach((worldMapPointManager::add)); - } - - worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance); - if (config.farmingPatchTooltips()) - { - Arrays.stream(FarmingPatchLocation.values()).forEach(location -> - Arrays.stream(location.getLocations()) - .map(point -> new FarmingPatchPoint(point, location.getTooltip(), BLANK_ICON)) - .forEach(worldMapPointManager::add) - ); - } - - worldMapPointManager.removeIf(TeleportPoint.class::isInstance); - Arrays.stream(TeleportLocationData.values()) - .filter(data -> - { - switch (data.getType()) - { - case NORMAL_MAGIC: - return config.normalTeleportIcon(); - case ANCIENT_MAGICKS: - return config.ancientTeleportIcon(); - case LUNAR_MAGIC: - return config.lunarTeleportIcon(); - case ARCEUUS_MAGIC: - return config.arceuusTeleportIcon(); - case JEWELLERY: - return config.jewelleryTeleportIcon(); - case SCROLL: - return config.scrollTeleportIcon(); - case OTHER: - return config.miscellaneousTeleportIcon(); - default: - return false; - } - }).map(TeleportPoint::new) - .forEach(worldMapPointManager::add); - } -} +/* + * Copyright (c) 2018, Morgan Lewis + * 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 HOLDER 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.worldmap; + +import com.google.inject.Inject; +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import java.util.Arrays; +import net.runelite.api.Client; +import net.runelite.api.Experience; +import net.runelite.api.Skill; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.ExperienceChanged; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.AgilityShortcut; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; +import net.runelite.client.util.ImageUtil; + +@PluginDescriptor( + name = "World Map", + description = "Enhance the world map to display additional information", + tags = {"agility", "fairy", "farming", "rings", "teleports"} +) +public class WorldMapPlugin extends Plugin +{ + static final BufferedImage BLANK_ICON; + private static final BufferedImage FAIRY_TRAVEL_ICON; + private static final BufferedImage NOPE_ICON; + + static final String CONFIG_KEY = "worldmap"; + static final String CONFIG_KEY_FAIRY_RING_TOOLTIPS = "fairyRingTooltips"; + static final String CONFIG_KEY_FAIRY_RING_ICON = "fairyRingIcon"; + static final String CONFIG_KEY_AGILITY_SHORTCUT_TOOLTIPS = "agilityShortcutTooltips"; + static final String CONFIG_KEY_AGILITY_SHORTCUT_LEVEL_ICON = "agilityShortcutIcon"; + static final String CONFIG_KEY_NORMAL_TELEPORT_ICON = "standardSpellbookIcon"; + static final String CONFIG_KEY_ANCIENT_TELEPORT_ICON = "ancientSpellbookIcon"; + static final String CONFIG_KEY_LUNAR_TELEPORT_ICON = "lunarSpellbookIcon"; + static final String CONFIG_KEY_ARCEUUS_TELEPORT_ICON = "arceuusSpellbookIcon"; + static final String CONFIG_KEY_JEWELLERY_TELEPORT_ICON = "jewelleryIcon"; + static final String CONFIG_KEY_SCROLL_TELEPORT_ICON = "scrollIcon"; + static final String CONFIG_KEY_MISC_TELEPORT_ICON = "miscellaneousTeleportIcon"; + static final String CONFIG_KEY_QUEST_START_TOOLTIPS = "questStartTooltips"; + static final String CONFIG_KEY_MINIGAME_TOOLTIP = "minigameTooltip"; + static final String CONFIG_KEY_FARMING_PATCH_TOOLTIPS = "farmingpatchTooltips"; + static final String CONFIG_KEY_RARE_TREE_TOOLTIPS = "rareTreeTooltips"; + static final String CONFIG_KEY_RARE_TREE_LEVEL_ICON = "rareTreeIcon"; + static final String CONFIG_KEY_TRANSPORATION_TELEPORT_TOOLTIPS = "transportationTooltips"; + + static + { + //A size of 17 gives us a buffer when triggering tooltips + final int iconBufferSize = 17; + + BLANK_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB); + + FAIRY_TRAVEL_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB); + final BufferedImage fairyTravelIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "fairy_ring_travel.png"); + FAIRY_TRAVEL_ICON.getGraphics().drawImage(fairyTravelIcon, 1, 1, null); + + NOPE_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB); + final BufferedImage nopeImage = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "nope_icon.png"); + NOPE_ICON.getGraphics().drawImage(nopeImage, 1, 1, null); + } + + @Inject + private Client client; + + @Inject + private WorldMapConfig config; + + @Inject + private WorldMapPointManager worldMapPointManager; + + private int agilityLevel = 0; + private int woodcuttingLevel = 0; + + @Provides + WorldMapConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(WorldMapConfig.class); + } + + @Override + protected void startUp() throws Exception + { + agilityLevel = client.getRealSkillLevel(Skill.AGILITY); + woodcuttingLevel = client.getRealSkillLevel(Skill.WOODCUTTING); + updateShownIcons(); + } + + @Override + protected void shutDown() throws Exception + { + worldMapPointManager.removeIf(FairyRingPoint.class::isInstance); + worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance); + worldMapPointManager.removeIf(QuestStartPoint.class::isInstance); + worldMapPointManager.removeIf(TeleportPoint.class::isInstance); + worldMapPointManager.removeIf(TransportationPoint.class::isInstance); + worldMapPointManager.removeIf(MinigamePoint.class::isInstance); + worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance); + worldMapPointManager.removeIf(RareTreePoint.class::isInstance); + agilityLevel = 0; + woodcuttingLevel = 0; + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!event.getGroup().equals(CONFIG_KEY)) + { + return; + } + + updateShownIcons(); + } + + @Subscribe + public void onExperienceChanged(ExperienceChanged event) + { + if (event.getSkill() == Skill.AGILITY) + { + int newAgilityLevel = Experience.getLevelForXp(client.getSkillExperience(Skill.AGILITY)); + if (newAgilityLevel != agilityLevel) + { + agilityLevel = newAgilityLevel; + updateAgilityIcons(); + } + } + + if (event.getSkill() == Skill.WOODCUTTING) + { + int newWoodcutLevel = Experience.getLevelForXp(client.getSkillExperience(Skill.WOODCUTTING)); + if (newWoodcutLevel != woodcuttingLevel) + { + woodcuttingLevel = newWoodcutLevel; + updateRareTreeIcons(); + } + } + } + + private void updateAgilityIcons() + { + worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance); + + if (config.agilityShortcutLevelIcon() || config.agilityShortcutTooltips()) + { + Arrays.stream(AgilityShortcut.values()) + .filter(value -> value.getWorldMapLocation() != null) + .map(value -> new AgilityShortcutPoint(value, + agilityLevel > 0 && config.agilityShortcutLevelIcon() && value.getLevel() > agilityLevel ? NOPE_ICON : BLANK_ICON, + config.agilityShortcutTooltips())) + .forEach(worldMapPointManager::add); + } + } + + private void updateRareTreeIcons() + { + worldMapPointManager.removeIf(RareTreePoint.class::isInstance); + + if (config.rareTreeLevelIcon() || config.rareTreeTooltips()) + { + Arrays.stream(RareTreeLocation.values()).forEach(rareTree -> + Arrays.stream(rareTree.getLocations()) + .map(point -> new RareTreePoint(point, + rareTree.getTooltip(), + woodcuttingLevel > 0 && config.rareTreeLevelIcon() && + rareTree.getLevelReq() > woodcuttingLevel ? NOPE_ICON : BLANK_ICON, + config.rareTreeTooltips())) + .forEach(worldMapPointManager::add)); + } + } + + private void updateShownIcons() + { + updateAgilityIcons(); + updateRareTreeIcons(); + + worldMapPointManager.removeIf(FairyRingPoint.class::isInstance); + if (config.fairyRingIcon() || config.fairyRingTooltips()) + { + Arrays.stream(FairyRingLocation.values()) + .map(value -> new FairyRingPoint(value, + config.fairyRingIcon() ? FAIRY_TRAVEL_ICON : BLANK_ICON, + config.fairyRingTooltips())) + .forEach(worldMapPointManager::add); + } + + worldMapPointManager.removeIf(MinigamePoint.class::isInstance); + if (config.minigameTooltip()) + { + Arrays.stream(MinigameLocation.values()) + .map(value -> new MinigamePoint(value, BLANK_ICON)) + .forEach(worldMapPointManager::add); + } + + worldMapPointManager.removeIf(QuestStartPoint.class::isInstance); + if (config.questStartTooltips()) + { + Arrays.stream(QuestStartLocation.values()) + .map(value -> new QuestStartPoint(value, BLANK_ICON)) + .forEach(worldMapPointManager::add); + } + + worldMapPointManager.removeIf(TransportationPoint.class::isInstance); + if (config.transportationTeleportTooltips()) + { + Arrays.stream(TransportationPointLocation.values()) + .map(value -> new TransportationPoint(value, BLANK_ICON)) + .forEach((worldMapPointManager::add)); + } + + worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance); + if (config.farmingPatchTooltips()) + { + Arrays.stream(FarmingPatchLocation.values()).forEach(location -> + Arrays.stream(location.getLocations()) + .map(point -> new FarmingPatchPoint(point, location.getTooltip(), BLANK_ICON)) + .forEach(worldMapPointManager::add) + ); + } + + worldMapPointManager.removeIf(TeleportPoint.class::isInstance); + Arrays.stream(TeleportLocationData.values()) + .filter(data -> + { + switch (data.getType()) + { + case NORMAL_MAGIC: + return config.normalTeleportIcon(); + case ANCIENT_MAGICKS: + return config.ancientTeleportIcon(); + case LUNAR_MAGIC: + return config.lunarTeleportIcon(); + case ARCEUUS_MAGIC: + return config.arceuusTeleportIcon(); + case JEWELLERY: + return config.jewelleryTeleportIcon(); + case SCROLL: + return config.scrollTeleportIcon(); + case OTHER: + return config.miscellaneousTeleportIcon(); + default: + return false; + } + }).map(TeleportPoint::new) + .forEach(worldMapPointManager::add); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java index ea2aabc2b5..3cd1489d9e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java @@ -1,187 +1,187 @@ -/* - * Copyright (c) 2017, Steve - * 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.xpglobes; - -import com.google.inject.Provides; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.Experience; -import net.runelite.api.Skill; -import net.runelite.api.events.ExperienceChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDependency; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.xptracker.XpTrackerPlugin; -import net.runelite.client.task.Schedule; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "XP Globes", - description = "Show XP globes for the respective skill when gaining XP", - tags = {"experience", "levels", "overlay"}, - enabledByDefault = false -) -@PluginDependency(XpTrackerPlugin.class) -public class XpGlobesPlugin extends Plugin -{ - private static final int MAXIMUM_SHOWN_GLOBES = 5; - - private XpGlobe[] globeCache = new XpGlobe[Skill.values().length - 1]; //overall does not trigger xp change event - - @Getter - private final List xpGlobes = new ArrayList<>(); - - @Inject - private Client client; - - @Inject - private XpGlobesConfig config; - - @Inject - private OverlayManager overlayManager; - - @Inject - private XpGlobesOverlay overlay; - - @Provides - XpGlobesConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(XpGlobesConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - } - - @Subscribe - public void onExperienceChanged(ExperienceChanged event) - { - Skill skill = event.getSkill(); - int currentXp = client.getSkillExperience(skill); - int currentLevel = Experience.getLevelForXp(currentXp); - int skillIdx = skill.ordinal(); - XpGlobe cachedGlobe = globeCache[skillIdx]; - - // ExperienceChanged event occurs when stats drain/boost check we have an change to actual xp - if (cachedGlobe != null && (cachedGlobe.getCurrentXp() >= currentXp)) - { - return; - } - - if (config.hideMaxed() && currentLevel >= Experience.MAX_REAL_LEVEL) - { - return; - } - - if (cachedGlobe != null) - { - cachedGlobe.setSkill(skill); - cachedGlobe.setCurrentXp(currentXp); - cachedGlobe.setCurrentLevel(currentLevel); - cachedGlobe.setTime(Instant.now()); - this.addXpGlobe(globeCache[skillIdx], MAXIMUM_SHOWN_GLOBES); - } - else - { - // dont draw non cached globes, this is triggered on login to setup all of the initial values - globeCache[skillIdx] = new XpGlobe(skill, currentXp, currentLevel, Instant.now()); - } - } - - private void addXpGlobe(XpGlobe xpGlobe, int maxLength) - { - //remove the old globe, allowing it to be readded as the most recent (right) side when drawn - xpGlobes.remove(xpGlobe); - if (getXpGlobesSize() >= maxLength) - { - xpGlobes.remove(0); - } - xpGlobes.add(xpGlobe); - } - - int getXpGlobesSize() - { - return xpGlobes.size(); - } - - @Schedule( - period = 1, - unit = ChronoUnit.SECONDS - ) - public void removeExpiredXpGlobes() - { - if (!xpGlobes.isEmpty()) - { - Instant currentTime = Instant.now(); - for (Iterator it = xpGlobes.iterator(); it.hasNext();) - { - XpGlobe globe = it.next(); - Instant globeCreationTime = globe.getTime(); - if (currentTime.isBefore(globeCreationTime.plusSeconds(config.xpOrbDuration()))) - { - //if a globe is not expired, stop checking newer globes - return; - } - it.remove(); - } - } - } - - private void resetGlobeState() - { - xpGlobes.clear(); - globeCache = new XpGlobe[Skill.values().length - 1]; - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - switch (event.getGameState()) - { - case HOPPING: - case LOGGING_IN: - resetGlobeState(); - break; - } - } - -} +/* + * Copyright (c) 2017, Steve + * 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.xpglobes; + +import com.google.inject.Provides; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Experience; +import net.runelite.api.Skill; +import net.runelite.api.events.ExperienceChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDependency; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.xptracker.XpTrackerPlugin; +import net.runelite.client.task.Schedule; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "XP Globes", + description = "Show XP globes for the respective skill when gaining XP", + tags = {"experience", "levels", "overlay"}, + enabledByDefault = false +) +@PluginDependency(XpTrackerPlugin.class) +public class XpGlobesPlugin extends Plugin +{ + private static final int MAXIMUM_SHOWN_GLOBES = 5; + + private XpGlobe[] globeCache = new XpGlobe[Skill.values().length - 1]; //overall does not trigger xp change event + + @Getter + private final List xpGlobes = new ArrayList<>(); + + @Inject + private Client client; + + @Inject + private XpGlobesConfig config; + + @Inject + private OverlayManager overlayManager; + + @Inject + private XpGlobesOverlay overlay; + + @Provides + XpGlobesConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(XpGlobesConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + } + + @Subscribe + public void onExperienceChanged(ExperienceChanged event) + { + Skill skill = event.getSkill(); + int currentXp = client.getSkillExperience(skill); + int currentLevel = Experience.getLevelForXp(currentXp); + int skillIdx = skill.ordinal(); + XpGlobe cachedGlobe = globeCache[skillIdx]; + + // ExperienceChanged event occurs when stats drain/boost check we have an change to actual xp + if (cachedGlobe != null && (cachedGlobe.getCurrentXp() >= currentXp)) + { + return; + } + + if (config.hideMaxed() && currentLevel >= Experience.MAX_REAL_LEVEL) + { + return; + } + + if (cachedGlobe != null) + { + cachedGlobe.setSkill(skill); + cachedGlobe.setCurrentXp(currentXp); + cachedGlobe.setCurrentLevel(currentLevel); + cachedGlobe.setTime(Instant.now()); + this.addXpGlobe(globeCache[skillIdx], MAXIMUM_SHOWN_GLOBES); + } + else + { + // dont draw non cached globes, this is triggered on login to setup all of the initial values + globeCache[skillIdx] = new XpGlobe(skill, currentXp, currentLevel, Instant.now()); + } + } + + private void addXpGlobe(XpGlobe xpGlobe, int maxLength) + { + //remove the old globe, allowing it to be readded as the most recent (right) side when drawn + xpGlobes.remove(xpGlobe); + if (getXpGlobesSize() >= maxLength) + { + xpGlobes.remove(0); + } + xpGlobes.add(xpGlobe); + } + + int getXpGlobesSize() + { + return xpGlobes.size(); + } + + @Schedule( + period = 1, + unit = ChronoUnit.SECONDS + ) + public void removeExpiredXpGlobes() + { + if (!xpGlobes.isEmpty()) + { + Instant currentTime = Instant.now(); + for (Iterator it = xpGlobes.iterator(); it.hasNext(); ) + { + XpGlobe globe = it.next(); + Instant globeCreationTime = globe.getTime(); + if (currentTime.isBefore(globeCreationTime.plusSeconds(config.xpOrbDuration()))) + { + //if a globe is not expired, stop checking newer globes + return; + } + it.remove(); + } + } + } + + private void resetGlobeState() + { + xpGlobes.clear(); + globeCache = new XpGlobe[Skill.values().length - 1]; + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + switch (event.getGameState()) + { + case HOPPING: + case LOGGING_IN: + resetGlobeState(); + break; + } + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java index 5ff11871e5..3455af4916 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -33,10 +33,12 @@ import java.awt.image.BufferedImage; import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.Experience; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; import net.runelite.api.Skill; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.SkillColor; import net.runelite.client.ui.overlay.Overlay; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; @@ -45,8 +47,6 @@ import net.runelite.client.ui.overlay.components.PanelComponent; import net.runelite.client.ui.overlay.components.ProgressBarComponent; import net.runelite.client.ui.overlay.components.SplitComponent; import net.runelite.client.util.StackFormatter; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; -import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; class XpInfoBoxOverlay extends Overlay { @@ -126,23 +126,23 @@ class XpInfoBoxOverlay extends Overlay .build(); final LineComponent xpHour = LineComponent.builder() - .left("XP/Hour:") - .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour(), true)) - .build(); + .left("XP/Hour:") + .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour(), true)) + .build(); final SplitComponent xpSplit = SplitComponent.builder() - .first(xpLine) - .second(xpHour) - .orientation(ComponentOrientation.VERTICAL) - .build(); + .first(xpLine) + .second(xpHour) + .orientation(ComponentOrientation.VERTICAL) + .build(); final ImageComponent imageComponent = new ImageComponent(icon); final SplitComponent iconXpSplit = SplitComponent.builder() - .first(imageComponent) - .second(xpSplit) - .orientation(ComponentOrientation.HORIZONTAL) - .gap(new Point(XP_AND_ICON_GAP, 0)) - .build(); + .first(imageComponent) + .second(xpSplit) + .orientation(ComponentOrientation.HORIZONTAL) + .gap(new Point(XP_AND_ICON_GAP, 0)) + .build(); iconXpSplitPanel.getChildren().add(iconXpSplit); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java index 16602b0cb4..4bf50a75f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java @@ -1,233 +1,240 @@ -/* - * Copyright (c) 2018, Levi - * 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.xptracker; - -import java.util.EnumMap; -import java.util.Map; -import lombok.NonNull; -import net.runelite.api.NPC; -import net.runelite.api.Skill; - -/** - * Internal state for the XpTrackerPlugin - * - * Note: This class's operations are not currently synchronized. - * It is intended to be called by the XpTrackerPlugin on the client thread. - */ -class XpState -{ - private static final double DEFAULT_XP_MODIFIER = 4.0; - private static final double SHARED_XP_MODIFIER = DEFAULT_XP_MODIFIER / 3.0; - private final Map xpSkills = new EnumMap<>(Skill.class); - private NPC interactedNPC; - - /** - * Destroys all internal state, however any XpSnapshotSingle or XpSnapshotTotal remain unaffected. - */ - void reset() - { - xpSkills.clear(); - } - - /** - * Resets a single skill - * @param skill Skill to reset - * @param currentXp Current XP to set to, if unknown set to -1 - */ - void resetSkill(Skill skill, long currentXp) - { - xpSkills.remove(skill); - xpSkills.put(skill, new XpStateSingle(skill, currentXp)); - } - - /** - * Updates a skill with the current known XP. - * When the result of this operation is XpUpdateResult.UPDATED, the UI should be updated accordingly. - * This is to distinguish events that reload all the skill's current values (such as world hopping) - * and also first-login when the skills are not initialized (the start XP will be -1 in this case). - * @param skill Skill to update - * @param currentXp Current known XP for this skill - * @param goalStartXp Possible XP start goal - * @param goalEndXp Possible XP end goal - * @return Whether or not the skill has been initialized, there was no change, or it has been updated - */ - XpUpdateResult updateSkill(Skill skill, long currentXp, int goalStartXp, int goalEndXp) - { - XpStateSingle state = getSkill(skill); - - if (state.getStartXp() == -1) - { - if (currentXp >= 0) - { - initializeSkill(skill, currentXp); - return XpUpdateResult.INITIALIZED; - } - else - { - return XpUpdateResult.NO_CHANGE; - } - } - else - { - long startXp = state.getStartXp(); - int gainedXp = state.getXpGained(); - - if (startXp + gainedXp > currentXp) - { - // Reinitialize with lesser currentXp, this can happen with negative xp lamps - initializeSkill(skill, currentXp); - return XpUpdateResult.INITIALIZED; - } - else - { - return state.update(currentXp, goalStartXp, goalEndXp) ? XpUpdateResult.UPDATED : XpUpdateResult.NO_CHANGE; - } - } - } - - private double getCombatXPModifier(Skill skill) - { - if (skill == Skill.HITPOINTS) - { - return SHARED_XP_MODIFIER; - } - - return DEFAULT_XP_MODIFIER; - } - - /** - * Updates skill with average actions based on currently interacted NPC. - * @param skill experience gained skill - * @param npc currently interacted NPC - * @param npcHealth health of currently interacted NPC - */ - void updateNpcExperience(Skill skill, NPC npc, Integer npcHealth) - { - if (npc == null || npc.getCombatLevel() <= 0 || npcHealth == null) - { - return; - } - - final XpStateSingle state = getSkill(skill); - final int actionExp = (int) (npcHealth * getCombatXPModifier(skill)); - final XpAction action = state.getXpAction(XpActionType.ACTOR_HEALTH); - - if (action.isActionsHistoryInitialized()) - { - action.getActionExps()[action.getActionExpIndex()] = actionExp; - - if (interactedNPC != npc) - { - action.setActionExpIndex((action.getActionExpIndex() + 1) % action.getActionExps().length); - } - } - else - { - // So we have a decent average off the bat, lets populate all values with what we see. - for (int i = 0; i < action.getActionExps().length; i++) - { - action.getActionExps()[i] = actionExp; - } - - action.setActionsHistoryInitialized(true); - } - - interactedNPC = npc; - state.setActionType(XpActionType.ACTOR_HEALTH); - } - - /** - * Update number of actions performed for skill (e.g amount of kills in this case) if last interacted - * NPC died - * @param skill skill to update actions for - * @param npc npc that just died - * @param npcHealth max health of npc that just died - * @return UPDATED in case new kill was successfully added - */ - XpUpdateResult updateNpcKills(Skill skill, NPC npc, Integer npcHealth) - { - XpStateSingle state = getSkill(skill); - - if (state.getXpGained() <= 0 || npcHealth == null || npc != interactedNPC) - { - return XpUpdateResult.NO_CHANGE; - } - - final XpAction xpAction = state.getXpAction(XpActionType.ACTOR_HEALTH); - xpAction.setActions(xpAction.getActions() + 1); - return xpAction.isActionsHistoryInitialized() ? XpUpdateResult.UPDATED : XpUpdateResult.NO_CHANGE; - } - - void tick(Skill skill, long delta) - { - getSkill(skill).tick(delta); - } - - /** - * Forcefully initialize a skill with a known start XP from the current XP. - * This is used in resetAndInitState by the plugin. It should not result in showing the XP in the UI. - * @param skill Skill to initialize - * @param currentXp Current known XP for the skill - */ - void initializeSkill(Skill skill, long currentXp) - { - xpSkills.put(skill, new XpStateSingle(skill, currentXp)); - } - - boolean isInitialized(Skill skill) - { - XpStateSingle xpStateSingle = xpSkills.get(skill); - return xpStateSingle != null && xpStateSingle.getStartXp() != -1; - } - - @NonNull - XpStateSingle getSkill(Skill skill) - { - return xpSkills.computeIfAbsent(skill, (s) -> new XpStateSingle(s, -1)); - } - - /** - * Obtain an immutable snapshot of the provided skill - * intended for use with the UI which operates on another thread - * @param skill Skill to obtain the snapshot for - * @return An immutable snapshot of the specified skill for this session since first login or last reset - */ - @NonNull - XpSnapshotSingle getSkillSnapshot(Skill skill) - { - return getSkill(skill).snapshot(); - } - - /** - * Obtain an immutable snapshot of the provided skill - * intended for use with the UI which operates on another thread - * @return An immutable snapshot of total information for this session since first login or last reset - */ - @NonNull - XpSnapshotSingle getTotalSnapshot() - { - return getSkill(Skill.OVERALL).snapshot(); - } -} +/* + * Copyright (c) 2018, Levi + * 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.xptracker; + +import java.util.EnumMap; +import java.util.Map; +import lombok.NonNull; +import net.runelite.api.NPC; +import net.runelite.api.Skill; + +/** + * Internal state for the XpTrackerPlugin + *

+ * Note: This class's operations are not currently synchronized. + * It is intended to be called by the XpTrackerPlugin on the client thread. + */ +class XpState +{ + private static final double DEFAULT_XP_MODIFIER = 4.0; + private static final double SHARED_XP_MODIFIER = DEFAULT_XP_MODIFIER / 3.0; + private final Map xpSkills = new EnumMap<>(Skill.class); + private NPC interactedNPC; + + /** + * Destroys all internal state, however any XpSnapshotSingle or XpSnapshotTotal remain unaffected. + */ + void reset() + { + xpSkills.clear(); + } + + /** + * Resets a single skill + * + * @param skill Skill to reset + * @param currentXp Current XP to set to, if unknown set to -1 + */ + void resetSkill(Skill skill, long currentXp) + { + xpSkills.remove(skill); + xpSkills.put(skill, new XpStateSingle(skill, currentXp)); + } + + /** + * Updates a skill with the current known XP. + * When the result of this operation is XpUpdateResult.UPDATED, the UI should be updated accordingly. + * This is to distinguish events that reload all the skill's current values (such as world hopping) + * and also first-login when the skills are not initialized (the start XP will be -1 in this case). + * + * @param skill Skill to update + * @param currentXp Current known XP for this skill + * @param goalStartXp Possible XP start goal + * @param goalEndXp Possible XP end goal + * @return Whether or not the skill has been initialized, there was no change, or it has been updated + */ + XpUpdateResult updateSkill(Skill skill, long currentXp, int goalStartXp, int goalEndXp) + { + XpStateSingle state = getSkill(skill); + + if (state.getStartXp() == -1) + { + if (currentXp >= 0) + { + initializeSkill(skill, currentXp); + return XpUpdateResult.INITIALIZED; + } + else + { + return XpUpdateResult.NO_CHANGE; + } + } + else + { + long startXp = state.getStartXp(); + int gainedXp = state.getXpGained(); + + if (startXp + gainedXp > currentXp) + { + // Reinitialize with lesser currentXp, this can happen with negative xp lamps + initializeSkill(skill, currentXp); + return XpUpdateResult.INITIALIZED; + } + else + { + return state.update(currentXp, goalStartXp, goalEndXp) ? XpUpdateResult.UPDATED : XpUpdateResult.NO_CHANGE; + } + } + } + + private double getCombatXPModifier(Skill skill) + { + if (skill == Skill.HITPOINTS) + { + return SHARED_XP_MODIFIER; + } + + return DEFAULT_XP_MODIFIER; + } + + /** + * Updates skill with average actions based on currently interacted NPC. + * + * @param skill experience gained skill + * @param npc currently interacted NPC + * @param npcHealth health of currently interacted NPC + */ + void updateNpcExperience(Skill skill, NPC npc, Integer npcHealth) + { + if (npc == null || npc.getCombatLevel() <= 0 || npcHealth == null) + { + return; + } + + final XpStateSingle state = getSkill(skill); + final int actionExp = (int) (npcHealth * getCombatXPModifier(skill)); + final XpAction action = state.getXpAction(XpActionType.ACTOR_HEALTH); + + if (action.isActionsHistoryInitialized()) + { + action.getActionExps()[action.getActionExpIndex()] = actionExp; + + if (interactedNPC != npc) + { + action.setActionExpIndex((action.getActionExpIndex() + 1) % action.getActionExps().length); + } + } + else + { + // So we have a decent average off the bat, lets populate all values with what we see. + for (int i = 0; i < action.getActionExps().length; i++) + { + action.getActionExps()[i] = actionExp; + } + + action.setActionsHistoryInitialized(true); + } + + interactedNPC = npc; + state.setActionType(XpActionType.ACTOR_HEALTH); + } + + /** + * Update number of actions performed for skill (e.g amount of kills in this case) if last interacted + * NPC died + * + * @param skill skill to update actions for + * @param npc npc that just died + * @param npcHealth max health of npc that just died + * @return UPDATED in case new kill was successfully added + */ + XpUpdateResult updateNpcKills(Skill skill, NPC npc, Integer npcHealth) + { + XpStateSingle state = getSkill(skill); + + if (state.getXpGained() <= 0 || npcHealth == null || npc != interactedNPC) + { + return XpUpdateResult.NO_CHANGE; + } + + final XpAction xpAction = state.getXpAction(XpActionType.ACTOR_HEALTH); + xpAction.setActions(xpAction.getActions() + 1); + return xpAction.isActionsHistoryInitialized() ? XpUpdateResult.UPDATED : XpUpdateResult.NO_CHANGE; + } + + void tick(Skill skill, long delta) + { + getSkill(skill).tick(delta); + } + + /** + * Forcefully initialize a skill with a known start XP from the current XP. + * This is used in resetAndInitState by the plugin. It should not result in showing the XP in the UI. + * + * @param skill Skill to initialize + * @param currentXp Current known XP for the skill + */ + void initializeSkill(Skill skill, long currentXp) + { + xpSkills.put(skill, new XpStateSingle(skill, currentXp)); + } + + boolean isInitialized(Skill skill) + { + XpStateSingle xpStateSingle = xpSkills.get(skill); + return xpStateSingle != null && xpStateSingle.getStartXp() != -1; + } + + @NonNull + XpStateSingle getSkill(Skill skill) + { + return xpSkills.computeIfAbsent(skill, (s) -> new XpStateSingle(s, -1)); + } + + /** + * Obtain an immutable snapshot of the provided skill + * intended for use with the UI which operates on another thread + * + * @param skill Skill to obtain the snapshot for + * @return An immutable snapshot of the specified skill for this session since first login or last reset + */ + @NonNull + XpSnapshotSingle getSkillSnapshot(Skill skill) + { + return getSkill(skill).snapshot(); + } + + /** + * Obtain an immutable snapshot of the provided skill + * intended for use with the UI which operates on another thread + * + * @return An immutable snapshot of total information for this session since first login or last reset + */ + @NonNull + XpSnapshotSingle getTotalSnapshot() + { + return getSkill(Skill.OVERALL).snapshot(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index 7d3006ddc9..3baf12962e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -275,6 +275,7 @@ public class XpTrackerPlugin extends Plugin /** * Reset an individual skill with the client's current known state of the skill * Will also clear the skill from the UI. + * * @param skill Skill to reset */ void resetSkillState(Skill skill) @@ -287,6 +288,7 @@ public class XpTrackerPlugin extends Plugin /** * Reset all skills except for the one provided + * * @param skill Skill to ignore during reset */ void resetOtherSkillState(Skill skill) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java index e799837e67..a1961b2085 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java @@ -52,7 +52,7 @@ public class ZoomPlugin extends Plugin implements KeyListener { /** * The largest (most zoomed in) value that can be used without the client crashing. - * + *

* Larger values trigger an overflow in the engine's fov to scale code. */ private static final int INNER_ZOOM_LIMIT = 1004; @@ -90,7 +90,7 @@ public class ZoomPlugin extends Plugin implements KeyListener int[] intStack = client.getIntStack(); int intStackSize = client.getIntStackSize(); - if ("scrollWheelZoom".equals(event.getEventName()) && zoomConfig.controlFunction() == ControlFunction.CONTROL_TO_ZOOM && !controlDown) + if ("scrollWheelZoom".equals(event.getEventName()) && zoomConfig.controlFunction() == ControlFunction.CONTROL_TO_ZOOM && !controlDown) { intStack[intStackSize - 1] = 1; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/BloatTimerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/BloatTimerOverlay.java index 731604122a..698203f54c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/BloatTimerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/BloatTimerOverlay.java @@ -1,102 +1,105 @@ -package net.runelite.client.plugins.ztob; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Polygon; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.OverlayUtil; - -public class BloatTimerOverlay extends Overlay { - - private final Client client; - private final TheatrePlugin plugin; - private final TheatreConfig config; - - @Inject - private BloatTimerOverlay(Client client, TheatrePlugin plugin, TheatreConfig config) { - this.client = client; - this.plugin = plugin; - this.config = config; - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.HIGH); - setLayer(OverlayLayer.ABOVE_SCENE); - } - - public Dimension render(Graphics2D graphics) - { - - if (config.bloatTimer()) - { - final String tickCounter = String.valueOf(plugin.bloatTimer); - int secondConversion = (int) (plugin.bloatTimer * .6); - if (plugin.getBloat_NPC() != null) - { - Point canvasPoint = plugin.getBloat_NPC().getCanvasTextLocation(graphics, tickCounter, 60); - if (plugin.bloatTimer <= 37) - { - renderTextLocation(graphics, tickCounter + "( " + secondConversion + " )", 15, Font.BOLD, Color.WHITE, canvasPoint); - } - else - { - renderTextLocation(graphics, tickCounter + "( " + secondConversion + " )", 15, Font.BOLD, Color.RED, canvasPoint); - } - } - } - - - - - - return null; - } - - private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) { - WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); - if (point.distanceTo(playerLocation) >= 32) { - return; - } - LocalPoint lp = LocalPoint.fromWorld(client, point); - if (lp == null) { - return; - } - - Polygon poly = Perspective.getCanvasTilePoly(client, lp); - if (poly == null) { - return; - } - //OverlayUtil.renderPolygon(graphics, poly, color); - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); - graphics.setStroke(new BasicStroke(strokeWidth)); - graphics.draw(poly); - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); - graphics.fill(poly); - } - - private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, net.runelite.api.Point canvasPoint) - { - graphics.setFont(new Font("Arial", fontStyle, fontSize)); - if (canvasPoint != null) - { - final net.runelite.api.Point canvasCenterPoint = new net.runelite.api.Point( - canvasPoint.getX(), - canvasPoint.getY()); - final net.runelite.api.Point canvasCenterPoint_shadow = new Point( - canvasPoint.getX() + 1, - canvasPoint.getY() + 1); - OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); - OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); - } - } -} +package net.runelite.client.plugins.ztob; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Polygon; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; + +public class BloatTimerOverlay extends Overlay +{ + + private final Client client; + private final TheatrePlugin plugin; + private final TheatreConfig config; + + @Inject + private BloatTimerOverlay(Client client, TheatrePlugin plugin, TheatreConfig config) + { + this.client = client; + this.plugin = plugin; + this.config = config; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGH); + setLayer(OverlayLayer.ABOVE_SCENE); + } + + public Dimension render(Graphics2D graphics) + { + + if (config.bloatTimer()) + { + final String tickCounter = String.valueOf(plugin.bloatTimer); + int secondConversion = (int) (plugin.bloatTimer * .6); + if (plugin.getBloat_NPC() != null) + { + Point canvasPoint = plugin.getBloat_NPC().getCanvasTextLocation(graphics, tickCounter, 60); + if (plugin.bloatTimer <= 37) + { + renderTextLocation(graphics, tickCounter + "( " + secondConversion + " )", 15, Font.BOLD, Color.WHITE, canvasPoint); + } + else + { + renderTextLocation(graphics, tickCounter + "( " + secondConversion + " )", 15, Font.BOLD, Color.RED, canvasPoint); + } + } + } + + + return null; + } + + private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) + { + WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); + if (point.distanceTo(playerLocation) >= 32) + { + return; + } + LocalPoint lp = LocalPoint.fromWorld(client, point); + if (lp == null) + { + return; + } + + Polygon poly = Perspective.getCanvasTilePoly(client, lp); + if (poly == null) + { + return; + } + //OverlayUtil.renderPolygon(graphics, poly, color); + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); + graphics.setStroke(new BasicStroke(strokeWidth)); + graphics.draw(poly); + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); + graphics.fill(poly); + } + + private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, net.runelite.api.Point canvasPoint) + { + graphics.setFont(new Font("Arial", fontStyle, fontSize)); + if (canvasPoint != null) + { + final net.runelite.api.Point canvasCenterPoint = new net.runelite.api.Point( + canvasPoint.getX(), + canvasPoint.getY()); + final net.runelite.api.Point canvasCenterPoint_shadow = new Point( + canvasPoint.getX() + 1, + canvasPoint.getY() + 1); + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreConfig.java index 963a2dcbe0..3403635411 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreConfig.java @@ -11,101 +11,100 @@ package net.runelite.client.plugins.ztob; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.Range; @ConfigGroup("Theatre") public interface TheatreConfig extends Config { - @ConfigItem( - position = 0, - keyName = "MaidenBlood", - name = "Maiden blood attack", - description = "" - ) + @ConfigItem( + position = 0, + keyName = "MaidenBlood", + name = "Maiden blood attack", + description = "" + ) default boolean MaidenBlood() { return true; } - @ConfigItem( - position = 1, - keyName = "MaidenSpawns", - name = "Maiden blood spawns", - description = "" - ) + @ConfigItem( + position = 1, + keyName = "MaidenSpawns", + name = "Maiden blood spawns", + description = "" + ) default boolean MaidenSpawns() { return true; } - @ConfigItem( - position = 2, - keyName = "BloatIndicator", - name = "Bloat Indicator", - description = "" - ) + @ConfigItem( + position = 2, + keyName = "BloatIndicator", + name = "Bloat Indicator", + description = "" + ) default boolean BloatIndicator() { return true; } - @ConfigItem( - position = 3, - keyName = "bloat Timer", - name = "Bloat Timer", - description = "" - ) + @ConfigItem( + position = 3, + keyName = "bloat Timer", + name = "Bloat Timer", + description = "" + ) default boolean bloatTimer() { return true; } - @ConfigItem( - position = 4, - keyName = "bloatFeet", - name = "Bloat Feet", - description = "" - ) + @ConfigItem( + position = 4, + keyName = "bloatFeet", + name = "Bloat Feet", + description = "" + ) default boolean bloatFeetIndicator() { return true; } - @ConfigItem( - position = 5, - keyName = "NyloPillars", - name = "Nylocas pillar health", - description = "" - ) + @ConfigItem( + position = 5, + keyName = "NyloPillars", + name = "Nylocas pillar health", + description = "" + ) default boolean NyloPillars() { return true; } - - @ConfigItem( - position = 6, - keyName = "NyloBlasts", - name = "Nylocas explosions", - description = "" - ) + @ConfigItem( + position = 6, + keyName = "NyloBlasts", + name = "Nylocas explosions", + description = "" + ) default boolean NyloBlasts() { return true; } - @ConfigItem( - position = 7, - keyName = "NyloMenu", - name = "Hide Attack options for Nylocas", - description = "" - ) + @ConfigItem( + position = 7, + keyName = "NyloMenu", + name = "Hide Attack options for Nylocas", + description = "" + ) - default boolean NyloMenu() { - return true; - } + default boolean NyloMenu() + { + return true; + } @ConfigItem( position = 8, @@ -118,107 +117,107 @@ public interface TheatreConfig extends Config return true; } - @ConfigItem( - position = 9, - keyName = "SotetsegMaze1", - name = "Sotetseg maze", - description = "" - ) + @ConfigItem( + position = 9, + keyName = "SotetsegMaze1", + name = "Sotetseg maze", + description = "" + ) default boolean SotetsegMaze1() { return true; } - @ConfigItem( - position = 10, - keyName = "SotetsegMaze2", - name = "Sotetseg maze (solo mode)", - description = "" - ) + @ConfigItem( + position = 10, + keyName = "SotetsegMaze2", + name = "Sotetseg maze (solo mode)", + description = "" + ) default boolean SotetsegMaze2() { return true; } - @ConfigItem( - position = 11, - keyName = "XarpusExhumed", - name = "Xarpus Exhumed", - description = "" - ) + @ConfigItem( + position = 11, + keyName = "XarpusExhumed", + name = "Xarpus Exhumed", + description = "" + ) default boolean XarpusExhumed() { return true; } - @ConfigItem( - position = 12, - keyName = "XarpusTick", - name = "Xarpus Tick", - description = "" - ) + @ConfigItem( + position = 12, + keyName = "XarpusTick", + name = "Xarpus Tick", + description = "" + ) default boolean XarpusTick() { return false; } - @ConfigItem( - position = 13, - keyName = "xarpusExhumes", - name = "Xarpus Exhume Counter", - description = "" - ) + @ConfigItem( + position = 13, + keyName = "xarpusExhumes", + name = "Xarpus Exhume Counter", + description = "" + ) default boolean XarpusExhumeOverlay() { return false; } - @ConfigItem( - position = 14, - keyName = "VerzikCupcakes", - name = "Verzik Projectile Markers", - description = "" - ) + @ConfigItem( + position = 14, + keyName = "VerzikCupcakes", + name = "Verzik Projectile Markers", + description = "" + ) default boolean VerzikCupcakes() { return false; } - @ConfigItem( - position = 15, - keyName = "VerzikTick", - name = "Verzik P3 Tick", - description = "" - ) + @ConfigItem( + position = 15, + keyName = "VerzikTick", + name = "Verzik P3 Tick", + description = "" + ) default boolean VerzikTick() { return false; } - @ConfigItem( - position = 16, - keyName = "VerzikMelee", - name = "Verzik P3 Melee Range", - description = "" - ) + @ConfigItem( + position = 16, + keyName = "VerzikMelee", + name = "Verzik P3 Melee Range", + description = "" + ) default boolean VerzikMelee() { return false; } - @ConfigItem( - position = 17, - keyName = "VerzikYellow", - name = "Verzik Yellow Timing", - description = "" - ) + @ConfigItem( + position = 17, + keyName = "VerzikYellow", + name = "Verzik Yellow Timing", + description = "" + ) default boolean VerzikYellow() { return false; } - @ConfigItem( - position = 18, + @ConfigItem( + position = 18, keyName = "Verzik Nylo", name = "Verzik Nylo Overlay", description = "" @@ -228,17 +227,16 @@ public interface TheatreConfig extends Config return false; } - @ConfigItem( - position = 19, - keyName = "VerzikTankTile", - name = "Verzik P3 Tile Overlay", - description = "" - ) + @ConfigItem( + position = 19, + keyName = "VerzikTankTile", + name = "Verzik P3 Tile Overlay", + description = "" + ) default boolean verzikTankTile() { return true; } - } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreOverlay.java index 14a158f136..222e83d8ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreOverlay.java @@ -35,22 +35,24 @@ import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPriority; import net.runelite.client.ui.overlay.OverlayUtil; -public class TheatreOverlay extends Overlay { - private final Client client; - private final TheatrePlugin plugin; - private final TheatreConfig config; +public class TheatreOverlay extends Overlay +{ + private final Client client; + private final TheatrePlugin plugin; + private final TheatreConfig config; - @Inject - private TheatreOverlay(Client client, TheatrePlugin plugin, TheatreConfig config) { - this.client = client; - this.plugin = plugin; - this.config = config; - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.HIGH); - setLayer(OverlayLayer.ABOVE_SCENE); - } + @Inject + private TheatreOverlay(Client client, TheatrePlugin plugin, TheatreConfig config) + { + this.client = client; + this.plugin = plugin; + this.config = config; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGH); + setLayer(OverlayLayer.ABOVE_SCENE); + } - @Override + @Override public Dimension render(Graphics2D graphics) { if (plugin.isRunMaiden()) @@ -59,22 +61,22 @@ public class TheatreOverlay extends Overlay { { for (WorldPoint point : plugin.getMaiden_BloodSpatters()) { - drawTile(graphics, point, new Color(36, 248, 229), 2, 150, 10); - } - } + drawTile(graphics, point, new Color(36, 248, 229), 2, 150, 10); + } + } if (config.MaidenSpawns()) { for (WorldPoint point : plugin.getMaiden_SpawnLocations()) { - drawTile(graphics, point, new Color(36, 248, 229), 2, 180, 20); - } + drawTile(graphics, point, new Color(36, 248, 229), 2, 180, 20); + } for (WorldPoint point : plugin.getMaiden_SpawnLocations2()) { drawTile(graphics, point, new Color(36, 248, 229), 1, 120, 10); - } - } - } + } + } + } if (plugin.isRunBloat() && config.BloatIndicator()) { @@ -107,64 +109,67 @@ public class TheatreOverlay extends Overlay { } } - } - NPC bloat = plugin.getBloat_NPC(); - int state = plugin.getBloat_State(); + } + NPC bloat = plugin.getBloat_NPC(); + int state = plugin.getBloat_State(); if (bloat == null) { - return null; - } + return null; + } switch (state) { - case 2: - renderNpcOverlay(graphics, bloat, Color.GREEN, 3, 150, 0); - break; - case 3: - renderNpcOverlay(graphics, bloat, Color.YELLOW, 3, 150, 0); - break; - default: - renderNpcOverlay(graphics, bloat, new Color(223, 109, 255), 3, 150, 0); - break; - } - } + case 2: + renderNpcOverlay(graphics, bloat, Color.GREEN, 3, 150, 0); + break; + case 3: + renderNpcOverlay(graphics, bloat, Color.YELLOW, 3, 150, 0); + break; + default: + renderNpcOverlay(graphics, bloat, new Color(223, 109, 255), 3, 150, 0); + break; + } + } if (plugin.isRunNylocas()) { if (config.NyloPillars()) { - Map pillars = plugin.getNylocas_Pillars(); - for (NPC npc : pillars.keySet()) { - final int health = pillars.get(npc); - final String healthStr = health + "%"; - WorldPoint p = npc.getWorldLocation(); - LocalPoint lp = LocalPoint.fromWorld(client, p.getX() + 1, p.getY() + 1); - final double rMod = 130.0 * health / 100.0; - final double gMod = 255.0 * health / 100.0; - final double bMod = 125.0 * health / 100.0; - final Color c = new Color((int) (255 - rMod), (int) (0 + gMod), (int) (0 + bMod)); - Point canvasPoint = Perspective.localToCanvas(client, lp, client.getPlane(), - 65); - renderTextLocation(graphics, healthStr, 13, Font.BOLD, c, canvasPoint); - } - } + Map pillars = plugin.getNylocas_Pillars(); + for (NPC npc : pillars.keySet()) + { + final int health = pillars.get(npc); + final String healthStr = health + "%"; + WorldPoint p = npc.getWorldLocation(); + LocalPoint lp = LocalPoint.fromWorld(client, p.getX() + 1, p.getY() + 1); + final double rMod = 130.0 * health / 100.0; + final double gMod = 255.0 * health / 100.0; + final double bMod = 125.0 * health / 100.0; + final Color c = new Color((int) (255 - rMod), (int) (0 + gMod), (int) (0 + bMod)); + Point canvasPoint = Perspective.localToCanvas(client, lp, client.getPlane(), + 65); + renderTextLocation(graphics, healthStr, 13, Font.BOLD, c, canvasPoint); + } + } if (config.NyloBlasts()) { - final Map npcMap = plugin.getNylocas_Map(); + final Map npcMap = plugin.getNylocas_Map(); for (NPC npc : npcMap.keySet()) { - int ticksLeft = npcMap.get(npc); - if (ticksLeft > -1) { - if (ticksLeft <= 6) { + int ticksLeft = npcMap.get(npc); + if (ticksLeft > -1) + { + if (ticksLeft <= 6) + { Color color = new Color(255, 255, 0, 180); - int outlineWidth = 2; - int outlineAlpha = 150; - renderNpcOverlay(graphics, npc, color, outlineWidth, outlineAlpha, 15); - } - } - } - } - } + int outlineWidth = 2; + int outlineAlpha = 150; + renderNpcOverlay(graphics, npc, color, outlineWidth, outlineAlpha, 15); + } + } + } + } + } if (plugin.isRunSotetseg()) { @@ -199,82 +204,81 @@ public class TheatreOverlay extends Overlay { if (config.SotetsegMaze1()) { - int i = 1; + int i = 1; for (GroundObject o : plugin.getRedTiles().keySet()) { - Polygon poly = o.getCanvasTilePoly(); + Polygon poly = o.getCanvasTilePoly(); if (poly != null) { - graphics.setColor(Color.WHITE); - graphics.setStroke(new BasicStroke(2)); - graphics.draw(poly); - } - Point textLocation = o.getCanvasTextLocation(graphics, String.valueOf(i), 0); + graphics.setColor(Color.WHITE); + graphics.setStroke(new BasicStroke(2)); + graphics.draw(poly); + } + Point textLocation = o.getCanvasTextLocation(graphics, String.valueOf(i), 0); if (textLocation != null) { - OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(i), Color.WHITE); - } + OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(i), Color.WHITE); + } - i++; - } - } + i++; + } + } if (config.SotetsegMaze2()) { for (WorldPoint p : plugin.getRedTilesOverworld()) { - drawTile(graphics, p, Color.WHITE, 2, 255, 10); - } - } - } + drawTile(graphics, p, Color.WHITE, 2, 255, 10); + } + } + } if (plugin.isRunXarpus()) { - NPC boss = plugin.getXarpus_NPC(); + NPC boss = plugin.getXarpus_NPC(); if (boss.getId() == NpcID.XARPUS_8340 && !plugin.isXarpus_Stare() && config.XarpusTick()) { - int tick = plugin.getXarpus_TicksUntilShoot(); + int tick = plugin.getXarpus_TicksUntilShoot(); if (tick < 1) { - tick = tick % 4 + 4; - } - final String ticksLeftStr = String.valueOf(tick); - Point canvasPoint = boss.getCanvasTextLocation(graphics, ticksLeftStr, 130); - renderTextLocation(graphics, ticksLeftStr, 12, Font.BOLD, Color.WHITE, canvasPoint); - } + tick = tick % 4 + 4; + } + final String ticksLeftStr = String.valueOf(tick); + Point canvasPoint = boss.getCanvasTextLocation(graphics, ticksLeftStr, 130); + renderTextLocation(graphics, ticksLeftStr, 12, Font.BOLD, Color.WHITE, canvasPoint); + } if (boss.getId() == NpcID.XARPUS_8339 && config.XarpusExhumed()) { for (GroundObject o : plugin.getXarpus_Exhumeds().keySet()) { - - Polygon poly = o.getCanvasTilePoly(); + Polygon poly = o.getCanvasTilePoly(); if (poly != null) { - graphics.setColor(new Color(0, 255, 0, 130)); - graphics.setStroke(new BasicStroke(1)); - graphics.draw(poly); - } - } + graphics.setColor(new Color(0, 255, 0, 130)); + graphics.setStroke(new BasicStroke(1)); + graphics.draw(poly); + } + } for (Map.Entry exhumes : plugin.getXarpusExhumedsTimer().entrySet()) { - final String ticksremaining = String.valueOf(exhumes.getValue()); + final String ticksremaining = String.valueOf(exhumes.getValue()); if (Integer.valueOf(ticksremaining) > 0) { - GroundObject ex = exhumes.getKey(); - Point point = ex.getCanvasTextLocation(graphics, ticksremaining, 0); - renderTextLocation(graphics, ticksremaining, 12, Font.BOLD, Color.white, point); - } + GroundObject ex = exhumes.getKey(); + Point point = ex.getCanvasTextLocation(graphics, ticksremaining, 0); + renderTextLocation(graphics, ticksremaining, 12, Font.BOLD, Color.white, point); + } - } + } - } + } - } + } if (plugin.isRunVerzik()) @@ -285,147 +289,151 @@ public class TheatreOverlay extends Overlay { { for (WorldPoint p : plugin.getVerzik_RangeProjectiles().values()) { - drawTile(graphics, p, Color.RED, 2, 180, 50); - } - } + drawTile(graphics, p, Color.RED, 2, 180, 50); + } + } if (config.VerzikYellow()) { for (WorldPoint p : plugin.getVerzik_YellowTiles()) { drawTile(graphics, p, Color.YELLOW, 3, 255, 0); - Projectile yellowBall = plugin.getVerzik_YellowBall(); + Projectile yellowBall = plugin.getVerzik_YellowBall(); if (yellowBall != null) { final int ticksToImpact = yellowBall.getRemainingCycles() / 30; - final String countdownStr = String.valueOf(ticksToImpact); - Point canvasPoint = Perspective.getCanvasTextLocation(client, graphics, LocalPoint.fromWorld(client, p), countdownStr, 0); - renderTextLocation(graphics, countdownStr, 12, Font.BOLD, Color.WHITE, canvasPoint); + final String countdownStr = String.valueOf(ticksToImpact); + Point canvasPoint = Perspective.getCanvasTextLocation(client, graphics, LocalPoint.fromWorld(client, p), countdownStr, 0); + renderTextLocation(graphics, countdownStr, 12, Font.BOLD, Color.WHITE, canvasPoint); - } - } - } + } + } + } - final NPC boss = plugin.getVerzik_NPC(); + final NPC boss = plugin.getVerzik_NPC(); if (boss.getId() == NpcID.VERZIK_VITUR_8374) { if (config.verzikTankTile()) { renderNpcOverlay(graphics, boss, new Color(75, 0, 130), 1, 255, 0); - } + } if (config.VerzikTick()) { - final int ticksLeft = plugin.getP3_TicksUntilAttack(); + final int ticksLeft = plugin.getP3_TicksUntilAttack(); if (ticksLeft > 0 && ticksLeft < 8) { - final String ticksLeftStr = String.valueOf(ticksLeft); - Point canvasPoint = boss.getCanvasTextLocation(graphics, ticksLeftStr, 60); - renderTextLocation(graphics, ticksLeftStr, 15, Font.BOLD, Color.WHITE, canvasPoint); - } - } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = boss.getCanvasTextLocation(graphics, ticksLeftStr, 60); + renderTextLocation(graphics, ticksLeftStr, 15, Font.BOLD, Color.WHITE, canvasPoint); + } + } if (config.VerzikMelee()) { - List meleeRange = getHitSquares(boss.getWorldLocation(), 7, 1, false); + List meleeRange = getHitSquares(boss.getWorldLocation(), 7, 1, false); for (WorldPoint p : meleeRange) { drawTile(graphics, p, Color.WHITE, 1, 155, 10); - } - } - } + } + } + } if (boss.getAnimation() == 8117) { - final int ticksLeft = plugin.getRedCrabsTimer(); + final int ticksLeft = plugin.getRedCrabsTimer(); if (ticksLeft > 0) { - final String ticksLeftStr = String.valueOf(ticksLeft); - Point canvasPoint = boss.getCanvasTextLocation(graphics, ticksLeftStr, 60); - renderTextLocation(graphics, ticksLeftStr, 15, Font.BOLD, Color.WHITE, canvasPoint); - } - } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = boss.getCanvasTextLocation(graphics, ticksLeftStr, 60); + renderTextLocation(graphics, ticksLeftStr, 15, Font.BOLD, Color.WHITE, canvasPoint); + } + } - } + } - return null; - } + return null; + } - private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) { - WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); - if (point.distanceTo(playerLocation) >= 32) { - return; - } - LocalPoint lp = LocalPoint.fromWorld(client, point); - if (lp == null) { - return; - } + private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) + { + WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); + if (point.distanceTo(playerLocation) >= 32) + { + return; + } + LocalPoint lp = LocalPoint.fromWorld(client, point); + if (lp == null) + { + return; + } - Polygon poly = Perspective.getCanvasTilePoly(client, lp); - if (poly == null) { - return; - } - //OverlayUtil.renderPolygon(graphics, poly, color); - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); - graphics.setStroke(new BasicStroke(strokeWidth)); - graphics.draw(poly); - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); - graphics.fill(poly); - } + Polygon poly = Perspective.getCanvasTilePoly(client, lp); + if (poly == null) + { + return; + } + //OverlayUtil.renderPolygon(graphics, poly, color); + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); + graphics.setStroke(new BasicStroke(strokeWidth)); + graphics.draw(poly); + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); + graphics.fill(poly); + } private void renderNpcOverlay(Graphics2D graphics, NPC actor, Color color, int outlineWidth, int outlineAlpha, int fillAlpha) { - int size = 1; - NPCComposition composition = actor.getTransformedComposition(); + int size = 1; + NPCComposition composition = actor.getTransformedComposition(); if (composition != null) { - size = composition.getSize(); - } - LocalPoint lp = actor.getLocalLocation(); - Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size); + size = composition.getSize(); + } + LocalPoint lp = actor.getLocalLocation(); + Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size); if (tilePoly != null) { - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); - graphics.setStroke(new BasicStroke(outlineWidth)); - graphics.draw(tilePoly); - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); - graphics.fill(tilePoly); - } - } + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); + graphics.setStroke(new BasicStroke(outlineWidth)); + graphics.draw(tilePoly); + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); + graphics.fill(tilePoly); + } + } private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, Point canvasPoint) { - graphics.setFont(new Font("Arial", fontStyle, fontSize)); + graphics.setFont(new Font("Arial", fontStyle, fontSize)); if (canvasPoint != null) { - final Point canvasCenterPoint = new Point( - canvasPoint.getX(), - canvasPoint.getY()); - final Point canvasCenterPoint_shadow = new Point( - canvasPoint.getX() + 1, + final Point canvasCenterPoint = new Point( + canvasPoint.getX(), + canvasPoint.getY()); + final Point canvasCenterPoint_shadow = new Point( + canvasPoint.getX() + 1, canvasPoint.getY() + 1); - OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); - OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); - } - } + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); + } + } private List getHitSquares(WorldPoint npcLoc, int npcSize, int thickness, boolean includeUnder) { - List little = new WorldArea(npcLoc, npcSize, npcSize).toWorldPointList(); + List little = new WorldArea(npcLoc, npcSize, npcSize).toWorldPointList(); List big = new WorldArea(npcLoc.getX() - thickness, npcLoc.getY() - thickness, npcSize + (thickness * 2), npcSize + (thickness * 2), npcLoc.getPlane()).toWorldPointList(); if (!includeUnder) { for (Iterator it = big.iterator(); it.hasNext(); ) { - WorldPoint p = it.next(); + WorldPoint p = it.next(); if (little.contains(p)) { - it.remove(); - } - } - } - return big; - } + it.remove(); + } + } + } + return big; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatrePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatrePlugin.java index 1735ae360c..ccc43cae1e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatrePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatrePlugin.java @@ -53,140 +53,141 @@ import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.Text; @PluginDescriptor( - name = "Theater of Blood", - description = "All-in-one plugin for Theatre of Blood", + name = "Theater of Blood", + description = "All-in-one plugin for Theatre of Blood", tags = {"ToB", "theatre", "blood"}, - enabledByDefault = false, + enabledByDefault = false, type = PluginType.PVM ) -public class TheatrePlugin extends Plugin { - private static final int GRAPHICSOBJECT_ID_MAIDEN = 1579; - private static final int NPCID_NYLOCAS_PILLAR = 8358; - private static final int GROUNDOBJECT_ID_BLACKMAZE = 33034; - private static final int GROUNDOBJECT_ID_REDMAZE = 33035; - private static final int GROUNDOBJECT_ID_EXHUMED = 32743; - private static final int ANIMATION_ID_XARPUS = 8059; - private static final int GRAPHICSOBJECT_ID_YELLOW = 1595; - private static final int PROJECTILE_ID_P2RANGE = 1583; - private static final int PROJECTILE_ID_YELLOW = 1596; - private static final int ANIMATION_ID_P3_WEB = 8127; - private static final int ANIMATION_ID_P3_YELLOW = 8126; - private static final int ANIMATION_ID_P3_MELEE = 8123; - private static final int ANIMATION_ID_P3_MAGE = 8124; - private static final int ANIMATION_ID_P3_RANGE = 8125; - private static final int VERZIK_ID_P3 = NpcID.VERZIK_VITUR_8374; - private static final int NPC_ID_TORNADO = 8386; - private static final int PROJECTILE_ID_P3_GREEN = 1598; +public class TheatrePlugin extends Plugin +{ + private static final int GRAPHICSOBJECT_ID_MAIDEN = 1579; + private static final int NPCID_NYLOCAS_PILLAR = 8358; + private static final int GROUNDOBJECT_ID_BLACKMAZE = 33034; + private static final int GROUNDOBJECT_ID_REDMAZE = 33035; + private static final int GROUNDOBJECT_ID_EXHUMED = 32743; + private static final int ANIMATION_ID_XARPUS = 8059; + private static final int GRAPHICSOBJECT_ID_YELLOW = 1595; + private static final int PROJECTILE_ID_P2RANGE = 1583; + private static final int PROJECTILE_ID_YELLOW = 1596; + private static final int ANIMATION_ID_P3_WEB = 8127; + private static final int ANIMATION_ID_P3_YELLOW = 8126; + private static final int ANIMATION_ID_P3_MELEE = 8123; + private static final int ANIMATION_ID_P3_MAGE = 8124; + private static final int ANIMATION_ID_P3_RANGE = 8125; + private static final int VERZIK_ID_P3 = NpcID.VERZIK_VITUR_8374; + private static final int NPC_ID_TORNADO = 8386; + private static final int PROJECTILE_ID_P3_GREEN = 1598; - @Getter - int exhumecount; + @Getter + int exhumecount; @Getter(AccessLevel.PACKAGE) private final Map xarpusExhumedsTimer = new HashMap<>(); - @Getter - int bloatTimer = 0; + @Getter + int bloatTimer = 0; - int bloatFeetTimer = 0; - - @Getter - private Set bloatTiles = new HashSet<>(); - - @Getter - private Set temp = new HashSet<>(); + int bloatFeetTimer = 0; @Getter - private Set temp2 = new HashSet<>(); + private Set bloatTiles = new HashSet<>(); @Getter - private Set localTemp = new HashSet<>(); + private Set temp = new HashSet<>(); + + @Getter + private Set temp2 = new HashSet<>(); + + @Getter + private Set localTemp = new HashSet<>(); NPC BossNylo = null; private boolean bloatFlag = false; - //@Getter - //private List bloatTiles = new ArrayList<>(); + //@Getter + //private List bloatTiles = new ArrayList<>(); - @Getter(AccessLevel.PACKAGE) - private boolean runMaiden; + @Getter(AccessLevel.PACKAGE) + private boolean runMaiden; - @Getter(AccessLevel.PACKAGE) - private List Maiden_BloodSpatters = new ArrayList<>(); + @Getter(AccessLevel.PACKAGE) + private List Maiden_BloodSpatters = new ArrayList<>(); - private List Maiden_Spawns = new ArrayList<>(); + private List Maiden_Spawns = new ArrayList<>(); - @Getter(AccessLevel.PACKAGE) - private List Maiden_SpawnLocations = new ArrayList<>(); + @Getter(AccessLevel.PACKAGE) + private List Maiden_SpawnLocations = new ArrayList<>(); - @Getter(AccessLevel.PACKAGE) - private List Maiden_SpawnLocations2 = new ArrayList<>(); + @Getter(AccessLevel.PACKAGE) + private List Maiden_SpawnLocations2 = new ArrayList<>(); - @Getter(AccessLevel.PACKAGE) - private boolean runBloat; + @Getter(AccessLevel.PACKAGE) + private boolean runBloat; - @Getter(AccessLevel.PACKAGE) - private NPC Bloat_NPC; + @Getter(AccessLevel.PACKAGE) + private NPC Bloat_NPC; - private int Bloat_downCount; + private int Bloat_downCount; - @Getter(AccessLevel.PACKAGE) - private Integer Bloat_State; + @Getter(AccessLevel.PACKAGE) + private Integer Bloat_State; - @Getter(AccessLevel.PACKAGE) - private boolean runNylocas; + @Getter(AccessLevel.PACKAGE) + private boolean runNylocas; - @Getter(AccessLevel.PACKAGE) - private Map Nylocas_Pillars = new HashMap<>(); + @Getter(AccessLevel.PACKAGE) + private Map Nylocas_Pillars = new HashMap<>(); - @Getter(AccessLevel.PACKAGE) - private Map Nylocas_Map = new HashMap<>(); + @Getter(AccessLevel.PACKAGE) + private Map Nylocas_Map = new HashMap<>(); - @Getter(AccessLevel.PACKAGE) - private boolean runSotetseg; + @Getter(AccessLevel.PACKAGE) + private boolean runSotetseg; - @Getter(AccessLevel.PACKAGE) - private final Map RedTiles = new LinkedHashMap<>(); + @Getter(AccessLevel.PACKAGE) + private final Map RedTiles = new LinkedHashMap<>(); - @Getter(AccessLevel.PACKAGE) - private List RedTilesOverworld = new ArrayList<>(); + @Getter(AccessLevel.PACKAGE) + private List RedTilesOverworld = new ArrayList<>(); - private List BlackTilesOverworld = new ArrayList<>(); - @Getter - private boolean tempFlag = false; - @Getter - private boolean temp2Flag = false; + private List BlackTilesOverworld = new ArrayList<>(); + @Getter + private boolean tempFlag = false; + @Getter + private boolean temp2Flag = false; - private List GridPath = new ArrayList<>(); - private List BlackTilesUnderworld = new ArrayList<>(); + private List GridPath = new ArrayList<>(); + private List BlackTilesUnderworld = new ArrayList<>(); - @Getter(AccessLevel.PACKAGE) - private boolean runXarpus; + @Getter(AccessLevel.PACKAGE) + private boolean runXarpus; - private int Xarpus_previousAnimation; + private int Xarpus_previousAnimation; - @Getter(AccessLevel.PACKAGE) - private boolean Xarpus_Stare; + @Getter(AccessLevel.PACKAGE) + private boolean Xarpus_Stare; - @Getter(AccessLevel.PACKAGE) - private final Map Xarpus_Exhumeds = new HashMap<>(); - private List RedTilesUnderworld = new ArrayList<>(); + @Getter(AccessLevel.PACKAGE) + private final Map Xarpus_Exhumeds = new HashMap<>(); + private List RedTilesUnderworld = new ArrayList<>(); - @Getter(AccessLevel.PACKAGE) - private int Xarpus_TicksUntilShoot = 9; + @Getter(AccessLevel.PACKAGE) + private int Xarpus_TicksUntilShoot = 9; - @Getter(AccessLevel.PACKAGE) - private NPC Xarpus_NPC; + @Getter(AccessLevel.PACKAGE) + private NPC Xarpus_NPC; - @Getter(AccessLevel.PACKAGE) - private boolean runVerzik; + @Getter(AccessLevel.PACKAGE) + private boolean runVerzik; - @Getter(AccessLevel.PACKAGE) - private final Map Verzik_RangeProjectiles = new HashMap<>(); + @Getter(AccessLevel.PACKAGE) + private final Map Verzik_RangeProjectiles = new HashMap<>(); @Getter(AccessLevel.PACKAGE) private final List Sotetseg_MageProjectiles = new ArrayList<>(); @@ -194,860 +195,1036 @@ public class TheatrePlugin extends Plugin { @Getter(AccessLevel.PACKAGE) private final List Sotetseg_RangeProjectiles = new ArrayList<>(); - @Getter(AccessLevel.PACKAGE) - private int P3_TicksUntilAttack = -1; - - @Getter(AccessLevel.PACKAGE) - private Projectile Verzik_YellowBall; - - @Getter(AccessLevel.PACKAGE) - private List Verzik_YellowTiles = new ArrayList<>(); - - @Getter(AccessLevel.PACKAGE) - private NPC Verzik_NPC; + @Getter(AccessLevel.PACKAGE) + private int P3_TicksUntilAttack = -1; @Getter(AccessLevel.PACKAGE) - private List tornadoList; + private Projectile Verzik_YellowBall; - @Getter(AccessLevel.PACKAGE) - private List crabList; + @Getter(AccessLevel.PACKAGE) + private List Verzik_YellowTiles = new ArrayList<>(); - @Getter - private int redCrabsTimer; + @Getter(AccessLevel.PACKAGE) + private NPC Verzik_NPC; - private int P3_attacksLeft; + @Getter(AccessLevel.PACKAGE) + private List tornadoList; - @Inject - private Client client; + @Getter(AccessLevel.PACKAGE) + private List crabList; - @Inject - private OverlayManager overlayManager; + @Getter + private int redCrabsTimer; - @Inject - private TheatreOverlay overlay; + private int P3_attacksLeft; - @Inject - private TheatreConfig config; + @Inject + private Client client; - @Inject - private TheatreXarpusOverlay xarpusOverlay; + @Inject + private OverlayManager overlayManager; - @Inject - private ChatMessageManager chatMessageManager; + @Inject + private TheatreOverlay overlay; - @Inject - private VerzikNyloOverlay verzikNyloOverlay; + @Inject + private TheatreConfig config; - @Inject - private BloatTimerOverlay bloatTimerOverlay; + @Inject + private TheatreXarpusOverlay xarpusOverlay; - @Provides - TheatreConfig getConfig(ConfigManager configManager) { - return configManager.getConfig(TheatreConfig.class); - } + @Inject + private ChatMessageManager chatMessageManager; - @Override - protected void startUp() { - overlayManager.add(overlay); - overlayManager.add(xarpusOverlay); - overlayManager.add(verzikNyloOverlay); - overlayManager.add(bloatTimerOverlay); - } + @Inject + private VerzikNyloOverlay verzikNyloOverlay; - @Override - protected void shutDown() { - overlayManager.remove(overlay); - overlayManager.remove(xarpusOverlay); - overlayManager.remove(xarpusOverlay); - overlayManager.remove(bloatTimerOverlay); - } + @Inject + private BloatTimerOverlay bloatTimerOverlay; - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) { - if (client.getGameState() != GameState.LOGGED_IN || !config.NyloMenu() || !runNylocas) { - return; - } + @Provides + TheatreConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(TheatreConfig.class); + } - final String pOptionToReplace = Text.removeTags(event.getOption()).toUpperCase(); + @Override + protected void startUp() + { + overlayManager.add(overlay); + overlayManager.add(xarpusOverlay); + overlayManager.add(verzikNyloOverlay); + overlayManager.add(bloatTimerOverlay); + } - int attackType = 0; //0=idk 1= melee 2= range 3= mage + @Override + protected void shutDown() + { + overlayManager.remove(overlay); + overlayManager.remove(xarpusOverlay); + overlayManager.remove(xarpusOverlay); + overlayManager.remove(bloatTimerOverlay); + } - for (KitType kitType : KitType.values()) { - int itemId = client.getLocalPlayer().getPlayerComposition().getEquipmentId(kitType); - switch (itemId) { - case ItemID.DRAGON_CLAWS: - case ItemID.SCYTHE_OF_VITUR: - case ItemID.SCYTHE_OF_VITUR_UNCHARGED: - case ItemID.SCYTHE_10735: - case ItemID.SCYTHE_OF_VITUR_22664: - case ItemID.HAM_JOINT: - case ItemID.EVENT_RPG: - case ItemID.ABYSSAL_WHIP: - case ItemID.ABYSSAL_TENTACLE: - case ItemID.FROZEN_ABYSSAL_WHIP: - case ItemID.VOLCANIC_ABYSSAL_WHIP: - case ItemID.GHRAZI_RAPIER: - case ItemID.DRAGON_WARHAMMER: - case ItemID.DRAGON_WARHAMMER_20785: - case ItemID.BANDOS_GODSWORD: - case ItemID.BANDOS_GODSWORD_OR: - case ItemID.BANDOS_GODSWORD_20782: - case ItemID.BANDOS_GODSWORD_21060: - case ItemID.CRYSTAL_HALBERD_510: - case ItemID.CRYSTAL_HALBERD_510_I: - case ItemID.CRYSTAL_HALBERD_610: - case ItemID.CRYSTAL_HALBERD_610_I: - case ItemID.CRYSTAL_HALBERD_710_I: - case ItemID.CRYSTAL_HALBERD_710: - case ItemID.CRYSTAL_HALBERD_110: - case ItemID.CRYSTAL_HALBERD_110_I: - case ItemID.CRYSTAL_HALBERD_210: - case ItemID.CRYSTAL_HALBERD_310: - case ItemID.CRYSTAL_HALBERD_310_I: - case ItemID.CRYSTAL_HALBERD_410: - case ItemID.CRYSTAL_HALBERD_410_I: - case ItemID.CRYSTAL_HALBERD_810: - case ItemID.CRYSTAL_HALBERD_810_I: - case ItemID.CRYSTAL_HALBERD_910: - case ItemID.CRYSTAL_HALBERD_910_I: - attackType = 1; - break; - case ItemID.TOXIC_BLOWPIPE: - case ItemID.TOXIC_BLOWPIPE_EMPTY: - case ItemID.RED_CHINCHOMPA_10034: - case ItemID.BLACK_CHINCHOMPA: - case ItemID.CHINCHOMPA_10033: - case ItemID.TWISTED_BOW: - attackType = 2; - break; - case ItemID.SANGUINESTI_STAFF: - case ItemID.TOXIC_STAFF_OF_THE_DEAD: - case ItemID.TRIDENT_OF_THE_SWAMP: - case ItemID.TRIDENT_OF_THE_SEAS_E: - case ItemID.TRIDENT_OF_THE_SEAS: - case ItemID.TRIDENT_OF_THE_SWAMP_E: - case ItemID.KODAI_WAND: - case ItemID.MASTER_WAND: - case ItemID.MASTER_WAND_20560: - attackType = 3; - break; - } - if (attackType != 0) { - break; - } + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + if (client.getGameState() != GameState.LOGGED_IN || !config.NyloMenu() || !runNylocas) + { + return; + } - } + final String pOptionToReplace = Text.removeTags(event.getOption()).toUpperCase(); - if (!pOptionToReplace.equals("ATTACK")) { - return; - } - int Id = 0; - if (BossNylo != null) { - Id = BossNylo.getId(); - } - String target = Text.removeTags(event.getTarget()).toLowerCase(); - if (attackType != 0) { - stripEntries(attackType, target, Id); - } + int attackType = 0; //0=idk 1= melee 2= range 3= mage - } + for (KitType kitType : KitType.values()) + { + int itemId = client.getLocalPlayer().getPlayerComposition().getEquipmentId(kitType); + switch (itemId) + { + case ItemID.DRAGON_CLAWS: + case ItemID.SCYTHE_OF_VITUR: + case ItemID.SCYTHE_OF_VITUR_UNCHARGED: + case ItemID.SCYTHE_10735: + case ItemID.SCYTHE_OF_VITUR_22664: + case ItemID.HAM_JOINT: + case ItemID.EVENT_RPG: + case ItemID.ABYSSAL_WHIP: + case ItemID.ABYSSAL_TENTACLE: + case ItemID.FROZEN_ABYSSAL_WHIP: + case ItemID.VOLCANIC_ABYSSAL_WHIP: + case ItemID.GHRAZI_RAPIER: + case ItemID.DRAGON_WARHAMMER: + case ItemID.DRAGON_WARHAMMER_20785: + case ItemID.BANDOS_GODSWORD: + case ItemID.BANDOS_GODSWORD_OR: + case ItemID.BANDOS_GODSWORD_20782: + case ItemID.BANDOS_GODSWORD_21060: + case ItemID.CRYSTAL_HALBERD_510: + case ItemID.CRYSTAL_HALBERD_510_I: + case ItemID.CRYSTAL_HALBERD_610: + case ItemID.CRYSTAL_HALBERD_610_I: + case ItemID.CRYSTAL_HALBERD_710_I: + case ItemID.CRYSTAL_HALBERD_710: + case ItemID.CRYSTAL_HALBERD_110: + case ItemID.CRYSTAL_HALBERD_110_I: + case ItemID.CRYSTAL_HALBERD_210: + case ItemID.CRYSTAL_HALBERD_310: + case ItemID.CRYSTAL_HALBERD_310_I: + case ItemID.CRYSTAL_HALBERD_410: + case ItemID.CRYSTAL_HALBERD_410_I: + case ItemID.CRYSTAL_HALBERD_810: + case ItemID.CRYSTAL_HALBERD_810_I: + case ItemID.CRYSTAL_HALBERD_910: + case ItemID.CRYSTAL_HALBERD_910_I: + attackType = 1; + break; + case ItemID.TOXIC_BLOWPIPE: + case ItemID.TOXIC_BLOWPIPE_EMPTY: + case ItemID.RED_CHINCHOMPA_10034: + case ItemID.BLACK_CHINCHOMPA: + case ItemID.CHINCHOMPA_10033: + case ItemID.TWISTED_BOW: + attackType = 2; + break; + case ItemID.SANGUINESTI_STAFF: + case ItemID.TOXIC_STAFF_OF_THE_DEAD: + case ItemID.TRIDENT_OF_THE_SWAMP: + case ItemID.TRIDENT_OF_THE_SEAS_E: + case ItemID.TRIDENT_OF_THE_SEAS: + case ItemID.TRIDENT_OF_THE_SWAMP_E: + case ItemID.KODAI_WAND: + case ItemID.MASTER_WAND: + case ItemID.MASTER_WAND_20560: + attackType = 3; + break; + } + if (attackType != 0) + { + break; + } - @Subscribe - public void onNpcSpawned(NpcSpawned npcSpawned) { + } - NPC npc = npcSpawned.getNpc(); - switch (npc.getId()) { - case NpcID.THE_MAIDEN_OF_SUGADINTI: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8361: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8362: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8363: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8364: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8365: - runMaiden = true; - break; - case NpcID.BLOOD_SPAWN: - Maiden_Spawns.add(npc); - break; - case NpcID.PESTILENT_BLOAT: - runBloat = true; - Bloat_NPC = npc; - bloatTimer = 0; - bloatFlag = false; - break; - case NpcID.NYLOCAS_VASILIAS: - case NpcID.NYLOCAS_VASILIAS_8355: - case NpcID.NYLOCAS_VASILIAS_8356: - case NpcID.NYLOCAS_VASILIAS_8357: - BossNylo = npc; - break; - case NPCID_NYLOCAS_PILLAR: - runNylocas = true; - if (!Nylocas_Pillars.keySet().contains(npc)) { - Nylocas_Pillars.put(npc, 100); - } - break; - case 8342: - case 8343: - case 8344: - case 8345: - case 8346: - case 8347: - case 8348: - case 8349: - case 8350: - case 8351: - case 8352: - case 8353: - if (runNylocas) { - Nylocas_Map.put(npc, 52); - } - break; - case NpcID.SOTETSEG: - case NpcID.SOTETSEG_8388: - runSotetseg = true; - RedTiles.clear(); - break; - case NpcID.XARPUS: - case NpcID.XARPUS_8339: - case NpcID.XARPUS_8340: - case NpcID.XARPUS_8341: - runXarpus = true; - exhumecount = 25; - Xarpus_NPC = npc; - Xarpus_Stare = false; - Xarpus_TicksUntilShoot = 9; - Xarpus_previousAnimation = -1; - break; - case NpcID.VERZIK_VITUR_8369: - case NpcID.VERZIK_VITUR_8370: - case NpcID.VERZIK_VITUR_8371: - case NpcID.VERZIK_VITUR_8372: - case NpcID.VERZIK_VITUR_8373: - case NpcID.VERZIK_VITUR_8374: - case NpcID.VERZIK_VITUR_8375: - P3_TicksUntilAttack = -1; - P3_attacksLeft = 9; - redCrabsTimer = 13; - Verzik_NPC = npc; - runVerzik = true; - tornadoList = new ArrayList<>(); - crabList = new ArrayList<>(); - break; - } - } + if (!pOptionToReplace.equals("ATTACK")) + { + return; + } + int Id = 0; + if (BossNylo != null) + { + Id = BossNylo.getId(); + } + String target = Text.removeTags(event.getTarget()).toLowerCase(); + if (attackType != 0) + { + stripEntries(attackType, target, Id); + } - @Subscribe - public void onNpcDespawned(NpcDespawned npcDespawned) { - NPC npc = npcDespawned.getNpc(); - switch (npc.getId()) { - case NpcID.THE_MAIDEN_OF_SUGADINTI: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8361: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8362: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8363: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8364: - case NpcID.THE_MAIDEN_OF_SUGADINTI_8365: - runMaiden = false; - Maiden_Spawns.clear(); - break; - case NpcID.BLOOD_SPAWN: - Maiden_Spawns.remove(npc); - break; - case NpcID.PESTILENT_BLOAT: - runBloat = false; - Bloat_NPC = null; - bloatTimer = 0; - break; - case NPCID_NYLOCAS_PILLAR: - if (Nylocas_Pillars.keySet().contains(npc)) { - Nylocas_Pillars.remove(npc); - } - break; - case 8342: - case 8343: - case 8344: - case 8345: - case 8346: - case 8347: - case 8348: - case 8349: - case 8350: - case 8351: - case 8352: - case 8353: - if (Nylocas_Map.keySet().contains(npc)) { - Nylocas_Map.remove(npc); - } - break; - case NpcID.SOTETSEG: - case NpcID.SOTETSEG_8388: - RedTiles.clear(); - if (client.getPlane() != 3) { - runSotetseg = false; - } - break; - case NpcID.XARPUS: - case NpcID.XARPUS_8339: - case NpcID.XARPUS_8340: - case NpcID.XARPUS_8341: - runXarpus = false; - Xarpus_NPC = null; - Xarpus_Stare = false; - Xarpus_TicksUntilShoot = 9; - Xarpus_previousAnimation = -1; - Xarpus_Exhumeds.clear(); - exhumecount = 0; - break; - case NpcID.VERZIK_VITUR_8369: - case NpcID.VERZIK_VITUR_8370: - case NpcID.VERZIK_VITUR_8371: - case NpcID.VERZIK_VITUR_8372: - case NpcID.VERZIK_VITUR_8373: - case NpcID.VERZIK_VITUR_8374: - case NpcID.VERZIK_VITUR_8375: - runVerzik = false; - redCrabsTimer = 0; - Verzik_NPC = null; - break; - } + } - } + @Subscribe + public void onNpcSpawned(NpcSpawned npcSpawned) + { - @Subscribe - public void onGroundObjectSpawned(GroundObjectSpawned event) { - if (runSotetseg) { - GroundObject o = event.getGroundObject(); - if (o.getId() == GROUNDOBJECT_ID_BLACKMAZE) { - Tile t = event.getTile(); - WorldPoint p = t.getWorldLocation(); - if (t.getPlane() == 0) { - if (!BlackTilesOverworld.contains(p)) - BlackTilesOverworld.add(p); - } else { - if (!BlackTilesUnderworld.contains(p)) - BlackTilesUnderworld.add(p); - } - } + NPC npc = npcSpawned.getNpc(); + switch (npc.getId()) + { + case NpcID.THE_MAIDEN_OF_SUGADINTI: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8361: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8362: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8363: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8364: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8365: + runMaiden = true; + break; + case NpcID.BLOOD_SPAWN: + Maiden_Spawns.add(npc); + break; + case NpcID.PESTILENT_BLOAT: + runBloat = true; + Bloat_NPC = npc; + bloatTimer = 0; + bloatFlag = false; + break; + case NpcID.NYLOCAS_VASILIAS: + case NpcID.NYLOCAS_VASILIAS_8355: + case NpcID.NYLOCAS_VASILIAS_8356: + case NpcID.NYLOCAS_VASILIAS_8357: + BossNylo = npc; + break; + case NPCID_NYLOCAS_PILLAR: + runNylocas = true; + if (!Nylocas_Pillars.keySet().contains(npc)) + { + Nylocas_Pillars.put(npc, 100); + } + break; + case 8342: + case 8343: + case 8344: + case 8345: + case 8346: + case 8347: + case 8348: + case 8349: + case 8350: + case 8351: + case 8352: + case 8353: + if (runNylocas) + { + Nylocas_Map.put(npc, 52); + } + break; + case NpcID.SOTETSEG: + case NpcID.SOTETSEG_8388: + runSotetseg = true; + RedTiles.clear(); + break; + case NpcID.XARPUS: + case NpcID.XARPUS_8339: + case NpcID.XARPUS_8340: + case NpcID.XARPUS_8341: + runXarpus = true; + exhumecount = 25; + Xarpus_NPC = npc; + Xarpus_Stare = false; + Xarpus_TicksUntilShoot = 9; + Xarpus_previousAnimation = -1; + break; + case NpcID.VERZIK_VITUR_8369: + case NpcID.VERZIK_VITUR_8370: + case NpcID.VERZIK_VITUR_8371: + case NpcID.VERZIK_VITUR_8372: + case NpcID.VERZIK_VITUR_8373: + case NpcID.VERZIK_VITUR_8374: + case NpcID.VERZIK_VITUR_8375: + P3_TicksUntilAttack = -1; + P3_attacksLeft = 9; + redCrabsTimer = 13; + Verzik_NPC = npc; + runVerzik = true; + tornadoList = new ArrayList<>(); + crabList = new ArrayList<>(); + break; + } + } - if (o.getId() == GROUNDOBJECT_ID_REDMAZE) { - Tile t = event.getTile(); - WorldPoint p = t.getWorldLocation(); - if (p.getPlane() == 0) { - if (!RedTiles.containsValue(t)) { - RedTiles.put(o, t); - } - } else { - if (!RedTilesUnderworld.contains(p)) - RedTilesUnderworld.add(p); - } - } - } + @Subscribe + public void onNpcDespawned(NpcDespawned npcDespawned) + { + NPC npc = npcDespawned.getNpc(); + switch (npc.getId()) + { + case NpcID.THE_MAIDEN_OF_SUGADINTI: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8361: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8362: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8363: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8364: + case NpcID.THE_MAIDEN_OF_SUGADINTI_8365: + runMaiden = false; + Maiden_Spawns.clear(); + break; + case NpcID.BLOOD_SPAWN: + Maiden_Spawns.remove(npc); + break; + case NpcID.PESTILENT_BLOAT: + runBloat = false; + Bloat_NPC = null; + bloatTimer = 0; + break; + case NPCID_NYLOCAS_PILLAR: + if (Nylocas_Pillars.keySet().contains(npc)) + { + Nylocas_Pillars.remove(npc); + } + break; + case 8342: + case 8343: + case 8344: + case 8345: + case 8346: + case 8347: + case 8348: + case 8349: + case 8350: + case 8351: + case 8352: + case 8353: + if (Nylocas_Map.keySet().contains(npc)) + { + Nylocas_Map.remove(npc); + } + break; + case NpcID.SOTETSEG: + case NpcID.SOTETSEG_8388: + RedTiles.clear(); + if (client.getPlane() != 3) + { + runSotetseg = false; + } + break; + case NpcID.XARPUS: + case NpcID.XARPUS_8339: + case NpcID.XARPUS_8340: + case NpcID.XARPUS_8341: + runXarpus = false; + Xarpus_NPC = null; + Xarpus_Stare = false; + Xarpus_TicksUntilShoot = 9; + Xarpus_previousAnimation = -1; + Xarpus_Exhumeds.clear(); + exhumecount = 0; + break; + case NpcID.VERZIK_VITUR_8369: + case NpcID.VERZIK_VITUR_8370: + case NpcID.VERZIK_VITUR_8371: + case NpcID.VERZIK_VITUR_8372: + case NpcID.VERZIK_VITUR_8373: + case NpcID.VERZIK_VITUR_8374: + case NpcID.VERZIK_VITUR_8375: + runVerzik = false; + redCrabsTimer = 0; + Verzik_NPC = null; + break; + } - if (runXarpus) { - GroundObject o = event.getGroundObject(); - if (o.getId() == GROUNDOBJECT_ID_EXHUMED) { + } - xarpusExhumedsTimer.put(o, 11); + @Subscribe + public void onGroundObjectSpawned(GroundObjectSpawned event) + { + if (runSotetseg) + { + GroundObject o = event.getGroundObject(); + if (o.getId() == GROUNDOBJECT_ID_BLACKMAZE) + { + Tile t = event.getTile(); + WorldPoint p = t.getWorldLocation(); + if (t.getPlane() == 0) + { + if (!BlackTilesOverworld.contains(p)) + { + BlackTilesOverworld.add(p); + } + } + else + { + if (!BlackTilesUnderworld.contains(p)) + { + BlackTilesUnderworld.add(p); + } + } + } - Xarpus_Exhumeds.put(o, 11); + if (o.getId() == GROUNDOBJECT_ID_REDMAZE) + { + Tile t = event.getTile(); + WorldPoint p = t.getWorldLocation(); + if (p.getPlane() == 0) + { + if (!RedTiles.containsValue(t)) + { + RedTiles.put(o, t); + } + } + else + { + if (!RedTilesUnderworld.contains(p)) + { + RedTilesUnderworld.add(p); + } + } + } + } - } + if (runXarpus) + { + GroundObject o = event.getGroundObject(); + if (o.getId() == GROUNDOBJECT_ID_EXHUMED) + { - } - } + xarpusExhumedsTimer.put(o, 11); - @Subscribe - public void onProjectileMoved(ProjectileMoved event) { - if (runVerzik) { - Projectile projectile = event.getProjectile(); - if (projectile.getId() == PROJECTILE_ID_P2RANGE) { - WorldPoint p = WorldPoint.fromLocal(client, event.getPosition()); - Verzik_RangeProjectiles.put(projectile, p); - } - } - if (runSotetseg) + Xarpus_Exhumeds.put(o, 11); + + } + + } + } + + @Subscribe + public void onProjectileMoved(ProjectileMoved event) + { + if (runVerzik) { Projectile projectile = event.getProjectile(); - if (projectile.getId() == 1606) { + if (projectile.getId() == PROJECTILE_ID_P2RANGE) + { + WorldPoint p = WorldPoint.fromLocal(client, event.getPosition()); + Verzik_RangeProjectiles.put(projectile, p); + } + } + if (runSotetseg) + { + Projectile projectile = event.getProjectile(); + if (projectile.getId() == 1606) + { Sotetseg_MageProjectiles.add(projectile); } - if (projectile.getId() == 1607) { + if (projectile.getId() == 1607) + { Sotetseg_RangeProjectiles.add(projectile); } } - } + } - @Subscribe - public void onAnimationChanged(AnimationChanged event) { - if (runVerzik) { - if (event.getActor().getAnimation() == 8117) { - redCrabsTimer = 11; - } - } - } + @Subscribe + public void onAnimationChanged(AnimationChanged event) + { + if (runVerzik) + { + if (event.getActor().getAnimation() == 8117) + { + redCrabsTimer = 11; + } + } + } - @Subscribe - public void onVarbitChanged(VarbitChanged event) { - if (runBloat) { + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + if (runBloat) + { - if (client.getVar(Varbits.BLOAT_ENTERED_ROOM) == 1) { - if (!bloatFlag) { - bloatTimer = 0; - bloatFlag = true; - } - } - } - } + if (client.getVar(Varbits.BLOAT_ENTERED_ROOM) == 1) + { + if (!bloatFlag) + { + bloatTimer = 0; + bloatFlag = true; + } + } + } + } - @Subscribe - public void onGraphicsObjectCreated(GraphicsObjectCreated event) { - GraphicsObject obj = event.getGraphicsObject(); - if (obj.getId() == 1570 || obj.getId() == 1571 || obj.getId() == 1572 || obj.getId() == 1573 || obj.getId() == 1574 || obj.getId() == 1575 || obj.getId() == 1576) { - WorldPoint p = WorldPoint.fromLocal(client, obj.getLocation()); - if (temp.size() == 0) { + @Subscribe + public void onGraphicsObjectCreated(GraphicsObjectCreated event) + { + GraphicsObject obj = event.getGraphicsObject(); + if (obj.getId() == 1570 || obj.getId() == 1571 || obj.getId() == 1572 || obj.getId() == 1573 || obj.getId() == 1574 || obj.getId() == 1575 || obj.getId() == 1576) + { + WorldPoint p = WorldPoint.fromLocal(client, obj.getLocation()); + if (temp.size() == 0) + { - } else { + } + else + { - } - } - } + } + } + } - @Subscribe - public void onGameTick(GameTick event) { - if (runMaiden) { - Maiden_BloodSpatters.clear(); - for (GraphicsObject o : client.getGraphicsObjects()) { - if (o.getId() == GRAPHICSOBJECT_ID_MAIDEN) { - Maiden_BloodSpatters.add(WorldPoint.fromLocal(client, o.getLocation())); - } - } + @Subscribe + public void onGameTick(GameTick event) + { + if (runMaiden) + { + Maiden_BloodSpatters.clear(); + for (GraphicsObject o : client.getGraphicsObjects()) + { + if (o.getId() == GRAPHICSOBJECT_ID_MAIDEN) + { + Maiden_BloodSpatters.add(WorldPoint.fromLocal(client, o.getLocation())); + } + } - Maiden_SpawnLocations2.clear(); - Maiden_SpawnLocations2.addAll(Maiden_SpawnLocations); - Maiden_SpawnLocations.clear(); - for (NPC spawn : Maiden_Spawns) { - Maiden_SpawnLocations.add(spawn.getWorldLocation()); - } - } + Maiden_SpawnLocations2.clear(); + Maiden_SpawnLocations2.addAll(Maiden_SpawnLocations); + Maiden_SpawnLocations.clear(); + for (NPC spawn : Maiden_Spawns) + { + Maiden_SpawnLocations.add(spawn.getWorldLocation()); + } + } - if (runBloat) { + if (runBloat) + { - localTemp.clear(); + localTemp.clear(); - //System.out.println("Temp flag" + tempFlag); - //System.out.println("Temp2 flag" + temp2Flag); + //System.out.println("Temp flag" + tempFlag); + //System.out.println("Temp2 flag" + temp2Flag); - for (GraphicsObject obj : client.getGraphicsObjects()) { - if (obj.getId() == 1570 || obj.getId() == 1571 || obj.getId() == 1572 || obj.getId() == 1573 || obj.getId() == 1574 || obj.getId() == 1575 || obj.getId() == 1576) { - WorldPoint p = WorldPoint.fromLocal(client, obj.getLocation()); - //Already have some feet in temp Set - if (temp.size() > 0) { - //System.out.println("temp size > 0, tempflag set false, tempflag2 set true"); - tempFlag = false; - temp2Flag = true; - } else { - //System.out.println("temp size 0, tempflag set true, tempflag2 set false"); - tempFlag = true; - temp2Flag = false; + for (GraphicsObject obj : client.getGraphicsObjects()) + { + if (obj.getId() == 1570 || obj.getId() == 1571 || obj.getId() == 1572 || obj.getId() == 1573 || obj.getId() == 1574 || obj.getId() == 1575 || obj.getId() == 1576) + { + WorldPoint p = WorldPoint.fromLocal(client, obj.getLocation()); + //Already have some feet in temp Set + if (temp.size() > 0) + { + //System.out.println("temp size > 0, tempflag set false, tempflag2 set true"); + tempFlag = false; + temp2Flag = true; + } + else + { + //System.out.println("temp size 0, tempflag set true, tempflag2 set false"); + tempFlag = true; + temp2Flag = false; - } - localTemp.add(p); - } - } + } + localTemp.add(p); + } + } - if (tempFlag) { - temp2.clear(); - temp2Flag = false; - temp.addAll(localTemp); + if (tempFlag) + { + temp2.clear(); + temp2Flag = false; + temp.addAll(localTemp); - //System.out.println("temp2 cleared, temp2flag set false, added to temp set"); - } else if (temp2Flag) { - temp.clear(); - tempFlag = false; - temp2.addAll(localTemp); - //System.out.println("temp cleared, tempflag set false, added to temp2 set"); + //System.out.println("temp2 cleared, temp2flag set false, added to temp set"); + } + else if (temp2Flag) + { + temp.clear(); + tempFlag = false; + temp2.addAll(localTemp); + //System.out.println("temp cleared, tempflag set false, added to temp2 set"); - } + } - Bloat_downCount++; + Bloat_downCount++; - if (Bloat_NPC.getAnimation() == -1) //1 = up; 2 = down; 3 = warn; - { - bloatTimer++; - Bloat_downCount = 0; - if (Bloat_NPC.getHealth() == 0) { - Bloat_State = 2; - } else - Bloat_State = 1; - } else { - if (25 < Bloat_downCount && Bloat_downCount < 35) { - Bloat_State = 3; - } else if (Bloat_downCount < 26) { - tempFlag = false; - temp2Flag = false; - temp2.clear(); - temp.clear(); - Bloat_State = 2; - bloatTimer = 0; - } else if (Bloat_NPC.getModelHeight() == 568) { - tempFlag = false; - temp2Flag = false; - temp2.clear(); - temp.clear(); - Bloat_State = 2; - } else - Bloat_State = 1; + if (Bloat_NPC.getAnimation() == -1) //1 = up; 2 = down; 3 = warn; + { + bloatTimer++; + Bloat_downCount = 0; + if (Bloat_NPC.getHealth() == 0) + { + Bloat_State = 2; + } + else + { + Bloat_State = 1; + } + } + else + { + if (25 < Bloat_downCount && Bloat_downCount < 35) + { + Bloat_State = 3; + } + else if (Bloat_downCount < 26) + { + tempFlag = false; + temp2Flag = false; + temp2.clear(); + temp.clear(); + Bloat_State = 2; + bloatTimer = 0; + } + else if (Bloat_NPC.getModelHeight() == 568) + { + tempFlag = false; + temp2Flag = false; + temp2.clear(); + temp.clear(); + Bloat_State = 2; + } + else + { + Bloat_State = 1; + } - } - } + } + } - if (runNylocas) { - for (Iterator it = Nylocas_Map.keySet().iterator(); it.hasNext(); ) { - NPC npc = it.next(); - int ticksLeft = Nylocas_Map.get(npc); + if (runNylocas) + { + for (Iterator it = Nylocas_Map.keySet().iterator(); it.hasNext(); ) + { + NPC npc = it.next(); + int ticksLeft = Nylocas_Map.get(npc); - if (ticksLeft < 0) { - it.remove(); - continue; - } - Nylocas_Map.replace(npc, ticksLeft - 1); - } + if (ticksLeft < 0) + { + it.remove(); + continue; + } + Nylocas_Map.replace(npc, ticksLeft - 1); + } - for (NPC pillar : Nylocas_Pillars.keySet()) { - int healthPercent = pillar.getHealthRatio(); - if (healthPercent > -1) { - Nylocas_Pillars.replace(pillar, healthPercent); - } - } - for (NPC npc : client.getNpcs()) { - if (npc.getId() == 8358) { - runNylocas = true; - break; - } - runNylocas = false; - BossNylo = null; - } - } + for (NPC pillar : Nylocas_Pillars.keySet()) + { + int healthPercent = pillar.getHealthRatio(); + if (healthPercent > -1) + { + Nylocas_Pillars.replace(pillar, healthPercent); + } + } + for (NPC npc : client.getNpcs()) + { + if (npc.getId() == 8358) + { + runNylocas = true; + break; + } + runNylocas = false; + BossNylo = null; + } + } - if (runSotetseg) { - boolean sotetsegFighting = false; - for (NPC npc : client.getNpcs()) { - if (npc.getId() == NpcID.SOTETSEG_8388) { - BlackTilesUnderworld.clear(); - BlackTilesOverworld.clear(); - RedTilesOverworld.clear(); - RedTilesUnderworld.clear(); - GridPath.clear(); - sotetsegFighting = true; - RedTiles.clear(); - break; - } - } + if (runSotetseg) + { + boolean sotetsegFighting = false; + for (NPC npc : client.getNpcs()) + { + if (npc.getId() == NpcID.SOTETSEG_8388) + { + BlackTilesUnderworld.clear(); + BlackTilesOverworld.clear(); + RedTilesOverworld.clear(); + RedTilesUnderworld.clear(); + GridPath.clear(); + sotetsegFighting = true; + RedTiles.clear(); + break; + } + } - if (!getSotetseg_MageProjectiles().isEmpty()) { - for (Iterator it = Sotetseg_MageProjectiles.iterator(); it.hasNext(); ) { + if (!getSotetseg_MageProjectiles().isEmpty()) + { + for (Iterator it = Sotetseg_MageProjectiles.iterator(); it.hasNext(); ) + { Projectile projectile = it.next(); - if (projectile.getRemainingCycles() < 1) { + if (projectile.getRemainingCycles() < 1) + { it.remove(); } } } - if (!getSotetseg_RangeProjectiles().isEmpty()) { - for (Iterator it = Sotetseg_RangeProjectiles.iterator(); it.hasNext(); ) { + if (!getSotetseg_RangeProjectiles().isEmpty()) + { + for (Iterator it = Sotetseg_RangeProjectiles.iterator(); it.hasNext(); ) + { Projectile projectile = it.next(); - if (projectile.getRemainingCycles() < 1) { + if (projectile.getRemainingCycles() < 1) + { it.remove(); } } } - if (!sotetsegFighting) { - if (!BlackTilesUnderworld.isEmpty() && !RedTilesUnderworld.isEmpty() && GridPath.isEmpty()) { - int minX = 99999; - int minY = 99999; - for (WorldPoint p : BlackTilesUnderworld) { - int x = p.getX(); - int y = p.getY(); - if (x < minX) { - minX = x; - } - if (y < minY) { - minY = y; - } - } + if (!sotetsegFighting) + { + if (!BlackTilesUnderworld.isEmpty() && !RedTilesUnderworld.isEmpty() && GridPath.isEmpty()) + { + int minX = 99999; + int minY = 99999; + for (WorldPoint p : BlackTilesUnderworld) + { + int x = p.getX(); + int y = p.getY(); + if (x < minX) + { + minX = x; + } + if (y < minY) + { + minY = y; + } + } - boolean messageSent = false; - for (WorldPoint p : RedTilesUnderworld) { - WorldPoint pN = new WorldPoint(p.getX(), p.getY() + 1, p.getPlane()); - WorldPoint pS = new WorldPoint(p.getX(), p.getY() - 1, p.getPlane()); - WorldPoint pE = new WorldPoint(p.getX() + 1, p.getY(), p.getPlane()); - WorldPoint pW = new WorldPoint(p.getX() - 1, p.getY(), p.getPlane()); + boolean messageSent = false; + for (WorldPoint p : RedTilesUnderworld) + { + WorldPoint pN = new WorldPoint(p.getX(), p.getY() + 1, p.getPlane()); + WorldPoint pS = new WorldPoint(p.getX(), p.getY() - 1, p.getPlane()); + WorldPoint pE = new WorldPoint(p.getX() + 1, p.getY(), p.getPlane()); + WorldPoint pW = new WorldPoint(p.getX() - 1, p.getY(), p.getPlane()); - if (!((RedTilesUnderworld.contains(pN) && RedTilesUnderworld.contains(pS)) || - (RedTilesUnderworld.contains(pE) && RedTilesUnderworld.contains(pW)))) { - GridPath.add(new Point(p.getX() - minX, p.getY() - minY)); - if (!messageSent) { - //client.addChatMessage(ChatMessageType.SERVER, "", "Maze path acquired.", null); - messageSent = true; - } - } + if (!((RedTilesUnderworld.contains(pN) && RedTilesUnderworld.contains(pS)) || + (RedTilesUnderworld.contains(pE) && RedTilesUnderworld.contains(pW)))) + { + GridPath.add(new Point(p.getX() - minX, p.getY() - minY)); + if (!messageSent) + { + //client.addChatMessage(ChatMessageType.SERVER, "", "Maze path acquired.", null); + messageSent = true; + } + } - } - } + } + } - if (!BlackTilesOverworld.isEmpty() && !GridPath.isEmpty() && RedTilesOverworld.isEmpty()) { - int minX = 99999; - int minY = 99999; - for (WorldPoint p : BlackTilesOverworld) { - int x = p.getX(); - int y = p.getY(); - if (x < minX) { - minX = x; - } - if (y < minY) { - minY = y; - } - } - for (Point p : GridPath) { - RedTilesOverworld.add(new WorldPoint(minX + p.getX(), minY + p.getY(), 0)); - } - } - } - } + if (!BlackTilesOverworld.isEmpty() && !GridPath.isEmpty() && RedTilesOverworld.isEmpty()) + { + int minX = 99999; + int minY = 99999; + for (WorldPoint p : BlackTilesOverworld) + { + int x = p.getX(); + int y = p.getY(); + if (x < minX) + { + minX = x; + } + if (y < minY) + { + minY = y; + } + } + for (Point p : GridPath) + { + RedTilesOverworld.add(new WorldPoint(minX + p.getX(), minY + p.getY(), 0)); + } + } + } + } - if (runXarpus) { - int size = xarpusExhumedsTimer.size(); - for (Map.Entry exhumes : xarpusExhumedsTimer.entrySet()) { - if (size > 0) { - exhumes.setValue(exhumes.getValue() - 1); - } + if (runXarpus) + { + int size = xarpusExhumedsTimer.size(); + for (Map.Entry exhumes : xarpusExhumedsTimer.entrySet()) + { + if (size > 0) + { + exhumes.setValue(exhumes.getValue() - 1); + } - } - for (Iterator it = Xarpus_Exhumeds.keySet().iterator(); it.hasNext(); ) { - GroundObject key = it.next(); - Xarpus_Exhumeds.replace(key, Xarpus_Exhumeds.get(key) - 1); - if (Xarpus_Exhumeds.get(key) < 0) { - it.remove(); - exhumecount--; - } - } - if ((Xarpus_NPC.getComposition().getOverheadIcon() != null)) { - Xarpus_Stare = true; - } - if (Xarpus_Stare) { - //dont hit xarpus if it looking at u - } else if (Xarpus_NPC.getId() == NpcID.XARPUS_8340) { - Xarpus_TicksUntilShoot--; - //if (Xarpus_NPC.getAnimation() == ANIMATION_ID_XARPUS && Xarpus_previousAnimation != ANIMATION_ID_XARPUS) - //{ - //Xarpus_TicksUntilShoot = 3; - //} - //Xarpus_previousAnimation = Xarpus_NPC.getAnimation(); - } + } + for (Iterator it = Xarpus_Exhumeds.keySet().iterator(); it.hasNext(); ) + { + GroundObject key = it.next(); + Xarpus_Exhumeds.replace(key, Xarpus_Exhumeds.get(key) - 1); + if (Xarpus_Exhumeds.get(key) < 0) + { + it.remove(); + exhumecount--; + } + } + if ((Xarpus_NPC.getComposition().getOverheadIcon() != null)) + { + Xarpus_Stare = true; + } + if (Xarpus_Stare) + { + //dont hit xarpus if it looking at u + } + else if (Xarpus_NPC.getId() == NpcID.XARPUS_8340) + { + Xarpus_TicksUntilShoot--; + //if (Xarpus_NPC.getAnimation() == ANIMATION_ID_XARPUS && Xarpus_previousAnimation != ANIMATION_ID_XARPUS) + //{ + //Xarpus_TicksUntilShoot = 3; + //} + //Xarpus_previousAnimation = Xarpus_NPC.getAnimation(); + } - } + } - if (runVerzik) { - crabList.clear(); - for (NPC npc : client.getNpcs()) { + if (runVerzik) + { + crabList.clear(); + for (NPC npc : client.getNpcs()) + { - if (npc.getName().toLowerCase().contains("nylo")) { - crabList.add(npc); - } - } + if (npc.getName().toLowerCase().contains("nylo")) + { + crabList.add(npc); + } + } - if (Verzik_NPC.getAnimation() == 8117) { - redCrabsTimer = redCrabsTimer - 1; - } - if (!Verzik_RangeProjectiles.isEmpty()) { - for (Iterator it = Verzik_RangeProjectiles.keySet().iterator(); it.hasNext(); ) { - Projectile projectile = it.next(); - if (projectile.getRemainingCycles() < 1) { - it.remove(); - } - } - } + if (Verzik_NPC.getAnimation() == 8117) + { + redCrabsTimer = redCrabsTimer - 1; + } + if (!Verzik_RangeProjectiles.isEmpty()) + { + for (Iterator it = Verzik_RangeProjectiles.keySet().iterator(); it.hasNext(); ) + { + Projectile projectile = it.next(); + if (projectile.getRemainingCycles() < 1) + { + it.remove(); + } + } + } - Verzik_YellowBall = null; - Verzik_YellowTiles.clear(); + Verzik_YellowBall = null; + Verzik_YellowTiles.clear(); - for (Projectile projectile : client.getProjectiles()) { - if (projectile.getId() == PROJECTILE_ID_YELLOW) { - Verzik_YellowBall = projectile; - break; - } - } - for (GraphicsObject o : client.getGraphicsObjects()) { - if (o.getId() == GRAPHICSOBJECT_ID_YELLOW) { + for (Projectile projectile : client.getProjectiles()) + { + if (projectile.getId() == PROJECTILE_ID_YELLOW) + { + Verzik_YellowBall = projectile; + break; + } + } + for (GraphicsObject o : client.getGraphicsObjects()) + { + if (o.getId() == GRAPHICSOBJECT_ID_YELLOW) + { - Verzik_YellowTiles.add(WorldPoint.fromLocal(client, o.getLocation())); - } - } + Verzik_YellowTiles.add(WorldPoint.fromLocal(client, o.getLocation())); + } + } - if (Verzik_NPC.getId() == VERZIK_ID_P3) { - boolean tornadosActive = false; - for (NPC npc : client.getNpcs()) { - if (npc.getId() == NPC_ID_TORNADO) { - tornadoList.add(npc); - tornadosActive = true; - break; - } - } + if (Verzik_NPC.getId() == VERZIK_ID_P3) + { + boolean tornadosActive = false; + for (NPC npc : client.getNpcs()) + { + if (npc.getId() == NPC_ID_TORNADO) + { + tornadoList.add(npc); + tornadosActive = true; + break; + } + } - boolean isGreenBall = false; - for (Projectile projectile : client.getProjectiles()) { - if (projectile.getId() == PROJECTILE_ID_P3_GREEN) { - isGreenBall = projectile.getRemainingCycles() > 210; - break; - } - } + boolean isGreenBall = false; + for (Projectile projectile : client.getProjectiles()) + { + if (projectile.getId() == PROJECTILE_ID_P3_GREEN) + { + isGreenBall = projectile.getRemainingCycles() > 210; + break; + } + } - P3_TicksUntilAttack--; + P3_TicksUntilAttack--; - switch (Verzik_NPC.getAnimation()) { - case ANIMATION_ID_P3_MAGE: - if (P3_TicksUntilAttack < 2) { - P3_attacksLeft--; - if (tornadosActive) { - P3_TicksUntilAttack = 5; - } else { - P3_TicksUntilAttack = 7; - } - if (P3_attacksLeft < 1) { - P3_TicksUntilAttack = 24; - } - } - break; - case ANIMATION_ID_P3_RANGE: - if (P3_TicksUntilAttack < 2) { - P3_attacksLeft--; - if (tornadosActive) { - P3_TicksUntilAttack = 5; - } else { - P3_TicksUntilAttack = 7; - } - if (P3_attacksLeft < 1) { - P3_TicksUntilAttack = 30; - } - if (isGreenBall) { - P3_TicksUntilAttack = 12; - } - } - break; - case ANIMATION_ID_P3_MELEE: - if (P3_TicksUntilAttack < 2) { - P3_attacksLeft--; - if (tornadosActive) { - P3_TicksUntilAttack = 5; - } else { - P3_TicksUntilAttack = 7; - } - if (P3_attacksLeft < 1) { - P3_TicksUntilAttack = 24; - } - } - break; - case ANIMATION_ID_P3_WEB: - P3_attacksLeft = 4; - P3_TicksUntilAttack = 11; // - break; - case ANIMATION_ID_P3_YELLOW: - P3_attacksLeft = 14; - P3_TicksUntilAttack = 11; - break; - } - } + switch (Verzik_NPC.getAnimation()) + { + case ANIMATION_ID_P3_MAGE: + if (P3_TicksUntilAttack < 2) + { + P3_attacksLeft--; + if (tornadosActive) + { + P3_TicksUntilAttack = 5; + } + else + { + P3_TicksUntilAttack = 7; + } + if (P3_attacksLeft < 1) + { + P3_TicksUntilAttack = 24; + } + } + break; + case ANIMATION_ID_P3_RANGE: + if (P3_TicksUntilAttack < 2) + { + P3_attacksLeft--; + if (tornadosActive) + { + P3_TicksUntilAttack = 5; + } + else + { + P3_TicksUntilAttack = 7; + } + if (P3_attacksLeft < 1) + { + P3_TicksUntilAttack = 30; + } + if (isGreenBall) + { + P3_TicksUntilAttack = 12; + } + } + break; + case ANIMATION_ID_P3_MELEE: + if (P3_TicksUntilAttack < 2) + { + P3_attacksLeft--; + if (tornadosActive) + { + P3_TicksUntilAttack = 5; + } + else + { + P3_TicksUntilAttack = 7; + } + if (P3_attacksLeft < 1) + { + P3_TicksUntilAttack = 24; + } + } + break; + case ANIMATION_ID_P3_WEB: + P3_attacksLeft = 4; + P3_TicksUntilAttack = 11; // + break; + case ANIMATION_ID_P3_YELLOW: + P3_attacksLeft = 14; + P3_TicksUntilAttack = 11; + break; + } + } - } + } - } + } - private void stripEntries(int style, String target, int NyloID) { - String Keep = null; - if (NyloID == 0) { - switch (style) { - case 1: - Keep = "Nylocas Ischyros"; - break; - case 2: + private void stripEntries(int style, String target, int NyloID) + { + String Keep = null; + if (NyloID == 0) + { + switch (style) + { + case 1: + Keep = "Nylocas Ischyros"; + break; + case 2: Keep = "Nylocas Toxobolos"; - break; - case 3: - Keep = "Nylocas Hagios"; - break; - } - } else { - Keep = "fuckaadamhypocrticalpos"; - switch (NyloID) { - case 8356://0=idk 1= melee 2= range 3= mage - if (style == 3) { + break; + case 3: + Keep = "Nylocas Hagios"; + break; + } + } + else + { + Keep = "fuckaadamhypocrticalpos"; + switch (NyloID) + { + case 8356://0=idk 1= melee 2= range 3= mage + if (style == 3) + { - Keep = "Nylocas Vasilias"; - } - break; - case 8357: - if (style == 2) { - Keep = "Nylocas Vasilias"; - } - break; - default: - if (style == 1) { - Keep = "Nylocas Vasilias"; - } - } + Keep = "Nylocas Vasilias"; + } + break; + case 8357: + if (style == 2) + { + Keep = "Nylocas Vasilias"; + } + break; + default: + if (style == 1) + { + Keep = "Nylocas Vasilias"; + } + } - } - int entryLength = 0; - List entryList = new ArrayList<>(); - for (MenuEntry entry : client.getMenuEntries()) { - if (Text.removeTags(entry.getTarget()).contains(Keep) && entry.getOption().equals("Attack")) { + } + int entryLength = 0; + List entryList = new ArrayList<>(); + for (MenuEntry entry : client.getMenuEntries()) + { + if (Text.removeTags(entry.getTarget()).contains(Keep) && entry.getOption().equals("Attack")) + { - entryList.add(entry); - entryLength++; - } - if (entry.getOption().equalsIgnoreCase("walk here") || entry.getOption().equalsIgnoreCase("pass") || entry.getOption().equalsIgnoreCase("take")) { - entryList.add(entry); - entryLength++; - } - } + entryList.add(entry); + entryLength++; + } + if (entry.getOption().equalsIgnoreCase("walk here") || entry.getOption().equalsIgnoreCase("pass") || entry.getOption().equalsIgnoreCase("take")) + { + entryList.add(entry); + entryLength++; + } + } - //System.out.println("i see " + entryLength + " good options using style" + style); - if (entryLength != 0) { - MenuEntry[] newEntries = new MenuEntry[entryLength]; + //System.out.println("i see " + entryLength + " good options using style" + style); + if (entryLength != 0) + { + MenuEntry[] newEntries = new MenuEntry[entryLength]; - for (int i = 0; i < (entryLength); i++) { - newEntries[i] = entryList.get(i); - } - client.setMenuEntries(newEntries); - } + for (int i = 0; i < (entryLength); i++) + { + newEntries[i] = entryList.get(i); + } + client.setMenuEntries(newEntries); + } - } + } - private int searchIndex(MenuEntry[] entries, String option, String target, boolean strict) { - for (int i = entries.length - 1; i >= 0; i--) { - MenuEntry entry = entries[i]; - String entryOption = Text.removeTags(entry.getOption()).toLowerCase(); - String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase(); + private int searchIndex(MenuEntry[] entries, String option, String target, boolean strict) + { + for (int i = entries.length - 1; i >= 0; i--) + { + MenuEntry entry = entries[i]; + String entryOption = Text.removeTags(entry.getOption()).toLowerCase(); + String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase(); - if (strict) { - if (entryOption.equals(option) && entryTarget.equals(target)) { - return i; - } - } else { - if (entryOption.contains(option.toLowerCase()) && entryTarget.equals(target)) { - return i; - } - } - } + if (strict) + { + if (entryOption.equals(option) && entryTarget.equals(target)) + { + return i; + } + } + else + { + if (entryOption.contains(option.toLowerCase()) && entryTarget.equals(target)) + { + return i; + } + } + } - return -1; - } + return -1; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreXarpusOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreXarpusOverlay.java index f5b0db1508..a9aad8eaf9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreXarpusOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/TheatreXarpusOverlay.java @@ -1,69 +1,74 @@ -package net.runelite.client.plugins.ztob; - -import com.google.inject.Inject; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; -import net.runelite.client.ui.overlay.Overlay; -import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; -import net.runelite.client.ui.overlay.OverlayMenuEntry; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -public class TheatreXarpusOverlay extends Overlay { - private final TheatrePlugin plugin; - private final TheatreConfig config; - PanelComponent panelComponent = new PanelComponent(); - - @Inject - private TheatreXarpusOverlay(TheatrePlugin plugin, TheatreConfig config) - { - super(plugin); - setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT); - setPosition(OverlayPosition.DYNAMIC); - setPosition(OverlayPosition.DETACHED); - this.plugin = plugin; - this.config = config; - getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Theatre xarpus overlay")); - - } - @Override - public Dimension render(Graphics2D graphics) { - if (plugin.isRunXarpus()) - { - if (config.XarpusExhumeOverlay()) { - if (plugin.getXarpus_NPC().getId() == 8339) { - panelComponent.getChildren().clear(); - String overlayTitle = "Exhume Counter"; - - - // Build overlay title - panelComponent.getChildren().add(TitleComponent.builder() - .text(overlayTitle) - .color(Color.GREEN) - .build()); - - //Set the size of overlay - panelComponent.setPreferredSize(new Dimension( - graphics.getFontMetrics().stringWidth(overlayTitle) + 30, 0 - )); - - panelComponent.getChildren().add(LineComponent.builder() - .left("Exhumes: ") - .right(String.valueOf(plugin.getExhumecount())) - .build()); - } - } - return panelComponent.render(graphics); - } - - return null; - - } - - -} - +package net.runelite.client.plugins.ztob; + +import com.google.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.client.ui.overlay.Overlay; +import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +public class TheatreXarpusOverlay extends Overlay +{ + private final TheatrePlugin plugin; + private final TheatreConfig config; + PanelComponent panelComponent = new PanelComponent(); + + @Inject + private TheatreXarpusOverlay(TheatrePlugin plugin, TheatreConfig config) + { + super(plugin); + setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT); + setPosition(OverlayPosition.DYNAMIC); + setPosition(OverlayPosition.DETACHED); + this.plugin = plugin; + this.config = config; + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Theatre xarpus overlay")); + + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (plugin.isRunXarpus()) + { + if (config.XarpusExhumeOverlay()) + { + if (plugin.getXarpus_NPC().getId() == 8339) + { + panelComponent.getChildren().clear(); + String overlayTitle = "Exhume Counter"; + + + // Build overlay title + panelComponent.getChildren().add(TitleComponent.builder() + .text(overlayTitle) + .color(Color.GREEN) + .build()); + + //Set the size of overlay + panelComponent.setPreferredSize(new Dimension( + graphics.getFontMetrics().stringWidth(overlayTitle) + 30, 0 + )); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Exhumes: ") + .right(String.valueOf(plugin.getExhumecount())) + .build()); + } + } + return panelComponent.render(graphics); + } + + return null; + + } + + +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/VerzikNyloOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/VerzikNyloOverlay.java index 14294a82cf..dc3cfc9d31 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ztob/VerzikNyloOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ztob/VerzikNyloOverlay.java @@ -1,102 +1,104 @@ -package net.runelite.client.plugins.ztob; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.NPC; -import net.runelite.api.Point; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.OverlayUtil; - -public class VerzikNyloOverlay extends Overlay { - - private final Client client; - private final TheatrePlugin plugin; - private final TheatreConfig config; - - @Inject - private VerzikNyloOverlay(Client client, TheatrePlugin plugin, TheatreConfig config) { - this.client = client; - this.plugin = plugin; - this.config = config; - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.HIGH); - setLayer(OverlayLayer.ABOVE_SCENE); - } - - public Dimension render(Graphics2D graphics) - { - - if (plugin.isRunVerzik()) - { - if (config.NyloTargetOverlay()) - { - if (plugin.getCrabList().size() > 0) - { - - for (NPC npc : plugin.getCrabList()) - { - if (npc.isDead()) - { - continue; - } - String renderText = ""; - if (npc.getInteracting() != null) - { - - renderText = npc.getInteracting().getName(); - Point point = npc.getCanvasTextLocation(graphics, npc.getInteracting().getName(), 0); - - - if (npc.getInteracting().getName().toLowerCase().equals(client.getLocalPlayer().getName().toLowerCase())) - { - point = npc.getCanvasTextLocation(graphics, client.getLocalPlayer().getName(), 0); - renderText = "YOU NIGGA RUN!"; - - } - else if (npc.getInteracting().getName().toLowerCase().equals("afyy")) - { - point = npc.getCanvasTextLocation(graphics, "Ricecup", 0); - renderText = "Ricecup"; - } - if (renderText.equals("YOU NIGGA RUN!")) - { - renderTextLocation(graphics, renderText, 12, Font.BOLD, Color.RED, point); - } - else - { - renderTextLocation(graphics, renderText, 12, Font.BOLD, Color.GREEN, point); - } - } - - } - } - - } - } - - return null; - } - - private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, Point canvasPoint) - { - graphics.setFont(new Font("Arial", fontStyle, fontSize)); - if (canvasPoint != null) - { - final Point canvasCenterPoint = new Point( - canvasPoint.getX(), - canvasPoint.getY()); - final Point canvasCenterPoint_shadow = new Point( - canvasPoint.getX() + 1, - canvasPoint.getY() + 1); - OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); - OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); - } - } -} +package net.runelite.client.plugins.ztob; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.Point; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; + +public class VerzikNyloOverlay extends Overlay +{ + + private final Client client; + private final TheatrePlugin plugin; + private final TheatreConfig config; + + @Inject + private VerzikNyloOverlay(Client client, TheatrePlugin plugin, TheatreConfig config) + { + this.client = client; + this.plugin = plugin; + this.config = config; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGH); + setLayer(OverlayLayer.ABOVE_SCENE); + } + + public Dimension render(Graphics2D graphics) + { + + if (plugin.isRunVerzik()) + { + if (config.NyloTargetOverlay()) + { + if (plugin.getCrabList().size() > 0) + { + + for (NPC npc : plugin.getCrabList()) + { + if (npc.isDead()) + { + continue; + } + String renderText = ""; + if (npc.getInteracting() != null) + { + + renderText = npc.getInteracting().getName(); + Point point = npc.getCanvasTextLocation(graphics, npc.getInteracting().getName(), 0); + + + if (npc.getInteracting().getName().toLowerCase().equals(client.getLocalPlayer().getName().toLowerCase())) + { + point = npc.getCanvasTextLocation(graphics, client.getLocalPlayer().getName(), 0); + renderText = "YOU NIGGA RUN!"; + + } + else if (npc.getInteracting().getName().toLowerCase().equals("afyy")) + { + point = npc.getCanvasTextLocation(graphics, "Ricecup", 0); + renderText = "Ricecup"; + } + if (renderText.equals("YOU NIGGA RUN!")) + { + renderTextLocation(graphics, renderText, 12, Font.BOLD, Color.RED, point); + } + else + { + renderTextLocation(graphics, renderText, 12, Font.BOLD, Color.GREEN, point); + } + } + + } + } + + } + } + + return null; + } + + private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, Point canvasPoint) + { + graphics.setFont(new Font("Arial", fontStyle, fontSize)); + if (canvasPoint != null) + { + final Point canvasCenterPoint = new Point( + canvasPoint.getX(), + canvasPoint.getY()); + final Point canvasCenterPoint_shadow = new Point( + canvasPoint.getX() + 1, + canvasPoint.getY() + 1); + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); + } + } +} From 53a82699e4c95d2c2148c6ba779824b0c154d4d8 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2019 05:11:02 +0200 Subject: [PATCH 20/78] more checkstyle etc --- .../runelite/client/ClientSessionManager.java | 2 +- .../java/net/runelite/client/Notifier.java | 2 +- .../java/net/runelite/client/RuneLite.java | 7 +- .../runelite/client/RuneLiteProperties.java | 7 +- .../net/runelite/client/SessionClient.java | 2 +- .../client/account/SessionManager.java | 464 +++---- .../net/runelite/client/callback/Hooks.java | 1 + .../config/ConfigInvocationHandler.java | 306 ++--- .../client/config/ConfigItemsGroup.java | 104 +- .../runelite/client/config/ConfigManager.java | 36 +- .../net/runelite/client/config/FontType.java | 97 +- .../client/config/RuneLiteConfig.java | 2 +- .../client/discord/DiscordService.java | 2 +- .../java/net/runelite/client/flexo/Flexo.java | 485 ++++--- .../net/runelite/client/flexo/FlexoMouse.java | 319 +++-- .../runelite/client/game/AgilityShortcut.java | 292 ++++- .../client/game/AsyncBufferedImage.java | 169 +-- .../net/runelite/client/game/ItemManager.java | 1061 ++++++++------- .../net/runelite/client/game/ItemMapping.java | 946 ++++++++++---- .../net/runelite/client/game/NPCManager.java | 131 +- .../game/chatbox/ChatboxPanelManager.java | 404 +++--- .../game/chatbox/ChatboxTextMenuInput.java | 426 +++--- .../client/graphics/ModelOutlineRenderer.java | 6 +- .../client/menus/WidgetMenuOption.java | 211 ++- .../plugins/blackjack/BlackjackPlugin.java | 8 +- .../combatlevel/CombatLevelOverlay.java | 2 +- .../client/plugins/config/PluginListItem.java | 6 +- .../demonicgorilla/DemonicGorillaPlugin.java | 2 +- .../plugins/easyscape/EasyscapePlugin.java | 10 +- .../plugins/freezetimers/PrayerTracker.java | 5 +- .../friendtagging/FriendTaggingPlugin.java | 2 +- .../client/plugins/gpu/GpuPlugin.java | 8 +- .../instancemap/InstanceMapOverlay.java | 2 +- .../ui/InventorySetupContainerPanel.java | 258 ++-- .../ui/InventorySetupPluginPanel.java | 612 ++++----- .../plugins/itemstats/ItemStatPlugin.java | 10 +- .../plugins/mta/graveyard/GraveyardRoom.java | 2 +- .../PlayerIndicatorsConfig.java | 4 +- .../PlayerIndicatorsMinimapOverlay.java | 2 +- .../PlayerIndicatorsOverlay.java | 2 +- .../PlayerIndicatorsPlugin.java | 2 +- .../playerinfo/PlayerInfoCustomIndicator.java | 1 + .../solver/pathfinding/IDAStarMM.java | 4 +- .../pyramidplunder/PyramidPlunderPlugin.java | 1 + .../client/plugins/raids/RaidsPlugin.java | 12 +- .../BatSolver/ThievingRoomType.java | 122 +- .../raidsthieving/RaidsThievingPlugin.java | 2 +- .../plugins/regenmeter/RegenMeterOverlay.java | 242 ++-- .../plugins/runecraft/RunecraftPlugin.java | 5 - .../plugins/runedoku/RunedokuOverlay.java | 12 +- .../client/plugins/runedoku/RunedokuUtil.java | 12 +- .../runeliteplus/RuneLitePlusPlugin.java | 4 +- .../plugins/slayer/SlayerTaskPanel.java | 6 +- .../plugins/slayer/TargetClickboxOverlay.java | 2 +- .../client/plugins/slayer/TaskBox.java | 3 +- .../tickcounter/TickCounterOverlay.java | 3 +- .../timetracking/OverviewTabPanel.java | 2 +- .../timetracking/TimeTrackingPanel.java | 2 +- .../timetracking/farming/FarmingTracker.java | 2 +- .../timetracking/hunter/BirdHouseTracker.java | 2 +- .../whalewatchers/WhaleWatchersPlugin.java | 2 +- .../wiki/WikiSearchChatboxTextInput.java | 2 +- .../net/runelite/client/rs/ClientLoader.java | 87 +- .../client/rs/mixins/MixinRunner.java | 53 +- .../transformers/AppendTransformer.java | 40 +- .../transformers/InjectTransformer.java | 26 +- .../transformers/InterfaceTransformer.java | 19 +- .../mixins/transformers/MethodReflector.java | 64 +- .../transformers/OverwriteSanityCheck.java | 23 +- .../transformers/OverwriteTransformer.java | 26 +- .../transformers/PrependTransformer.java | 36 +- .../transformers/ProtectTransformer.java | 6 +- .../rs/mixins/transformers/SanityChecker.java | 2 +- .../net/runelite/client/ui/ClientPanel.java | 130 +- .../java/net/runelite/client/ui/ClientUI.java | 13 +- .../runelite/client/ui/ContainableFrame.java | 402 +++--- .../runelite/client/ui/DynamicGridLayout.java | 429 +++--- .../net/runelite/client/ui/FontManager.java | 192 +-- .../client/ui/RuneLiteSplashScreen.java | 491 +++---- .../client/ui/components/DimmableJPanel.java | 181 +-- .../client/ui/components/ThinProgressBar.java | 188 +-- .../runelite/client/ui/overlay/Overlay.java | 143 +- .../client/ui/overlay/OverlayManager.java | 768 +++++------ .../client/ui/overlay/OverlayRenderer.java | 1162 ++++++++--------- .../client/ui/overlay/OverlayUtil.java | 11 +- .../client/ui/overlay/WidgetOverlay.java | 8 +- .../ui/overlay/arrow/ArrowMinimapOverlay.java | 5 +- .../ui/overlay/arrow/ArrowPointManager.java | 118 +- .../components/BackgroundComponent.java | 196 +-- .../LayoutableRenderableEntity.java | 76 +- .../ui/overlay/components/PanelComponent.java | 20 +- .../overlay/components/TooltipComponent.java | 440 +++---- .../ui/overlay/infobox/InfoBoxManager.java | 332 ++--- .../ui/overlay/worldmap/WorldMapOverlay.java | 623 ++++----- .../net/runelite/client/util/ColorUtil.java | 485 +++---- .../net/runelite/client/util/ImageUtil.java | 57 +- .../net/runelite/client/util/LinkBrowser.java | 302 ++--- .../net/runelite/client/util/MenuUtil.java | 8 +- .../net/runelite/client/util/MiscUtils.java | 171 +-- .../net/runelite/client/util/PvPUtil.java | 224 ++-- .../net/runelite/client/util/RefUtils.java | 16 +- .../runelite/client/util/StackFormatter.java | 2 +- .../java/net/runelite/client/util/Text.java | 8 +- .../client/util/WildernessLocation.java | 188 +-- .../net/runelite/client/util/WorldUtil.java | 105 +- .../plugins/slayer/SlayerPluginTest.java | 2 - 106 files changed, 7790 insertions(+), 6950 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java b/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java index f672a0d05e..fc26d2c8af 100644 --- a/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java @@ -79,7 +79,7 @@ public class ClientSessionManager } sessionId = null; } - + scheduledFuture.cancel(true); } diff --git a/runelite-client/src/main/java/net/runelite/client/Notifier.java b/runelite-client/src/main/java/net/runelite/client/Notifier.java index d1423f168e..3978bebfa4 100644 --- a/runelite-client/src/main/java/net/runelite/client/Notifier.java +++ b/runelite-client/src/main/java/net/runelite/client/Notifier.java @@ -100,7 +100,7 @@ public class Notifier // First check if we are running in launcher this.terminalNotifierAvailable = !Strings.isNullOrEmpty(RuneLiteProperties.getLauncherVersion()) - && isTerminalNotifierAvailable(); + && isTerminalNotifierAvailable(); storeIcon(); } diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index c9c575bd36..81b0249b89 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -59,7 +59,6 @@ import net.runelite.client.menus.MenuManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginInstantiationException; import net.runelite.client.plugins.PluginManager; -import net.runelite.client.plugins.config.ConfigPanel; import net.runelite.client.rs.ClientUpdateCheckMode; import net.runelite.client.task.Scheduler; import net.runelite.client.ui.ClientUI; @@ -86,10 +85,10 @@ public class RuneLite public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles"); public static final File PLUGIN_DIR = new File(RUNELITE_DIR, "plugins"); public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots"); - public static RuneLiteSplashScreen splashScreen = new RuneLiteSplashScreen(); + static final RuneLiteSplashScreen splashScreen = new RuneLiteSplashScreen(); - @Getter + @Getter private static Injector injector; @Inject @@ -242,7 +241,7 @@ public class RuneLite // The submessage is shown in case the connection is slow splashScreen.setMessage("Starting RuneLite Injector"); - splashScreen.setSubMessage( " "); + splashScreen.setSubMessage(" "); final long start = System.currentTimeMillis(); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java index e86e436c54..b3ca2cafcf 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java @@ -80,9 +80,12 @@ public class RuneLiteProperties public String getDiscordAppId() { - if (RuneLitePlusPlugin.customPresenceEnabled) { + if (RuneLitePlusPlugin.customPresenceEnabled) + { return properties.getProperty(RuneLitePlusPlugin.rlPlusDiscordApp); - } else { + } + else + { return properties.getProperty(DISCORD_APP_ID); } } diff --git a/runelite-client/src/main/java/net/runelite/client/SessionClient.java b/runelite-client/src/main/java/net/runelite/client/SessionClient.java index 9d02ee1961..658c73b571 100644 --- a/runelite-client/src/main/java/net/runelite/client/SessionClient.java +++ b/runelite-client/src/main/java/net/runelite/client/SessionClient.java @@ -50,7 +50,7 @@ class SessionClient try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) { ResponseBody body = response.body(); - + InputStream in = body.byteStream(); return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), UUID.class); } diff --git a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java index 6ef8c82e73..4fc8152126 100644 --- a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java @@ -1,232 +1,232 @@ -/* - * Copyright (c) 2017, Adam - * 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.account; - -import com.google.gson.Gson; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.time.Instant; -import java.util.UUID; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.RuneLite; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.util.LinkBrowser; -import net.runelite.client.ws.WSClient; -import net.runelite.http.api.account.AccountClient; -import net.runelite.http.api.account.OAuthResponse; -import net.runelite.http.api.ws.messages.LoginResponse; - -@Singleton -@Slf4j -public class SessionManager -{ - private static final File SESSION_FILE = new File(RuneLite.RUNELITE_DIR, "session"); - - @Getter - private AccountSession accountSession; - - private final EventBus eventBus; - private final ConfigManager configManager; - private final WSClient wsClient; - - @Inject - private SessionManager(ConfigManager configManager, EventBus eventBus, WSClient wsClient) - { - this.configManager = configManager; - this.eventBus = eventBus; - this.wsClient = wsClient; - eventBus.register(this); - } - - public void loadSession() - { - if (!SESSION_FILE.exists()) - { - log.info("No session file exists"); - return; - } - - AccountSession session; - - try (FileInputStream in = new FileInputStream(SESSION_FILE)) - { - session = new Gson().fromJson(new InputStreamReader(in), AccountSession.class); - - log.debug("Loaded session for {}", session.getUsername()); - } - catch (Exception ex) - { - log.warn("Unable to load session file", ex); - return; - } - - // Check if session is still valid - AccountClient accountClient = new AccountClient(session.getUuid()); - if (!accountClient.sesssionCheck()) - { - log.debug("Loaded session {} is invalid", session.getUuid()); - return; - } - - openSession(session, false); - } - - private void saveSession() - { - if (accountSession == null) - { - return; - } - - try (FileWriter fw = new FileWriter(SESSION_FILE)) - { - new Gson().toJson(accountSession, fw); - - log.debug("Saved session to {}", SESSION_FILE); - } - catch (IOException ex) - { - log.warn("Unable to save session file", ex); - } - } - - private void deleteSession() - { - SESSION_FILE.delete(); - } - - /** - * Set the given session as the active session and open a socket to the - * server with the given session - * - * @param session session - */ - private void openSession(AccountSession session, boolean openSocket) - { - // Change session on the websocket - if (openSocket) - { - wsClient.changeSession(session.getUuid()); - } - - accountSession = session; - - if (session.getUsername() != null) - { - // Initialize config for new session - // If the session isn't logged in yet, don't switch to the new config - configManager.switchSession(session); - } - - eventBus.post(new SessionOpen()); - } - - private void closeSession() - { - wsClient.changeSession(null); - - if (accountSession == null) - { - return; - } - - log.debug("Logging out of account {}", accountSession.getUsername()); - - AccountClient client = new AccountClient(accountSession.getUuid()); - try - { - client.logout(); - } - catch (IOException ex) - { - log.warn("Unable to logout of session", ex); - } - - accountSession = null; // No more account - - // Restore config - configManager.switchSession(null); - - eventBus.post(new SessionClose()); - } - - public void login() - { - // If a session is already open, use that id. Otherwise generate a new id. - UUID uuid = wsClient.getSessionId() != null ? wsClient.getSessionId() : UUID.randomUUID(); - AccountClient loginClient = new AccountClient(uuid); - - final OAuthResponse login; - - try - { - login = loginClient.login(); - } - catch (IOException ex) - { - log.warn("Unable to get oauth url", ex); - return; - } - - // Create new session - openSession(new AccountSession(login.getUid(), Instant.now()), true); - - // Navigate to login link - LinkBrowser.browse(login.getOauthUrl()); - } - - @Subscribe - public void onLoginResponse(LoginResponse loginResponse) - { - log.debug("Now logged in as {}", loginResponse.getUsername()); - - AccountSession session = getAccountSession(); - session.setUsername(loginResponse.getUsername()); - - // Open session, again, now that we have a username - // This triggers onSessionOpen - // The socket is already opened here anyway so we pass true for openSocket - openSession(session, true); - - // Save session to disk - saveSession(); - } - - public void logout() - { - closeSession(); - deleteSession(); - } -} +/* + * Copyright (c) 2017, Adam + * 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.account; + +import com.google.gson.Gson; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.time.Instant; +import java.util.UUID; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLite; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.util.LinkBrowser; +import net.runelite.client.ws.WSClient; +import net.runelite.http.api.account.AccountClient; +import net.runelite.http.api.account.OAuthResponse; +import net.runelite.http.api.ws.messages.LoginResponse; + +@Singleton +@Slf4j +public class SessionManager +{ + private static final File SESSION_FILE = new File(RuneLite.RUNELITE_DIR, "session"); + + @Getter + private AccountSession accountSession; + + private final EventBus eventBus; + private final ConfigManager configManager; + private final WSClient wsClient; + + @Inject + private SessionManager(ConfigManager configManager, EventBus eventBus, WSClient wsClient) + { + this.configManager = configManager; + this.eventBus = eventBus; + this.wsClient = wsClient; + eventBus.register(this); + } + + public void loadSession() + { + if (!SESSION_FILE.exists()) + { + log.info("No session file exists"); + return; + } + + AccountSession session; + + try (FileInputStream in = new FileInputStream(SESSION_FILE)) + { + session = new Gson().fromJson(new InputStreamReader(in), AccountSession.class); + + log.debug("Loaded session for {}", session.getUsername()); + } + catch (Exception ex) + { + log.warn("Unable to load session file", ex); + return; + } + + // Check if session is still valid + AccountClient accountClient = new AccountClient(session.getUuid()); + if (!accountClient.sesssionCheck()) + { + log.debug("Loaded session {} is invalid", session.getUuid()); + return; + } + + openSession(session, false); + } + + private void saveSession() + { + if (accountSession == null) + { + return; + } + + try (FileWriter fw = new FileWriter(SESSION_FILE)) + { + new Gson().toJson(accountSession, fw); + + log.debug("Saved session to {}", SESSION_FILE); + } + catch (IOException ex) + { + log.warn("Unable to save session file", ex); + } + } + + private void deleteSession() + { + SESSION_FILE.delete(); + } + + /** + * Set the given session as the active session and open a socket to the + * server with the given session + * + * @param session session + */ + private void openSession(AccountSession session, boolean openSocket) + { + // Change session on the websocket + if (openSocket) + { + wsClient.changeSession(session.getUuid()); + } + + accountSession = session; + + if (session.getUsername() != null) + { + // Initialize config for new session + // If the session isn't logged in yet, don't switch to the new config + configManager.switchSession(session); + } + + eventBus.post(new SessionOpen()); + } + + private void closeSession() + { + wsClient.changeSession(null); + + if (accountSession == null) + { + return; + } + + log.debug("Logging out of account {}", accountSession.getUsername()); + + AccountClient client = new AccountClient(accountSession.getUuid()); + try + { + client.logout(); + } + catch (IOException ex) + { + log.warn("Unable to logout of session", ex); + } + + accountSession = null; // No more account + + // Restore config + configManager.switchSession(null); + + eventBus.post(new SessionClose()); + } + + public void login() + { + // If a session is already open, use that id. Otherwise generate a new id. + UUID uuid = wsClient.getSessionId() != null ? wsClient.getSessionId() : UUID.randomUUID(); + AccountClient loginClient = new AccountClient(uuid); + + final OAuthResponse login; + + try + { + login = loginClient.login(); + } + catch (IOException ex) + { + log.warn("Unable to get oauth url", ex); + return; + } + + // Create new session + openSession(new AccountSession(login.getUid(), Instant.now()), true); + + // Navigate to login link + LinkBrowser.browse(login.getOauthUrl()); + } + + @Subscribe + public void onLoginResponse(LoginResponse loginResponse) + { + log.debug("Now logged in as {}", loginResponse.getUsername()); + + AccountSession session = getAccountSession(); + session.setUsername(loginResponse.getUsername()); + + // Open session, again, now that we have a username + // This triggers onSessionOpen + // The socket is already opened here anyway so we pass true for openSocket + openSession(session, true); + + // Save session to disk + saveSession(); + } + + public void logout() + { + closeSession(); + deleteSession(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index 12de2c567b..efe003367b 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -374,6 +374,7 @@ public class Hooks implements Callbacks /** * Copy an image + * * @param src * @return */ diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java index f2aa57ff3e..e1813a6fac 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java @@ -1,153 +1,153 @@ -/* - * Copyright (c) 2017, Adam - * 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.config; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.Objects; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -class ConfigInvocationHandler implements InvocationHandler -{ - private final ConfigManager manager; - - public ConfigInvocationHandler(ConfigManager manager) - { - this.manager = manager; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - { - Class iface = proxy.getClass().getInterfaces()[0]; - - ConfigGroup group = iface.getAnnotation(ConfigGroup.class); - ConfigItem item = method.getAnnotation(ConfigItem.class); - - if (group == null) - { - log.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass()); - return null; - } - - if (item == null) - { - log.warn("Configuration method {} has no @ConfigItem!", method); - return null; - } - - if (args == null) - { - // Getting configuration item - String value = manager.getConfiguration(group.value(), item.keyName()); - - if (value == null) - { - if (method.isDefault()) - { - return callDefaultMethod(proxy, method, null); - } - - return null; - } - - // Convert value to return type - Class returnType = method.getReturnType(); - - try - { - return ConfigManager.stringToObject(value, returnType); - } - catch (Exception e) - { - log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e); - if (method.isDefault()) - { - return callDefaultMethod(proxy, method, null); - } - return null; - } - } - else - { - // Setting a configuration value - - if (args.length != 1) - { - throw new RuntimeException("Invalid number of arguents to configuration method"); - } - - Object newValue = args[0]; - - Class type = method.getParameterTypes()[0]; - Object oldValue = manager.getConfiguration(group.value(), item.keyName(), type); - - if (Objects.equals(oldValue, newValue)) - { - // nothing to do - return null; - } - - if (method.isDefault()) - { - Object defaultValue = callDefaultMethod(proxy, method, args); - - if (Objects.equals(newValue, defaultValue)) - { - // Just unset if it goes back to the default - manager.unsetConfiguration(group.value(), item.keyName()); - return null; - } - } - - if (newValue == null) - { - manager.unsetConfiguration(group.value(), item.keyName()); - } - else - { - String newValueStr = ConfigManager.objectToString(newValue); - manager.setConfiguration(group.value(), item.keyName(), newValueStr); - } - return null; - } - } - - static Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable - { - // Call the default method implementation - https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/ - Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); - constructor.setAccessible(true); - - Class declaringClass = method.getDeclaringClass(); - return constructor.newInstance(declaringClass, MethodHandles.Lookup.PUBLIC | MethodHandles.Lookup.PRIVATE) - .unreflectSpecial(method, declaringClass) - .bindTo(proxy) - .invokeWithArguments(args); - } -} +/* + * Copyright (c) 2017, Adam + * 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.config; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +class ConfigInvocationHandler implements InvocationHandler +{ + private final ConfigManager manager; + + public ConfigInvocationHandler(ConfigManager manager) + { + this.manager = manager; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + Class iface = proxy.getClass().getInterfaces()[0]; + + ConfigGroup group = iface.getAnnotation(ConfigGroup.class); + ConfigItem item = method.getAnnotation(ConfigItem.class); + + if (group == null) + { + log.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass()); + return null; + } + + if (item == null) + { + log.warn("Configuration method {} has no @ConfigItem!", method); + return null; + } + + if (args == null) + { + // Getting configuration item + String value = manager.getConfiguration(group.value(), item.keyName()); + + if (value == null) + { + if (method.isDefault()) + { + return callDefaultMethod(proxy, method, null); + } + + return null; + } + + // Convert value to return type + Class returnType = method.getReturnType(); + + try + { + return ConfigManager.stringToObject(value, returnType); + } + catch (Exception e) + { + log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e); + if (method.isDefault()) + { + return callDefaultMethod(proxy, method, null); + } + return null; + } + } + else + { + // Setting a configuration value + + if (args.length != 1) + { + throw new RuntimeException("Invalid number of arguents to configuration method"); + } + + Object newValue = args[0]; + + Class type = method.getParameterTypes()[0]; + Object oldValue = manager.getConfiguration(group.value(), item.keyName(), type); + + if (Objects.equals(oldValue, newValue)) + { + // nothing to do + return null; + } + + if (method.isDefault()) + { + Object defaultValue = callDefaultMethod(proxy, method, args); + + if (Objects.equals(newValue, defaultValue)) + { + // Just unset if it goes back to the default + manager.unsetConfiguration(group.value(), item.keyName()); + return null; + } + } + + if (newValue == null) + { + manager.unsetConfiguration(group.value(), item.keyName()); + } + else + { + String newValueStr = ConfigManager.objectToString(newValue); + manager.setConfiguration(group.value(), item.keyName(), newValueStr); + } + return null; + } + } + + static Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable + { + // Call the default method implementation - https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/ + Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); + constructor.setAccessible(true); + + Class declaringClass = method.getDeclaringClass(); + return constructor.newInstance(declaringClass, MethodHandles.Lookup.PUBLIC | MethodHandles.Lookup.PRIVATE) + .unreflectSpecial(method, declaringClass) + .bindTo(proxy) + .invokeWithArguments(args); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java index 51363c81c4..3c78e8f331 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2018, Craftiii4 - * 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.config; - -import lombok.AccessLevel; -import lombok.Getter; -import java.util.ArrayList; -import java.util.Collection; - -public class ConfigItemsGroup -{ - - @Getter(AccessLevel.PUBLIC) - private final String group; - - @Getter(AccessLevel.PUBLIC) - private Collection items; - - public ConfigItemsGroup(String group) - { - this.group = group; - this.items = new ArrayList<>(); - } - - public void addItem(ConfigItemDescriptor item) - { - items.add(item); - } - -} +/* + * Copyright (c) 2018, Craftiii4 + * 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.config; + +import java.util.ArrayList; +import java.util.Collection; +import lombok.AccessLevel; +import lombok.Getter; + +public class ConfigItemsGroup +{ + + @Getter(AccessLevel.PUBLIC) + private final String group; + + @Getter(AccessLevel.PUBLIC) + private Collection items; + + public ConfigItemsGroup(String group) + { + this.group = group; + this.items = new ArrayList<>(); + } + + public void addItem(ConfigItemDescriptor item) + { + items.add(item); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index da8b608aa3..b0f42f7bf1 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -364,9 +364,9 @@ public class ConfigManager } itemGroups = itemGroups.stream().sorted((a, b) -> ComparisonChain.start() - .compare(a.getGroup(), b.getGroup()) - .result()) - .collect(Collectors.toList()); + .compare(a.getGroup(), b.getGroup()) + .result()) + .collect(Collectors.toList()); return new ConfigDescriptor(group, itemGroups); } @@ -511,22 +511,22 @@ public class ConfigManager { return Duration.ofMillis(Long.parseLong(str)); } - if (type == Map.class) - { - Map output = new HashMap<>(); - str = str.substring(1, str.length() - 1); - String[] splitStr = str.split(", "); - for (String s : splitStr) - { - String[] keyVal = s.split("="); - if (keyVal.length > 1) - { - output.put(keyVal[0], keyVal[1]); - } - } + if (type == Map.class) + { + Map output = new HashMap<>(); + str = str.substring(1, str.length() - 1); + String[] splitStr = str.split(", "); + for (String s : splitStr) + { + String[] keyVal = s.split("="); + if (keyVal.length > 1) + { + output.put(keyVal[0], keyVal[1]); + } + } - return output; - } + return output; + } return str; } diff --git a/runelite-client/src/main/java/net/runelite/client/config/FontType.java b/runelite-client/src/main/java/net/runelite/client/config/FontType.java index 8ed57bd302..c8a28dd262 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/FontType.java +++ b/runelite-client/src/main/java/net/runelite/client/config/FontType.java @@ -1,49 +1,48 @@ -/* - * Copyright (c) 2018, Tanner - * 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.config; - -import lombok.RequiredArgsConstructor; -import lombok.Getter; -import net.runelite.client.ui.FontManager; - -import java.awt.Font; - -@Getter -@RequiredArgsConstructor -public enum FontType -{ - REGULAR("Regular", FontManager.getRunescapeFont()), - BOLD("Bold", FontManager.getRunescapeBoldFont()), - SMALL("Small", FontManager.getRunescapeSmallFont()); - - private final String name; - private final Font font; - - @Override - public String toString() - { - return name; - } -} +/* + * Copyright (c) 2018, Tanner + * 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.config; + +import java.awt.Font; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.runelite.client.ui.FontManager; + +@Getter +@RequiredArgsConstructor +public enum FontType +{ + REGULAR("Regular", FontManager.getRunescapeFont()), + BOLD("Bold", FontManager.getRunescapeBoldFont()), + SMALL("Small", FontManager.getRunescapeSmallFont()); + + private final String name; + private final Font font; + + @Override + public String toString() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java index 78ec89a46f..be6fef1d6d 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java @@ -67,7 +67,7 @@ public interface RuneLiteConfig extends Config keyName = "enablePlugins", name = "Enable loading of external plugins", description = "Enable loading of external plugins", - position = 10 + position = 10 ) default boolean enablePlugins() { diff --git a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java index c125ca0feb..dbf3c36ba2 100644 --- a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java +++ b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java @@ -106,7 +106,7 @@ public class DiscordService implements AutoCloseable discordEventHandlers.joinGame = this::joinGame; discordEventHandlers.spectateGame = this::spectateGame; discordEventHandlers.joinRequest = this::joinRequest; - discordRPC.Discord_Initialize(runeLiteProperties.discordAppID, discordEventHandlers, true, null); + discordRPC.Discord_Initialize(RuneLiteProperties.discordAppID, discordEventHandlers, true, null); executorService.scheduleAtFixedRate(discordRPC::Discord_RunCallbacks, 0, 2, TimeUnit.SECONDS); } diff --git a/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java b/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java index 3427279226..bb810d69a8 100644 --- a/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java +++ b/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java @@ -35,248 +35,307 @@ for mouse motion. package net.runelite.client.flexo; import com.github.joonasvali.naturalmouse.api.MouseMotionFactory; -import net.runelite.api.Client; -import net.runelite.client.ui.ClientUI; -import sun.awt.ComponentFactory; - -import javax.swing.*; -import java.awt.*; +import java.awt.AWTException; +import java.awt.Color; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.peer.RobotPeer; import java.util.Random; import java.util.logging.Logger; +import net.runelite.api.Client; +import net.runelite.api.Constants; +import net.runelite.client.ui.ClientUI; +import sun.awt.ComponentFactory; -public class Flexo extends Robot { - public ThreadGroup flexoThreads = new ThreadGroup("flexo"); - public static boolean isActive; - public static double scale; - public static Client client; - public static ClientUI clientUI; - public static int fixedWidth = 765; - public static int fixedHeight = 503; - public static boolean isStretched; - public static int minDelay = 45; - public static MouseMotionFactory currentMouseMotionFactory; - public boolean pausedIndefinitely = false; - private Thread holdKeyThread; - private RobotPeer peer; +public class Flexo extends Robot +{ + public ThreadGroup flexoThreads = new ThreadGroup("flexo"); + public static boolean isActive; + public static double scale; + public static Client client; + public static ClientUI clientUI; + public static int fixedWidth = Constants.GAME_FIXED_WIDTH; + public static int fixedHeight = Constants.GAME_FIXED_HEIGHT; + public static boolean isStretched; + public static int minDelay = 45; + public static MouseMotionFactory currentMouseMotionFactory; + public boolean pausedIndefinitely = false; + private Thread holdKeyThread; + private RobotPeer peer; - public Flexo() throws AWTException { - if (GraphicsEnvironment.isHeadless()) { - throw new AWTException("headless environment"); - } - init(GraphicsEnvironment.getLocalGraphicsEnvironment() - .getDefaultScreenDevice()); - } + public Flexo() throws AWTException + { + if (GraphicsEnvironment.isHeadless()) + { + throw new AWTException("headless environment"); + } + init(GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice()); + } - private void init(GraphicsDevice screen) throws AWTException { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - if (toolkit instanceof ComponentFactory) { - peer = ((ComponentFactory)toolkit).createRobot(this, screen); - RobotDisposer disposer = new RobotDisposer(peer); - sun.java2d.Disposer.addRecord(anchor, disposer); - } - } + private void init(GraphicsDevice screen) throws AWTException + { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + if (toolkit instanceof ComponentFactory) + { + peer = ((ComponentFactory) toolkit).createRobot(this, screen); + RobotDisposer disposer = new RobotDisposer(peer); + sun.java2d.Disposer.addRecord(anchor, disposer); + } + } - private transient Object anchor = new Object(); + private transient Object anchor = new Object(); - static class RobotDisposer implements sun.java2d.DisposerRecord { - private final RobotPeer peer; - private RobotDisposer(RobotPeer peer) { - this.peer = peer; - } - public void dispose() { - if (peer != null) { - peer.dispose(); - } - } - } + static class RobotDisposer implements sun.java2d.DisposerRecord + { + private final RobotPeer peer; - private void pauseMS(int delayMS) { - long initialMS = System.currentTimeMillis(); - while (System.currentTimeMillis()5) { - Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); - return; - } - peer.mousePress(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - } + @Override + public synchronized void mouseMove(int x, int y) + { + try + { + //TODO: Must be better way to determine titlebar width + currentMouseMotionFactory.build(ClientUI.frame.getX() + x + determineHorizontalOffset(), ClientUI.frame.getY() + y + determineVerticalOffset()).move(); + this.delay(getMinDelay()); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } - public synchronized void mousePressAndRelease(int buttonID) { - if (buttonID<1 || buttonID >5) { - Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); - return; - } - peer.mousePress(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - } + public synchronized void mouseMove(Point p) + { + Point p2 = p; + mouseMove((int) p.getX(), (int) p.getY()); + try + { + Thread.sleep(150); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } - //TODO: Symbols are nut supported at this time - public synchronized void typeMessage(String message) { + @Override + public synchronized void mousePress(int buttonID) + { + if (buttonID < 1 || buttonID > 5) + { + Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); + return; + } + peer.mousePress(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + } - Random r = new Random(); - char[] charArray = message.toCharArray(); - for (char c : charArray) { - keyPress(KeyEvent.getExtendedKeyCodeForChar(c)); - this.delay(93+r.nextInt(getMinDelay())); - } - keyPress(KeyEvent.VK_ENTER); - this.delay(93+r.nextInt(getMinDelay())); - ClientUI.allowInput = true; - } + public synchronized void mousePressAndRelease(int buttonID) + { + if (buttonID < 1 || buttonID > 5) + { + Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); + return; + } + peer.mousePress(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + } + + //TODO: Symbols are nut supported at this time + public synchronized void typeMessage(String message) + { + + Random r = new Random(); + char[] charArray = message.toCharArray(); + for (char c : charArray) + { + keyPress(KeyEvent.getExtendedKeyCodeForChar(c)); + this.delay(93 + r.nextInt(getMinDelay())); + } + keyPress(KeyEvent.VK_ENTER); + this.delay(93 + r.nextInt(getMinDelay())); + ClientUI.allowInput = true; + } + @Override + public synchronized void mouseRelease(int buttonID) + { + if (buttonID < 1 || buttonID > 5) + { + Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); + return; + } + peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + } - @Override - public synchronized void mouseRelease(int buttonID) { - if (buttonID<1 || buttonID >5) { - Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); - return; - } - peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - } + private int getMinDelay() + { + Random random = new Random(); + int random1 = random.nextInt(minDelay); + if (random1 < minDelay / 2) + { + random1 = random.nextInt(minDelay / 2) + minDelay / 2 + random.nextInt(minDelay / 2); + } + return random1; + } - private int getMinDelay() { - Random random = new Random(); - int random1 = random.nextInt(minDelay); - if (random1 < minDelay/2) - random1 = random.nextInt(minDelay/2) + minDelay/2+random.nextInt(minDelay/2); - return random1; - } + private int getWheelDelay() + { + Random random = new Random(); + int random1 = random.nextInt(minDelay); + if (random1 < minDelay / 2) + { + random1 = random.nextInt(minDelay / 2) + minDelay / 2 + random.nextInt(minDelay / 2); + } + return random1; + } - private int getWheelDelay() { - Random random = new Random(); - int random1 = random.nextInt(minDelay); - if (random1 < minDelay/2) - random1 = random.nextInt(minDelay/2) + minDelay/2+random.nextInt(minDelay/2); - return random1; - } + /** + * Rotates the scroll wheel on wheel-equipped mice. + * + * @param wheelAmt number of "notches" to move the mouse wheel + * Negative values indicate movement up/away from the user, + * positive values indicate movement down/towards the user. + * @since 1.4 + */ + @Override + public synchronized void mouseWheel(int wheelAmt) + { + for (int i : new int[wheelAmt]) + { + peer.mouseWheel(wheelAmt); + this.delay(getWheelDelay()); + } + } - /** - * Rotates the scroll wheel on wheel-equipped mice. - * - * @param wheelAmt number of "notches" to move the mouse wheel - * Negative values indicate movement up/away from the user, - * positive values indicate movement down/towards the user. - * - * @since 1.4 - */ - @Override - public synchronized void mouseWheel(int wheelAmt) { - for (int i : new int[wheelAmt]) { - peer.mouseWheel(wheelAmt); - this.delay(getWheelDelay()); - } - } + /** + * Presses a given key. The key should be released using the + * keyRelease method. + *

+ * Key codes that have more than one physical key associated with them + * (e.g. KeyEvent.VK_SHIFT could mean either the + * left or right shift key) will map to the left key. + * + * @param keycode Key to press (e.g. KeyEvent.VK_A) + * @throws IllegalArgumentException if keycode is not + * a valid key + * @see #keyRelease(int) + * @see java.awt.event.KeyEvent + */ + @Override + public synchronized void keyPress(int keycode) + { + peer.keyPress(keycode); + this.delay(getMinDelay()); + } - /** - * Presses a given key. The key should be released using the - * keyRelease method. - *

- * Key codes that have more than one physical key associated with them - * (e.g. KeyEvent.VK_SHIFT could mean either the - * left or right shift key) will map to the left key. - * - * @param keycode Key to press (e.g. KeyEvent.VK_A) - * @throws IllegalArgumentException if keycode is not - * a valid key - * @see #keyRelease(int) - * @see java.awt.event.KeyEvent - */ - @Override - public synchronized void keyPress(int keycode) { - peer.keyPress(keycode); - this.delay(getMinDelay()); - } + @Override + public synchronized void keyRelease(int keycode) + { + peer.keyRelease(keycode); + this.delay(getMinDelay()); + } - @Override - public synchronized void keyRelease(int keycode) { - peer.keyRelease(keycode); - this.delay(getMinDelay()); - } + public synchronized void holdKey(int keycode, int timeMS) + { + new Thread(() -> + { + peer.keyPress(keycode); + long startTime = System.currentTimeMillis(); + while ((startTime + timeMS) > System.currentTimeMillis()) + { + } + peer.keyRelease(keycode); + this.delay(getMinDelay()); + }).start(); + } - public synchronized void holdKey(int keycode, int timeMS) { - new Thread(() -> { - peer.keyPress(keycode); - long startTime = System.currentTimeMillis(); - while ((startTime + timeMS) > System.currentTimeMillis()) { } - peer.keyRelease(keycode); - this.delay(getMinDelay()); - }).start(); - } + public synchronized void holdKeyIndefinitely(int keycode) + { + holdKeyThread = new Thread(() -> + { + pausedIndefinitely = true; + peer.keyPress(keycode); + while (pausedIndefinitely) + { + try + { + Thread.sleep(10); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + peer.keyRelease(keycode); + this.delay(getMinDelay()); + }); + holdKeyThread.start(); - public synchronized void holdKeyIndefinitely(int keycode) { - holdKeyThread = new Thread(() -> { - pausedIndefinitely = true; - peer.keyPress(keycode); - while (pausedIndefinitely) { - try { - holdKeyThread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - peer.keyRelease(keycode); - this.delay(getMinDelay()); - }); - holdKeyThread.start(); + } - } + @Override + public Color getPixelColor(int x, int y) + { + Color color = new Color(peer.getRGBPixel(x, y)); + return color; + } - @Override - public Color getPixelColor(int x, int y) { - Color color = new Color(peer.getRGBPixel(x, y)); - return color; - } + @Override + public void delay(int ms) + { + pauseMS(ms); + } - @Override - public void delay(int ms) { - pauseMS(ms); - } - - public int determineHorizontalOffset() { - return clientUI.getCanvasOffset().getX(); - } - - public int determineVerticalOffset() { - return clientUI.getCanvasOffset().getY(); - } + public int determineHorizontalOffset() + { + return clientUI.getCanvasOffset().getX(); + } + + public int determineVerticalOffset() + { + return clientUI.getCanvasOffset().getY(); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java b/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java index 70bbf51ba6..76e1545250 100644 --- a/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java +++ b/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java @@ -28,163 +28,198 @@ package net.runelite.client.flexo; -import net.runelite.client.ui.ClientUI; - -import java.awt.*; +import java.awt.Point; +import java.awt.Rectangle; import java.util.Random; import java.util.logging.Logger; +import net.runelite.api.Constants; +import net.runelite.client.ui.ClientUI; -public class FlexoMouse { +public class FlexoMouse +{ - /* - Should pass unstretched coords, handles all conversions here. - */ - public static Point getClickPoint(Rectangle rect) - { - if (rect!=null) { - Random r = new Random(); - int x = -1; - int y = -1; - x = rect.x+r.nextInt(rect.width); - y = rect.y+r.nextInt(rect.height); + /* + Should pass unstretched coords, handles all conversions here. + */ + public static Point getClickPoint(Rectangle rect) + { + if (rect != null) + { + Random r = new Random(); + int x = -1; + int y = -1; + x = rect.x + r.nextInt(rect.width); + y = rect.y + r.nextInt(rect.height); - if (Flexo.isStretched) { - double wScale; - double hScale; + if (Flexo.isStretched) + { + double wScale; + double hScale; - if (Flexo.client.isResized()) { - wScale = (Flexo.client.getStretchedDimensions().width / Flexo.client.getRealDimensions().width); - hScale = (Flexo.client.getStretchedDimensions().height / Flexo.client.getRealDimensions().height); - int newX = (int)(x*wScale); - int newY = (int)(y*hScale); - if (newX>0 && newX< ClientUI.frame.getWidth()) { - if (newY>0 && newY< ClientUI.frame.getHeight()) { - return new Point(newX, newY); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } else { - if (x>0 && x< ClientUI.frame.getWidth()) { - if (y>0 && y< ClientUI.frame.getHeight()) { - return new Point(x, y); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } + if (Flexo.client.isResized()) + { + wScale = (Flexo.client.getStretchedDimensions().width / (double) Flexo.client.getRealDimensions().width); + hScale = (Flexo.client.getStretchedDimensions().height / (double) Flexo.client.getRealDimensions().height); + int newX = (int) (x * wScale); + int newY = (int) (y * hScale); + if (newX > 0 && newX < ClientUI.frame.getWidth()) + { + if (newY > 0 && newY < ClientUI.frame.getHeight()) + { + return new Point(newX, newY); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } + else + { + if (x > 0 && x < ClientUI.frame.getWidth()) + { + if (y > 0 && y < ClientUI.frame.getHeight()) + { + return new Point(x, y); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } - } else if (!Flexo.client.isResized()) { - int fixedWidth = 765; - int widthDif = ClientUI.frame.getWidth(); + } + else if (!Flexo.client.isResized()) + { + final int fixedWidth = Constants.GAME_FIXED_WIDTH; + int widthDif = ClientUI.frame.getWidth(); - if (ClientUI.pluginToolbar.isVisible()) { - widthDif -= ClientUI.pluginToolbar.getWidth(); - } - if (ClientUI.pluginPanel!=null) - widthDif -= ClientUI.pluginPanel.getWidth(); + if (ClientUI.pluginToolbar.isVisible()) + { + widthDif -= ClientUI.pluginToolbar.getWidth(); + } + if (ClientUI.pluginPanel != null) + { + widthDif -= ClientUI.pluginPanel.getWidth(); + } - widthDif -= fixedWidth; - if (x+(widthDif/2)>0 && x+(widthDif/2)< ClientUI.frame.getWidth()) { - if (y>0 && y< ClientUI.frame.getHeight()) { - return new Point(x, y); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } - else { - if (x>0 && x< ClientUI.frame.getWidth()) { - if (y>0 && y< ClientUI.frame.getHeight()) { - return new Point(x, y); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } - } - return null; - } + widthDif -= fixedWidth; + if (x + (widthDif / 2) > 0 && x + (widthDif / 2) < ClientUI.frame.getWidth()) + { + if (y > 0 && y < ClientUI.frame.getHeight()) + { + return new Point(x, y); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } + else + { + if (x > 0 && x < ClientUI.frame.getWidth()) + { + if (y > 0 && y < ClientUI.frame.getHeight()) + { + return new Point(x, y); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } + } + return null; + } - public static Rectangle getClickArea(Rectangle rect) - { - if (Flexo.isStretched) - { - double wScale; - double hScale; + public static Rectangle getClickArea(Rectangle rect) + { + if (Flexo.isStretched) + { + double wScale; + double hScale; - if (Flexo.client.isResized()) { - wScale = (Flexo.client.getStretchedDimensions().width / Flexo.client.getRealDimensions().width); - hScale = (Flexo.client.getStretchedDimensions().height / Flexo.client.getRealDimensions().height); - } else { - wScale = ((double) Flexo.client.getStretchedDimensions().width) / Flexo.fixedWidth; - hScale = ((double) Flexo.client.getStretchedDimensions().height) / Flexo.fixedHeight; - } + if (Flexo.client.isResized()) + { + wScale = (Flexo.client.getStretchedDimensions().width / (double) Flexo.client.getRealDimensions().width); + hScale = (Flexo.client.getStretchedDimensions().height / (double) Flexo.client.getRealDimensions().height); + } + else + { + wScale = (Flexo.client.getStretchedDimensions().width) / (double) Flexo.fixedWidth; + hScale = (Flexo.client.getStretchedDimensions().height) / (double) Flexo.fixedHeight; + } - int xPadding = (int)rect.getWidth()/5; - int yPadding = (int)rect.getHeight()/5; - Random r = new Random(); - Rectangle clickRect = new Rectangle(); - clickRect.width = rect.width-xPadding*2; - clickRect.height = rect.height-yPadding*2; - clickRect.x = rect.x+xPadding; - clickRect.y = rect.y+yPadding; - if (clickRect.width>0&&clickRect.height>0) { - int x = clickRect.x+r.nextInt(clickRect.width); - int y = clickRect.y+r.nextInt(clickRect.height); - double tScale = 1 + (Flexo.scale / 100); + int xPadding = (int) rect.getWidth() / 5; + int yPadding = (int) rect.getHeight() / 5; + Random r = new Random(); + Rectangle clickRect = new Rectangle(); + clickRect.width = rect.width - xPadding * 2; + clickRect.height = rect.height - yPadding * 2; + clickRect.x = rect.x + xPadding; + clickRect.y = rect.y + yPadding; + if (clickRect.width > 0 && clickRect.height > 0) + { + int x = clickRect.x + r.nextInt(clickRect.width); + int y = clickRect.y + r.nextInt(clickRect.height); + double tScale = 1 + (Flexo.scale / 100); - if (Flexo.client.isResized()) { - return new Rectangle((int)(clickRect.x * wScale), (int)(clickRect.y * wScale), (int)(clickRect.width * wScale), (int)(clickRect.getHeight()*hScale)); - } else { - return new Rectangle((int)(clickRect.x), (int)(clickRect.y), (int)(clickRect.width), (int)(clickRect.getHeight())); - } - } + if (Flexo.client.isResized()) + { + return new Rectangle((int) (clickRect.x * wScale), (int) (clickRect.y * wScale), (int) (clickRect.width * wScale), (int) (clickRect.getHeight() * hScale)); + } + else + { + return new Rectangle(clickRect.x, clickRect.y, clickRect.width, (int) (clickRect.getHeight())); + } + } - } - //Fixed, not stretched - else if (!Flexo.client.isResized()) { - int fixedWidth = 765; - int widthDif = ClientUI.frame.getWidth(); + } + //Fixed, not stretched + else if (!Flexo.client.isResized()) + { + int fixedWidth = 765; + int widthDif = ClientUI.frame.getWidth(); - if (ClientUI.pluginToolbar.isVisible()) { - widthDif -= ClientUI.pluginToolbar.getWidth(); - } - if (ClientUI.pluginPanel!=null) - widthDif -= ClientUI.pluginPanel.getWidth(); + if (ClientUI.pluginToolbar.isVisible()) + { + widthDif -= ClientUI.pluginToolbar.getWidth(); + } + if (ClientUI.pluginPanel != null) + { + widthDif -= ClientUI.pluginPanel.getWidth(); + } - widthDif -= fixedWidth; - int xPadding = (int)rect.getWidth()/5; - int yPadding = (int)rect.getHeight()/5; - Random r = new Random(); - Rectangle clickRect = new Rectangle(); - clickRect.width = rect.width-xPadding; - clickRect.height = rect.height-yPadding; - clickRect.x = rect.x+xPadding; - clickRect.y = rect.y+yPadding; - if (clickRect.height>0&&clickRect.width>0) { - int x = clickRect.x + r.nextInt(clickRect.width); - int y = clickRect.y + r.nextInt(clickRect.height); - return new Rectangle((int) (clickRect.x), (int) (clickRect.y), (int) (clickRect.width), (int) (clickRect.getHeight())); - } - } - //Resizable, not stretched - else { - int xPadding = (int)rect.getWidth()/5; - int yPadding = (int)rect.getHeight()/5; - Random r = new Random(); - Rectangle clickRect = new Rectangle(); - clickRect.width = rect.width-xPadding*2; - clickRect.height = rect.height-yPadding*2; - clickRect.x = rect.x+xPadding; - clickRect.y = rect.y+yPadding; - if (clickRect.height>0&&clickRect.width>0) { - int x = clickRect.x+r.nextInt(clickRect.width); - int y = clickRect.y+r.nextInt(clickRect.height); - return new Rectangle((int)(clickRect.x), (int)(clickRect.y), (int)(clickRect.width), (int)(clickRect.getHeight())); - } - } + widthDif -= fixedWidth; + int xPadding = (int) rect.getWidth() / 5; + int yPadding = (int) rect.getHeight() / 5; + Random r = new Random(); + Rectangle clickRect = new Rectangle(); + clickRect.width = rect.width - xPadding; + clickRect.height = rect.height - yPadding; + clickRect.x = rect.x + xPadding; + clickRect.y = rect.y + yPadding; + if (clickRect.height > 0 && clickRect.width > 0) + { + int x = clickRect.x + r.nextInt(clickRect.width); + int y = clickRect.y + r.nextInt(clickRect.height); + return new Rectangle(clickRect.x, clickRect.y, clickRect.width, (int) (clickRect.getHeight())); + } + } + //Resizable, not stretched + else + { + int xPadding = (int) rect.getWidth() / 5; + int yPadding = (int) rect.getHeight() / 5; + Random r = new Random(); + Rectangle clickRect = new Rectangle(); + clickRect.width = rect.width - xPadding * 2; + clickRect.height = rect.height - yPadding * 2; + clickRect.x = rect.x + xPadding; + clickRect.y = rect.y + yPadding; + if (clickRect.height > 0 && clickRect.width > 0) + { + int x = clickRect.x + r.nextInt(clickRect.width); + int y = clickRect.y + r.nextInt(clickRect.height); + return new Rectangle(clickRect.x, clickRect.y, clickRect.width, (int) (clickRect.getHeight())); + } + } - return null; - } + return null; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java index 4a0312485c..49b908992b 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java +++ b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java @@ -26,54 +26,258 @@ package net.runelite.client.game; import lombok.Getter; -import static net.runelite.api.NullObjectID.*; -import static net.runelite.api.ObjectID.*; +import static net.runelite.api.NullObjectID.NULL_25337; +import static net.runelite.api.NullObjectID.NULL_26371; +import static net.runelite.api.NullObjectID.NULL_26375; +import static net.runelite.api.NullObjectID.NULL_26884; +import static net.runelite.api.NullObjectID.NULL_26886; +import static net.runelite.api.NullObjectID.NULL_29868; +import static net.runelite.api.NullObjectID.NULL_29869; +import static net.runelite.api.NullObjectID.NULL_29870; +import static net.runelite.api.NullObjectID.NULL_31823; +import static net.runelite.api.NullObjectID.NULL_31849; +import static net.runelite.api.NullObjectID.NULL_33327; +import static net.runelite.api.NullObjectID.NULL_33328; +import static net.runelite.api.ObjectID.A_WOODEN_LOG; +import static net.runelite.api.ObjectID.BALANCING_LEDGE_23548; +import static net.runelite.api.ObjectID.BIG_WINDOW; +import static net.runelite.api.ObjectID.BOULDER_27990; +import static net.runelite.api.ObjectID.BROKEN_FENCE; +import static net.runelite.api.ObjectID.BROKEN_FENCE_2618; +import static net.runelite.api.ObjectID.BROKEN_RAFT; +import static net.runelite.api.ObjectID.BROKEN_WALL_33344; +import static net.runelite.api.ObjectID.CASTLE_WALL; +import static net.runelite.api.ObjectID.CLIMBING_ROCKS; +import static net.runelite.api.ObjectID.CLIMBING_ROCKS_11948; +import static net.runelite.api.ObjectID.CLIMBING_ROCKS_11949; +import static net.runelite.api.ObjectID.CREVICE_16465; +import static net.runelite.api.ObjectID.CREVICE_16539; +import static net.runelite.api.ObjectID.CREVICE_16543; +import static net.runelite.api.ObjectID.CREVICE_19043; +import static net.runelite.api.ObjectID.CREVICE_30198; +import static net.runelite.api.ObjectID.CREVICE_9739; +import static net.runelite.api.ObjectID.CREVICE_9740; +import static net.runelite.api.ObjectID.CROSSBOW_TREE_17062; +import static net.runelite.api.ObjectID.CRUMBLING_WALL_24222; +import static net.runelite.api.ObjectID.DARK_TUNNEL_10047; +import static net.runelite.api.ObjectID.DENSE_FOREST; +import static net.runelite.api.ObjectID.DENSE_FOREST_3938; +import static net.runelite.api.ObjectID.DENSE_FOREST_3939; +import static net.runelite.api.ObjectID.DENSE_FOREST_3998; +import static net.runelite.api.ObjectID.DENSE_FOREST_3999; +import static net.runelite.api.ObjectID.FALLEN_TREE_33192; +import static net.runelite.api.ObjectID.FENCE_16518; +import static net.runelite.api.ObjectID.GAP; +import static net.runelite.api.ObjectID.GAP_2831; +import static net.runelite.api.ObjectID.GAP_29326; +import static net.runelite.api.ObjectID.HOLE_16520; +import static net.runelite.api.ObjectID.HOLE_30966; +import static net.runelite.api.ObjectID.HOLE_31481; +import static net.runelite.api.ObjectID.HOLE_31482; +import static net.runelite.api.ObjectID.ICE_CHUNKS_31822; +import static net.runelite.api.ObjectID.ICE_CHUNKS_31990; +import static net.runelite.api.ObjectID.JUTTING_WALL_17002; +import static net.runelite.api.ObjectID.LADDER_30938; +import static net.runelite.api.ObjectID.LADDER_30939; +import static net.runelite.api.ObjectID.LADDER_30940; +import static net.runelite.api.ObjectID.LADDER_30941; +import static net.runelite.api.ObjectID.LEAVES; +import static net.runelite.api.ObjectID.LEAVES_3924; +import static net.runelite.api.ObjectID.LEAVES_3925; +import static net.runelite.api.ObjectID.LEDGE_33190; +import static net.runelite.api.ObjectID.LITTLE_BOULDER; +import static net.runelite.api.ObjectID.LOG_BALANCE_16540; +import static net.runelite.api.ObjectID.LOG_BALANCE_16541; +import static net.runelite.api.ObjectID.LOG_BALANCE_16542; +import static net.runelite.api.ObjectID.LOG_BALANCE_16546; +import static net.runelite.api.ObjectID.LOG_BALANCE_16547; +import static net.runelite.api.ObjectID.LOG_BALANCE_16548; +import static net.runelite.api.ObjectID.LOG_BALANCE_20882; +import static net.runelite.api.ObjectID.LOG_BALANCE_20884; +import static net.runelite.api.ObjectID.LOG_BALANCE_23274; +import static net.runelite.api.ObjectID.LOG_BALANCE_3929; +import static net.runelite.api.ObjectID.LOG_BALANCE_3930; +import static net.runelite.api.ObjectID.LOG_BALANCE_3931; +import static net.runelite.api.ObjectID.LOG_BALANCE_3932; +import static net.runelite.api.ObjectID.LOG_BALANCE_3933; +import static net.runelite.api.ObjectID.LOOSE_RAILING; +import static net.runelite.api.ObjectID.LOOSE_RAILING_2186; +import static net.runelite.api.ObjectID.LOOSE_RAILING_28849; +import static net.runelite.api.ObjectID.LOW_FENCE; +import static net.runelite.api.ObjectID.MONKEYBARS_23566; +import static net.runelite.api.ObjectID.MONKEYBARS_23567; +import static net.runelite.api.ObjectID.MYSTERIOUS_PIPE; +import static net.runelite.api.ObjectID.OBSTACLE; +import static net.runelite.api.ObjectID.OBSTACLE_30767; +import static net.runelite.api.ObjectID.OBSTACLE_30962; +import static net.runelite.api.ObjectID.OBSTACLE_30964; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_16509; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_16511; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_23140; +import static net.runelite.api.ObjectID.ORNATE_RAILING; +import static net.runelite.api.ObjectID.ORNATE_RAILING_17000; +import static net.runelite.api.ObjectID.PILE_OF_RUBBLE_23563; +import static net.runelite.api.ObjectID.PILE_OF_RUBBLE_23564; +import static net.runelite.api.ObjectID.PILLAR_31561; +import static net.runelite.api.ObjectID.PILLAR_31809; +import static net.runelite.api.ObjectID.PIPE_21727; +import static net.runelite.api.ObjectID.PIPE_21728; +import static net.runelite.api.ObjectID.ROCKS; +import static net.runelite.api.ObjectID.ROCKSLIDE_33184; +import static net.runelite.api.ObjectID.ROCKSLIDE_33185; +import static net.runelite.api.ObjectID.ROCKSLIDE_33191; +import static net.runelite.api.ObjectID.ROCKS_14106; +import static net.runelite.api.ObjectID.ROCKS_16464; +import static net.runelite.api.ObjectID.ROCKS_16514; +import static net.runelite.api.ObjectID.ROCKS_16515; +import static net.runelite.api.ObjectID.ROCKS_16521; +import static net.runelite.api.ObjectID.ROCKS_16522; +import static net.runelite.api.ObjectID.ROCKS_16523; +import static net.runelite.api.ObjectID.ROCKS_16524; +import static net.runelite.api.ObjectID.ROCKS_16534; +import static net.runelite.api.ObjectID.ROCKS_16535; +import static net.runelite.api.ObjectID.ROCKS_16545; +import static net.runelite.api.ObjectID.ROCKS_16549; +import static net.runelite.api.ObjectID.ROCKS_16550; +import static net.runelite.api.ObjectID.ROCKS_16998; +import static net.runelite.api.ObjectID.ROCKS_16999; +import static net.runelite.api.ObjectID.ROCKS_17042; +import static net.runelite.api.ObjectID.ROCKS_19849; +import static net.runelite.api.ObjectID.ROCKS_2231; +import static net.runelite.api.ObjectID.ROCKS_27984; +import static net.runelite.api.ObjectID.ROCKS_27985; +import static net.runelite.api.ObjectID.ROCKS_27987; +import static net.runelite.api.ObjectID.ROCKS_27988; +import static net.runelite.api.ObjectID.ROCKS_31757; +import static net.runelite.api.ObjectID.ROCKS_31758; +import static net.runelite.api.ObjectID.ROCKS_31759; +import static net.runelite.api.ObjectID.ROCKS_34396; +import static net.runelite.api.ObjectID.ROCKS_34397; +import static net.runelite.api.ObjectID.ROCKS_34741; +import static net.runelite.api.ObjectID.ROCKS_3748; +import static net.runelite.api.ObjectID.ROCKS_3790; +import static net.runelite.api.ObjectID.ROCKS_3791; +import static net.runelite.api.ObjectID.ROCKS_3803; +import static net.runelite.api.ObjectID.ROCKS_3804; +import static net.runelite.api.ObjectID.ROCKS_6673; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26400; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26401; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26402; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26404; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26405; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26406; +import static net.runelite.api.ObjectID.ROCK_16115; +import static net.runelite.api.ObjectID.ROPESWING_23568; +import static net.runelite.api.ObjectID.ROPESWING_23569; +import static net.runelite.api.ObjectID.ROPE_ANCHOR; +import static net.runelite.api.ObjectID.ROPE_ANCHOR_30917; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21306; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21307; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21308; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21309; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21310; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21311; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21312; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21313; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21314; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21315; +import static net.runelite.api.ObjectID.RUBBER_CAP_MUSHROOM; +import static net.runelite.api.ObjectID.SPIKEY_CHAIN; +import static net.runelite.api.ObjectID.SPIKEY_CHAIN_16538; +import static net.runelite.api.ObjectID.STAIRS_31485; +import static net.runelite.api.ObjectID.STEPPING_STONES; +import static net.runelite.api.ObjectID.STEPPING_STONES_23646; +import static net.runelite.api.ObjectID.STEPPING_STONES_23647; +import static net.runelite.api.ObjectID.STEPPING_STONE_10663; +import static net.runelite.api.ObjectID.STEPPING_STONE_11768; +import static net.runelite.api.ObjectID.STEPPING_STONE_13504; +import static net.runelite.api.ObjectID.STEPPING_STONE_14917; +import static net.runelite.api.ObjectID.STEPPING_STONE_14918; +import static net.runelite.api.ObjectID.STEPPING_STONE_16466; +import static net.runelite.api.ObjectID.STEPPING_STONE_16513; +import static net.runelite.api.ObjectID.STEPPING_STONE_16533; +import static net.runelite.api.ObjectID.STEPPING_STONE_19040; +import static net.runelite.api.ObjectID.STEPPING_STONE_19042; +import static net.runelite.api.ObjectID.STEPPING_STONE_21738; +import static net.runelite.api.ObjectID.STEPPING_STONE_21739; +import static net.runelite.api.ObjectID.STEPPING_STONE_29728; +import static net.runelite.api.ObjectID.STEPPING_STONE_29729; +import static net.runelite.api.ObjectID.STEPPING_STONE_29730; +import static net.runelite.api.ObjectID.STEPPING_STONE_5948; +import static net.runelite.api.ObjectID.STEPPING_STONE_5949; +import static net.runelite.api.ObjectID.STEPS; +import static net.runelite.api.ObjectID.STEPS_29993; +import static net.runelite.api.ObjectID.STICKS; +import static net.runelite.api.ObjectID.STILE; +import static net.runelite.api.ObjectID.STILE_12982; +import static net.runelite.api.ObjectID.STRANGE_FLOOR; +import static net.runelite.api.ObjectID.STRANGE_FLOOR_16544; +import static net.runelite.api.ObjectID.STRONG_TREE_17074; +import static net.runelite.api.ObjectID.TIGHTGAP; +import static net.runelite.api.ObjectID.TRELLIS_20056; +import static net.runelite.api.ObjectID.TRIPWIRE; +import static net.runelite.api.ObjectID.TUNNEL_30174; +import static net.runelite.api.ObjectID.TUNNEL_30175; +import static net.runelite.api.ObjectID.TUNNEL_30959; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_16528; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_16529; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_16530; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_19032; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_19036; +import static net.runelite.api.ObjectID.VINE_26880; +import static net.runelite.api.ObjectID.VINE_26882; +import static net.runelite.api.ObjectID.WALL_17047; +import static net.runelite.api.ObjectID.WALL_17049; +import static net.runelite.api.ObjectID.WALL_17050; +import static net.runelite.api.ObjectID.WEATHERED_WALL; +import static net.runelite.api.ObjectID.WEATHERED_WALL_16526; import net.runelite.api.coords.WorldPoint; @Getter public enum AgilityShortcut { GENERIC_SHORTCUT(1, "Shortcut", null, - // Trollheim - ROCKS_3790, ROCKS_3791, - // Fremennik Slayer Cave - STEPS_29993, - // Fossil Island - LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, RUBBER_CAP_MUSHROOM, - // Brimhaven dungeon - CREVICE_30198, - // Lumbridge - STILE_12982, - // Gu'Tanoth Bridge - GAP, GAP_2831, - // Lumbridge Swamp Caves - STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673, - // Morytania Pirate Ship - ROCK_16115, - // Lumber Yard - BROKEN_FENCE_2618, - // McGrubor's Wood - LOOSE_RAILING, - // Underwater Area Fossil Island - TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, - // Tree Gnome Village - LOOSE_RAILING_2186, - // Burgh de Rott - LOW_FENCE, - // Taverley - STILE, - // Asgarnian Ice Dungeon - STEPS, - // Fossil Island Wyvern Cave - STAIRS_31485), + // Trollheim + ROCKS_3790, ROCKS_3791, + // Fremennik Slayer Cave + STEPS_29993, + // Fossil Island + LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, RUBBER_CAP_MUSHROOM, + // Brimhaven dungeon + CREVICE_30198, + // Lumbridge + STILE_12982, + // Gu'Tanoth Bridge + GAP, GAP_2831, + // Lumbridge Swamp Caves + STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673, + // Morytania Pirate Ship + ROCK_16115, + // Lumber Yard + BROKEN_FENCE_2618, + // McGrubor's Wood + LOOSE_RAILING, + // Underwater Area Fossil Island + TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, + // Tree Gnome Village + LOOSE_RAILING_2186, + // Burgh de Rott + LOW_FENCE, + // Taverley + STILE, + // Asgarnian Ice Dungeon + STEPS, + // Fossil Island Wyvern Cave + STAIRS_31485), BRIMHAVEN_DUNGEON_MEDIUM_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2698, 9491, 0), PIPE_21727), BRIMHAVEN_DUNGEON_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2655, 9573, 0), PIPE_21728), BRIMHAVEN_DUNGEON_STEPPING_STONES_RETURN(1, "Pipe Squeeze", null, STEPPING_STONE_21739), BRIMHAVEN_DUNGEON_LOG_BALANCE_RETURN(1, "Log Balance", null, LOG_BALANCE_20884), AGILITY_PYRAMID_ROCKS_WEST(1, "Rocks", null, CLIMBING_ROCKS_11948), CAIRN_ISLE_CLIMBING_ROCKS(1, "Rocks", null, CLIMBING_ROCKS), - KARAMJA_GLIDER_LOG(1, "Log Balance", new WorldPoint(2906, 3050, 0), A_WOODEN_LOG ), - FALADOR_CRUMBLING_WALL(5, "Crumbling Wall", new WorldPoint(2936, 3357, 0), CRUMBLING_WALL_24222 ), + KARAMJA_GLIDER_LOG(1, "Log Balance", new WorldPoint(2906, 3050, 0), A_WOODEN_LOG), + FALADOR_CRUMBLING_WALL(5, "Crumbling Wall", new WorldPoint(2936, 3357, 0), CRUMBLING_WALL_24222), RIVER_LUM_GRAPPLE_WEST(8, "Grapple Broken Raft", new WorldPoint(3245, 3179, 0), BROKEN_RAFT), RIVER_LUM_GRAPPLE_EAST(8, "Grapple Broken Raft", new WorldPoint(3258, 3179, 0), BROKEN_RAFT), CORSAIR_COVE_ROCKS(10, "Rocks", new WorldPoint(2545, 2871, 0), ROCKS_31757), @@ -84,7 +288,7 @@ public enum AgilityShortcut GOBLIN_VILLAGE_WALL(14, "Wall", new WorldPoint(2925, 3523, 0), TIGHTGAP), CORSAIR_COVE_DUNGEON_PILLAR(15, "Pillar Jump", new WorldPoint(1980, 8996, 0), PILLAR_31809), EDGEVILLE_DUNGEON_MONKEYBARS(15, "Monkey Bars", null, MONKEYBARS_23566), - TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15 + TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15 YANILLE_UNDERWALL_TUNNEL(16, "Underwall Tunnel", new WorldPoint(2574, 3109, 0), HOLE_16520, CASTLE_WALL), YANILLE_WATCHTOWER_TRELLIS(18, "Trellis", null, TRELLIS_20056), COAL_TRUCKS_LOG_BALANCE(20, "Log Balance", new WorldPoint(2598, 3475, 0), LOG_BALANCE_23274), @@ -128,7 +332,7 @@ public enum AgilityShortcut DEEP_WILDERNESS_DUNGEON_CREVICE_SOUTH(46, "Narrow Crevice", new WorldPoint(3045, 10327, 0), CREVICE_19043), TROLLHEIM_HARD_CLIFF_SCRAMBLE(47, "Rocks", new WorldPoint(2902, 3680, 0), ROCKS_16524), FREMENNIK_LOG_BALANCE(48, "Log Balance", new WorldPoint(2721, 3591, 0), LOG_BALANCE_16540, LOG_BALANCE_16541, LOG_BALANCE_16542), - YANILLE_DUNGEON_PIPE_SQUEEZE(49, "Pipe Squeeze", null, OBSTACLE_PIPE_23140), + YANILLE_DUNGEON_PIPE_SQUEEZE(49, "Pipe Squeeze", null, OBSTACLE_PIPE_23140), ARCEUUS_ESSENCE_MINE_BOULDER(49, "Boulder", new WorldPoint(1774, 3888, 0), BOULDER_27990), MORYTANIA_STEPPING_STONE(50, "Stepping Stone", new WorldPoint(3418, 3326, 0), STEPPING_STONE_13504), VARROCK_SEWERS_PIPE_SQUEEZE(51, "Pipe Squeeze", new WorldPoint(3152, 9905, 0), OBSTACLE_PIPE_16511), @@ -141,7 +345,7 @@ public enum AgilityShortcut ISAFDAR_FOREST_OBSTACLES(56, "Trap", null, DENSE_FOREST_3938, DENSE_FOREST_3939, DENSE_FOREST_3998, DENSE_FOREST_3999, DENSE_FOREST, LEAVES, LEAVES_3924, LEAVES_3925, STICKS, TRIPWIRE), RELEKKA_EAST_FENCE(57, "Fence", new WorldPoint(2688, 3697, 0), BROKEN_FENCE), YANILLE_DUNGEON_MONKEY_BARS(57, "Monkey Bars", null, MONKEYBARS_23567), - PHASMATYS_ECTOPOOL_SHORTCUT(58, "Weathered Wall", null , WEATHERED_WALL, WEATHERED_WALL_16526), + PHASMATYS_ECTOPOOL_SHORTCUT(58, "Weathered Wall", null, WEATHERED_WALL, WEATHERED_WALL_16526), ELVEN_OVERPASS_CLIFF_SCRAMBLE(59, "Rocks", new WorldPoint(2345, 3300, 0), ROCKS_16514, ROCKS_16515), WILDERNESS_GWD_CLIMB_EAST(60, "Rocks", new WorldPoint(2943, 3770, 0), ROCKY_HANDHOLDS_26400, ROCKY_HANDHOLDS_26401, ROCKY_HANDHOLDS_26402, ROCKY_HANDHOLDS_26404, ROCKY_HANDHOLDS_26405, ROCKY_HANDHOLDS_26406), WILDERNESS_GWD_CLIMB_WEST(60, "Rocks", new WorldPoint(2928, 3760, 0), ROCKY_HANDHOLDS_26400, ROCKY_HANDHOLDS_26401, ROCKY_HANDHOLDS_26402, ROCKY_HANDHOLDS_26404, ROCKY_HANDHOLDS_26405, ROCKY_HANDHOLDS_26406), @@ -169,22 +373,22 @@ public enum AgilityShortcut TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON(70, "Pipe Squeeze", new WorldPoint(2886, 9798, 0), OBSTACLE_PIPE_16509), TAVERLEY_DUNGEON_ROCKS_NORTH(70, "Rocks", new WorldPoint(2887, 9823, 0), ROCKS, ROCKS_14106), TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106), - FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole" , new WorldPoint(3713, 3827, 0), HOLE_31481, HOLE_31482), - FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole" , new WorldPoint(3715, 3817, 0), HOLE_31481, HOLE_31482), + FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole", new WorldPoint(3713, 3827, 0), HOLE_31481, HOLE_31482), + FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole", new WorldPoint(3715, 3817, 0), HOLE_31481, HOLE_31482), AL_KHARID_WINDOW(70, "Window", new WorldPoint(3293, 3158, 0), BROKEN_WALL_33344, BIG_WINDOW), GWD_SARADOMIN_ROPE_NORTH(70, "Rope Descent", new WorldPoint(2912, 5300, 0), NULL_26371), GWD_SARADOMIN_ROPE_SOUTH(70, "Rope Descent", new WorldPoint(2951, 5267, 0), NULL_26375), - SLAYER_TOWER_ADVANCED_CHAIN_FIRST(71, "Spiked Chain (Floor 2)", new WorldPoint(3447, 3578, 0), SPIKEY_CHAIN ), + SLAYER_TOWER_ADVANCED_CHAIN_FIRST(71, "Spiked Chain (Floor 2)", new WorldPoint(3447, 3578, 0), SPIKEY_CHAIN), SLAYER_TOWER_ADVANCED_CHAIN_SECOND(71, "Spiked Chain (Floor 3)", new WorldPoint(3446, 3576, 0), SPIKEY_CHAIN_16538), STRONGHOLD_SLAYER_CAVE_TUNNEL(72, "Tunnel", new WorldPoint(2431, 9806, 0), TUNNEL_30174, TUNNEL_30175), TROLL_STRONGHOLD_WALL_CLIMB(73, "Rocks", new WorldPoint(2841, 3694, 0), ROCKS_16464), - ARCEUUS_ESSENSE_MINE_WEST(73, "Rock Climb", new WorldPoint(1742, 3853, 0), ROCKS_27984, ROCKS_27985 ), + ARCEUUS_ESSENSE_MINE_WEST(73, "Rock Climb", new WorldPoint(1742, 3853, 0), ROCKS_27984, ROCKS_27985), LAVA_DRAGON_ISLE_JUMP(74, "Stepping Stone", new WorldPoint(3200, 3807, 0), STEPPING_STONE_14918), REVENANT_CAVES_DEMONS_JUMP(75, "Jump", new WorldPoint(3199, 10135, 0), PILLAR_31561), REVENANT_CAVES_ANKOU_EAST(75, "Jump", new WorldPoint(3201, 10195, 0), PILLAR_31561), REVENANT_CAVES_ANKOU_NORTH(75, "Jump", new WorldPoint(3180, 10209, 0), PILLAR_31561), ZUL_ANDRA_ISLAND_CROSSING(76, "Stepping Stone", new WorldPoint(2156, 3073, 0), STEPPING_STONE_10663), - SHILO_VILLAGE_STEPPING_STONES( 77, "Stepping Stones", new WorldPoint(2863, 2974, 0), STEPPING_STONE_16466), + SHILO_VILLAGE_STEPPING_STONES(77, "Stepping Stones", new WorldPoint(2863, 2974, 0), STEPPING_STONE_16466), KHARAZI_JUNGLE_VINE_CLIMB(79, "Vine", new WorldPoint(2897, 2939, 0), NULL_26884, NULL_26886), TAVERLEY_DUNGEON_SPIKED_BLADES(80, "Strange Floor", new WorldPoint(2877, 9813, 0), STRANGE_FLOOR), SLAYER_DUNGEON_CHASM_JUMP(81, "Spiked Blades", new WorldPoint(2770, 10003, 0), STRANGE_FLOOR_16544), diff --git a/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java b/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java index 0290c7856a..c4c9a66df7 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java +++ b/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java @@ -1,84 +1,85 @@ -/* - * Copyright (c) 2018 Abex - * 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.game; - -import java.awt.image.BufferedImage; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JLabel; - -public class AsyncBufferedImage extends BufferedImage -{ - private final List listeners = new CopyOnWriteArrayList<>(); - public AsyncBufferedImage(int width, int height, int imageType) - { - super(width, height, imageType); - } - - /** - * Call when the buffer has been changed - */ - public void changed() - { - for (Runnable r : listeners) - { - r.run(); - } - } - - /** - * Register a function to be ran when the buffer has changed - */ - public void onChanged(Runnable r) - { - listeners.add(r); - } - - /** - * Calls setIcon on c, ensuring it is repainted when this changes - */ - public void addTo(JButton c) - { - c.setIcon(makeIcon(c)); - } - - /** - * Calls setIcon on c, ensuring it is repainted when this changes - */ - public void addTo(JLabel c) - { - c.setIcon(makeIcon(c)); - } - - private ImageIcon makeIcon(JComponent c) - { - listeners.add(c::repaint); - return new ImageIcon(this); - } -} +/* + * Copyright (c) 2018 Abex + * 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.game; + +import java.awt.image.BufferedImage; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; + +public class AsyncBufferedImage extends BufferedImage +{ + private final List listeners = new CopyOnWriteArrayList<>(); + + public AsyncBufferedImage(int width, int height, int imageType) + { + super(width, height, imageType); + } + + /** + * Call when the buffer has been changed + */ + public void changed() + { + for (Runnable r : listeners) + { + r.run(); + } + } + + /** + * Register a function to be ran when the buffer has changed + */ + public void onChanged(Runnable r) + { + listeners.add(r); + } + + /** + * Calls setIcon on c, ensuring it is repainted when this changes + */ + public void addTo(JButton c) + { + c.setIcon(makeIcon(c)); + } + + /** + * Calls setIcon on c, ensuring it is repainted when this changes + */ + public void addTo(JLabel c) + { + c.setIcon(makeIcon(c)); + } + + private ImageIcon makeIcon(JComponent c) + { + listeners.add(c::repaint); + return new ImageIcon(this); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index 0f21a5b434..a8f7200568 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -1,475 +1,586 @@ -/* - * Copyright (c) 2017, Adam - * 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.game; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableMap; -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.Value; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM; -import net.runelite.api.GameState; -import net.runelite.api.ItemComposition; -import net.runelite.api.ItemID; -import static net.runelite.api.ItemID.*; -import net.runelite.api.SpritePixels; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.PostItemComposition; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.http.api.item.ItemClient; -import net.runelite.http.api.item.ItemPrice; -import net.runelite.http.api.item.ItemStats; - -@Singleton -@Slf4j -public class ItemManager -{ - @Value - private static class ImageKey - { - private final int itemId; - private final int itemQuantity; - private final boolean stackable; - } - - @Value - private static class OutlineKey - { - private final int itemId; - private final int itemQuantity; - private final Color outlineColor; - } - - private final Client client; - private final ScheduledExecutorService scheduledExecutorService; - private final ClientThread clientThread; - - private final ItemClient itemClient = new ItemClient(); - private Map itemPrices = Collections.emptyMap(); - private Map itemStats = Collections.emptyMap(); - private final LoadingCache itemImages; - private final LoadingCache itemCompositions; - private final LoadingCache itemOutlines; - - // Worn items with weight reducing property have a different worn and inventory ItemID - private static final ImmutableMap WORN_ITEMS = ImmutableMap.builder(). - put(BOOTS_OF_LIGHTNESS_89, BOOTS_OF_LIGHTNESS). - put(PENANCE_GLOVES_10554, PENANCE_GLOVES). - - put(GRACEFUL_HOOD_11851, GRACEFUL_HOOD). - put(GRACEFUL_CAPE_11853, GRACEFUL_CAPE). - put(GRACEFUL_TOP_11855, GRACEFUL_TOP). - put(GRACEFUL_LEGS_11857, GRACEFUL_LEGS). - put(GRACEFUL_GLOVES_11859, GRACEFUL_GLOVES). - put(GRACEFUL_BOOTS_11861, GRACEFUL_BOOTS). - put(GRACEFUL_HOOD_13580, GRACEFUL_HOOD_13579). - put(GRACEFUL_CAPE_13582, GRACEFUL_CAPE_13581). - put(GRACEFUL_TOP_13584, GRACEFUL_TOP_13583). - put(GRACEFUL_LEGS_13586, GRACEFUL_LEGS_13585). - put(GRACEFUL_GLOVES_13588, GRACEFUL_GLOVES_13587). - put(GRACEFUL_BOOTS_13590, GRACEFUL_BOOTS_13589). - put(GRACEFUL_HOOD_13592, GRACEFUL_HOOD_13591). - put(GRACEFUL_CAPE_13594, GRACEFUL_CAPE_13593). - put(GRACEFUL_TOP_13596, GRACEFUL_TOP_13595). - put(GRACEFUL_LEGS_13598, GRACEFUL_LEGS_13597). - put(GRACEFUL_GLOVES_13600, GRACEFUL_GLOVES_13599). - put(GRACEFUL_BOOTS_13602, GRACEFUL_BOOTS_13601). - put(GRACEFUL_HOOD_13604, GRACEFUL_HOOD_13603). - put(GRACEFUL_CAPE_13606, GRACEFUL_CAPE_13605). - put(GRACEFUL_TOP_13608, GRACEFUL_TOP_13607). - put(GRACEFUL_LEGS_13610, GRACEFUL_LEGS_13609). - put(GRACEFUL_GLOVES_13612, GRACEFUL_GLOVES_13611). - put(GRACEFUL_BOOTS_13614, GRACEFUL_BOOTS_13613). - put(GRACEFUL_HOOD_13616, GRACEFUL_HOOD_13615). - put(GRACEFUL_CAPE_13618, GRACEFUL_CAPE_13617). - put(GRACEFUL_TOP_13620, GRACEFUL_TOP_13619). - put(GRACEFUL_LEGS_13622, GRACEFUL_LEGS_13621). - put(GRACEFUL_GLOVES_13624, GRACEFUL_GLOVES_13623). - put(GRACEFUL_BOOTS_13626, GRACEFUL_BOOTS_13625). - put(GRACEFUL_HOOD_13628, GRACEFUL_HOOD_13627). - put(GRACEFUL_CAPE_13630, GRACEFUL_CAPE_13629). - put(GRACEFUL_TOP_13632, GRACEFUL_TOP_13631). - put(GRACEFUL_LEGS_13634, GRACEFUL_LEGS_13633). - put(GRACEFUL_GLOVES_13636, GRACEFUL_GLOVES_13635). - put(GRACEFUL_BOOTS_13638, GRACEFUL_BOOTS_13637). - put(GRACEFUL_HOOD_13668, GRACEFUL_HOOD_13667). - put(GRACEFUL_CAPE_13670, GRACEFUL_CAPE_13669). - put(GRACEFUL_TOP_13672, GRACEFUL_TOP_13671). - put(GRACEFUL_LEGS_13674, GRACEFUL_LEGS_13673). - put(GRACEFUL_GLOVES_13676, GRACEFUL_GLOVES_13675). - put(GRACEFUL_BOOTS_13678, GRACEFUL_BOOTS_13677). - put(GRACEFUL_HOOD_21063, GRACEFUL_HOOD_21061). - put(GRACEFUL_CAPE_21066, GRACEFUL_CAPE_21064). - put(GRACEFUL_TOP_21069, GRACEFUL_TOP_21067). - put(GRACEFUL_LEGS_21072, GRACEFUL_LEGS_21070). - put(GRACEFUL_GLOVES_21075, GRACEFUL_GLOVES_21073). - put(GRACEFUL_BOOTS_21078, GRACEFUL_BOOTS_21076). - - put(MAX_CAPE_13342, MAX_CAPE). - - put(SPOTTED_CAPE_10073, SPOTTED_CAPE). - put(SPOTTIER_CAPE_10074, SPOTTIER_CAPE). - - put(AGILITY_CAPET_13341, AGILITY_CAPET). - put(AGILITY_CAPE_13340, AGILITY_CAPE). - build(); - - @Inject - public ItemManager(Client client, ScheduledExecutorService executor, ClientThread clientThread) - { - this.client = client; - this.scheduledExecutorService = executor; - this.clientThread = clientThread; - - scheduledExecutorService.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES); - scheduledExecutorService.submit(this::loadStats); - - itemImages = CacheBuilder.newBuilder() - .maximumSize(128L) - .expireAfterAccess(1, TimeUnit.HOURS) - .build(new CacheLoader() - { - @Override - public AsyncBufferedImage load(ImageKey key) throws Exception - { - return loadImage(key.itemId, key.itemQuantity, key.stackable); - } - }); - - itemCompositions = CacheBuilder.newBuilder() - .maximumSize(1024L) - .expireAfterAccess(1, TimeUnit.HOURS) - .build(new CacheLoader() - { - @Override - public ItemComposition load(Integer key) throws Exception - { - return client.getItemDefinition(key); - } - }); - - itemOutlines = CacheBuilder.newBuilder() - .maximumSize(128L) - .expireAfterAccess(1, TimeUnit.HOURS) - .build(new CacheLoader() - { - @Override - public BufferedImage load(OutlineKey key) throws Exception - { - return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor); - } - }); - } - - private void loadPrices() - { - try - { - ItemPrice[] prices = itemClient.getPrices(); - if (prices != null) - { - ImmutableMap.Builder map = ImmutableMap.builderWithExpectedSize(prices.length); - for (ItemPrice price : prices) - { - map.put(price.getId(), price); - } - itemPrices = map.build(); - } - - log.debug("Loaded {} prices", itemPrices.size()); - } - catch (IOException e) - { - log.warn("error loading prices!", e); - } - } - - private void loadStats() - { - try - { - final Map stats = itemClient.getStats(); - if (stats != null) - { - itemStats = ImmutableMap.copyOf(stats); - } - - log.debug("Loaded {} stats", itemStats.size()); - } - catch (IOException e) - { - log.warn("error loading stats!", e); - } - } - - - @Subscribe - public void onGameStateChanged(final GameStateChanged event) - { - if (event.getGameState() == GameState.HOPPING || event.getGameState() == GameState.LOGIN_SCREEN) - { - itemCompositions.invalidateAll(); - } - } - - @Subscribe - public void onPostItemComposition(PostItemComposition event) - { - itemCompositions.put(event.getItemComposition().getId(), event.getItemComposition()); - } - - /** - * Invalidates internal item manager item composition cache (but not client item composition cache) - * @see Client#getItemCompositionCache() - */ - public void invalidateItemCompositionCache() - { - itemCompositions.invalidateAll(); - } - - /** - * Look up an item's price - * - * @param itemID item id - * @return item price - */ - public int getItemPrice(int itemID) - { - if (itemID == ItemID.COINS_995) - { - return 1; - } - if (itemID == ItemID.PLATINUM_TOKEN) - { - return 1000; - } - - UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(itemID)); - if (p != null) - { - return getItemPrice(p.getPriceID()) * p.getQuantity(); - } - - int price = 0; - for (int mappedID : ItemMapping.map(itemID)) - { - ItemPrice ip = itemPrices.get(mappedID); - if (ip != null) - { - price += ip.getPrice(); - } - } - - return price; - } - - /** - * Look up an item's stats - * @param itemId item id - * @return item stats - */ - @Nullable - public ItemStats getItemStats(int itemId, boolean allowNote) - { - ItemComposition itemComposition = getItemComposition(itemId); - - if (itemComposition == null || itemComposition.getName() == null || (!allowNote && itemComposition.getNote() != -1)) - { - return null; - } - - return itemStats.get(canonicalize(itemId)); - } - - /** - * Search for tradeable items based on item name - * - * @param itemName item name - * @return - */ - public List search(String itemName) - { - itemName = itemName.toLowerCase(); - - List result = new ArrayList<>(); - for (ItemPrice itemPrice : itemPrices.values()) - { - final String name = itemPrice.getName(); - if (name.toLowerCase().contains(itemName)) - { - result.add(itemPrice); - } - } - return result; - } - - /** - * Look up an item's composition - * - * @param itemId item id - * @return item composition - */ - public ItemComposition getItemComposition(int itemId) - { - assert client.isClientThread() : "getItemComposition must be called on client thread"; - return itemCompositions.getUnchecked(itemId); - } - - /** - * Get an item's un-noted, un-placeholdered ID - */ - public int canonicalize(int itemID) - { - ItemComposition itemComposition = getItemComposition(itemID); - - if (itemComposition.getNote() != -1) - { - return itemComposition.getLinkedNoteId(); - } - - if (itemComposition.getPlaceholderTemplateId() != -1) - { - return itemComposition.getPlaceholderId(); - } - - return WORN_ITEMS.getOrDefault(itemID, itemID); - } - - /** - * Loads item sprite from game, makes transparent, and generates image - * - * @param itemId - * @return - */ - private AsyncBufferedImage loadImage(int itemId, int quantity, boolean stackable) - { - AsyncBufferedImage img = new AsyncBufferedImage(36, 32, BufferedImage.TYPE_INT_ARGB); - clientThread.invoke(() -> - { - if (client.getGameState().ordinal() < GameState.LOGIN_SCREEN.ordinal()) - { - return false; - } - SpritePixels sprite = client.createItemSprite(itemId, quantity, 1, SpritePixels.DEFAULT_SHADOW_COLOR, - stackable ? 1 : 0, false, CLIENT_DEFAULT_ZOOM); - if (sprite == null) - { - return false; - } - sprite.toBufferedImage(img); - img.changed(); - return true; - }); - return img; - } - - /** - * Get item sprite image as BufferedImage. - *

- * This method may return immediately with a blank image if not called on the game thread. - * The image will be filled in later. If this is used for a UI label/button, it should be added - * using AsyncBufferedImage::addTo to ensure it is painted properly - * - * @param itemId - * @return - */ - public AsyncBufferedImage getImage(int itemId) - { - return getImage(itemId, 1, false); - } - - /** - * Get item sprite image as BufferedImage. - *

- * This method may return immediately with a blank image if not called on the game thread. - * The image will be filled in later. If this is used for a UI label/button, it should be added - * using AsyncBufferedImage::addTo to ensure it is painted properly - * - * @param itemId - * @param quantity - * @return - */ - public AsyncBufferedImage getImage(int itemId, int quantity, boolean stackable) - { - try - { - return itemImages.get(new ImageKey(itemId, quantity, stackable)); - } - catch (ExecutionException ex) - { - return null; - } - } - - /** - * Create item sprite and applies an outline. - * - * @param itemId item id - * @param itemQuantity item quantity - * @param outlineColor outline color - * @return image - */ - private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) - { - final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, true, 710); - return itemSprite.toBufferedOutline(outlineColor); - } - - /** - * Get item outline with a specific color. - * - * @param itemId item id - * @param itemQuantity item quantity - * @param outlineColor outline color - * @return image - */ - public BufferedImage getItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) - { - try - { - return itemOutlines.get(new OutlineKey(itemId, itemQuantity, outlineColor)); - } - catch (ExecutionException e) - { - return null; - } - } -} +/* + * Copyright (c) 2017, Adam + * 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.game; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM; +import net.runelite.api.GameState; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemID; +import static net.runelite.api.ItemID.AGILITY_CAPE; +import static net.runelite.api.ItemID.AGILITY_CAPET; +import static net.runelite.api.ItemID.AGILITY_CAPET_13341; +import static net.runelite.api.ItemID.AGILITY_CAPE_13340; +import static net.runelite.api.ItemID.BOOTS_OF_LIGHTNESS; +import static net.runelite.api.ItemID.BOOTS_OF_LIGHTNESS_89; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_11861; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13589; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13590; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13601; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13602; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13613; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13614; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13625; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13626; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13637; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13638; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13677; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13678; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_21076; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_21078; +import static net.runelite.api.ItemID.GRACEFUL_CAPE; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_11853; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13581; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13582; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13593; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13594; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13605; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13606; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13617; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13618; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13629; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13630; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13669; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13670; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_21064; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_21066; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_11859; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13587; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13588; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13599; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13600; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13611; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13612; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13623; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13624; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13635; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13636; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13675; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13676; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_21073; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_21075; +import static net.runelite.api.ItemID.GRACEFUL_HOOD; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_11851; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13579; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13580; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13591; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13592; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13603; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13604; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13615; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13616; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13627; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13628; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13667; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13668; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_21061; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_21063; +import static net.runelite.api.ItemID.GRACEFUL_LEGS; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_11857; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13585; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13586; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13597; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13598; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13609; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13610; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13621; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13622; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13633; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13634; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13673; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13674; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_21070; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_21072; +import static net.runelite.api.ItemID.GRACEFUL_TOP; +import static net.runelite.api.ItemID.GRACEFUL_TOP_11855; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13583; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13584; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13595; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13596; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13607; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13608; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13619; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13620; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13631; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13632; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13671; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13672; +import static net.runelite.api.ItemID.GRACEFUL_TOP_21067; +import static net.runelite.api.ItemID.GRACEFUL_TOP_21069; +import static net.runelite.api.ItemID.MAX_CAPE; +import static net.runelite.api.ItemID.MAX_CAPE_13342; +import static net.runelite.api.ItemID.PENANCE_GLOVES; +import static net.runelite.api.ItemID.PENANCE_GLOVES_10554; +import static net.runelite.api.ItemID.SPOTTED_CAPE; +import static net.runelite.api.ItemID.SPOTTED_CAPE_10073; +import static net.runelite.api.ItemID.SPOTTIER_CAPE; +import static net.runelite.api.ItemID.SPOTTIER_CAPE_10074; +import net.runelite.api.SpritePixels; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.PostItemComposition; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.http.api.item.ItemClient; +import net.runelite.http.api.item.ItemPrice; +import net.runelite.http.api.item.ItemStats; + +@Singleton +@Slf4j +public class ItemManager +{ + @Value + private static class ImageKey + { + private final int itemId; + private final int itemQuantity; + private final boolean stackable; + } + + @Value + private static class OutlineKey + { + private final int itemId; + private final int itemQuantity; + private final Color outlineColor; + } + + private final Client client; + private final ScheduledExecutorService scheduledExecutorService; + private final ClientThread clientThread; + + private final ItemClient itemClient = new ItemClient(); + private Map itemPrices = Collections.emptyMap(); + private Map itemStats = Collections.emptyMap(); + private final LoadingCache itemImages; + private final LoadingCache itemCompositions; + private final LoadingCache itemOutlines; + + // Worn items with weight reducing property have a different worn and inventory ItemID + private static final ImmutableMap WORN_ITEMS = ImmutableMap.builder(). + put(BOOTS_OF_LIGHTNESS_89, BOOTS_OF_LIGHTNESS). + put(PENANCE_GLOVES_10554, PENANCE_GLOVES). + + put(GRACEFUL_HOOD_11851, GRACEFUL_HOOD). + put(GRACEFUL_CAPE_11853, GRACEFUL_CAPE). + put(GRACEFUL_TOP_11855, GRACEFUL_TOP). + put(GRACEFUL_LEGS_11857, GRACEFUL_LEGS). + put(GRACEFUL_GLOVES_11859, GRACEFUL_GLOVES). + put(GRACEFUL_BOOTS_11861, GRACEFUL_BOOTS). + put(GRACEFUL_HOOD_13580, GRACEFUL_HOOD_13579). + put(GRACEFUL_CAPE_13582, GRACEFUL_CAPE_13581). + put(GRACEFUL_TOP_13584, GRACEFUL_TOP_13583). + put(GRACEFUL_LEGS_13586, GRACEFUL_LEGS_13585). + put(GRACEFUL_GLOVES_13588, GRACEFUL_GLOVES_13587). + put(GRACEFUL_BOOTS_13590, GRACEFUL_BOOTS_13589). + put(GRACEFUL_HOOD_13592, GRACEFUL_HOOD_13591). + put(GRACEFUL_CAPE_13594, GRACEFUL_CAPE_13593). + put(GRACEFUL_TOP_13596, GRACEFUL_TOP_13595). + put(GRACEFUL_LEGS_13598, GRACEFUL_LEGS_13597). + put(GRACEFUL_GLOVES_13600, GRACEFUL_GLOVES_13599). + put(GRACEFUL_BOOTS_13602, GRACEFUL_BOOTS_13601). + put(GRACEFUL_HOOD_13604, GRACEFUL_HOOD_13603). + put(GRACEFUL_CAPE_13606, GRACEFUL_CAPE_13605). + put(GRACEFUL_TOP_13608, GRACEFUL_TOP_13607). + put(GRACEFUL_LEGS_13610, GRACEFUL_LEGS_13609). + put(GRACEFUL_GLOVES_13612, GRACEFUL_GLOVES_13611). + put(GRACEFUL_BOOTS_13614, GRACEFUL_BOOTS_13613). + put(GRACEFUL_HOOD_13616, GRACEFUL_HOOD_13615). + put(GRACEFUL_CAPE_13618, GRACEFUL_CAPE_13617). + put(GRACEFUL_TOP_13620, GRACEFUL_TOP_13619). + put(GRACEFUL_LEGS_13622, GRACEFUL_LEGS_13621). + put(GRACEFUL_GLOVES_13624, GRACEFUL_GLOVES_13623). + put(GRACEFUL_BOOTS_13626, GRACEFUL_BOOTS_13625). + put(GRACEFUL_HOOD_13628, GRACEFUL_HOOD_13627). + put(GRACEFUL_CAPE_13630, GRACEFUL_CAPE_13629). + put(GRACEFUL_TOP_13632, GRACEFUL_TOP_13631). + put(GRACEFUL_LEGS_13634, GRACEFUL_LEGS_13633). + put(GRACEFUL_GLOVES_13636, GRACEFUL_GLOVES_13635). + put(GRACEFUL_BOOTS_13638, GRACEFUL_BOOTS_13637). + put(GRACEFUL_HOOD_13668, GRACEFUL_HOOD_13667). + put(GRACEFUL_CAPE_13670, GRACEFUL_CAPE_13669). + put(GRACEFUL_TOP_13672, GRACEFUL_TOP_13671). + put(GRACEFUL_LEGS_13674, GRACEFUL_LEGS_13673). + put(GRACEFUL_GLOVES_13676, GRACEFUL_GLOVES_13675). + put(GRACEFUL_BOOTS_13678, GRACEFUL_BOOTS_13677). + put(GRACEFUL_HOOD_21063, GRACEFUL_HOOD_21061). + put(GRACEFUL_CAPE_21066, GRACEFUL_CAPE_21064). + put(GRACEFUL_TOP_21069, GRACEFUL_TOP_21067). + put(GRACEFUL_LEGS_21072, GRACEFUL_LEGS_21070). + put(GRACEFUL_GLOVES_21075, GRACEFUL_GLOVES_21073). + put(GRACEFUL_BOOTS_21078, GRACEFUL_BOOTS_21076). + + put(MAX_CAPE_13342, MAX_CAPE). + + put(SPOTTED_CAPE_10073, SPOTTED_CAPE). + put(SPOTTIER_CAPE_10074, SPOTTIER_CAPE). + + put(AGILITY_CAPET_13341, AGILITY_CAPET). + put(AGILITY_CAPE_13340, AGILITY_CAPE). + build(); + + @Inject + public ItemManager(Client client, ScheduledExecutorService executor, ClientThread clientThread) + { + this.client = client; + this.scheduledExecutorService = executor; + this.clientThread = clientThread; + + scheduledExecutorService.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES); + scheduledExecutorService.submit(this::loadStats); + + itemImages = CacheBuilder.newBuilder() + .maximumSize(128L) + .expireAfterAccess(1, TimeUnit.HOURS) + .build(new CacheLoader() + { + @Override + public AsyncBufferedImage load(ImageKey key) throws Exception + { + return loadImage(key.itemId, key.itemQuantity, key.stackable); + } + }); + + itemCompositions = CacheBuilder.newBuilder() + .maximumSize(1024L) + .expireAfterAccess(1, TimeUnit.HOURS) + .build(new CacheLoader() + { + @Override + public ItemComposition load(Integer key) throws Exception + { + return client.getItemDefinition(key); + } + }); + + itemOutlines = CacheBuilder.newBuilder() + .maximumSize(128L) + .expireAfterAccess(1, TimeUnit.HOURS) + .build(new CacheLoader() + { + @Override + public BufferedImage load(OutlineKey key) throws Exception + { + return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor); + } + }); + } + + private void loadPrices() + { + try + { + ItemPrice[] prices = itemClient.getPrices(); + if (prices != null) + { + ImmutableMap.Builder map = ImmutableMap.builderWithExpectedSize(prices.length); + for (ItemPrice price : prices) + { + map.put(price.getId(), price); + } + itemPrices = map.build(); + } + + log.debug("Loaded {} prices", itemPrices.size()); + } + catch (IOException e) + { + log.warn("error loading prices!", e); + } + } + + private void loadStats() + { + try + { + final Map stats = itemClient.getStats(); + if (stats != null) + { + itemStats = ImmutableMap.copyOf(stats); + } + + log.debug("Loaded {} stats", itemStats.size()); + } + catch (IOException e) + { + log.warn("error loading stats!", e); + } + } + + + @Subscribe + public void onGameStateChanged(final GameStateChanged event) + { + if (event.getGameState() == GameState.HOPPING || event.getGameState() == GameState.LOGIN_SCREEN) + { + itemCompositions.invalidateAll(); + } + } + + @Subscribe + public void onPostItemComposition(PostItemComposition event) + { + itemCompositions.put(event.getItemComposition().getId(), event.getItemComposition()); + } + + /** + * Invalidates internal item manager item composition cache (but not client item composition cache) + * + * @see Client#getItemCompositionCache() + */ + public void invalidateItemCompositionCache() + { + itemCompositions.invalidateAll(); + } + + /** + * Look up an item's price + * + * @param itemID item id + * @return item price + */ + public int getItemPrice(int itemID) + { + if (itemID == ItemID.COINS_995) + { + return 1; + } + if (itemID == ItemID.PLATINUM_TOKEN) + { + return 1000; + } + + UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(itemID)); + if (p != null) + { + return getItemPrice(p.getPriceID()) * p.getQuantity(); + } + + int price = 0; + for (int mappedID : ItemMapping.map(itemID)) + { + ItemPrice ip = itemPrices.get(mappedID); + if (ip != null) + { + price += ip.getPrice(); + } + } + + return price; + } + + /** + * Look up an item's stats + * + * @param itemId item id + * @return item stats + */ + @Nullable + public ItemStats getItemStats(int itemId, boolean allowNote) + { + ItemComposition itemComposition = getItemComposition(itemId); + + if (itemComposition == null || itemComposition.getName() == null || (!allowNote && itemComposition.getNote() != -1)) + { + return null; + } + + return itemStats.get(canonicalize(itemId)); + } + + /** + * Search for tradeable items based on item name + * + * @param itemName item name + * @return + */ + public List search(String itemName) + { + itemName = itemName.toLowerCase(); + + List result = new ArrayList<>(); + for (ItemPrice itemPrice : itemPrices.values()) + { + final String name = itemPrice.getName(); + if (name.toLowerCase().contains(itemName)) + { + result.add(itemPrice); + } + } + return result; + } + + /** + * Look up an item's composition + * + * @param itemId item id + * @return item composition + */ + public ItemComposition getItemComposition(int itemId) + { + assert client.isClientThread() : "getItemComposition must be called on client thread"; + return itemCompositions.getUnchecked(itemId); + } + + /** + * Get an item's un-noted, un-placeholdered ID + */ + public int canonicalize(int itemID) + { + ItemComposition itemComposition = getItemComposition(itemID); + + if (itemComposition.getNote() != -1) + { + return itemComposition.getLinkedNoteId(); + } + + if (itemComposition.getPlaceholderTemplateId() != -1) + { + return itemComposition.getPlaceholderId(); + } + + return WORN_ITEMS.getOrDefault(itemID, itemID); + } + + /** + * Loads item sprite from game, makes transparent, and generates image + * + * @param itemId + * @return + */ + private AsyncBufferedImage loadImage(int itemId, int quantity, boolean stackable) + { + AsyncBufferedImage img = new AsyncBufferedImage(36, 32, BufferedImage.TYPE_INT_ARGB); + clientThread.invoke(() -> + { + if (client.getGameState().ordinal() < GameState.LOGIN_SCREEN.ordinal()) + { + return false; + } + SpritePixels sprite = client.createItemSprite(itemId, quantity, 1, SpritePixels.DEFAULT_SHADOW_COLOR, + stackable ? 1 : 0, false, CLIENT_DEFAULT_ZOOM); + if (sprite == null) + { + return false; + } + sprite.toBufferedImage(img); + img.changed(); + return true; + }); + return img; + } + + /** + * Get item sprite image as BufferedImage. + *

+ * This method may return immediately with a blank image if not called on the game thread. + * The image will be filled in later. If this is used for a UI label/button, it should be added + * using AsyncBufferedImage::addTo to ensure it is painted properly + * + * @param itemId + * @return + */ + public AsyncBufferedImage getImage(int itemId) + { + return getImage(itemId, 1, false); + } + + /** + * Get item sprite image as BufferedImage. + *

+ * This method may return immediately with a blank image if not called on the game thread. + * The image will be filled in later. If this is used for a UI label/button, it should be added + * using AsyncBufferedImage::addTo to ensure it is painted properly + * + * @param itemId + * @param quantity + * @return + */ + public AsyncBufferedImage getImage(int itemId, int quantity, boolean stackable) + { + try + { + return itemImages.get(new ImageKey(itemId, quantity, stackable)); + } + catch (ExecutionException ex) + { + return null; + } + } + + /** + * Create item sprite and applies an outline. + * + * @param itemId item id + * @param itemQuantity item quantity + * @param outlineColor outline color + * @return image + */ + private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) + { + final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, true, 710); + return itemSprite.toBufferedOutline(outlineColor); + } + + /** + * Get item outline with a specific color. + * + * @param itemId item id + * @param itemQuantity item quantity + * @param outlineColor outline color + * @return image + */ + public BufferedImage getItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) + { + try + { + return itemOutlines.get(new OutlineKey(itemId, itemQuantity, outlineColor)); + } + catch (ExecutionException e) + { + return null; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java index 22eed36031..b0e70bcd49 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java @@ -1,271 +1,675 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * Copyright (c) 2018, Seth - * 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.game; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import java.util.Collection; -import java.util.Collections; -import static net.runelite.api.ItemID.*; - -/** - * Converts untradeable items to it's tradeable counterparts - */ -public enum ItemMapping -{ - // Barrows equipment - ITEM_AHRIMS_HOOD(AHRIMS_HOOD, AHRIMS_HOOD_25, AHRIMS_HOOD_50, AHRIMS_HOOD_75, AHRIMS_HOOD_100), - ITEM_AHRIMS_ROBETOP(AHRIMS_ROBETOP, AHRIMS_ROBETOP_25, AHRIMS_ROBETOP_50, AHRIMS_ROBETOP_75, AHRIMS_ROBETOP_100), - ITEM_AHRIMS_ROBEBOTTOM(AHRIMS_ROBESKIRT, AHRIMS_ROBESKIRT_25, AHRIMS_ROBESKIRT_50, AHRIMS_ROBESKIRT_75, AHRIMS_ROBESKIRT_100), - ITEM_AHRIMS_STAFF(AHRIMS_STAFF, AHRIMS_STAFF_25, AHRIMS_STAFF_50, AHRIMS_STAFF_75, AHRIMS_STAFF_100), - ITEM_KARILS_COIF(KARILS_COIF, KARILS_COIF_25, KARILS_COIF_50, KARILS_COIF_75, KARILS_COIF_100), - ITEM_KARILS_LEATHERTOP(KARILS_LEATHERTOP, KARILS_LEATHERTOP_25, KARILS_LEATHERTOP_50, KARILS_LEATHERTOP_75, KARILS_LEATHERTOP_100), - ITEM_KARILS_LEATHERSKIRT(KARILS_LEATHERSKIRT, KARILS_LEATHERSKIRT_25, KARILS_LEATHERSKIRT_50, KARILS_LEATHERSKIRT_75, KARILS_LEATHERSKIRT_100), - ITEM_KARILS_CROSSBOW(KARILS_CROSSBOW, KARILS_CROSSBOW_25, KARILS_CROSSBOW_50, KARILS_CROSSBOW_75, KARILS_CROSSBOW_100), - ITEM_DHAROKS_HELM(DHAROKS_HELM, DHAROKS_HELM_25, DHAROKS_HELM_50, DHAROKS_HELM_75, DHAROKS_HELM_100), - ITEM_DHAROKS_PLATEBODY(DHAROKS_PLATEBODY, DHAROKS_PLATEBODY_25, DHAROKS_PLATEBODY_50, DHAROKS_PLATEBODY_75, DHAROKS_PLATEBODY_100), - ITEM_DHAROKS_PLATELEGS(DHAROKS_PLATELEGS, DHAROKS_PLATELEGS_25, DHAROKS_PLATELEGS_50, DHAROKS_PLATELEGS_75, DHAROKS_PLATELEGS_100), - ITEM_DHARKS_GREATEAXE(DHAROKS_GREATAXE, DHAROKS_GREATAXE_25, DHAROKS_GREATAXE_50, DHAROKS_GREATAXE_75, DHAROKS_GREATAXE_100), - ITEM_GUTHANS_HELM(GUTHANS_HELM, GUTHANS_HELM_25, GUTHANS_HELM_50, GUTHANS_HELM_75, GUTHANS_HELM_100), - ITEM_GUTHANS_PLATEBODY(GUTHANS_PLATEBODY, GUTHANS_PLATEBODY_25, GUTHANS_PLATEBODY_50, GUTHANS_PLATEBODY_75, GUTHANS_PLATEBODY_100), - ITEM_GUTHANS_CHAINSKIRT(GUTHANS_CHAINSKIRT, GUTHANS_CHAINSKIRT_25, GUTHANS_CHAINSKIRT_50, GUTHANS_CHAINSKIRT_75, GUTHANS_CHAINSKIRT_100), - ITEM_GUTHANS_WARSPEAR(GUTHANS_WARSPEAR, GUTHANS_WARSPEAR_25, GUTHANS_WARSPEAR_50, GUTHANS_WARSPEAR_75, GUTHANS_WARSPEAR_100), - ITEM_TORAGS_HELM(TORAGS_HELM, TORAGS_HELM_25, TORAGS_HELM_50, TORAGS_HELM_75, TORAGS_HELM_100), - ITEM_TORAGS_PLATEBODY(TORAGS_PLATEBODY, TORAGS_PLATEBODY_25, TORAGS_PLATEBODY_50, TORAGS_PLATEBODY_75, TORAGS_PLATEBODY_100), - ITEM_TORAGS_PLATELEGS(TORAGS_PLATELEGS, TORAGS_PLATELEGS_25, TORAGS_PLATELEGS_50, TORAGS_PLATELEGS_75, TORAGS_PLATELEGS_100), - ITEM_TORAGS_HAMMERS(TORAGS_HAMMERS, TORAGS_HAMMERS_25, TORAGS_HAMMERS_50, TORAGS_HAMMERS_75, TORAGS_HAMMERS_100), - ITEM_VERACS_HELM(VERACS_HELM, VERACS_HELM_25, VERACS_HELM_50, VERACS_HELM_75, VERACS_HELM_100), - ITEM_VERACS_BRASSARD(VERACS_BRASSARD, VERACS_BRASSARD_25, VERACS_BRASSARD_50, VERACS_BRASSARD_75, VERACS_BRASSARD_100), - ITEM_VERACS_PLATESKIRT(VERACS_PLATESKIRT, VERACS_PLATESKIRT_25, VERACS_PLATESKIRT_50, VERACS_PLATESKIRT_75, VERACS_PLATESKIRT_100), - ITEM_VERACS_FLAIL(VERACS_FLAIL, VERACS_FLAIL_25, VERACS_FLAIL_50, VERACS_FLAIL_75, VERACS_FLAIL_100), - - // Dragon equipment ornament kits - ITEM_DRAGON_SCIMITAR(DRAGON_SCIMITAR, DRAGON_SCIMITAR_OR), - ITEM_DRAGON_SCIMITAR_ORNAMENT_KIT(DRAGON_SCIMITAR_ORNAMENT_KIT, DRAGON_SCIMITAR_OR), - ITEM_DRAGON_DEFENDER(DRAGON_DEFENDER_ORNAMENT_KIT, DRAGON_DEFENDER_T), - ITEM_DRAGON_PICKAXE(DRAGON_PICKAXE, DRAGON_PICKAXE_12797), - ITEM_DRAGON_KITESHIELD(DRAGON_KITESHIELD, DRAGON_KITESHIELD_G), - ITEM_DRAGON_KITESHIELD_ORNAMENT_KIT(DRAGON_KITESHIELD_ORNAMENT_KIT, DRAGON_KITESHIELD_G), - ITEM_DRAGON_FULL_HELM(DRAGON_FULL_HELM, DRAGON_FULL_HELM_G), - ITEM_DRAGON_FULL_HELM_ORNAMENT_KIT(DRAGON_FULL_HELM_ORNAMENT_KIT, DRAGON_FULL_HELM_G), - ITEM_DRAGON_CHAINBODY(DRAGON_CHAINBODY_3140, DRAGON_CHAINBODY_G), - ITEM_DRAGON_CHAINBODY_ORNAMENT_KIT(DRAGON_CHAINBODY_ORNAMENT_KIT, DRAGON_CHAINBODY_G), - ITEM_DRAGON_PLATEBODY(DRAGON_PLATEBODY, DRAGON_PLATEBODY_G), - ITEM_DRAGON_PLATEBODY_ORNAMENT_KIT(DRAGON_PLATEBODY_ORNAMENT_KIT, DRAGON_PLATEBODY_G), - ITEM_DRAGON_PLATESKIRT(DRAGON_PLATESKIRT, DRAGON_PLATESKIRT_G), - ITEM_DRAGON_SKIRT_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATESKIRT_G), - ITEM_DRAGON_PLATELEGS(DRAGON_PLATELEGS, DRAGON_PLATELEGS_G), - ITEM_DRAGON_LEGS_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATELEGS_G), - ITEM_DRAGON_SQ_SHIELD(DRAGON_SQ_SHIELD, DRAGON_SQ_SHIELD_G), - ITEM_DRAGON_SQ_SHIELD_ORNAMENT_KIT(DRAGON_SQ_SHIELD_ORNAMENT_KIT, DRAGON_SQ_SHIELD_G), - ITEM_DRAGON_BOOTS(DRAGON_BOOTS, DRAGON_BOOTS_G), - ITEM_DRAGON_BOOTS_ORNAMENT_KIT(DRAGON_BOOTS_ORNAMENT_KIT, DRAGON_BOOTS_G), - - // Godsword ornament kits - ITEM_ARMADYL_GODSWORD(ARMADYL_GODSWORD, ARMADYL_GODSWORD_OR), - ITEM_ARMADYL_GODSWORD_ORNAMENT_KIT(ARMADYL_GODSWORD_ORNAMENT_KIT, ARMADYL_GODSWORD_OR), - ITEM_BANDOS_GODSWORD(BANDOS_GODSWORD, BANDOS_GODSWORD_OR), - ITEM_BANDOS_GODSWORD_ORNAMENT_KIT(BANDOS_GODSWORD_ORNAMENT_KIT, BANDOS_GODSWORD_OR), - ITEM_ZAMORAK_GODSWORD(ZAMORAK_GODSWORD, ZAMORAK_GODSWORD_OR), - ITEM_ZAMORAK_GODSWORD_ORNAMENT_KIT(ZAMORAK_GODSWORD_ORNAMENT_KIT, ZAMORAK_GODSWORD_OR), - ITEM_SARADOMIN_GODSWORD(SARADOMIN_GODSWORD, SARADOMIN_GODSWORD_OR), - ITEM_SARADOMIN_GODSWORD_ORNAMENT_KIT(SARADOMIN_GODSWORD_ORNAMENT_KIT, SARADOMIN_GODSWORD_OR), - - // Jewellery ornament kits - ITEM_AMULET_OF_TORTURE(AMULET_OF_TORTURE, AMULET_OF_TORTURE_OR), - ITEM_TORTURE_ORNAMENT_KIT(TORTURE_ORNAMENT_KIT, AMULET_OF_TORTURE_OR), - ITEM_NECKLACE_OF_ANGUISH(NECKLACE_OF_ANGUISH, NECKLACE_OF_ANGUISH_OR), - ITEM_ANGUISH_ORNAMENT_KIT(ANGUISH_ORNAMENT_KIT, NECKLACE_OF_ANGUISH_OR), - ITEM_OCCULT_NECKLACE(OCCULT_NECKLACE, OCCULT_NECKLACE_OR), - ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR), - ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), - ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), - - // Ensouled heads - ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD), - ITEM_ENSOULED_MONKEY_HEAD(ENSOULED_MONKEY_HEAD_13451, ENSOULED_MONKEY_HEAD), - ITEM_ENSOULED_IMP_HEAD(ENSOULED_IMP_HEAD_13454, ENSOULED_IMP_HEAD), - ITEM_ENSOULED_MINOTAUR_HEAD(ENSOULED_MINOTAUR_HEAD_13457, ENSOULED_MINOTAUR_HEAD), - ITEM_ENSOULED_SCORPION_HEAD(ENSOULED_SCORPION_HEAD_13460, ENSOULED_SCORPION_HEAD), - ITEM_ENSOULED_BEAR_HEAD(ENSOULED_BEAR_HEAD_13463, ENSOULED_BEAR_HEAD), - ITEM_ENSOULED_UNICORN_HEAD(ENSOULED_UNICORN_HEAD_13466, ENSOULED_UNICORN_HEAD), - ITEM_ENSOULED_DOG_HEAD(ENSOULED_DOG_HEAD_13469, ENSOULED_DOG_HEAD), - ITEM_ENSOULED_CHAOS_DRUID_HEAD(ENSOULED_CHAOS_DRUID_HEAD_13472, ENSOULED_CHAOS_DRUID_HEAD), - ITEM_ENSOULED_GIANT_HEAD(ENSOULED_GIANT_HEAD_13475, ENSOULED_GIANT_HEAD), - ITEM_ENSOULED_OGRE_HEAD(ENSOULED_OGRE_HEAD_13478, ENSOULED_OGRE_HEAD), - ITEM_ENSOULED_ELF_HEAD(ENSOULED_ELF_HEAD_13481, ENSOULED_ELF_HEAD), - ITEM_ENSOULED_TROLL_HEAD(ENSOULED_TROLL_HEAD_13484, ENSOULED_TROLL_HEAD), - ITEM_ENSOULED_HORROR_HEAD(ENSOULED_HORROR_HEAD_13487, ENSOULED_HORROR_HEAD), - ITEM_ENSOULED_KALPHITE_HEAD(ENSOULED_KALPHITE_HEAD_13490, ENSOULED_KALPHITE_HEAD), - ITEM_ENSOULED_DAGANNOTH_HEAD(ENSOULED_DAGANNOTH_HEAD_13493, ENSOULED_DAGANNOTH_HEAD), - ITEM_ENSOULED_BLOODVELD_HEAD(ENSOULED_BLOODVELD_HEAD_13496, ENSOULED_BLOODVELD_HEAD), - ITEM_ENSOULED_TZHAAR_HEAD(ENSOULED_TZHAAR_HEAD_13499, ENSOULED_TZHAAR_HEAD), - ITEM_ENSOULED_DEMON_HEAD(ENSOULED_DEMON_HEAD_13502, ENSOULED_DEMON_HEAD), - ITEM_ENSOULED_AVIANSIE_HEAD(ENSOULED_AVIANSIE_HEAD_13505, ENSOULED_AVIANSIE_HEAD), - ITEM_ENSOULED_ABYSSAL_HEAD(ENSOULED_ABYSSAL_HEAD_13508, ENSOULED_ABYSSAL_HEAD), - ITEM_ENSOULED_DRAGON_HEAD(ENSOULED_DRAGON_HEAD_13511, ENSOULED_DRAGON_HEAD), - - // Imbued rings - ITEM_BERSERKER_RING(BERSERKER_RING, BERSERKER_RING_I), - ITEM_SEERS_RING(SEERS_RING, SEERS_RING_I), - ITEM_WARRIOR_RING(WARRIOR_RING, WARRIOR_RING_I), - ITEM_ARCHERS_RING(ARCHERS_RING, ARCHERS_RING_I), - ITEM_TREASONOUS_RING(TREASONOUS_RING, TREASONOUS_RING_I), - ITEM_TYRANNICAL_RING(TYRANNICAL_RING, TYRANNICAL_RING_I), - ITEM_RING_OF_THE_GODS(RING_OF_THE_GODS, RING_OF_THE_GODS_I), - ITEM_RING_OF_SUFFERING(RING_OF_SUFFERING, RING_OF_SUFFERING_I, RING_OF_SUFFERING_R, RING_OF_SUFFERING_RI), - ITEM_GRANITE_RING(GRANITE_RING, GRANITE_RING_I), - - // Bounty hunter - ITEM_GRANITE_MAUL(GRANITE_MAUL, GRANITE_MAUL_12848), - ITEM_MAGIC_SHORTBOW(MAGIC_SHORTBOW, MAGIC_SHORTBOW_I), - ITEM_SARADOMINS_BLESSED_SWORD(SARADOMINS_TEAR, SARADOMINS_BLESSED_SWORD), - - // Jewellery with charges - ITEM_RING_OF_WEALTH(RING_OF_WEALTH, RING_OF_WEALTH_I, RING_OF_WEALTH_1, RING_OF_WEALTH_I1, RING_OF_WEALTH_2, RING_OF_WEALTH_I2, RING_OF_WEALTH_3, RING_OF_WEALTH_I3, RING_OF_WEALTH_4, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5), - ITEM_AMULET_OF_GLORY(AMULET_OF_GLORY, AMULET_OF_GLORY1, AMULET_OF_GLORY2, AMULET_OF_GLORY3, AMULET_OF_GLORY5), - ITEM_AMULET_OF_GLORY_T(AMULET_OF_GLORY_T, AMULET_OF_GLORY_T1, AMULET_OF_GLORY_T2, AMULET_OF_GLORY_T3, AMULET_OF_GLORY_T5), - ITEM_SKILLS_NECKLACE(SKILLS_NECKLACE, SKILLS_NECKLACE1, SKILLS_NECKLACE2, SKILLS_NECKLACE3, SKILLS_NECKLACE5), - ITEM_RING_OF_DUELING(RING_OF_DUELING8, RING_OF_DUELING1, RING_OF_DUELING2, RING_OF_DUELING3, RING_OF_DUELING4, RING_OF_DUELING5, RING_OF_DUELING6, RING_OF_DUELING7), - ITEM_GAMES_NECKLACE(GAMES_NECKLACE8, GAMES_NECKLACE1, GAMES_NECKLACE2, GAMES_NECKLACE3, GAMES_NECKLACE4, GAMES_NECKLACE5, GAMES_NECKLACE6, GAMES_NECKLACE7), - - // Degradable/charged weaponry/armour - ITEM_ABYSSAL_WHIP(ABYSSAL_WHIP, VOLCANIC_ABYSSAL_WHIP, FROZEN_ABYSSAL_WHIP), - ITEM_KRAKEN_TENTACLE(KRAKEN_TENTACLE, ABYSSAL_TENTACLE), - ITEM_TRIDENT_OF_THE_SEAS(UNCHARGED_TRIDENT, TRIDENT_OF_THE_SEAS), - ITEM_TRIDENT_OF_THE_SEAS_E(UNCHARGED_TRIDENT_E, TRIDENT_OF_THE_SEAS_E), - ITEM_TRIDENT_OF_THE_SWAMP(UNCHARGED_TOXIC_TRIDENT, TRIDENT_OF_THE_SWAMP), - ITEM_TRIDENT_OF_THE_SWAMP_E(UNCHARGED_TOXIC_TRIDENT_E, TRIDENT_OF_THE_SWAMP_E), - ITEM_TOXIC_BLOWPIPE(TOXIC_BLOWPIPE_EMPTY, TOXIC_BLOWPIPE), - ITEM_TOXIC_STAFF_OFF_THE_DEAD(TOXIC_STAFF_UNCHARGED, TOXIC_STAFF_OF_THE_DEAD), - ITEM_SERPENTINE_HELM(SERPENTINE_HELM_UNCHARGED, SERPENTINE_HELM, TANZANITE_HELM_UNCHARGED, TANZANITE_HELM, MAGMA_HELM_UNCHARGED, MAGMA_HELM), - ITEM_DRAGONFIRE_SHIELD(DRAGONFIRE_SHIELD_11284, DRAGONFIRE_SHIELD), - ITEM_DRAGONFIRE_WARD(DRAGONFIRE_WARD_22003, DRAGONFIRE_WARD), - ITEM_ANCIENT_WYVERN_SHIELD(ANCIENT_WYVERN_SHIELD_21634, ANCIENT_WYVERN_SHIELD), - ITEM_SANGUINESTI_STAFF(SANGUINESTI_STAFF_UNCHARGED, SANGUINESTI_STAFF), - ITEM_SCYTHE_OF_VITUR(SCYTHE_OF_VITUR_UNCHARGED, SCYTHE_OF_VITUR), - ITEM_TOME_OF_FIRE(TOME_OF_FIRE_EMPTY, TOME_OF_FIRE), - ITEM_CRAWS_BOW(CRAWS_BOW_U, CRAWS_BOW), - ITEM_VIGGORAS_CHAINMACE(VIGGORAS_CHAINMACE_U, VIGGORAS_CHAINMACE), - ITEM_THAMMARONS_SCEPTRE(THAMMARONS_SCEPTRE_U, THAMMARONS_SCEPTRE), - - // Infinity colour kits - ITEM_INFINITY_TOP(INFINITY_TOP, INFINITY_TOP_10605, INFINITY_TOP_20574, DARK_INFINITY_TOP, LIGHT_INFINITY_TOP), - ITEM_INFINITY_TOP_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_TOP), - ITEM_INFINITY_TOP_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_TOP), - ITEM_INFINITY_BOTTOMS(INFINITY_BOTTOMS, INFINITY_BOTTOMS_20575, DARK_INFINITY_BOTTOMS, LIGHT_INFINITY_BOTTOMS), - ITEM_INFINITY_BOTTOMS_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_BOTTOMS), - ITEM_INFINITY_BOTTOMS_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_BOTTOMS), - ITEM_INFINITY_HAT(INFINITY_HAT, DARK_INFINITY_HAT, LIGHT_INFINITY_HAT), - ITEM_INFINITY_HAT_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_HAT), - ITEM_INFINITY_HAT_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_HAT), - - // Miscellaneous ornament kits - ITEM_DARK_BOW(DARK_BOW, DARK_BOW_12765, DARK_BOW_12766, DARK_BOW_12767, DARK_BOW_12768, DARK_BOW_20408), - ITEM_ODIUM_WARD(ODIUM_WARD, ODIUM_WARD_12807), - ITEM_MALEDICTION_WARD(MALEDICTION_WARD, MALEDICTION_WARD_12806), - ITEM_STEAM_BATTLESTAFF(STEAM_BATTLESTAFF, STEAM_BATTLESTAFF_12795), - ITEM_LAVA_BATTLESTAFF(LAVA_BATTLESTAFF, LAVA_BATTLESTAFF_21198), - - // Slayer helm/black mask - ITEM_BLACK_MASK( - BLACK_MASK, BLACK_MASK_I, BLACK_MASK_1, BLACK_MASK_1_I, BLACK_MASK_2, BLACK_MASK_2_I, BLACK_MASK_3, BLACK_MASK_3_I, BLACK_MASK_4, BLACK_MASK_4_I, BLACK_MASK_5, - BLACK_MASK_5_I, BLACK_MASK_6, BLACK_MASK_6_I, BLACK_MASK_7, BLACK_MASK_7_I, BLACK_MASK_8, BLACK_MASK_8_I, BLACK_MASK_9, BLACK_MASK_9_I, BLACK_MASK_10_I, - SLAYER_HELMET, SLAYER_HELMET_I, BLACK_SLAYER_HELMET, BLACK_SLAYER_HELMET_I, PURPLE_SLAYER_HELMET, PURPLE_SLAYER_HELMET_I, RED_SLAYER_HELMET, RED_SLAYER_HELMET_I, - GREEN_SLAYER_HELMET, GREEN_SLAYER_HELMET_I, TURQUOISE_SLAYER_HELMET, TURQUOISE_SLAYER_HELMET_I, HYDRA_SLAYER_HELMET, HYDRA_SLAYER_HELMET_I), - - // Pharaoh's Sceptres - ITEM_PHARAOHS_SCEPTRE_1(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_1), - ITEM_PHARAOHS_SCEPTRE_2(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_2), - ITEM_PHARAOHS_SCEPTRE_4(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_4), - ITEM_PHARAOHS_SCEPTRE_5(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_5), - ITEM_PHARAOHS_SCEPTRE_6(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_6), - ITEM_PHARAOHS_SCEPTRE_7(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_7), - ITEM_PHARAOHS_SCEPTRE_8(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_8), - - // Revertible items - ITEM_HYDRA_LEATHER(HYDRA_LEATHER, FEROCIOUS_GLOVES), - ITEM_HYDRA_TAIL(HYDRA_TAIL, BONECRUSHER_NECKLACE), - ITEM_DRAGONBONE_NECKLACE(DRAGONBONE_NECKLACE, BONECRUSHER_NECKLACE), - ITEM_BOTTOMLESS_COMPOST_BUCKET(BOTTOMLESS_COMPOST_BUCKET, BOTTOMLESS_COMPOST_BUCKET_22997); - - private static final Multimap MAPPINGS = HashMultimap.create(); - private final int tradeableItem; - private final int[] untradableItems; - - static - { - for (final ItemMapping item : values()) - { - for (int itemId : item.untradableItems) - { - MAPPINGS.put(itemId, item.tradeableItem); - } - } - } - - ItemMapping(int tradeableItem, int... untradableItems) - { - this.tradeableItem = tradeableItem; - this.untradableItems = untradableItems; - } - - /** - * Get collection of items that are mapped from single item id. - * - * @param itemId the item id - * @return the collection - */ - public static Collection map(int itemId) - { - final Collection mapping = MAPPINGS.get(itemId); - - if (mapping == null || mapping.isEmpty()) - { - return Collections.singleton(itemId); - } - - return mapping; - } - - /** - * Map an item from its untradeable version to its tradeable version - * - * @param itemId - * @return - */ - public static int mapFirst(int itemId) - { - final Collection mapping = MAPPINGS.get(itemId); - - if (mapping == null || mapping.isEmpty()) - { - return itemId; - } - - return mapping.iterator().next(); - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * Copyright (c) 2018, Seth + * 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.game; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.Collections; +import static net.runelite.api.ItemID.ABYSSAL_TENTACLE; +import static net.runelite.api.ItemID.ABYSSAL_WHIP; +import static net.runelite.api.ItemID.AHRIMS_HOOD; +import static net.runelite.api.ItemID.AHRIMS_HOOD_100; +import static net.runelite.api.ItemID.AHRIMS_HOOD_25; +import static net.runelite.api.ItemID.AHRIMS_HOOD_50; +import static net.runelite.api.ItemID.AHRIMS_HOOD_75; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_100; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_25; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_50; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_75; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_100; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_25; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_50; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_75; +import static net.runelite.api.ItemID.AHRIMS_STAFF; +import static net.runelite.api.ItemID.AHRIMS_STAFF_100; +import static net.runelite.api.ItemID.AHRIMS_STAFF_25; +import static net.runelite.api.ItemID.AHRIMS_STAFF_50; +import static net.runelite.api.ItemID.AHRIMS_STAFF_75; +import static net.runelite.api.ItemID.AMULET_OF_FURY; +import static net.runelite.api.ItemID.AMULET_OF_FURY_OR; +import static net.runelite.api.ItemID.AMULET_OF_GLORY; +import static net.runelite.api.ItemID.AMULET_OF_GLORY1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY5; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T5; +import static net.runelite.api.ItemID.AMULET_OF_TORTURE; +import static net.runelite.api.ItemID.AMULET_OF_TORTURE_OR; +import static net.runelite.api.ItemID.ANCIENT_WYVERN_SHIELD; +import static net.runelite.api.ItemID.ANCIENT_WYVERN_SHIELD_21634; +import static net.runelite.api.ItemID.ANGUISH_ORNAMENT_KIT; +import static net.runelite.api.ItemID.ARCHERS_RING; +import static net.runelite.api.ItemID.ARCHERS_RING_I; +import static net.runelite.api.ItemID.ARMADYL_GODSWORD; +import static net.runelite.api.ItemID.ARMADYL_GODSWORD_OR; +import static net.runelite.api.ItemID.ARMADYL_GODSWORD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.BANDOS_GODSWORD; +import static net.runelite.api.ItemID.BANDOS_GODSWORD_OR; +import static net.runelite.api.ItemID.BANDOS_GODSWORD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.BERSERKER_RING; +import static net.runelite.api.ItemID.BERSERKER_RING_I; +import static net.runelite.api.ItemID.BLACK_MASK; +import static net.runelite.api.ItemID.BLACK_MASK_1; +import static net.runelite.api.ItemID.BLACK_MASK_10_I; +import static net.runelite.api.ItemID.BLACK_MASK_1_I; +import static net.runelite.api.ItemID.BLACK_MASK_2; +import static net.runelite.api.ItemID.BLACK_MASK_2_I; +import static net.runelite.api.ItemID.BLACK_MASK_3; +import static net.runelite.api.ItemID.BLACK_MASK_3_I; +import static net.runelite.api.ItemID.BLACK_MASK_4; +import static net.runelite.api.ItemID.BLACK_MASK_4_I; +import static net.runelite.api.ItemID.BLACK_MASK_5; +import static net.runelite.api.ItemID.BLACK_MASK_5_I; +import static net.runelite.api.ItemID.BLACK_MASK_6; +import static net.runelite.api.ItemID.BLACK_MASK_6_I; +import static net.runelite.api.ItemID.BLACK_MASK_7; +import static net.runelite.api.ItemID.BLACK_MASK_7_I; +import static net.runelite.api.ItemID.BLACK_MASK_8; +import static net.runelite.api.ItemID.BLACK_MASK_8_I; +import static net.runelite.api.ItemID.BLACK_MASK_9; +import static net.runelite.api.ItemID.BLACK_MASK_9_I; +import static net.runelite.api.ItemID.BLACK_MASK_I; +import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET; +import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.BONECRUSHER_NECKLACE; +import static net.runelite.api.ItemID.BOTTOMLESS_COMPOST_BUCKET; +import static net.runelite.api.ItemID.BOTTOMLESS_COMPOST_BUCKET_22997; +import static net.runelite.api.ItemID.CRAWS_BOW; +import static net.runelite.api.ItemID.CRAWS_BOW_U; +import static net.runelite.api.ItemID.DARK_BOW; +import static net.runelite.api.ItemID.DARK_BOW_12765; +import static net.runelite.api.ItemID.DARK_BOW_12766; +import static net.runelite.api.ItemID.DARK_BOW_12767; +import static net.runelite.api.ItemID.DARK_BOW_12768; +import static net.runelite.api.ItemID.DARK_BOW_20408; +import static net.runelite.api.ItemID.DARK_INFINITY_BOTTOMS; +import static net.runelite.api.ItemID.DARK_INFINITY_COLOUR_KIT; +import static net.runelite.api.ItemID.DARK_INFINITY_HAT; +import static net.runelite.api.ItemID.DARK_INFINITY_TOP; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_100; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_25; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_50; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_75; +import static net.runelite.api.ItemID.DHAROKS_HELM; +import static net.runelite.api.ItemID.DHAROKS_HELM_100; +import static net.runelite.api.ItemID.DHAROKS_HELM_25; +import static net.runelite.api.ItemID.DHAROKS_HELM_50; +import static net.runelite.api.ItemID.DHAROKS_HELM_75; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_100; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_25; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_50; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_75; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_100; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_25; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_50; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_75; +import static net.runelite.api.ItemID.DRAGONBONE_NECKLACE; +import static net.runelite.api.ItemID.DRAGONFIRE_SHIELD; +import static net.runelite.api.ItemID.DRAGONFIRE_SHIELD_11284; +import static net.runelite.api.ItemID.DRAGONFIRE_WARD; +import static net.runelite.api.ItemID.DRAGONFIRE_WARD_22003; +import static net.runelite.api.ItemID.DRAGON_BOOTS; +import static net.runelite.api.ItemID.DRAGON_BOOTS_G; +import static net.runelite.api.ItemID.DRAGON_BOOTS_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_CHAINBODY_3140; +import static net.runelite.api.ItemID.DRAGON_CHAINBODY_G; +import static net.runelite.api.ItemID.DRAGON_CHAINBODY_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_DEFENDER_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_DEFENDER_T; +import static net.runelite.api.ItemID.DRAGON_FULL_HELM; +import static net.runelite.api.ItemID.DRAGON_FULL_HELM_G; +import static net.runelite.api.ItemID.DRAGON_FULL_HELM_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_KITESHIELD; +import static net.runelite.api.ItemID.DRAGON_KITESHIELD_G; +import static net.runelite.api.ItemID.DRAGON_KITESHIELD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_LEGSSKIRT_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_PICKAXE; +import static net.runelite.api.ItemID.DRAGON_PICKAXE_12797; +import static net.runelite.api.ItemID.DRAGON_PLATEBODY; +import static net.runelite.api.ItemID.DRAGON_PLATEBODY_G; +import static net.runelite.api.ItemID.DRAGON_PLATEBODY_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_PLATELEGS; +import static net.runelite.api.ItemID.DRAGON_PLATELEGS_G; +import static net.runelite.api.ItemID.DRAGON_PLATESKIRT; +import static net.runelite.api.ItemID.DRAGON_PLATESKIRT_G; +import static net.runelite.api.ItemID.DRAGON_SCIMITAR; +import static net.runelite.api.ItemID.DRAGON_SCIMITAR_OR; +import static net.runelite.api.ItemID.DRAGON_SCIMITAR_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD; +import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD_G; +import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.ENSOULED_ABYSSAL_HEAD; +import static net.runelite.api.ItemID.ENSOULED_ABYSSAL_HEAD_13508; +import static net.runelite.api.ItemID.ENSOULED_AVIANSIE_HEAD; +import static net.runelite.api.ItemID.ENSOULED_AVIANSIE_HEAD_13505; +import static net.runelite.api.ItemID.ENSOULED_BEAR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_BEAR_HEAD_13463; +import static net.runelite.api.ItemID.ENSOULED_BLOODVELD_HEAD; +import static net.runelite.api.ItemID.ENSOULED_BLOODVELD_HEAD_13496; +import static net.runelite.api.ItemID.ENSOULED_CHAOS_DRUID_HEAD; +import static net.runelite.api.ItemID.ENSOULED_CHAOS_DRUID_HEAD_13472; +import static net.runelite.api.ItemID.ENSOULED_DAGANNOTH_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DAGANNOTH_HEAD_13493; +import static net.runelite.api.ItemID.ENSOULED_DEMON_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DEMON_HEAD_13502; +import static net.runelite.api.ItemID.ENSOULED_DOG_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DOG_HEAD_13469; +import static net.runelite.api.ItemID.ENSOULED_DRAGON_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DRAGON_HEAD_13511; +import static net.runelite.api.ItemID.ENSOULED_ELF_HEAD; +import static net.runelite.api.ItemID.ENSOULED_ELF_HEAD_13481; +import static net.runelite.api.ItemID.ENSOULED_GIANT_HEAD; +import static net.runelite.api.ItemID.ENSOULED_GIANT_HEAD_13475; +import static net.runelite.api.ItemID.ENSOULED_GOBLIN_HEAD; +import static net.runelite.api.ItemID.ENSOULED_GOBLIN_HEAD_13448; +import static net.runelite.api.ItemID.ENSOULED_HORROR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_HORROR_HEAD_13487; +import static net.runelite.api.ItemID.ENSOULED_IMP_HEAD; +import static net.runelite.api.ItemID.ENSOULED_IMP_HEAD_13454; +import static net.runelite.api.ItemID.ENSOULED_KALPHITE_HEAD; +import static net.runelite.api.ItemID.ENSOULED_KALPHITE_HEAD_13490; +import static net.runelite.api.ItemID.ENSOULED_MINOTAUR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_MINOTAUR_HEAD_13457; +import static net.runelite.api.ItemID.ENSOULED_MONKEY_HEAD; +import static net.runelite.api.ItemID.ENSOULED_MONKEY_HEAD_13451; +import static net.runelite.api.ItemID.ENSOULED_OGRE_HEAD; +import static net.runelite.api.ItemID.ENSOULED_OGRE_HEAD_13478; +import static net.runelite.api.ItemID.ENSOULED_SCORPION_HEAD; +import static net.runelite.api.ItemID.ENSOULED_SCORPION_HEAD_13460; +import static net.runelite.api.ItemID.ENSOULED_TROLL_HEAD; +import static net.runelite.api.ItemID.ENSOULED_TROLL_HEAD_13484; +import static net.runelite.api.ItemID.ENSOULED_TZHAAR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_TZHAAR_HEAD_13499; +import static net.runelite.api.ItemID.ENSOULED_UNICORN_HEAD; +import static net.runelite.api.ItemID.ENSOULED_UNICORN_HEAD_13466; +import static net.runelite.api.ItemID.FEROCIOUS_GLOVES; +import static net.runelite.api.ItemID.FROZEN_ABYSSAL_WHIP; +import static net.runelite.api.ItemID.FURY_ORNAMENT_KIT; +import static net.runelite.api.ItemID.GAMES_NECKLACE1; +import static net.runelite.api.ItemID.GAMES_NECKLACE2; +import static net.runelite.api.ItemID.GAMES_NECKLACE3; +import static net.runelite.api.ItemID.GAMES_NECKLACE4; +import static net.runelite.api.ItemID.GAMES_NECKLACE5; +import static net.runelite.api.ItemID.GAMES_NECKLACE6; +import static net.runelite.api.ItemID.GAMES_NECKLACE7; +import static net.runelite.api.ItemID.GAMES_NECKLACE8; +import static net.runelite.api.ItemID.GRANITE_MAUL; +import static net.runelite.api.ItemID.GRANITE_MAUL_12848; +import static net.runelite.api.ItemID.GRANITE_RING; +import static net.runelite.api.ItemID.GRANITE_RING_I; +import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET; +import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_100; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_25; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_50; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_75; +import static net.runelite.api.ItemID.GUTHANS_HELM; +import static net.runelite.api.ItemID.GUTHANS_HELM_100; +import static net.runelite.api.ItemID.GUTHANS_HELM_25; +import static net.runelite.api.ItemID.GUTHANS_HELM_50; +import static net.runelite.api.ItemID.GUTHANS_HELM_75; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_100; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_25; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_50; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_75; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_100; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_25; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_50; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_75; +import static net.runelite.api.ItemID.HYDRA_LEATHER; +import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET; +import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.HYDRA_TAIL; +import static net.runelite.api.ItemID.INFINITY_BOTTOMS; +import static net.runelite.api.ItemID.INFINITY_BOTTOMS_20575; +import static net.runelite.api.ItemID.INFINITY_HAT; +import static net.runelite.api.ItemID.INFINITY_TOP; +import static net.runelite.api.ItemID.INFINITY_TOP_10605; +import static net.runelite.api.ItemID.INFINITY_TOP_20574; +import static net.runelite.api.ItemID.KARILS_COIF; +import static net.runelite.api.ItemID.KARILS_COIF_100; +import static net.runelite.api.ItemID.KARILS_COIF_25; +import static net.runelite.api.ItemID.KARILS_COIF_50; +import static net.runelite.api.ItemID.KARILS_COIF_75; +import static net.runelite.api.ItemID.KARILS_CROSSBOW; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_100; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_25; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_50; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_75; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_100; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_25; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_50; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_75; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_100; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_25; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_50; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_75; +import static net.runelite.api.ItemID.KRAKEN_TENTACLE; +import static net.runelite.api.ItemID.LAVA_BATTLESTAFF; +import static net.runelite.api.ItemID.LAVA_BATTLESTAFF_21198; +import static net.runelite.api.ItemID.LIGHT_INFINITY_BOTTOMS; +import static net.runelite.api.ItemID.LIGHT_INFINITY_COLOUR_KIT; +import static net.runelite.api.ItemID.LIGHT_INFINITY_HAT; +import static net.runelite.api.ItemID.LIGHT_INFINITY_TOP; +import static net.runelite.api.ItemID.MAGIC_SHORTBOW; +import static net.runelite.api.ItemID.MAGIC_SHORTBOW_I; +import static net.runelite.api.ItemID.MAGMA_HELM; +import static net.runelite.api.ItemID.MAGMA_HELM_UNCHARGED; +import static net.runelite.api.ItemID.MALEDICTION_WARD; +import static net.runelite.api.ItemID.MALEDICTION_WARD_12806; +import static net.runelite.api.ItemID.NECKLACE_OF_ANGUISH; +import static net.runelite.api.ItemID.NECKLACE_OF_ANGUISH_OR; +import static net.runelite.api.ItemID.OCCULT_NECKLACE; +import static net.runelite.api.ItemID.OCCULT_NECKLACE_OR; +import static net.runelite.api.ItemID.OCCULT_ORNAMENT_KIT; +import static net.runelite.api.ItemID.ODIUM_WARD; +import static net.runelite.api.ItemID.ODIUM_WARD_12807; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_1; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_2; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_4; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_5; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_6; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_7; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_8; +import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET; +import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.RED_SLAYER_HELMET; +import static net.runelite.api.ItemID.RED_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.RING_OF_DUELING1; +import static net.runelite.api.ItemID.RING_OF_DUELING2; +import static net.runelite.api.ItemID.RING_OF_DUELING3; +import static net.runelite.api.ItemID.RING_OF_DUELING4; +import static net.runelite.api.ItemID.RING_OF_DUELING5; +import static net.runelite.api.ItemID.RING_OF_DUELING6; +import static net.runelite.api.ItemID.RING_OF_DUELING7; +import static net.runelite.api.ItemID.RING_OF_DUELING8; +import static net.runelite.api.ItemID.RING_OF_SUFFERING; +import static net.runelite.api.ItemID.RING_OF_SUFFERING_I; +import static net.runelite.api.ItemID.RING_OF_SUFFERING_R; +import static net.runelite.api.ItemID.RING_OF_SUFFERING_RI; +import static net.runelite.api.ItemID.RING_OF_THE_GODS; +import static net.runelite.api.ItemID.RING_OF_THE_GODS_I; +import static net.runelite.api.ItemID.RING_OF_WEALTH; +import static net.runelite.api.ItemID.RING_OF_WEALTH_1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I5; +import static net.runelite.api.ItemID.SANGUINESTI_STAFF; +import static net.runelite.api.ItemID.SANGUINESTI_STAFF_UNCHARGED; +import static net.runelite.api.ItemID.SARADOMINS_BLESSED_SWORD; +import static net.runelite.api.ItemID.SARADOMINS_TEAR; +import static net.runelite.api.ItemID.SARADOMIN_GODSWORD; +import static net.runelite.api.ItemID.SARADOMIN_GODSWORD_OR; +import static net.runelite.api.ItemID.SARADOMIN_GODSWORD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.SCYTHE_OF_VITUR; +import static net.runelite.api.ItemID.SCYTHE_OF_VITUR_UNCHARGED; +import static net.runelite.api.ItemID.SEERS_RING; +import static net.runelite.api.ItemID.SEERS_RING_I; +import static net.runelite.api.ItemID.SERPENTINE_HELM; +import static net.runelite.api.ItemID.SERPENTINE_HELM_UNCHARGED; +import static net.runelite.api.ItemID.SKILLS_NECKLACE; +import static net.runelite.api.ItemID.SKILLS_NECKLACE1; +import static net.runelite.api.ItemID.SKILLS_NECKLACE2; +import static net.runelite.api.ItemID.SKILLS_NECKLACE3; +import static net.runelite.api.ItemID.SKILLS_NECKLACE5; +import static net.runelite.api.ItemID.SLAYER_HELMET; +import static net.runelite.api.ItemID.SLAYER_HELMET_I; +import static net.runelite.api.ItemID.STEAM_BATTLESTAFF; +import static net.runelite.api.ItemID.STEAM_BATTLESTAFF_12795; +import static net.runelite.api.ItemID.TANZANITE_HELM; +import static net.runelite.api.ItemID.TANZANITE_HELM_UNCHARGED; +import static net.runelite.api.ItemID.THAMMARONS_SCEPTRE; +import static net.runelite.api.ItemID.THAMMARONS_SCEPTRE_U; +import static net.runelite.api.ItemID.TOME_OF_FIRE; +import static net.runelite.api.ItemID.TOME_OF_FIRE_EMPTY; +import static net.runelite.api.ItemID.TORAGS_HAMMERS; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_100; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_25; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_50; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_75; +import static net.runelite.api.ItemID.TORAGS_HELM; +import static net.runelite.api.ItemID.TORAGS_HELM_100; +import static net.runelite.api.ItemID.TORAGS_HELM_25; +import static net.runelite.api.ItemID.TORAGS_HELM_50; +import static net.runelite.api.ItemID.TORAGS_HELM_75; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_100; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_25; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_50; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_75; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_100; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_25; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_50; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_75; +import static net.runelite.api.ItemID.TORTURE_ORNAMENT_KIT; +import static net.runelite.api.ItemID.TOXIC_BLOWPIPE; +import static net.runelite.api.ItemID.TOXIC_BLOWPIPE_EMPTY; +import static net.runelite.api.ItemID.TOXIC_STAFF_OF_THE_DEAD; +import static net.runelite.api.ItemID.TOXIC_STAFF_UNCHARGED; +import static net.runelite.api.ItemID.TREASONOUS_RING; +import static net.runelite.api.ItemID.TREASONOUS_RING_I; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SEAS; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SEAS_E; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SWAMP; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SWAMP_E; +import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET; +import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.TYRANNICAL_RING; +import static net.runelite.api.ItemID.TYRANNICAL_RING_I; +import static net.runelite.api.ItemID.UNCHARGED_TOXIC_TRIDENT; +import static net.runelite.api.ItemID.UNCHARGED_TOXIC_TRIDENT_E; +import static net.runelite.api.ItemID.UNCHARGED_TRIDENT; +import static net.runelite.api.ItemID.UNCHARGED_TRIDENT_E; +import static net.runelite.api.ItemID.VERACS_BRASSARD; +import static net.runelite.api.ItemID.VERACS_BRASSARD_100; +import static net.runelite.api.ItemID.VERACS_BRASSARD_25; +import static net.runelite.api.ItemID.VERACS_BRASSARD_50; +import static net.runelite.api.ItemID.VERACS_BRASSARD_75; +import static net.runelite.api.ItemID.VERACS_FLAIL; +import static net.runelite.api.ItemID.VERACS_FLAIL_100; +import static net.runelite.api.ItemID.VERACS_FLAIL_25; +import static net.runelite.api.ItemID.VERACS_FLAIL_50; +import static net.runelite.api.ItemID.VERACS_FLAIL_75; +import static net.runelite.api.ItemID.VERACS_HELM; +import static net.runelite.api.ItemID.VERACS_HELM_100; +import static net.runelite.api.ItemID.VERACS_HELM_25; +import static net.runelite.api.ItemID.VERACS_HELM_50; +import static net.runelite.api.ItemID.VERACS_HELM_75; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_100; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_25; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_50; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_75; +import static net.runelite.api.ItemID.VIGGORAS_CHAINMACE; +import static net.runelite.api.ItemID.VIGGORAS_CHAINMACE_U; +import static net.runelite.api.ItemID.VOLCANIC_ABYSSAL_WHIP; +import static net.runelite.api.ItemID.WARRIOR_RING; +import static net.runelite.api.ItemID.WARRIOR_RING_I; +import static net.runelite.api.ItemID.ZAMORAK_GODSWORD; +import static net.runelite.api.ItemID.ZAMORAK_GODSWORD_OR; +import static net.runelite.api.ItemID.ZAMORAK_GODSWORD_ORNAMENT_KIT; + +/** + * Converts untradeable items to it's tradeable counterparts + */ +public enum ItemMapping +{ + // Barrows equipment + ITEM_AHRIMS_HOOD(AHRIMS_HOOD, AHRIMS_HOOD_25, AHRIMS_HOOD_50, AHRIMS_HOOD_75, AHRIMS_HOOD_100), + ITEM_AHRIMS_ROBETOP(AHRIMS_ROBETOP, AHRIMS_ROBETOP_25, AHRIMS_ROBETOP_50, AHRIMS_ROBETOP_75, AHRIMS_ROBETOP_100), + ITEM_AHRIMS_ROBEBOTTOM(AHRIMS_ROBESKIRT, AHRIMS_ROBESKIRT_25, AHRIMS_ROBESKIRT_50, AHRIMS_ROBESKIRT_75, AHRIMS_ROBESKIRT_100), + ITEM_AHRIMS_STAFF(AHRIMS_STAFF, AHRIMS_STAFF_25, AHRIMS_STAFF_50, AHRIMS_STAFF_75, AHRIMS_STAFF_100), + ITEM_KARILS_COIF(KARILS_COIF, KARILS_COIF_25, KARILS_COIF_50, KARILS_COIF_75, KARILS_COIF_100), + ITEM_KARILS_LEATHERTOP(KARILS_LEATHERTOP, KARILS_LEATHERTOP_25, KARILS_LEATHERTOP_50, KARILS_LEATHERTOP_75, KARILS_LEATHERTOP_100), + ITEM_KARILS_LEATHERSKIRT(KARILS_LEATHERSKIRT, KARILS_LEATHERSKIRT_25, KARILS_LEATHERSKIRT_50, KARILS_LEATHERSKIRT_75, KARILS_LEATHERSKIRT_100), + ITEM_KARILS_CROSSBOW(KARILS_CROSSBOW, KARILS_CROSSBOW_25, KARILS_CROSSBOW_50, KARILS_CROSSBOW_75, KARILS_CROSSBOW_100), + ITEM_DHAROKS_HELM(DHAROKS_HELM, DHAROKS_HELM_25, DHAROKS_HELM_50, DHAROKS_HELM_75, DHAROKS_HELM_100), + ITEM_DHAROKS_PLATEBODY(DHAROKS_PLATEBODY, DHAROKS_PLATEBODY_25, DHAROKS_PLATEBODY_50, DHAROKS_PLATEBODY_75, DHAROKS_PLATEBODY_100), + ITEM_DHAROKS_PLATELEGS(DHAROKS_PLATELEGS, DHAROKS_PLATELEGS_25, DHAROKS_PLATELEGS_50, DHAROKS_PLATELEGS_75, DHAROKS_PLATELEGS_100), + ITEM_DHARKS_GREATEAXE(DHAROKS_GREATAXE, DHAROKS_GREATAXE_25, DHAROKS_GREATAXE_50, DHAROKS_GREATAXE_75, DHAROKS_GREATAXE_100), + ITEM_GUTHANS_HELM(GUTHANS_HELM, GUTHANS_HELM_25, GUTHANS_HELM_50, GUTHANS_HELM_75, GUTHANS_HELM_100), + ITEM_GUTHANS_PLATEBODY(GUTHANS_PLATEBODY, GUTHANS_PLATEBODY_25, GUTHANS_PLATEBODY_50, GUTHANS_PLATEBODY_75, GUTHANS_PLATEBODY_100), + ITEM_GUTHANS_CHAINSKIRT(GUTHANS_CHAINSKIRT, GUTHANS_CHAINSKIRT_25, GUTHANS_CHAINSKIRT_50, GUTHANS_CHAINSKIRT_75, GUTHANS_CHAINSKIRT_100), + ITEM_GUTHANS_WARSPEAR(GUTHANS_WARSPEAR, GUTHANS_WARSPEAR_25, GUTHANS_WARSPEAR_50, GUTHANS_WARSPEAR_75, GUTHANS_WARSPEAR_100), + ITEM_TORAGS_HELM(TORAGS_HELM, TORAGS_HELM_25, TORAGS_HELM_50, TORAGS_HELM_75, TORAGS_HELM_100), + ITEM_TORAGS_PLATEBODY(TORAGS_PLATEBODY, TORAGS_PLATEBODY_25, TORAGS_PLATEBODY_50, TORAGS_PLATEBODY_75, TORAGS_PLATEBODY_100), + ITEM_TORAGS_PLATELEGS(TORAGS_PLATELEGS, TORAGS_PLATELEGS_25, TORAGS_PLATELEGS_50, TORAGS_PLATELEGS_75, TORAGS_PLATELEGS_100), + ITEM_TORAGS_HAMMERS(TORAGS_HAMMERS, TORAGS_HAMMERS_25, TORAGS_HAMMERS_50, TORAGS_HAMMERS_75, TORAGS_HAMMERS_100), + ITEM_VERACS_HELM(VERACS_HELM, VERACS_HELM_25, VERACS_HELM_50, VERACS_HELM_75, VERACS_HELM_100), + ITEM_VERACS_BRASSARD(VERACS_BRASSARD, VERACS_BRASSARD_25, VERACS_BRASSARD_50, VERACS_BRASSARD_75, VERACS_BRASSARD_100), + ITEM_VERACS_PLATESKIRT(VERACS_PLATESKIRT, VERACS_PLATESKIRT_25, VERACS_PLATESKIRT_50, VERACS_PLATESKIRT_75, VERACS_PLATESKIRT_100), + ITEM_VERACS_FLAIL(VERACS_FLAIL, VERACS_FLAIL_25, VERACS_FLAIL_50, VERACS_FLAIL_75, VERACS_FLAIL_100), + + // Dragon equipment ornament kits + ITEM_DRAGON_SCIMITAR(DRAGON_SCIMITAR, DRAGON_SCIMITAR_OR), + ITEM_DRAGON_SCIMITAR_ORNAMENT_KIT(DRAGON_SCIMITAR_ORNAMENT_KIT, DRAGON_SCIMITAR_OR), + ITEM_DRAGON_DEFENDER(DRAGON_DEFENDER_ORNAMENT_KIT, DRAGON_DEFENDER_T), + ITEM_DRAGON_PICKAXE(DRAGON_PICKAXE, DRAGON_PICKAXE_12797), + ITEM_DRAGON_KITESHIELD(DRAGON_KITESHIELD, DRAGON_KITESHIELD_G), + ITEM_DRAGON_KITESHIELD_ORNAMENT_KIT(DRAGON_KITESHIELD_ORNAMENT_KIT, DRAGON_KITESHIELD_G), + ITEM_DRAGON_FULL_HELM(DRAGON_FULL_HELM, DRAGON_FULL_HELM_G), + ITEM_DRAGON_FULL_HELM_ORNAMENT_KIT(DRAGON_FULL_HELM_ORNAMENT_KIT, DRAGON_FULL_HELM_G), + ITEM_DRAGON_CHAINBODY(DRAGON_CHAINBODY_3140, DRAGON_CHAINBODY_G), + ITEM_DRAGON_CHAINBODY_ORNAMENT_KIT(DRAGON_CHAINBODY_ORNAMENT_KIT, DRAGON_CHAINBODY_G), + ITEM_DRAGON_PLATEBODY(DRAGON_PLATEBODY, DRAGON_PLATEBODY_G), + ITEM_DRAGON_PLATEBODY_ORNAMENT_KIT(DRAGON_PLATEBODY_ORNAMENT_KIT, DRAGON_PLATEBODY_G), + ITEM_DRAGON_PLATESKIRT(DRAGON_PLATESKIRT, DRAGON_PLATESKIRT_G), + ITEM_DRAGON_SKIRT_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATESKIRT_G), + ITEM_DRAGON_PLATELEGS(DRAGON_PLATELEGS, DRAGON_PLATELEGS_G), + ITEM_DRAGON_LEGS_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATELEGS_G), + ITEM_DRAGON_SQ_SHIELD(DRAGON_SQ_SHIELD, DRAGON_SQ_SHIELD_G), + ITEM_DRAGON_SQ_SHIELD_ORNAMENT_KIT(DRAGON_SQ_SHIELD_ORNAMENT_KIT, DRAGON_SQ_SHIELD_G), + ITEM_DRAGON_BOOTS(DRAGON_BOOTS, DRAGON_BOOTS_G), + ITEM_DRAGON_BOOTS_ORNAMENT_KIT(DRAGON_BOOTS_ORNAMENT_KIT, DRAGON_BOOTS_G), + + // Godsword ornament kits + ITEM_ARMADYL_GODSWORD(ARMADYL_GODSWORD, ARMADYL_GODSWORD_OR), + ITEM_ARMADYL_GODSWORD_ORNAMENT_KIT(ARMADYL_GODSWORD_ORNAMENT_KIT, ARMADYL_GODSWORD_OR), + ITEM_BANDOS_GODSWORD(BANDOS_GODSWORD, BANDOS_GODSWORD_OR), + ITEM_BANDOS_GODSWORD_ORNAMENT_KIT(BANDOS_GODSWORD_ORNAMENT_KIT, BANDOS_GODSWORD_OR), + ITEM_ZAMORAK_GODSWORD(ZAMORAK_GODSWORD, ZAMORAK_GODSWORD_OR), + ITEM_ZAMORAK_GODSWORD_ORNAMENT_KIT(ZAMORAK_GODSWORD_ORNAMENT_KIT, ZAMORAK_GODSWORD_OR), + ITEM_SARADOMIN_GODSWORD(SARADOMIN_GODSWORD, SARADOMIN_GODSWORD_OR), + ITEM_SARADOMIN_GODSWORD_ORNAMENT_KIT(SARADOMIN_GODSWORD_ORNAMENT_KIT, SARADOMIN_GODSWORD_OR), + + // Jewellery ornament kits + ITEM_AMULET_OF_TORTURE(AMULET_OF_TORTURE, AMULET_OF_TORTURE_OR), + ITEM_TORTURE_ORNAMENT_KIT(TORTURE_ORNAMENT_KIT, AMULET_OF_TORTURE_OR), + ITEM_NECKLACE_OF_ANGUISH(NECKLACE_OF_ANGUISH, NECKLACE_OF_ANGUISH_OR), + ITEM_ANGUISH_ORNAMENT_KIT(ANGUISH_ORNAMENT_KIT, NECKLACE_OF_ANGUISH_OR), + ITEM_OCCULT_NECKLACE(OCCULT_NECKLACE, OCCULT_NECKLACE_OR), + ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR), + ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), + ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), + + // Ensouled heads + ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD), + ITEM_ENSOULED_MONKEY_HEAD(ENSOULED_MONKEY_HEAD_13451, ENSOULED_MONKEY_HEAD), + ITEM_ENSOULED_IMP_HEAD(ENSOULED_IMP_HEAD_13454, ENSOULED_IMP_HEAD), + ITEM_ENSOULED_MINOTAUR_HEAD(ENSOULED_MINOTAUR_HEAD_13457, ENSOULED_MINOTAUR_HEAD), + ITEM_ENSOULED_SCORPION_HEAD(ENSOULED_SCORPION_HEAD_13460, ENSOULED_SCORPION_HEAD), + ITEM_ENSOULED_BEAR_HEAD(ENSOULED_BEAR_HEAD_13463, ENSOULED_BEAR_HEAD), + ITEM_ENSOULED_UNICORN_HEAD(ENSOULED_UNICORN_HEAD_13466, ENSOULED_UNICORN_HEAD), + ITEM_ENSOULED_DOG_HEAD(ENSOULED_DOG_HEAD_13469, ENSOULED_DOG_HEAD), + ITEM_ENSOULED_CHAOS_DRUID_HEAD(ENSOULED_CHAOS_DRUID_HEAD_13472, ENSOULED_CHAOS_DRUID_HEAD), + ITEM_ENSOULED_GIANT_HEAD(ENSOULED_GIANT_HEAD_13475, ENSOULED_GIANT_HEAD), + ITEM_ENSOULED_OGRE_HEAD(ENSOULED_OGRE_HEAD_13478, ENSOULED_OGRE_HEAD), + ITEM_ENSOULED_ELF_HEAD(ENSOULED_ELF_HEAD_13481, ENSOULED_ELF_HEAD), + ITEM_ENSOULED_TROLL_HEAD(ENSOULED_TROLL_HEAD_13484, ENSOULED_TROLL_HEAD), + ITEM_ENSOULED_HORROR_HEAD(ENSOULED_HORROR_HEAD_13487, ENSOULED_HORROR_HEAD), + ITEM_ENSOULED_KALPHITE_HEAD(ENSOULED_KALPHITE_HEAD_13490, ENSOULED_KALPHITE_HEAD), + ITEM_ENSOULED_DAGANNOTH_HEAD(ENSOULED_DAGANNOTH_HEAD_13493, ENSOULED_DAGANNOTH_HEAD), + ITEM_ENSOULED_BLOODVELD_HEAD(ENSOULED_BLOODVELD_HEAD_13496, ENSOULED_BLOODVELD_HEAD), + ITEM_ENSOULED_TZHAAR_HEAD(ENSOULED_TZHAAR_HEAD_13499, ENSOULED_TZHAAR_HEAD), + ITEM_ENSOULED_DEMON_HEAD(ENSOULED_DEMON_HEAD_13502, ENSOULED_DEMON_HEAD), + ITEM_ENSOULED_AVIANSIE_HEAD(ENSOULED_AVIANSIE_HEAD_13505, ENSOULED_AVIANSIE_HEAD), + ITEM_ENSOULED_ABYSSAL_HEAD(ENSOULED_ABYSSAL_HEAD_13508, ENSOULED_ABYSSAL_HEAD), + ITEM_ENSOULED_DRAGON_HEAD(ENSOULED_DRAGON_HEAD_13511, ENSOULED_DRAGON_HEAD), + + // Imbued rings + ITEM_BERSERKER_RING(BERSERKER_RING, BERSERKER_RING_I), + ITEM_SEERS_RING(SEERS_RING, SEERS_RING_I), + ITEM_WARRIOR_RING(WARRIOR_RING, WARRIOR_RING_I), + ITEM_ARCHERS_RING(ARCHERS_RING, ARCHERS_RING_I), + ITEM_TREASONOUS_RING(TREASONOUS_RING, TREASONOUS_RING_I), + ITEM_TYRANNICAL_RING(TYRANNICAL_RING, TYRANNICAL_RING_I), + ITEM_RING_OF_THE_GODS(RING_OF_THE_GODS, RING_OF_THE_GODS_I), + ITEM_RING_OF_SUFFERING(RING_OF_SUFFERING, RING_OF_SUFFERING_I, RING_OF_SUFFERING_R, RING_OF_SUFFERING_RI), + ITEM_GRANITE_RING(GRANITE_RING, GRANITE_RING_I), + + // Bounty hunter + ITEM_GRANITE_MAUL(GRANITE_MAUL, GRANITE_MAUL_12848), + ITEM_MAGIC_SHORTBOW(MAGIC_SHORTBOW, MAGIC_SHORTBOW_I), + ITEM_SARADOMINS_BLESSED_SWORD(SARADOMINS_TEAR, SARADOMINS_BLESSED_SWORD), + + // Jewellery with charges + ITEM_RING_OF_WEALTH(RING_OF_WEALTH, RING_OF_WEALTH_I, RING_OF_WEALTH_1, RING_OF_WEALTH_I1, RING_OF_WEALTH_2, RING_OF_WEALTH_I2, RING_OF_WEALTH_3, RING_OF_WEALTH_I3, RING_OF_WEALTH_4, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5), + ITEM_AMULET_OF_GLORY(AMULET_OF_GLORY, AMULET_OF_GLORY1, AMULET_OF_GLORY2, AMULET_OF_GLORY3, AMULET_OF_GLORY5), + ITEM_AMULET_OF_GLORY_T(AMULET_OF_GLORY_T, AMULET_OF_GLORY_T1, AMULET_OF_GLORY_T2, AMULET_OF_GLORY_T3, AMULET_OF_GLORY_T5), + ITEM_SKILLS_NECKLACE(SKILLS_NECKLACE, SKILLS_NECKLACE1, SKILLS_NECKLACE2, SKILLS_NECKLACE3, SKILLS_NECKLACE5), + ITEM_RING_OF_DUELING(RING_OF_DUELING8, RING_OF_DUELING1, RING_OF_DUELING2, RING_OF_DUELING3, RING_OF_DUELING4, RING_OF_DUELING5, RING_OF_DUELING6, RING_OF_DUELING7), + ITEM_GAMES_NECKLACE(GAMES_NECKLACE8, GAMES_NECKLACE1, GAMES_NECKLACE2, GAMES_NECKLACE3, GAMES_NECKLACE4, GAMES_NECKLACE5, GAMES_NECKLACE6, GAMES_NECKLACE7), + + // Degradable/charged weaponry/armour + ITEM_ABYSSAL_WHIP(ABYSSAL_WHIP, VOLCANIC_ABYSSAL_WHIP, FROZEN_ABYSSAL_WHIP), + ITEM_KRAKEN_TENTACLE(KRAKEN_TENTACLE, ABYSSAL_TENTACLE), + ITEM_TRIDENT_OF_THE_SEAS(UNCHARGED_TRIDENT, TRIDENT_OF_THE_SEAS), + ITEM_TRIDENT_OF_THE_SEAS_E(UNCHARGED_TRIDENT_E, TRIDENT_OF_THE_SEAS_E), + ITEM_TRIDENT_OF_THE_SWAMP(UNCHARGED_TOXIC_TRIDENT, TRIDENT_OF_THE_SWAMP), + ITEM_TRIDENT_OF_THE_SWAMP_E(UNCHARGED_TOXIC_TRIDENT_E, TRIDENT_OF_THE_SWAMP_E), + ITEM_TOXIC_BLOWPIPE(TOXIC_BLOWPIPE_EMPTY, TOXIC_BLOWPIPE), + ITEM_TOXIC_STAFF_OFF_THE_DEAD(TOXIC_STAFF_UNCHARGED, TOXIC_STAFF_OF_THE_DEAD), + ITEM_SERPENTINE_HELM(SERPENTINE_HELM_UNCHARGED, SERPENTINE_HELM, TANZANITE_HELM_UNCHARGED, TANZANITE_HELM, MAGMA_HELM_UNCHARGED, MAGMA_HELM), + ITEM_DRAGONFIRE_SHIELD(DRAGONFIRE_SHIELD_11284, DRAGONFIRE_SHIELD), + ITEM_DRAGONFIRE_WARD(DRAGONFIRE_WARD_22003, DRAGONFIRE_WARD), + ITEM_ANCIENT_WYVERN_SHIELD(ANCIENT_WYVERN_SHIELD_21634, ANCIENT_WYVERN_SHIELD), + ITEM_SANGUINESTI_STAFF(SANGUINESTI_STAFF_UNCHARGED, SANGUINESTI_STAFF), + ITEM_SCYTHE_OF_VITUR(SCYTHE_OF_VITUR_UNCHARGED, SCYTHE_OF_VITUR), + ITEM_TOME_OF_FIRE(TOME_OF_FIRE_EMPTY, TOME_OF_FIRE), + ITEM_CRAWS_BOW(CRAWS_BOW_U, CRAWS_BOW), + ITEM_VIGGORAS_CHAINMACE(VIGGORAS_CHAINMACE_U, VIGGORAS_CHAINMACE), + ITEM_THAMMARONS_SCEPTRE(THAMMARONS_SCEPTRE_U, THAMMARONS_SCEPTRE), + + // Infinity colour kits + ITEM_INFINITY_TOP(INFINITY_TOP, INFINITY_TOP_10605, INFINITY_TOP_20574, DARK_INFINITY_TOP, LIGHT_INFINITY_TOP), + ITEM_INFINITY_TOP_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_TOP), + ITEM_INFINITY_TOP_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_TOP), + ITEM_INFINITY_BOTTOMS(INFINITY_BOTTOMS, INFINITY_BOTTOMS_20575, DARK_INFINITY_BOTTOMS, LIGHT_INFINITY_BOTTOMS), + ITEM_INFINITY_BOTTOMS_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_BOTTOMS), + ITEM_INFINITY_BOTTOMS_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_BOTTOMS), + ITEM_INFINITY_HAT(INFINITY_HAT, DARK_INFINITY_HAT, LIGHT_INFINITY_HAT), + ITEM_INFINITY_HAT_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_HAT), + ITEM_INFINITY_HAT_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_HAT), + + // Miscellaneous ornament kits + ITEM_DARK_BOW(DARK_BOW, DARK_BOW_12765, DARK_BOW_12766, DARK_BOW_12767, DARK_BOW_12768, DARK_BOW_20408), + ITEM_ODIUM_WARD(ODIUM_WARD, ODIUM_WARD_12807), + ITEM_MALEDICTION_WARD(MALEDICTION_WARD, MALEDICTION_WARD_12806), + ITEM_STEAM_BATTLESTAFF(STEAM_BATTLESTAFF, STEAM_BATTLESTAFF_12795), + ITEM_LAVA_BATTLESTAFF(LAVA_BATTLESTAFF, LAVA_BATTLESTAFF_21198), + + // Slayer helm/black mask + ITEM_BLACK_MASK( + BLACK_MASK, BLACK_MASK_I, BLACK_MASK_1, BLACK_MASK_1_I, BLACK_MASK_2, BLACK_MASK_2_I, BLACK_MASK_3, BLACK_MASK_3_I, BLACK_MASK_4, BLACK_MASK_4_I, BLACK_MASK_5, + BLACK_MASK_5_I, BLACK_MASK_6, BLACK_MASK_6_I, BLACK_MASK_7, BLACK_MASK_7_I, BLACK_MASK_8, BLACK_MASK_8_I, BLACK_MASK_9, BLACK_MASK_9_I, BLACK_MASK_10_I, + SLAYER_HELMET, SLAYER_HELMET_I, BLACK_SLAYER_HELMET, BLACK_SLAYER_HELMET_I, PURPLE_SLAYER_HELMET, PURPLE_SLAYER_HELMET_I, RED_SLAYER_HELMET, RED_SLAYER_HELMET_I, + GREEN_SLAYER_HELMET, GREEN_SLAYER_HELMET_I, TURQUOISE_SLAYER_HELMET, TURQUOISE_SLAYER_HELMET_I, HYDRA_SLAYER_HELMET, HYDRA_SLAYER_HELMET_I), + + // Pharaoh's Sceptres + ITEM_PHARAOHS_SCEPTRE_1(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_1), + ITEM_PHARAOHS_SCEPTRE_2(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_2), + ITEM_PHARAOHS_SCEPTRE_4(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_4), + ITEM_PHARAOHS_SCEPTRE_5(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_5), + ITEM_PHARAOHS_SCEPTRE_6(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_6), + ITEM_PHARAOHS_SCEPTRE_7(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_7), + ITEM_PHARAOHS_SCEPTRE_8(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_8), + + // Revertible items + ITEM_HYDRA_LEATHER(HYDRA_LEATHER, FEROCIOUS_GLOVES), + ITEM_HYDRA_TAIL(HYDRA_TAIL, BONECRUSHER_NECKLACE), + ITEM_DRAGONBONE_NECKLACE(DRAGONBONE_NECKLACE, BONECRUSHER_NECKLACE), + ITEM_BOTTOMLESS_COMPOST_BUCKET(BOTTOMLESS_COMPOST_BUCKET, BOTTOMLESS_COMPOST_BUCKET_22997); + + private static final Multimap MAPPINGS = HashMultimap.create(); + private final int tradeableItem; + private final int[] untradableItems; + + static + { + for (final ItemMapping item : values()) + { + for (int itemId : item.untradableItems) + { + MAPPINGS.put(itemId, item.tradeableItem); + } + } + } + + ItemMapping(int tradeableItem, int... untradableItems) + { + this.tradeableItem = tradeableItem; + this.untradableItems = untradableItems; + } + + /** + * Get collection of items that are mapped from single item id. + * + * @param itemId the item id + * @return the collection + */ + public static Collection map(int itemId) + { + final Collection mapping = MAPPINGS.get(itemId); + + if (mapping == null || mapping.isEmpty()) + { + return Collections.singleton(itemId); + } + + return mapping; + } + + /** + * Map an item from its untradeable version to its tradeable version + * + * @param itemId + * @return + */ + public static int mapFirst(int itemId) + { + final Collection mapping = MAPPINGS.get(itemId); + + if (mapping == null || mapping.isEmpty()) + { + return itemId; + } + + return mapping.iterator().next(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java b/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java index f34d2c13ee..36693e289f 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java @@ -1,65 +1,66 @@ -/* - * Copyright (c) 2018, Adam - * 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.game; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Type; -import java.util.Map; -import javax.annotation.Nullable; -import javax.inject.Inject; -import javax.inject.Singleton; - -@Singleton -public class NPCManager -{ - private final Map healthMap; - - @Inject - private NPCManager() - { - final Gson gson = new Gson(); - final Type typeToken = new TypeToken>() - { - }.getType(); - - final InputStream healthFile = getClass().getResourceAsStream("/npc_health.json"); - healthMap = gson.fromJson(new InputStreamReader(healthFile), typeToken); - } - - /** - * Returns health for target NPC based on it's combat level and name - * @param name npc name - * @param combatLevel npc combat level - * @return health or null if HP is unknown - */ - @Nullable - public Integer getHealth(final String name, final int combatLevel) - { - return healthMap.get(name + "_" + combatLevel); - } -} +/* + * Copyright (c) 2018, Adam + * 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.game; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.util.Map; +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class NPCManager +{ + private final Map healthMap; + + @Inject + private NPCManager() + { + final Gson gson = new Gson(); + final Type typeToken = new TypeToken>() + { + }.getType(); + + final InputStream healthFile = getClass().getResourceAsStream("/npc_health.json"); + healthMap = gson.fromJson(new InputStreamReader(healthFile), typeToken); + } + + /** + * Returns health for target NPC based on it's combat level and name + * + * @param name npc name + * @param combatLevel npc combat level + * @return health or null if HP is unknown + */ + @Nullable + public Integer getHealth(final String name, final int combatLevel) + { + return healthMap.get(name + "_" + combatLevel); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java index ff23bb2cda..0504929cfb 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java @@ -1,202 +1,202 @@ -/* - * Copyright (c) 2018 Abex - * 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.game.chatbox; - -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.Singleton; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.ScriptID; -import net.runelite.api.VarClientInt; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.vars.InputType; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.input.MouseListener; -import net.runelite.client.input.MouseManager; -import net.runelite.client.input.MouseWheelListener; - -@Singleton -@Slf4j -public class ChatboxPanelManager -{ - private final Client client; - private final ClientThread clientThread; - private final EventBus eventBus; - - private final KeyManager keyManager; - private final MouseManager mouseManager; - - private final Provider chatboxTextMenuInputProvider; - private final Provider chatboxTextInputProvider; - - @Getter - private ChatboxInput currentInput = null; - - @Inject - private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread, - KeyManager keyManager, MouseManager mouseManager, - Provider chatboxTextMenuInputProvider, Provider chatboxTextInputProvider) - { - this.client = client; - this.clientThread = clientThread; - this.eventBus = eventBus; - - this.keyManager = keyManager; - this.mouseManager = mouseManager; - - this.chatboxTextMenuInputProvider = chatboxTextMenuInputProvider; - this.chatboxTextInputProvider = chatboxTextInputProvider; - } - - public void close() - { - clientThread.invokeLater(this::unsafeCloseInput); - } - - private void unsafeCloseInput() - { - client.runScript( - ScriptID.RESET_CHATBOX_INPUT, - 0, - 1 - ); - if (currentInput != null) - { - killCurrentPanel(); - } - } - - private void unsafeOpenInput(ChatboxInput input) - { - client.runScript(ScriptID.CLEAR_CHATBOX_PANEL); - - eventBus.register(input); - if (input instanceof KeyListener) - { - keyManager.registerKeyListener((KeyListener) input); - } - if (input instanceof MouseListener) - { - mouseManager.registerMouseListener((MouseListener) input); - } - if (input instanceof MouseWheelListener) - { - mouseManager.registerMouseWheelListener((MouseWheelListener) input); - } - - if (currentInput != null) - { - killCurrentPanel(); - } - - currentInput = input; - client.setVar(VarClientInt.INPUT_TYPE, InputType.RUNELITE_CHATBOX_PANEL.getType()); - client.getWidget(WidgetInfo.CHATBOX_TITLE).setHidden(true); - client.getWidget(WidgetInfo.CHATBOX_FULL_INPUT).setHidden(true); - - Widget c = getContainerWidget(); - c.deleteAllChildren(); - c.setOnDialogAbortListener((JavaScriptCallback) ev -> this.unsafeCloseInput()); - input.open(); - } - - public void openInput(ChatboxInput input) - { - clientThread.invokeLater(() -> unsafeOpenInput(input)); - } - - public ChatboxTextMenuInput openTextMenuInput(String title) - { - return chatboxTextMenuInputProvider.get() - .title(title); - } - - public ChatboxTextInput openTextInput(String prompt) - { - return chatboxTextInputProvider.get() - .prompt(prompt); - } - - @Subscribe - public void onScriptCallbackEvent(ScriptCallbackEvent ev) - { - if (currentInput != null && "resetChatboxInput".equals(ev.getEventName())) - { - killCurrentPanel(); - } - } - - @Subscribe - private void onGameStateChanged(GameStateChanged ev) - { - if (currentInput != null && ev.getGameState() == GameState.LOGIN_SCREEN) - { - killCurrentPanel(); - } - } - - private void killCurrentPanel() - { - try - { - currentInput.close(); - } - catch (Exception e) - { - log.warn("Exception closing {}", currentInput.getClass(), e); - } - - eventBus.unregister(currentInput); - if (currentInput instanceof KeyListener) - { - keyManager.unregisterKeyListener((KeyListener) currentInput); - } - if (currentInput instanceof MouseListener) - { - mouseManager.unregisterMouseListener((MouseListener) currentInput); - } - if (currentInput instanceof MouseWheelListener) - { - mouseManager.unregisterMouseWheelListener((MouseWheelListener) currentInput); - } - currentInput = null; - } - - public Widget getContainerWidget() - { - return client.getWidget(WidgetInfo.CHATBOX_CONTAINER); - } -} +/* + * Copyright (c) 2018 Abex + * 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.game.chatbox; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.ScriptID; +import net.runelite.api.VarClientInt; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.vars.InputType; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseListener; +import net.runelite.client.input.MouseManager; +import net.runelite.client.input.MouseWheelListener; + +@Singleton +@Slf4j +public class ChatboxPanelManager +{ + private final Client client; + private final ClientThread clientThread; + private final EventBus eventBus; + + private final KeyManager keyManager; + private final MouseManager mouseManager; + + private final Provider chatboxTextMenuInputProvider; + private final Provider chatboxTextInputProvider; + + @Getter + private ChatboxInput currentInput = null; + + @Inject + private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread, + KeyManager keyManager, MouseManager mouseManager, + Provider chatboxTextMenuInputProvider, Provider chatboxTextInputProvider) + { + this.client = client; + this.clientThread = clientThread; + this.eventBus = eventBus; + + this.keyManager = keyManager; + this.mouseManager = mouseManager; + + this.chatboxTextMenuInputProvider = chatboxTextMenuInputProvider; + this.chatboxTextInputProvider = chatboxTextInputProvider; + } + + public void close() + { + clientThread.invokeLater(this::unsafeCloseInput); + } + + private void unsafeCloseInput() + { + client.runScript( + ScriptID.RESET_CHATBOX_INPUT, + 0, + 1 + ); + if (currentInput != null) + { + killCurrentPanel(); + } + } + + private void unsafeOpenInput(ChatboxInput input) + { + client.runScript(ScriptID.CLEAR_CHATBOX_PANEL); + + eventBus.register(input); + if (input instanceof KeyListener) + { + keyManager.registerKeyListener((KeyListener) input); + } + if (input instanceof MouseListener) + { + mouseManager.registerMouseListener((MouseListener) input); + } + if (input instanceof MouseWheelListener) + { + mouseManager.registerMouseWheelListener((MouseWheelListener) input); + } + + if (currentInput != null) + { + killCurrentPanel(); + } + + currentInput = input; + client.setVar(VarClientInt.INPUT_TYPE, InputType.RUNELITE_CHATBOX_PANEL.getType()); + client.getWidget(WidgetInfo.CHATBOX_TITLE).setHidden(true); + client.getWidget(WidgetInfo.CHATBOX_FULL_INPUT).setHidden(true); + + Widget c = getContainerWidget(); + c.deleteAllChildren(); + c.setOnDialogAbortListener((JavaScriptCallback) ev -> this.unsafeCloseInput()); + input.open(); + } + + public void openInput(ChatboxInput input) + { + clientThread.invokeLater(() -> unsafeOpenInput(input)); + } + + public ChatboxTextMenuInput openTextMenuInput(String title) + { + return chatboxTextMenuInputProvider.get() + .title(title); + } + + public ChatboxTextInput openTextInput(String prompt) + { + return chatboxTextInputProvider.get() + .prompt(prompt); + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent ev) + { + if (currentInput != null && "resetChatboxInput".equals(ev.getEventName())) + { + killCurrentPanel(); + } + } + + @Subscribe + private void onGameStateChanged(GameStateChanged ev) + { + if (currentInput != null && ev.getGameState() == GameState.LOGIN_SCREEN) + { + killCurrentPanel(); + } + } + + private void killCurrentPanel() + { + try + { + currentInput.close(); + } + catch (Exception e) + { + log.warn("Exception closing {}", currentInput.getClass(), e); + } + + eventBus.unregister(currentInput); + if (currentInput instanceof KeyListener) + { + keyManager.unregisterKeyListener((KeyListener) currentInput); + } + if (currentInput instanceof MouseListener) + { + mouseManager.unregisterMouseListener((MouseListener) currentInput); + } + if (currentInput instanceof MouseWheelListener) + { + mouseManager.unregisterMouseWheelListener((MouseWheelListener) currentInput); + } + currentInput = null; + } + + public Widget getContainerWidget() + { + return client.getWidget(WidgetInfo.CHATBOX_CONTAINER); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java index 51e5e7dfde..c634c0fa2b 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java @@ -1,213 +1,213 @@ -/* - * Copyright (c) 2018 Abex - * 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.game.chatbox; - -import com.google.inject.Inject; -import java.awt.event.KeyEvent; -import java.util.ArrayList; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.FontID; -import net.runelite.api.widgets.WidgetType; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetPositionMode; -import net.runelite.api.widgets.WidgetSizeMode; -import net.runelite.api.widgets.WidgetTextAlignment; -import net.runelite.client.input.KeyListener; - -@Slf4j -public class ChatboxTextMenuInput extends ChatboxInput implements KeyListener -{ - @Data - @AllArgsConstructor - private static final class Entry - { - private String text; - private Runnable callback; - } - - private final ChatboxPanelManager chatboxPanelManager; - - @Getter - private String title; - - @Getter - private List options = new ArrayList<>(); - - @Getter - private Runnable onClose; - - @Inject - protected ChatboxTextMenuInput(ChatboxPanelManager chatboxPanelManager) - { - this.chatboxPanelManager = chatboxPanelManager; - } - - public ChatboxTextMenuInput title(String title) - { - this.title = title; - return this; - } - - public ChatboxTextMenuInput option(String text, Runnable callback) - { - options.add(new Entry(text, callback)); - return this; - } - - public ChatboxTextMenuInput onClose(Runnable onClose) - { - this.onClose = onClose; - return this; - } - - public ChatboxTextMenuInput build() - { - if (title == null) - { - throw new IllegalStateException("Title must be set"); - } - - if (options.size() < 1) - { - throw new IllegalStateException("You must have atleast 1 option"); - } - - chatboxPanelManager.openInput(this); - return this; - } - - @Override - protected void open() - { - Widget container = chatboxPanelManager.getContainerWidget(); - - Widget prompt = container.createChild(-1, WidgetType.TEXT); - prompt.setText(title); - prompt.setTextColor(0x800000); - prompt.setFontId(FontID.QUILL_8); - prompt.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - prompt.setOriginalX(0); - prompt.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - prompt.setOriginalY(8); - prompt.setOriginalHeight(24); - prompt.setXTextAlignment(WidgetTextAlignment.CENTER); - prompt.setYTextAlignment(WidgetTextAlignment.CENTER); - prompt.setWidthMode(WidgetSizeMode.MINUS); - prompt.revalidate(); - - int y = prompt.getRelativeX() + prompt.getHeight() + 6; - int height = container.getHeight() - y - 8; - int step = height / options.size(); - int maxStep = options.size() >= 3 ? 25 : 30; - if (step > maxStep) - { - int ds = step - maxStep; - step = maxStep; - y += (ds * options.size()) / 2; - } - - for (Entry option : options) - { - Widget optWidget = container.createChild(-1, WidgetType.TEXT); - optWidget.setText(option.text); - optWidget.setFontId(FontID.QUILL_8); - optWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - optWidget.setOriginalX(0); - optWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - optWidget.setOriginalY(y); - optWidget.setOriginalHeight(24); - optWidget.setXTextAlignment(WidgetTextAlignment.CENTER); - optWidget.setYTextAlignment(WidgetTextAlignment.CENTER); - optWidget.setWidthMode(WidgetSizeMode.MINUS); - optWidget.setAction(0, "Continue"); - optWidget.setOnOpListener((JavaScriptCallback) ev -> callback(option)); - optWidget.setOnMouseOverListener((JavaScriptCallback) ev -> optWidget.setTextColor(0xFFFFFF)); - optWidget.setOnMouseLeaveListener((JavaScriptCallback) ev -> optWidget.setTextColor(0)); - optWidget.setHasListener(true); - optWidget.revalidate(); - - y += step; - } - } - - private void callback(Entry entry) - { - Widget container = chatboxPanelManager.getContainerWidget(); - container.setOnKeyListener((Object[]) null); - - chatboxPanelManager.close(); - - entry.callback.run(); - } - - @Override - protected void close() - { - if (onClose != null) - { - onClose.run(); - } - } - - - @Override - public void keyTyped(KeyEvent e) - { - char c = e.getKeyChar(); - - if (c == '\033') - { - chatboxPanelManager.close(); - e.consume(); - return; - } - - int n = c - '1'; - if (n >= 0 && n < options.size()) - { - callback(options.get(n)); - e.consume(); - } - } - - @Override - public void keyPressed(KeyEvent e) - { - if (e.getKeyCode() == KeyEvent.VK_ESCAPE) - { - e.consume(); - } - } - - @Override - public void keyReleased(KeyEvent e) - { - } -} +/* + * Copyright (c) 2018 Abex + * 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.game.chatbox; + +import com.google.inject.Inject; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.FontID; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.input.KeyListener; + +@Slf4j +public class ChatboxTextMenuInput extends ChatboxInput implements KeyListener +{ + @Data + @AllArgsConstructor + private static final class Entry + { + private String text; + private Runnable callback; + } + + private final ChatboxPanelManager chatboxPanelManager; + + @Getter + private String title; + + @Getter + private List options = new ArrayList<>(); + + @Getter + private Runnable onClose; + + @Inject + protected ChatboxTextMenuInput(ChatboxPanelManager chatboxPanelManager) + { + this.chatboxPanelManager = chatboxPanelManager; + } + + public ChatboxTextMenuInput title(String title) + { + this.title = title; + return this; + } + + public ChatboxTextMenuInput option(String text, Runnable callback) + { + options.add(new Entry(text, callback)); + return this; + } + + public ChatboxTextMenuInput onClose(Runnable onClose) + { + this.onClose = onClose; + return this; + } + + public ChatboxTextMenuInput build() + { + if (title == null) + { + throw new IllegalStateException("Title must be set"); + } + + if (options.size() < 1) + { + throw new IllegalStateException("You must have atleast 1 option"); + } + + chatboxPanelManager.openInput(this); + return this; + } + + @Override + protected void open() + { + Widget container = chatboxPanelManager.getContainerWidget(); + + Widget prompt = container.createChild(-1, WidgetType.TEXT); + prompt.setText(title); + prompt.setTextColor(0x800000); + prompt.setFontId(FontID.QUILL_8); + prompt.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + prompt.setOriginalX(0); + prompt.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + prompt.setOriginalY(8); + prompt.setOriginalHeight(24); + prompt.setXTextAlignment(WidgetTextAlignment.CENTER); + prompt.setYTextAlignment(WidgetTextAlignment.CENTER); + prompt.setWidthMode(WidgetSizeMode.MINUS); + prompt.revalidate(); + + int y = prompt.getRelativeX() + prompt.getHeight() + 6; + int height = container.getHeight() - y - 8; + int step = height / options.size(); + int maxStep = options.size() >= 3 ? 25 : 30; + if (step > maxStep) + { + int ds = step - maxStep; + step = maxStep; + y += (ds * options.size()) / 2; + } + + for (Entry option : options) + { + Widget optWidget = container.createChild(-1, WidgetType.TEXT); + optWidget.setText(option.text); + optWidget.setFontId(FontID.QUILL_8); + optWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + optWidget.setOriginalX(0); + optWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + optWidget.setOriginalY(y); + optWidget.setOriginalHeight(24); + optWidget.setXTextAlignment(WidgetTextAlignment.CENTER); + optWidget.setYTextAlignment(WidgetTextAlignment.CENTER); + optWidget.setWidthMode(WidgetSizeMode.MINUS); + optWidget.setAction(0, "Continue"); + optWidget.setOnOpListener((JavaScriptCallback) ev -> callback(option)); + optWidget.setOnMouseOverListener((JavaScriptCallback) ev -> optWidget.setTextColor(0xFFFFFF)); + optWidget.setOnMouseLeaveListener((JavaScriptCallback) ev -> optWidget.setTextColor(0)); + optWidget.setHasListener(true); + optWidget.revalidate(); + + y += step; + } + } + + private void callback(Entry entry) + { + Widget container = chatboxPanelManager.getContainerWidget(); + container.setOnKeyListener((Object[]) null); + + chatboxPanelManager.close(); + + entry.callback.run(); + } + + @Override + protected void close() + { + if (onClose != null) + { + onClose.run(); + } + } + + + @Override + public void keyTyped(KeyEvent e) + { + char c = e.getKeyChar(); + + if (c == '\033') + { + chatboxPanelManager.close(); + e.consume(); + return; + } + + int n = c - '1'; + if (n >= 0 && n < options.size()) + { + callback(options.get(n)); + e.consume(); + } + } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) + { + e.consume(); + } + } + + @Override + public void keyReleased(KeyEvent e) + { + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java b/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java index a1a0cb0c99..e4d80fbb64 100644 --- a/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java @@ -743,7 +743,7 @@ public class ModelOutlineRenderer * @param outerColor The color of the pixels of the outline furthest away from the model */ private void renderOutline(BufferedImage image, int outlineWidth, - Color innerColor, Color outerColor) + Color innerColor, Color outerColor) { int[] imageData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); List ps = getPriorityList(outlineWidth); @@ -887,8 +887,8 @@ public class ModelOutlineRenderer * @param outerColor The color of the pixels of the outline furthest away from the model */ private void drawModelOutline(Model model, - int localX, int localY, int localZ, int orientation, - int outlineWidth, Color innerColor, Color outerColor) + int localX, int localY, int localZ, int orientation, + int outlineWidth, Color innerColor, Color outerColor) { if (outlineWidth <= 0) { diff --git a/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java b/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java index 307551542c..1737486363 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java @@ -1,106 +1,105 @@ -/* - * Copyright (c) 2017, Robin - * 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.menus; - -import net.runelite.api.widgets.WidgetInfo; - -import java.awt.Color; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.util.ColorUtil; - -public final class WidgetMenuOption -{ - /** - * The left hand text to be displayed on the menu option. Ex. the menuOption of "Drop Bones" is "Drop" - */ - private String menuOption; - /** - * The right hand text to be displayed on the menu option Ex. the menuTarget of "Drop Bones" is "Bones" - */ - private String menuTarget; - /** - * The color that the menuTarget should be. Defaults to the brownish color that most menu options have. - */ - private Color color = JagexColors.MENU_TARGET; - - /** - * The widget to add the option to - */ - private final WidgetInfo widget; - - /** - * Creates a menu to be added to right click menus. The menu will only be added if match is found within the menu options - * - * @param menuOption Option text of this right click option - * @param menuTarget Target text of this right click option - * @param widget The widget to attach this option to - */ - public WidgetMenuOption(String menuOption, String menuTarget, WidgetInfo widget) - { - this.menuOption = menuOption; - setMenuTarget(menuTarget); - this.widget = widget; - } - - public void setMenuOption(String option) - { - menuOption = option; - } - - /** - * Sets the target of the menu option. Color code will be added on to target - * - * @param target The target text without color code. - */ - public void setMenuTarget(String target) - { - menuTarget = ColorUtil.wrapWithColorTag(target, color); - } - - public String getMenuOption() - { - return menuOption; - } - - public String getMenuTarget() - { - return menuTarget; - } - - public WidgetInfo getWidget() - { - return widget; - } - - public Color getColor() - { - return color; - } - - public void setColor(Color col) - { - color = col; - } -} +/* + * Copyright (c) 2017, Robin + * 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.menus; + +import java.awt.Color; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.util.ColorUtil; + +public final class WidgetMenuOption +{ + /** + * The left hand text to be displayed on the menu option. Ex. the menuOption of "Drop Bones" is "Drop" + */ + private String menuOption; + /** + * The right hand text to be displayed on the menu option Ex. the menuTarget of "Drop Bones" is "Bones" + */ + private String menuTarget; + /** + * The color that the menuTarget should be. Defaults to the brownish color that most menu options have. + */ + private Color color = JagexColors.MENU_TARGET; + + /** + * The widget to add the option to + */ + private final WidgetInfo widget; + + /** + * Creates a menu to be added to right click menus. The menu will only be added if match is found within the menu options + * + * @param menuOption Option text of this right click option + * @param menuTarget Target text of this right click option + * @param widget The widget to attach this option to + */ + public WidgetMenuOption(String menuOption, String menuTarget, WidgetInfo widget) + { + this.menuOption = menuOption; + setMenuTarget(menuTarget); + this.widget = widget; + } + + public void setMenuOption(String option) + { + menuOption = option; + } + + /** + * Sets the target of the menu option. Color code will be added on to target + * + * @param target The target text without color code. + */ + public void setMenuTarget(String target) + { + menuTarget = ColorUtil.wrapWithColorTag(target, color); + } + + public String getMenuOption() + { + return menuOption; + } + + public String getMenuTarget() + { + return menuTarget; + } + + public WidgetInfo getWidget() + { + return widget; + } + + public Color getColor() + { + return color; + } + + public void setColor(Color col) + { + color = col; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java index c3a8a0876b..0bbac48f60 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java @@ -59,11 +59,11 @@ public class BlackjackPlugin extends Plugin @Inject Client client; - private static long timeSinceKnockout; - private static long timeSinceAggro; + private long timeSinceKnockout; + private long timeSinceAggro; @Getter - private static long currentGameTick; + private long currentGameTick; @Override public void configure(Binder binder) @@ -109,7 +109,7 @@ public class BlackjackPlugin extends Plugin public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) { String target = menuEntryAdded.getTarget().toLowerCase(); - if ((target.contains("bandit") | target.contains("menaphite thug"))) + if ((target.contains("bandit") || target.contains("menaphite thug"))) { Quest quest = Quest.THE_FEUD; if (quest.getState(client) == QuestState.FINISHED) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java index 3e811a60d2..95bc61fbb8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java @@ -99,7 +99,7 @@ class CombatLevelOverlay extends Overlay int prayerLevel = client.getRealSkillLevel(Skill.PRAYER); // calculate initial required numbers - double base = DEF_HP_MULT * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2)); + double base = DEF_HP_MULT * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2D)); double melee = ATT_STR_MULT * (attackLevel + strengthLevel); double range = RANGE_MAGIC_MULT * Math.floor(rangedLevel * RANGE_MAGIC_LEVEL_MULT); double mage = RANGE_MAGIC_MULT * Math.floor(magicLevel * RANGE_MAGIC_LEVEL_MULT); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java index 9481a9f1f6..c52d85a575 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java @@ -123,7 +123,7 @@ public class PluginListItem extends JPanel * if there is no configuration associated with the plugin. */ PluginListItem(ConfigPanel configPanel, ConfigManager configManager, Plugin plugin, PluginDescriptor descriptor, - @Nullable Config config, @Nullable ConfigDescriptor configDescriptor) + @Nullable Config config, @Nullable ConfigDescriptor configDescriptor) { this(configPanel, configManager, plugin, config, configDescriptor, descriptor.name(), descriptor.description(), descriptor.tags()); @@ -133,13 +133,13 @@ public class PluginListItem extends JPanel * Creates a new {@code PluginListItem} for a core configuration. */ PluginListItem(ConfigPanel configPanel, ConfigManager configManager, Config config, ConfigDescriptor configDescriptor, - String name, String description, String... tags) + String name, String description, String... tags) { this(configPanel, configManager, null, config, configDescriptor, name, description, tags); } private PluginListItem(ConfigPanel configPanel, ConfigManager configManager, @Nullable Plugin plugin, @Nullable Config config, - @Nullable ConfigDescriptor configDescriptor, String name, String description, String... tags) + @Nullable ConfigDescriptor configDescriptor, String name, String description, String... tags) { this.configPanel = configPanel; this.configManager = configManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java index e0bc04dfad..c9424703d7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java @@ -156,7 +156,7 @@ public class DemonicGorillaPlugin extends Plugin } private void checkGorillaAttackStyleSwitch(DemonicGorilla gorilla, - final DemonicGorilla.AttackStyle... protectedStyles) + final DemonicGorilla.AttackStyle... protectedStyles) { if (gorilla.getAttacksUntilSwitch() <= 0 || gorilla.getNextPosibleAttackStyles().isEmpty()) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 6ad12ca97a..35e942382c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -357,11 +357,11 @@ public class EasyscapePlugin extends Plugin } } - if (config.getGlory()) - { - if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) - { - switch (config.getGloryMode()) + if (config.getGlory()) + { + if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) + { + switch (config.getGloryMode()) { case EDGEVILLE: swap(client, GloryMode.EDGEVILLE.toString(), option, target); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java index 13228de07b..dacc526a19 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java @@ -66,10 +66,7 @@ public class PrayerTracker } if (actor instanceof Player) { - if (actor instanceof Player) - { - newTick.get(actor).put("PrayerIcon", ((Player) actor).getOverheadIcon() == null ? -1 : ((Player) actor).getOverheadIcon().ordinal()); - } + newTick.get(actor).put("PrayerIcon", ((Player) actor).getOverheadIcon() == null ? -1 : ((Player) actor).getOverheadIcon().ordinal()); } newTick.get(actor).put("SpotAnim", actor.getGraphic()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java index 896363e681..ea0f90d53a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java @@ -53,7 +53,7 @@ import org.apache.commons.lang3.ArrayUtils; ) public class FriendTaggingPlugin extends Plugin { - public static ConcurrentHashMap taggedFriends = new ConcurrentHashMap<>(); + public static final ConcurrentHashMap taggedFriends = new ConcurrentHashMap<>(); private static final String CONFIG_GROUP = "friendtagging"; private static final int CHARACTER_LIMIT = 30; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index 449f1b5441..f16275a13f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -718,8 +718,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } public void drawScenePaint(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, - SceneTilePaint paint, int tileZ, int tileX, int tileY, - int zoom, int centerX, int centerY) + SceneTilePaint paint, int tileZ, int tileX, int tileY, + int zoom, int centerX, int centerY) { if (paint.getBufferLen() > 0) { @@ -744,8 +744,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } public void drawSceneModel(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, - SceneTileModel model, int tileZ, int tileX, int tileY, - int zoom, int centerX, int centerY) + SceneTileModel model, int tileZ, int tileX, int tileY, + int zoom, int centerX, int centerY) { if (model.getBufferLen() > 0) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java index c25ecf6771..df475162d7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java @@ -214,7 +214,7 @@ class InstanceMapOverlay extends Overlay * @param graphics graphics to be drawn to */ private void drawPlayerDot(Graphics2D graphics, Player player, - Color dotColor, Color outlineColor) + Color dotColor, Color outlineColor) { LocalPoint playerLoc = player.getLocalLocation(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java index 2db6e0de45..c2f1db70b8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java @@ -1,130 +1,130 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.inventorysetups.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.util.ArrayList; -import javax.swing.JLabel; -import javax.swing.JPanel; -import net.runelite.client.game.AsyncBufferedImage; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemVariationMapping; -import net.runelite.client.plugins.inventorysetups.InventorySetupConfig; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.ColorScheme; - -public abstract class InventorySetupContainerPanel extends JPanel -{ - protected ItemManager itemManager; - - private final InventorySetupPlugin plugin; - - InventorySetupContainerPanel(final ItemManager itemManager, final InventorySetupPlugin plugin, String captionText) - { - this.itemManager = itemManager; - this.plugin = plugin; - JPanel containerPanel = new JPanel(); - - final JPanel containerSlotsPanel = new JPanel(); - - setupContainerPanel(containerSlotsPanel); - - // caption - final JLabel caption = new JLabel(captionText); - caption.setHorizontalAlignment(JLabel.CENTER); - caption.setVerticalAlignment(JLabel.CENTER); - - // panel that holds the caption and any other graphics - final JPanel captionPanel = new JPanel(); - captionPanel.add(caption); - - containerPanel.setLayout(new BorderLayout()); - containerPanel.add(captionPanel, BorderLayout.NORTH); - containerPanel.add(containerSlotsPanel, BorderLayout.CENTER); - - add(containerPanel); - } - - void setContainerSlot(int index, - final InventorySetupSlot containerSlot, - final ArrayList items) - { - if (index >= items.size() || items.get(index).getId() == -1) - { - containerSlot.setImageLabel(null, null); - return; - } - - int itemId = items.get(index).getId(); - int quantity = items.get(index).getQuantity(); - final String itemName = items.get(index).getName(); - AsyncBufferedImage itemImg = itemManager.getImage(itemId, quantity, quantity > 1); - String toolTip = itemName; - if (quantity > 1) - { - toolTip += " (" + quantity + ")"; - } - containerSlot.setImageLabel(toolTip, itemImg); - } - - void highlightDifferentSlotColor(InventorySetupItem savedItem, - InventorySetupItem currItem, - final InventorySetupSlot containerSlot) - { - // important note: do not use item names for comparisons - // they are all empty to avoid clientThread usage when highlighting - - final InventorySetupConfig config = plugin.getConfig(); - final Color highlightColor = config.getHighlightColor(); - - if (config.getStackDifference() && currItem.getQuantity() != savedItem.getQuantity()) - { - containerSlot.setBackground(highlightColor); - return; - } - - int currId = currItem.getId(); - int checkId = savedItem.getId(); - - if (!config.getVariationDifference()) - { - currId = ItemVariationMapping.map(currId); - checkId = ItemVariationMapping.map(checkId); - } - - if (currId != checkId) - { - containerSlot.setBackground(highlightColor); - return; - } - - // set the color back to the original, because they match - containerSlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); - } - - abstract public void setupContainerPanel(final JPanel containerSlotsPanel); +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.inventorysetups.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.util.ArrayList; +import javax.swing.JLabel; +import javax.swing.JPanel; +import net.runelite.client.game.AsyncBufferedImage; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemVariationMapping; +import net.runelite.client.plugins.inventorysetups.InventorySetupConfig; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.ColorScheme; + +public abstract class InventorySetupContainerPanel extends JPanel +{ + protected ItemManager itemManager; + + private final InventorySetupPlugin plugin; + + InventorySetupContainerPanel(final ItemManager itemManager, final InventorySetupPlugin plugin, String captionText) + { + this.itemManager = itemManager; + this.plugin = plugin; + JPanel containerPanel = new JPanel(); + + final JPanel containerSlotsPanel = new JPanel(); + + setupContainerPanel(containerSlotsPanel); + + // caption + final JLabel caption = new JLabel(captionText); + caption.setHorizontalAlignment(JLabel.CENTER); + caption.setVerticalAlignment(JLabel.CENTER); + + // panel that holds the caption and any other graphics + final JPanel captionPanel = new JPanel(); + captionPanel.add(caption); + + containerPanel.setLayout(new BorderLayout()); + containerPanel.add(captionPanel, BorderLayout.NORTH); + containerPanel.add(containerSlotsPanel, BorderLayout.CENTER); + + add(containerPanel); + } + + void setContainerSlot(int index, + final InventorySetupSlot containerSlot, + final ArrayList items) + { + if (index >= items.size() || items.get(index).getId() == -1) + { + containerSlot.setImageLabel(null, null); + return; + } + + int itemId = items.get(index).getId(); + int quantity = items.get(index).getQuantity(); + final String itemName = items.get(index).getName(); + AsyncBufferedImage itemImg = itemManager.getImage(itemId, quantity, quantity > 1); + String toolTip = itemName; + if (quantity > 1) + { + toolTip += " (" + quantity + ")"; + } + containerSlot.setImageLabel(toolTip, itemImg); + } + + void highlightDifferentSlotColor(InventorySetupItem savedItem, + InventorySetupItem currItem, + final InventorySetupSlot containerSlot) + { + // important note: do not use item names for comparisons + // they are all empty to avoid clientThread usage when highlighting + + final InventorySetupConfig config = plugin.getConfig(); + final Color highlightColor = config.getHighlightColor(); + + if (config.getStackDifference() && currItem.getQuantity() != savedItem.getQuantity()) + { + containerSlot.setBackground(highlightColor); + return; + } + + int currId = currItem.getId(); + int checkId = savedItem.getId(); + + if (!config.getVariationDifference()) + { + currId = ItemVariationMapping.map(currId); + checkId = ItemVariationMapping.map(checkId); + } + + if (currId != checkId) + { + containerSlot.setBackground(highlightColor); + return; + } + + // set the color back to the original, because they match + containerSlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); + } + + abstract public void setupContainerPanel(final JPanel containerSlotsPanel); } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java index d81a29ece8..67f2504c32 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java @@ -1,307 +1,307 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.inventorysetups.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.event.ItemEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.border.EmptyBorder; -import net.runelite.api.InventoryID; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.inventorysetups.InventorySetup; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.ui.components.PluginErrorPanel; -import net.runelite.client.util.ImageUtil; - -public class InventorySetupPluginPanel extends PluginPanel -{ - private static ImageIcon ADD_ICON; - private static ImageIcon ADD_HOVER_ICON; - private static ImageIcon REMOVE_ICON; - private static ImageIcon REMOVE_HOVER_ICON; - - private final JPanel noSetupsPanel; - private final JPanel invEqPanel; - - private final InventorySetupInventoryPanel invPanel; - private final InventorySetupEquipmentPanel eqpPanel; - - private final JComboBox setupComboBox; - - private final JLabel removeMarker; - - private final InventorySetupPlugin plugin; - - static - { - final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "add_icon.png"); - ADD_ICON = new ImageIcon(addIcon); - ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); - - final BufferedImage removeIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "remove_icon.png"); - REMOVE_ICON = new ImageIcon(removeIcon); - REMOVE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(removeIcon, 0.53f)); - } - - public InventorySetupPluginPanel(final InventorySetupPlugin plugin, final ItemManager itemManager) - { - super(false); - this.plugin = plugin; - this.removeMarker = new JLabel(REMOVE_ICON); - this.invPanel = new InventorySetupInventoryPanel(itemManager, plugin); - this.eqpPanel = new InventorySetupEquipmentPanel(itemManager, plugin); - this.noSetupsPanel = new JPanel(); - this.invEqPanel = new JPanel(); - this.setupComboBox = new JComboBox<>(); - - // setup the title - final JLabel addMarker = new JLabel(ADD_ICON); - final JLabel title = new JLabel(); - title.setText("Inventory Setups"); - title.setForeground(Color.WHITE); - - // setup the add marker (+ sign in the top right) - addMarker.setToolTipText("Add a new inventory setup"); - addMarker.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - plugin.addInventorySetup(); - } - - @Override - public void mouseEntered(MouseEvent e) - { - addMarker.setIcon(ADD_HOVER_ICON); - } - - @Override - public void mouseExited(MouseEvent e) - { - addMarker.setIcon(ADD_ICON); - } - }); - - // setup the remove marker (X sign in the top right) - removeMarker.setToolTipText("Remove the current inventory setup"); - removeMarker.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - final String name = (String) setupComboBox.getSelectedItem(); - plugin.removeInventorySetup(name, true); - } - - @Override - public void mouseEntered(MouseEvent e) - { - if (removeMarker.isEnabled()) - { - removeMarker.setIcon(REMOVE_HOVER_ICON); - } - } - - @Override - public void mouseExited(MouseEvent e) - { - removeMarker.setIcon(REMOVE_ICON); - } - }); - - // setup the combo box for selection switching - // add empty to indicate the empty position - setupComboBox.addItem(""); - setupComboBox.setSelectedIndex(0); - setupComboBox.addItemListener(e -> - { - if (e.getStateChange() == ItemEvent.SELECTED) - { - String selection = (String) e.getItem(); - setCurrentInventorySetup(selection); - } - }); - - // the panel on the top right that holds the add and delete buttons - final JPanel markersPanel = new JPanel(); - markersPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 0)); - markersPanel.add(removeMarker); - markersPanel.add(addMarker); - - // the top panel that has the title and the buttons - final JPanel titleAndMarkersPanel = new JPanel(); - titleAndMarkersPanel.setLayout(new BorderLayout()); - titleAndMarkersPanel.add(title, BorderLayout.WEST); - titleAndMarkersPanel.add(markersPanel, BorderLayout.EAST); - - // the panel that stays at the top and doesn't scroll - // contains the title, buttons, and the combo box - final JPanel northAnchoredPanel = new JPanel(); - northAnchoredPanel.setLayout(new BoxLayout(northAnchoredPanel, BoxLayout.Y_AXIS)); - northAnchoredPanel.setBorder(new EmptyBorder(0, 0, 10, 0)); - northAnchoredPanel.add(titleAndMarkersPanel); - northAnchoredPanel.add(Box.createRigidArea(new Dimension(0, 10))); - northAnchoredPanel.add(setupComboBox); - - // the panel that holds the inventory and equipment panels - final BoxLayout invEqLayout = new BoxLayout(invEqPanel, BoxLayout.Y_AXIS); - invEqPanel.setLayout(invEqLayout); - invEqPanel.add(invPanel); - invEqPanel.add(Box.createRigidArea(new Dimension(0, 10))); - invEqPanel.add(eqpPanel); - - // setup the error panel. It's wrapped around a normal panel - // so it doesn't stretch to fill the parent panel - final PluginErrorPanel errorPanel = new PluginErrorPanel(); - errorPanel.setContent("Inventory Setups", "Select or create an inventory setup."); - noSetupsPanel.add(errorPanel); - - // the panel that holds the inventory panels, and the error panel - final JPanel contentPanel = new JPanel(); - final BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS); - contentPanel.setLayout(contentLayout); - contentPanel.add(invEqPanel); - contentPanel.add(noSetupsPanel); - - // wrapper for the main content panel to keep it from stretching - final JPanel contentWrapper = new JPanel(new BorderLayout()); - contentWrapper.add(Box.createGlue(), BorderLayout.CENTER); - contentWrapper.add(contentPanel, BorderLayout.NORTH); - final JScrollPane contentWrapperPane = new JScrollPane(contentWrapper); - contentWrapperPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(10, 10, 10, 10)); - add(northAnchoredPanel, BorderLayout.NORTH); - add(contentWrapperPane, BorderLayout.CENTER); - - // show the no setups panel on startup - showNoSetupsPanel(); - - } - - public void showNoSetupsPanel() - { - setupComboBox.setSelectedIndex(0); - removeMarker.setEnabled(false); - noSetupsPanel.setVisible(true); - invEqPanel.setVisible(false); - } - - private void showHasSetupPanel(final String name) - { - setupComboBox.setSelectedItem(name); - removeMarker.setEnabled(true); - noSetupsPanel.setVisible(false); - invEqPanel.setVisible(true); - } - - public void setCurrentInventorySetup(final String name) - { - if (name.isEmpty()) - { - showNoSetupsPanel(); - return; - } - - showHasSetupPanel(name); - - final InventorySetup inventorySetup = plugin.getInventorySetup(name); - - invPanel.setInventorySetupSlots(inventorySetup); - eqpPanel.setEquipmentSetupSlots(inventorySetup); - - if (plugin.getHighlightDifference()) - { - final ArrayList normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY); - final ArrayList normEqp = plugin.getNormalizedContainer(InventoryID.EQUIPMENT); - - highlightDifferences(normInv, inventorySetup, InventoryID.INVENTORY); - highlightDifferences(normEqp, inventorySetup, InventoryID.EQUIPMENT); - } - else - { - invPanel.resetInventorySlotsColor(); - eqpPanel.resetEquipmentSlotsColor(); - } - - validate(); - repaint(); - } - - public void addInventorySetup(final String name) - { - setupComboBox.addItem(name); - } - - public void removeInventorySetup(final String name) - { - setupComboBox.removeItem(name); - showNoSetupsPanel(); - - invPanel.resetInventorySlotsColor(); - eqpPanel.resetEquipmentSlotsColor(); - - validate(); - repaint(); - } - - public void highlightDifferences(final ArrayList container, - final InventorySetup setupToCheck, - final InventoryID type) - { - switch (type) - { - case INVENTORY: - invPanel.highlightDifferentSlots(container, setupToCheck); - break; - - case EQUIPMENT: - eqpPanel.highlightDifferences(container, setupToCheck); - break; - } - } - - public final String getSelectedInventorySetup() - { - return (String) setupComboBox.getSelectedItem(); - } +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.inventorysetups.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ItemEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.border.EmptyBorder; +import net.runelite.api.InventoryID; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.inventorysetups.InventorySetup; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.PluginErrorPanel; +import net.runelite.client.util.ImageUtil; + +public class InventorySetupPluginPanel extends PluginPanel +{ + private static ImageIcon ADD_ICON; + private static ImageIcon ADD_HOVER_ICON; + private static ImageIcon REMOVE_ICON; + private static ImageIcon REMOVE_HOVER_ICON; + + private final JPanel noSetupsPanel; + private final JPanel invEqPanel; + + private final InventorySetupInventoryPanel invPanel; + private final InventorySetupEquipmentPanel eqpPanel; + + private final JComboBox setupComboBox; + + private final JLabel removeMarker; + + private final InventorySetupPlugin plugin; + + static + { + final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "add_icon.png"); + ADD_ICON = new ImageIcon(addIcon); + ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); + + final BufferedImage removeIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "remove_icon.png"); + REMOVE_ICON = new ImageIcon(removeIcon); + REMOVE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(removeIcon, 0.53f)); + } + + public InventorySetupPluginPanel(final InventorySetupPlugin plugin, final ItemManager itemManager) + { + super(false); + this.plugin = plugin; + this.removeMarker = new JLabel(REMOVE_ICON); + this.invPanel = new InventorySetupInventoryPanel(itemManager, plugin); + this.eqpPanel = new InventorySetupEquipmentPanel(itemManager, plugin); + this.noSetupsPanel = new JPanel(); + this.invEqPanel = new JPanel(); + this.setupComboBox = new JComboBox<>(); + + // setup the title + final JLabel addMarker = new JLabel(ADD_ICON); + final JLabel title = new JLabel(); + title.setText("Inventory Setups"); + title.setForeground(Color.WHITE); + + // setup the add marker (+ sign in the top right) + addMarker.setToolTipText("Add a new inventory setup"); + addMarker.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + plugin.addInventorySetup(); + } + + @Override + public void mouseEntered(MouseEvent e) + { + addMarker.setIcon(ADD_HOVER_ICON); + } + + @Override + public void mouseExited(MouseEvent e) + { + addMarker.setIcon(ADD_ICON); + } + }); + + // setup the remove marker (X sign in the top right) + removeMarker.setToolTipText("Remove the current inventory setup"); + removeMarker.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + final String name = (String) setupComboBox.getSelectedItem(); + plugin.removeInventorySetup(name, true); + } + + @Override + public void mouseEntered(MouseEvent e) + { + if (removeMarker.isEnabled()) + { + removeMarker.setIcon(REMOVE_HOVER_ICON); + } + } + + @Override + public void mouseExited(MouseEvent e) + { + removeMarker.setIcon(REMOVE_ICON); + } + }); + + // setup the combo box for selection switching + // add empty to indicate the empty position + setupComboBox.addItem(""); + setupComboBox.setSelectedIndex(0); + setupComboBox.addItemListener(e -> + { + if (e.getStateChange() == ItemEvent.SELECTED) + { + String selection = (String) e.getItem(); + setCurrentInventorySetup(selection); + } + }); + + // the panel on the top right that holds the add and delete buttons + final JPanel markersPanel = new JPanel(); + markersPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 0)); + markersPanel.add(removeMarker); + markersPanel.add(addMarker); + + // the top panel that has the title and the buttons + final JPanel titleAndMarkersPanel = new JPanel(); + titleAndMarkersPanel.setLayout(new BorderLayout()); + titleAndMarkersPanel.add(title, BorderLayout.WEST); + titleAndMarkersPanel.add(markersPanel, BorderLayout.EAST); + + // the panel that stays at the top and doesn't scroll + // contains the title, buttons, and the combo box + final JPanel northAnchoredPanel = new JPanel(); + northAnchoredPanel.setLayout(new BoxLayout(northAnchoredPanel, BoxLayout.Y_AXIS)); + northAnchoredPanel.setBorder(new EmptyBorder(0, 0, 10, 0)); + northAnchoredPanel.add(titleAndMarkersPanel); + northAnchoredPanel.add(Box.createRigidArea(new Dimension(0, 10))); + northAnchoredPanel.add(setupComboBox); + + // the panel that holds the inventory and equipment panels + final BoxLayout invEqLayout = new BoxLayout(invEqPanel, BoxLayout.Y_AXIS); + invEqPanel.setLayout(invEqLayout); + invEqPanel.add(invPanel); + invEqPanel.add(Box.createRigidArea(new Dimension(0, 10))); + invEqPanel.add(eqpPanel); + + // setup the error panel. It's wrapped around a normal panel + // so it doesn't stretch to fill the parent panel + final PluginErrorPanel errorPanel = new PluginErrorPanel(); + errorPanel.setContent("Inventory Setups", "Select or create an inventory setup."); + noSetupsPanel.add(errorPanel); + + // the panel that holds the inventory panels, and the error panel + final JPanel contentPanel = new JPanel(); + final BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS); + contentPanel.setLayout(contentLayout); + contentPanel.add(invEqPanel); + contentPanel.add(noSetupsPanel); + + // wrapper for the main content panel to keep it from stretching + final JPanel contentWrapper = new JPanel(new BorderLayout()); + contentWrapper.add(Box.createGlue(), BorderLayout.CENTER); + contentWrapper.add(contentPanel, BorderLayout.NORTH); + final JScrollPane contentWrapperPane = new JScrollPane(contentWrapper); + contentWrapperPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + setLayout(new BorderLayout()); + setBorder(new EmptyBorder(10, 10, 10, 10)); + add(northAnchoredPanel, BorderLayout.NORTH); + add(contentWrapperPane, BorderLayout.CENTER); + + // show the no setups panel on startup + showNoSetupsPanel(); + + } + + public void showNoSetupsPanel() + { + setupComboBox.setSelectedIndex(0); + removeMarker.setEnabled(false); + noSetupsPanel.setVisible(true); + invEqPanel.setVisible(false); + } + + private void showHasSetupPanel(final String name) + { + setupComboBox.setSelectedItem(name); + removeMarker.setEnabled(true); + noSetupsPanel.setVisible(false); + invEqPanel.setVisible(true); + } + + public void setCurrentInventorySetup(final String name) + { + if (name.isEmpty()) + { + showNoSetupsPanel(); + return; + } + + showHasSetupPanel(name); + + final InventorySetup inventorySetup = plugin.getInventorySetup(name); + + invPanel.setInventorySetupSlots(inventorySetup); + eqpPanel.setEquipmentSetupSlots(inventorySetup); + + if (plugin.getHighlightDifference()) + { + final ArrayList normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY); + final ArrayList normEqp = plugin.getNormalizedContainer(InventoryID.EQUIPMENT); + + highlightDifferences(normInv, inventorySetup, InventoryID.INVENTORY); + highlightDifferences(normEqp, inventorySetup, InventoryID.EQUIPMENT); + } + else + { + invPanel.resetInventorySlotsColor(); + eqpPanel.resetEquipmentSlotsColor(); + } + + validate(); + repaint(); + } + + public void addInventorySetup(final String name) + { + setupComboBox.addItem(name); + } + + public void removeInventorySetup(final String name) + { + setupComboBox.removeItem(name); + showNoSetupsPanel(); + + invPanel.resetInventorySlotsColor(); + eqpPanel.resetEquipmentSlotsColor(); + + validate(); + repaint(); + } + + public void highlightDifferences(final ArrayList container, + final InventorySetup setupToCheck, + final InventoryID type) + { + switch (type) + { + case INVENTORY: + invPanel.highlightDifferentSlots(container, setupToCheck); + break; + + case EQUIPMENT: + eqpPanel.highlightDifferences(container, setupToCheck); + break; + } + } + + public final String getSelectedInventorySetup() + { + return (String) setupComboBox.getSelectedItem(); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java index d38b28dccc..02a2ae844c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java @@ -214,13 +214,9 @@ public class ItemStatPlugin extends Plugin closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); closeButton.setAction(0, "Close"); closeButton.setOnMouseOverListener((JavaScriptCallback) (ev) -> - { - closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL_HOVERED); - }); + closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL_HOVERED)); closeButton.setOnMouseLeaveListener((JavaScriptCallback) (ev) -> - { - closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); - }); + closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL)); closeButton.setOnOpListener((JavaScriptCallback) (ev) -> resetGEInventory()); closeButton.setHasListener(true); closeButton.revalidate(); @@ -349,7 +345,7 @@ public class ItemStatPlugin extends Plugin } private static Widget createText(Widget parent, String text, int fontId, int textColor, - int x, int y, int width, int height) + int x, int y, int width, int height) { final Widget widget = parent.createChild(-1, WidgetType.TEXT); widget.setText(text); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java index 8d823f40e8..89956cf89c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java @@ -60,7 +60,7 @@ public class GraveyardRoom extends MTARoom @Inject private GraveyardRoom(MTAConfig config, Client client, MTAPlugin plugin, - ItemManager itemManager, InfoBoxManager infoBoxManager) + ItemManager itemManager, InfoBoxManager infoBoxManager) { super(config); this.client = client; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java index ffeccd7def..24ce90e561 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java @@ -266,9 +266,9 @@ public interface PlayerIndicatorsConfig extends Config description = "The location of the skull icon for skulled players", group = "Target Indicator" ) - default PlayerIndicatorsPlugin.minimapSkullLocations skullLocation() + default PlayerIndicatorsPlugin.MinimapSkullLocations skullLocation() { - return PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME; + return PlayerIndicatorsPlugin.MinimapSkullLocations.AFTER_NAME; } @ConfigItem( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java index 32f4b3c07b..e356d9b5f2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java @@ -97,7 +97,7 @@ public class PlayerIndicatorsMinimapOverlay extends Overlay { int width = graphics.getFontMetrics().stringWidth(name); int height = graphics.getFontMetrics().getHeight(); - if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) + if (config.skullLocation().equals(PlayerIndicatorsPlugin.MinimapSkullLocations.AFTER_NAME)) { OverlayUtil.renderImageLocation(graphics, new Point(minimapLocation.getX() + width, minimapLocation.getY() - height), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java index 6f2aff1484..9876dc9647 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java @@ -217,7 +217,7 @@ public class PlayerIndicatorsOverlay extends Overlay { int width = graphics.getFontMetrics().stringWidth(name); int height = graphics.getFontMetrics().getHeight(); - if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) + if (config.skullLocation().equals(PlayerIndicatorsPlugin.MinimapSkullLocations.AFTER_NAME)) { OverlayUtil.renderImageLocation(graphics, new Point(textLocation.getX() + width, textLocation.getY() - height), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index e1c62de125..6b3dfc3d4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -365,7 +365,7 @@ public class PlayerIndicatorsPlugin extends Plugin } } - public enum minimapSkullLocations + public enum MinimapSkullLocations { BEFORE_NAME, AFTER_NAME diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java index b76a0b9b52..e43e486112 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java @@ -100,6 +100,7 @@ public class PlayerInfoCustomIndicator extends InfoBox break; case SPECIAL: currLvl = client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT) / 1000.0F; + break; case WORLD: currLvl = 1000; // hacky } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java index 97749e048a..7f5a30a210 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java @@ -226,7 +226,7 @@ public class IDAStarMM extends IDAStar Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); swap(locBlank, locSwap); } - else if (distY <= -1) + else { Point locSwap = new Point(locBlank.getX(), locBlank.getY() - 1); swap(locBlank, locSwap); @@ -252,7 +252,7 @@ public class IDAStarMM extends IDAStar Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); swap(locBlank, locSwap); } - else if (distX <= -1) + else { Point locSwap = new Point(locBlank.getX() - 1, locBlank.getY()); swap(locBlank, locSwap); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java index 31beb64cd8..afd2464204 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java @@ -162,6 +162,7 @@ public class PyramidPlunderPlugin extends Plugin break; case LOADING: obstacles.clear(); + break; case LOGGED_IN: if (!isInRegion()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 66becd116f..772a9b1b48 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -817,7 +817,7 @@ public class RaidsPlugin extends Plugin StringBuilder builder = new StringBuilder(); if (seconds >= 3600) { - builder.append((int) Math.floor(seconds / 3600) + ";"); + builder.append((int) Math.floor(seconds / 3600)).append(";"); } seconds %= 3600; if (builder.toString().equals("")) @@ -842,7 +842,7 @@ public class RaidsPlugin extends Plugin tooltip = null; return; } - builder.append("Upper level: " + secondsToTime(upperTime)); + builder.append("Upper level: ").append(secondsToTime(upperTime)); if (middleTime == -1) { if (lowerTime == -1) @@ -852,12 +852,12 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: " + secondsToTime(lowerTime - upperTime)); + builder.append("
Lower level: ").append(secondsToTime(lowerTime - upperTime)); } } else { - builder.append("
Middle level: " + secondsToTime(middleTime - upperTime)); + builder.append("
Middle level: ").append(secondsToTime(middleTime - upperTime)); if (lowerTime == -1) { tooltip = builder.toString(); @@ -865,7 +865,7 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: " + secondsToTime(lowerTime - middleTime)); + builder.append("
Lower level: ").append(secondsToTime(lowerTime - middleTime)); } } if (raidTime == -1) @@ -873,7 +873,7 @@ public class RaidsPlugin extends Plugin tooltip = builder.toString(); return; } - builder.append("
Olm: " + secondsToTime(raidTime - lowerTime)); + builder.append("
Olm: ").append(secondsToTime(raidTime - lowerTime)); tooltip = builder.toString(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java index f709b2d435..e81bb0c95f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2018, Tim Lehner - * 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.raidsthieving.BatSolver; - -// There are three distinct Thieving rooms, distinguished by the position of the entrance relative to the exit -// e.g. If you enter the room and must turn left to get to the exit and trough, this is a LEFT_TURN - -import net.runelite.client.plugins.raidsthieving.InstancePoint; - -public enum ThievingRoomType -{ - LEFT_TURN(3271, 5389), - RIGHT_TURN(3350, 5399), - STRAIGHT(3317, 5397); - - private final int x; - private final int y; - - ThievingRoomType(int x, int y) - { - this.x = x; - this.y = y; - } - - public static ThievingRoomType IdentifyByInstancePoint(InstancePoint point) - { - for (ThievingRoomType type : ThievingRoomType.values()) - { - if (Math.abs(type.x - point.getX()) <= 1 && - Math.abs(type.y - point.getY()) <= 1) - { - return type; - } - } - - return null; - } - -} +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +// There are three distinct Thieving rooms, distinguished by the position of the entrance relative to the exit +// e.g. If you enter the room and must turn left to get to the exit and trough, this is a LEFT_TURN + +import net.runelite.client.plugins.raidsthieving.InstancePoint; + +public enum ThievingRoomType +{ + LEFT_TURN(3271, 5389), + RIGHT_TURN(3350, 5399), + STRAIGHT(3317, 5397); + + private final int x; + private final int y; + + ThievingRoomType(int x, int y) + { + this.x = x; + this.y = y; + } + + public static ThievingRoomType identifyByInstancePoint(InstancePoint point) + { + for (ThievingRoomType type : ThievingRoomType.values()) + { + if (Math.abs(type.x - point.getX()) <= 1 && + Math.abs(type.y - point.getY()) <= 1) + { + return type; + } + } + + return null; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java index 3c1b19a4e5..5776597f1f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java @@ -126,7 +126,7 @@ public class RaidsThievingPlugin extends Plugin if (obj.getId() == RaidsThievingConstants.EMPTY_TROUGH) { - ThievingRoomType type = ThievingRoomType.IdentifyByInstancePoint(absLoc); + ThievingRoomType type = ThievingRoomType.identifyByInstancePoint(absLoc); if (type != null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java index 3843370e87..764401a36e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java @@ -1,121 +1,121 @@ -/* - * Copyright (c) 2018 Abex - * 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.regenmeter; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Stroke; -import java.awt.geom.Arc2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.VarPlayer; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -public class RegenMeterOverlay extends Overlay -{ - private static final Color HITPOINTS_COLOR = brighter(0x9B0703); - private static final Color SPECIAL_COLOR = brighter(0x1E95B0); - private static final Color OVERLAY_COLOR = new Color(255, 255, 255, 60); - private static final double DIAMETER = 26D; - private static final int OFFSET = 27; - - private final Client client; - private RegenMeterPlugin plugin; - private RegenMeterConfig config; - - private static Color brighter(int color) - { - float[] hsv = new float[3]; - Color.RGBtoHSB(color >>> 16, (color >> 8) & 0xFF, color & 0xFF, hsv); - return Color.getHSBColor(hsv[0], 1.f, 1.f); - } - - @Inject - public RegenMeterOverlay(Client client, RegenMeterPlugin plugin, RegenMeterConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_WIDGETS); - this.client = client; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D g) - { - g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - - if (config.showHitpoints()) - { - renderRegen(g, WidgetInfo.MINIMAP_HEALTH_ORB, plugin.getHitpointsPercentage(), HITPOINTS_COLOR); - } - - if (config.showSpecial()) - { - if (client.getVar(VarPlayer.SPECIAL_ATTACK_ENABLED) == 1) - { - final Widget widget = client.getWidget(WidgetInfo.MINIMAP_SPEC_ORB); - - if (widget != null && !widget.isHidden()) - { - final Rectangle bounds = widget.getBounds(); - g.setColor(RegenMeterOverlay.OVERLAY_COLOR); - g.fillOval( - bounds.x + OFFSET, - bounds.y + (int) (bounds.height / 2 - (DIAMETER) / 2), - (int) DIAMETER, (int) DIAMETER); - } - } - - renderRegen(g, WidgetInfo.MINIMAP_SPEC_ORB, plugin.getSpecialPercentage(), SPECIAL_COLOR); - } - - return null; - } - - private void renderRegen(Graphics2D g, WidgetInfo widgetInfo, double percent, Color color) - { - Widget widget = client.getWidget(widgetInfo); - if (widget == null || widget.isHidden()) - { - return; - } - Rectangle bounds = widget.getBounds(); - - Arc2D.Double arc = new Arc2D.Double(bounds.x + OFFSET, bounds.y + (bounds.height / 2 - DIAMETER / 2), DIAMETER, DIAMETER, 90.d, -360.d * percent, Arc2D.OPEN); - final Stroke STROKE = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - g.setStroke(STROKE); - g.setColor(color); - g.draw(arc); - } -} +/* + * Copyright (c) 2018 Abex + * 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.regenmeter; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.geom.Arc2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.VarPlayer; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +public class RegenMeterOverlay extends Overlay +{ + private static final Color HITPOINTS_COLOR = brighter(0x9B0703); + private static final Color SPECIAL_COLOR = brighter(0x1E95B0); + private static final Color OVERLAY_COLOR = new Color(255, 255, 255, 60); + private static final double DIAMETER = 26D; + private static final int OFFSET = 27; + + private final Client client; + private RegenMeterPlugin plugin; + private RegenMeterConfig config; + + private static Color brighter(int color) + { + float[] hsv = new float[3]; + Color.RGBtoHSB(color >>> 16, (color >> 8) & 0xFF, color & 0xFF, hsv); + return Color.getHSBColor(hsv[0], 1.f, 1.f); + } + + @Inject + public RegenMeterOverlay(Client client, RegenMeterPlugin plugin, RegenMeterConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D g) + { + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + + if (config.showHitpoints()) + { + renderRegen(g, WidgetInfo.MINIMAP_HEALTH_ORB, plugin.getHitpointsPercentage(), HITPOINTS_COLOR); + } + + if (config.showSpecial()) + { + if (client.getVar(VarPlayer.SPECIAL_ATTACK_ENABLED) == 1) + { + final Widget widget = client.getWidget(WidgetInfo.MINIMAP_SPEC_ORB); + + if (widget != null && !widget.isHidden()) + { + final Rectangle bounds = widget.getBounds(); + g.setColor(RegenMeterOverlay.OVERLAY_COLOR); + g.fillOval( + bounds.x + OFFSET, + bounds.y + (int) (bounds.height / 2D - (DIAMETER) / 2D), + (int) DIAMETER, (int) DIAMETER); + } + } + + renderRegen(g, WidgetInfo.MINIMAP_SPEC_ORB, plugin.getSpecialPercentage(), SPECIAL_COLOR); + } + + return null; + } + + private void renderRegen(Graphics2D g, WidgetInfo widgetInfo, double percent, Color color) + { + Widget widget = client.getWidget(widgetInfo); + if (widget == null || widget.isHidden()) + { + return; + } + Rectangle bounds = widget.getBounds(); + + Arc2D.Double arc = new Arc2D.Double(bounds.x + OFFSET, bounds.y + (bounds.height / 2D - DIAMETER / 2D), DIAMETER, DIAMETER, 90.d, -360.d * percent, Arc2D.OPEN); + final Stroke STROKE = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); + g.setStroke(STROKE); + g.setColor(color); + g.draw(arc); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java index 55563b2fb9..4ff23ce802 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java @@ -228,11 +228,6 @@ public class RunecraftPlugin extends Plugin client.setMenuEntries(newEntries); } - private int searchIndex(MenuEntry[] entries, String option, String target) - { - return searchIndex(entries, option, target, false); - } - private int searchIndex(MenuEntry[] entries, String option, String target, boolean contains) { for (int i = entries.length - 1; i >= 0; i--) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java index 5cdb2908ce..6bcfe8a388 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java @@ -100,16 +100,16 @@ class RunedokuOverlay extends Overlay { if (!util.makeSimple(util.createTable(client)).contains(0)) { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), Color.GREEN); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(widget.getBounds()), Color.GREEN); } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), util.referenceColors(i)); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(widget.getBounds()), util.referenceColors(i)); } } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), RED); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(widget.getBounds()), RED); } } @@ -134,17 +134,17 @@ class RunedokuOverlay extends Overlay { if (!util.makeSimple(util.createTable(client)).contains(0)) { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), Color.GREEN); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(squareToHighlight.getBounds()), Color.GREEN); } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), util.sudokuPieceToColor(simpleArr.get(iteration))); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(squareToHighlight.getBounds()), util.sudokuPieceToColor(simpleArr.get(iteration))); } iteration++; } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), RED); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(squareToHighlight.getBounds()), RED); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java index 2f6baf1c6b..94cae519be 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java @@ -9,7 +9,7 @@ import net.runelite.api.Client; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetItem; -public class RunedokuUtil +class RunedokuUtil { private final RunedokuConfig config; @@ -20,7 +20,7 @@ public class RunedokuUtil this.config = config; } - protected Color sudokuPieceToColor(int i) + Color sudokuPieceToColor(int i) { switch (i) { @@ -47,7 +47,7 @@ public class RunedokuUtil } } - protected Color referenceColors(int i) + Color referenceColors(int i) { switch (i) { @@ -80,7 +80,7 @@ public class RunedokuUtil * @param board * @return */ - protected ArrayList makeSimple(int[][] board) + ArrayList makeSimple(int[][] board) { ArrayList list = new ArrayList<>(); for (int i = 0; i < 9; i++) @@ -99,7 +99,7 @@ public class RunedokuUtil * @param rect * @return */ - protected Polygon RectangleToPolygon(Rectangle rect) + public static Polygon rectangleToPolygon(Rectangle rect) { int[] xpoints = {rect.x, rect.x + rect.width, rect.x + rect.width, rect.x}; int[] ypoints = {rect.y, rect.y, rect.y + rect.height, rect.y + rect.height}; @@ -113,7 +113,7 @@ public class RunedokuUtil * @return sudoku table that the client currently sees in a 2d array * @author gazivodag */ - protected int[][] createTable(Client client) + int[][] createTable(Client client) { int[][] myArr = new int[9][9]; Widget sudokuScreen = client.getWidget(288, 131); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java index f7f0505f86..72c638588c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java @@ -52,8 +52,8 @@ import net.runelite.client.ui.ClientUI; public class RuneLitePlusPlugin extends Plugin { public static boolean customPresenceEnabled = false; - public static String rlPlusDiscordApp = "560644885250572289"; - public static String rlDiscordApp = "409416265891971072"; + public static final String rlPlusDiscordApp = "560644885250572289"; + public static final String rlDiscordApp = "409416265891971072"; @Inject public RuneLitePlusConfig config; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java index d40f7955b5..ea3fbf0712 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java @@ -301,7 +301,8 @@ public class SlayerTaskPanel extends PluginPanel if (tasks.isEmpty() || isNewAssignment) { // new task so append it to the front of the list - SwingUtilities.invokeLater(() -> { + SwingUtilities.invokeLater(() -> + { TaskBox newBox = buildBox(slayerPlugin, tasksContainer, newData); newBox.update(true, newData.isPaused(), newData); }); @@ -322,7 +323,8 @@ public class SlayerTaskPanel extends PluginPanel // so this previous task is invalid so delete it then add in the new actually // correct task - SwingUtilities.invokeLater(() -> { + SwingUtilities.invokeLater(() -> + { tasksContainer.remove(tasks.get(0)); tasks.remove(0); TaskBox newBox = buildBox(slayerPlugin, tasksContainer, newData); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java index 004c33c52f..ed6e0582d4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java @@ -58,7 +58,7 @@ public class TargetClickboxOverlay extends Overlay @Inject TargetClickboxOverlay(Client client, SlayerConfig config, SlayerPlugin plugin, - ModelOutlineRenderer modelOutlineRenderer) + ModelOutlineRenderer modelOutlineRenderer) { this.client = client; this.config = config; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java index c50d359de7..ff3b509898 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java @@ -80,7 +80,8 @@ class TaskBox extends JPanel container.setLayout(new BorderLayout()); container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - SwingUtilities.invokeLater(() -> { + SwingUtilities.invokeLater(() -> + { BufferedImage taskImg = slayerPlugin.getImageForTask(Task.getTask(taskData.getTaskName())); JLabel taskIcon = new JLabel(new ImageIcon(taskImg)); taskIcon.setHorizontalAlignment(SwingConstants.CENTER); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java index d33084be37..397392ad8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java @@ -42,7 +42,8 @@ public class TickCounterOverlay extends Overlay panelComponent.setBackgroundColor(config.bgColor()); elems.add(TitleComponent.builder().text("Combat counter").color(config.titleColor()).build()); List> list = new ArrayList<>(plugin.activity.entrySet()); - list.sort((o1, o2) -> { + list.sort((o1, o2) -> + { int value = -Integer.compare(o1.getValue(), o2.getValue()); if (value == 0) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java index 633d548750..de2154185c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java @@ -50,7 +50,7 @@ class OverviewTabPanel extends TabContentPanel private final OverviewItemPanel birdHouseOverview; OverviewTabPanel(ItemManager itemManager, TimeTrackingConfig config, TimeTrackingPanel pluginPanel, - FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) + FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) { this.config = config; this.farmingTracker = farmingTracker; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java index 54b863f4b0..0962af3acd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java @@ -64,7 +64,7 @@ class TimeTrackingPanel extends PluginPanel private TabContentPanel activeTabPanel = null; TimeTrackingPanel(ItemManager itemManager, TimeTrackingConfig config, - FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) + FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) { super(false); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java index 3d6d926126..f4e73622b0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java @@ -60,7 +60,7 @@ public class FarmingTracker @Inject private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, - TimeTrackingConfig config, FarmingWorld farmingWorld) + TimeTrackingConfig config, FarmingWorld farmingWorld) { this.client = client; this.itemManager = itemManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java index bef011cea4..f3838998f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java @@ -73,7 +73,7 @@ public class BirdHouseTracker @Inject private BirdHouseTracker(Client client, ItemManager itemManager, ConfigManager configManager, - TimeTrackingConfig config, Notifier notifier) + TimeTrackingConfig config, Notifier notifier) { this.client = client; this.itemManager = itemManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java index 0ed7fe4e0b..47c56fe3d0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java @@ -121,7 +121,7 @@ public class WhaleWatchersPlugin extends Plugin { if (config.showDamageCounter()) { - if (!(event.getActor() == client.getLocalPlayer() | + if (!(event.getActor() == client.getLocalPlayer() || event.getActor() == client.getLocalPlayer().getInteracting())) { return; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java index 37814ade62..f0085288a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java @@ -76,7 +76,7 @@ public class WikiSearchChatboxTextInput extends ChatboxTextInput @Inject public WikiSearchChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread, - ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode) + ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode) { super(chatboxPanelManager, clientThread); this.chatboxPanelManager = chatboxPanelManager; diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java index 7f0f1009f7..8c5c8a14e7 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java @@ -32,17 +32,14 @@ import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import io.sigpipe.jbsdiff.InvalidHeaderException; import io.sigpipe.jbsdiff.Patch; - import java.applet.Applet; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import java.net.URL; -import java.nio.file.Files; import java.util.HashMap; import java.util.Map; import java.util.jar.Attributes; @@ -53,13 +50,10 @@ import java.util.jar.Manifest; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; - import lombok.extern.slf4j.Slf4j; - import static net.runelite.client.rs.ClientUpdateCheckMode.AUTO; import static net.runelite.client.rs.ClientUpdateCheckMode.NONE; import static net.runelite.client.rs.ClientUpdateCheckMode.VANILLA; - import net.runelite.client.rs.mixins.MixinRunner; import net.runelite.http.api.RuneLiteAPI; import okhttp3.Request; @@ -72,41 +66,42 @@ public class ClientLoader { private final ClientConfigLoader clientConfigLoader; private ClientUpdateCheckMode updateCheckMode; + @Inject private ClientLoader( - @Named("updateCheckMode") final ClientUpdateCheckMode updateCheckMode, - final ClientConfigLoader clientConfigLoader) + @Named("updateCheckMode") final ClientUpdateCheckMode updateCheckMode, + final ClientConfigLoader clientConfigLoader) { this.updateCheckMode = updateCheckMode; this.clientConfigLoader = clientConfigLoader; } - + public Applet load() { if (updateCheckMode == NONE) { return null; } - + try { Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); RSConfig config = clientConfigLoader.fetch(); - + Map zipFile = new HashMap<>(); { String codebase = config.getCodeBase(); String initialJar = config.getInitialJar(); URL url = new URL(codebase + initialJar); Request request = new Request.Builder() - .url(url) - .build(); - + .url(url) + .build(); + try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) { JarInputStream jis; - + jis = new JarInputStream(response.body().byteStream()); byte[] tmp = new byte[4096]; ByteArrayOutputStream buffer = new ByteArrayOutputStream(756 * 1024); @@ -117,7 +112,7 @@ public class ClientLoader { break; } - + buffer.reset(); for (; ; ) { @@ -128,12 +123,12 @@ public class ClientLoader } buffer.write(tmp, 0, n); } - + zipFile.put(metadata.getName(), buffer.toByteArray()); } } } - + if (updateCheckMode == AUTO) { Map hashes; @@ -143,33 +138,33 @@ public class ClientLoader { }.getType()); } - + for (Map.Entry file : hashes.entrySet()) { byte[] bytes = zipFile.get(file.getKey()); - + String ourHash = null; if (bytes != null) { ourHash = Hashing.sha512().hashBytes(bytes).toString(); } - + if (!file.getValue().equals(ourHash)) { log.info("{} had a hash mismatch; falling back to vanilla. {} != {}", file.getKey(), - file.getValue(), ourHash); + file.getValue(), ourHash); log.info("Client is outdated!"); updateCheckMode = VANILLA; break; } } } - + if (updateCheckMode == AUTO) { ByteArrayOutputStream patchOs = new ByteArrayOutputStream(756 * 1024); int patchCount = 0; - + for (Map.Entry file : zipFile.entrySet()) { byte[] bytes; @@ -179,27 +174,27 @@ public class ClientLoader { continue; } - + bytes = ByteStreams.toByteArray(is); } - + patchOs.reset(); Patch.patch(file.getValue(), bytes, patchOs); file.setValue(patchOs.toByteArray()); - + ++patchCount; } - + log.info("Patched {} classes", patchCount); } - + log.info("Patching for RuneLitePlus"); - + if (updateCheckMode == AUTO) { - + HashMap patches = new HashMap<>(); - + for (Map.Entry file : zipFile.entrySet()) { byte[] patchClass; @@ -209,20 +204,20 @@ public class ClientLoader { continue; } - + patchClass = ByteStreams.toByteArray(is); } - + patches.put(file.getKey(), patchClass); - + } - + new MixinRunner(zipFile, patches).run(); - + } - + String initialClass = config.getInitialClass(); - + ClassLoader rsClassLoader = new ClassLoader(ClientLoader.class.getClassLoader()) { @Override @@ -234,13 +229,13 @@ public class ClientLoader { throw new ClassNotFoundException(name); } - + return defineClass(name, data, 0, data.length); } }; - + Class clientClass = rsClassLoader.loadClass(initialClass); - + Applet rs = (Applet) clientClass.newInstance(); rs.setStub(new RSAppletStub(config)); return rs; @@ -250,15 +245,15 @@ public class ClientLoader if (e instanceof ClassNotFoundException) { log.error("Unable to load client - class not found. This means you" - + " are not running RuneLite with Maven as the client patch" - + " is not in your classpath."); + + " are not running RuneLite with Maven as the client patch" + + " is not in your classpath."); } - + log.error("Error loading RS!", e); return null; } } - + private void add(byte[] bytes, String entryName, JarOutputStream target) throws IOException { BufferedInputStream in = null; diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java index e745e06190..cde7fac215 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java @@ -25,8 +25,18 @@ package net.runelite.client.rs.mixins; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; import lombok.RequiredArgsConstructor; -import net.runelite.client.rs.mixins.transformers.*; +import net.runelite.client.rs.mixins.transformers.AppendTransformer; +import net.runelite.client.rs.mixins.transformers.DoNothingTransformer; +import net.runelite.client.rs.mixins.transformers.InjectTransformer; +import net.runelite.client.rs.mixins.transformers.InterfaceTransformer; +import net.runelite.client.rs.mixins.transformers.OverwriteSanityCheck; +import net.runelite.client.rs.mixins.transformers.OverwriteTransformer; +import net.runelite.client.rs.mixins.transformers.PrependTransformer; +import net.runelite.client.rs.mixins.transformers.ProtectTransformer; +import net.runelite.client.rs.mixins.transformers.SanityChecker; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; @@ -34,18 +44,15 @@ import org.objectweb.asm.commons.ClassRemapper; import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.ClassNode; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; - @RequiredArgsConstructor public class MixinRunner { - + private final Map classes; private final Map patches; - + public Map run() - throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { runVisitor(InterfaceTransformer.class); runVisitor(OverwriteTransformer.class); @@ -55,11 +62,11 @@ public class MixinRunner // (test method: Projectile.rl$$init()V ) runVisitor(PrependTransformer.class); runRemapper(ProtectTransformer.class); - + recalcMaxes(); return classes; } - + private void runRemapper(Class clazz) throws IllegalAccessException, InstantiationException { for (Map.Entry entry : classes.entrySet()) @@ -72,19 +79,19 @@ public class MixinRunner ClassReader cr = new ClassReader(entry.getValue()); ClassWriter cw = new ClassWriter(cr, 1); cr.accept(new ClassRemapper(cw, inst), 0); - + entry.setValue(cw.toByteArray()); } } - + private void runVisitor(Class clazz) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { runVisitor(clazz, 1); } - + private void runVisitor(Class clazz, int flags) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { for (Map.Entry entry : classes.entrySet()) { @@ -98,21 +105,21 @@ public class MixinRunner ClassNode node = new ClassNode(); cr.accept(node, 0); ClassVisitor inst = clazz.getConstructor(ClassVisitor.class, byte[].class, ClassNode.class).newInstance(cw, - patch, node); + patch, node); cr.accept(inst, 0); - + entry.setValue(cw.toByteArray()); } } - + private void runSanityChecker(Class clazz) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { runSanityChecker(clazz, 1); } - + private void runSanityChecker(Class clazz, int flags) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { for (Map.Entry entry : patches.entrySet()) { @@ -124,11 +131,11 @@ public class MixinRunner cr.accept(inst, 0); } } - + private void recalcMaxes() - throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException + throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { runVisitor(DoNothingTransformer.class, 3); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java index 340c93e08b..5ee15c84c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java @@ -40,25 +40,25 @@ import org.objectweb.asm.tree.MethodNode; @Slf4j public class AppendTransformer extends ClassVisitor implements Opcodes { - + private final byte[] patch; private String className; private ClassNode classNode; - + public AppendTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.classNode = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -73,44 +73,44 @@ public class AppendTransformer extends ClassVisitor implements Opcodes { MethodNode patchMethod = (MethodNode) obj; if ((patchMethod.access == access && patchMethod.name.equals("append$" + name) && - patchMethod.desc.equals(descriptor)) && - RefUtils.checkAnnotation(patchMethod, "Append")) + patchMethod.desc.equals(descriptor)) && + RefUtils.checkAnnotation(patchMethod, "Append")) { MethodVisitor mv = - new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, - exceptions)) - { - }; + new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, + exceptions)) + { + }; mv.visitCode(); - + for (Object obj2 : classNode.methods) { MethodNode classMethod = (MethodNode) obj2; if (classMethod.access == access && classMethod.name.equals(name) && - classMethod.desc.equals(descriptor)) + classMethod.desc.equals(descriptor)) { AbstractInsnNode inode = classMethod.instructions.getLast(); - - while(inode instanceof LabelNode || inode instanceof LineNumberNode) + + while (inode instanceof LabelNode || inode instanceof LineNumberNode) { inode = inode.getPrevious(); } - - if(RefUtils.isReturn(inode.getOpcode(), true)) + + if (RefUtils.isReturn(inode.getOpcode(), true)) { log.error("[Append] Can't append to {}.{}, requires typed return opcode", className, name); return super.visitMethod(access, name, descriptor, signature, exceptions); } - + classMethod.instructions.remove(inode); - + classMethod.accept(new MethodReflector(mv)); break; } } - + patchMethod.accept(new MethodReflector(mv)); - + mv.visitEnd(); return mv; } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java index 283d6d4208..29fb2bf554 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java @@ -36,26 +36,26 @@ import org.objectweb.asm.tree.MethodNode; public class InjectTransformer extends ClassVisitor { - + private final byte[] patch; private ClassNode node; private String className; private boolean patching = false; - + public InjectTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.node = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -63,8 +63,8 @@ public class InjectTransformer extends ClassVisitor { return super.visitMethod(access, name, descriptor, signature, exceptions); } - if (name.startsWith("prepend$") || name.startsWith("append$")|| - (patching && name.startsWith("<"))) + if (name.startsWith("prepend$") || name.startsWith("append$") || + (patching && name.startsWith("<"))) { return null; } @@ -76,7 +76,7 @@ public class InjectTransformer extends ClassVisitor { MethodNode node = (MethodNode) obj; if ((node.access == access && node.name.equals(name) && node.desc.equals(descriptor)) && - RefUtils.checkAnnotation(node, "Inject")) + RefUtils.checkAnnotation(node, "Inject")) { mv.visitCode(); node.accept(new MethodReflector(mv)); @@ -85,17 +85,17 @@ public class InjectTransformer extends ClassVisitor } return mv; } - + @Override public void visitEnd() { - + if (patch == null) { super.visitEnd(); return; } - + ClassReader cr = new ClassReader(patch); ClassNode patchNode = new ClassNode(Opcodes.ASM6); cr.accept(patchNode, 0); @@ -106,10 +106,10 @@ public class InjectTransformer extends ClassVisitor if (RefUtils.checkAnnotation(node, "Inject")) { visitMethod(node.access, node.name, node.desc, node.signature, - (String[]) node.exceptions.toArray(new String[0])); + (String[]) node.exceptions.toArray(new String[0])); } } - + for (Object obj : patchNode.fields) { FieldNode node = (FieldNode) obj; @@ -121,5 +121,5 @@ public class InjectTransformer extends ClassVisitor patching = false; super.visitEnd(); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java index 633b45409b..850e3be921 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java @@ -25,42 +25,41 @@ package net.runelite.client.rs.mixins.transformers; +import java.util.ArrayList; +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; -import java.util.ArrayList; -import java.util.Arrays; - @Slf4j public class InterfaceTransformer extends ClassVisitor implements Opcodes { - + private final byte[] patch; private ClassNode node; private String className; - + public InterfaceTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.node = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; - if(patch != null) + if (patch != null) { ClassReader reader = new ClassReader(patch); ClassNode pNode = new ClassNode(); reader.accept(pNode, 0); - if(pNode.interfaces != null && pNode.interfaces.size() != 0) + if (pNode.interfaces != null && pNode.interfaces.size() != 0) { - if(interfaces == null) + if (interfaces == null) { interfaces = (String[]) pNode.interfaces.toArray(new String[0]); } @@ -74,5 +73,5 @@ public class InterfaceTransformer extends ClassVisitor implements Opcodes } super.visit(version, access, name, signature, superName, interfaces); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java index 775b791f5b..a6f6813c49 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java @@ -35,15 +35,15 @@ import org.objectweb.asm.TypePath; public class MethodReflector extends MethodVisitor { - + private MethodVisitor target; - + public MethodReflector(MethodVisitor target) { super(Opcodes.ASM6); this.target = target; } - + public void visitParameter(String var1, int var2) { if (target != null) @@ -52,27 +52,27 @@ public class MethodReflector extends MethodVisitor } super.visitParameter(var1, var2); } - + public AnnotationVisitor visitAnnotationDefault() { return super.visitAnnotationDefault(); } - + public AnnotationVisitor visitAnnotation(String var1, boolean var2) { return super.visitAnnotation(var1, var2); } - + public AnnotationVisitor visitTypeAnnotation(int var1, TypePath var2, String var3, boolean var4) { return super.visitTypeAnnotation(var1, var2, var3, var4); } - + public AnnotationVisitor visitParameterAnnotation(int var1, String var2, boolean var3) { return super.visitParameterAnnotation(var1, var2, var3); } - + public void visitAttribute(Attribute var1) { if (target != null) @@ -81,7 +81,7 @@ public class MethodReflector extends MethodVisitor } super.visitAttribute(var1); } - + public void visitFrame(int var1, int var2, Object[] var3, int var4, Object[] var5) { if (target != null) @@ -90,7 +90,7 @@ public class MethodReflector extends MethodVisitor } super.visitFrame(var1, var2, var3, var4, var5); } - + public void visitInsn(int var1) { if (target != null) @@ -99,7 +99,7 @@ public class MethodReflector extends MethodVisitor } super.visitInsn(var1); } - + public void visitIntInsn(int var1, int var2) { if (target != null) @@ -108,7 +108,7 @@ public class MethodReflector extends MethodVisitor } super.visitIntInsn(var1, var2); } - + public void visitVarInsn(int var1, int var2) { if (target != null) @@ -117,7 +117,7 @@ public class MethodReflector extends MethodVisitor } super.visitVarInsn(var1, var2); } - + public void visitTypeInsn(int var1, String var2) { if (target != null) @@ -126,7 +126,7 @@ public class MethodReflector extends MethodVisitor } super.visitTypeInsn(var1, var2); } - + public void visitFieldInsn(int var1, String var2, String var3, String var4) { if (target != null) @@ -135,7 +135,7 @@ public class MethodReflector extends MethodVisitor } super.visitFieldInsn(var1, var2, var3, var4); } - + /** * @deprecated */ @@ -147,7 +147,7 @@ public class MethodReflector extends MethodVisitor } super.visitMethodInsn(var1, var2, var3, var4); } - + public void visitMethodInsn(int var1, String var2, String var3, String var4, boolean var5) { if (target != null) @@ -156,7 +156,7 @@ public class MethodReflector extends MethodVisitor } super.visitMethodInsn(var1, var2, var3, var4, var5); } - + public void visitInvokeDynamicInsn(String var1, String var2, Handle var3, Object... var4) { if (target != null) @@ -165,7 +165,7 @@ public class MethodReflector extends MethodVisitor } super.visitInvokeDynamicInsn(var1, var2, var3, var4); } - + public void visitJumpInsn(int var1, Label var2) { if (target != null) @@ -174,7 +174,7 @@ public class MethodReflector extends MethodVisitor } super.visitJumpInsn(var1, var2); } - + public void visitLabel(Label var1) { if (target != null) @@ -183,7 +183,7 @@ public class MethodReflector extends MethodVisitor } super.visitLabel(var1); } - + public void visitLdcInsn(Object var1) { if (target != null) @@ -192,7 +192,7 @@ public class MethodReflector extends MethodVisitor } super.visitLdcInsn(var1); } - + public void visitIincInsn(int var1, int var2) { if (target != null) @@ -201,7 +201,7 @@ public class MethodReflector extends MethodVisitor } super.visitIincInsn(var1, var2); } - + public void visitTableSwitchInsn(int var1, int var2, Label var3, Label... var4) { if (target != null) @@ -210,7 +210,7 @@ public class MethodReflector extends MethodVisitor } super.visitTableSwitchInsn(var1, var2, var3, var4); } - + public void visitLookupSwitchInsn(Label var1, int[] var2, Label[] var3) { if (target != null) @@ -219,7 +219,7 @@ public class MethodReflector extends MethodVisitor } super.visitLookupSwitchInsn(var1, var2, var3); } - + public void visitMultiANewArrayInsn(String var1, int var2) { if (target != null) @@ -228,7 +228,7 @@ public class MethodReflector extends MethodVisitor } super.visitMultiANewArrayInsn(var1, var2); } - + public AnnotationVisitor visitInsnAnnotation(int var1, TypePath var2, String var3, boolean var4) { if (target != null) @@ -237,7 +237,7 @@ public class MethodReflector extends MethodVisitor } return super.visitInsnAnnotation(var1, var2, var3, var4); } - + public void visitTryCatchBlock(Label var1, Label var2, Label var3, String var4) { if (target != null) @@ -246,7 +246,7 @@ public class MethodReflector extends MethodVisitor } super.visitTryCatchBlock(var1, var2, var3, var4); } - + public AnnotationVisitor visitTryCatchAnnotation(int var1, TypePath var2, String var3, boolean var4) { if (target != null) @@ -255,7 +255,7 @@ public class MethodReflector extends MethodVisitor } return super.visitTryCatchAnnotation(var1, var2, var3, var4); } - + public void visitLocalVariable(String var1, String var2, String var3, Label var4, Label var5, int var6) { if (target != null) @@ -264,7 +264,7 @@ public class MethodReflector extends MethodVisitor } super.visitLocalVariable(var1, var2, var3, var4, var5, var6); } - + public AnnotationVisitor visitLocalVariableAnnotation(int var1, TypePath var2, Label[] var3, Label[] var4, int[] var5, String var6, boolean var7) { if (target != null) @@ -273,7 +273,7 @@ public class MethodReflector extends MethodVisitor } return super.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7); } - + public void visitLineNumber(int var1, Label var2) { if (target != null) @@ -282,7 +282,7 @@ public class MethodReflector extends MethodVisitor } super.visitLineNumber(var1, var2); } - + public void visitMaxs(int var1, int var2) { if (target != null) @@ -291,5 +291,5 @@ public class MethodReflector extends MethodVisitor } super.visitMaxs(var1, var2); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java index ff619753de..37c0ca9d65 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java @@ -25,6 +25,7 @@ package net.runelite.client.rs.mixins.transformers; +import java.util.ArrayList; import lombok.extern.slf4j.Slf4j; import net.runelite.client.util.RefUtils; import org.objectweb.asm.ClassVisitor; @@ -33,51 +34,49 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; -import java.util.ArrayList; - @Slf4j public class OverwriteSanityCheck extends SanityChecker implements Opcodes { - + private String className; private ClassNode patchNode; public static final ArrayList methodsUsed = new ArrayList<>(); - + public OverwriteSanityCheck(ClassVisitor classVisitor, ClassNode node) { super(ASM6, classVisitor); this.className = node.name; this.patchNode = node; } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { String check = String.format("%s %s %s %s", className, name, - descriptor, access); - + descriptor, access); + MethodNode methodNode = null; for (Object obj2 : patchNode.methods) { MethodNode classMethod = (MethodNode) obj2; if (classMethod.access == access && classMethod.name.equals(name) && - classMethod.desc.equals(descriptor)) + classMethod.desc.equals(descriptor)) { methodNode = classMethod; } } - - if(methodNode == null) + + if (methodNode == null) { log.error("[OverwriteSanity] Failed to find original patch method for {}", check); return super.visitMethod(access, name, descriptor, signature, exceptions); } - + if (!RefUtils.checkAnnotation(methodNode, "Overwrite")) { return super.visitMethod(access, name, descriptor, signature, exceptions); } - + if (!methodsUsed.contains(check)) { throw new RuntimeException("[OverwriteSanity] Overwrite target not found: " + check); diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java index f7c8c09bef..9decd259bd 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java @@ -37,11 +37,11 @@ import org.objectweb.asm.tree.MethodNode; @Slf4j public class OverwriteTransformer extends ClassVisitor { - + private final byte[] patch; private ClassNode node; private String className; - + public OverwriteTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); @@ -49,14 +49,14 @@ public class OverwriteTransformer extends ClassVisitor this.node = node; this.className = node.name; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -64,34 +64,34 @@ public class OverwriteTransformer extends ClassVisitor { return super.visitMethod(access, name, descriptor, signature, exceptions); } - + if (name.startsWith("prepend$") || name.startsWith("append$")) { return null; } - + ClassReader cr = new ClassReader(patch); ClassNode patchNode = new ClassNode(Opcodes.ASM6); cr.accept(patchNode, 0); - + for (Object obj : patchNode.methods) { MethodNode patchMethod = (MethodNode) obj; - + if (patchMethod.access == access && patchMethod.name.equals(name) && patchMethod.desc.equals(descriptor)) { if (RefUtils.checkAnnotation(patchMethod, "Overwrite")) { MethodVisitor mv = - new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, - exceptions)) - { - }; + new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, + exceptions)) + { + }; mv.visitCode(); patchMethod.accept(new MethodReflector(mv)); mv.visitEnd(); String s = String.format("%s %s %s %s", className, patchMethod.name, - patchMethod.desc, patchMethod.access); + patchMethod.desc, patchMethod.access); OverwriteSanityCheck.methodsUsed.add(s); return mv; } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java index 6aedbab699..e06c4703ea 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java @@ -37,25 +37,25 @@ import org.objectweb.asm.tree.MethodNode; public class PrependTransformer extends ClassVisitor { - + private final byte[] patch; private String className; private ClassNode classNode; - + public PrependTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.classNode = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -70,47 +70,47 @@ public class PrependTransformer extends ClassVisitor { MethodNode patchMethod = (MethodNode) obj; if ((patchMethod.access == access && patchMethod.name.equals("prepend$" + name) && - patchMethod.desc.equals(descriptor)) && - RefUtils.checkAnnotation(patchMethod, "Prepend")) + patchMethod.desc.equals(descriptor)) && + RefUtils.checkAnnotation(patchMethod, "Prepend")) { MethodVisitor mv = - new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, - exceptions)) - { - }; + new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, + exceptions)) + { + }; mv.visitCode(); - + AbstractInsnNode node = patchMethod.instructions.getLast(); while (!(node instanceof InsnNode)) { node = node.getPrevious(); } - + if (RefUtils.isReturn(node.getOpcode())) { patchMethod.instructions.remove(node); } - + patchMethod.accept(new MethodReflector(mv)); - + for (Object obj2 : classNode.methods) { MethodNode classMethod = (MethodNode) obj2; if (classMethod.access == access && classMethod.name.equals(name) && - classMethod.desc.equals(descriptor)) + classMethod.desc.equals(descriptor)) { classMethod.accept(new MethodReflector(mv)); break; } } - + mv.visitEnd(); return mv; } } return super.visitMethod(access, name, descriptor, signature, exceptions); } - + @Override public void visitEnd() { @@ -121,5 +121,5 @@ public class PrependTransformer extends ClassVisitor } super.visitEnd(); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java index b3c52b5783..51a96cfc14 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java @@ -29,7 +29,7 @@ import org.objectweb.asm.commons.Remapper; public class ProtectTransformer extends Remapper { - + public String mapFieldName(String owner, String name, String descriptor) { if (name.startsWith("1protect$")) @@ -38,7 +38,7 @@ public class ProtectTransformer extends Remapper } return super.mapFieldName(owner, name, descriptor); } - + public String mapMethodName(String owner, String name, String descriptor) { if (name.startsWith("1protect$")) @@ -47,5 +47,5 @@ public class ProtectTransformer extends Remapper } return super.mapMethodName(owner, name, descriptor); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java index f7a5cf1915..4581b00c59 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java @@ -34,5 +34,5 @@ public abstract class SanityChecker extends ClassVisitor implements Opcodes { super(i, classVisitor); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java index c7ccb1a3ed..01ab643939 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2016-2017, Adam - * 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.ui; - -import java.applet.Applet; -import java.awt.BorderLayout; -import java.awt.Color; -import javax.annotation.Nullable; -import javax.swing.JPanel; -import net.runelite.api.Client; -import net.runelite.api.Constants; - -final class ClientPanel extends JPanel -{ - public ClientPanel(@Nullable Applet client) - { - setSize(Constants.GAME_FIXED_SIZE); - setMinimumSize(Constants.GAME_FIXED_SIZE); - setPreferredSize(Constants.GAME_FIXED_SIZE); - setLayout(new BorderLayout()); - setBackground(Color.black); - - if (client == null) - { - return; - } - - client.setLayout(null); - client.setSize(Constants.GAME_FIXED_SIZE); - - client.init(); - client.start(); - - add(client, BorderLayout.CENTER); - - // This causes the whole game frame to be redrawn each frame instead - // of only the viewport, so we can hook to MainBufferProvider#draw - // and draw anywhere without it leaving artifacts - if (client instanceof Client) - { - ((Client)client).setGameDrawingMode(2); - } - } +/* + * Copyright (c) 2016-2017, Adam + * 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.ui; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import javax.annotation.Nullable; +import javax.swing.JPanel; +import net.runelite.api.Client; +import net.runelite.api.Constants; + +final class ClientPanel extends JPanel +{ + public ClientPanel(@Nullable Applet client) + { + setSize(Constants.GAME_FIXED_SIZE); + setMinimumSize(Constants.GAME_FIXED_SIZE); + setPreferredSize(Constants.GAME_FIXED_SIZE); + setLayout(new BorderLayout()); + setBackground(Color.black); + + if (client == null) + { + return; + } + + client.setLayout(null); + client.setSize(Constants.GAME_FIXED_SIZE); + + client.init(); + client.start(); + + add(client, BorderLayout.CENTER); + + // This causes the whole game frame to be redrawn each frame instead + // of only the viewport, so we can hook to MainBufferProvider#draw + // and draw anywhere without it leaving artifacts + if (client instanceof Client) + { + ((Client) client).setGameDrawingMode(2); + } + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index 9c73179105..8b3fc96130 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -174,8 +174,8 @@ public class ClientUI { if (!event.getGroup().equals(CONFIG_GROUP) && !(event.getGroup().equals(PLUS_CONFIG_GROUP) - && event.getKey().equals(CONFIG_OPACITY) || - event.getKey().equals(CONFIG_OPACITY_AMOUNT)) || + && event.getKey().equals(CONFIG_OPACITY) || + event.getKey().equals(CONFIG_OPACITY_AMOUNT)) || event.getKey().equals(CONFIG_CLIENT_MAXIMIZED) || event.getKey().equals(CONFIG_CLIENT_BOUNDS)) { @@ -278,7 +278,7 @@ public class ClientUI return; } - final Client client = (Client)this.client; + final Client client = (Client) this.client; final ClientThread clientThread = clientThreadProvider.get(); // Keep scheduling event until we get our name @@ -615,8 +615,9 @@ public class ClientUI /** * Changes cursor for client window. Requires ${@link ClientUI#open(RuneLite)} to be called first. * FIXME: This is working properly only on Windows, Linux and Mac are displaying cursor incorrectly + * * @param image cursor image - * @param name cursor name + * @param name cursor name */ public void setCursor(final BufferedImage image, final String name) { @@ -632,6 +633,7 @@ public class ClientUI /** * Resets client window cursor to default one. + * * @see ClientUI#setCursor(BufferedImage, String) */ public void resetCursor() @@ -666,6 +668,7 @@ public class ClientUI /** * Paint UI related overlays to target graphics + * * @param graphics target graphics */ public void paintOverlays(final Graphics2D graphics) @@ -845,7 +848,7 @@ public class ClientUI if (config.usernameInTitle() && (client instanceof Client)) { - final Player player = ((Client)client).getLocalPlayer(); + final Player player = ((Client) client).getLocalPlayer(); if (player != null && player.getName() != null) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java index 0748731c9a..32436a23a3 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java @@ -1,200 +1,202 @@ -/* - * Copyright (c) 2018, Woox - * 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.ui; - -import java.awt.Frame; -import java.awt.Rectangle; -import javax.swing.JFrame; -import lombok.Setter; -import net.runelite.client.config.ExpandResizeType; - -public class ContainableFrame extends JFrame -{ - private static final int SCREEN_EDGE_CLOSE_DISTANCE = 40; - - @Setter - private ExpandResizeType expandResizeType; - private boolean containedInScreen; - private boolean expandedClientOppositeDirection; - - public void setContainedInScreen(boolean value) - { - this.containedInScreen = value; - - if (value) - { - // Reposition the frame if it is intersecting with the bounds - this.setLocation(this.getX(), this.getY()); - this.setBounds(this.getX(), this.getY(), this.getWidth(), this.getHeight()); - } - } - - @Override - public void setLocation(int x, int y) - { - if (containedInScreen) - { - Rectangle bounds = this.getGraphicsConfiguration().getBounds(); - x = Math.max(x, (int)bounds.getX()); - x = Math.min(x, (int)(bounds.getX() + bounds.getWidth() - this.getWidth())); - y = Math.max(y, (int)bounds.getY()); - y = Math.min(y, (int)(bounds.getY() + bounds.getHeight() - this.getHeight())); - } - - super.setLocation(x, y); - } - - @Override - public void setBounds(int x, int y, int width, int height) - { - if (containedInScreen) - { - Rectangle bounds = this.getGraphicsConfiguration().getBounds(); - width = Math.min(width, width - (int)bounds.getX() + x); - x = Math.max(x, (int)bounds.getX()); - height = Math.min(height, height - (int)bounds.getY() + y); - y = Math.max(y, (int)bounds.getY()); - width = Math.min(width, (int)(bounds.getX() + bounds.getWidth()) - x); - height = Math.min(height, (int)(bounds.getY() + bounds.getHeight()) - y); - } - - super.setBounds(x, y, width, height); - } - - /** - * Expand frame by specified value. If the frame is going to be expanded outside of screen push the frame to - * the side. - * @param value size to expand frame by - */ - public void expandBy(final int value) - { - if (isFullScreen()) - { - return; - } - - int increment = value; - boolean forcedWidthIncrease = false; - - if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE) - { - final int minimumWidth = getLayout().minimumLayoutSize(this).width; - final int currentWidth = getWidth(); - - if (minimumWidth > currentWidth) - { - forcedWidthIncrease = true; - increment = minimumWidth - currentWidth; - } - } - - if (forcedWidthIncrease || expandResizeType == ExpandResizeType.KEEP_GAME_SIZE) - { - final int newWindowWidth = getWidth() + increment; - final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - final boolean wouldExpandThroughEdge = getX() + newWindowWidth > screenBounds.getX() + screenBounds.getWidth(); - int newWindowX = getX(); - - if (wouldExpandThroughEdge) - { - if (!isFrameCloseToRightEdge() || isFrameCloseToLeftEdge()) - { - // Move the window to the edge - newWindowX = (int)(screenBounds.getX() + screenBounds.getWidth()) - getWidth(); - } - - // Expand the window to the left as the user probably don't want the - // window to go through the screen - newWindowX -= increment; - - expandedClientOppositeDirection = true; - } - - setBounds(newWindowX, getY(), newWindowWidth, getHeight()); - } - - revalidateMinimumSize(); - } - - /** - * Contract frame by specified value. If new frame size is less than it's minimum size, force the minimum size. - * If the frame was pushed from side before, restore it's original position. - * @param value value to contract frame by - */ - public void contractBy(final int value) - { - if (isFullScreen()) - { - return; - } - - revalidateMinimumSize(); - final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - final boolean wasCloseToLeftEdge = Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; - int newWindowX = getX(); - int newWindowWidth = getWidth() - value; - - if (isFrameCloseToRightEdge() && (expandedClientOppositeDirection || !wasCloseToLeftEdge)) - { - // Keep the distance to the right edge - newWindowX += value; - } - - if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE && newWindowWidth > getMinimumSize().width) - { - // The sidebar fits inside the window, do not resize and move - newWindowWidth = getWidth(); - newWindowX = getX(); - } - - setBounds(newWindowX, getY(), newWindowWidth, getHeight()); - expandedClientOppositeDirection = false; - } - - /** - * Force minimum size of frame to be it's layout manager's minimum size - */ - public void revalidateMinimumSize() - { - setMinimumSize(getLayout().minimumLayoutSize(this)); - } - - private boolean isFullScreen() - { - return (getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH; - } - - private boolean isFrameCloseToLeftEdge() - { - Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - return Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; - } - - private boolean isFrameCloseToRightEdge() - { - Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - return Math.abs((getX() + getWidth()) - (screenBounds.getX() + screenBounds.getWidth())) <= SCREEN_EDGE_CLOSE_DISTANCE; - } -} +/* + * Copyright (c) 2018, Woox + * 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.ui; + +import java.awt.Frame; +import java.awt.Rectangle; +import javax.swing.JFrame; +import lombok.Setter; +import net.runelite.client.config.ExpandResizeType; + +public class ContainableFrame extends JFrame +{ + private static final int SCREEN_EDGE_CLOSE_DISTANCE = 40; + + @Setter + private ExpandResizeType expandResizeType; + private boolean containedInScreen; + private boolean expandedClientOppositeDirection; + + public void setContainedInScreen(boolean value) + { + this.containedInScreen = value; + + if (value) + { + // Reposition the frame if it is intersecting with the bounds + this.setLocation(this.getX(), this.getY()); + this.setBounds(this.getX(), this.getY(), this.getWidth(), this.getHeight()); + } + } + + @Override + public void setLocation(int x, int y) + { + if (containedInScreen) + { + Rectangle bounds = this.getGraphicsConfiguration().getBounds(); + x = Math.max(x, (int) bounds.getX()); + x = Math.min(x, (int) (bounds.getX() + bounds.getWidth() - this.getWidth())); + y = Math.max(y, (int) bounds.getY()); + y = Math.min(y, (int) (bounds.getY() + bounds.getHeight() - this.getHeight())); + } + + super.setLocation(x, y); + } + + @Override + public void setBounds(int x, int y, int width, int height) + { + if (containedInScreen) + { + Rectangle bounds = this.getGraphicsConfiguration().getBounds(); + width = Math.min(width, width - (int) bounds.getX() + x); + x = Math.max(x, (int) bounds.getX()); + height = Math.min(height, height - (int) bounds.getY() + y); + y = Math.max(y, (int) bounds.getY()); + width = Math.min(width, (int) (bounds.getX() + bounds.getWidth()) - x); + height = Math.min(height, (int) (bounds.getY() + bounds.getHeight()) - y); + } + + super.setBounds(x, y, width, height); + } + + /** + * Expand frame by specified value. If the frame is going to be expanded outside of screen push the frame to + * the side. + * + * @param value size to expand frame by + */ + public void expandBy(final int value) + { + if (isFullScreen()) + { + return; + } + + int increment = value; + boolean forcedWidthIncrease = false; + + if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE) + { + final int minimumWidth = getLayout().minimumLayoutSize(this).width; + final int currentWidth = getWidth(); + + if (minimumWidth > currentWidth) + { + forcedWidthIncrease = true; + increment = minimumWidth - currentWidth; + } + } + + if (forcedWidthIncrease || expandResizeType == ExpandResizeType.KEEP_GAME_SIZE) + { + final int newWindowWidth = getWidth() + increment; + final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + final boolean wouldExpandThroughEdge = getX() + newWindowWidth > screenBounds.getX() + screenBounds.getWidth(); + int newWindowX = getX(); + + if (wouldExpandThroughEdge) + { + if (!isFrameCloseToRightEdge() || isFrameCloseToLeftEdge()) + { + // Move the window to the edge + newWindowX = (int) (screenBounds.getX() + screenBounds.getWidth()) - getWidth(); + } + + // Expand the window to the left as the user probably don't want the + // window to go through the screen + newWindowX -= increment; + + expandedClientOppositeDirection = true; + } + + setBounds(newWindowX, getY(), newWindowWidth, getHeight()); + } + + revalidateMinimumSize(); + } + + /** + * Contract frame by specified value. If new frame size is less than it's minimum size, force the minimum size. + * If the frame was pushed from side before, restore it's original position. + * + * @param value value to contract frame by + */ + public void contractBy(final int value) + { + if (isFullScreen()) + { + return; + } + + revalidateMinimumSize(); + final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + final boolean wasCloseToLeftEdge = Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; + int newWindowX = getX(); + int newWindowWidth = getWidth() - value; + + if (isFrameCloseToRightEdge() && (expandedClientOppositeDirection || !wasCloseToLeftEdge)) + { + // Keep the distance to the right edge + newWindowX += value; + } + + if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE && newWindowWidth > getMinimumSize().width) + { + // The sidebar fits inside the window, do not resize and move + newWindowWidth = getWidth(); + newWindowX = getX(); + } + + setBounds(newWindowX, getY(), newWindowWidth, getHeight()); + expandedClientOppositeDirection = false; + } + + /** + * Force minimum size of frame to be it's layout manager's minimum size + */ + public void revalidateMinimumSize() + { + setMinimumSize(getLayout().minimumLayoutSize(this)); + } + + private boolean isFullScreen() + { + return (getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH; + } + + private boolean isFrameCloseToLeftEdge() + { + Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + return Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; + } + + private boolean isFrameCloseToRightEdge() + { + Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + return Math.abs((getX() + getWidth()) - (screenBounds.getX() + screenBounds.getWidth())) <= SCREEN_EDGE_CLOSE_DISTANCE; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java b/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java index 8be06a706c..291b181063 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java @@ -1,215 +1,216 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * 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.ui; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.Insets; -import java.util.function.Function; - -/** - * Grid layout implementation with support for cells with unequal size. - * - * See https://www.javaworld.com/article/2077486/core-java/java-tip-121--flex-your-grid-layout.html - */ -public class DynamicGridLayout extends GridLayout -{ - public DynamicGridLayout() - { - this(1, 0, 0, 0); - } - - public DynamicGridLayout(int rows, int cols) - { - this(rows, cols, 0, 0); - } - - public DynamicGridLayout(int rows, int cols, int hgap, int vgap) - { - super(rows, cols, hgap, vgap); - } - - @Override - public Dimension preferredLayoutSize(Container parent) - { - synchronized (parent.getTreeLock()) - { - return calculateSize(parent, Component::getPreferredSize); - } - } - - @Override - public Dimension minimumLayoutSize(Container parent) - { - synchronized (parent.getTreeLock()) - { - return calculateSize(parent, Component::getMinimumSize); - } - } - - @Override - public void layoutContainer(Container parent) - { - synchronized (parent.getTreeLock()) - { - final Insets insets = parent.getInsets(); - final int ncomponents = parent.getComponentCount(); - int nrows = getRows(); - int ncols = getColumns(); - - if (ncomponents == 0) - { - return; - } - - if (nrows > 0) - { - ncols = (ncomponents + nrows - 1) / nrows; - } - else - { - nrows = (ncomponents + ncols - 1) / ncols; - } - - final int hgap = getHgap(); - final int vgap = getVgap(); - - // scaling factors - final Dimension pd = preferredLayoutSize(parent); - final double sw = (1.0 * parent.getWidth()) / pd.width; - final double sh = (1.0 * parent.getHeight()) / pd.height; - - final int[] w = new int[ncols]; - final int[] h = new int[nrows]; - - // calculate dimensions for all components + apply scaling - for (int i = 0; i < ncomponents; i++) - { - final int r = i / ncols; - final int c = i % ncols; - final Component comp = parent.getComponent(i); - final Dimension d = comp.getPreferredSize(); - d.width = (int) (sw * d.width); - d.height = (int) (sh * d.height); - - if (w[c] < d.width) - { - w[c] = d.width; - } - - if (h[r] < d.height) - { - h[r] = d.height; - } - } - - // Apply new bounds to all child components - for (int c = 0, x = insets.left; c < ncols; c++) - { - for (int r = 0, y = insets.top; r < nrows; r++) - { - int i = r * ncols + c; - - if (i < ncomponents) - { - parent.getComponent(i).setBounds(x, y, w[c], h[r]); - } - - y += h[r] + vgap; - } - - x += w[c] + hgap; - } - } - } - - /** - * Calculate outer size of the layout based on it's children and sizer - * @param parent parent component - * @param sizer functioning returning dimension of the child component - * @return outer size - */ - private Dimension calculateSize(final Container parent, final Function sizer) - { - final int ncomponents = parent.getComponentCount(); - int nrows = getRows(); - int ncols = getColumns(); - - if (nrows > 0) - { - ncols = (ncomponents + nrows - 1) / nrows; - } - else - { - nrows = (ncomponents + ncols - 1) / ncols; - } - - final int[] w = new int[ncols]; - final int[] h = new int[nrows]; - - // Calculate dimensions for all components - for (int i = 0; i < ncomponents; i++) - { - final int r = i / ncols; - final int c = i % ncols; - final Component comp = parent.getComponent(i); - final Dimension d = sizer.apply(comp); - - if (w[c] < d.width) - { - w[c] = d.width; - } - - if (h[r] < d.height) - { - h[r] = d.height; - } - } - - // Calculate total width and height of the layout - int nw = 0; - - for (int j = 0; j < ncols; j++) - { - nw += w[j]; - } - - int nh = 0; - - for (int i = 0; i < nrows; i++) - { - nh += h[i]; - } - - final Insets insets = parent.getInsets(); - - // Apply insets and horizontal and vertical gap to layout - return new Dimension( - insets.left + insets.right + nw + (ncols - 1) * getHgap(), - insets.top + insets.bottom + nh + (nrows - 1) * getVgap()); - } +/* + * Copyright (c) 2018, Tomas Slusny + * 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.ui; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Insets; +import java.util.function.Function; + +/** + * Grid layout implementation with support for cells with unequal size. + *

+ * See https://www.javaworld.com/article/2077486/core-java/java-tip-121--flex-your-grid-layout.html + */ +public class DynamicGridLayout extends GridLayout +{ + public DynamicGridLayout() + { + this(1, 0, 0, 0); + } + + public DynamicGridLayout(int rows, int cols) + { + this(rows, cols, 0, 0); + } + + public DynamicGridLayout(int rows, int cols, int hgap, int vgap) + { + super(rows, cols, hgap, vgap); + } + + @Override + public Dimension preferredLayoutSize(Container parent) + { + synchronized (parent.getTreeLock()) + { + return calculateSize(parent, Component::getPreferredSize); + } + } + + @Override + public Dimension minimumLayoutSize(Container parent) + { + synchronized (parent.getTreeLock()) + { + return calculateSize(parent, Component::getMinimumSize); + } + } + + @Override + public void layoutContainer(Container parent) + { + synchronized (parent.getTreeLock()) + { + final Insets insets = parent.getInsets(); + final int ncomponents = parent.getComponentCount(); + int nrows = getRows(); + int ncols = getColumns(); + + if (ncomponents == 0) + { + return; + } + + if (nrows > 0) + { + ncols = (ncomponents + nrows - 1) / nrows; + } + else + { + nrows = (ncomponents + ncols - 1) / ncols; + } + + final int hgap = getHgap(); + final int vgap = getVgap(); + + // scaling factors + final Dimension pd = preferredLayoutSize(parent); + final double sw = (1.0 * parent.getWidth()) / pd.width; + final double sh = (1.0 * parent.getHeight()) / pd.height; + + final int[] w = new int[ncols]; + final int[] h = new int[nrows]; + + // calculate dimensions for all components + apply scaling + for (int i = 0; i < ncomponents; i++) + { + final int r = i / ncols; + final int c = i % ncols; + final Component comp = parent.getComponent(i); + final Dimension d = comp.getPreferredSize(); + d.width = (int) (sw * d.width); + d.height = (int) (sh * d.height); + + if (w[c] < d.width) + { + w[c] = d.width; + } + + if (h[r] < d.height) + { + h[r] = d.height; + } + } + + // Apply new bounds to all child components + for (int c = 0, x = insets.left; c < ncols; c++) + { + for (int r = 0, y = insets.top; r < nrows; r++) + { + int i = r * ncols + c; + + if (i < ncomponents) + { + parent.getComponent(i).setBounds(x, y, w[c], h[r]); + } + + y += h[r] + vgap; + } + + x += w[c] + hgap; + } + } + } + + /** + * Calculate outer size of the layout based on it's children and sizer + * + * @param parent parent component + * @param sizer functioning returning dimension of the child component + * @return outer size + */ + private Dimension calculateSize(final Container parent, final Function sizer) + { + final int ncomponents = parent.getComponentCount(); + int nrows = getRows(); + int ncols = getColumns(); + + if (nrows > 0) + { + ncols = (ncomponents + nrows - 1) / nrows; + } + else + { + nrows = (ncomponents + ncols - 1) / ncols; + } + + final int[] w = new int[ncols]; + final int[] h = new int[nrows]; + + // Calculate dimensions for all components + for (int i = 0; i < ncomponents; i++) + { + final int r = i / ncols; + final int c = i % ncols; + final Component comp = parent.getComponent(i); + final Dimension d = sizer.apply(comp); + + if (w[c] < d.width) + { + w[c] = d.width; + } + + if (h[r] < d.height) + { + h[r] = d.height; + } + } + + // Calculate total width and height of the layout + int nw = 0; + + for (int j = 0; j < ncols; j++) + { + nw += w[j]; + } + + int nh = 0; + + for (int i = 0; i < nrows; i++) + { + nh += h[i]; + } + + final Insets insets = parent.getInsets(); + + // Apply insets and horizontal and vertical gap to layout + return new Dimension( + insets.left + insets.right + nw + (ncols - 1) * getHgap(), + insets.top + insets.bottom + nh + (nrows - 1) * getVgap()); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java index b6fdac5172..9bff6fe9f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java @@ -1,96 +1,96 @@ -/* - * Copyright (c) 2017, Tyler - * 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.ui; - -import javax.swing.text.StyleContext; -import java.awt.Font; -import java.awt.FontFormatException; -import java.awt.GraphicsEnvironment; -import java.io.IOException; - -public class FontManager -{ - private static final Font runescapeFont; - private static final Font runescapeSmallFont; - private static final Font runescapeBoldFont; - - static - { - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - - try - { - Font font = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape.ttf")) - .deriveFont(Font.PLAIN, 16); - ge.registerFont(font); - - runescapeFont = StyleContext.getDefaultStyleContext() - .getFont(font.getName(), Font.PLAIN, 16); - ge.registerFont(runescapeFont); - - Font smallFont = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape_small.ttf")) - .deriveFont(Font.PLAIN, 16); - ge.registerFont(smallFont); - - runescapeSmallFont = StyleContext.getDefaultStyleContext() - .getFont(smallFont.getName(), Font.PLAIN, 16); - ge.registerFont(runescapeSmallFont); - - Font boldFont = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape_bold.ttf")) - .deriveFont(Font.PLAIN, 16); - ge.registerFont(boldFont); - - runescapeBoldFont = StyleContext.getDefaultStyleContext() - .getFont(boldFont.getName(), Font.PLAIN, 16); - ge.registerFont(runescapeBoldFont); - } - catch (FontFormatException ex) - { - throw new RuntimeException("Font loaded, but format incorrect.", ex); - } - catch (IOException ex) - { - throw new RuntimeException("Font file not found.", ex); - } - } - - public static Font getRunescapeFont() - { - return runescapeFont; - } - - public static Font getRunescapeSmallFont() - { - return runescapeSmallFont; - } - - public static Font getRunescapeBoldFont() - { - return runescapeBoldFont; - } -} +/* + * Copyright (c) 2017, Tyler + * 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.ui; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.io.IOException; +import javax.swing.text.StyleContext; + +public class FontManager +{ + private static final Font runescapeFont; + private static final Font runescapeSmallFont; + private static final Font runescapeBoldFont; + + static + { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + + try + { + Font font = Font.createFont(Font.TRUETYPE_FONT, + FontManager.class.getResourceAsStream("runescape.ttf")) + .deriveFont(Font.PLAIN, 16); + ge.registerFont(font); + + runescapeFont = StyleContext.getDefaultStyleContext() + .getFont(font.getName(), Font.PLAIN, 16); + ge.registerFont(runescapeFont); + + Font smallFont = Font.createFont(Font.TRUETYPE_FONT, + FontManager.class.getResourceAsStream("runescape_small.ttf")) + .deriveFont(Font.PLAIN, 16); + ge.registerFont(smallFont); + + runescapeSmallFont = StyleContext.getDefaultStyleContext() + .getFont(smallFont.getName(), Font.PLAIN, 16); + ge.registerFont(runescapeSmallFont); + + Font boldFont = Font.createFont(Font.TRUETYPE_FONT, + FontManager.class.getResourceAsStream("runescape_bold.ttf")) + .deriveFont(Font.PLAIN, 16); + ge.registerFont(boldFont); + + runescapeBoldFont = StyleContext.getDefaultStyleContext() + .getFont(boldFont.getName(), Font.PLAIN, 16); + ge.registerFont(runescapeBoldFont); + } + catch (FontFormatException ex) + { + throw new RuntimeException("Font loaded, but format incorrect.", ex); + } + catch (IOException ex) + { + throw new RuntimeException("Font file not found.", ex); + } + } + + public static Font getRunescapeFont() + { + return runescapeFont; + } + + public static Font getRunescapeSmallFont() + { + return runescapeSmallFont; + } + + public static Font getRunescapeBoldFont() + { + return runescapeBoldFont; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java b/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java index 9bbf474cf0..d5b998b0f8 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java @@ -1,243 +1,248 @@ -/* - * Copyright (c) 2016-2017, Jeremy Plsek - * 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.ui; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.IOException; -import javax.imageio.ImageIO; -import javax.inject.Singleton; -import javax.swing.ImageIcon; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; -import javax.swing.plaf.basic.BasicProgressBarUI; - -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.RuneLite; -import net.runelite.client.RuneLiteProperties; -import net.runelite.client.util.SwingUtil; -import org.pushingpixels.substance.internal.SubstanceSynapse; - -/** - * This is a custom Splash Screen and does not use Java's SplashScreen class. This has helper methods to update the - * status while loading RuneLite. All public methods run non-blocking passed to the swing thread. - */ -@Slf4j -@Singleton -public class RuneLiteSplashScreen -{ - private RuneLiteProperties runeLiteProperties = new RuneLiteProperties(); - - public JFrame frame; - public JPanel panel = new JPanel(); - public JLabel messageLabel; - public JLabel subMessageLabel; - public JProgressBar progressBar = new JProgressBar(); - - private int currentStep; - - /** - * This is not done in the constructor in order to avoid processing in case the user chooses to not load - * the splash screen. - * @param estimatedSteps steps until completion, used for the progress bar - */ - private void initLayout(final int estimatedSteps) - { - SwingUtil.setupRuneLiteLookAndFeel(); - - // init fields with updated swing look and feel - frame = new JFrame("RuneLitePlus Loading"); - messageLabel = new JLabel("Loading..."); - subMessageLabel = new JLabel(); - progressBar.setUI(new BasicProgressBarUI()); - progressBar.setMinimum(0); - progressBar.setMaximum(estimatedSteps); - - // frame setup - frame.setSize(220, 290); - frame.setLocationRelativeTo(null); - frame.setUndecorated(true); - - // main panel setup - // To reduce substance's colorization (tinting) - panel.putClientProperty(SubstanceSynapse.COLORIZATION_FACTOR, 1.0); - panel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - final GridBagLayout layout = new GridBagLayout(); - layout.columnWeights = new double[]{1}; - layout.rowWeights = new double[]{1, 0, 0, 1, 0, 1}; - panel.setLayout(layout); - - // logo - synchronized (ImageIO.class) - { - try - { - final BufferedImage logo = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus.png")); - frame.setIconImage(logo); - - final BufferedImage logoTransparent = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus_transparent.png")); - final GridBagConstraints logoConstraints = new GridBagConstraints(); - logoConstraints.anchor = GridBagConstraints.SOUTH; - panel.add(new JLabel(new ImageIcon(logoTransparent.getScaledInstance(96, 96, Image.SCALE_SMOOTH))), logoConstraints); - } - catch (IOException e) - { - log.warn("Error loading logo", e); - } - } - - // runelite title - final JLabel title = new JLabel("RuneLitePlus"); - final GridBagConstraints titleConstraints = new GridBagConstraints(); - titleConstraints.gridy = 1; - panel.add(title, titleConstraints); - - // version - final JLabel version = new JLabel("RuneLite Version : " + runeLiteProperties.getVersion()); - version.setForeground(Color.GREEN); - version.setFont(FontManager.getRunescapeSmallFont()); - version.setForeground(version.getForeground().darker()); - final GridBagConstraints versionConstraints = new GridBagConstraints(); - versionConstraints.gridy = 2; - panel.add(version, versionConstraints); - - // version - final JLabel litVersion = new JLabel("Plus Version : PRE-" + RuneLite.RUNELIT_VERSION); - litVersion.setForeground(Color.GREEN); - litVersion.setFont(FontManager.getRunescapeSmallFont()); - litVersion.setForeground(litVersion.getForeground().darker()); - final GridBagConstraints litVersionConstraints = new GridBagConstraints(); - litVersionConstraints.gridy = 3; - litVersionConstraints.weightx = 4; - panel.add(litVersion, litVersionConstraints); - - - // progressbar - final GridBagConstraints progressConstraints = new GridBagConstraints(); - progressConstraints.fill = GridBagConstraints.HORIZONTAL; - progressConstraints.anchor = GridBagConstraints.SOUTH; - progressConstraints.gridy = 4; - panel.add(progressBar, progressConstraints); - - // main message - messageLabel.setFont(FontManager.getRunescapeSmallFont()); - final GridBagConstraints messageConstraints = new GridBagConstraints(); - messageConstraints.gridy = 5; - panel.add(messageLabel, messageConstraints); - - // alternate message - final GridBagConstraints subMessageConstraints = new GridBagConstraints(); - subMessageLabel.setForeground(subMessageLabel.getForeground().darker()); - subMessageLabel.setFont(FontManager.getRunescapeSmallFont()); - subMessageConstraints.gridy = 6; - panel.add(subMessageLabel, subMessageConstraints); - - frame.setContentPane(panel); - } - - private boolean notActive() - { - return frame == null || !frame.isDisplayable(); - } - - /** - * Close/dispose of the splash screen - */ - public void close() - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - - frame.dispose(); - }); - } - - /** - * Set the splash screen to be visible. - * @param estimatedSteps steps until completion, used for the progress bar - */ - public void open(final int estimatedSteps) - { - SwingUtilities.invokeLater(() -> - { - initLayout(estimatedSteps); - frame.setVisible(true); - }); - } - - public void setMessage(final String message) - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - messageLabel.setText(message); - }); - } - - public void setSubMessage(final String subMessage) - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - subMessageLabel.setText(subMessage); - }); - } - - public void setProgress(int currentProgress, int progressGoal) - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - if (progressGoal!=progressBar.getMaximum()) { - panel.remove(progressBar); - panel.validate(); - final GridBagConstraints progressConstraints = new GridBagConstraints(); - progressConstraints.fill = GridBagConstraints.HORIZONTAL; - progressConstraints.anchor = GridBagConstraints.SOUTH; - progressConstraints.gridy = 4; - panel.add(progressBar, progressConstraints); - panel.validate(); - } - progressBar.setMaximum(progressGoal); - progressBar.setValue(currentProgress); - }); - } -} +/* + * Copyright (c) 2016-2017, Jeremy Plsek + * 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.ui; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.IOException; +import javax.imageio.ImageIO; +import javax.inject.Singleton; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicProgressBarUI; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLite; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.util.SwingUtil; +import org.pushingpixels.substance.internal.SubstanceSynapse; + +/** + * This is a custom Splash Screen and does not use Java's SplashScreen class. This has helper methods to update the + * status while loading RuneLite. All public methods run non-blocking passed to the swing thread. + */ +@Slf4j +@Singleton +public class RuneLiteSplashScreen +{ + private RuneLiteProperties runeLiteProperties = new RuneLiteProperties(); + + public JFrame frame; + public JPanel panel = new JPanel(); + public JLabel messageLabel; + public JLabel subMessageLabel; + public JProgressBar progressBar = new JProgressBar(); + + private int currentStep; + + /** + * This is not done in the constructor in order to avoid processing in case the user chooses to not load + * the splash screen. + * + * @param estimatedSteps steps until completion, used for the progress bar + */ + private void initLayout(final int estimatedSteps) + { + SwingUtil.setupRuneLiteLookAndFeel(); + + // init fields with updated swing look and feel + frame = new JFrame("RuneLitePlus Loading"); + messageLabel = new JLabel("Loading..."); + subMessageLabel = new JLabel(); + progressBar.setUI(new BasicProgressBarUI()); + progressBar.setMinimum(0); + progressBar.setMaximum(estimatedSteps); + + // frame setup + frame.setSize(220, 290); + frame.setLocationRelativeTo(null); + frame.setUndecorated(true); + + // main panel setup + // To reduce substance's colorization (tinting) + panel.putClientProperty(SubstanceSynapse.COLORIZATION_FACTOR, 1.0); + panel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + final GridBagLayout layout = new GridBagLayout(); + layout.columnWeights = new double[]{1}; + layout.rowWeights = new double[]{1, 0, 0, 1, 0, 1}; + panel.setLayout(layout); + + // logo + synchronized (ImageIO.class) + { + try + { + final BufferedImage logo = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus.png")); + frame.setIconImage(logo); + + final BufferedImage logoTransparent = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus_transparent.png")); + final GridBagConstraints logoConstraints = new GridBagConstraints(); + logoConstraints.anchor = GridBagConstraints.SOUTH; + panel.add(new JLabel(new ImageIcon(logoTransparent.getScaledInstance(96, 96, Image.SCALE_SMOOTH))), logoConstraints); + } + catch (IOException e) + { + log.warn("Error loading logo", e); + } + } + + // runelite title + final JLabel title = new JLabel("RuneLitePlus"); + final GridBagConstraints titleConstraints = new GridBagConstraints(); + titleConstraints.gridy = 1; + panel.add(title, titleConstraints); + + // version + final JLabel version = new JLabel("RuneLite Version : " + runeLiteProperties.getVersion()); + version.setForeground(Color.GREEN); + version.setFont(FontManager.getRunescapeSmallFont()); + version.setForeground(version.getForeground().darker()); + final GridBagConstraints versionConstraints = new GridBagConstraints(); + versionConstraints.gridy = 2; + panel.add(version, versionConstraints); + + // version + final JLabel litVersion = new JLabel("Plus Version : PRE-" + RuneLite.RUNELIT_VERSION); + litVersion.setForeground(Color.GREEN); + litVersion.setFont(FontManager.getRunescapeSmallFont()); + litVersion.setForeground(litVersion.getForeground().darker()); + final GridBagConstraints litVersionConstraints = new GridBagConstraints(); + litVersionConstraints.gridy = 3; + litVersionConstraints.weightx = 4; + panel.add(litVersion, litVersionConstraints); + + + // progressbar + final GridBagConstraints progressConstraints = new GridBagConstraints(); + progressConstraints.fill = GridBagConstraints.HORIZONTAL; + progressConstraints.anchor = GridBagConstraints.SOUTH; + progressConstraints.gridy = 4; + panel.add(progressBar, progressConstraints); + + // main message + messageLabel.setFont(FontManager.getRunescapeSmallFont()); + final GridBagConstraints messageConstraints = new GridBagConstraints(); + messageConstraints.gridy = 5; + panel.add(messageLabel, messageConstraints); + + // alternate message + final GridBagConstraints subMessageConstraints = new GridBagConstraints(); + subMessageLabel.setForeground(subMessageLabel.getForeground().darker()); + subMessageLabel.setFont(FontManager.getRunescapeSmallFont()); + subMessageConstraints.gridy = 6; + panel.add(subMessageLabel, subMessageConstraints); + + frame.setContentPane(panel); + } + + private boolean notActive() + { + return frame == null || !frame.isDisplayable(); + } + + /** + * Close/dispose of the splash screen + */ + public void close() + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + + frame.dispose(); + }); + } + + /** + * Set the splash screen to be visible. + * + * @param estimatedSteps steps until completion, used for the progress bar + */ + public void open(final int estimatedSteps) + { + SwingUtilities.invokeLater(() -> + { + initLayout(estimatedSteps); + frame.setVisible(true); + }); + } + + public void setMessage(final String message) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + messageLabel.setText(message); + }); + } + + public void setSubMessage(final String subMessage) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + subMessageLabel.setText(subMessage); + }); + } + + public void setProgress(int currentProgress, int progressGoal) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + if (progressGoal != progressBar.getMaximum()) + { + panel.remove(progressBar); + panel.validate(); + final GridBagConstraints progressConstraints = new GridBagConstraints(); + progressConstraints.fill = GridBagConstraints.HORIZONTAL; + progressConstraints.anchor = GridBagConstraints.SOUTH; + progressConstraints.gridy = 4; + panel.add(progressBar, progressConstraints); + panel.validate(); + } + progressBar.setMaximum(progressGoal); + progressBar.setValue(currentProgress); + }); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java index c36dd72abe..11131a8413 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java @@ -1,90 +1,91 @@ -/* - * Copyright (c) 2018, Levi - * 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.ui.components; - -import java.awt.Color; -import javax.swing.JPanel; -import lombok.Getter; - -public class DimmableJPanel extends JPanel -{ - // Dimming state, allows for restoring original colors before dimming - @Getter - private boolean dimmed = false; - private Color dimmedForeground = null; - private Color dimmedBackground = null; - private Color undimmedForeground = null; - private Color undimmedBackground = null; - - @Override - public void setForeground(Color color) - { - undimmedForeground = color; - dimmedForeground = color.darker(); - super.setForeground(color); - } - - @Override - public void setBackground(Color color) - { - undimmedBackground = color; - dimmedBackground = color.darker(); - super.setBackground(color); - } - - @Override - public Color getForeground() - { - return dimmed ? dimmedForeground : undimmedForeground; - } - - @Override - public Color getBackground() - { - return dimmed ? dimmedBackground : undimmedBackground; - } - - /** - * Dimming sets all parts of this component with darker colors except for the central label - * This is useful for showing that progress is paused - * Setting dim to false will restore the original colors from before the component was dimmed. - * @param dimmed - */ - public void setDimmed(boolean dimmed) - { - this.dimmed = dimmed; - - if (dimmed) - { - super.setBackground(dimmedBackground); - super.setForeground(dimmedForeground); - } - else - { - super.setBackground(undimmedBackground); - super.setForeground(undimmedForeground); - } - } -} +/* + * Copyright (c) 2018, Levi + * 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.ui.components; + +import java.awt.Color; +import javax.swing.JPanel; +import lombok.Getter; + +public class DimmableJPanel extends JPanel +{ + // Dimming state, allows for restoring original colors before dimming + @Getter + private boolean dimmed = false; + private Color dimmedForeground = null; + private Color dimmedBackground = null; + private Color undimmedForeground = null; + private Color undimmedBackground = null; + + @Override + public void setForeground(Color color) + { + undimmedForeground = color; + dimmedForeground = color.darker(); + super.setForeground(color); + } + + @Override + public void setBackground(Color color) + { + undimmedBackground = color; + dimmedBackground = color.darker(); + super.setBackground(color); + } + + @Override + public Color getForeground() + { + return dimmed ? dimmedForeground : undimmedForeground; + } + + @Override + public Color getBackground() + { + return dimmed ? dimmedBackground : undimmedBackground; + } + + /** + * Dimming sets all parts of this component with darker colors except for the central label + * This is useful for showing that progress is paused + * Setting dim to false will restore the original colors from before the component was dimmed. + * + * @param dimmed + */ + public void setDimmed(boolean dimmed) + { + this.dimmed = dimmed; + + if (dimmed) + { + super.setBackground(dimmedBackground); + super.setForeground(dimmedForeground); + } + else + { + super.setBackground(undimmedBackground); + super.setForeground(undimmedForeground); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java b/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java index f80ff5b740..7a658cade6 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java @@ -1,95 +1,95 @@ -/* - * Copyright (c) 2018, Psikoi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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 HOLDER 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.ui.components; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import javax.swing.JPanel; -import lombok.Getter; - -/** - * A progress bar to be displayed underneath the GE offer item panels - */ -public class ThinProgressBar extends JPanel -{ - @Getter - private int maximumValue = 1; - - @Getter - private int value; - - public ThinProgressBar() - { - setForeground(Color.GREEN); - setMaximumSize(new Dimension(Integer.MAX_VALUE, 4)); - setMinimumSize(new Dimension(0, 4)); - setPreferredSize(new Dimension(0, 4)); - setSize(new Dimension(0, 4)); - setOpaque(true); - } - - public double getPercentage() - { - return (value * 100) / maximumValue; - } - - @Override - public void setForeground(Color color) - { - super.setForeground(color); - setBackground(color.darker()); - } - - public void setMaximumValue(int maximumValue) - { - if (maximumValue < 1) - { - maximumValue = 1; - } - this.maximumValue = maximumValue; - repaint(); - } - - public void setValue(int value) - { - this.value = value; - repaint(); - } - - @Override - public void paintComponent(Graphics g) - { - super.paintComponent(g); - int w = getWidth(); - int h = getHeight(); - int div = (value * w) / maximumValue; - g.setColor(getBackground()); - g.fillRect(div, 0, w, h); - g.setColor(getForeground()); - g.fillRect(0, 0, div, h); - } +/* + * Copyright (c) 2018, Psikoi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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 HOLDER 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.ui.components; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import javax.swing.JPanel; +import lombok.Getter; + +/** + * A progress bar to be displayed underneath the GE offer item panels + */ +public class ThinProgressBar extends JPanel +{ + @Getter + private int maximumValue = 1; + + @Getter + private int value; + + public ThinProgressBar() + { + setForeground(Color.GREEN); + setMaximumSize(new Dimension(Integer.MAX_VALUE, 4)); + setMinimumSize(new Dimension(0, 4)); + setPreferredSize(new Dimension(0, 4)); + setSize(new Dimension(0, 4)); + setOpaque(true); + } + + public double getPercentage() + { + return (value * 100) / (double) maximumValue; + } + + @Override + public void setForeground(Color color) + { + super.setForeground(color); + setBackground(color.darker()); + } + + public void setMaximumValue(int maximumValue) + { + if (maximumValue < 1) + { + maximumValue = 1; + } + this.maximumValue = maximumValue; + repaint(); + } + + public void setValue(int value) + { + this.value = value; + repaint(); + } + + @Override + public void paintComponent(Graphics g) + { + super.paintComponent(g); + int w = getWidth(); + int h = getHeight(); + int div = (value * w) / maximumValue; + g.setColor(getBackground()); + g.fillRect(div, 0, w, h); + g.setColor(getForeground()); + g.fillRect(0, 0, div, h); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java index 07b9518be3..207d909d8a 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java @@ -1,71 +1,72 @@ -/* - * Copyright (c) 2016-2017, Adam - * 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.ui.overlay; - -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; -import javax.annotation.Nullable; -import lombok.Getter; -import lombok.Setter; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity; - -@Getter -@Setter -public abstract class Overlay implements LayoutableRenderableEntity -{ - @Nullable - private final Plugin plugin; - private Point preferredLocation; - private Dimension preferredSize; - private OverlayPosition preferredPosition; - private Rectangle bounds = new Rectangle(); - private OverlayPosition position = OverlayPosition.TOP_LEFT; - private OverlayPriority priority = OverlayPriority.NONE; - private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS; - private final List menuEntries = new ArrayList<>(); - - protected Overlay() - { - plugin = null; - } - - protected Overlay(Plugin plugin) - { - this.plugin = plugin; - } - - /** - * Overlay name, used for saving the overlay, needs to be unique - * @return overlay name - */ - public String getName() - { - return this.getClass().getSimpleName(); - } -} +/* + * Copyright (c) 2016-2017, Adam + * 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.ui.overlay; + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity; + +@Getter +@Setter +public abstract class Overlay implements LayoutableRenderableEntity +{ + @Nullable + private final Plugin plugin; + private Point preferredLocation; + private Dimension preferredSize; + private OverlayPosition preferredPosition; + private Rectangle bounds = new Rectangle(); + private OverlayPosition position = OverlayPosition.TOP_LEFT; + private OverlayPriority priority = OverlayPriority.NONE; + private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS; + private final List menuEntries = new ArrayList<>(); + + protected Overlay() + { + plugin = null; + } + + protected Overlay(Plugin plugin) + { + this.plugin = plugin; + } + + /** + * Overlay name, used for saving the overlay, needs to be unique + * + * @return overlay name + */ + public String getName() + { + return this.getClass().getSimpleName(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java index bb21e1e3f3..fb5d3bfaf7 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java @@ -1,385 +1,385 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * 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.ui.overlay; - -import com.google.common.annotations.VisibleForTesting; -import java.awt.Dimension; -import java.awt.Point; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Predicate; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.MenuAction; -import net.runelite.api.events.MenuOptionClicked; -import net.runelite.api.widgets.WidgetItem; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.events.OverlayMenuClicked; -import net.runelite.client.events.PluginChanged; - -/** - * Manages state of all game overlays - */ -@Singleton -public class OverlayManager -{ - public static final String OPTION_CONFIGURE = "Configure"; - - private static final String OVERLAY_CONFIG_PREFERRED_LOCATION = "_preferredLocation"; - private static final String OVERLAY_CONFIG_PREFERRED_POSITION = "_preferredPosition"; - private static final String OVERLAY_CONFIG_PREFERRED_SIZE = "_preferredSize"; - private static final String RUNELITE_CONFIG_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value(); - - @VisibleForTesting - static final Comparator OVERLAY_COMPARATOR = (a, b) -> - { - final OverlayPosition aPos = a.getPreferredPosition() != null - ? a.getPreferredPosition() - : a.getPosition(); - - final OverlayPosition bPos = b.getPreferredPosition() != null - ? b.getPreferredPosition() - : b.getPosition(); - - if (aPos != bPos) - { - // This is so non-dynamic overlays render after dynamic - // overlays, which are generally in the scene - return aPos.compareTo(bPos); - } - - // For dynamic overlays, higher priority means to - // draw *later* so it is on top. - // For non-dynamic overlays, higher priority means - // draw *first* so that they are closer to their - // defined position. - return aPos == OverlayPosition.DYNAMIC - ? a.getPriority().compareTo(b.getPriority()) - : b.getPriority().compareTo(a.getPriority()); - }; - - /** - * Insertion-order sorted set of overlays - * All access to this must be guarded by a lock on this OverlayManager - */ - @Getter(AccessLevel.PACKAGE) - private final List overlays = new ArrayList<>(); - @Getter - private final List itemWidgets = new ArrayList<>(); - - private final Map> overlayLayers = new EnumMap<>(OverlayLayer.class); - - private final ConfigManager configManager; - private final EventBus eventBus; - - @Inject - private OverlayManager(final ConfigManager configManager, final EventBus eventBus) - { - this.configManager = configManager; - this.eventBus = eventBus; - } - - @Subscribe - public void onPluginChanged(final PluginChanged event) - { - overlays.forEach(this::loadOverlay); - rebuildOverlayLayers(); - } - - @Subscribe - public void onMenuOptionClicked(MenuOptionClicked event) - { - if (event.getMenuAction() != MenuAction.RUNELITE_OVERLAY) - { - return; - } - - event.consume(); - - Optional optionalOverlay = overlays.stream().filter(o -> overlays.indexOf(o) == event.getId()).findAny(); - if (optionalOverlay.isPresent()) - { - Overlay overlay = optionalOverlay.get(); - List menuEntries = overlay.getMenuEntries(); - Optional optionalOverlayMenuEntry = menuEntries.stream() - .filter(me -> me.getOption().equals(event.getMenuOption())) - .findAny(); - if (optionalOverlayMenuEntry.isPresent()) - { - eventBus.post(new OverlayMenuClicked(optionalOverlayMenuEntry.get(), overlay)); - } - } - } - - /** - * Gets all of the overlays on a layer sorted by priority and position - * - * @param layer the layer - * @return An immutable list of all of the overlays on that layer - */ - synchronized List getLayer(OverlayLayer layer) - { - return overlayLayers.get(layer); - } - - /** - * Add overlay. - * - * @param overlay the overlay - * @return true if overlay was added - */ - public synchronized boolean add(final Overlay overlay) - { - if (overlays.contains(overlay)) - { - return false; - } - - // Add is always true - overlays.add(overlay); - loadOverlay(overlay); - // WidgetItemOverlays have a reference to the overlay manager in order to get the WidgetItems - // for each frame. - if (overlay instanceof WidgetItemOverlay) - { - ((WidgetItemOverlay) overlay).setOverlayManager(this); - } - rebuildOverlayLayers(); - return true; - } - - /** - * Remove overlay. - * - * @param overlay the overlay - * @return true if overlay was removed - */ - public synchronized boolean remove(final Overlay overlay) - { - final boolean remove = overlays.remove(overlay); - - if (remove) - { - rebuildOverlayLayers(); - } - - return remove; - } - - /** - * Remove if overlay matches filter - * - * @param filter the filter - * @return true if any overlay was removed - */ - public synchronized boolean removeIf(Predicate filter) - { - final boolean removeIf = overlays.removeIf(filter); - - if (removeIf) - { - rebuildOverlayLayers(); - } - - return removeIf; - } - - /** - * Clear all overlays - */ - public synchronized void clear() - { - overlays.clear(); - rebuildOverlayLayers(); - } - - /** - * Force save overlay data - * - * @param overlay overlay to save - */ - public synchronized void saveOverlay(final Overlay overlay) - { - saveOverlayPosition(overlay); - saveOverlaySize(overlay); - saveOverlayLocation(overlay); - rebuildOverlayLayers(); - } - - /** - * Resets stored overlay position data - * - * @param overlay overlay to reset - */ - public synchronized void resetOverlay(final Overlay overlay) - { - overlay.setPreferredPosition(null); - overlay.setPreferredSize(null); - overlay.setPreferredLocation(null); - saveOverlay(overlay); - } - - private synchronized void rebuildOverlayLayers() - { - for (OverlayLayer l : OverlayLayer.values()) - { - overlayLayers.put(l, new ArrayList<>()); - } - - for (final Overlay overlay : overlays) - { - OverlayLayer layer = overlay.getLayer(); - - if (overlay.getPreferredLocation() != null && overlay.getPreferredPosition() == null) - { - // When UNDER_WIDGET overlays are in preferred locations, move to - // ABOVE_WIDGETS so that it can draw over interfaces - if (layer == OverlayLayer.UNDER_WIDGETS && !(overlay instanceof WidgetOverlay)) - { - layer = OverlayLayer.ABOVE_WIDGETS; - } - } - - overlayLayers.get(layer).add(overlay); - } - - overlayLayers.forEach((layer, value) -> - { - value.sort(OVERLAY_COMPARATOR); - overlayLayers.put(layer, Collections.unmodifiableList(value)); - }); - } - - private void loadOverlay(final Overlay overlay) - { - final Point location = loadOverlayLocation(overlay); - overlay.setPreferredLocation(location); - final Dimension size = loadOverlaySize(overlay); - overlay.setPreferredSize(size); - final OverlayPosition position = loadOverlayPosition(overlay); - overlay.setPreferredPosition(position); - } - - private void saveOverlayLocation(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; - if (overlay.getPreferredLocation() != null) - { - configManager.setConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key, - overlay.getPreferredLocation()); - } - else - { - configManager.unsetConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key); - } - } - - private void saveOverlaySize(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; - if (overlay.getPreferredSize() != null) - { - configManager.setConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key, - overlay.getPreferredSize()); - } - else - { - configManager.unsetConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key); - } - } - - private void saveOverlayPosition(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; - if (overlay.getPreferredPosition() != null) - { - configManager.setConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key, - overlay.getPreferredPosition()); - } - else - { - configManager.unsetConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key); - } - } - - private Point loadOverlayLocation(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; - return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Point.class); - } - - private Dimension loadOverlaySize(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; - return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Dimension.class); - } - - private OverlayPosition loadOverlayPosition(final Overlay overlay) - { - final String locationKey = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; - return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, locationKey, OverlayPosition.class); - } - - public WidgetOverlay getWidgetOverlay(final WidgetInfo info) - { - for (Overlay o : overlays) - { - if (o instanceof WidgetOverlay) - { - WidgetOverlay overlay = (WidgetOverlay) o; - if (overlay.getWidgetInfo().equals(info)) - { - return overlay; - } - } - } - - return null; - } +/* + * Copyright (c) 2018, Tomas Slusny + * 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.ui.overlay; + +import com.google.common.annotations.VisibleForTesting; +import java.awt.Dimension; +import java.awt.Point; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.MenuAction; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.OverlayMenuClicked; +import net.runelite.client.events.PluginChanged; + +/** + * Manages state of all game overlays + */ +@Singleton +public class OverlayManager +{ + public static final String OPTION_CONFIGURE = "Configure"; + + private static final String OVERLAY_CONFIG_PREFERRED_LOCATION = "_preferredLocation"; + private static final String OVERLAY_CONFIG_PREFERRED_POSITION = "_preferredPosition"; + private static final String OVERLAY_CONFIG_PREFERRED_SIZE = "_preferredSize"; + private static final String RUNELITE_CONFIG_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value(); + + @VisibleForTesting + static final Comparator OVERLAY_COMPARATOR = (a, b) -> + { + final OverlayPosition aPos = a.getPreferredPosition() != null + ? a.getPreferredPosition() + : a.getPosition(); + + final OverlayPosition bPos = b.getPreferredPosition() != null + ? b.getPreferredPosition() + : b.getPosition(); + + if (aPos != bPos) + { + // This is so non-dynamic overlays render after dynamic + // overlays, which are generally in the scene + return aPos.compareTo(bPos); + } + + // For dynamic overlays, higher priority means to + // draw *later* so it is on top. + // For non-dynamic overlays, higher priority means + // draw *first* so that they are closer to their + // defined position. + return aPos == OverlayPosition.DYNAMIC + ? a.getPriority().compareTo(b.getPriority()) + : b.getPriority().compareTo(a.getPriority()); + }; + + /** + * Insertion-order sorted set of overlays + * All access to this must be guarded by a lock on this OverlayManager + */ + @Getter(AccessLevel.PACKAGE) + private final List overlays = new ArrayList<>(); + @Getter + private final List itemWidgets = new ArrayList<>(); + + private final Map> overlayLayers = new EnumMap<>(OverlayLayer.class); + + private final ConfigManager configManager; + private final EventBus eventBus; + + @Inject + private OverlayManager(final ConfigManager configManager, final EventBus eventBus) + { + this.configManager = configManager; + this.eventBus = eventBus; + } + + @Subscribe + public void onPluginChanged(final PluginChanged event) + { + overlays.forEach(this::loadOverlay); + rebuildOverlayLayers(); + } + + @Subscribe + public void onMenuOptionClicked(MenuOptionClicked event) + { + if (event.getMenuAction() != MenuAction.RUNELITE_OVERLAY) + { + return; + } + + event.consume(); + + Optional optionalOverlay = overlays.stream().filter(o -> overlays.indexOf(o) == event.getId()).findAny(); + if (optionalOverlay.isPresent()) + { + Overlay overlay = optionalOverlay.get(); + List menuEntries = overlay.getMenuEntries(); + Optional optionalOverlayMenuEntry = menuEntries.stream() + .filter(me -> me.getOption().equals(event.getMenuOption())) + .findAny(); + if (optionalOverlayMenuEntry.isPresent()) + { + eventBus.post(new OverlayMenuClicked(optionalOverlayMenuEntry.get(), overlay)); + } + } + } + + /** + * Gets all of the overlays on a layer sorted by priority and position + * + * @param layer the layer + * @return An immutable list of all of the overlays on that layer + */ + synchronized List getLayer(OverlayLayer layer) + { + return overlayLayers.get(layer); + } + + /** + * Add overlay. + * + * @param overlay the overlay + * @return true if overlay was added + */ + public synchronized boolean add(final Overlay overlay) + { + if (overlays.contains(overlay)) + { + return false; + } + + // Add is always true + overlays.add(overlay); + loadOverlay(overlay); + // WidgetItemOverlays have a reference to the overlay manager in order to get the WidgetItems + // for each frame. + if (overlay instanceof WidgetItemOverlay) + { + ((WidgetItemOverlay) overlay).setOverlayManager(this); + } + rebuildOverlayLayers(); + return true; + } + + /** + * Remove overlay. + * + * @param overlay the overlay + * @return true if overlay was removed + */ + public synchronized boolean remove(final Overlay overlay) + { + final boolean remove = overlays.remove(overlay); + + if (remove) + { + rebuildOverlayLayers(); + } + + return remove; + } + + /** + * Remove if overlay matches filter + * + * @param filter the filter + * @return true if any overlay was removed + */ + public synchronized boolean removeIf(Predicate filter) + { + final boolean removeIf = overlays.removeIf(filter); + + if (removeIf) + { + rebuildOverlayLayers(); + } + + return removeIf; + } + + /** + * Clear all overlays + */ + public synchronized void clear() + { + overlays.clear(); + rebuildOverlayLayers(); + } + + /** + * Force save overlay data + * + * @param overlay overlay to save + */ + public synchronized void saveOverlay(final Overlay overlay) + { + saveOverlayPosition(overlay); + saveOverlaySize(overlay); + saveOverlayLocation(overlay); + rebuildOverlayLayers(); + } + + /** + * Resets stored overlay position data + * + * @param overlay overlay to reset + */ + public synchronized void resetOverlay(final Overlay overlay) + { + overlay.setPreferredPosition(null); + overlay.setPreferredSize(null); + overlay.setPreferredLocation(null); + saveOverlay(overlay); + } + + private synchronized void rebuildOverlayLayers() + { + for (OverlayLayer l : OverlayLayer.values()) + { + overlayLayers.put(l, new ArrayList<>()); + } + + for (final Overlay overlay : overlays) + { + OverlayLayer layer = overlay.getLayer(); + + if (overlay.getPreferredLocation() != null && overlay.getPreferredPosition() == null) + { + // When UNDER_WIDGET overlays are in preferred locations, move to + // ABOVE_WIDGETS so that it can draw over interfaces + if (layer == OverlayLayer.UNDER_WIDGETS && !(overlay instanceof WidgetOverlay)) + { + layer = OverlayLayer.ABOVE_WIDGETS; + } + } + + overlayLayers.get(layer).add(overlay); + } + + overlayLayers.forEach((layer, value) -> + { + value.sort(OVERLAY_COMPARATOR); + overlayLayers.put(layer, Collections.unmodifiableList(value)); + }); + } + + private void loadOverlay(final Overlay overlay) + { + final Point location = loadOverlayLocation(overlay); + overlay.setPreferredLocation(location); + final Dimension size = loadOverlaySize(overlay); + overlay.setPreferredSize(size); + final OverlayPosition position = loadOverlayPosition(overlay); + overlay.setPreferredPosition(position); + } + + private void saveOverlayLocation(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; + if (overlay.getPreferredLocation() != null) + { + configManager.setConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key, + overlay.getPreferredLocation()); + } + else + { + configManager.unsetConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key); + } + } + + private void saveOverlaySize(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; + if (overlay.getPreferredSize() != null) + { + configManager.setConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key, + overlay.getPreferredSize()); + } + else + { + configManager.unsetConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key); + } + } + + private void saveOverlayPosition(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; + if (overlay.getPreferredPosition() != null) + { + configManager.setConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key, + overlay.getPreferredPosition()); + } + else + { + configManager.unsetConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key); + } + } + + private Point loadOverlayLocation(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; + return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Point.class); + } + + private Dimension loadOverlaySize(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; + return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Dimension.class); + } + + private OverlayPosition loadOverlayPosition(final Overlay overlay) + { + final String locationKey = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; + return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, locationKey, OverlayPosition.class); + } + + public WidgetOverlay getWidgetOverlay(final WidgetInfo info) + { + for (Overlay o : overlays) + { + if (o instanceof WidgetOverlay) + { + WidgetOverlay overlay = (WidgetOverlay) o; + if (overlay.getWidgetInfo().equals(info)) + { + return overlay; + } + } + } + + return null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index a9f2e9f017..ec85807477 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -1,581 +1,581 @@ -/* - * Copyright (c) 2016-2017, Adam - * 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.ui.overlay; - -import com.google.common.base.MoreObjects; -import com.google.common.primitives.Ints; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.swing.SwingUtilities; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.MenuAction; -import net.runelite.api.MenuEntry; -import net.runelite.api.events.BeforeRender; -import net.runelite.api.events.ClientTick; -import net.runelite.api.events.FocusChanged; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.input.MouseAdapter; -import net.runelite.client.input.MouseManager; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.util.ColorUtil; - -@Singleton -public class OverlayRenderer extends MouseAdapter implements KeyListener -{ - private static final int BORDER = 5; - private static final int BORDER_TOP = BORDER + 15; - private static final int PADDING = 2; - private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80); - private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50); - private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100); - private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100); - private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200); - private final Client client; - private final OverlayManager overlayManager; - private final RuneLiteConfig runeLiteConfig; - - // Overlay movement variables - private final Point overlayOffset = new Point(); - private final Point mousePosition = new Point(); - private Overlay movedOverlay; - private boolean inOverlayDraggingMode; - private boolean inMenuEntryMode; - private MenuEntry[] menuEntries; - - // Overlay state validation - private Rectangle viewportBounds; - private Rectangle chatboxBounds; - private int viewportOffset; - private boolean chatboxHidden; - private boolean isResizeable; - private OverlayBounds snapCorners; - - @Inject - private OverlayRenderer( - final Client client, - final OverlayManager overlayManager, - final RuneLiteConfig runeLiteConfig, - final MouseManager mouseManager, - final KeyManager keyManager) - { - this.client = client; - this.overlayManager = overlayManager; - this.runeLiteConfig = runeLiteConfig; - keyManager.registerKeyListener(this); - mouseManager.registerMouseListener(this); - } - - @Subscribe - public void onFocusChanged(FocusChanged event) - { - if (!event.isFocused()) - { - inOverlayDraggingMode = false; - inMenuEntryMode = false; - menuEntries = null; - } - } - - @Subscribe - protected void onClientTick(ClientTick t) - { - if (menuEntries == null) - { - return; - } - - if (!inMenuEntryMode && runeLiteConfig.menuEntryShift()) - { - return; - } - - if (client.isMenuOpen()) - { - return; - } - - MenuEntry[] clientMenuEntries = client.getMenuEntries(); - MenuEntry[] newEntries = new MenuEntry[clientMenuEntries.length + menuEntries.length]; - - newEntries[0] = clientMenuEntries[0]; // Keep cancel at 0 - System.arraycopy(menuEntries, 0, newEntries, 1, menuEntries.length); // Add overlay menu entries - System.arraycopy(clientMenuEntries, 1, newEntries, menuEntries.length + 1, clientMenuEntries.length - 1); // Add remaining menu entries - client.setMenuEntries(newEntries); - } - - @Subscribe - public void onBeforeRender(BeforeRender event) - { - menuEntries = null; - } - - public void render(Graphics2D graphics, final OverlayLayer layer) - { - if (layer != OverlayLayer.ABOVE_MAP - && client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT) != null - && !client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT).isHidden()) - { - return; - } - - final List overlays = overlayManager.getLayer(layer); - - if (overlays == null - || overlays.isEmpty() - || client.getGameState() != GameState.LOGGED_IN - || client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null - || client.getViewportWidget() == null) - { - return; - } - - if (shouldInvalidateBounds()) - { - snapCorners = buildSnapCorners(); - } - - // Create copy of snap corners because overlays will modify them - OverlayBounds snapCorners = new OverlayBounds(this.snapCorners); - OverlayUtil.setGraphicProperties(graphics); - - // Draw snap corners - if (layer == OverlayLayer.UNDER_WIDGETS && movedOverlay != null && movedOverlay.getPosition() != OverlayPosition.DETACHED) - { - final OverlayBounds translatedSnapCorners = snapCorners.translated( - -SNAP_CORNER_SIZE.width, - -SNAP_CORNER_SIZE.height); - - final Color previous = graphics.getColor(); - - for (final Rectangle corner : translatedSnapCorners.getBounds()) - { - graphics.setColor(corner.contains(mousePosition) ? SNAP_CORNER_ACTIVE_COLOR : SNAP_CORNER_COLOR); - graphics.fill(corner); - } - - graphics.setColor(previous); - } - - // Get mouse position - final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition(); - final Point mouse = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY()); - - for (Overlay overlay : overlays) - { - OverlayPosition overlayPosition = overlay.getPosition(); - - if (overlay.getPreferredPosition() != null) - { - overlayPosition = overlay.getPreferredPosition(); - } - - if (!isResizeable) - { - // On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as - // BOTTOM_RIGHT and CANVAST_TOP_RIGHT is same as TOP_RIGHT. - // Just use BOTTOM_RIGHT and TOP_RIGHT to prevent overlays from - // drawing over each other. - switch (overlayPosition) - { - case CANVAS_TOP_RIGHT: - overlayPosition = OverlayPosition.TOP_RIGHT; - break; - case ABOVE_CHATBOX_RIGHT: - overlayPosition = OverlayPosition.BOTTOM_RIGHT; - break; - } - } - - if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) - { - safeRender(client, overlay, layer, graphics, new Point()); - } - else - { - final Point location = overlay.getBounds().getLocation(); - final Dimension dimension = overlay.getBounds().getSize(); - - // If the final position is not modified, layout it - if (overlayPosition != OverlayPosition.DETACHED && (overlay.getPreferredLocation() == null || overlay.getPreferredPosition() != null)) - { - final Rectangle snapCorner = snapCorners.forPosition(overlayPosition); - final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); - location.setLocation(snapCorner.getX() + translation.x, snapCorner.getY() + translation.y); - final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING); - snapCorner.translate(padding.x, padding.y); - } - else - { - final Point preferredLocation = overlay.getPreferredLocation(); - - if (preferredLocation != null) - { - location.setLocation(preferredLocation); - } - - final Dimension realDimensions = client.getRealDimensions(); - location.x = Ints.constrainToRange(location.x, 0, Math.max(0, realDimensions.width - dimension.width)); - location.y = Ints.constrainToRange(location.y, 0, Math.max(0, realDimensions.height - dimension.height)); - } - - if (overlay.getPreferredSize() != null) - { - overlay.getBounds().setSize(overlay.getPreferredSize()); - } - - safeRender(client, overlay, layer, graphics, location); - final Rectangle bounds = overlay.getBounds(); - - if (bounds.isEmpty()) - { - continue; - } - - if (inOverlayDraggingMode) - { - final Color previous = graphics.getColor(); - graphics.setColor(movedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR); - graphics.draw(bounds); - graphics.setColor(previous); - } - - if (menuEntries == null && !client.isMenuOpen() && bounds.contains(mouse)) - { - menuEntries = createRightClickMenuEntries(overlay); - } - } - } - } - - @Override - public MouseEvent mousePressed(MouseEvent mouseEvent) - { - if (!inOverlayDraggingMode) - { - return mouseEvent; - } - - final Point mousePoint = mouseEvent.getPoint(); - mousePosition.setLocation(mousePoint); - - synchronized (overlayManager) - { - for (Overlay overlay : overlayManager.getOverlays()) - { - if (overlay.getBounds().contains(mousePoint)) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - overlayManager.resetOverlay(overlay); - } - else - { - final Point offset = new Point(mousePoint.x, mousePoint.y); - offset.translate(-overlay.getBounds().x, -overlay.getBounds().y); - overlayOffset.setLocation(offset); - - mousePoint.translate(-offset.x, -offset.y); - movedOverlay = overlay; - movedOverlay.setPreferredPosition(null); - movedOverlay.setPreferredLocation(mousePoint); - overlayManager.saveOverlay(movedOverlay); - } - - mouseEvent.consume(); - break; - } - } - } - - return mouseEvent; - } - - @Override - public MouseEvent mouseDragged(MouseEvent mouseEvent) - { - if (!inOverlayDraggingMode) - { - return mouseEvent; - } - - final Point mousePoint = mouseEvent.getPoint(); - mousePosition.setLocation(mousePoint); - final Rectangle canvasRect = new Rectangle(client.getRealDimensions()); - - if (!canvasRect.contains(mousePoint)) - { - return mouseEvent; - } - - if (movedOverlay != null) - { - final Dimension realDimension = client.getRealDimensions(); - mousePoint.translate(-overlayOffset.x, -overlayOffset.y); - mousePoint.x = Ints.constrainToRange(mousePoint.x, 0, Math.max(0, realDimension.width - movedOverlay.getBounds().width)); - mousePoint.y = Ints.constrainToRange(mousePoint.y, 0, Math.max(0, realDimension.height - movedOverlay.getBounds().height)); - movedOverlay.setPreferredPosition(null); - movedOverlay.setPreferredLocation(mousePoint); - mouseEvent.consume(); - } - - return mouseEvent; - } - - @Override - public MouseEvent mouseReleased(MouseEvent mouseEvent) - { - if (movedOverlay != null) - { - mousePosition.setLocation(-1, -1); - - // do not snapcorner detached overlays - if (movedOverlay.getPosition() != OverlayPosition.DETACHED) - { - final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height); - - for (Rectangle snapCorner : snapCorners.getBounds()) - { - if (snapCorner.contains(mouseEvent.getPoint())) - { - OverlayPosition position = snapCorners.fromBounds(snapCorner); - - if (position == movedOverlay.getPosition()) - { - // overlay moves back to default position - position = null; - } - - movedOverlay.setPreferredPosition(position); - movedOverlay.setPreferredLocation(null); // from dragging - break; - } - } - } - - overlayManager.saveOverlay(movedOverlay); - movedOverlay = null; - mouseEvent.consume(); - } - - return mouseEvent; - } - - @Override - public void keyTyped(KeyEvent e) - { - } - - @Override - public void keyPressed(KeyEvent e) - { - if (e.isAltDown()) - { - inOverlayDraggingMode = true; - } - - if (e.isShiftDown() && runeLiteConfig.menuEntryShift()) - { - inMenuEntryMode = true; - } - } - - @Override - public void keyReleased(KeyEvent e) - { - if (!e.isAltDown()) - { - inOverlayDraggingMode = false; - } - - if (!e.isShiftDown()) - { - inMenuEntryMode = false; - } - } - - private void safeRender(Client client, Overlay overlay, OverlayLayer layer, Graphics2D graphics, Point point) - { - final Graphics2D subGraphics = (Graphics2D) graphics.create(); - - if (!isResizeable && (layer == OverlayLayer.ABOVE_SCENE || layer == OverlayLayer.UNDER_WIDGETS)) - { - subGraphics.setClip(client.getViewportXOffset(), - client.getViewportYOffset(), - client.getViewportWidth(), - client.getViewportHeight()); - } - - final OverlayPosition position = overlay.getPosition(); - - // Set font based on configuration - if (position == OverlayPosition.DYNAMIC || position == OverlayPosition.DETACHED) - { - subGraphics.setFont(runeLiteConfig.fontType().getFont()); - } - else if (position == OverlayPosition.TOOLTIP) - { - subGraphics.setFont(runeLiteConfig.tooltipFontType().getFont()); - } - else - { - subGraphics.setFont(runeLiteConfig.interfaceFontType().getFont()); - } - - subGraphics.translate(point.x, point.y); - final Dimension dimension = MoreObjects.firstNonNull(overlay.render(subGraphics), new Dimension()); - subGraphics.dispose(); - overlay.setBounds(new Rectangle(point, dimension)); - } - - private boolean shouldInvalidateBounds() - { - final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX); - final boolean resizeableChanged = isResizeable != client.isResized(); - boolean changed = false; - - if (resizeableChanged) - { - isResizeable = client.isResized(); - changed = true; - } - - final boolean chatboxBoundsChanged = chatbox == null || !chatbox.getBounds().equals(chatboxBounds); - - if (chatboxBoundsChanged) - { - chatboxBounds = chatbox != null ? chatbox.getBounds() : new Rectangle(); - changed = true; - } - - final boolean chatboxHiddenChanged = chatboxHidden != (chatbox == null || chatbox.isHidden()); - - if (chatboxHiddenChanged) - { - chatboxHidden = chatbox == null || chatbox.isHidden(); - changed = true; - } - - final boolean viewportChanged = !client.getViewportWidget().getBounds().equals(viewportBounds); - - if (viewportChanged) - { - viewportBounds = client.getViewportWidget().getBounds(); - changed = true; - } - - final boolean viewportOffsetChanged = client.getViewportXOffset() != viewportOffset; - - if (viewportOffsetChanged) - { - viewportOffset = client.getViewportXOffset(); - changed = true; - } - - return changed; - } - - private OverlayBounds buildSnapCorners() - { - final Point topLeftPoint = new Point( - viewportOffset + BORDER, - viewportOffset + BORDER_TOP); - - final Point topCenterPoint = new Point( - viewportOffset + viewportBounds.width / 2, - viewportOffset + BORDER - ); - - final Point topRightPoint = new Point( - viewportOffset + viewportBounds.width - BORDER, - topCenterPoint.y); - - final Point bottomLeftPoint = new Point( - topLeftPoint.x, - viewportOffset + viewportBounds.height - BORDER); - - final Point bottomRightPoint = new Point( - topRightPoint.x, - bottomLeftPoint.y); - - // Check to see if chat box is minimized - if (isResizeable && chatboxHidden) - { - bottomLeftPoint.y += chatboxBounds.height; - } - - final Point rightChatboxPoint = isResizeable ? new Point( - viewportOffset + chatboxBounds.width - BORDER, - bottomLeftPoint.y) : bottomRightPoint; - - final Point canvasTopRightPoint = isResizeable ? new Point( - (int)client.getRealDimensions().getWidth(), - 0) : topRightPoint; - - return new OverlayBounds( - new Rectangle(topLeftPoint, SNAP_CORNER_SIZE), - new Rectangle(topCenterPoint, SNAP_CORNER_SIZE), - new Rectangle(topRightPoint, SNAP_CORNER_SIZE), - new Rectangle(bottomLeftPoint, SNAP_CORNER_SIZE), - new Rectangle(bottomRightPoint, SNAP_CORNER_SIZE), - new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE), - new Rectangle(canvasTopRightPoint, SNAP_CORNER_SIZE)); - } - - private MenuEntry[] createRightClickMenuEntries(Overlay overlay) - { - List menuEntries = overlay.getMenuEntries(); - final MenuEntry[] entries = new MenuEntry[menuEntries.size()]; - - // Add in reverse order so they display correctly in the right-click menu - for (int i = menuEntries.size() - 1; i >= 0; --i) - { - OverlayMenuEntry overlayMenuEntry = menuEntries.get(i); - - final MenuEntry entry = new MenuEntry(); - entry.setOption(overlayMenuEntry.getOption()); - entry.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET)); - entry.setType(MenuAction.RUNELITE_OVERLAY.getId()); - entry.setIdentifier(overlayManager.getOverlays().indexOf(overlay)); // overlay id - - entries[i] = entry; - } - - return entries; - } -} +/* + * Copyright (c) 2016-2017, Adam + * 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.ui.overlay; + +import com.google.common.base.MoreObjects; +import com.google.common.primitives.Ints; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.swing.SwingUtilities; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.events.BeforeRender; +import net.runelite.api.events.ClientTick; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseAdapter; +import net.runelite.client.input.MouseManager; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.util.ColorUtil; + +@Singleton +public class OverlayRenderer extends MouseAdapter implements KeyListener +{ + private static final int BORDER = 5; + private static final int BORDER_TOP = BORDER + 15; + private static final int PADDING = 2; + private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80); + private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50); + private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100); + private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100); + private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200); + private final Client client; + private final OverlayManager overlayManager; + private final RuneLiteConfig runeLiteConfig; + + // Overlay movement variables + private final Point overlayOffset = new Point(); + private final Point mousePosition = new Point(); + private Overlay movedOverlay; + private boolean inOverlayDraggingMode; + private boolean inMenuEntryMode; + private MenuEntry[] menuEntries; + + // Overlay state validation + private Rectangle viewportBounds; + private Rectangle chatboxBounds; + private int viewportOffset; + private boolean chatboxHidden; + private boolean isResizeable; + private OverlayBounds snapCorners; + + @Inject + private OverlayRenderer( + final Client client, + final OverlayManager overlayManager, + final RuneLiteConfig runeLiteConfig, + final MouseManager mouseManager, + final KeyManager keyManager) + { + this.client = client; + this.overlayManager = overlayManager; + this.runeLiteConfig = runeLiteConfig; + keyManager.registerKeyListener(this); + mouseManager.registerMouseListener(this); + } + + @Subscribe + public void onFocusChanged(FocusChanged event) + { + if (!event.isFocused()) + { + inOverlayDraggingMode = false; + inMenuEntryMode = false; + menuEntries = null; + } + } + + @Subscribe + protected void onClientTick(ClientTick t) + { + if (menuEntries == null) + { + return; + } + + if (!inMenuEntryMode && runeLiteConfig.menuEntryShift()) + { + return; + } + + if (client.isMenuOpen()) + { + return; + } + + MenuEntry[] clientMenuEntries = client.getMenuEntries(); + MenuEntry[] newEntries = new MenuEntry[clientMenuEntries.length + menuEntries.length]; + + newEntries[0] = clientMenuEntries[0]; // Keep cancel at 0 + System.arraycopy(menuEntries, 0, newEntries, 1, menuEntries.length); // Add overlay menu entries + System.arraycopy(clientMenuEntries, 1, newEntries, menuEntries.length + 1, clientMenuEntries.length - 1); // Add remaining menu entries + client.setMenuEntries(newEntries); + } + + @Subscribe + public void onBeforeRender(BeforeRender event) + { + menuEntries = null; + } + + public void render(Graphics2D graphics, final OverlayLayer layer) + { + if (layer != OverlayLayer.ABOVE_MAP + && client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT) != null + && !client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT).isHidden()) + { + return; + } + + final List overlays = overlayManager.getLayer(layer); + + if (overlays == null + || overlays.isEmpty() + || client.getGameState() != GameState.LOGGED_IN + || client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null + || client.getViewportWidget() == null) + { + return; + } + + if (shouldInvalidateBounds()) + { + snapCorners = buildSnapCorners(); + } + + // Create copy of snap corners because overlays will modify them + OverlayBounds snapCorners = new OverlayBounds(this.snapCorners); + OverlayUtil.setGraphicProperties(graphics); + + // Draw snap corners + if (layer == OverlayLayer.UNDER_WIDGETS && movedOverlay != null && movedOverlay.getPosition() != OverlayPosition.DETACHED) + { + final OverlayBounds translatedSnapCorners = snapCorners.translated( + -SNAP_CORNER_SIZE.width, + -SNAP_CORNER_SIZE.height); + + final Color previous = graphics.getColor(); + + for (final Rectangle corner : translatedSnapCorners.getBounds()) + { + graphics.setColor(corner.contains(mousePosition) ? SNAP_CORNER_ACTIVE_COLOR : SNAP_CORNER_COLOR); + graphics.fill(corner); + } + + graphics.setColor(previous); + } + + // Get mouse position + final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition(); + final Point mouse = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY()); + + for (Overlay overlay : overlays) + { + OverlayPosition overlayPosition = overlay.getPosition(); + + if (overlay.getPreferredPosition() != null) + { + overlayPosition = overlay.getPreferredPosition(); + } + + if (!isResizeable) + { + // On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as + // BOTTOM_RIGHT and CANVAST_TOP_RIGHT is same as TOP_RIGHT. + // Just use BOTTOM_RIGHT and TOP_RIGHT to prevent overlays from + // drawing over each other. + switch (overlayPosition) + { + case CANVAS_TOP_RIGHT: + overlayPosition = OverlayPosition.TOP_RIGHT; + break; + case ABOVE_CHATBOX_RIGHT: + overlayPosition = OverlayPosition.BOTTOM_RIGHT; + break; + } + } + + if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) + { + safeRender(client, overlay, layer, graphics, new Point()); + } + else + { + final Point location = overlay.getBounds().getLocation(); + final Dimension dimension = overlay.getBounds().getSize(); + + // If the final position is not modified, layout it + if (overlayPosition != OverlayPosition.DETACHED && (overlay.getPreferredLocation() == null || overlay.getPreferredPosition() != null)) + { + final Rectangle snapCorner = snapCorners.forPosition(overlayPosition); + final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); + location.setLocation(snapCorner.getX() + translation.x, snapCorner.getY() + translation.y); + final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING); + snapCorner.translate(padding.x, padding.y); + } + else + { + final Point preferredLocation = overlay.getPreferredLocation(); + + if (preferredLocation != null) + { + location.setLocation(preferredLocation); + } + + final Dimension realDimensions = client.getRealDimensions(); + location.x = Ints.constrainToRange(location.x, 0, Math.max(0, realDimensions.width - dimension.width)); + location.y = Ints.constrainToRange(location.y, 0, Math.max(0, realDimensions.height - dimension.height)); + } + + if (overlay.getPreferredSize() != null) + { + overlay.getBounds().setSize(overlay.getPreferredSize()); + } + + safeRender(client, overlay, layer, graphics, location); + final Rectangle bounds = overlay.getBounds(); + + if (bounds.isEmpty()) + { + continue; + } + + if (inOverlayDraggingMode) + { + final Color previous = graphics.getColor(); + graphics.setColor(movedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR); + graphics.draw(bounds); + graphics.setColor(previous); + } + + if (menuEntries == null && !client.isMenuOpen() && bounds.contains(mouse)) + { + menuEntries = createRightClickMenuEntries(overlay); + } + } + } + } + + @Override + public MouseEvent mousePressed(MouseEvent mouseEvent) + { + if (!inOverlayDraggingMode) + { + return mouseEvent; + } + + final Point mousePoint = mouseEvent.getPoint(); + mousePosition.setLocation(mousePoint); + + synchronized (overlayManager) + { + for (Overlay overlay : overlayManager.getOverlays()) + { + if (overlay.getBounds().contains(mousePoint)) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + overlayManager.resetOverlay(overlay); + } + else + { + final Point offset = new Point(mousePoint.x, mousePoint.y); + offset.translate(-overlay.getBounds().x, -overlay.getBounds().y); + overlayOffset.setLocation(offset); + + mousePoint.translate(-offset.x, -offset.y); + movedOverlay = overlay; + movedOverlay.setPreferredPosition(null); + movedOverlay.setPreferredLocation(mousePoint); + overlayManager.saveOverlay(movedOverlay); + } + + mouseEvent.consume(); + break; + } + } + } + + return mouseEvent; + } + + @Override + public MouseEvent mouseDragged(MouseEvent mouseEvent) + { + if (!inOverlayDraggingMode) + { + return mouseEvent; + } + + final Point mousePoint = mouseEvent.getPoint(); + mousePosition.setLocation(mousePoint); + final Rectangle canvasRect = new Rectangle(client.getRealDimensions()); + + if (!canvasRect.contains(mousePoint)) + { + return mouseEvent; + } + + if (movedOverlay != null) + { + final Dimension realDimension = client.getRealDimensions(); + mousePoint.translate(-overlayOffset.x, -overlayOffset.y); + mousePoint.x = Ints.constrainToRange(mousePoint.x, 0, Math.max(0, realDimension.width - movedOverlay.getBounds().width)); + mousePoint.y = Ints.constrainToRange(mousePoint.y, 0, Math.max(0, realDimension.height - movedOverlay.getBounds().height)); + movedOverlay.setPreferredPosition(null); + movedOverlay.setPreferredLocation(mousePoint); + mouseEvent.consume(); + } + + return mouseEvent; + } + + @Override + public MouseEvent mouseReleased(MouseEvent mouseEvent) + { + if (movedOverlay != null) + { + mousePosition.setLocation(-1, -1); + + // do not snapcorner detached overlays + if (movedOverlay.getPosition() != OverlayPosition.DETACHED) + { + final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height); + + for (Rectangle snapCorner : snapCorners.getBounds()) + { + if (snapCorner.contains(mouseEvent.getPoint())) + { + OverlayPosition position = snapCorners.fromBounds(snapCorner); + + if (position == movedOverlay.getPosition()) + { + // overlay moves back to default position + position = null; + } + + movedOverlay.setPreferredPosition(position); + movedOverlay.setPreferredLocation(null); // from dragging + break; + } + } + } + + overlayManager.saveOverlay(movedOverlay); + movedOverlay = null; + mouseEvent.consume(); + } + + return mouseEvent; + } + + @Override + public void keyTyped(KeyEvent e) + { + } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.isAltDown()) + { + inOverlayDraggingMode = true; + } + + if (e.isShiftDown() && runeLiteConfig.menuEntryShift()) + { + inMenuEntryMode = true; + } + } + + @Override + public void keyReleased(KeyEvent e) + { + if (!e.isAltDown()) + { + inOverlayDraggingMode = false; + } + + if (!e.isShiftDown()) + { + inMenuEntryMode = false; + } + } + + private void safeRender(Client client, Overlay overlay, OverlayLayer layer, Graphics2D graphics, Point point) + { + final Graphics2D subGraphics = (Graphics2D) graphics.create(); + + if (!isResizeable && (layer == OverlayLayer.ABOVE_SCENE || layer == OverlayLayer.UNDER_WIDGETS)) + { + subGraphics.setClip(client.getViewportXOffset(), + client.getViewportYOffset(), + client.getViewportWidth(), + client.getViewportHeight()); + } + + final OverlayPosition position = overlay.getPosition(); + + // Set font based on configuration + if (position == OverlayPosition.DYNAMIC || position == OverlayPosition.DETACHED) + { + subGraphics.setFont(runeLiteConfig.fontType().getFont()); + } + else if (position == OverlayPosition.TOOLTIP) + { + subGraphics.setFont(runeLiteConfig.tooltipFontType().getFont()); + } + else + { + subGraphics.setFont(runeLiteConfig.interfaceFontType().getFont()); + } + + subGraphics.translate(point.x, point.y); + final Dimension dimension = MoreObjects.firstNonNull(overlay.render(subGraphics), new Dimension()); + subGraphics.dispose(); + overlay.setBounds(new Rectangle(point, dimension)); + } + + private boolean shouldInvalidateBounds() + { + final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX); + final boolean resizeableChanged = isResizeable != client.isResized(); + boolean changed = false; + + if (resizeableChanged) + { + isResizeable = client.isResized(); + changed = true; + } + + final boolean chatboxBoundsChanged = chatbox == null || !chatbox.getBounds().equals(chatboxBounds); + + if (chatboxBoundsChanged) + { + chatboxBounds = chatbox != null ? chatbox.getBounds() : new Rectangle(); + changed = true; + } + + final boolean chatboxHiddenChanged = chatboxHidden != (chatbox == null || chatbox.isHidden()); + + if (chatboxHiddenChanged) + { + chatboxHidden = chatbox == null || chatbox.isHidden(); + changed = true; + } + + final boolean viewportChanged = !client.getViewportWidget().getBounds().equals(viewportBounds); + + if (viewportChanged) + { + viewportBounds = client.getViewportWidget().getBounds(); + changed = true; + } + + final boolean viewportOffsetChanged = client.getViewportXOffset() != viewportOffset; + + if (viewportOffsetChanged) + { + viewportOffset = client.getViewportXOffset(); + changed = true; + } + + return changed; + } + + private OverlayBounds buildSnapCorners() + { + final Point topLeftPoint = new Point( + viewportOffset + BORDER, + viewportOffset + BORDER_TOP); + + final Point topCenterPoint = new Point( + viewportOffset + viewportBounds.width / 2, + viewportOffset + BORDER + ); + + final Point topRightPoint = new Point( + viewportOffset + viewportBounds.width - BORDER, + topCenterPoint.y); + + final Point bottomLeftPoint = new Point( + topLeftPoint.x, + viewportOffset + viewportBounds.height - BORDER); + + final Point bottomRightPoint = new Point( + topRightPoint.x, + bottomLeftPoint.y); + + // Check to see if chat box is minimized + if (isResizeable && chatboxHidden) + { + bottomLeftPoint.y += chatboxBounds.height; + } + + final Point rightChatboxPoint = isResizeable ? new Point( + viewportOffset + chatboxBounds.width - BORDER, + bottomLeftPoint.y) : bottomRightPoint; + + final Point canvasTopRightPoint = isResizeable ? new Point( + (int) client.getRealDimensions().getWidth(), + 0) : topRightPoint; + + return new OverlayBounds( + new Rectangle(topLeftPoint, SNAP_CORNER_SIZE), + new Rectangle(topCenterPoint, SNAP_CORNER_SIZE), + new Rectangle(topRightPoint, SNAP_CORNER_SIZE), + new Rectangle(bottomLeftPoint, SNAP_CORNER_SIZE), + new Rectangle(bottomRightPoint, SNAP_CORNER_SIZE), + new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE), + new Rectangle(canvasTopRightPoint, SNAP_CORNER_SIZE)); + } + + private MenuEntry[] createRightClickMenuEntries(Overlay overlay) + { + List menuEntries = overlay.getMenuEntries(); + final MenuEntry[] entries = new MenuEntry[menuEntries.size()]; + + // Add in reverse order so they display correctly in the right-click menu + for (int i = menuEntries.size() - 1; i >= 0; --i) + { + OverlayMenuEntry overlayMenuEntry = menuEntries.get(i); + + final MenuEntry entry = new MenuEntry(); + entry.setOption(overlayMenuEntry.getOption()); + entry.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET)); + entry.setType(MenuAction.RUNELITE_OVERLAY.getId()); + entry.setIdentifier(overlayManager.getOverlays().indexOf(overlay)); // overlay id + + entries[i] = entry; + } + + return entries; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index bf3d0a3bc2..581977218c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -37,7 +37,6 @@ import java.awt.image.BufferedImage; import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.Perspective; -import net.runelite.api.Player; import net.runelite.api.Point; import net.runelite.api.TileObject; import net.runelite.api.coords.LocalPoint; @@ -77,7 +76,7 @@ public class OverlayUtil graphics.setColor(color); graphics.rotate(angle, center.getX(), center.getY()); graphics.drawRect(center.getX() - width / 2, center.getY() - height / 2, width, height); - graphics.rotate(-angle , center.getX(), center.getY()); + graphics.rotate(-angle, center.getX(), center.getY()); } public static void renderTextLocation(Graphics2D graphics, Point txtLoc, String text, Color color) @@ -259,13 +258,13 @@ public class OverlayUtil return result; } - + public static void renderActorTextAndImage(Graphics2D graphics, Actor actor, String text, Color color, - BufferedImage image, int yOffset, int xOffset) + BufferedImage image, int yOffset, int xOffset) { Point textLocation = new Point(actor.getConvexHull().getBounds().x + xOffset, - actor.getConvexHull().getBounds().y + yOffset); - + actor.getConvexHull().getBounds().y + yOffset); + renderImageLocation(graphics, textLocation, image); xOffset = image.getWidth() + 1; yOffset = (image.getHeight() - (int) graphics.getFontMetrics().getStringBounds(text, graphics).getHeight()); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java index 00f894bf58..68ece82079 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java @@ -101,8 +101,8 @@ public class WidgetOverlay extends Overlay int y = bounds.y; x = Math.max(parent.x, x); y = Math.max(parent.y, y); - x = Math.min((int)parent.getMaxX() - bounds.width, x); - y = Math.min((int)parent.getMaxY() - bounds.height, y); + x = Math.min((int) parent.getMaxX() - bounds.width, x); + y = Math.min((int) parent.getMaxY() - bounds.height, y); bounds.setLocation(x, y); return bounds; } @@ -123,8 +123,8 @@ public class WidgetOverlay extends Overlay int y = bounds.y; x = Math.max(parent.x, x); y = Math.max(parent.y, y); - x = Math.min((int)parent.getMaxX() - bounds.width, x); - y = Math.min((int)parent.getMaxY() - bounds.height, y); + x = Math.min((int) parent.getMaxX() - bounds.width, x); + y = Math.min((int) parent.getMaxY() - bounds.height, y); bounds.setLocation(x, y); widget.setOriginalX(0); widget.setOriginalY(0); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java index 2dccd96dc7..3d503e5858 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java @@ -200,10 +200,7 @@ public class ArrowMinimapOverlay extends Overlay localPoint = new LocalPoint(localPoint.getX() + 1, localPoint.getY() + 1); } } - else - { - localPoint = npc.getLocalLocation(); - } + localPoint = null; renderMinimapArrow(graphics, arrowPoint, localPoint, localPlayerPos, worldPlayerPos); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java index 36e547d389..13cbf0b418 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java @@ -1,61 +1,59 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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.ui.overlay.arrow; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import javax.inject.Singleton; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.events.NpcSpawned; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; - -@Singleton -public class ArrowPointManager -{ - @Getter(AccessLevel.PACKAGE) - private final Multimap arrowPoints = HashMultimap.create(); - - public void add(Plugin plugin, ArrowPoint arrowPoint) - { - arrowPoints.put(plugin, arrowPoint); - } - - public void remove(Plugin plugin, ArrowPoint arrowPoint) - { - arrowPoints.remove(plugin, arrowPoint); - } - - public void clear(Plugin plugin) - { - arrowPoints.removeAll(plugin); - } - - public void clear() - { - arrowPoints.clear(); - } +/* + * Copyright (c) 2018, Morgan Lewis + * 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.ui.overlay.arrow; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import javax.inject.Singleton; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.client.plugins.Plugin; + +@Singleton +public class ArrowPointManager +{ + @Getter(AccessLevel.PACKAGE) + private final Multimap arrowPoints = HashMultimap.create(); + + public void add(Plugin plugin, ArrowPoint arrowPoint) + { + arrowPoints.put(plugin, arrowPoint); + } + + public void remove(Plugin plugin, ArrowPoint arrowPoint) + { + arrowPoints.remove(plugin, arrowPoint); + } + + public void clear(Plugin plugin) + { + arrowPoints.removeAll(plugin); + } + + public void clear() + { + arrowPoints.clear(); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java index 34a19d1469..6a6f52ce95 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2017, Tomas Slusny - * 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.ui.overlay.components; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; -import lombok.Setter; -import net.runelite.client.ui.overlay.RenderableEntity; - -@NoArgsConstructor -@AllArgsConstructor -@Setter -public class BackgroundComponent implements RenderableEntity -{ - private static final int BORDER_OFFSET = 2; - - private static final int OUTSIDE_STROKE_RED_OFFSET = 14; - private static final int OUTSIDE_STROKE_GREEN_OFFSET = 13; - private static final int OUTSIDE_STROKE_BLUE_OFFSET = 15; - private static final int OUTSIDE_STROKE_ALPHA = 255; - - private static final int INSIDE_STROKE_RED_OFFSET = 20; - private static final int INSIDE_STROKE_GREEN_OFFSET = 21; - private static final int INSIDE_STROKE_BLUE_OFFSET = 19; - private static final int INSIDE_STROKE_ALPHA = 255; - - private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; - private Rectangle rectangle = new Rectangle(); - private boolean fill = true; - - @Override - public Dimension render(Graphics2D graphics) - { - Color outsideStrokeColor = new Color( - Math.max(0, backgroundColor.getRed() - OUTSIDE_STROKE_RED_OFFSET), - Math.max(0, backgroundColor.getGreen() - OUTSIDE_STROKE_GREEN_OFFSET), - Math.max(0, backgroundColor.getBlue() - OUTSIDE_STROKE_BLUE_OFFSET), - OUTSIDE_STROKE_ALPHA - ); - - Color insideStrokeColor = new Color( - Math.min(255, backgroundColor.getRed() + INSIDE_STROKE_RED_OFFSET), - Math.min(255, backgroundColor.getGreen() + INSIDE_STROKE_GREEN_OFFSET), - Math.min(255, backgroundColor.getBlue() + INSIDE_STROKE_BLUE_OFFSET), - INSIDE_STROKE_ALPHA - ); - - // Render background - if (fill) - { - graphics.setColor(backgroundColor); - graphics.fill(rectangle); - } - - // Render outside stroke - final Rectangle outsideStroke = new Rectangle(); - outsideStroke.setLocation(rectangle.x, rectangle.y); - outsideStroke.setSize(rectangle.width - BORDER_OFFSET / 2, rectangle.height - BORDER_OFFSET / 2); - graphics.setColor(outsideStrokeColor); - graphics.draw(outsideStroke); - - // Render inside stroke - final Rectangle insideStroke = new Rectangle(); - insideStroke.setLocation(rectangle.x + BORDER_OFFSET / 2, rectangle.y + BORDER_OFFSET / 2); - insideStroke.setSize(rectangle.width - BORDER_OFFSET - BORDER_OFFSET / 2, - rectangle.height - BORDER_OFFSET - BORDER_OFFSET / 2); - graphics.setColor(insideStrokeColor); - graphics.draw(insideStroke); - - return new Dimension(rectangle.getSize()); - } -} +/* + * Copyright (c) 2017, Tomas Slusny + * 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.ui.overlay.components; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.runelite.client.ui.overlay.RenderableEntity; + +@NoArgsConstructor +@AllArgsConstructor +@Setter +public class BackgroundComponent implements RenderableEntity +{ + private static final int BORDER_OFFSET = 2; + + private static final int OUTSIDE_STROKE_RED_OFFSET = 14; + private static final int OUTSIDE_STROKE_GREEN_OFFSET = 13; + private static final int OUTSIDE_STROKE_BLUE_OFFSET = 15; + private static final int OUTSIDE_STROKE_ALPHA = 255; + + private static final int INSIDE_STROKE_RED_OFFSET = 20; + private static final int INSIDE_STROKE_GREEN_OFFSET = 21; + private static final int INSIDE_STROKE_BLUE_OFFSET = 19; + private static final int INSIDE_STROKE_ALPHA = 255; + + private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; + private Rectangle rectangle = new Rectangle(); + private boolean fill = true; + + @Override + public Dimension render(Graphics2D graphics) + { + Color outsideStrokeColor = new Color( + Math.max(0, backgroundColor.getRed() - OUTSIDE_STROKE_RED_OFFSET), + Math.max(0, backgroundColor.getGreen() - OUTSIDE_STROKE_GREEN_OFFSET), + Math.max(0, backgroundColor.getBlue() - OUTSIDE_STROKE_BLUE_OFFSET), + OUTSIDE_STROKE_ALPHA + ); + + Color insideStrokeColor = new Color( + Math.min(255, backgroundColor.getRed() + INSIDE_STROKE_RED_OFFSET), + Math.min(255, backgroundColor.getGreen() + INSIDE_STROKE_GREEN_OFFSET), + Math.min(255, backgroundColor.getBlue() + INSIDE_STROKE_BLUE_OFFSET), + INSIDE_STROKE_ALPHA + ); + + // Render background + if (fill) + { + graphics.setColor(backgroundColor); + graphics.fill(rectangle); + } + + // Render outside stroke + final Rectangle outsideStroke = new Rectangle(); + outsideStroke.setLocation(rectangle.x, rectangle.y); + outsideStroke.setSize(rectangle.width - BORDER_OFFSET / 2, rectangle.height - BORDER_OFFSET / 2); + graphics.setColor(outsideStrokeColor); + graphics.draw(outsideStroke); + + // Render inside stroke + final Rectangle insideStroke = new Rectangle(); + insideStroke.setLocation(rectangle.x + BORDER_OFFSET / 2, rectangle.y + BORDER_OFFSET / 2); + insideStroke.setSize(rectangle.width - BORDER_OFFSET - BORDER_OFFSET / 2, + rectangle.height - BORDER_OFFSET - BORDER_OFFSET / 2); + graphics.setColor(insideStrokeColor); + graphics.draw(insideStroke); + + return new Dimension(rectangle.getSize()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java index 7a736686d0..6858fbab8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java @@ -1,37 +1,39 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * 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.ui.overlay.components; - -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import net.runelite.client.ui.overlay.RenderableEntity; - -public interface LayoutableRenderableEntity extends RenderableEntity -{ - Rectangle getBounds(); - void setPreferredLocation(Point position); - void setPreferredSize(Dimension dimension); -} +/* + * Copyright (c) 2018, Tomas Slusny + * 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.ui.overlay.components; + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import net.runelite.client.ui.overlay.RenderableEntity; + +public interface LayoutableRenderableEntity extends RenderableEntity +{ + Rectangle getBounds(); + + void setPreferredLocation(Point position); + + void setPreferredSize(Dimension dimension); +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java index a792dbda14..3eda960450 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java @@ -61,10 +61,10 @@ public class PanelComponent implements LayoutableRenderableEntity @Setter private Rectangle border = new Rectangle( - ComponentConstants.STANDARD_BORDER, - ComponentConstants.STANDARD_BORDER, - ComponentConstants.STANDARD_BORDER, - ComponentConstants.STANDARD_BORDER); + ComponentConstants.STANDARD_BORDER, + ComponentConstants.STANDARD_BORDER, + ComponentConstants.STANDARD_BORDER, + ComponentConstants.STANDARD_BORDER); @Setter private Point gap = new Point(0, 0); @@ -81,8 +81,8 @@ public class PanelComponent implements LayoutableRenderableEntity // Calculate panel dimension final Dimension dimension = new Dimension( - border.x + childDimensions.width + border.width, - border.y + childDimensions.height + border.height); + border.x + childDimensions.width + border.width, + border.y + childDimensions.height + border.height); // Render background if (backgroundColor != null) @@ -103,15 +103,15 @@ public class PanelComponent implements LayoutableRenderableEntity // Create child preferred size final Dimension childPreferredSize = new Dimension( - preferredSize.width - border.x - border.width, - preferredSize.height - border.y - border.height); + preferredSize.width - border.x - border.width, + preferredSize.height - border.y - border.height); // Calculate max width/height for infoboxes int totalHeight = 0; int totalWidth = 0; // Render all children - for (int i = 0; i < children.size(); i ++) + for (int i = 0; i < children.size(); i++) { final LayoutableRenderableEntity child = children.get(i); child.setPreferredLocation(new Point(x, y)); @@ -136,7 +136,7 @@ public class PanelComponent implements LayoutableRenderableEntity totalWidth = Math.max(totalWidth, width); totalHeight = Math.max(totalHeight, height); - if (wrapping > 0 && i < children.size() - 1 && (i + 1) % wrapping == 0) + if (wrapping > 0 && i < children.size() - 1 && (i + 1) % wrapping == 0) { switch (orientation) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java index c7c5381b86..b81ede1f43 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java @@ -1,220 +1,220 @@ -/* - * Copyright (c) 2016-2017, Adam - * 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.ui.overlay.components; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.util.regex.Pattern; -import lombok.Setter; -import net.runelite.api.IndexedSprite; -import net.runelite.client.ui.overlay.RenderableEntity; - -@Setter -public class TooltipComponent implements RenderableEntity -{ - private static final Pattern BR = Pattern.compile("
"); - private static final int OFFSET = 4; - private static final int MOD_ICON_WIDTH = 13; // they are generally 13px wide - - private String text; - private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; - private Point position = new Point(); - private IndexedSprite[] modIcons; - - @Override - public Dimension render(Graphics2D graphics) - { - // Tooltip size - final FontMetrics metrics = graphics.getFontMetrics(); - final int textDescent = metrics.getDescent(); - final int textHeight = metrics.getHeight(); - int tooltipWidth = 0; - int tooltipHeight = 0; - String[] lines = BR.split(text); - - // Calculate tooltip size - for (String line : lines) - { - int textWidth = calculateTextWidth(metrics, line); - - if (textWidth > tooltipWidth) - { - tooltipWidth = textWidth; - } - - tooltipHeight += textHeight; - } - - // Tooltip position - int x = position.x; - int y = position.y; - - // Render tooltip - background - final Rectangle tooltipBackground = new Rectangle(x, y, - tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); - final BackgroundComponent backgroundComponent = new BackgroundComponent(); - backgroundComponent.setBackgroundColor(backgroundColor); - backgroundComponent.setRectangle(tooltipBackground); - backgroundComponent.render(graphics); - graphics.setColor(Color.WHITE); - - // Render tooltip - text - line by line - int textX = x + OFFSET; - int textY = y + OFFSET; - int lineX; - Color nextColor = Color.WHITE; - for (int i = 0; i < lines.length; i++) - { - lineX = textX; - final String line = lines[i]; - char[] chars = line.toCharArray(); - - int begin = 0; - for (int j = 0; j < chars.length; j++) - { - if (chars[j] == '<') - { - TextComponent textComponent = new TextComponent(); - textComponent.setColor(nextColor); - String text = line.substring(begin, j); - textComponent.setText(text); - textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); - textComponent.render(graphics); - - lineX += metrics.stringWidth(text); - - begin = j; - } - else if (chars[j] == '>') - { - String subLine = line.substring(begin + 1, j); - - if (subLine.startsWith("col=")) - { - String argument = subLine.substring(4); - nextColor = Color.decode("#" + argument); - } - else if (subLine.equals("/col")) - { - nextColor = Color.WHITE; - } - else if (subLine.startsWith("img=")) - { - if (modIcons != null) - { - String argument = subLine.substring(4); - int iconId = Integer.parseInt(argument); - IndexedSprite modIcon = modIcons[iconId]; - renderModIcon(graphics, lineX, textY + i * textHeight - textDescent, modIcon); - lineX += modIcon.getWidth(); - } - } - else - { - TextComponent textComponent = new TextComponent(); - textComponent.setColor(nextColor); - String text = line.substring(begin, j + 1); - textComponent.setText(text); - textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); - textComponent.render(graphics); - - lineX += metrics.stringWidth(text); - } - - begin = j + 1; - } - } - - // Draw trailing text (after last tag) - final TextComponent textComponent = new TextComponent(); - textComponent.setColor(nextColor); - textComponent.setText(line.substring(begin, line.length())); - textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); - textComponent.render(graphics); - } - - return new Dimension(tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); - } - - private static int calculateTextWidth(FontMetrics metrics, String line) - { - char[] chars = line.toCharArray(); - int textWidth = 0; - - int begin = 0; - for (int j = 0; j < chars.length; j++) - { - if (chars[j] == '<') - { - textWidth += metrics.stringWidth(line.substring(begin, j)); - - begin = j; - } - else if (chars[j] == '>') - { - String subLine = line.substring(begin + 1, j); - - if (subLine.startsWith("img=")) - { - textWidth += MOD_ICON_WIDTH; - } - else if (!subLine.startsWith("col=") && !subLine.startsWith("/col")) - { - textWidth += metrics.stringWidth(line.substring(begin, j + 1)); - } - - begin = j + 1; - } - } - - // Include trailing text (after last tag) - textWidth += metrics.stringWidth(line.substring(begin, line.length())); - - return textWidth; - } - - private void renderModIcon(Graphics2D graphics, int x, int y, IndexedSprite modIcon) - { - int sourceOffset = 0; - - for (int y2 = 0; y2 < modIcon.getHeight(); y2++) - { - for (int x2 = 0; x2 < modIcon.getWidth(); x2++) - { - int index = modIcon.getPixels()[sourceOffset++] & 0xff; - - if (index != 0) - { - graphics.setColor(new Color(modIcon.getPalette()[index])); - graphics.drawLine(x + x2, y + y2, x + x2, y + y2); - } - } - } - } -} +/* + * Copyright (c) 2016-2017, Adam + * 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.ui.overlay.components; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.util.regex.Pattern; +import lombok.Setter; +import net.runelite.api.IndexedSprite; +import net.runelite.client.ui.overlay.RenderableEntity; + +@Setter +public class TooltipComponent implements RenderableEntity +{ + private static final Pattern BR = Pattern.compile("
"); + private static final int OFFSET = 4; + private static final int MOD_ICON_WIDTH = 13; // they are generally 13px wide + + private String text; + private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; + private Point position = new Point(); + private IndexedSprite[] modIcons; + + @Override + public Dimension render(Graphics2D graphics) + { + // Tooltip size + final FontMetrics metrics = graphics.getFontMetrics(); + final int textDescent = metrics.getDescent(); + final int textHeight = metrics.getHeight(); + int tooltipWidth = 0; + int tooltipHeight = 0; + String[] lines = BR.split(text); + + // Calculate tooltip size + for (String line : lines) + { + int textWidth = calculateTextWidth(metrics, line); + + if (textWidth > tooltipWidth) + { + tooltipWidth = textWidth; + } + + tooltipHeight += textHeight; + } + + // Tooltip position + int x = position.x; + int y = position.y; + + // Render tooltip - background + final Rectangle tooltipBackground = new Rectangle(x, y, + tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); + final BackgroundComponent backgroundComponent = new BackgroundComponent(); + backgroundComponent.setBackgroundColor(backgroundColor); + backgroundComponent.setRectangle(tooltipBackground); + backgroundComponent.render(graphics); + graphics.setColor(Color.WHITE); + + // Render tooltip - text - line by line + int textX = x + OFFSET; + int textY = y + OFFSET; + int lineX; + Color nextColor = Color.WHITE; + for (int i = 0; i < lines.length; i++) + { + lineX = textX; + final String line = lines[i]; + char[] chars = line.toCharArray(); + + int begin = 0; + for (int j = 0; j < chars.length; j++) + { + if (chars[j] == '<') + { + TextComponent textComponent = new TextComponent(); + textComponent.setColor(nextColor); + String text = line.substring(begin, j); + textComponent.setText(text); + textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); + textComponent.render(graphics); + + lineX += metrics.stringWidth(text); + + begin = j; + } + else if (chars[j] == '>') + { + String subLine = line.substring(begin + 1, j); + + if (subLine.startsWith("col=")) + { + String argument = subLine.substring(4); + nextColor = Color.decode("#" + argument); + } + else if (subLine.equals("/col")) + { + nextColor = Color.WHITE; + } + else if (subLine.startsWith("img=")) + { + if (modIcons != null) + { + String argument = subLine.substring(4); + int iconId = Integer.parseInt(argument); + IndexedSprite modIcon = modIcons[iconId]; + renderModIcon(graphics, lineX, textY + i * textHeight - textDescent, modIcon); + lineX += modIcon.getWidth(); + } + } + else + { + TextComponent textComponent = new TextComponent(); + textComponent.setColor(nextColor); + String text = line.substring(begin, j + 1); + textComponent.setText(text); + textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); + textComponent.render(graphics); + + lineX += metrics.stringWidth(text); + } + + begin = j + 1; + } + } + + // Draw trailing text (after last tag) + final TextComponent textComponent = new TextComponent(); + textComponent.setColor(nextColor); + textComponent.setText(line.substring(begin)); + textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); + textComponent.render(graphics); + } + + return new Dimension(tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); + } + + private static int calculateTextWidth(FontMetrics metrics, String line) + { + char[] chars = line.toCharArray(); + int textWidth = 0; + + int begin = 0; + for (int j = 0; j < chars.length; j++) + { + if (chars[j] == '<') + { + textWidth += metrics.stringWidth(line.substring(begin, j)); + + begin = j; + } + else if (chars[j] == '>') + { + String subLine = line.substring(begin + 1, j); + + if (subLine.startsWith("img=")) + { + textWidth += MOD_ICON_WIDTH; + } + else if (!subLine.startsWith("col=") && !subLine.startsWith("/col")) + { + textWidth += metrics.stringWidth(line.substring(begin, j + 1)); + } + + begin = j + 1; + } + } + + // Include trailing text (after last tag) + textWidth += metrics.stringWidth(line.substring(begin)); + + return textWidth; + } + + private void renderModIcon(Graphics2D graphics, int x, int y, IndexedSprite modIcon) + { + int sourceOffset = 0; + + for (int y2 = 0; y2 < modIcon.getHeight(); y2++) + { + for (int x2 = 0; x2 < modIcon.getWidth(); x2++) + { + int index = modIcon.getPixels()[sourceOffset++] & 0xff; + + if (index != 0) + { + graphics.setColor(new Color(modIcon.getPalette()[index])); + graphics.drawLine(x + x2, y + y2, x + x2, y + y2); + } + } + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java index 4fd1c1ca11..fc85fce6d6 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java @@ -1,166 +1,166 @@ -/* - * Copyright (c) 2017, Adam - * 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.ui.overlay.infobox; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ComparisonChain; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.function.Predicate; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.events.ConfigChanged; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.PluginDescriptor; - -@Singleton -@Slf4j -public class InfoBoxManager -{ - private final List infoBoxes = new ArrayList<>(); - private final RuneLiteConfig runeLiteConfig; - - @Inject - private InfoBoxManager(final RuneLiteConfig runeLiteConfig) - { - this.runeLiteConfig = runeLiteConfig; - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("runelite") && event.getKey().equals("infoBoxSize")) - { - infoBoxes.forEach(this::updateInfoBoxImage); - } - } - - public void addInfoBox(InfoBox infoBox) - { - Preconditions.checkNotNull(infoBox); - log.debug("Adding InfoBox {}", infoBox); - - updateInfoBoxImage(infoBox); - infoBoxes.add(infoBox); - refreshInfoBoxes(); - } - - public void removeInfoBox(InfoBox infoBox) - { - if (infoBoxes.remove(infoBox)) - { - log.debug("Removed InfoBox {}", infoBox); - refreshInfoBoxes(); - } - } - - public void removeIf(Predicate filter) - { - if (infoBoxes.removeIf(filter)) - { - log.debug("Removed InfoBoxes for filter {}", filter); - refreshInfoBoxes(); - } - } - - public List getInfoBoxes() - { - return Collections.unmodifiableList(infoBoxes); - } - - public void cull() - { - boolean culled = false; - for (Iterator it = infoBoxes.iterator(); it.hasNext();) - { - InfoBox box = it.next(); - - if (box.cull()) - { - log.debug("Culling InfoBox {}", box); - it.remove(); - culled = true; - } - } - - if (culled) - { - refreshInfoBoxes(); - } - } - - private void updateInfoBoxImage(final InfoBox infoBox) - { - if (infoBox.getImage() == null) - { - return; - } - - // Set scaled InfoBox image - final Image image = infoBox.getImage(); - Image resultImage = image; - final double width = image.getWidth(null); - final double height = image.getHeight(null); - final double size = Math.max(2, runeLiteConfig.infoBoxSize()); // Limit size to 2 as that is minimum size not causing breakage - - if (size < width || size < height) - { - final double scalex = size / width; - final double scaley = size / height; - - if (scalex == 1 && scaley == 1) - { - return; - } - - final double scale = Math.min(scalex, scaley); - final int newWidth = (int) (width * scale); - final int newHeight = (int) (height * scale); - final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); - final Graphics g = scaledImage.createGraphics(); - g.drawImage(image, 0, 0, newWidth, newHeight, null); - g.dispose(); - resultImage = scaledImage; - } - - infoBox.setScaledImage(resultImage); - } - - private void refreshInfoBoxes() - { - infoBoxes.sort((b1, b2) -> ComparisonChain - .start() - .compare(b1.getPriority(), b2.getPriority()) - .compare(b1.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name(), b2.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name()) - .result()); - } -} +/* + * Copyright (c) 2017, Adam + * 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.ui.overlay.infobox; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ComparisonChain; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.function.Predicate; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.events.ConfigChanged; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.PluginDescriptor; + +@Singleton +@Slf4j +public class InfoBoxManager +{ + private final List infoBoxes = new ArrayList<>(); + private final RuneLiteConfig runeLiteConfig; + + @Inject + private InfoBoxManager(final RuneLiteConfig runeLiteConfig) + { + this.runeLiteConfig = runeLiteConfig; + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("runelite") && event.getKey().equals("infoBoxSize")) + { + infoBoxes.forEach(this::updateInfoBoxImage); + } + } + + public void addInfoBox(InfoBox infoBox) + { + Preconditions.checkNotNull(infoBox); + log.debug("Adding InfoBox {}", infoBox); + + updateInfoBoxImage(infoBox); + infoBoxes.add(infoBox); + refreshInfoBoxes(); + } + + public void removeInfoBox(InfoBox infoBox) + { + if (infoBoxes.remove(infoBox)) + { + log.debug("Removed InfoBox {}", infoBox); + refreshInfoBoxes(); + } + } + + public void removeIf(Predicate filter) + { + if (infoBoxes.removeIf(filter)) + { + log.debug("Removed InfoBoxes for filter {}", filter); + refreshInfoBoxes(); + } + } + + public List getInfoBoxes() + { + return Collections.unmodifiableList(infoBoxes); + } + + public void cull() + { + boolean culled = false; + for (Iterator it = infoBoxes.iterator(); it.hasNext(); ) + { + InfoBox box = it.next(); + + if (box.cull()) + { + log.debug("Culling InfoBox {}", box); + it.remove(); + culled = true; + } + } + + if (culled) + { + refreshInfoBoxes(); + } + } + + private void updateInfoBoxImage(final InfoBox infoBox) + { + if (infoBox.getImage() == null) + { + return; + } + + // Set scaled InfoBox image + final Image image = infoBox.getImage(); + Image resultImage = image; + final double width = image.getWidth(null); + final double height = image.getHeight(null); + final double size = Math.max(2, runeLiteConfig.infoBoxSize()); // Limit size to 2 as that is minimum size not causing breakage + + if (size < width || size < height) + { + final double scalex = size / width; + final double scaley = size / height; + + if (scalex == 1 && scaley == 1) + { + return; + } + + final double scale = Math.min(scalex, scaley); + final int newWidth = (int) (width * scale); + final int newHeight = (int) (height * scale); + final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); + final Graphics g = scaledImage.createGraphics(); + g.drawImage(image, 0, 0, newWidth, newHeight, null); + g.dispose(); + resultImage = scaledImage; + } + + infoBox.setScaledImage(resultImage); + } + + private void refreshInfoBoxes() + { + infoBoxes.sort((b1, b2) -> ComparisonChain + .start() + .compare(b1.getPriority(), b2.getPriority()) + .compare(b1.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name(), b2.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name()) + .result()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java index 6b5b7474a6..2faa4e0008 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java @@ -1,311 +1,312 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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.ui.overlay.worldmap; - -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.Area; -import java.awt.image.BufferedImage; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Singleton; -import net.runelite.api.Client; -import net.runelite.api.Point; -import net.runelite.api.RenderOverview; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.input.MouseManager; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; - -@Singleton -public class WorldMapOverlay extends Overlay -{ - private static final int TOOLTIP_OFFSET_HEIGHT = 25; - private static final int TOOLTIP_OFFSET_WIDTH = 5; - private static final int TOOLTIP_PADDING_HEIGHT = 1; - private static final int TOOLTIP_PADDING_WIDTH = 2; - - private final WorldMapPointManager worldMapPointManager; - private final Client client; - - @Inject - private WorldMapOverlay( - Client client, - WorldMapPointManager worldMapPointManager, - MouseManager mouseManager, - WorldMapOverlayMouseListener worldMapOverlayMouseListener) - { - this.client = client; - this.worldMapPointManager = worldMapPointManager; - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.HIGHEST); - setLayer(OverlayLayer.ABOVE_MAP); - mouseManager.registerMouseListener(worldMapOverlayMouseListener); - } - - @Override - public Dimension render(Graphics2D graphics) - { - final List points = worldMapPointManager.getWorldMapPoints(); - - if (points.isEmpty()) - { - return null; - } - - Widget widget = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); - if (widget == null) - { - return null; - } - - final Rectangle worldMapRectangle = widget.getBounds(); - final Area mapViewArea = getWorldMapClipArea(worldMapRectangle); - final Rectangle canvasBounds = client.getCanvas().getBounds(); - // in fixed, the bounds are offset by the size of the black borders outside the canvas - canvasBounds.setLocation(0, 0); - final Area canvasViewArea = getWorldMapClipArea(canvasBounds); - Area currentClip = null; - - WorldMapPoint tooltipPoint = null; - - for (WorldMapPoint worldPoint : points) - { - BufferedImage image = worldPoint.getImage(); - WorldPoint point = worldPoint.getWorldPoint(); - - if (image != null && point != null) - { - Point drawPoint = mapWorldPointToGraphicsPoint(point); - - if (drawPoint == null) - { - worldPoint.setClickbox(null); - continue; - } - - if (worldPoint.isSnapToEdge() && canvasViewArea != currentClip) - { - graphics.setClip(canvasViewArea); - currentClip = canvasViewArea; - } - else if (!worldPoint.isSnapToEdge() && mapViewArea != currentClip) - { - graphics.setClip(mapViewArea); - currentClip = mapViewArea; - } - - if (worldPoint.isSnapToEdge()) - { - if (worldMapRectangle.contains(drawPoint.getX(), drawPoint.getY())) - { - if (worldPoint.isCurrentlyEdgeSnapped()) - { - worldPoint.setCurrentlyEdgeSnapped(false); - worldPoint.onEdgeUnsnap(); - } - } - else - { - drawPoint = clipToRectangle(drawPoint, worldMapRectangle); - if (!worldPoint.isCurrentlyEdgeSnapped()) - { - worldPoint.setCurrentlyEdgeSnapped(true); - worldPoint.onEdgeSnap(); - } - } - } - - int drawX = drawPoint.getX(); - int drawY = drawPoint.getY(); - - if (worldPoint.getImagePoint() == null) - { - drawX -= image.getWidth() / 2; - drawY -= image.getHeight() / 2; - } - else - { - drawX -= worldPoint.getImagePoint().getX(); - drawY -= worldPoint.getImagePoint().getY(); - } - - graphics.drawImage(image, drawX, drawY, null); - Rectangle clickbox = new Rectangle(drawX, drawY, image.getWidth(), image.getHeight()); - worldPoint.setClickbox(clickbox); - - if (worldPoint.isTooltipVisible()) - { - tooltipPoint = worldPoint; - } - } - } - - if (tooltipPoint != null) - { - drawTooltip(graphics, tooltipPoint); - } - - return null; - } - - /** - * Get the screen coordinates for a WorldPoint on the world map - * @param worldPoint WorldPoint to get screen coordinates of - * @return Point of screen coordinates of the center of the world point - */ - public Point mapWorldPointToGraphicsPoint(WorldPoint worldPoint) - { - RenderOverview ro = client.getRenderOverview(); - - if (!ro.getWorldMapData().surfaceContainsPosition(worldPoint.getX(), worldPoint.getY())) - { - return null; - } - - Float pixelsPerTile = ro.getWorldMapZoom(); - - Widget map = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); - if (map != null) - { - Rectangle worldMapRect = map.getBounds(); - - int widthInTiles = (int) Math.ceil(worldMapRect.getWidth() / pixelsPerTile); - int heightInTiles = (int) Math.ceil(worldMapRect.getHeight() / pixelsPerTile); - - Point worldMapPosition = ro.getWorldMapPosition(); - - //Offset in tiles from anchor sides - int yTileMax = worldMapPosition.getY() - heightInTiles / 2; - int yTileOffset = (yTileMax - worldPoint.getY() - 1) * -1; - int xTileOffset = worldPoint.getX() + widthInTiles / 2 - worldMapPosition.getX(); - - int xGraphDiff = ((int) (xTileOffset * pixelsPerTile)); - int yGraphDiff = (int) (yTileOffset * pixelsPerTile); - - //Center on tile. - yGraphDiff -= pixelsPerTile - Math.ceil(pixelsPerTile / 2); - xGraphDiff += pixelsPerTile - Math.ceil(pixelsPerTile / 2); - - yGraphDiff = worldMapRect.height - yGraphDiff; - yGraphDiff += (int) worldMapRect.getY(); - xGraphDiff += (int) worldMapRect.getX(); - - return new Point(xGraphDiff, yGraphDiff); - } - return null; - } - - /** - * Gets a clip area which excludes the area of widgets which overlay the world map. - * - * @param baseRectangle The base area to clip from - * @return An {@link Area} representing baseRectangle, with the area - * of visible widgets overlaying the world map clipped from it. - */ - private Area getWorldMapClipArea(Rectangle baseRectangle) - { - final Widget overview = client.getWidget(WidgetInfo.WORLD_MAP_OVERVIEW_MAP); - final Widget surfaceSelector = client.getWidget(WidgetInfo.WORLD_MAP_SURFACE_SELECTOR); - - Area clipArea = new Area(baseRectangle); - - if (overview != null && !overview.isHidden()) - { - clipArea.subtract(new Area(overview.getBounds())); - } - - if (surfaceSelector != null && !surfaceSelector.isHidden()) - { - clipArea.subtract(new Area(surfaceSelector.getBounds())); - } - - return clipArea; - } - - private void drawTooltip(Graphics2D graphics, WorldMapPoint worldPoint) - { - String tooltip = worldPoint.getTooltip(); - Point drawPoint = mapWorldPointToGraphicsPoint(worldPoint.getWorldPoint()); - if (tooltip == null || tooltip.length() <= 0 || drawPoint == null) - { - return; - } - - drawPoint = new Point(drawPoint.getX() + TOOLTIP_OFFSET_WIDTH, drawPoint.getY() + TOOLTIP_OFFSET_HEIGHT); - - graphics.setClip(client.getCanvas().getBounds()); - graphics.setColor(JagexColors.TOOLTIP_BACKGROUND); - graphics.setFont(FontManager.getRunescapeFont()); - FontMetrics fm = graphics.getFontMetrics(); - int width = fm.stringWidth(tooltip); - int height = fm.getHeight(); - - Rectangle tooltipRect = new Rectangle(drawPoint.getX() - TOOLTIP_PADDING_WIDTH, drawPoint.getY() - TOOLTIP_PADDING_HEIGHT, width + TOOLTIP_PADDING_WIDTH * 2, height + TOOLTIP_PADDING_HEIGHT * 2); - graphics.fillRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); - - graphics.setColor(JagexColors.TOOLTIP_BORDER); - graphics.drawRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); - graphics.setColor(JagexColors.TOOLTIP_TEXT); - graphics.drawString(tooltip, drawPoint.getX(), drawPoint.getY() + height); - } - - private Point clipToRectangle(Point drawPoint, Rectangle mapDisplayRectangle) - { - int clippedX = drawPoint.getX(); - - if (drawPoint.getX() < mapDisplayRectangle.getX()) - { - clippedX = (int) mapDisplayRectangle.getX(); - } - - if (drawPoint.getX() > mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()) - { - clippedX = (int) (mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()); - } - - int clippedY = drawPoint.getY(); - - if (drawPoint.getY() < mapDisplayRectangle.getY()) - { - clippedY = (int) mapDisplayRectangle.getY(); - } - - if (drawPoint.getY() > mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()) - { - clippedY = (int) (mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()); - } - - return new Point(clippedX, clippedY); - } -} +/* + * Copyright (c) 2018, Morgan Lewis + * 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.ui.overlay.worldmap; + +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.Area; +import java.awt.image.BufferedImage; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.RenderOverview; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.input.MouseManager; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +@Singleton +public class WorldMapOverlay extends Overlay +{ + private static final int TOOLTIP_OFFSET_HEIGHT = 25; + private static final int TOOLTIP_OFFSET_WIDTH = 5; + private static final int TOOLTIP_PADDING_HEIGHT = 1; + private static final int TOOLTIP_PADDING_WIDTH = 2; + + private final WorldMapPointManager worldMapPointManager; + private final Client client; + + @Inject + private WorldMapOverlay( + Client client, + WorldMapPointManager worldMapPointManager, + MouseManager mouseManager, + WorldMapOverlayMouseListener worldMapOverlayMouseListener) + { + this.client = client; + this.worldMapPointManager = worldMapPointManager; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGHEST); + setLayer(OverlayLayer.ABOVE_MAP); + mouseManager.registerMouseListener(worldMapOverlayMouseListener); + } + + @Override + public Dimension render(Graphics2D graphics) + { + final List points = worldMapPointManager.getWorldMapPoints(); + + if (points.isEmpty()) + { + return null; + } + + Widget widget = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); + if (widget == null) + { + return null; + } + + final Rectangle worldMapRectangle = widget.getBounds(); + final Area mapViewArea = getWorldMapClipArea(worldMapRectangle); + final Rectangle canvasBounds = client.getCanvas().getBounds(); + // in fixed, the bounds are offset by the size of the black borders outside the canvas + canvasBounds.setLocation(0, 0); + final Area canvasViewArea = getWorldMapClipArea(canvasBounds); + Area currentClip = null; + + WorldMapPoint tooltipPoint = null; + + for (WorldMapPoint worldPoint : points) + { + BufferedImage image = worldPoint.getImage(); + WorldPoint point = worldPoint.getWorldPoint(); + + if (image != null && point != null) + { + Point drawPoint = mapWorldPointToGraphicsPoint(point); + + if (drawPoint == null) + { + worldPoint.setClickbox(null); + continue; + } + + if (worldPoint.isSnapToEdge() && canvasViewArea != currentClip) + { + graphics.setClip(canvasViewArea); + currentClip = canvasViewArea; + } + else if (!worldPoint.isSnapToEdge() && mapViewArea != currentClip) + { + graphics.setClip(mapViewArea); + currentClip = mapViewArea; + } + + if (worldPoint.isSnapToEdge()) + { + if (worldMapRectangle.contains(drawPoint.getX(), drawPoint.getY())) + { + if (worldPoint.isCurrentlyEdgeSnapped()) + { + worldPoint.setCurrentlyEdgeSnapped(false); + worldPoint.onEdgeUnsnap(); + } + } + else + { + drawPoint = clipToRectangle(drawPoint, worldMapRectangle); + if (!worldPoint.isCurrentlyEdgeSnapped()) + { + worldPoint.setCurrentlyEdgeSnapped(true); + worldPoint.onEdgeSnap(); + } + } + } + + int drawX = drawPoint.getX(); + int drawY = drawPoint.getY(); + + if (worldPoint.getImagePoint() == null) + { + drawX -= image.getWidth() / 2; + drawY -= image.getHeight() / 2; + } + else + { + drawX -= worldPoint.getImagePoint().getX(); + drawY -= worldPoint.getImagePoint().getY(); + } + + graphics.drawImage(image, drawX, drawY, null); + Rectangle clickbox = new Rectangle(drawX, drawY, image.getWidth(), image.getHeight()); + worldPoint.setClickbox(clickbox); + + if (worldPoint.isTooltipVisible()) + { + tooltipPoint = worldPoint; + } + } + } + + if (tooltipPoint != null) + { + drawTooltip(graphics, tooltipPoint); + } + + return null; + } + + /** + * Get the screen coordinates for a WorldPoint on the world map + * + * @param worldPoint WorldPoint to get screen coordinates of + * @return Point of screen coordinates of the center of the world point + */ + public Point mapWorldPointToGraphicsPoint(WorldPoint worldPoint) + { + RenderOverview ro = client.getRenderOverview(); + + if (!ro.getWorldMapData().surfaceContainsPosition(worldPoint.getX(), worldPoint.getY())) + { + return null; + } + + Float pixelsPerTile = ro.getWorldMapZoom(); + + Widget map = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); + if (map != null) + { + Rectangle worldMapRect = map.getBounds(); + + int widthInTiles = (int) Math.ceil(worldMapRect.getWidth() / pixelsPerTile); + int heightInTiles = (int) Math.ceil(worldMapRect.getHeight() / pixelsPerTile); + + Point worldMapPosition = ro.getWorldMapPosition(); + + //Offset in tiles from anchor sides + int yTileMax = worldMapPosition.getY() - heightInTiles / 2; + int yTileOffset = (yTileMax - worldPoint.getY() - 1) * -1; + int xTileOffset = worldPoint.getX() + widthInTiles / 2 - worldMapPosition.getX(); + + int xGraphDiff = ((int) (xTileOffset * pixelsPerTile)); + int yGraphDiff = (int) (yTileOffset * pixelsPerTile); + + //Center on tile. + yGraphDiff -= pixelsPerTile - Math.ceil(pixelsPerTile / 2); + xGraphDiff += pixelsPerTile - Math.ceil(pixelsPerTile / 2); + + yGraphDiff = worldMapRect.height - yGraphDiff; + yGraphDiff += (int) worldMapRect.getY(); + xGraphDiff += (int) worldMapRect.getX(); + + return new Point(xGraphDiff, yGraphDiff); + } + return null; + } + + /** + * Gets a clip area which excludes the area of widgets which overlay the world map. + * + * @param baseRectangle The base area to clip from + * @return An {@link Area} representing baseRectangle, with the area + * of visible widgets overlaying the world map clipped from it. + */ + private Area getWorldMapClipArea(Rectangle baseRectangle) + { + final Widget overview = client.getWidget(WidgetInfo.WORLD_MAP_OVERVIEW_MAP); + final Widget surfaceSelector = client.getWidget(WidgetInfo.WORLD_MAP_SURFACE_SELECTOR); + + Area clipArea = new Area(baseRectangle); + + if (overview != null && !overview.isHidden()) + { + clipArea.subtract(new Area(overview.getBounds())); + } + + if (surfaceSelector != null && !surfaceSelector.isHidden()) + { + clipArea.subtract(new Area(surfaceSelector.getBounds())); + } + + return clipArea; + } + + private void drawTooltip(Graphics2D graphics, WorldMapPoint worldPoint) + { + String tooltip = worldPoint.getTooltip(); + Point drawPoint = mapWorldPointToGraphicsPoint(worldPoint.getWorldPoint()); + if (tooltip == null || tooltip.length() <= 0 || drawPoint == null) + { + return; + } + + drawPoint = new Point(drawPoint.getX() + TOOLTIP_OFFSET_WIDTH, drawPoint.getY() + TOOLTIP_OFFSET_HEIGHT); + + graphics.setClip(client.getCanvas().getBounds()); + graphics.setColor(JagexColors.TOOLTIP_BACKGROUND); + graphics.setFont(FontManager.getRunescapeFont()); + FontMetrics fm = graphics.getFontMetrics(); + int width = fm.stringWidth(tooltip); + int height = fm.getHeight(); + + Rectangle tooltipRect = new Rectangle(drawPoint.getX() - TOOLTIP_PADDING_WIDTH, drawPoint.getY() - TOOLTIP_PADDING_HEIGHT, width + TOOLTIP_PADDING_WIDTH * 2, height + TOOLTIP_PADDING_HEIGHT * 2); + graphics.fillRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); + + graphics.setColor(JagexColors.TOOLTIP_BORDER); + graphics.drawRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); + graphics.setColor(JagexColors.TOOLTIP_TEXT); + graphics.drawString(tooltip, drawPoint.getX(), drawPoint.getY() + height); + } + + private Point clipToRectangle(Point drawPoint, Rectangle mapDisplayRectangle) + { + int clippedX = drawPoint.getX(); + + if (drawPoint.getX() < mapDisplayRectangle.getX()) + { + clippedX = (int) mapDisplayRectangle.getX(); + } + + if (drawPoint.getX() > mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()) + { + clippedX = (int) (mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()); + } + + int clippedY = drawPoint.getY(); + + if (drawPoint.getY() < mapDisplayRectangle.getY()) + { + clippedY = (int) mapDisplayRectangle.getY(); + } + + if (drawPoint.getY() > mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()) + { + clippedY = (int) (mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()); + } + + return new Point(clippedX, clippedY); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java index 5c66d129b3..ec48dba9ff 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java @@ -1,242 +1,243 @@ -/* - * Copyright (c) 2018, Jordan Atwood - * 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.primitives.Ints; -import java.awt.Color; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; - -public class ColorUtil -{ - public static final int MAX_RGB_VALUE = 255; - public static final int MIN_RGB_VALUE = 0; - private static final String OPENING_COLOR_TAG_START = " + * 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.primitives.Ints; +import java.awt.Color; +import java.util.regex.Pattern; +import javax.annotation.Nonnull; + +public class ColorUtil +{ + public static final int MAX_RGB_VALUE = 255; + public static final int MIN_RGB_VALUE = 0; + private static final String OPENING_COLOR_TAG_START = " fillCondition) { @@ -296,8 +296,8 @@ public class ImageUtil * @param image The image to be outlined. * @param color The color to use for the outline. * @param outlineCorners Whether to draw an outline around corners, or only around edges. - * @return The BufferedImage with its edges--and optionally, corners--outlined - * with the given color. + * @return The BufferedImage with its edges--and optionally, corners--outlined + * with the given color. */ public static BufferedImage outlineImage(final BufferedImage image, final Color color, final Boolean outlineCorners) { @@ -312,8 +312,8 @@ public class ImageUtil * @param color The color to use for the outline. * @param fillCondition The predicate to be consumed by {@link #fillImage(BufferedImage, Color, Predicate) fillImage(BufferedImage, Color, Predicate)} * @param outlineCorners Whether to draw an outline around corners, or only around edges. - * @return The BufferedImage with its edges--and optionally, corners--outlined - * with the given color. + * @return The BufferedImage with its edges--and optionally, corners--outlined + * with the given color. */ public static BufferedImage outlineImage(final BufferedImage image, final Color color, final Predicate fillCondition, final Boolean outlineCorners) { @@ -347,7 +347,7 @@ public class ImageUtil * * @param c The class to be referenced for resource path. * @param path The path, relative to the given class. - * @return A {@link BufferedImage} of the loaded image resource from the given path. + * @return A {@link BufferedImage} of the loaded image resource from the given path. */ public static BufferedImage getResourceStreamFromClass(final Class c, final String path) { @@ -369,7 +369,7 @@ public class ImageUtil * * @param image The image which should have its non-transparent pixels filled. * @param color The color with which to fill pixels. - * @return The given image with all non-transparent pixels set to the given color. + * @return The given image with all non-transparent pixels set to the given color. */ public static BufferedImage fillImage(final BufferedImage image, final Color color) { @@ -377,14 +377,14 @@ public class ImageUtil } /** - * Fills pixels of the given image with the given color based on a given fill condition - * predicate. + * Fills pixels of the given image with the given color based on a given fill condition + * predicate. * * @param image The image which should have its non-transparent pixels filled. * @param color The color with which to fill pixels. * @param fillCondition The condition on which to fill pixels with the given color. - * @return The given image with all pixels fulfilling the fill condition predicate - * set to the given color. + * @return The given image with all pixels fulfilling the fill condition predicate + * set to the given color. */ static BufferedImage fillImage(final BufferedImage image, final Color color, final Predicate fillCondition) { @@ -411,7 +411,7 @@ public class ImageUtil * @param image The image to be adjusted. * @param scales An array of scale operations to be performed on the image's color components. * @param offsets An array of offset operations to be performed on the image's color components. - * @return The modified image after applying the given adjustments. + * @return The modified image after applying the given adjustments. */ private static BufferedImage offset(final BufferedImage image, final float[] scales, final float[] offsets) { @@ -421,9 +421,10 @@ public class ImageUtil /** * Converts the buffered image into a sprite image and returns it + * * @param image The image to be converted * @param client Current client instance - * @return The buffered image as a sprite image + * @return The buffered image as a sprite image */ public static SpritePixels getImageSpritePixels(BufferedImage image, Client client) { @@ -455,12 +456,12 @@ public class ImageUtil /** * Converts an image into an {@code IndexedSprite} instance. - * + *

* The passed in image can only have at max 255 different colors. * * @param image The image to be converted * @param client Current client instance - * @return The image as an {@code IndexedSprite} + * @return The image as an {@code IndexedSprite} */ public static IndexedSprite getImageIndexedSprite(BufferedImage image, Client client) { diff --git a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java index 194b1974b2..b5d4ab23f8 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java +++ b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java @@ -1,150 +1,152 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * 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.base.Strings; -import java.awt.Desktop; -import java.awt.Toolkit; -import java.awt.datatransfer.StringSelection; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import javax.inject.Singleton; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import lombok.extern.slf4j.Slf4j; - -/** - * Utility class used for browser navigation - */ -@Singleton -@Slf4j -public class LinkBrowser -{ - private static boolean shouldAttemptXdg = OSType.getOSType() == OSType.Linux; - - /** - * Tries to navigate to specified URL in browser. In case operation fails, displays message box with message - * and copies link to clipboard to navigate to. - * @param url url to open - * @return true if operation was successful - */ - public static boolean browse(final String url) - { - if (Strings.isNullOrEmpty(url)) - { - return false; - } - - if (attemptDesktopBrowse(url)) - { - log.debug("Opened browser through Desktop#browse to {}", url); - return true; - } - - if (shouldAttemptXdg && attemptXdgOpen(url)) - { - log.debug("Opened browser through xdg-open to {}", url); - return true; - } - - showMessageBox("Unable to open link. Press 'OK' and link will be copied to your clipboard.", url); - return false; - } - - private static boolean attemptXdgOpen(String url) - { - try - { - final Process exec = Runtime.getRuntime().exec(new String[]{"xdg-open", url}); - exec.waitFor(); - - final int ret = exec.exitValue(); - if (ret == 0) - { - return true; - } - - log.warn("xdg-open {} returned with error code {}", url, ret); - return false; - } - catch (IOException ex) - { - // xdg-open not found - shouldAttemptXdg = false; - return false; - } - catch (InterruptedException ex) - { - log.warn("Interrupted while waiting for xdg-open {} to execute", url); - return false; - } - } - - private static boolean attemptDesktopBrowse(String url) - { - if (!Desktop.isDesktopSupported()) - { - return false; - } - - final Desktop desktop = Desktop.getDesktop(); - - if (!desktop.isSupported(Desktop.Action.BROWSE)) - { - return false; - } - - try - { - desktop.browse(new URI(url)); - return true; - } - catch (IOException | URISyntaxException ex) - { - log.warn("Failed to open Desktop#browser {}", url, ex); - return false; - } - } - - /** - * Open swing message box with specified message and copy data to clipboard - * @param message message to show - */ - private static void showMessageBox(final String message, final String data) - { - SwingUtilities.invokeLater(() -> - { - final int result = JOptionPane.showConfirmDialog(null, message, "Message", - JOptionPane.OK_CANCEL_OPTION); - - if (result == JOptionPane.OK_OPTION) - { - final StringSelection stringSelection = new StringSelection(data); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); - } - }); - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * 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.base.Strings; +import java.awt.Desktop; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import javax.inject.Singleton; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import lombok.extern.slf4j.Slf4j; + +/** + * Utility class used for browser navigation + */ +@Singleton +@Slf4j +public class LinkBrowser +{ + private static boolean shouldAttemptXdg = OSType.getOSType() == OSType.Linux; + + /** + * Tries to navigate to specified URL in browser. In case operation fails, displays message box with message + * and copies link to clipboard to navigate to. + * + * @param url url to open + * @return true if operation was successful + */ + public static boolean browse(final String url) + { + if (Strings.isNullOrEmpty(url)) + { + return false; + } + + if (attemptDesktopBrowse(url)) + { + log.debug("Opened browser through Desktop#browse to {}", url); + return true; + } + + if (shouldAttemptXdg && attemptXdgOpen(url)) + { + log.debug("Opened browser through xdg-open to {}", url); + return true; + } + + showMessageBox("Unable to open link. Press 'OK' and link will be copied to your clipboard.", url); + return false; + } + + private static boolean attemptXdgOpen(String url) + { + try + { + final Process exec = Runtime.getRuntime().exec(new String[]{"xdg-open", url}); + exec.waitFor(); + + final int ret = exec.exitValue(); + if (ret == 0) + { + return true; + } + + log.warn("xdg-open {} returned with error code {}", url, ret); + return false; + } + catch (IOException ex) + { + // xdg-open not found + shouldAttemptXdg = false; + return false; + } + catch (InterruptedException ex) + { + log.warn("Interrupted while waiting for xdg-open {} to execute", url); + return false; + } + } + + private static boolean attemptDesktopBrowse(String url) + { + if (!Desktop.isDesktopSupported()) + { + return false; + } + + final Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.BROWSE)) + { + return false; + } + + try + { + desktop.browse(new URI(url)); + return true; + } + catch (IOException | URISyntaxException ex) + { + log.warn("Failed to open Desktop#browser {}", url, ex); + return false; + } + } + + /** + * Open swing message box with specified message and copy data to clipboard + * + * @param message message to show + */ + private static void showMessageBox(final String message, final String data) + { + SwingUtilities.invokeLater(() -> + { + final int result = JOptionPane.showConfirmDialog(null, message, "Message", + JOptionPane.OK_CANCEL_OPTION); + + if (result == JOptionPane.OK_OPTION) + { + final StringSelection stringSelection = new StringSelection(data); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); + } + }); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java b/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java index 7677c16d2f..e98c3d1dd3 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java @@ -109,8 +109,8 @@ public class MenuUtil private static MenuEntry findOptionTarget(Stream stream, String option, String target) { Optional maybeEntry = stream.filter(e -> Text.standardize(e.getOption()).equals(option) && - Text.standardize(e.getTarget()).equals(target)) - /* autism */ .findFirst(); + Text.standardize(e.getTarget()).equals(target)) + /* autism */.findFirst(); return maybeEntry.orElse(null); } @@ -118,8 +118,8 @@ public class MenuUtil private static MenuEntry findOptionTargetLenient(Stream stream, String option, String target) { Optional maybeEntry = stream.filter(e -> Text.standardize(e.getOption()).contains(option) && - Text.standardize(e.getTarget()).contains(target)) - /* autism */ .findFirst(); + Text.standardize(e.getTarget()).contains(target)) + /* autism */.findFirst(); return maybeEntry.orElse(null); } diff --git a/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java b/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java index 077439ee88..6bd6d09b1c 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java +++ b/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java @@ -1,79 +1,92 @@ -package net.runelite.client.util; - -import net.runelite.api.Client; -import net.runelite.api.Player; -import net.runelite.api.WorldType; -import net.runelite.api.coords.WorldPoint; - -import java.awt.*; - -public class MiscUtils -{ - private static int[] abovePointsX = { 2944, 3392, 3392, 2944 }; - private static int[] abovePointsY = { 3523, 3523, 3971, 3971 }; - private static int[] belowPointsX = { 2944, 2944, 3264, 3264 }; - private static int[] belowPointsY = { 9918, 10360, 10360, 9918 }; - - private static Polygon abovePoly = new Polygon(abovePointsX, abovePointsY, abovePointsX.length); - private static Polygon belowPoly = new Polygon(belowPointsX, belowPointsY, belowPointsX.length); - - //test replacement so private for now - private static boolean inWildy(WorldPoint point) - { - if (point == null) - return false; - - return abovePoly.contains(point.getX(), point.getY()) || belowPoly.contains(point.getX(), point.getY()); - } - - public static int getWildernessLevelFrom(Client client, WorldPoint point) - { - if (client == null) - return 0; - - if (point == null) - return 0; - - int x = point.getX(); - - if (point.getPlane() == 0 && (x < 2940 || x > 3391)) - return 0; - - int y = point.getY(); - //v underground //v above ground - int wildernessLevel = clamp(y > 6400 ? ((y - 9920) / 8) + 1 : ((y - 3520) / 8) + 1, 0, 56); - - if (point.getPlane() > 0) - if (y < 9920) - wildernessLevel = 0; - - if (client.getWorldType().stream().anyMatch(worldType -> worldType == WorldType.PVP || worldType == WorldType.HIGH_RISK)) - { - wildernessLevel += 15; - } - - return Math.max(0, wildernessLevel); - } - - public static int clamp(int val, int min, int max) - { - return Math.max(min, Math.min(max, val)); - } - - public static float clamp(float val, float min, float max) - { - return Math.max(min, Math.min(max, val)); - } - - public static boolean inWilderness(Client client) - { - Player localPlayer = client.getLocalPlayer(); - - if (localPlayer == null) - return false; - - return inWildy(localPlayer.getWorldLocation()); - - //return getWildernessLevelFrom(client, localPlayer.getWorldLocation()) > 0; - } -} +package net.runelite.client.util; + +import java.awt.Polygon; +import net.runelite.api.Client; +import net.runelite.api.Player; +import net.runelite.api.WorldType; +import net.runelite.api.coords.WorldPoint; + +public class MiscUtils +{ + private static int[] abovePointsX = {2944, 3392, 3392, 2944}; + private static int[] abovePointsY = {3523, 3523, 3971, 3971}; + private static int[] belowPointsX = {2944, 2944, 3264, 3264}; + private static int[] belowPointsY = {9918, 10360, 10360, 9918}; + + private static Polygon abovePoly = new Polygon(abovePointsX, abovePointsY, abovePointsX.length); + private static Polygon belowPoly = new Polygon(belowPointsX, belowPointsY, belowPointsX.length); + + //test replacement so private for now + private static boolean inWildy(WorldPoint point) + { + if (point == null) + { + return false; + } + + return abovePoly.contains(point.getX(), point.getY()) || belowPoly.contains(point.getX(), point.getY()); + } + + public static int getWildernessLevelFrom(Client client, WorldPoint point) + { + if (client == null) + { + return 0; + } + + if (point == null) + { + return 0; + } + + int x = point.getX(); + + if (point.getPlane() == 0 && (x < 2940 || x > 3391)) + { + return 0; + } + + int y = point.getY(); + //v underground //v above ground + int wildernessLevel = clamp(y > 6400 ? ((y - 9920) / 8) + 1 : ((y - 3520) / 8) + 1, 0, 56); + + if (point.getPlane() > 0) + { + if (y < 9920) + { + wildernessLevel = 0; + } + } + + if (client.getWorldType().stream().anyMatch(worldType -> worldType == WorldType.PVP || worldType == WorldType.HIGH_RISK)) + { + wildernessLevel += 15; + } + + return Math.max(0, wildernessLevel); + } + + public static int clamp(int val, int min, int max) + { + return Math.max(min, Math.min(max, val)); + } + + public static float clamp(float val, float min, float max) + { + return Math.max(min, Math.min(max, val)); + } + + public static boolean inWilderness(Client client) + { + Player localPlayer = client.getLocalPlayer(); + + if (localPlayer == null) + { + return false; + } + + return inWildy(localPlayer.getWorldLocation()); + + //return getWildernessLevelFrom(client, localPlayer.getWorldLocation()) > 0; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java index c306d45125..3150816a9d 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java @@ -1,111 +1,113 @@ -/* - * Copyright (c) 2019. PKLite - All Rights Reserved - * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. - * Proprietary and confidential. Refer to PKLite License file for more information on - * full terms of this copyright and to determine what constitutes authorized use. - * Written by PKLite(ST0NEWALL, others) , 2019 - * - */ - -package net.runelite.client.util; - -import java.util.Comparator; -import java.util.Objects; -import java.util.TreeMap; -import net.runelite.api.Client; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemComposition; -import net.runelite.api.Player; -import net.runelite.api.Varbits; -import net.runelite.api.WorldType; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.game.ItemManager; -import static net.runelite.client.util.StackFormatter.quantityToRSDecimalStack; -import org.apache.commons.lang3.ArrayUtils; - -/** - * - */ -public class PvPUtil -{ - - /** - * Gets the wilderness level based on a world point - * @param point the point in the world to get the wilderness level for - * @return the int representing the wilderness level - */ - public static int getWildernessLevelFrom(WorldPoint point) - { - int x = point.getX(); - int y = point.getY(); - - int underLevel = ((y - 9920) / 8) + 1; - int upperLevel = ((y - 3520) / 8) + 1; - - return y > 6400 ? underLevel : upperLevel; - } - - /** - * Determines if another player is attackable based off of wilderness level and combat levels - * @param client The client of the local player - * @param player the player to determine attackability - * @return returns true if the player is attackable, false otherwise - */ - public static boolean isAttackable(Client client, Player player) - { - int wildernessLevel = 0; - if (!(client.getVar(Varbits.IN_WILDERNESS) == 1 || WorldType.isPvpWorld(client.getWorldType()))) - { - return false; - } - if (WorldType.isPvpWorld(client.getWorldType())) - { - if (client.getVar(Varbits.IN_WILDERNESS) != 1) - { - return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) <= 15; - } - wildernessLevel = 15; - } - return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) - < (getWildernessLevelFrom(client.getLocalPlayer().getWorldLocation())+ wildernessLevel); - } - - public static int calculateRisk(Client client, ItemManager itemManager) - { - if (client.getItemContainer(InventoryID.EQUIPMENT) == null) - { - return 0; - } - if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null) - { - return 0; - } - Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(), - Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems()); - TreeMap priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue)); - int wealth = 0; - for (Item i : items) - { - int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity()); - - final ItemComposition itemComposition = itemManager.getItemComposition(i.getId()); - if (!itemComposition.isTradeable() && value == 0) - { - value = itemComposition.getPrice() * i.getQuantity(); - priceMap.put(value, i); - } - else - { - value = itemManager.getItemPrice(i.getId()) * i.getQuantity(); - if (i.getId() > 0 && value > 0) - { - priceMap.put(value, i); - } - } - wealth += value; - } - return Integer.parseInt(quantityToRSDecimalStack(priceMap.keySet().stream().mapToInt(Integer::intValue).sum())); - - } -} +/* + * Copyright (c) 2019. PKLite - All Rights Reserved + * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. + * Proprietary and confidential. Refer to PKLite License file for more information on + * full terms of this copyright and to determine what constitutes authorized use. + * Written by PKLite(ST0NEWALL, others) , 2019 + * + */ + +package net.runelite.client.util; + +import java.util.Comparator; +import java.util.Objects; +import java.util.TreeMap; +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemComposition; +import net.runelite.api.Player; +import net.runelite.api.Varbits; +import net.runelite.api.WorldType; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.game.ItemManager; +import static net.runelite.client.util.StackFormatter.quantityToRSDecimalStack; +import org.apache.commons.lang3.ArrayUtils; + +/** + * + */ +public class PvPUtil +{ + + /** + * Gets the wilderness level based on a world point + * + * @param point the point in the world to get the wilderness level for + * @return the int representing the wilderness level + */ + public static int getWildernessLevelFrom(WorldPoint point) + { + int x = point.getX(); + int y = point.getY(); + + int underLevel = ((y - 9920) / 8) + 1; + int upperLevel = ((y - 3520) / 8) + 1; + + return y > 6400 ? underLevel : upperLevel; + } + + /** + * Determines if another player is attackable based off of wilderness level and combat levels + * + * @param client The client of the local player + * @param player the player to determine attackability + * @return returns true if the player is attackable, false otherwise + */ + public static boolean isAttackable(Client client, Player player) + { + int wildernessLevel = 0; + if (!(client.getVar(Varbits.IN_WILDERNESS) == 1 || WorldType.isPvpWorld(client.getWorldType()))) + { + return false; + } + if (WorldType.isPvpWorld(client.getWorldType())) + { + if (client.getVar(Varbits.IN_WILDERNESS) != 1) + { + return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) <= 15; + } + wildernessLevel = 15; + } + return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) + < (getWildernessLevelFrom(client.getLocalPlayer().getWorldLocation()) + wildernessLevel); + } + + public static int calculateRisk(Client client, ItemManager itemManager) + { + if (client.getItemContainer(InventoryID.EQUIPMENT) == null) + { + return 0; + } + if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null) + { + return 0; + } + Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(), + Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems()); + TreeMap priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue)); + int wealth = 0; + for (Item i : items) + { + int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity()); + + final ItemComposition itemComposition = itemManager.getItemComposition(i.getId()); + if (!itemComposition.isTradeable() && value == 0) + { + value = itemComposition.getPrice() * i.getQuantity(); + priceMap.put(value, i); + } + else + { + value = itemManager.getItemPrice(i.getId()) * i.getQuantity(); + if (i.getId() > 0 && value > 0) + { + priceMap.put(value, i); + } + } + wealth += value; + } + return Integer.parseInt(quantityToRSDecimalStack(priceMap.keySet().stream().mapToInt(Integer::intValue).sum())); + + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java b/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java index 50733334b9..5c4e5d08f3 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java +++ b/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java @@ -32,20 +32,20 @@ import org.objectweb.asm.tree.MethodNode; public class RefUtils implements Opcodes { - + private static final String TYPE_PREFIX = "us/runelitepl/mixinprocessor/annotations/"; - + public static boolean isReturn(int opcode, boolean checkType) { return (opcode == RETURN && !checkType) || opcode == IRETURN || opcode == LRETURN || opcode == DRETURN || - opcode == ARETURN || opcode == FRETURN; + opcode == ARETURN || opcode == FRETURN; } - + public static boolean isReturn(int opcode) { return isReturn(opcode, false); } - + public static boolean checkAnnotation(MethodNode method, String annotation) { if (method.visibleAnnotations != null) @@ -60,7 +60,7 @@ public class RefUtils implements Opcodes } return false; } - + public static boolean checkAnnotation(FieldNode field, String annotation) { if (field.visibleAnnotations != null) @@ -75,10 +75,10 @@ public class RefUtils implements Opcodes } return false; } - + public static String makeAnnotationDesc(String annot) { return "L" + TYPE_PREFIX + annot + ";"; } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java index c9282f7f46..38a8669244 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java +++ b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java @@ -173,7 +173,7 @@ public class StackFormatter *

* * @param quantity The quantity to convert. - * @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million. + * @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million. * @return The stack size as it would appear in RS, with decimals, * with K after 100,000 and M after 10,000,000 */ diff --git a/runelite-client/src/main/java/net/runelite/client/util/Text.java b/runelite-client/src/main/java/net/runelite/client/util/Text.java index 6158b9a32f..67892bdbc3 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/Text.java +++ b/runelite-client/src/main/java/net/runelite/client/util/Text.java @@ -81,8 +81,8 @@ public class Text /** * In addition to removing all tags, replaces nbsp with space, trims string and lowercases it - * @param str The string to standardize * + * @param str The string to standardize * @return The given `str` that is standardized */ public static String standardize(String str) @@ -166,9 +166,9 @@ public class Text * converts enum name format from THIS_FORMAT to This Format. * * @param o an enum - * @return the enum's name in title case, - * or if it overrides toString, - * the value returned by toString + * @return the enum's name in title case, + * or if it overrides toString, + * the value returned by toString */ public static String titleCase(Enum o) { diff --git a/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java b/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java index 0338f874bd..d212fe7060 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java @@ -1,93 +1,95 @@ -package net.runelite.client.util; - -import lombok.Getter; -import net.runelite.api.coords.WorldArea; - -public enum WildernessLocation -{ - - REV_CAVE_OTHER("Rev Cave", new Location(3128, 10232, 3225, 10059), 0), - REV_BLACK_DRAGS("Rev Black Drags", new Location(3223, 10216, 3254, 10190), 0), - REV_DARK_BEAST("Rev Dark Beast", new Location(3243, 10154, 3264, 10136), 0), - REV_MAIN_CHAMBER("Main Rev Chamber", new Location(3227, 10187, 3261, 10157), 0), - REV_ENTRANCE_INSIDE("Inside Rev Ent.", new Location(3238, 10236, 3243, 10231), 0), - ICE_ROCK("Ice Rock", new Location(2957, 3942, 2984, 3929), 0), - WILDY_AGILITY_COURSE("Wildy Agility Course", new Location(2988, 3967, 3008, 3906), 0), - FIRE_GIANT_ENTRANCE("Fire Giant Entrance", new Location(3042, 3929, 3051, 3920), 0), - PIRATE_HUT("Pirate Hut", new Location(3037, 3959, 3045, 3948), 0), - MAGE_BANK("Mage Bank", new Location(3082, 3960, 3103, 3952), 0), - MAGE_ARENA("Mage Arena", new Location(3088, 3949, 3123, 3919), 0), - LEVER("Lever", new Location(3149, 3933, 3162, 3917), 0), - WEB("Web", new Location(3153, 3961, 3163, 3948), 0), - RESOURCE_ARENA("Resource Arena", new Location(3174, 3946, 3195, 3923), 0), - AXE_HUT("Axe Hut", new Location(3187, 3962, 3194, 3957), 0), - SCORPIA("Scorpia", new Location(3216, 3949, 3248, 3935), 0), - ROGUE_CASTLE("Rogue Castle", new Location(3275, 3947, 3299, 3920), 0), - FIFTY_PORTS("50 ports", new Location(3301, 3923, 3315, 3909), 0), - VOLCANO("Volcano", new Location(3345, 3957, 3390, 3916), 0), - NEW_GATE("New Gate", new Location(3345, 3957, 3390, 3916), 0), - GLORY_HOLE("Glory Hole", new Location(3352, 3897, 3386, 3869), 0), - GLORY_HILL("Glory Hill", new Location(3331, 3890, 3348, 3866), 0), - GDZ("Gdz", new Location(3279, 3895, 3296, 3875), 0), - GAP("Gap", new Location(3238, 3855, 3258, 3841), 0), - OLD_GATE("Old Gate", new Location(3211, 3906, 3238, 3882), 0), - LAVA_DRAGS("Lava Drags", new Location(3175, 3857, 3221, 3805), 0), - SPIDER_HILL("Spider Hill", new Location(3156, 3896, 3182, 3871), 0), - RUNE_ROCKS("Rune Rocks", new Location(3055, 3890, 3072, 3876), 0), - ICE_GATE("Ice Gate", new Location(2945, 3913, 2978, 3878), 0), - VENENATIS("Venenatis", new Location(3298, 3759, 3353, 3722), 0), - SINGLE_STRIP("Single Strip", new Location(3333, 3842, 3348, 3774), 0), - CALLISTO("Callisto", new Location(3266, 3863, 3315, 3827), 0), - DWARVES("Dwarves", new Location(3230, 3805, 3264, 3779), 0), - VETTION("Vet'tion", new Location(3183, 3796, 3227, 3765), 0), - EAST_DRAGONS("East Drags", new Location(3326, 3704, 3365, 3671), 0), - HILL_GIANTS("Hill Giants", new Location(3282, 3687, 3300, 3674), 0), - ENTS("Ents", new Location(3300, 3627, 3320, 3584), 0), - CHAOS_TEMPLE("Chaos Temple", new Location(3220, 3632, 3255, 3593), 0), - NINETEEN_OBELISK("19s", new Location(3220, 3672, 3234, 3660), 0), - CORP_CAVE("Corp Cave", new Location(3201, 3684, 3219, 3672), 0), - THIRTEEN_OBELISK("13s", new Location(3145, 3628, 3168, 3609), 0), - SOUTH_REV_ENTRANCE("Lvl 18 Rev Ent", new Location(3071, 3660, 3092, 3645), 0), - GRAVES("Graves", new Location(3128, 3686, 3181, 3658), 0), - GRAVEYARD_DRAGS("Graveyard Drags", new Location(3129, 3717, 3172, 3691), 0), - CHINS("Chins", new Location(3128, 3792, 3160, 3754), 0), - REV_ENTRANCE("Rev Entrance", new Location(3118, 3837, 3142, 3818), 0), - HOB_OBELISK("35 Obelisk", new Location(3097, 3804, 3115, 3785), 0), - HOBGOBLINS("Hobgoblins", new Location(3073, 3775, 3104, 3745), 0), - GWD("God Wars Dungeon", new Location(3010, 3745, 3027, 3727), 0), - LAVA_MAZE_TELE("Lava Maze Tele", new Location(3019, 3842, 3044, 3812), 0), - KBD_CAGE("KBD CAGE", new Location(3007, 3855, 3021, 3839), 0), - GHORROCK("44s", new Location(2973, 3870, 2987, 3859), 0), - CHAOS_FANATIC("Chaos Fanatic", new Location(2971, 3854, 2992, 3834), 0), - HIGH_ALTAR("High Altar", new Location(2945, 3826, 2970, 3813), 0), - CEMETERY("Cemetery", new Location(2956, 3767, 2996, 3736), 0), - CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", new Location(2952, 3709, 2985, 3678), 0), - DARK_WARRIOR_FORTRESS("Dark Warriors", new Location(3014, 3648, 3046, 3616), 0), - WEST_DRAGONS("West Drags", new Location(2960, 3627, 2992, 3598), 0), - BANDIT_CAMP("Bandit Camp", new Location(3017, 3712, 3059, 3681), 0); - - @Getter - private final String name; - @Getter - private final WorldArea worldArea; - WildernessLocation(String name, Location location, int plane) - { - this.name = name; - this.worldArea = new WorldArea(location.x, location.y, location.width, location.height, plane); - } - - public static class Location - { - public int x; - public int y; - public int width; - public int height; - Location(int x, int y, int x1, int y1) - { - this.x = x; - this.y = y1; - this.width = x1 - x; - this.height = y - y1; - } - } -} +package net.runelite.client.util; + +import lombok.Getter; +import net.runelite.api.coords.WorldArea; + +public enum WildernessLocation +{ + + REV_CAVE_OTHER("Rev Cave", new Location(3128, 10232, 3225, 10059), 0), + REV_BLACK_DRAGS("Rev Black Drags", new Location(3223, 10216, 3254, 10190), 0), + REV_DARK_BEAST("Rev Dark Beast", new Location(3243, 10154, 3264, 10136), 0), + REV_MAIN_CHAMBER("Main Rev Chamber", new Location(3227, 10187, 3261, 10157), 0), + REV_ENTRANCE_INSIDE("Inside Rev Ent.", new Location(3238, 10236, 3243, 10231), 0), + ICE_ROCK("Ice Rock", new Location(2957, 3942, 2984, 3929), 0), + WILDY_AGILITY_COURSE("Wildy Agility Course", new Location(2988, 3967, 3008, 3906), 0), + FIRE_GIANT_ENTRANCE("Fire Giant Entrance", new Location(3042, 3929, 3051, 3920), 0), + PIRATE_HUT("Pirate Hut", new Location(3037, 3959, 3045, 3948), 0), + MAGE_BANK("Mage Bank", new Location(3082, 3960, 3103, 3952), 0), + MAGE_ARENA("Mage Arena", new Location(3088, 3949, 3123, 3919), 0), + LEVER("Lever", new Location(3149, 3933, 3162, 3917), 0), + WEB("Web", new Location(3153, 3961, 3163, 3948), 0), + RESOURCE_ARENA("Resource Arena", new Location(3174, 3946, 3195, 3923), 0), + AXE_HUT("Axe Hut", new Location(3187, 3962, 3194, 3957), 0), + SCORPIA("Scorpia", new Location(3216, 3949, 3248, 3935), 0), + ROGUE_CASTLE("Rogue Castle", new Location(3275, 3947, 3299, 3920), 0), + FIFTY_PORTS("50 ports", new Location(3301, 3923, 3315, 3909), 0), + VOLCANO("Volcano", new Location(3345, 3957, 3390, 3916), 0), + NEW_GATE("New Gate", new Location(3345, 3957, 3390, 3916), 0), + GLORY_HOLE("Glory Hole", new Location(3352, 3897, 3386, 3869), 0), + GLORY_HILL("Glory Hill", new Location(3331, 3890, 3348, 3866), 0), + GDZ("Gdz", new Location(3279, 3895, 3296, 3875), 0), + GAP("Gap", new Location(3238, 3855, 3258, 3841), 0), + OLD_GATE("Old Gate", new Location(3211, 3906, 3238, 3882), 0), + LAVA_DRAGS("Lava Drags", new Location(3175, 3857, 3221, 3805), 0), + SPIDER_HILL("Spider Hill", new Location(3156, 3896, 3182, 3871), 0), + RUNE_ROCKS("Rune Rocks", new Location(3055, 3890, 3072, 3876), 0), + ICE_GATE("Ice Gate", new Location(2945, 3913, 2978, 3878), 0), + VENENATIS("Venenatis", new Location(3298, 3759, 3353, 3722), 0), + SINGLE_STRIP("Single Strip", new Location(3333, 3842, 3348, 3774), 0), + CALLISTO("Callisto", new Location(3266, 3863, 3315, 3827), 0), + DWARVES("Dwarves", new Location(3230, 3805, 3264, 3779), 0), + VETTION("Vet'tion", new Location(3183, 3796, 3227, 3765), 0), + EAST_DRAGONS("East Drags", new Location(3326, 3704, 3365, 3671), 0), + HILL_GIANTS("Hill Giants", new Location(3282, 3687, 3300, 3674), 0), + ENTS("Ents", new Location(3300, 3627, 3320, 3584), 0), + CHAOS_TEMPLE("Chaos Temple", new Location(3220, 3632, 3255, 3593), 0), + NINETEEN_OBELISK("19s", new Location(3220, 3672, 3234, 3660), 0), + CORP_CAVE("Corp Cave", new Location(3201, 3684, 3219, 3672), 0), + THIRTEEN_OBELISK("13s", new Location(3145, 3628, 3168, 3609), 0), + SOUTH_REV_ENTRANCE("Lvl 18 Rev Ent", new Location(3071, 3660, 3092, 3645), 0), + GRAVES("Graves", new Location(3128, 3686, 3181, 3658), 0), + GRAVEYARD_DRAGS("Graveyard Drags", new Location(3129, 3717, 3172, 3691), 0), + CHINS("Chins", new Location(3128, 3792, 3160, 3754), 0), + REV_ENTRANCE("Rev Entrance", new Location(3118, 3837, 3142, 3818), 0), + HOB_OBELISK("35 Obelisk", new Location(3097, 3804, 3115, 3785), 0), + HOBGOBLINS("Hobgoblins", new Location(3073, 3775, 3104, 3745), 0), + GWD("God Wars Dungeon", new Location(3010, 3745, 3027, 3727), 0), + LAVA_MAZE_TELE("Lava Maze Tele", new Location(3019, 3842, 3044, 3812), 0), + KBD_CAGE("KBD CAGE", new Location(3007, 3855, 3021, 3839), 0), + GHORROCK("44s", new Location(2973, 3870, 2987, 3859), 0), + CHAOS_FANATIC("Chaos Fanatic", new Location(2971, 3854, 2992, 3834), 0), + HIGH_ALTAR("High Altar", new Location(2945, 3826, 2970, 3813), 0), + CEMETERY("Cemetery", new Location(2956, 3767, 2996, 3736), 0), + CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", new Location(2952, 3709, 2985, 3678), 0), + DARK_WARRIOR_FORTRESS("Dark Warriors", new Location(3014, 3648, 3046, 3616), 0), + WEST_DRAGONS("West Drags", new Location(2960, 3627, 2992, 3598), 0), + BANDIT_CAMP("Bandit Camp", new Location(3017, 3712, 3059, 3681), 0); + + @Getter + private final String name; + @Getter + private final WorldArea worldArea; + + WildernessLocation(String name, Location location, int plane) + { + this.name = name; + this.worldArea = new WorldArea(location.x, location.y, location.width, location.height, plane); + } + + public static class Location + { + public int x; + public int y; + public int width; + public int height; + + Location(int x, int y, int x1, int y1) + { + this.x = x; + this.y = y1; + this.width = x1 - x; + this.height = y - y1; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java b/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java index 9f508676a5..67115d49ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java @@ -1,52 +1,53 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * 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.EnumSet; -import net.runelite.api.WorldType; - -/** - * Utility class for RuneScape worlds - */ -public class WorldUtil -{ - /** - * Converts http-api world types to runelite-api world types - * TODO: Find a better way to handle these to not have duplicate interfaces - * @param apiTypes http-api world types - * @return runelite-api world types - */ - public static EnumSet toWorldTypes(final EnumSet apiTypes) - { - final EnumSet types = EnumSet.noneOf(net.runelite.api.WorldType.class); - - for (net.runelite.http.api.worlds.WorldType apiType : apiTypes) - { - types.add(net.runelite.api.WorldType.valueOf(apiType.name())); - } - - return types; - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * 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.EnumSet; +import net.runelite.api.WorldType; + +/** + * Utility class for RuneScape worlds + */ +public class WorldUtil +{ + /** + * Converts http-api world types to runelite-api world types + * TODO: Find a better way to handle these to not have duplicate interfaces + * + * @param apiTypes http-api world types + * @return runelite-api world types + */ + public static EnumSet toWorldTypes(final EnumSet apiTypes) + { + final EnumSet types = EnumSet.noneOf(net.runelite.api.WorldType.class); + + for (net.runelite.http.api.worlds.WorldType apiType : apiTypes) + { + types.add(net.runelite.api.WorldType.valueOf(apiType.name())); + } + + return types; + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java index e7e5d914f2..099a76d19b 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java @@ -34,9 +34,7 @@ import net.runelite.api.ChatMessageType; import static net.runelite.api.ChatMessageType.GAMEMESSAGE; import net.runelite.api.Client; import net.runelite.api.MessageNode; -import net.runelite.api.Player; import net.runelite.api.Varbits; -import net.runelite.api.coords.LocalPoint; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameTick; import net.runelite.api.events.VarbitChanged; From a587cb5c8204bb7175ce04d4d0e4ea996a458624 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Fri, 17 May 2019 08:43:45 +0100 Subject: [PATCH 21/78] Freeze additions (#275) * Update FreezeTimersOverlay.java * add FreezeInfo.Java --- .../plugins/freezetimers/FreezeInfo.java | 15 ++++++++++++ .../freezetimers/FreezeTimersOverlay.java | 24 ++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java new file mode 100644 index 0000000000..bc08d81168 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java @@ -0,0 +1,15 @@ +package net.runelite.client.plugins.freezetimers; + +import lombok.Builder; +import lombok.Getter; +import net.runelite.api.Actor; +import net.runelite.api.coords.LocalPoint; + +@Builder +public class FreezeInfo +{ + @Getter + private final Actor actor; + @Getter + private final LocalPoint freezePoint; +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java index 9a9bf58828..1652556f9b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeTimersOverlay.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2019, ganom + * Copyright (c) 2019, kyle * Copyright (c) 2019, pklite * All rights reserved. * @@ -24,6 +25,7 @@ */ package net.runelite.client.plugins.freezetimers; +import com.google.common.eventbus.Subscribe; import java.awt.Color; import static java.awt.Color.RED; import static java.awt.Color.WHITE; @@ -32,10 +34,14 @@ import java.awt.Font; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.image.BufferedImage; +import java.util.Map; +import java.util.HashMap; import javax.inject.Inject; import net.runelite.api.Actor; import net.runelite.api.Client; +import net.runelite.api.events.PlayerDespawned; import net.runelite.api.GraphicID; +import net.runelite.api.Player; import net.runelite.api.Point; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.Overlay; @@ -47,7 +53,7 @@ import net.runelite.client.util.ImageUtil; public class FreezeTimersOverlay extends Overlay { - + private final Map freezes = new HashMap<>(); private final FreezeTimersConfig config; private final Client client; private final Font timerFont = FontManager.getRunescapeBoldFont().deriveFont(14.0f); @@ -84,6 +90,22 @@ public class FreezeTimersOverlay extends Overlay return null; } + @Subscribe + public void onPlayerDespawned(PlayerDespawned playerDespawned) + { + final Player player = playerDespawned.getPlayer(); + // All despawns ok: death, teleports, log out, runs away from screen + if (config.showPlayers() | config.showNpcs() | config.FreezeTimers() | config.Veng() | config.TB()) + { + this.remove(player); + } + + } + + public void remove(Actor actor) + { + freezes.remove(actor.getName()); + } private void renderOverlayFor(Graphics2D g, Actor actor) { if (timers.areAllTimersZero(actor)) From 279b964b502d62544559286cd8cfb485bb5e0410 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Fri, 17 May 2019 15:14:16 +0200 Subject: [PATCH 22/78] Freezeinfo checkstyle (#286) --- .../client/plugins/freezetimers/FreezeInfo.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java index bc08d81168..f614da97db 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/FreezeInfo.java @@ -6,10 +6,10 @@ import net.runelite.api.Actor; import net.runelite.api.coords.LocalPoint; @Builder -public class FreezeInfo +class FreezeInfo { - @Getter - private final Actor actor; - @Getter - private final LocalPoint freezePoint; + @Getter + private final Actor actor; + @Getter + private final LocalPoint freezePoint; } \ No newline at end of file From eb8077b88585c7cec36aab811b104ffe0c41e9da Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Fri, 17 May 2019 15:40:24 +0200 Subject: [PATCH 23/78] Copy online settings if they're newer than offline (#285) * Copy online settings if they're newer than offline * Add range for opacity --- .../client/account/SessionManager.java | 4 +- .../runelite/client/config/ConfigManager.java | 48 +++++++++++++++---- .../runeliteplus/RuneLitePlusConfig.java | 5 ++ 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java index 4fc8152126..3b86e4b681 100644 --- a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java @@ -147,7 +147,7 @@ public class SessionManager { // Initialize config for new session // If the session isn't logged in yet, don't switch to the new config - configManager.switchSession(session); + configManager.switchSession(); } eventBus.post(new SessionOpen()); @@ -177,7 +177,7 @@ public class SessionManager accountSession = null; // No more account // Restore config - configManager.switchSession(null); + configManager.switchSession(); eventBus.post(new SessionClose()); } diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index b0f42f7bf1..d7d2c52f47 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -62,7 +62,7 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ConfigChanged; import net.runelite.client.RuneLite; -import net.runelite.client.account.AccountSession; +import static net.runelite.client.RuneLite.PROFILES_DIR; import net.runelite.client.eventbus.EventBus; import net.runelite.client.util.ColorUtil; @@ -71,14 +71,14 @@ import net.runelite.client.util.ColorUtil; public class ConfigManager { private static final String SETTINGS_FILE_NAME = "runeliteplus.properties"; + private static final String STANDARD_SETTINGS_FILE_NAME = "settings.properties"; private static final File SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME); - private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, "settings.properties"); + private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, STANDARD_SETTINGS_FILE_NAME); @Inject EventBus eventBus; private final ScheduledExecutorService executor; - private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this); private final Properties properties = new Properties(); private final Map pendingChanges = new HashMap<>(); @@ -91,7 +91,7 @@ public class ConfigManager executor.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS); } - public final void switchSession(AccountSession session) + public final void switchSession() { // Ensure existing config is saved load(); @@ -164,7 +164,7 @@ public class ConfigManager catch (FileNotFoundException ex) { log.debug("Unable to load settings - no such file, syncing from standard settings"); - syncPropertiesFromFile(STANDARD_SETTINGS_FILE); + syncLastModified(); } catch (IllegalArgumentException | IOException ex) { @@ -201,11 +201,11 @@ public class ConfigManager } } - private void saveToFile(final File propertiesFile) throws IOException + private void saveToFile() throws IOException { - propertiesFile.getParentFile().mkdirs(); + ConfigManager.SETTINGS_FILE.getParentFile().mkdirs(); - try (FileOutputStream out = new FileOutputStream(propertiesFile)) + try (FileOutputStream out = new FileOutputStream(ConfigManager.SETTINGS_FILE)) { final FileLock lock = out.getChannel().lock(); @@ -589,7 +589,7 @@ public class ConfigManager { try { - saveToFile(SETTINGS_FILE); + saveToFile(); } catch (IOException ex) { @@ -597,4 +597,32 @@ public class ConfigManager } } } -} + + private void syncLastModified() + { + File newestFile; + + newestFile = STANDARD_SETTINGS_FILE; + + for (File profileDir : PROFILES_DIR.listFiles()) + { + if (!profileDir.isDirectory()) + { + continue; + } + + for (File settings : profileDir.listFiles()) + { + if (!settings.getName().equals(STANDARD_SETTINGS_FILE_NAME) || + settings.lastModified() < newestFile.lastModified()) + { + continue; + } + + newestFile = settings; + } + } + + syncPropertiesFromFile(newestFile); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java index dbdeea12d0..7e666c19b2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java @@ -29,6 +29,7 @@ package net.runelite.client.plugins.runeliteplus; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; @ConfigGroup("runeliteplus") public interface RuneLitePlusConfig extends Config @@ -55,6 +56,10 @@ public interface RuneLitePlusConfig extends Config return false; } + @Range( + min = 15, + max = 100 + ) @ConfigItem( keyName = "opacityPercentage", name = "Opacity percentage", From 4589e39543834be0cadc73eae254f73262ee3da3 Mon Sep 17 00:00:00 2001 From: Ganom Date: Fri, 17 May 2019 09:50:32 -0400 Subject: [PATCH 24/78] Update InfoPanel.java (#282) --- .../client/plugins/info/InfoPanel.java | 622 +++++++++--------- 1 file changed, 311 insertions(+), 311 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java index d9d93d8f23..43a4b09437 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java @@ -1,311 +1,311 @@ -/* - * Copyright (c) 2018 Abex - * Copyright (c) 2018, Psikoi - * 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.info; - -import com.google.common.base.MoreObjects; -import com.google.inject.Inject; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.GridLayout; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.Nullable; -import javax.inject.Singleton; -import javax.swing.Box; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.border.EmptyBorder; -import javax.swing.event.HyperlinkEvent; -import net.runelite.api.Client; -import net.runelite.client.RuneLiteProperties; -import net.runelite.client.account.SessionManager; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.LinkBrowser; - -@Singleton -public class InfoPanel extends PluginPanel -{ - private static final String RUNELITE_LOGIN = "https://runelite_login/"; - - private static final ImageIcon ARROW_RIGHT_ICON; - private static final ImageIcon GITHUB_ICON; - private static final ImageIcon DISCORD_ICON; - private static final ImageIcon PATREON_ICON; - private static final ImageIcon WIKI_ICON; - private static final ImageIcon IMPORT_ICON; - - private final JLabel loggedLabel = new JLabel(); - private final JRichTextPane emailLabel = new JRichTextPane(); - private JPanel syncPanel; - private JPanel actionsContainer; - - @Inject - @Nullable - private Client client; - - @Inject - private RuneLiteProperties runeLiteProperties; - - @Inject - private EventBus eventBus; - - @Inject - private SessionManager sessionManager; - - @Inject - private ScheduledExecutorService executor; - - @Inject - private ConfigManager configManager; - - static - { - ARROW_RIGHT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/util/arrow_right.png")); - GITHUB_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "github_icon.png")); - DISCORD_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "discord_icon.png")); - PATREON_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "patreon_icon.png")); - WIKI_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "wiki_icon.png")); - IMPORT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "import_icon.png")); - } - - void init() - { - setLayout(new BorderLayout()); - setBackground(ColorScheme.DARK_GRAY_COLOR); - setBorder(new EmptyBorder(10, 10, 10, 10)); - - JPanel versionPanel = new JPanel(); - versionPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - versionPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); - versionPanel.setLayout(new GridLayout(0, 1)); - - final Font smallFont = FontManager.getRunescapeSmallFont(); - - JLabel version = new JLabel(htmlLabel("RuneLite version: ", runeLiteProperties.getVersion())); - version.setFont(smallFont); - - JLabel revision = new JLabel(); - revision.setFont(smallFont); - - String engineVer = "Unknown"; - if (client != null) - { - engineVer = String.format("Rev %d", client.getRevision()); - } - - revision.setText(htmlLabel("Oldschool revision: ", engineVer)); - - JLabel launcher = new JLabel(htmlLabel("Launcher version: ", MoreObjects - .firstNonNull(RuneLiteProperties.getLauncherVersion(), "Unknown"))); - launcher.setFont(smallFont); - - loggedLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - loggedLabel.setFont(smallFont); - - emailLabel.setForeground(Color.WHITE); - emailLabel.setFont(smallFont); - emailLabel.enableAutoLinkHandler(false); - emailLabel.addHyperlinkListener(e -> - { - if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null) - { - if (e.getURL().toString().equals(RUNELITE_LOGIN)) - { - executor.execute(sessionManager::login); - } - } - }); - - versionPanel.add(version); - versionPanel.add(revision); - versionPanel.add(launcher); - versionPanel.add(Box.createGlue()); - versionPanel.add(loggedLabel); - versionPanel.add(emailLabel); - - actionsContainer = new JPanel(); - actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0)); - actionsContainer.setLayout(new GridLayout(0, 1, 0, 10)); - - syncPanel = buildLinkPanel(IMPORT_ICON, "Import local settings", "to remote RuneLite account", () -> - { - final int result = JOptionPane.showOptionDialog(syncPanel, - "This will replace your current RuneLite account settings with settings from your local profile.", - "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, - null, new String[]{"Yes", "No"}, "No"); - - if (result == JOptionPane.YES_OPTION) - { - configManager.importLocal(); - } - }); - - actionsContainer.add(buildLinkPanel(GITHUB_ICON, "License info", "for distribution", "https://github.com/runelite-extended/runelite/blob/master/LICENSE")); - actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", "https://discord.gg/s2fzu5U")); - actionsContainer.add(buildLinkPanel(PATREON_ICON, "Patreon to support", "the RuneLite devs", runeLiteProperties.getPatreonLink())); - /* actionsContainer.add(buildLinkPanel(WIKI_ICON, "Information about", "RuneLite and plugins", runeLiteProperties.getWikiLink()));*/ - - add(versionPanel, BorderLayout.NORTH); - add(actionsContainer, BorderLayout.CENTER); - - updateLoggedIn(); - eventBus.register(this); - } - - /** - * Builds a link panel with a given icon, text and url to redirect to. - */ - private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url) - { - return buildLinkPanel(icon, topText, bottomText, () -> LinkBrowser.browse(url)); - } - - /** - * Builds a link panel with a given icon, text and callable to call. - */ - private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, Runnable callback) - { - JPanel container = new JPanel(); - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - container.setLayout(new BorderLayout()); - container.setBorder(new EmptyBorder(10, 10, 10, 10)); - - final Color hoverColor = ColorScheme.DARKER_GRAY_HOVER_COLOR; - final Color pressedColor = ColorScheme.DARKER_GRAY_COLOR.brighter(); - - JLabel iconLabel = new JLabel(icon); - container.add(iconLabel, BorderLayout.WEST); - - JPanel textContainer = new JPanel(); - textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - textContainer.setLayout(new GridLayout(2, 1)); - textContainer.setBorder(new EmptyBorder(5, 10, 5, 10)); - - container.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - container.setBackground(pressedColor); - textContainer.setBackground(pressedColor); - } - - @Override - public void mouseReleased(MouseEvent e) - { - callback.run(); - container.setBackground(hoverColor); - textContainer.setBackground(hoverColor); - } - - @Override - public void mouseEntered(MouseEvent e) - { - container.setBackground(hoverColor); - textContainer.setBackground(hoverColor); - container.setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - @Override - public void mouseExited(MouseEvent e) - { - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - container.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - JLabel topLine = new JLabel(topText); - topLine.setForeground(Color.WHITE); - topLine.setFont(FontManager.getRunescapeSmallFont()); - - JLabel bottomLine = new JLabel(bottomText); - bottomLine.setForeground(Color.WHITE); - bottomLine.setFont(FontManager.getRunescapeSmallFont()); - - textContainer.add(topLine); - textContainer.add(bottomLine); - - container.add(textContainer, BorderLayout.CENTER); - - JLabel arrowLabel = new JLabel(ARROW_RIGHT_ICON); - container.add(arrowLabel, BorderLayout.EAST); - - return container; - } - - private void updateLoggedIn() - { - final String name = sessionManager.getAccountSession() != null - ? sessionManager.getAccountSession().getUsername() - : null; - - if (name != null) - { - emailLabel.setContentType("text/plain"); - emailLabel.setText(name); - loggedLabel.setText("Logged in as"); - actionsContainer.add(syncPanel, 0); - } - else - { - //emailLabel.setContentType("text/html"); - //emailLabel.setText("Login to sync settings to the cloud."); - //loggedLabel.setText("Not logged in"); - actionsContainer.remove(syncPanel); - } - } - - private static String htmlLabel(String key, String value) - { - return "" + key + "" + value + ""; - } - - @Subscribe - public void onSessionOpen(SessionOpen sessionOpen) - { - updateLoggedIn(); - } - - @Subscribe - public void onSessionClose(SessionClose e) - { - updateLoggedIn(); - } -} +/* + * Copyright (c) 2018 Abex + * Copyright (c) 2018, Psikoi + * 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.info; + +import com.google.common.base.MoreObjects; +import com.google.inject.Inject; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.ScheduledExecutorService; +import javax.annotation.Nullable; +import javax.inject.Singleton; +import javax.swing.Box; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import javax.swing.event.HyperlinkEvent; +import net.runelite.api.Client; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.account.SessionManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.LinkBrowser; + +@Singleton +public class InfoPanel extends PluginPanel +{ + private static final String RUNELITE_LOGIN = "https://runelite_login/"; + + private static final ImageIcon ARROW_RIGHT_ICON; + private static final ImageIcon GITHUB_ICON; + private static final ImageIcon DISCORD_ICON; + private static final ImageIcon PATREON_ICON; + private static final ImageIcon WIKI_ICON; + private static final ImageIcon IMPORT_ICON; + + private final JLabel loggedLabel = new JLabel(); + private final JRichTextPane emailLabel = new JRichTextPane(); + private JPanel syncPanel; + private JPanel actionsContainer; + + @Inject + @Nullable + private Client client; + + @Inject + private RuneLiteProperties runeLiteProperties; + + @Inject + private EventBus eventBus; + + @Inject + private SessionManager sessionManager; + + @Inject + private ScheduledExecutorService executor; + + @Inject + private ConfigManager configManager; + + static + { + ARROW_RIGHT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/util/arrow_right.png")); + GITHUB_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "github_icon.png")); + DISCORD_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "discord_icon.png")); + PATREON_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "patreon_icon.png")); + WIKI_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "wiki_icon.png")); + IMPORT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "import_icon.png")); + } + + void init() + { + setLayout(new BorderLayout()); + setBackground(ColorScheme.DARK_GRAY_COLOR); + setBorder(new EmptyBorder(10, 10, 10, 10)); + + JPanel versionPanel = new JPanel(); + versionPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + versionPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + versionPanel.setLayout(new GridLayout(0, 1)); + + final Font smallFont = FontManager.getRunescapeSmallFont(); + + JLabel version = new JLabel(htmlLabel("RuneLite version: ", runeLiteProperties.getVersion())); + version.setFont(smallFont); + + JLabel revision = new JLabel(); + revision.setFont(smallFont); + + String engineVer = "Unknown"; + if (client != null) + { + engineVer = String.format("Rev %d", client.getRevision()); + } + + revision.setText(htmlLabel("Oldschool revision: ", engineVer)); + + JLabel launcher = new JLabel(htmlLabel("Launcher version: ", MoreObjects + .firstNonNull(RuneLiteProperties.getLauncherVersion(), "Unknown"))); + launcher.setFont(smallFont); + + loggedLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + loggedLabel.setFont(smallFont); + + emailLabel.setForeground(Color.WHITE); + emailLabel.setFont(smallFont); + emailLabel.enableAutoLinkHandler(false); + emailLabel.addHyperlinkListener(e -> + { + if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null) + { + if (e.getURL().toString().equals(RUNELITE_LOGIN)) + { + executor.execute(sessionManager::login); + } + } + }); + + versionPanel.add(version); + versionPanel.add(revision); + versionPanel.add(launcher); + versionPanel.add(Box.createGlue()); + versionPanel.add(loggedLabel); + versionPanel.add(emailLabel); + + actionsContainer = new JPanel(); + actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0)); + actionsContainer.setLayout(new GridLayout(0, 1, 0, 10)); + + syncPanel = buildLinkPanel(IMPORT_ICON, "Import local settings", "to remote RuneLite account", () -> + { + final int result = JOptionPane.showOptionDialog(syncPanel, + "This will replace your current RuneLite account settings with settings from your local profile.", + "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, new String[]{"Yes", "No"}, "No"); + + if (result == JOptionPane.YES_OPTION) + { + configManager.importLocal(); + } + }); + + actionsContainer.add(buildLinkPanel(GITHUB_ICON, "License info", "for distribution", "https://github.com/runelite-extended/runelite/blob/master/LICENSE")); + actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", "https://discord.gg/s2fzu5U")); + actionsContainer.add(buildLinkPanel(PATREON_ICON, "Patreon to support", "the RuneLitePlus devs", runeLiteProperties.getPatreonLink())); + /* actionsContainer.add(buildLinkPanel(WIKI_ICON, "Information about", "RuneLite and plugins", runeLiteProperties.getWikiLink()));*/ + + add(versionPanel, BorderLayout.NORTH); + add(actionsContainer, BorderLayout.CENTER); + + updateLoggedIn(); + eventBus.register(this); + } + + /** + * Builds a link panel with a given icon, text and url to redirect to. + */ + private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url) + { + return buildLinkPanel(icon, topText, bottomText, () -> LinkBrowser.browse(url)); + } + + /** + * Builds a link panel with a given icon, text and callable to call. + */ + private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, Runnable callback) + { + JPanel container = new JPanel(); + container.setBackground(ColorScheme.DARKER_GRAY_COLOR); + container.setLayout(new BorderLayout()); + container.setBorder(new EmptyBorder(10, 10, 10, 10)); + + final Color hoverColor = ColorScheme.DARKER_GRAY_HOVER_COLOR; + final Color pressedColor = ColorScheme.DARKER_GRAY_COLOR.brighter(); + + JLabel iconLabel = new JLabel(icon); + container.add(iconLabel, BorderLayout.WEST); + + JPanel textContainer = new JPanel(); + textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); + textContainer.setLayout(new GridLayout(2, 1)); + textContainer.setBorder(new EmptyBorder(5, 10, 5, 10)); + + container.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + container.setBackground(pressedColor); + textContainer.setBackground(pressedColor); + } + + @Override + public void mouseReleased(MouseEvent e) + { + callback.run(); + container.setBackground(hoverColor); + textContainer.setBackground(hoverColor); + } + + @Override + public void mouseEntered(MouseEvent e) + { + container.setBackground(hoverColor); + textContainer.setBackground(hoverColor); + container.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) + { + container.setBackground(ColorScheme.DARKER_GRAY_COLOR); + textContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); + container.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + JLabel topLine = new JLabel(topText); + topLine.setForeground(Color.WHITE); + topLine.setFont(FontManager.getRunescapeSmallFont()); + + JLabel bottomLine = new JLabel(bottomText); + bottomLine.setForeground(Color.WHITE); + bottomLine.setFont(FontManager.getRunescapeSmallFont()); + + textContainer.add(topLine); + textContainer.add(bottomLine); + + container.add(textContainer, BorderLayout.CENTER); + + JLabel arrowLabel = new JLabel(ARROW_RIGHT_ICON); + container.add(arrowLabel, BorderLayout.EAST); + + return container; + } + + private void updateLoggedIn() + { + final String name = sessionManager.getAccountSession() != null + ? sessionManager.getAccountSession().getUsername() + : null; + + if (name != null) + { + emailLabel.setContentType("text/plain"); + emailLabel.setText(name); + loggedLabel.setText("Logged in as"); + actionsContainer.add(syncPanel, 0); + } + else + { + //emailLabel.setContentType("text/html"); + //emailLabel.setText("Login to sync settings to the cloud."); + //loggedLabel.setText("Not logged in"); + actionsContainer.remove(syncPanel); + } + } + + private static String htmlLabel(String key, String value) + { + return "" + key + "" + value + ""; + } + + @Subscribe + public void onSessionOpen(SessionOpen sessionOpen) + { + updateLoggedIn(); + } + + @Subscribe + public void onSessionClose(SessionClose e) + { + updateLoggedIn(); + } +} \ No newline at end of file From 8e06383d1a92493fdc4295763798211ae910b62c Mon Sep 17 00:00:00 2001 From: Ganom Date: Fri, 17 May 2019 16:51:13 -0400 Subject: [PATCH 25/78] Update to Raids, fixes timer issue aswell. --- .../client/plugins/raids/RaidsConfig.java | 32 +++- .../client/plugins/raids/RaidsOverlay.java | 39 +++-- .../client/plugins/raids/RaidsPlugin.java | 105 +++++++----- .../client/plugins/raids/RaidsTimer.java | 150 ++++++++++++++++++ 4 files changed, 258 insertions(+), 68 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java index 14f5add239..751e25d2f2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Kamiel + * Copyright (c) 2019, ganom * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,8 +36,8 @@ public interface RaidsConfig extends Config @ConfigItem( position = 0, keyName = "raidsTimer", - name = "Level time tooltip", - description = "Displays your level times as a tooltip on the points overlay" + name = "Display elapsed raid time", + description = "Display elapsed raid time" ) default boolean raidsTimer() { @@ -168,8 +169,7 @@ public interface RaidsConfig extends Config position = 12, keyName = "enhanceScouterTitle", name = "Enhance scouter title", - description = "Adds #combat and good puzzles to scouter title", - hidden = true + description = "Adds #combat and good puzzles to scouter title" ) default boolean enhanceScouterTitle() { @@ -288,6 +288,28 @@ public interface RaidsConfig extends Config @ConfigItem( position = 25, + keyName = "hideVanguards", + name = "Hide Vanguard raids", + description = "Completely hides raids with Vanguards" + ) + default boolean hideVanguards() + { + return false; + } + + @ConfigItem( + position = 26, + keyName = "hideUnknownCombat", + name = "Hide Unknown combat raids", + description = "Completely hides raids with Unknown combat" + ) + default boolean hideUnknownCombat() + { + return false; + } + + @ConfigItem( + position = 27, keyName = "layoutMessage", name = "Send raid layout message when entering raid", description = "Sends game message with raid layout on entering new raid" @@ -298,7 +320,7 @@ public interface RaidsConfig extends Config } @ConfigItem( - position = 26, + position = 28, keyName = "displayFloorBreak", name = "Layout floor break", description = "Displays floor break in layout" diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java index de7fd5779a..b70bf23621 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Kamiel + * Copyright (c) 2019, ganom * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -151,7 +152,10 @@ public class RaidsOverlay extends Overlay boolean iceDemon = false; boolean tightrope = false; boolean thieving = false; + boolean vanguards = false; + boolean unknownCombat = false; String puzzles = ""; + String roomName = ""; if (config.enhanceScouterTitle() || config.scavsBeforeIce() || sharable) { for (Room layoutRoom : plugin.getRaid().getLayout().getRooms()) @@ -168,9 +172,19 @@ public class RaidsOverlay extends Overlay { case COMBAT: combatCount++; + roomName = room.getBoss().getName(); + switch (RaidRoom.Boss.fromString(roomName)) + { + case VANGUARDS: + vanguards = true; + break; + case UNKNOWN: + unknownCombat = true; + break; + } break; case PUZZLE: - String roomName = room.getPuzzle().getName(); + roomName = room.getPuzzle().getName(); switch (RaidRoom.Puzzle.fromString(roomName)) { case CRABS: @@ -195,13 +209,12 @@ public class RaidsOverlay extends Overlay roomCount++; } if (tightrope) - { puzzles = crabs ? "cr" : iceDemon ? "ri" : thieving ? "tr" : "?r"; - } - else if (config.hideRopeless()) + + if ((config.hideVanguards() && vanguards) || (config.hideRopeless() && !tightrope) || (config.hideUnknownCombat() && unknownCombat)) { panelComponent.getChildren().add(TitleComponent.builder() - .text("No Tightrope!") + .text("Bad Raid!") .color(Color.RED) .build()); @@ -217,9 +230,7 @@ public class RaidsOverlay extends Overlay for (Integer s : scavRooms) { if (s > i) - { break; - } prev = s; } scavsBeforeIceRooms.add(prev); @@ -288,9 +299,7 @@ public class RaidsOverlay extends Overlay if (config.showRecommendedItems()) { if (plugin.getRecommendedItemsList().get(bossNameLC) != null) - { imageIds.addAll(plugin.getRecommendedItemsList().get(bossNameLC)); - } } panelComponent.getChildren().add(LineComponent.builder() @@ -305,9 +314,7 @@ public class RaidsOverlay extends Overlay String puzzleName = room.getPuzzle().getName(); String puzzleNameLC = puzzleName.toLowerCase(); if (plugin.getRecommendedItemsList().get(puzzleNameLC) != null) - { imageIds.addAll(plugin.getRecommendedItemsList().get(puzzleNameLC)); - } if (plugin.getRoomWhitelist().contains(puzzleNameLC)) { color = Color.GREEN; @@ -411,25 +418,15 @@ public class RaidsOverlay extends Overlay { BufferedImage bim; if (id != SpriteID.SPELL_ICE_BARRAGE) - { bim = itemManager.getImage(id); - } else - { bim = spriteManager.getSprite(id, 0); - } if (bim == null) - { return null; - } if (!small) - { return ImageUtil.resizeCanvas(bim, ICON_SIZE, ICON_SIZE); - } if (id != SpriteID.SPELL_ICE_BARRAGE) - { return ImageUtil.resizeImage(bim, SMALL_ICON_SIZE, SMALL_ICON_SIZE); - } return ImageUtil.resizeCanvas(bim, SMALL_ICON_SIZE, SMALL_ICON_SIZE); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 772a9b1b48..615c582606 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Kamiel + * Copyright (c) 2019, ganom * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,6 +29,7 @@ import com.google.inject.Binder; import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.text.DecimalFormat; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -48,6 +50,7 @@ import net.runelite.api.NullObjectID; import static net.runelite.api.Perspective.SCENE_SIZE; import net.runelite.api.Point; import net.runelite.api.SpriteID; +import static net.runelite.api.SpriteID.TAB_QUESTS_BROWN_RAIDING_PARTY; import net.runelite.api.Tile; import net.runelite.api.VarPlayer; import net.runelite.api.Varbits; @@ -96,6 +99,9 @@ import org.apache.commons.lang3.StringUtils; public class RaidsPlugin extends Plugin { private static final int LOBBY_PLANE = 3; + private static final String RAID_START_MESSAGE = "The raid has begun!"; + private static final String LEVEL_COMPLETE_MESSAGE = "level complete!"; + private static final String RAID_COMPLETE_MESSAGE = "Congratulations - your raid is complete!"; private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##"); static final DecimalFormat POINTS_FORMAT = new DecimalFormat("#,###"); private static final String SPLIT_REGEX = "\\s*,\\s*"; @@ -181,6 +187,7 @@ public class RaidsPlugin extends Plugin private String tooltip; public boolean canShow; private NavigationButton navButton; + private RaidsTimer timer; @Provides RaidsConfig provideConfig(ConfigManager configManager) @@ -220,9 +227,11 @@ public class RaidsPlugin extends Plugin overlayManager.remove(overlay); overlayManager.remove(pointsOverlay); clientToolbar.removeNavigation(navButton); + infoBoxManager.removeInfoBox(timer); inRaidChambers = false; widgetOverlay = null; raid = null; + timer = null; final Widget widget = client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX); if (widget != null) @@ -240,6 +249,12 @@ public class RaidsPlugin extends Plugin return; } + if (event.getKey().equals("raidsTimer")) + { + updateInfoBoxState(); + return; + } + updateLists(); clientThread.invokeLater(() -> checkRaidPresence(true)); } @@ -274,26 +289,26 @@ public class RaidsPlugin extends Plugin String message = Text.removeTags(event.getMessage()); Matcher matcher; - matcher = LEVEL_COMPLETE_REGEX.matcher(message); - if (matcher.find()) + if (config.raidsTimer() && message.startsWith(RAID_START_MESSAGE)) { - String floor = matcher.group(1); - int time = timeToSeconds(matcher.group(2)); - if (floor.equals("Upper")) + timer = new RaidsTimer(spriteManager.getSprite(TAB_QUESTS_BROWN_RAIDING_PARTY, 0), this, Instant.now()); + infoBoxManager.addInfoBox(timer); + } + + if (timer != null && message.contains(LEVEL_COMPLETE_MESSAGE)) + { + timer.timeFloor(); + } + + if (message.startsWith(RAID_COMPLETE_MESSAGE)) + { + if (timer != null) { - upperTime = time; - } - else if (floor.equals("Middle")) - { - middleTime = time; - } - else if (floor.equals("Lower")) - { - lowerTime = time; + timer.timeOlm(); + timer.setStopped(true); } updateTooltip(); } - matcher = RAID_COMPLETE_REGEX.matcher(message); if (matcher.find()) { @@ -410,6 +425,7 @@ public class RaidsPlugin extends Plugin if (force || inRaidChambers != setting) { inRaidChambers = setting; + updateInfoBoxState(); if (inRaidChambers) { @@ -434,14 +450,9 @@ public class RaidsPlugin extends Plugin overlay.setScoutOverlayShown(true); sendRaidLayoutMessage(); } - else + else if (!config.scoutOverlayAtBank()) { - if (!config.scoutOverlayAtBank()) - { - overlay.setScoutOverlayShown(false); - } - - reset(); + overlay.setScoutOverlayShown(false); } } @@ -474,6 +485,30 @@ public class RaidsPlugin extends Plugin .build()); } + private void updateInfoBoxState() + { + if (timer == null) + { + return; + } + + if (inRaidChambers && config.raidsTimer()) + { + if (!infoBoxManager.getInfoBoxes().contains(timer)) + { + infoBoxManager.addInfoBox(timer); + } + } + else + { + infoBoxManager.removeInfoBox(timer); + } + + if (!inRaidChambers) + { + timer = null; + } + } private void updateLists() { @@ -494,14 +529,10 @@ public class RaidsPlugin extends Plugin String everything = m.group(1).toLowerCase(); int split = everything.indexOf(','); if (split < 0) - { continue; - } String key = everything.substring(0, split); if (key.length() < 1) - { continue; - } String[] itemNames = everything.substring(split).split(SPLIT_REGEX); map.computeIfAbsent(key, k -> new ArrayList<>()); @@ -509,25 +540,15 @@ public class RaidsPlugin extends Plugin for (String itemName : itemNames) { if (itemName.equals("")) - { continue; - } if (itemName.equals("ice barrage")) - { map.get(key).add(SpriteID.SPELL_ICE_BARRAGE); - } else if (itemName.startsWith("salve")) - { map.get(key).add(ItemID.SALVE_AMULETEI); - } else if (itemManager.search(itemName).size() > 0) - { map.get(key).add(itemManager.search(itemName).get(0).getId()); - } else - { log.info("RaidsPlugin: Could not find an item ID for item: " + itemName); - } } } } @@ -817,7 +838,7 @@ public class RaidsPlugin extends Plugin StringBuilder builder = new StringBuilder(); if (seconds >= 3600) { - builder.append((int) Math.floor(seconds / 3600)).append(";"); + builder.append((int) Math.floor(seconds / 3600) + ";"); } seconds %= 3600; if (builder.toString().equals("")) @@ -842,7 +863,7 @@ public class RaidsPlugin extends Plugin tooltip = null; return; } - builder.append("Upper level: ").append(secondsToTime(upperTime)); + builder.append("Upper level: " + secondsToTime(upperTime)); if (middleTime == -1) { if (lowerTime == -1) @@ -852,12 +873,12 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: ").append(secondsToTime(lowerTime - upperTime)); + builder.append("
Lower level: " + secondsToTime(lowerTime - upperTime)); } } else { - builder.append("
Middle level: ").append(secondsToTime(middleTime - upperTime)); + builder.append("
Middle level: " + secondsToTime(middleTime - upperTime)); if (lowerTime == -1) { tooltip = builder.toString(); @@ -865,7 +886,7 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: ").append(secondsToTime(lowerTime - middleTime)); + builder.append("
Lower level: " + secondsToTime(lowerTime - middleTime)); } } if (raidTime == -1) @@ -873,7 +894,7 @@ public class RaidsPlugin extends Plugin tooltip = builder.toString(); return; } - builder.append("
Olm: ").append(secondsToTime(raidTime - lowerTime)); + builder.append("
Olm: " + secondsToTime(raidTime - lowerTime)); tooltip = builder.toString(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java new file mode 100644 index 0000000000..8df3087054 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018, Kamiel + * 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.raids; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import lombok.Setter; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.ui.overlay.infobox.InfoBox; + +public class RaidsTimer extends InfoBox +{ + private final Instant startTime; + private Instant floorTime; + private LocalTime time; + private LocalTime firstFloorTime; + private LocalTime secondFloorTime; + private LocalTime thirdFloorTime; + private LocalTime olmTime; + + @Setter + private boolean stopped; + + public RaidsTimer(BufferedImage image, Plugin plugin, Instant startTime) + { + super(image, plugin); + this.startTime = startTime; + floorTime = startTime; + stopped = false; + } + + public void timeFloor() + { + Duration elapsed = Duration.between(floorTime, Instant.now()); + + if (firstFloorTime == null) + { + firstFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); + } + else if (secondFloorTime == null) + { + secondFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); + } + else if (thirdFloorTime == null) + { + thirdFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); + } + + floorTime = Instant.now(); + } + + public void timeOlm() + { + Duration elapsed = Duration.between(floorTime, Instant.now()); + olmTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); + } + + @Override + public String getText() + { + if (startTime == null) + { + return ""; + } + + if (!stopped) + { + Duration elapsed = Duration.between(startTime, Instant.now()); + time = LocalTime.ofSecondOfDay(elapsed.getSeconds()); + } + + if (time.getHour() > 0) + { + return time.format(DateTimeFormatter.ofPattern("HH:mm")); + } + + return time.format(DateTimeFormatter.ofPattern("mm:ss")); + } + + @Override + public Color getTextColor() + { + if (stopped) + { + return Color.GREEN; + } + + return Color.WHITE; + } + + @Override + public String getTooltip() + { + StringBuilder builder = new StringBuilder(); + builder.append("Elapsed raid time: "); + builder.append(time.format(DateTimeFormatter.ofPattern("HH:mm:ss"))); + + if (firstFloorTime != null) + { + builder.append("
First floor: "); + builder.append(firstFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); + } + + if (secondFloorTime != null) + { + builder.append("
Second floor: "); + builder.append(secondFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); + } + + if (thirdFloorTime != null) + { + builder.append("
Third floor: "); + builder.append(thirdFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); + } + + if (olmTime != null) + { + builder.append("
Olm: "); + builder.append(olmTime.format(DateTimeFormatter.ofPattern("mm:ss"))); + } + + return builder.toString(); + } +} From af8ba0d8845bf96e534080e552f17ba682dade91 Mon Sep 17 00:00:00 2001 From: Justin Date: Sat, 18 May 2019 14:15:38 +1000 Subject: [PATCH 26/78] Made Fountains easier to see the outline (#291) * Made Fountains easier to see the outline --- .../client/plugins/alchemicalhydra/HydraPoisonOverlay.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java index f4cd114acc..c8ef496ce9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPoisonOverlay.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.alchemicalhydra; +import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; @@ -140,6 +141,7 @@ class HydraPoisonOverlay extends Overlay } graphics.setColor(color); + graphics.setStroke(new BasicStroke(3)); graphics.draw(poly); } -} \ No newline at end of file +} From 863ed09e6640782749dba8f37c23aea2705e5e59 Mon Sep 17 00:00:00 2001 From: James Munson Date: Sat, 18 May 2019 00:22:43 -0700 Subject: [PATCH 27/78] Added recoil and explorers ring to itemcharges, disabled hide statusbar by default --- .../main/java/net/runelite/api/Varbits.java | 8 + .../plugins/itemcharges/ItemChargeConfig.java | 44 +++++ .../itemcharges/ItemChargeOverlay.java | 2 + .../plugins/itemcharges/ItemChargePlugin.java | 55 ++++++ .../itemcharges/ItemExplorerRingOverlay.java | 163 ++++++++++++++++++ .../ItemExplorerRingOverlayMode.java | 33 ++++ .../itemcharges/ItemRecoilOverlay.java | 72 ++++++++ .../plugins/statusbars/StatusBarsConfig.java | 2 +- 8 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemRecoilOverlay.java diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index dccdc89331..595803b711 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -523,6 +523,14 @@ public enum Varbits */ QUEST_TAB(8168), + /** + * Explorer ring + */ + EXPLORER_RING_ALCHTYPE(5398), + EXPLORER_RING_TELEPORTS(4552), + EXPLORER_RING_ALCHS(4554), + EXPLORER_RING_RUNENERGY(4553), + /** * Temple Trekking */ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java index df98a3e738..55fa6ae449 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java @@ -388,4 +388,48 @@ public interface ItemChargeConfig extends Config { return false; } + + @ConfigItem( + keyName = "showrecoil", + name = "Show If Recoil is activated", + description = "Configures if Recoil is activated", + position = 22 + ) + default boolean showrecoil() + { + return false; + } + + @ConfigItem( + keyName = "showExplorer", + name = "Show Explorer's Ring Charges", + description = "Configures if Explorer's Ring charge is shown", + position = 23 + ) + default boolean showExplorer() + { + return false; + } + + @ConfigItem( + keyName = "fontcolor", + name = "Font Color For Explorer's Ring", + description = "Color of the font for the number of charges", + position = 24 + ) + default Color fontColor() + { + return Color.yellow; + } + + @ConfigItem( + keyName = "explorerRingOverlayMode", + name = "Explorer's Ring Display Mode", + description = "Configures where explorer ring overlay is displayed", + position = 25 + ) + default ItemExplorerRingOverlayMode explorerRingOverlayMode() + { + return ItemExplorerRingOverlayMode.BOTH; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java index 5cdb7ae66e..d405225875 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java @@ -41,6 +41,7 @@ import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.WidgetItemOverlay; import net.runelite.client.ui.overlay.components.TextComponent; + class ItemChargeOverlay extends WidgetItemOverlay { private final ItemChargePlugin itemChargePlugin; @@ -150,6 +151,7 @@ class ItemChargeOverlay extends WidgetItemOverlay charges = chargeItem.getCharges(); } + final Rectangle bounds = itemWidget.getCanvasBounds(); final TextComponent textComponent = new TextComponent(); textComponent.setPosition(new diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java index 823a6678b6..03be0e56fd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java @@ -57,6 +57,8 @@ import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.Text; +import static net.runelite.api.ItemID.RING_OF_RECOIL; + @PluginDescriptor( name = "Item Charges", description = "Show number of item charges remaining", @@ -118,6 +120,27 @@ public class ItemChargePlugin extends Plugin private static final int MAX_EXPEDITIOUS_CHARGES = 30; private static final int MAX_BINDING_CHARGES = 16; + public boolean isRingOfRecoilAvailable() + { + return ringOfRecoilAvailable; + } + + private boolean ringOfRecoilAvailable = false; + + boolean isRingOfRecoilEquipped() + { + return ringOfRecoilEquipped; + } + + private boolean ringOfRecoilEquipped = false; + private BufferedImage recoilRingImage; + + BufferedImage getRecoilRingImage() + { + return recoilRingImage; + } + + @Inject private Client client; @@ -127,6 +150,12 @@ public class ItemChargePlugin extends Plugin @Inject private ItemChargeOverlay overlay; + @Inject + private ItemRecoilOverlay recoilOverlay; + + @Inject + private ItemExplorerRingOverlay eRingOverlay; + @Inject private ItemManager itemManager; @@ -152,12 +181,17 @@ public class ItemChargePlugin extends Plugin protected void startUp() { overlayManager.add(overlay); + overlayManager.add(recoilOverlay); + overlayManager.add(eRingOverlay); + recoilRingImage = itemManager.getImage(RING_OF_RECOIL); } @Override protected void shutDown() throws Exception { overlayManager.remove(overlay); + overlayManager.remove(recoilOverlay); + overlayManager.remove(eRingOverlay); infoBoxManager.removeIf(ItemChargeInfobox.class::isInstance); lastCheckTick = -1; } @@ -382,6 +416,27 @@ public class ItemChargePlugin extends Plugin } } + ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); + ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); + ringOfRecoilAvailable = false; + ringOfRecoilEquipped = false; + + Item ring = equipment.getItems()[net.runelite.api.EquipmentInventorySlot.RING.getSlotIdx()]; + if (ring.getId() == RING_OF_RECOIL) + { + ringOfRecoilEquipped = true; + ringOfRecoilAvailable = true; + } + Item[] items = inventory.getItems(); + for (Item item : items) + { + if (item.getId() == RING_OF_RECOIL) + { + ringOfRecoilAvailable = true; + break; + } + } + Widget dialog1 = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT); Widget dialog2 = client.getWidget(WidgetInfo.DIALOG2_SPRITE_TEXT); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java new file mode 100644 index 0000000000..6c678c5eda --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, https://github.com/runeliteplusplus + * 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.itemcharges; + +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.ItemID; +import net.runelite.api.Point; +import net.runelite.api.Varbits; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.WidgetItemOverlay; + +import java.awt.*; +import net.runelite.client.ui.overlay.tooltip.Tooltip; +import net.runelite.client.ui.overlay.tooltip.TooltipManager; + +public class ItemExplorerRingOverlay extends WidgetItemOverlay +{ + private static final Varbits TELEPORTS = Varbits.EXPLORER_RING_TELEPORTS; + private static final Varbits ALCHS = Varbits.EXPLORER_RING_ALCHS; + private static final Varbits RUNENERGY = Varbits.EXPLORER_RING_RUNENERGY; + private static final Varbits ALCHTYPE = Varbits.EXPLORER_RING_ALCHTYPE; + + private static final int MAX_ALCHS = 30; + private static final int MAX_TELEPORTS = 3; + private static final int[] MAX_RUNREPLENISH = { + 2, /* Explorer's ring 1 */ + 3, + 4, + 3 + }; + + private final Client client; + private final ItemChargeConfig config; + private final TooltipManager tooltipManager; + + @Inject + ItemExplorerRingOverlay(Client client, ItemChargeConfig config, TooltipManager tooltipManager) + { + this.client = client; + this.config = config; + this.tooltipManager = tooltipManager; + + showOnInventory(); + showOnEquipment(); + } + + @Override + public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem itemWidget) + { + if (config.showExplorer()) + { + if (itemId < ItemID.EXPLORERS_RING_1 || itemId > ItemID.EXPLORERS_RING_4) + return; + + graphics.setFont(FontManager.getRunescapeSmallFont()); + + Point location = itemWidget.getCanvasLocation(); + StringBuilder tooltipBuilder = new StringBuilder(); + + // Pen position tracking. + int penShadowX = location.getX() + 1; + int penX = location.getX(); + int penShadowY = location.getY(); + int penY = location.getY(); + + // Alchemy (level 4 ring is High Alc) + int alchAmount = MAX_ALCHS - client.getVar(ALCHS); + if (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.MOUSE_HOVER) + { + String alchStr = "A: " + alchAmount; + + penShadowY += 1 + (graphics.getFontMetrics().getHeight() - 1); + graphics.setColor(Color.BLACK); + graphics.drawString(alchStr, penShadowX, + penShadowY); + + penY += (graphics.getFontMetrics().getHeight() - 1); + graphics.setColor(config.fontColor()); + graphics.drawString(alchStr, penX, + penY); + } + + tooltipBuilder.append("Alchs: " + alchAmount + "
"); + + // Run energy + int runAmount = MAX_RUNREPLENISH[itemId - ItemID.EXPLORERS_RING_1] - client.getVar(RUNENERGY); + + if (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.MOUSE_HOVER) + { + String runStr = "R: " + runAmount; + + penShadowY += 1 + (graphics.getFontMetrics().getHeight() - 1); + graphics.setColor(Color.BLACK); + graphics.drawString(runStr, penShadowX, + penShadowY); + + penY += (graphics.getFontMetrics().getHeight() - 1); + graphics.setColor(config.fontColor()); + graphics.drawString(runStr, penX, + penY); + } + + tooltipBuilder.append("Run Replenish: " + runAmount + "
"); + + // Teleport charges (unique to level 2 ring). + if (itemId == ItemID.EXPLORERS_RING_2) + { + int teleAmount = MAX_TELEPORTS - client.getVar(TELEPORTS); + + if (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.MOUSE_HOVER) + { + String teleStr = "T: " + teleAmount; + + penShadowY += 1 + (graphics.getFontMetrics().getHeight() - 1); + graphics.setColor(Color.BLACK); + graphics.drawString(teleStr, penShadowX + 1, + penShadowY); + + penY += (graphics.getFontMetrics().getHeight() - 1); + graphics.setColor(config.fontColor()); + graphics.drawString(teleStr, penX + 1, + penY); + } + + tooltipBuilder.append("Teleports: " + teleAmount + "
"); + } + + // Display tooltip + String finalTooltip = tooltipBuilder.toString(); + if (!finalTooltip.isEmpty() && + (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.INVENTORY) && + itemWidget.getCanvasBounds().contains(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY())) + { + tooltipManager.add(new Tooltip(finalTooltip)); + } + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java new file mode 100644 index 0000000000..7d0c5a05cc --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, https://github.com/runeliteplusplus + * 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.itemcharges; + +public enum ItemExplorerRingOverlayMode +{ + INVENTORY, + MOUSE_HOVER, + BOTH +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemRecoilOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemRecoilOverlay.java new file mode 100644 index 0000000000..6828fbb646 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemRecoilOverlay.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, https://github.com/runeliteplusplus + * 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.itemcharges; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ImageComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +class ItemRecoilOverlay extends Overlay +{ + private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150); + private static final Color ACTIVATED_BACKGROUND_COLOR = new Color(0, 150, 0, 150); + private final ItemChargePlugin plugin; + private final ItemChargeConfig config; + private final PanelComponent imagePanelComponent = new PanelComponent(); + + @Inject + public ItemRecoilOverlay(Client client, ItemChargePlugin plugin, ItemChargeConfig config) + { + setPosition(OverlayPosition.TOP_LEFT); + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + this.imagePanelComponent.getChildren().clear(); + if (config.showrecoil()) + { + if (plugin.isRingOfRecoilAvailable()) + { + BufferedImage recoilImage = plugin.getRecoilRingImage(); + imagePanelComponent.setBackgroundColor(plugin + .isRingOfRecoilEquipped() ? ACTIVATED_BACKGROUND_COLOR : NOT_ACTIVATED_BACKGROUND_COLOR); + imagePanelComponent.getChildren().add(new ImageComponent(recoilImage)); + return imagePanelComponent.render(graphics); + } + } + return null; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java index 58842332e2..573e561e2d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java @@ -72,7 +72,7 @@ public interface StatusBarsConfig extends Config ) default boolean toggleRestorationBars() { - return true; + return false; } @ConfigItem( From 341ea528f709784b465f943a56efff1b6e0ae1fc Mon Sep 17 00:00:00 2001 From: Justin Date: Sat, 18 May 2019 21:32:00 +1000 Subject: [PATCH 28/78] Moved Climb-Up/Down plugin into MenuEntrySwapper --- .../plugins/climbupclimbdown/ClimbPlugin.java | 111 ------------------ .../ShiftCtrlInputListener.java | 62 ---------- .../MenuEntrySwapperConfig.java | 10 ++ .../MenuEntrySwapperPlugin.java | 33 ++++++ .../ShiftClickInputListener.java | 8 ++ 5 files changed, 51 insertions(+), 173 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ClimbPlugin.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ShiftCtrlInputListener.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ClimbPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ClimbPlugin.java deleted file mode 100644 index 4bc899a5e4..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ClimbPlugin.java +++ /dev/null @@ -1,111 +0,0 @@ -package net.runelite.client.plugins.climbupclimbdown; - -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.MenuEntry; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; - -@PluginDescriptor( - name = "Climb Up Climb Down", - description = "Hold Shift to Climb up, Ctrl to Climb down", - tags = {"climb", "stairs", "ladder", "swap", "key", "input"}, - type = PluginType.UTILITY -) -@Slf4j -@Singleton -public class ClimbPlugin extends Plugin -{ - - @Inject - Client client; - - @Inject - KeyManager keyManager; - - @Inject - ShiftCtrlInputListener inputListener; - - @Getter - @Setter - private boolean isHoldingShift; - - @Getter - @Setter - private boolean isHoldingCtrl; - - @Override - protected void startUp() throws Exception - { - enableCustomization(); - } - - @Override - protected void shutDown() throws Exception - { - disableCustomization(); - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) - { - try - { - if (menuEntryAdded.getOption().equalsIgnoreCase("climb")) - { - if (isHoldingCtrl ^ isHoldingShift) - { - if (isHoldingShift) - { - stripExceptFor("climb-up"); - } - if (isHoldingCtrl) - { - stripExceptFor("climb-down"); - } - } - } - } - catch (Exception e) - { - log.error("Uh oh!", e); - } - } - - - private void enableCustomization() - { - keyManager.registerKeyListener(inputListener); - } - - private void disableCustomization() - { - keyManager.unregisterKeyListener(inputListener); - } - - private void stripExceptFor(String option) - { - MenuEntry[] newEntries = new MenuEntry[1]; - - for (MenuEntry entry : client.getMenuEntries()) - { - if (entry.getOption().equalsIgnoreCase(option)) - { - newEntries[0] = entry; - } - } - - if (newEntries[0] != null) - { - client.setMenuEntries(newEntries); - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ShiftCtrlInputListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ShiftCtrlInputListener.java deleted file mode 100644 index 4535c116ba..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/climbupclimbdown/ShiftCtrlInputListener.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.runelite.client.plugins.climbupclimbdown; - -import java.awt.event.KeyEvent; -import javax.inject.Inject; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.input.KeyListener; - -@Slf4j -public class ShiftCtrlInputListener implements KeyListener -{ - @Inject - ClimbPlugin plugin; - - @Override - public void keyTyped(KeyEvent e) - { - } - - @Override - public void keyPressed(KeyEvent e) - { - switch (e.getKeyCode()) - { - case KeyEvent.VK_SHIFT: - if (plugin.isHoldingShift()) - { - return; - } - plugin.setHoldingShift(true); - break; - case KeyEvent.VK_CONTROL: - if (plugin.isHoldingCtrl()) - { - return; - } - plugin.setHoldingCtrl(true); - break; - } - } - - @Override - public void keyReleased(KeyEvent e) - { - switch (e.getKeyCode()) - { - case KeyEvent.VK_SHIFT: - if (!plugin.isHoldingShift()) - { - return; - } - plugin.setHoldingShift(false); - break; - case KeyEvent.VK_CONTROL: - if (!plugin.isHoldingCtrl()) - { - return; - } - plugin.setHoldingCtrl(false); - break; - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java index fbfe53c822..f1a39f4427 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java @@ -302,4 +302,14 @@ public interface MenuEntrySwapperConfig extends Config { return true; } + + @ConfigItem( + keyName = "swapClimbUpDown", + name = "Climb", + description = "Swap Climb-Up/Down depending on Shift or Control key " + ) + default boolean swapClimbUpDown() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 0308323471..39f54920f6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -128,9 +128,14 @@ public class MenuEntrySwapperPlugin extends Plugin @Getter private boolean configuringShiftClick = false; + @Getter @Setter private boolean shiftModifier = false; + @Getter + @Setter + private boolean controlModifier = false; + @Provides MenuEntrySwapperConfig provideConfig(ConfigManager configManager) { @@ -452,6 +457,16 @@ public class MenuEntrySwapperPlugin extends Plugin } } + else if (option.equalsIgnoreCase("climb") && config.swapClimbUpDown()) { + if (controlModifier ^ shiftModifier) { + if (shiftModifier) { + stripExceptFor("climb-up"); + } + if (controlModifier) { + stripExceptFor("climb-down"); + } + } + } else if (config.swapTravel() && option.equals("pass") && target.equals("energy barrier")) { swap(client, "pay-toll(2-ecto)", option, target, true); @@ -603,6 +618,24 @@ public class MenuEntrySwapperPlugin extends Plugin } } + private void stripExceptFor(String option) + { + MenuEntry[] newEntries = new MenuEntry[1]; + + for (MenuEntry entry : client.getMenuEntries()) + { + if (entry.getOption().equalsIgnoreCase(option)) + { + newEntries[0] = entry; + } + } + + if (newEntries[0] != null) + { + client.setMenuEntries(newEntries); + } + } + @Subscribe public void onPostItemComposition(PostItemComposition event) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java index f7dde77e00..cea447b527 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java @@ -54,6 +54,10 @@ public class ShiftClickInputListener implements KeyListener { plugin.setShiftModifier(true); } + if (event.getKeyCode() == KeyEvent.VK_CONTROL) + { + plugin.setControlModifier(true); + } } @Override @@ -63,5 +67,9 @@ public class ShiftClickInputListener implements KeyListener { plugin.setShiftModifier(false); } + if (event.getKeyCode() == KeyEvent.VK_CONTROL) + { + plugin.setControlModifier(false); + } } } From 7e41f58fa282563dcf5dadde11fad3d2a1352122 Mon Sep 17 00:00:00 2001 From: Justin Date: Sat, 18 May 2019 22:10:36 +1000 Subject: [PATCH 29/78] Checkstyle fixes --- .../menuentryswapper/MenuEntrySwapperPlugin.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 39f54920f6..e20ead4eeb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -457,12 +457,16 @@ public class MenuEntrySwapperPlugin extends Plugin } } - else if (option.equalsIgnoreCase("climb") && config.swapClimbUpDown()) { - if (controlModifier ^ shiftModifier) { - if (shiftModifier) { + else if (option.equalsIgnoreCase("climb") && config.swapClimbUpDown()) + { + if (controlModifier ^ shiftModifier) + { + if (shiftModifier) + { stripExceptFor("climb-up"); } - if (controlModifier) { + if (controlModifier) + { stripExceptFor("climb-down"); } } From d8bb022e4eaacc263c0052e41aefd2c0267f2755 Mon Sep 17 00:00:00 2001 From: Justin Date: Sat, 18 May 2019 22:26:46 +1000 Subject: [PATCH 30/78] Added copyright text to TickCounter plugin - sourced author from original push request --- .../tickcounter/TickCounterConfig.java | 25 +++++++++++++++++++ .../tickcounter/TickCounterOverlay.java | 25 +++++++++++++++++++ .../tickcounter/TickCounterPlugin.java | 25 +++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterConfig.java index a08f012e7a..ef349f58d1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterConfig.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2018, James Munson + * 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 HOLDER 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.tickcounter; import java.awt.Color; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java index 397392ad8c..2a05b06833 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2018, James Munson + * 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 HOLDER 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.tickcounter; import java.awt.Dimension; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterPlugin.java index fd4a8a935a..11c9d349d6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterPlugin.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2018, James Munson + * 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 HOLDER 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.tickcounter; import com.google.inject.Provides; From 92a4d718af7867360c72f14c636db4df5f508da5 Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 19 May 2019 01:43:09 +1000 Subject: [PATCH 31/78] Added COX Olm attacking projectile IDs (#293) * Added COX Olm attacking projectile IDs added OLM_MAGE_ATTACK and OLM_RANGE_ATTACK ids * no hardcoded projectiles removed two hardcoded projectiles for olm attacks --- .../src/main/java/net/runelite/api/ProjectileID.java | 4 +++- .../java/net/runelite/client/plugins/zcox/CoxPlugin.java | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/ProjectileID.java b/runelite-api/src/main/java/net/runelite/api/ProjectileID.java index c7d9c836cc..5dff0bc450 100644 --- a/runelite-api/src/main/java/net/runelite/api/ProjectileID.java +++ b/runelite-api/src/main/java/net/runelite/api/ProjectileID.java @@ -49,7 +49,9 @@ public class ProjectileID public static final int OLM_FALLING_CRYSTAL_TRAIL = 1352; public static final int OLM_ACID_TRAIL = 1354; public static final int OLM_FIRE_LINE = 1347; - + public static final int OLM_MAGE_ATTACK = 1339; + public static final int OLM_RANGE_ATTACK = 1340; + public static final int VORKATH_BOMB_AOE = 1481; public static final int VORKATH_POISON_POOL_AOE = 1483; public static final int VORKATH_TICK_FIRE_AOE = 1482; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zcox/CoxPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zcox/CoxPlugin.java index 477acadb43..d1450ad838 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zcox/CoxPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zcox/CoxPlugin.java @@ -41,6 +41,7 @@ import net.runelite.api.MessageNode; import net.runelite.api.NPC; import net.runelite.api.NpcID; import net.runelite.api.Projectile; +import net.runelite.api.ProjectileID; import net.runelite.api.Varbits; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; @@ -269,13 +270,13 @@ public class CoxPlugin extends Plugin public void onProjectileMoved(ProjectileMoved event) { Projectile projectile = event.getProjectile(); - if (projectile.getId() == 1339) + if (projectile.getId() == ProjectileID.OLM_MAGE_ATTACK) { log.debug("Mage Detected"); prayAgainstOlm = PrayAgainst.MAGIC; lastPrayTime = System.currentTimeMillis(); } - if (projectile.getId() == 1340) + if (projectile.getId() == ProjectileID.OLM_RANGE_ATTACK) { log.debug("Range Detected"); prayAgainstOlm = PrayAgainst.RANGED; From 1bfb925b2bccb946f26c51d0c95d55e0b6d3788a Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 19 May 2019 01:46:03 +1000 Subject: [PATCH 32/78] fixed incorrect ID (#297) closes #296 --- .../client/plugins/raids/shortcuts/ShortcutOverlay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java index 6ae37169e8..315346882e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java @@ -68,7 +68,7 @@ public class ShortcutOverlay extends Overlay case 29738: name = "Rocks"; break; - case 297480: + case 29748: name = "Boulder"; break; case 29737: From c8b556f391890fd141a9b5a15c3deb0e70221455 Mon Sep 17 00:00:00 2001 From: Ganom Date: Sat, 18 May 2019 12:27:34 -0400 Subject: [PATCH 33/78] Adding Braces --- .../runelite/client/plugins/raids/RaidsPlugin.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 615c582606..92dfdbbc14 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -529,10 +529,14 @@ public class RaidsPlugin extends Plugin String everything = m.group(1).toLowerCase(); int split = everything.indexOf(','); if (split < 0) + { continue; + } String key = everything.substring(0, split); if (key.length() < 1) + { continue; + } String[] itemNames = everything.substring(split).split(SPLIT_REGEX); map.computeIfAbsent(key, k -> new ArrayList<>()); @@ -540,15 +544,25 @@ public class RaidsPlugin extends Plugin for (String itemName : itemNames) { if (itemName.equals("")) + { continue; + } if (itemName.equals("ice barrage")) + { map.get(key).add(SpriteID.SPELL_ICE_BARRAGE); + } else if (itemName.startsWith("salve")) + { map.get(key).add(ItemID.SALVE_AMULETEI); + } else if (itemManager.search(itemName).size() > 0) + { map.get(key).add(itemManager.search(itemName).get(0).getId()); + } else + { log.info("RaidsPlugin: Could not find an item ID for item: " + itemName); + } } } } From 2347253b269791310e19e5aaa51fe1b71d02ba7b Mon Sep 17 00:00:00 2001 From: Ganom Date: Sat, 18 May 2019 12:28:53 -0400 Subject: [PATCH 34/78] Adding Braces --- .../client/plugins/raids/RaidsOverlay.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java index b70bf23621..784b2a9afe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java @@ -209,7 +209,9 @@ public class RaidsOverlay extends Overlay roomCount++; } if (tightrope) + { puzzles = crabs ? "cr" : iceDemon ? "ri" : thieving ? "tr" : "?r"; + } if ((config.hideVanguards() && vanguards) || (config.hideRopeless() && !tightrope) || (config.hideUnknownCombat() && unknownCombat)) { @@ -230,7 +232,9 @@ public class RaidsOverlay extends Overlay for (Integer s : scavRooms) { if (s > i) + { break; + } prev = s; } scavsBeforeIceRooms.add(prev); @@ -299,7 +303,9 @@ public class RaidsOverlay extends Overlay if (config.showRecommendedItems()) { if (plugin.getRecommendedItemsList().get(bossNameLC) != null) + { imageIds.addAll(plugin.getRecommendedItemsList().get(bossNameLC)); + } } panelComponent.getChildren().add(LineComponent.builder() @@ -314,7 +320,9 @@ public class RaidsOverlay extends Overlay String puzzleName = room.getPuzzle().getName(); String puzzleNameLC = puzzleName.toLowerCase(); if (plugin.getRecommendedItemsList().get(puzzleNameLC) != null) + { imageIds.addAll(plugin.getRecommendedItemsList().get(puzzleNameLC)); + } if (plugin.getRoomWhitelist().contains(puzzleNameLC)) { color = Color.GREEN; @@ -418,15 +426,25 @@ public class RaidsOverlay extends Overlay { BufferedImage bim; if (id != SpriteID.SPELL_ICE_BARRAGE) + { bim = itemManager.getImage(id); + } else + { bim = spriteManager.getSprite(id, 0); + } if (bim == null) + { return null; + } if (!small) + { return ImageUtil.resizeCanvas(bim, ICON_SIZE, ICON_SIZE); + } if (id != SpriteID.SPELL_ICE_BARRAGE) + { return ImageUtil.resizeImage(bim, SMALL_ICON_SIZE, SMALL_ICON_SIZE); + } return ImageUtil.resizeCanvas(bim, SMALL_ICON_SIZE, SMALL_ICON_SIZE); } } From 4dc9d2f60c9247f32787e51907e3af87187c6c48 Mon Sep 17 00:00:00 2001 From: Ganom Date: Sat, 18 May 2019 12:32:28 -0400 Subject: [PATCH 35/78] Revert append change. --- .../net/runelite/client/plugins/raids/RaidsPlugin.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 92dfdbbc14..4c0b9fc28c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -877,7 +877,7 @@ public class RaidsPlugin extends Plugin tooltip = null; return; } - builder.append("Upper level: " + secondsToTime(upperTime)); + builder.append("Upper level: ").append(secondsToTime(upperTime)); if (middleTime == -1) { if (lowerTime == -1) @@ -887,12 +887,12 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: " + secondsToTime(lowerTime - upperTime)); + builder.append("
Lower level: ").append(secondsToTime(lowerTime - upperTime)); } } else { - builder.append("
Middle level: " + secondsToTime(middleTime - upperTime)); + builder.append("
Middle level: ").append(secondsToTime(middleTime - upperTime)); if (lowerTime == -1) { tooltip = builder.toString(); @@ -900,7 +900,7 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: " + secondsToTime(lowerTime - middleTime)); + builder.append("
Lower level: ").append(secondsToTime(lowerTime - middleTime)); } } if (raidTime == -1) @@ -908,7 +908,7 @@ public class RaidsPlugin extends Plugin tooltip = builder.toString(); return; } - builder.append("
Olm: " + secondsToTime(raidTime - lowerTime)); + builder.append("
Olm: ").append(secondsToTime(raidTime - lowerTime)); tooltip = builder.toString(); } } From 26fd53aa8f95ec7a1b3f208a4df59566e1e291f6 Mon Sep 17 00:00:00 2001 From: James Munson Date: Sat, 18 May 2019 09:58:16 -0700 Subject: [PATCH 36/78] removed explorers ring --- .../plugins/itemcharges/ItemChargeConfig.java | 33 ---- .../plugins/itemcharges/ItemChargePlugin.java | 5 - .../itemcharges/ItemExplorerRingOverlay.java | 163 ------------------ .../ItemExplorerRingOverlayMode.java | 33 ---- 4 files changed, 234 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java index 55fa6ae449..7bb41bfabf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java @@ -399,37 +399,4 @@ public interface ItemChargeConfig extends Config { return false; } - - @ConfigItem( - keyName = "showExplorer", - name = "Show Explorer's Ring Charges", - description = "Configures if Explorer's Ring charge is shown", - position = 23 - ) - default boolean showExplorer() - { - return false; - } - - @ConfigItem( - keyName = "fontcolor", - name = "Font Color For Explorer's Ring", - description = "Color of the font for the number of charges", - position = 24 - ) - default Color fontColor() - { - return Color.yellow; - } - - @ConfigItem( - keyName = "explorerRingOverlayMode", - name = "Explorer's Ring Display Mode", - description = "Configures where explorer ring overlay is displayed", - position = 25 - ) - default ItemExplorerRingOverlayMode explorerRingOverlayMode() - { - return ItemExplorerRingOverlayMode.BOTH; - } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java index 03be0e56fd..94c5862bc2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java @@ -153,9 +153,6 @@ public class ItemChargePlugin extends Plugin @Inject private ItemRecoilOverlay recoilOverlay; - @Inject - private ItemExplorerRingOverlay eRingOverlay; - @Inject private ItemManager itemManager; @@ -182,7 +179,6 @@ public class ItemChargePlugin extends Plugin { overlayManager.add(overlay); overlayManager.add(recoilOverlay); - overlayManager.add(eRingOverlay); recoilRingImage = itemManager.getImage(RING_OF_RECOIL); } @@ -191,7 +187,6 @@ public class ItemChargePlugin extends Plugin { overlayManager.remove(overlay); overlayManager.remove(recoilOverlay); - overlayManager.remove(eRingOverlay); infoBoxManager.removeIf(ItemChargeInfobox.class::isInstance); lastCheckTick = -1; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java deleted file mode 100644 index 6c678c5eda..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlay.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * Copyright (c) 2018, https://github.com/runeliteplusplus - * 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.itemcharges; - -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.ItemID; -import net.runelite.api.Point; -import net.runelite.api.Varbits; -import net.runelite.api.widgets.WidgetItem; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.overlay.WidgetItemOverlay; - -import java.awt.*; -import net.runelite.client.ui.overlay.tooltip.Tooltip; -import net.runelite.client.ui.overlay.tooltip.TooltipManager; - -public class ItemExplorerRingOverlay extends WidgetItemOverlay -{ - private static final Varbits TELEPORTS = Varbits.EXPLORER_RING_TELEPORTS; - private static final Varbits ALCHS = Varbits.EXPLORER_RING_ALCHS; - private static final Varbits RUNENERGY = Varbits.EXPLORER_RING_RUNENERGY; - private static final Varbits ALCHTYPE = Varbits.EXPLORER_RING_ALCHTYPE; - - private static final int MAX_ALCHS = 30; - private static final int MAX_TELEPORTS = 3; - private static final int[] MAX_RUNREPLENISH = { - 2, /* Explorer's ring 1 */ - 3, - 4, - 3 - }; - - private final Client client; - private final ItemChargeConfig config; - private final TooltipManager tooltipManager; - - @Inject - ItemExplorerRingOverlay(Client client, ItemChargeConfig config, TooltipManager tooltipManager) - { - this.client = client; - this.config = config; - this.tooltipManager = tooltipManager; - - showOnInventory(); - showOnEquipment(); - } - - @Override - public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem itemWidget) - { - if (config.showExplorer()) - { - if (itemId < ItemID.EXPLORERS_RING_1 || itemId > ItemID.EXPLORERS_RING_4) - return; - - graphics.setFont(FontManager.getRunescapeSmallFont()); - - Point location = itemWidget.getCanvasLocation(); - StringBuilder tooltipBuilder = new StringBuilder(); - - // Pen position tracking. - int penShadowX = location.getX() + 1; - int penX = location.getX(); - int penShadowY = location.getY(); - int penY = location.getY(); - - // Alchemy (level 4 ring is High Alc) - int alchAmount = MAX_ALCHS - client.getVar(ALCHS); - if (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.MOUSE_HOVER) - { - String alchStr = "A: " + alchAmount; - - penShadowY += 1 + (graphics.getFontMetrics().getHeight() - 1); - graphics.setColor(Color.BLACK); - graphics.drawString(alchStr, penShadowX, - penShadowY); - - penY += (graphics.getFontMetrics().getHeight() - 1); - graphics.setColor(config.fontColor()); - graphics.drawString(alchStr, penX, - penY); - } - - tooltipBuilder.append("Alchs: " + alchAmount + "
"); - - // Run energy - int runAmount = MAX_RUNREPLENISH[itemId - ItemID.EXPLORERS_RING_1] - client.getVar(RUNENERGY); - - if (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.MOUSE_HOVER) - { - String runStr = "R: " + runAmount; - - penShadowY += 1 + (graphics.getFontMetrics().getHeight() - 1); - graphics.setColor(Color.BLACK); - graphics.drawString(runStr, penShadowX, - penShadowY); - - penY += (graphics.getFontMetrics().getHeight() - 1); - graphics.setColor(config.fontColor()); - graphics.drawString(runStr, penX, - penY); - } - - tooltipBuilder.append("Run Replenish: " + runAmount + "
"); - - // Teleport charges (unique to level 2 ring). - if (itemId == ItemID.EXPLORERS_RING_2) - { - int teleAmount = MAX_TELEPORTS - client.getVar(TELEPORTS); - - if (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.MOUSE_HOVER) - { - String teleStr = "T: " + teleAmount; - - penShadowY += 1 + (graphics.getFontMetrics().getHeight() - 1); - graphics.setColor(Color.BLACK); - graphics.drawString(teleStr, penShadowX + 1, - penShadowY); - - penY += (graphics.getFontMetrics().getHeight() - 1); - graphics.setColor(config.fontColor()); - graphics.drawString(teleStr, penX + 1, - penY); - } - - tooltipBuilder.append("Teleports: " + teleAmount + "
"); - } - - // Display tooltip - String finalTooltip = tooltipBuilder.toString(); - if (!finalTooltip.isEmpty() && - (config.explorerRingOverlayMode() != ItemExplorerRingOverlayMode.INVENTORY) && - itemWidget.getCanvasBounds().contains(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY())) - { - tooltipManager.add(new Tooltip(finalTooltip)); - } - } - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java deleted file mode 100644 index 7d0c5a05cc..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemExplorerRingOverlayMode.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * Copyright (c) 2018, https://github.com/runeliteplusplus - * 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.itemcharges; - -public enum ItemExplorerRingOverlayMode -{ - INVENTORY, - MOUSE_HOVER, - BOTH -} \ No newline at end of file From 4023bd2e57e14631fc0dfaba7cfad7940bfdd41a Mon Sep 17 00:00:00 2001 From: James Munson Date: Sat, 18 May 2019 09:59:45 -0700 Subject: [PATCH 37/78] Fix --- .../runelite/client/plugins/itemcharges/ItemChargeOverlay.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java index d405225875..5cdb7ae66e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java @@ -41,7 +41,6 @@ import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.WidgetItemOverlay; import net.runelite.client.ui.overlay.components.TextComponent; - class ItemChargeOverlay extends WidgetItemOverlay { private final ItemChargePlugin itemChargePlugin; @@ -151,7 +150,6 @@ class ItemChargeOverlay extends WidgetItemOverlay charges = chargeItem.getCharges(); } - final Rectangle bounds = itemWidget.getCanvasBounds(); final TextComponent textComponent = new TextComponent(); textComponent.setPosition(new From 347f0c0d24e4e9fa08da6f59a27674a8f927f4c5 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 18 May 2019 21:45:34 +0100 Subject: [PATCH 38/78] Hide Prayer Reformat (#299) * prayer bringup prayer bringup recoded to use switches instead of if's. * fix checkstyle fix checkstyle * Update HidePrayersPVMPlugin.java fix --- .../plugins/hideprayers/PVM/Armadyl.java | 47 --- .../plugins/hideprayers/PVM/Bandos.java | 47 --- .../plugins/hideprayers/PVM/Barrows.java | 47 --- .../hideprayers/PVM/HidePrayersPVMConfig.java | 100 +---- .../hideprayers/PVM/HidePrayersPVMPlugin.java | 385 ++++++++---------- .../PVM/{Cerberus.java => PVMPrayers.java} | 20 +- .../plugins/hideprayers/PVM/Saradomin.java | 47 --- .../plugins/hideprayers/PVM/Vorkath.java | 47 --- .../plugins/hideprayers/PVM/Zamorak.java | 47 --- .../plugins/hideprayers/PVM/Zulrah.java | 47 --- .../hideprayers/PVP/HidePrayersPVPConfig.java | 24 +- .../hideprayers/PVP/HidePrayersPVPPlugin.java | 380 ++++++++--------- 12 files changed, 382 insertions(+), 856 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Armadyl.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Bandos.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Barrows.java rename runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/{Cerberus.java => PVMPrayers.java} (76%) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Saradomin.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Vorkath.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zamorak.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zulrah.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Armadyl.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Armadyl.java deleted file mode 100644 index fabdb13e33..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Armadyl.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.hideprayers.PVM; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum Armadyl -{ - DISABLED("Disabled"), - ARMADYL_CHEAP("Eagle eye"), - ARMADYL_EXPENSIVE("Rigour"); - - private String name; - - @Override - public String toString() - { - return getName(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Bandos.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Bandos.java deleted file mode 100644 index ef688cd8ed..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Bandos.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.hideprayers.PVM; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum Bandos -{ - DISABLED("Disabled"), - BANDOS_CHEAP("Low LVL Melee"), - BANDOS_EXPENSIVE("Piety"); - - private String name; - - @Override - public String toString() - { - return getName(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Barrows.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Barrows.java deleted file mode 100644 index e09c13d607..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Barrows.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.hideprayers.PVM; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum Barrows -{ - DISABLED("Disabled"), - BARROWS_CHEAP("Eagle/Mystic"), - BARROWS_EXPENSIVE("Augury/Rigour"); - - private String name; - - @Override - public String toString() - { - return getName(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java index a66461482c..31de44631b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMConfig.java @@ -35,98 +35,14 @@ import net.runelite.client.config.ConfigItem; public interface HidePrayersPVMConfig extends Config { @ConfigItem - ( - position = 0, - keyName = "Barrows", - name = "Barrows", - description = "Shows prayers for Barrows" - ) - default Barrows Barrows() + ( + position = 0, + keyName = "PVMPrayers", + name = "PVM Prayers", + description = "Shows prayers based on prayer build" + ) + default PVMPrayers PVMPrayers() { - return Barrows.DISABLED; - } - - @ConfigItem - ( - position = 1, - keyName = "Cerberus", - name = "Cerberus", - description = "Shows prayers for Cerberus" - ) - default Cerberus Cerberus() - { - return Cerberus.DISABLED; - } - - @ConfigItem - ( - position = 2, - keyName = "Vorkath", - name = "Vorkath", - description = "Shows prayers for Vorkath" - ) - default Vorkath Vorkath() - { - return Vorkath.DISABLED; - } - - @ConfigItem - ( - position = 3, - keyName = "Zulrah", - name = "Zulrah", - description = "Shows prayers for Zulrah" - ) - default Zulrah Zulrah() - { - return Zulrah.DISABLED; - } - - @ConfigItem - ( - position = 4, - keyName = "Armadyl", - name = "Armadyl", - description = "Shows prayers for Armadyl" - ) - default Armadyl Armadyl() - { - return Armadyl.DISABLED; - } - - @ConfigItem - ( - position = 5, - keyName = "Bandos", - name = "Bandos", - description = "Shows prayers for Bandos" - ) - default Bandos Bandos() - { - return Bandos.DISABLED; - } - - @ConfigItem - ( - position = 6, - keyName = "Saradomin", - name = "Saradomin", - description = "Shows prayers for Saradomin" - ) - default Saradomin Saradomin() - { - return Saradomin.DISABLED; - } - - @ConfigItem - ( - position = 7, - keyName = "Zamorak", - name = "Zamorak", - description = "Shows prayers for Zamorak" - ) - default Zamorak Zamorak() - { - return Zamorak.DISABLED; + return PVMPrayers.DISABLED; } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java index fc4b75684a..24a8f6a037 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java @@ -29,15 +29,7 @@ package net.runelite.client.plugins.hideprayers.PVM; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.HashTable; -import net.runelite.api.Prayer; -import net.runelite.api.WidgetNode; +import net.runelite.api.*; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.WidgetLoaded; @@ -51,6 +43,11 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.hideprayers.util.PrayerTabStates; +import javax.inject.Inject; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + @PluginDescriptor ( name = "Show/Hide PVM Prayers", @@ -115,7 +112,7 @@ public class HidePrayersPVMPlugin extends Plugin protected void startUp() throws Exception { hidePrayers(); - configManager.setConfiguration("runelite", "hideprayerspvmplugin", false); + configManager.setConfiguration("runelite", "hideprayersindividualplugin", false); configManager.setConfiguration("runelite", "hideprayerspvpplugin", false); } @@ -219,213 +216,171 @@ public class HidePrayersPVMPlugin extends Plugin Prayer prayer = Prayer.values()[index]; Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); - if (config.Armadyl() == Armadyl.DISABLED - && config.Bandos() == Bandos.DISABLED - && config.Barrows() == Barrows.DISABLED - && config.Cerberus() == Cerberus.DISABLED - && config.Saradomin() == Saradomin.DISABLED - && config.Vorkath() == Vorkath.DISABLED - && config.Zamorak() == Zamorak.DISABLED - && config.Zulrah() == Zulrah.DISABLED - ) + switch (config.PVMPrayers()) { - prayerWidget.setHidden(false); - } + case DISABLED: + prayerWidget.setHidden(false); + break; - if (config.Zulrah() == Zulrah.ZULRAH_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false);// mystic might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Zulrah() == Zulrah.ZULRAH_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour - prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false);// Augury - } - - if (config.Barrows() == Barrows.BARROWS_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false);// mystic might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Barrows() == Barrows.BARROWS_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour - prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false);// Augury - } - - if (config.Vorkath() == Vorkath.VORKATH_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Vorkath() == Vorkath.VORKATH_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour - } - - if (config.Cerberus() == Cerberus.CERBERUS_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel PVM - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Cerberus() == Cerberus.CERBERUS_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety - } - - if (config.Cerberus() == Cerberus.CERBERUS_CHEAP_RANGE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Cerberus() == Cerberus.CERBERUS_EXPENSIVE_RANGE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour - } - - if (config.Armadyl() == Armadyl.ARMADYL_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Armadyl() == Armadyl.ARMADYL_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour - } - - if (config.Bandos() == Bandos.BANDOS_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel PVM - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Bandos() == Bandos.BANDOS_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety - } - - if (config.Saradomin() == Saradomin.SARDOMIN_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel PVM - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from magic - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Saradomin() == Saradomin.SARADOMIN_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour - } - - if (config.Zamorak() == Zamorak.ZAMORAK_CHEAP) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - } - - if (config.Zamorak() == Zamorak.ZAMORAK_EXPENSIVE) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety + case ARMADYL_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case ARMADYL_EXPENSIVE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour + break; + case BANDOS_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case BANDOS_EXPENSIVE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety + break; + case BARROWS_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false);// mystic might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case BARROWS_EXPENSIVE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour + prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false);// Augury + break; + case CERBERUS_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel PVM + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case CERBERUS_CHEAP_RANGE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case CERBERUS_EXPENSIVE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety + break; + case CERBERUS_EXPENSIVE_RANGE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour + break; + case SARADOMIN_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from magic + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case SARADOMIN_EXPENSIVE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour + break; + case VORKATH_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case VORKATH_EXPENSIVE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour + break; + case ZAMORAK_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false);// Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false);// Incredible Reflex + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case ZAMORAK_EXPENSIVE: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// Piety + break; + case ZULRAH_CHEAP: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false);// mystic might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + break; + case ZULRAH_EXPENSIVE: + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// Protect from Range + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false);// Redemption + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false);// Preserve + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// Rigour + prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false);// Augury + break; } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Cerberus.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/PVMPrayers.java similarity index 76% rename from runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Cerberus.java rename to runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/PVMPrayers.java index 2bfecd2f1b..8fab96671c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Cerberus.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/PVMPrayers.java @@ -31,18 +31,32 @@ import lombok.Getter; @Getter @AllArgsConstructor -public enum Cerberus +public enum PVMPrayers { DISABLED("Disabled"), + ARMADYL_CHEAP("Eagle eye"), + ARMADYL_EXPENSIVE("Rigour"), + BANDOS_CHEAP("Low LVL Melee"), + BANDOS_EXPENSIVE("Piety"), + BARROWS_CHEAP("Eagle/Mystic"), + BARROWS_EXPENSIVE("Augury/Rigour"), CERBERUS_CHEAP("Low LVL Melee"), CERBERUS_EXPENSIVE("Melee Piety"), CERBERUS_CHEAP_RANGE("Range Eagle Eye"), - CERBERUS_EXPENSIVE_RANGE("Range Rigour"); + CERBERUS_EXPENSIVE_RANGE("Range Rigour"), + SARADOMIN_CHEAP("Melee/Eagle"), + SARADOMIN_EXPENSIVE("Piety/Rigour"), + VORKATH_CHEAP("Eagle Eye"), + VORKATH_EXPENSIVE("Rigour"), + ZAMORAK_CHEAP("Low LVL Melee"), + ZAMORAK_EXPENSIVE("Piety"), + ZULRAH_CHEAP("Eagle/Mystic"), + ZULRAH_EXPENSIVE("Augury/Rigour"); private String name; @Override - public String toString() + public String toString() { return getName(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Saradomin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Saradomin.java deleted file mode 100644 index 7c5fbf9fac..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Saradomin.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.hideprayers.PVM; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum Saradomin -{ - DISABLED("Disabled"), - SARDOMIN_CHEAP("Melee/Eagle"), - SARADOMIN_EXPENSIVE("Piety/Rigour"); - - private String name; - - @Override - public String toString() - { - return getName(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Vorkath.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Vorkath.java deleted file mode 100644 index a8754e908a..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Vorkath.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.hideprayers.PVM; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum Vorkath -{ - DISABLED("Disabled"), - VORKATH_CHEAP("Eagle Eye"), - VORKATH_EXPENSIVE("Rigour"); - - private String name; - - @Override - public String toString() - { - return getName(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zamorak.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zamorak.java deleted file mode 100644 index a3e859b390..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zamorak.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.hideprayers.PVM; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum Zamorak -{ - DISABLED("Disabled"), - ZAMORAK_CHEAP("Low LVL Melee"), - ZAMORAK_EXPENSIVE("Piety"); - - private String name; - - @Override - public String toString() - { - return getName(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zulrah.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zulrah.java deleted file mode 100644 index 7f139000e0..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/Zulrah.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * Copyright (c) 2018, Raqes - * 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 HOLDER 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.hideprayers.PVM; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum Zulrah -{ - DISABLED("Disabled"), - ZULRAH_CHEAP("Eagle/Mystic"), - ZULRAH_EXPENSIVE("Augury/Rigour"); - - private String name; - - @Override - public String toString() - { - return getName(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java index 30e482d489..61c47d33b4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPConfig.java @@ -35,14 +35,26 @@ import net.runelite.client.config.ConfigItem; public interface HidePrayersPVPConfig extends Config { @ConfigItem - ( - position = 0, - keyName = "CombatPrayers", - name = "Combat Prayers", - description = "Shows prayers based on prayer build" - ) + ( + position = 0, + keyName = "CombatPrayers", + name = "Combat Prayers", + description = "Shows prayers based on prayer build" + ) default CombatPrayers CombatPrayers() { return CombatPrayers.DISABLED; } + + @ConfigItem + ( + position = 1, + keyName = "HideRapidHealRestore", + name = "Hide Rapid Heal and Rapid Restore", + description = "Hides the Rapid Heal and Rapid Restore prayers" + ) + default boolean HideRapidHealRestore() + { + return false; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java index 0fc21ec4a8..05d75d5b3a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java @@ -29,15 +29,7 @@ package net.runelite.client.plugins.hideprayers.PVP; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.HashTable; -import net.runelite.api.Prayer; -import net.runelite.api.WidgetNode; +import net.runelite.api.*; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.WidgetLoaded; @@ -51,6 +43,11 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.hideprayers.util.PrayerTabStates; +import javax.inject.Inject; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + @PluginDescriptor ( name = "Show/Hide PVP Prayers", @@ -219,215 +216,176 @@ public class HidePrayersPVPPlugin extends Plugin Prayer prayer = Prayer.values()[index]; Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); - if (config.CombatPrayers() == CombatPrayers.DISABLED) + if (config.HideRapidHealRestore()) { - prayerWidget.setHidden(false); + prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(true); // Rapid Restore + prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(true); // Rapid Heal } - - if (config.CombatPrayers() == CombatPrayers.PRAY1) + else { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin - } - - if (config.CombatPrayers() == CombatPrayers.PRAY13) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength - } - - if (config.CombatPrayers() == CombatPrayers.PRAY16) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed - } - - - if (config.CombatPrayers() == CombatPrayers.PRAY25) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye - prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will - prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin - prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item } - - if (config.CombatPrayers() == CombatPrayers.PRAY31) + switch (config.CombatPrayers()) { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - } - - if (config.CombatPrayers() == CombatPrayers.PRAY43) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - } - - if (config.CombatPrayers() == CombatPrayers.PRAY44) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - } - - if (config.CombatPrayers() == CombatPrayers.PRAY45) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - } - - if (config.CombatPrayers() == CombatPrayers.PRAY52) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - } - - if (config.CombatPrayers() == CombatPrayers.PRAY55) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin - prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength - prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - } - - if (config.CombatPrayers() == CombatPrayers.PRAY60) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(false); // Chivalry - } - - if (config.CombatPrayers() == CombatPrayers.PRAY70) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety - } - - if (config.CombatPrayers() == CombatPrayers.PRAY74) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour - } - - if (config.CombatPrayers() == CombatPrayers.PRAY77) - { - prayerWidget.setHidden(true); - prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(false); // Rapid Restore - prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(false); // Rapid Heal - prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item - prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic - prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range - prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee - prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption - prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite - prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve - prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety - prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour - prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false); // Augury + case DISABLED: + prayerWidget.setHidden(false); + break; + case PRAY1: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin + break; + case PRAY13: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[0].ordinal()).setHidden(false); // Thick Skin + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength + break; + case PRAY16: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed + break; + case PRAY25: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[3].ordinal()).setHidden(false); // Sharp Eye + prayerWidgets.get(Prayer.values()[4].ordinal()).setHidden(false); // Mystic Will + prayerWidgets.get(Prayer.values()[5].ordinal()).setHidden(false); // Rock Skin + prayerWidgets.get(Prayer.values()[6].ordinal()).setHidden(false); // Super Human Strength + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + break; + case PRAY31: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[7].ordinal()).setHidden(false); // Improved Reflexed + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + break; + case PRAY43: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[11].ordinal()).setHidden(false); // Hawk Eye + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + break; + case PRAY44: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[12].ordinal()).setHidden(false); // Mystic Lore + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + break; + case PRAY45: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + break; + case PRAY52: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + break; + case PRAY55: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[13].ordinal()).setHidden(false); // Steel Skin + prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false); // Ultimate Strength + prayerWidgets.get(Prayer.values()[15].ordinal()).setHidden(false); // Incredible Reflexes + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + break; + case PRAY60: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[25].ordinal()).setHidden(false); // Chivalry + break; + case PRAY70: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false); // Eagle Eye + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety + break; + case PRAY74: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false); // Mystic Might + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour + break; + case PRAY77: + prayerWidget.setHidden(true); + prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false); // Protect Item + prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false); // Protect from Magic + prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false); // Protect from Range + prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false); // Protect from Melee + prayerWidgets.get(Prayer.values()[22].ordinal()).setHidden(false); // Redemption + prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false); // Smite + prayerWidgets.get(Prayer.values()[24].ordinal()).setHidden(false); // Preserve + prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false); // Piety + prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false); // Rigour + prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false); // Augury + break; } } } From a7f7c71ff4b36cdacf503e787f1ff654ac08a00c Mon Sep 17 00:00:00 2001 From: Ganom Date: Sat, 18 May 2019 17:08:18 -0400 Subject: [PATCH 39/78] Fix formatting of HidePrayers Plugin (#301) * Fix Imports * Fix Formatting * Fix Imports/Formatting --- .../hideprayers/PVM/HidePrayersPVMPlugin.java | 17 ++++++++++------- .../plugins/hideprayers/PVM/PVMPrayers.java | 6 +++--- .../hideprayers/PVP/HidePrayersPVPPlugin.java | 19 +++++++++++-------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java index 24a8f6a037..c5dbfdfcc0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/HidePrayersPVMPlugin.java @@ -29,7 +29,15 @@ package net.runelite.client.plugins.hideprayers.PVM; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; -import net.runelite.api.*; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HashTable; +import net.runelite.api.Prayer; +import net.runelite.api.WidgetNode; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.WidgetLoaded; @@ -43,11 +51,6 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.hideprayers.util.PrayerTabStates; -import javax.inject.Inject; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - @PluginDescriptor ( name = "Show/Hide PVM Prayers", @@ -385,4 +388,4 @@ public class HidePrayersPVMPlugin extends Plugin } } } -} \ No newline at end of file +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/PVMPrayers.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/PVMPrayers.java index 8fab96671c..4bcd46ff0c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/PVMPrayers.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVM/PVMPrayers.java @@ -31,7 +31,7 @@ import lombok.Getter; @Getter @AllArgsConstructor -public enum PVMPrayers +public enum PVMPrayers { DISABLED("Disabled"), ARMADYL_CHEAP("Eagle eye"), @@ -56,8 +56,8 @@ public enum PVMPrayers private String name; @Override - public String toString() + public String toString() { return getName(); } -} \ No newline at end of file +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java index 05d75d5b3a..6f2e3f3705 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hideprayers/PVP/HidePrayersPVPPlugin.java @@ -29,7 +29,15 @@ package net.runelite.client.plugins.hideprayers.PVP; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; -import net.runelite.api.*; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HashTable; +import net.runelite.api.Prayer; +import net.runelite.api.WidgetNode; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.WidgetLoaded; @@ -43,11 +51,6 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.hideprayers.util.PrayerTabStates; -import javax.inject.Inject; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - @PluginDescriptor ( name = "Show/Hide PVP Prayers", @@ -216,7 +219,7 @@ public class HidePrayersPVPPlugin extends Plugin Prayer prayer = Prayer.values()[index]; Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); - if (config.HideRapidHealRestore()) + if (config.HideRapidHealRestore()) { prayerWidgets.get(Prayer.values()[8].ordinal()).setHidden(true); // Rapid Restore prayerWidgets.get(Prayer.values()[9].ordinal()).setHidden(true); // Rapid Heal @@ -390,4 +393,4 @@ public class HidePrayersPVPPlugin extends Plugin } } } -} \ No newline at end of file +} From d241151ec77ccec82f820f209b60b508090959d7 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Sat, 18 May 2019 23:08:35 +0200 Subject: [PATCH 40/78] Re-enable certificate checking for gamepack and remove unused method (#300) --- .../net/runelite/client/rs/ClientLoader.java | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java index 8c5c8a14e7..599ab9889b 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java @@ -33,19 +33,22 @@ import com.google.gson.Gson; import io.sigpipe.jbsdiff.InvalidHeaderException; import io.sigpipe.jbsdiff.Patch; import java.applet.Applet; -import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import java.net.URL; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import javax.inject.Inject; import javax.inject.Named; @@ -91,6 +94,7 @@ public class ClientLoader Map zipFile = new HashMap<>(); { + Certificate[] jagexCertificateChain = getJagexCertificateChain(); String codebase = config.getCodeBase(); String initialJar = config.getInitialJar(); URL url = new URL(codebase + initialJar); @@ -124,6 +128,20 @@ public class ClientLoader buffer.write(tmp, 0, n); } + if (!Arrays.equals(metadata.getCertificates(), jagexCertificateChain)) + { + if (metadata.getName().startsWith("META-INF/")) + { + // META-INF/JAGEXLTD.SF and META-INF/JAGEXLTD.RSA are not signed, but we don't need + // anything in META-INF anyway. + continue; + } + else + { + throw new VerificationException("Unable to verify jar entry: " + metadata.getName()); + } + } + zipFile.put(metadata.getName(), buffer.toByteArray()); } } @@ -240,7 +258,7 @@ public class ClientLoader rs.setStub(new RSAppletStub(config)); return rs; } - catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException | CompressorException | InvalidHeaderException | SecurityException | NoSuchMethodException | InvocationTargetException e) + catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException | CompressorException | InvalidHeaderException | SecurityException | NoSuchMethodException | InvocationTargetException | CertificateException | VerificationException e) { if (e instanceof ClassNotFoundException) { @@ -254,22 +272,10 @@ public class ClientLoader } } - private void add(byte[] bytes, String entryName, JarOutputStream target) throws IOException + private static Certificate[] getJagexCertificateChain() throws CertificateException { - BufferedInputStream in = null; - try - { - JarEntry entry = new JarEntry(entryName); - target.putNextEntry(entry); - target.write(bytes); - target.closeEntry(); - } - finally - { - if (in != null) - { - in.close(); - } - } + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Collection certificates = certificateFactory.generateCertificates(ClientLoader.class.getResourceAsStream("jagex.crt")); + return certificates.toArray(new Certificate[0]); } } From 70a097b1ad4da1c44c085f9f0006b818add0f90a Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 18 May 2019 22:09:32 +0100 Subject: [PATCH 41/78] press enter to chat - no wasd shit press enter to chat - no wasd shit --- .../entertochat/EnterToChatListener.java | 135 ++++++++++++ .../entertochat/EnterToChatPlugin.java | 206 ++++++++++++++++++ .../plugins/wasdcamera/WASDCameraPlugin.java | 4 + 3 files changed, 345 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatListener.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatListener.java new file mode 100644 index 0000000000..3dabc56600 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatListener.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018, Adam + * Copyright (c) 2018, Abexlry + * 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.entertochat; + +import com.google.common.base.Strings; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.util.Map; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.VarClientStr; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.MouseAdapter; + +class EnterToChatListener extends MouseAdapter implements KeyListener +{ + @Inject + private EnterToChatPlugin plugin; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + private final Map modified = new HashMap<>(); + + @Override + public void keyTyped(KeyEvent e) + { + } + + @Override + public void keyPressed(KeyEvent e) + { + if (client.getGameState() != GameState.LOGGED_IN || !plugin.chatboxFocused()) + { + return; + } + + if (!plugin.isTyping()) + { + switch (e.getKeyCode()) + { + case KeyEvent.VK_ENTER: + case KeyEvent.VK_SLASH: + case KeyEvent.VK_COLON: + // refocus chatbox + plugin.setTyping(true); + clientThread.invoke(() -> + { + plugin.unlockChat(); + }); + break; + } + } + else + { + switch (e.getKeyCode()) + { + case KeyEvent.VK_ENTER: + plugin.setTyping(false); + clientThread.invoke(() -> + { + plugin.lockChat(); + }); + break; + case KeyEvent.VK_ESCAPE: + plugin.setTyping(false); + clientThread.invoke(() -> + { + client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, ""); + plugin.lockChat(); + }); + break; + case KeyEvent.VK_BACK_SPACE: + if (Strings.isNullOrEmpty(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT))) + { + plugin.setTyping(false); + clientThread.invoke(() -> plugin.lockChat()); + } + } + } + } + + @Override + public void keyReleased(KeyEvent e) + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + if (plugin.chatboxFocused() && !plugin.isTyping()) + { + modified.remove(e.getKeyCode()); + + } + else + { + // press d + enter + release d - causes the right arrow to never be released + Integer m = modified.get(e.getKeyCode()); + if (m != null) + { + modified.remove(e.getKeyCode()); + e.setKeyCode(m); + } + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatPlugin.java new file mode 100644 index 0000000000..6436b6802a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/entertochat/EnterToChatPlugin.java @@ -0,0 +1,206 @@ +/*' + * Copyright (c) 2018, Adam + * Copyright (c) 2018, Abexlry + * 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.entertochat; + +import java.awt.Color; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.IconID; +import net.runelite.api.VarClientInt; +import net.runelite.api.VarClientStr; +import net.runelite.api.Varbits; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.util.ColorUtil; + +@PluginDescriptor( + name = "Press Enter to Chat", + description = "'Press Enter to Chat'", + tags = {"enter", "chat"}, + enabledByDefault = false, + type = PluginType.UTILITY +) +public class EnterToChatPlugin extends Plugin +{ + private static final String PRESS_ENTER_TO_CHAT = "Press Enter to Chat..."; + private static final String SCRIPT_EVENT_SET_CHATBOX_INPUT = "setChatboxInput"; + private static final String SCRIPT_EVENT_BLOCK_CHAT_INPUT = "blockChatInput"; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private ConfigManager configManager; + + @Inject + private KeyManager keyManager; + + @Inject + private EnterToChatListener inputListener; + + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean typing; + + @Override + protected void startUp() throws Exception + { + configManager.setConfiguration("runelite", "wasdcameraplugin", false); + typing = false; + keyManager.registerKeyListener(inputListener); + + clientThread.invoke(() -> + { + if (client.getGameState() == GameState.LOGGED_IN) + { + lockChat(); + } + }); + } + + @Override + protected void shutDown() throws Exception + { + clientThread.invoke(() -> + { + if (client.getGameState() == GameState.LOGGED_IN) + { + unlockChat(); + } + }); + + keyManager.unregisterKeyListener(inputListener); + } + + + boolean chatboxFocused() + { + Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); + if (chatboxParent == null || chatboxParent.getOnKeyListener() == null) + { + return false; + } + + // the search box on the world map can be focused, and chat input goes there, even + // though the chatbox still has its key listener. + Widget worldMapSearch = client.getWidget(WidgetInfo.WORLD_MAP_SEARCH); + return worldMapSearch == null || client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) != 1; + + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent) + { + switch (scriptCallbackEvent.getEventName()) + { + case SCRIPT_EVENT_SET_CHATBOX_INPUT: + Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); + if (chatboxInput != null) + { + if (chatboxFocused() && !typing) + { + chatboxInput.setText(PRESS_ENTER_TO_CHAT); + } + } + break; + case SCRIPT_EVENT_BLOCK_CHAT_INPUT: + if (!typing) + { + int[] intStack = client.getIntStack(); + int intStackSize = client.getIntStackSize(); + intStack[intStackSize - 1] = 1; + } + break; + } + } + + void lockChat() + { + Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); + if (chatboxParent != null && chatboxParent.getOnKeyListener() != null) + { + Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); + if (chatboxInput != null) + { + chatboxInput.setText(PRESS_ENTER_TO_CHAT); + } + } + } + + void unlockChat() + { + Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); + if (chatboxParent != null) + { + Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); + if (chatboxInput != null) + { + if (client.getGameState() == GameState.LOGGED_IN) + { + final boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1; + final Color textColor = isChatboxTransparent ? JagexColors.CHAT_TYPED_TEXT_TRANSPARENT_BACKGROUND : JagexColors.CHAT_TYPED_TEXT_OPAQUE_BACKGROUND; + chatboxInput.setText(getPlayerNameWithIcon() + ": " + ColorUtil.wrapWithColorTag(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT) + "*", textColor)); + } + } + } + } + + private String getPlayerNameWithIcon() + { + IconID icon; + switch (client.getAccountType()) + { + case IRONMAN: + icon = IconID.IRONMAN; + break; + case ULTIMATE_IRONMAN: + icon = IconID.ULTIMATE_IRONMAN; + break; + case HARDCORE_IRONMAN: + icon = IconID.HARDCORE_IRONMAN; + break; + default: + return client.getLocalPlayer().getName(); + } + return icon + client.getLocalPlayer().getName(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java index a60a389674..ac59c414d6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wasdcamera/WASDCameraPlugin.java @@ -67,6 +67,9 @@ public class WASDCameraPlugin extends Plugin @Inject private ClientThread clientThread; + @Inject + private ConfigManager configManager; + @Inject private KeyManager keyManager; @@ -80,6 +83,7 @@ public class WASDCameraPlugin extends Plugin @Override protected void startUp() throws Exception { + configManager.setConfiguration("runelite", "entertochatplugin", false); typing = false; keyManager.registerKeyListener(inputListener); From 49ca5b619958b86f2de7d070902188a7fe936e95 Mon Sep 17 00:00:00 2001 From: Wealth <30428646+Wea1thRS@users.noreply.github.com> Date: Sat, 18 May 2019 16:14:03 -0500 Subject: [PATCH 42/78] Inventory setups credit (#303) --- .../runelite/client/plugins/inventorysetups/InventorySetup.java | 1 + .../plugins/inventorysetups/InventorySetupBankOverlay.java | 1 + .../client/plugins/inventorysetups/InventorySetupConfig.java | 1 + .../client/plugins/inventorysetups/InventorySetupItem.java | 1 + .../client/plugins/inventorysetups/InventorySetupPlugin.java | 1 + .../plugins/inventorysetups/ui/InventorySetupContainerPanel.java | 1 + .../plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java | 1 + .../plugins/inventorysetups/ui/InventorySetupInventoryPanel.java | 1 + .../plugins/inventorysetups/ui/InventorySetupPluginPanel.java | 1 + .../client/plugins/inventorysetups/ui/InventorySetupSlot.java | 1 + 10 files changed, 10 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java index 98bf656f5a..e49e8b1512 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java index 5d013b0c47..1b0be390fb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java index a4ba32ab8b..1c49ba73d4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java index f67d5325e8..7849c817d8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java index 2b4399d7ba..225a91aacd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java index c2f1db70b8..f49b6f9e54 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java index f56842e608..b964a205eb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java index d10b43a4db..689773b517 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java index 67f2504c32..db18b8ec4b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java index af4d24d966..0af6a142cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2019, Ethan * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * From f69ebb66a200357a55b50fd097c132589b94b496 Mon Sep 17 00:00:00 2001 From: Ganom Date: Sat, 18 May 2019 22:42:40 -0400 Subject: [PATCH 43/78] Remove Unnecessary code (#307) --- .../net/runelite/client/plugins/fightcave/FightCavePlugin.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java index 2fa61cb94e..10458ec0e8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java @@ -50,7 +50,6 @@ import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.flexo.Flexo; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; @@ -169,7 +168,6 @@ public class FightCavePlugin extends Plugin overlayManager.add(waveOverlay); overlayManager.add(jadOverlay); overlayManager.add(timersOverlay); - Flexo.client = client; } @Override From 8a21d94977c2993566bd674264887f2f5224ec65 Mon Sep 17 00:00:00 2001 From: Ganom Date: Sun, 19 May 2019 01:06:29 -0400 Subject: [PATCH 44/78] Update ShortcutOverlay.java --- .../client/plugins/raids/shortcuts/ShortcutOverlay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java index 315346882e..706ca2ddf1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java @@ -68,7 +68,7 @@ public class ShortcutOverlay extends Overlay case 29738: name = "Rocks"; break; - case 29748: + case 29740: name = "Boulder"; break; case 29737: From 63e813b6b89ea613575771e17316a7022ce30949 Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 19 May 2019 18:49:49 +1000 Subject: [PATCH 45/78] no longer strip entire menu, using swap function --- .../MenuEntrySwapperPlugin.java | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index e20ead4eeb..7804079226 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -463,11 +463,11 @@ public class MenuEntrySwapperPlugin extends Plugin { if (shiftModifier) { - stripExceptFor("climb-up"); + swap(client, "climb-up", option, target, true); } if (controlModifier) { - stripExceptFor("climb-down"); + swap(client, "climb-down", option, target, true); } } } @@ -622,24 +622,6 @@ public class MenuEntrySwapperPlugin extends Plugin } } - private void stripExceptFor(String option) - { - MenuEntry[] newEntries = new MenuEntry[1]; - - for (MenuEntry entry : client.getMenuEntries()) - { - if (entry.getOption().equalsIgnoreCase(option)) - { - newEntries[0] = entry; - } - } - - if (newEntries[0] != null) - { - client.setMenuEntries(newEntries); - } - } - @Subscribe public void onPostItemComposition(PostItemComposition event) { From 8daf70c2b103f1868843cdf75221bfc9a6d884bb Mon Sep 17 00:00:00 2001 From: sdburns1998 <49877861+sdburns1998@users.noreply.github.com> Date: Sun, 19 May 2019 19:08:31 +0200 Subject: [PATCH 46/78] Config && easyscape (#309) * Add back config groups * Use a JSider when there is a max value known * update Easyscape * Add JSlider to changeConfiguration --- .../client/plugins/config/ConfigPanel.java | 457 ++++++++------ .../plugins/easyscape/EasyscapeConfig.java | 586 ++++++++++++++++++ .../plugins/easyscape/EasyscapePlugin.java | 344 +++++----- .../easyscape/EasyscapePluginConfig.java | 341 ---------- .../plugins/easyscape/WealthRingMode.java | 46 -- .../easyscape/{ => util}/DuelingRingMode.java | 90 +-- .../easyscape/{ => util}/EssenceMode.java | 88 +-- .../{ => util}/GamesNecklaceMode.java | 94 +-- .../easyscape/{ => util}/GloryMode.java | 92 +-- 9 files changed, 1229 insertions(+), 909 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java rename runelite-client/src/main/java/net/runelite/client/plugins/easyscape/{ => util}/DuelingRingMode.java (91%) rename runelite-client/src/main/java/net/runelite/client/plugins/easyscape/{ => util}/EssenceMode.java (91%) rename runelite-client/src/main/java/net/runelite/client/plugins/easyscape/{ => util}/GamesNecklaceMode.java (92%) rename runelite-client/src/main/java/net/runelite/client/plugins/easyscape/{ => util}/GloryMode.java (91%) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 152458de73..276be04829 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -30,6 +30,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.Insets; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; @@ -49,12 +50,14 @@ import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; +import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JScrollPane; +import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.JTextArea; import javax.swing.ScrollPaneConstants; @@ -72,6 +75,7 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigDescriptor; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.ConfigItemsGroup; import net.runelite.client.config.ConfigItemDescriptor; import net.runelite.client.config.ConfigManager; import net.runelite.client.config.Keybind; @@ -413,223 +417,279 @@ public class ConfigPanel extends PluginPanel title.setToolTipText("" + name + ":
" + listItem.getDescription() + ""); topPanel.add(title); - for (ConfigItemDescriptor cid : cd.getItems()) + for (ConfigItemsGroup cig : cd.getItemGroups()) { - if (cid.getItem().hidden()) + boolean collapsed = false; + if (!cig.getGroup().equals("")) { + String header = cig.getGroup(); + + JPanel item = new JPanel(); + item.setLayout(new BorderLayout()); + item.setMinimumSize(new Dimension(PANEL_WIDTH, 0)); + + JLabel headerLabel = new JLabel(header); + headerLabel.setForeground(Color.ORANGE); + headerLabel.setPreferredSize(new Dimension(PANEL_WIDTH, (int)headerLabel.getPreferredSize().getHeight())); + String sCollapsed = configManager.getConfiguration(cd.getGroup().value(), cig.getGroup() + "_collapse"); + + if (sCollapsed != null) + collapsed = Boolean.parseBoolean(sCollapsed); + + JButton collapse = new JButton(collapsed ? "+" : "-"); + collapse.setPreferredSize(new Dimension(20, 20)); + collapse.setFont(collapse.getFont().deriveFont(16.0f)); + collapse.setBorder(null); + collapse.setMargin(new Insets(0, 0, 0, 0)); + collapse.addActionListener(ae -> changeGroupCollapse(listItem, config, collapse, cd, cig)); + headerLabel.setBorder(new EmptyBorder(0, 10, 0, 0)); + + item.add(collapse, BorderLayout.WEST); + item.add(headerLabel, BorderLayout.CENTER); + + mainPanel.add(item); + } + + if (collapsed) continue; - } - JPanel item = new JPanel(); - item.setLayout(new BorderLayout()); - item.setMinimumSize(new Dimension(PANEL_WIDTH, 0)); - name = cid.getItem().name(); - JLabel configEntryName = new JLabel(name); - configEntryName.setForeground(Color.WHITE); - configEntryName.setToolTipText("" + name + ":
" + cid.getItem().description() + ""); - item.add(configEntryName, BorderLayout.CENTER); - - if (cid.getType() == boolean.class) + for (ConfigItemDescriptor cid : cig.getItems()) { - JCheckBox checkbox = new JCheckBox(); - checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR); - checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()))); - checkbox.addActionListener(ae -> changeConfiguration(listItem, config, checkbox, cd, cid)); - - item.add(checkbox, BorderLayout.EAST); - } - - if (cid.getType() == int.class) - { - int value = Integer.parseInt(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); - - Range range = cid.getRange(); - int min = 0, max = Integer.MAX_VALUE; - if (range != null) + if (cid.getItem().hidden()) { - min = range.min(); - max = range.max(); + continue; } - // Config may previously have been out of range - value = Ints.constrainToRange(value, min, max); + JPanel item = new JPanel(); + item.setLayout(new BorderLayout()); + item.setMinimumSize(new Dimension(PANEL_WIDTH, 0)); + name = cid.getItem().name(); + JLabel configEntryName = new JLabel(name); + configEntryName.setPreferredSize(new Dimension(PANEL_WIDTH, (int)configEntryName.getPreferredSize().getHeight())); + configEntryName.setForeground(Color.WHITE); + configEntryName.setToolTipText("" + name + ":
" + cid.getItem().description() + ""); + item.add(configEntryName, BorderLayout.CENTER); - SpinnerModel model = new SpinnerNumberModel(value, min, max, 1); - JSpinner spinner = new JSpinner(model); - Component editor = spinner.getEditor(); - JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField(); - spinnerTextField.setColumns(SPINNER_FIELD_WIDTH); - spinner.addChangeListener(ce -> changeConfiguration(listItem, config, spinner, cd, cid)); - - item.add(spinner, BorderLayout.EAST); - } - - if (cid.getType() == String.class) - { - JTextComponent textField; - - if (cid.getItem().secret()) + if (cid.getType() == boolean.class) { - textField = new JPasswordField(); - } - else - { - final JTextArea textArea = new JTextArea(); - textArea.setLineWrap(true); - textArea.setWrapStyleWord(true); - textField = textArea; + JCheckBox checkbox = new JCheckBox(); + checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR); + checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()))); + checkbox.addActionListener(ae -> changeConfiguration(listItem, config, checkbox, cd, cid)); + + item.add(checkbox, BorderLayout.EAST); } - textField.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - textField.setText(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); - - textField.addFocusListener(new FocusAdapter() + if (cid.getType() == int.class) { - @Override - public void focusLost(FocusEvent e) + int value = Integer.parseInt(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); + + Range range = cid.getRange(); + int min = 0, max = Integer.MAX_VALUE; + if (range != null) { - changeConfiguration(listItem, config, textField, cd, cid); + min = range.min(); + max = range.max(); } - }); - item.add(textField, BorderLayout.SOUTH); - } + // Config may previously have been out of range + value = Ints.constrainToRange(value, min, max); - if (cid.getType() == Color.class) - { - String existing = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()); - - Color existingColor; - JButton colorPickerBtn; - - if (existing == null) - { - existingColor = Color.BLACK; - colorPickerBtn = new JButton("Pick a color"); - } - else - { - existingColor = ColorUtil.fromString(existing); - colorPickerBtn = new JButton(ColorUtil.toHexColor(existingColor).toUpperCase()); - } - - colorPickerBtn.setFocusable(false); - colorPickerBtn.setBackground(existingColor); - colorPickerBtn.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) + if (max < Integer.MAX_VALUE) { - RuneliteColorPicker colorPicker = new RuneliteColorPicker(SwingUtilities.windowForComponent(ConfigPanel.this), - colorPickerBtn.getBackground(), cid.getItem().name(), cid.getAlpha() == null); - colorPicker.setLocation(getLocationOnScreen()); - colorPicker.setOnColorChange(c -> - { - colorPickerBtn.setBackground(c); - colorPickerBtn.setText(ColorUtil.toHexColor(c).toUpperCase()); - }); - - colorPicker.addWindowListener(new WindowAdapter() - { - @Override - public void windowClosing(WindowEvent e) + JSlider slider = new JSlider(min, max, value); + configEntryName.setText(name.concat(": ").concat(String.valueOf(slider.getValue()))); + slider.setPreferredSize(new Dimension(topPanel.getPreferredSize().width, slider.getHeight())); + String finalName = name; + slider.addChangeListener((l) -> { - changeConfiguration(listItem, config, colorPicker, cd, cid); + configEntryName.setText(finalName.concat(": ").concat(String.valueOf(slider.getValue()))); + if (!slider.getValueIsAdjusting()) + changeConfiguration(listItem, config, slider, cd, cid); } - }); - colorPicker.setVisible(true); + ); + item.add(slider, BorderLayout.EAST); } - }); - - item.add(colorPickerBtn, BorderLayout.EAST); - } - - if (cid.getType() == Dimension.class) - { - JPanel dimensionPanel = new JPanel(); - dimensionPanel.setLayout(new BorderLayout()); - - String str = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()); - String[] splitStr = str.split("x"); - int width = Integer.parseInt(splitStr[0]); - int height = Integer.parseInt(splitStr[1]); - - SpinnerModel widthModel = new SpinnerNumberModel(width, 0, Integer.MAX_VALUE, 1); - JSpinner widthSpinner = new JSpinner(widthModel); - Component widthEditor = widthSpinner.getEditor(); - JFormattedTextField widthSpinnerTextField = ((JSpinner.DefaultEditor) widthEditor).getTextField(); - widthSpinnerTextField.setColumns(4); - - SpinnerModel heightModel = new SpinnerNumberModel(height, 0, Integer.MAX_VALUE, 1); - JSpinner heightSpinner = new JSpinner(heightModel); - Component heightEditor = heightSpinner.getEditor(); - JFormattedTextField heightSpinnerTextField = ((JSpinner.DefaultEditor) heightEditor).getTextField(); - heightSpinnerTextField.setColumns(4); - - ChangeListener listener = e -> - configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue()); - - widthSpinner.addChangeListener(listener); - heightSpinner.addChangeListener(listener); - - dimensionPanel.add(widthSpinner, BorderLayout.WEST); - dimensionPanel.add(new JLabel(" x "), BorderLayout.CENTER); - dimensionPanel.add(heightSpinner, BorderLayout.EAST); - - item.add(dimensionPanel, BorderLayout.EAST); - } - - if (cid.getType().isEnum()) - { - Class type = (Class) cid.getType(); - JComboBox box = new JComboBox(type.getEnumConstants()); - box.setPreferredSize(new Dimension(box.getPreferredSize().width, 25)); - box.setRenderer(new ComboBoxListRenderer()); - box.setForeground(Color.WHITE); - box.setFocusable(false); - box.setPrototypeDisplayValue("XXXXXXXX"); //sorry but this is the way to keep the size of the combobox in check. - try - { - Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); - box.setSelectedItem(selectedItem); - box.setToolTipText(Text.titleCase(selectedItem)); - } - catch (IllegalArgumentException ex) - { - log.debug("invalid seleced item", ex); - } - box.addItemListener(e -> - { - if (e.getStateChange() == ItemEvent.SELECTED) + else { - changeConfiguration(listItem, config, box, cd, cid); - box.setToolTipText(Text.titleCase((Enum) box.getSelectedItem())); + SpinnerModel model = new SpinnerNumberModel(value, min, max, 1); + JSpinner spinner = new JSpinner(model); + Component editor = spinner.getEditor(); + JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField(); + spinnerTextField.setColumns(SPINNER_FIELD_WIDTH); + spinner.addChangeListener(ce -> changeConfiguration(listItem, config, spinner, cd, cid)); + + item.add(spinner, BorderLayout.EAST); } - }); - item.add(box, BorderLayout.EAST); - } + } - if (cid.getType() == Keybind.class || cid.getType() == ModifierlessKeybind.class) - { - Keybind startingValue = configManager.getConfiguration(cd.getGroup().value(), - cid.getItem().keyName(), - (Class) cid.getType()); - - HotkeyButton button = new HotkeyButton(startingValue, cid.getType() == ModifierlessKeybind.class); - - button.addFocusListener(new FocusAdapter() + if (cid.getType() == String.class) { - @Override - public void focusLost(FocusEvent e) + JTextComponent textField; + + if (cid.getItem().secret()) { - changeConfiguration(listItem, config, button, cd, cid); + textField = new JPasswordField(); + } + else + { + final JTextArea textArea = new JTextArea(); + textArea.setLineWrap(true); + textArea.setWrapStyleWord(true); + textField = textArea; } - }); - item.add(button, BorderLayout.EAST); + textField.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + textField.setText(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); + + textField.addFocusListener(new FocusAdapter() + { + @Override + public void focusLost(FocusEvent e) + { + changeConfiguration(listItem, config, textField, cd, cid); + } + }); + + item.add(textField, BorderLayout.SOUTH); + } + + if (cid.getType() == Color.class) + { + String existing = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()); + + Color existingColor; + JButton colorPickerBtn; + + if (existing == null) + { + existingColor = Color.BLACK; + colorPickerBtn = new JButton("Pick a color"); + } + else + { + existingColor = ColorUtil.fromString(existing); + colorPickerBtn = new JButton(ColorUtil.toHexColor(existingColor).toUpperCase()); + } + + colorPickerBtn.setFocusable(false); + colorPickerBtn.setBackground(existingColor); + colorPickerBtn.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + RuneliteColorPicker colorPicker = new RuneliteColorPicker(SwingUtilities.windowForComponent(ConfigPanel.this), + colorPickerBtn.getBackground(), cid.getItem().name(), cid.getAlpha() == null); + colorPicker.setLocation(getLocationOnScreen()); + colorPicker.setOnColorChange(c -> + { + colorPickerBtn.setBackground(c); + colorPickerBtn.setText(ColorUtil.toHexColor(c).toUpperCase()); + }); + + colorPicker.addWindowListener(new WindowAdapter() + { + @Override + public void windowClosing(WindowEvent e) + { + changeConfiguration(listItem, config, colorPicker, cd, cid); + } + }); + colorPicker.setVisible(true); + } + }); + + item.add(colorPickerBtn, BorderLayout.EAST); + } + + if (cid.getType() == Dimension.class) + { + JPanel dimensionPanel = new JPanel(); + dimensionPanel.setLayout(new BorderLayout()); + + String str = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()); + String[] splitStr = str.split("x"); + int width = Integer.parseInt(splitStr[0]); + int height = Integer.parseInt(splitStr[1]); + + SpinnerModel widthModel = new SpinnerNumberModel(width, 0, Integer.MAX_VALUE, 1); + JSpinner widthSpinner = new JSpinner(widthModel); + Component widthEditor = widthSpinner.getEditor(); + JFormattedTextField widthSpinnerTextField = ((JSpinner.DefaultEditor) widthEditor).getTextField(); + widthSpinnerTextField.setColumns(4); + + SpinnerModel heightModel = new SpinnerNumberModel(height, 0, Integer.MAX_VALUE, 1); + JSpinner heightSpinner = new JSpinner(heightModel); + Component heightEditor = heightSpinner.getEditor(); + JFormattedTextField heightSpinnerTextField = ((JSpinner.DefaultEditor) heightEditor).getTextField(); + heightSpinnerTextField.setColumns(4); + + ChangeListener listener = e -> + configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue()); + + widthSpinner.addChangeListener(listener); + heightSpinner.addChangeListener(listener); + + dimensionPanel.add(widthSpinner, BorderLayout.WEST); + dimensionPanel.add(new JLabel(" x "), BorderLayout.CENTER); + dimensionPanel.add(heightSpinner, BorderLayout.EAST); + + item.add(dimensionPanel, BorderLayout.EAST); + } + + if (cid.getType().isEnum()) + { + Class type = (Class) cid.getType(); + JComboBox box = new JComboBox(type.getEnumConstants()); + box.setPreferredSize(new Dimension(box.getPreferredSize().width, 25)); + box.setRenderer(new ComboBoxListRenderer()); + box.setForeground(Color.WHITE); + box.setFocusable(false); + box.setPrototypeDisplayValue("XXXXXXXX"); //sorry but this is the way to keep the size of the combobox in check. + try + { + Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); + box.setSelectedItem(selectedItem); + box.setToolTipText(selectedItem.toString()); + } + catch (IllegalArgumentException ex) + { + log.debug("invalid seleced item", ex); + } + box.addItemListener(e -> + { + if (e.getStateChange() == ItemEvent.SELECTED) + { + changeConfiguration(listItem, config, box, cd, cid); + box.setToolTipText(box.getSelectedItem().toString()); + } + }); + item.add(box, BorderLayout.EAST); + } + + if (cid.getType() == Keybind.class || cid.getType() == ModifierlessKeybind.class) + { + Keybind startingValue = configManager.getConfiguration(cd.getGroup().value(), + cid.getItem().keyName(), + (Class) cid.getType()); + + HotkeyButton button = new HotkeyButton(startingValue, cid.getType() == ModifierlessKeybind.class); + + button.addFocusListener(new FocusAdapter() + { + @Override + public void focusLost(FocusEvent e) + { + changeConfiguration(listItem, config, button, cd, cid); + } + }); + + item.add(button, BorderLayout.EAST); + } + + mainPanel.add(item); } - - mainPanel.add(item); } JButton resetButton = new JButton("Reset"); @@ -657,6 +717,22 @@ public class ConfigPanel extends PluginPanel scrollPane.getVerticalScrollBar().setValue(0); } + private void changeGroupCollapse(PluginListItem listItem, Config config, JComponent component, ConfigDescriptor cd, ConfigItemsGroup cig) + { + if (component instanceof JButton) + { + + String sCollapsed = configManager.getConfiguration(cd.getGroup().value(), cig.getGroup() + "_collapse"); + boolean collapse = true; + + if (sCollapsed != null) + collapse = !Boolean.parseBoolean(sCollapsed); + + configManager.setConfiguration(cd.getGroup().value(), cig.getGroup() + "_collapse", collapse); + openGroupConfigPanel(listItem, config, cd); + } + } + private void changeConfiguration(PluginListItem listItem, Config config, Component component, ConfigDescriptor cd, ConfigItemDescriptor cid) { final ConfigItem configItem = cid.getItem(); @@ -704,6 +780,11 @@ public class ConfigPanel extends PluginPanel HotkeyButton hotkeyButton = (HotkeyButton) component; configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), hotkeyButton.getValue()); } + else if (component instanceof JSlider) + { + JSlider slider = (JSlider) component; + configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), slider.getValue()); + } } void startPlugin(Plugin plugin, PluginListItem listItem) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java new file mode 100644 index 0000000000..cba9a8baaf --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2019, Owain van Brakel + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.plugins.easyscape.util.DuelingRingMode; +import net.runelite.client.plugins.easyscape.util.EssenceMode; +import net.runelite.client.plugins.easyscape.util.GamesNecklaceMode; +import net.runelite.client.plugins.easyscape.util.GloryMode; + + +@ConfigGroup("easyscape") +public interface EasyscapeConfig extends Config +{ + @ConfigItem( + keyName = "withdrawOne", + name = "Withdraw/Deposit One", + description = "", + position = 0, + group = "Banking" + ) + default boolean getWithdrawOne() + { + return false; + } + + @ConfigItem( + keyName = "withdrawOneItems", + name = "Items", + description = "", + position = 1, + group = "Banking" + ) + default String getWithdrawOneItems() + { + return ""; + } + + @ConfigItem( + keyName = "withdrawFive", + name = "Withdraw/Deposit Five", + description = "", + position = 2, + group = "Banking" + ) + default boolean getWithdrawFive() + { + return false; + } + + @ConfigItem( + keyName = "withdrawFiveItems", + name = "Items", + description = "", + position = 3, + group = "Banking" + ) + default String getWithdrawFiveItems() + { + return ""; + } + + @ConfigItem( + keyName = "withdrawTen", + name = "Withdraw/Deposit Ten", + description = "", + position = 4, + group = "Banking" + ) + default boolean getWithdrawTen() + { + return false; + } + + @ConfigItem( + keyName = "withdrawTenItems", + name = "Items", + description = "", + position = 5, + group = "Banking" + ) + default String getWithdrawTenItems() + { + return ""; + } + + @ConfigItem( + keyName = "withdrawX", + name = "Withdraw/Deposit X", + description = "", + position = 6, + group = "Banking" + ) + default boolean getWithdrawX() + { + return false; + } + + @ConfigItem( + keyName = "withdrawXAmount", + name = "Amount", + description = "", + position = 7, + group = "Banking" + ) + default String getWithdrawXAmount() + { + return ""; + } + + @ConfigItem( + keyName = "withdrawXItems", + name = "Items", + description = "", + position = 8, + group = "Banking" + ) + default String getWithdrawXItems() + { + return ""; + } + + @ConfigItem( + keyName = "withdrawAll", + name = "Withdraw/Deposit All", + description = "", + position = 9, + group = "Banking" + ) + default boolean getWithdrawAll() + { + return false; + } + + @ConfigItem( + keyName = "withdrawAllItems", + name = "Items", + description = "", + position = 10, + group = "Banking" + ) + default String getWithdrawAllItems() + { + return ""; + } + +// ----------------------------------------------------------- // + + @ConfigItem( + keyName = "removeObjects", + name = "Remove Objects", + description = "Removes interaction with the listed objects.", + position = 12, + group = "Miscellaneous easyscape" + ) + default boolean getRemoveObjects() + { + return false; + } + + @ConfigItem( + keyName = "removedObjects", + name = "Objects", + description = "Objects listed here will have all interaction be removed.", + position = 13, + group = "Miscellaneous easyscape" + ) + default String getRemovedObjects() + { + return ""; + } + +// ----------------------------------------------------------- // + + @ConfigItem( + keyName = "swapBuyOne", + name = "Swappable Buy One", + description = "", + position = 14, + group = "Shop / stores" + ) + default boolean getSwapBuyOne() + { + return false; + } + + @ConfigItem( + keyName = "buyOneItems", + name = "Items", + description = "", + position = 15, + group = "Shop / stores" + ) + default String getBuyOneItems() + { + return ""; + } + + @ConfigItem( + keyName = "swapBuyFive", + name = "Swappable Buy Five", + description = "", + position = 16, + group = "Shop / stores" + ) + default boolean getSwapBuyFive() + { + return false; + } + + @ConfigItem( + keyName = "buyFiveItems", + name = "Items", + description = "", + position = 17, + group = "Shop / stores" + ) + default String getBuyFiveItems() + { + return ""; + } + + @ConfigItem( + keyName = "swapBuyTen", + name = "Swappable Buy Ten", + description = "", + position = 18, + group = "Shop / stores" + ) + default boolean getSwapBuyTen() + { + return false; + } + + @ConfigItem( + keyName = "buyTenItems", + name = "Items", + description = "", + position = 19, + group = "Shop / stores" + ) + default String getBuyTenItems() + { + return ""; + } + + @ConfigItem( + keyName = "swapBuyFifty", + name = "Swappable Buy Fifty", + description = "", + position = 20, + group = "Shop / stores" + ) + default boolean getSwapBuyFifty() + { + return false; + } + + @ConfigItem( + keyName = "buyFiftyItems", + name = "Items", + description = "", + position = 21, + group = "Shop / stores" + ) + default String getBuyFiftyItems() + { + return ""; + } + + @ConfigItem( + keyName = "swapSellOne", + name = "Swappable Sell One", + description = "", + position = 22, + group = "Shop / stores" + ) + default boolean getSwapSellOne() + { + return false; + } + + @ConfigItem( + keyName = "sellOneItems", + name = "Items", + description = "", + position = 23, + group = "Shop / stores" + ) + default String getSellOneItems() + { + return ""; + } + + @ConfigItem( + keyName = "swapSellFive", + name = "Swappable Sell Five", + description = "", + position = 24, + group = "Shop / stores" + ) + default boolean getSwapSellFive() + { + return false; + } + + @ConfigItem( + keyName = "sellFiveItems", + name = "Items", + description = "", + position = 25, + group = "Shop / stores" + ) + default String getSellFiveItems() + { + return ""; + } + + @ConfigItem( + keyName = "swapSellTen", + name = "Swappable Sell Ten", + description = "", + position = 26, + group = "Shop / stores" + ) + default boolean getSwapSellTen() + { + return false; + } + + @ConfigItem( + keyName = "sellTenItems", + name = "Items", + description = "", + position = 27, + group = "Shop / stores" + ) + default String getSellTenItems() + { + return ""; + } + + @ConfigItem( + keyName = "swapSellFifty", + name = "Swappable Sell Fifty", + description = "", + position = 28, + group = "Shop / stores" + ) + default boolean getSwapSellFifty() + { + return false; + } + + @ConfigItem( + keyName = "sellFiftyItems", + name = "Items", + description = "", + position = 29, + group = "Shop / stores" + ) + default String getSellFiftyItems() + { + return ""; + } + +// ----------------------------------------------------------- // + + @ConfigItem( + keyName = "easyConstruction", + name = "Easy Construction", + description = "Makes \"Remove\" the default option for listed items in build mode.", + position = 30, + group = "Miscellaneous swapper" + ) + default boolean getEasyConstruction() + { + return false; + } + + @ConfigItem( + keyName = "constructionItems", + name = "Construction Items", + description = "Items listed here will have the default option set to \"Removed\" in build mode.", + position = 31, + group = "Miscellaneous swapper" + ) + default String getConstructionItems() + { + return ""; + } + + + @ConfigItem( + keyName = "swapSmithing", + name = "Swap Smithing", + description = "Enables swapping of smith-1 and smith-all options.", + position = 32, + group = "Miscellaneous swapper" + ) + default boolean getSwapSmithing() + { + return false; + } + + @ConfigItem( + keyName = "swapTanning", + name = "Swap Tanning", + description = "Enables swapping of tan-1 and tan-all options.", + position = 33, + group = "Miscellaneous swapper" + ) + default boolean getSwapTanning() + { + return false; + } + + @ConfigItem( + keyName = "swapArdougneCape", + name = "Swap Ardougne Cape", + description = "Enables swapping of teleport and wear.", + position = 34, + group = "Miscellaneous swapper" + ) + default boolean getSwapArdougneCape() + { + return false; + } + + @ConfigItem( + keyName = "swapSawmill", + name = "Swap Sawmill Operator", + description = "Makes Buy-plank the default option on the sawmill operator.", + position = 35, + group = "Miscellaneous swapper" + ) + default boolean getSwapSawmill() + { + return false; + } + + @ConfigItem( + keyName = "swapSawmillPlanks", + name = "Swap Buy Planks", + description = "Makes Buy All the default option in buy planks.", + position = 36, + group = "Miscellaneous swapper" + ) + default boolean getSwapSawmillPlanks() + { + return false; + } + + @ConfigItem( + keyName = "swapPuroPuro", + name = "Swap Puro Puro Wheat", + description = "", + position = 37, + group = "Miscellaneous swapper" + ) + default boolean getSwapPuro() + { + return false; + } + + @ConfigItem( + keyName = "swapEssencePounch", + name = "Swap Essence Pouch", + description = "", + position = 38, + group = "Miscellaneous swapper" + ) + default boolean getSwapEssencePouch() + { + return false; + } + + @ConfigItem( + keyName = "essenceMode", + name = "Mode", + description = "", + position = 39, + group = "Miscellaneous swapper" + ) + default EssenceMode getEssenceMode() + { + return EssenceMode.RUNECRAFTING; + } + + @ConfigItem( + keyName = "swapGamesNecklace", + name = "Swap Games Necklace", + description = "", + position = 40, + group = "Miscellaneous swapper" + ) + default boolean getGamesNecklace() + { + return false; + } + + @ConfigItem( + keyName = "gamesNecklaceMode", + name = "Mode", + description = "", + position = 41, + group = "Miscellaneous swapper" + ) + default GamesNecklaceMode getGamesNecklaceMode() + { + return GamesNecklaceMode.BURTHORPE; + } + + @ConfigItem( + keyName = "swapDuelingRing", + name = "Swap Dueling Ring", + description = "", + position = 42, + group = "Miscellaneous swapper" + ) + default boolean getDuelingRing() + { + return false; + } + + @ConfigItem( + keyName = "duelingRingMode", + name = "Mode", + description = "", + position = 43, + group = "Miscellaneous swapper" + ) + default DuelingRingMode getDuelingRingMode() + { + return DuelingRingMode.DUEL_ARENA; + } + + @ConfigItem( + keyName = "swapGlory", + name = "Swap Glory", + description = "", + position = 44, + group = "Miscellaneous swapper" + ) + default boolean getGlory() + { + return false; + } + + @ConfigItem( + keyName = "gloryMode", + name = "Mode", + description = "", + position = 45, + group = "Miscellaneous swapper" + ) + default GloryMode getGloryMode() + { + return GloryMode.EDGEVILLE; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 35e942382c..41476f163f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2019, Owain van Brakel + * Copyright (c) 2019, Alan Baumgartner * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,15 +27,18 @@ package net.runelite.client.plugins.easyscape; import com.google.inject.Provides; import javax.inject.Inject; -import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.GameObject; import net.runelite.api.GameState; import net.runelite.api.MenuAction; import static net.runelite.api.MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET; import static net.runelite.api.MenuAction.WALK; import net.runelite.api.MenuEntry; +import static net.runelite.api.ObjectID.PORTAL_4525; import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameObjectDespawned; +import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -50,49 +54,30 @@ import org.apache.commons.lang3.ArrayUtils; @PluginDescriptor( name = "Easyscape", - description = "Easyscape.", - tags = {"Easyscape"}, - enabledByDefault = false, type = PluginType.UTILITY ) - -@Slf4j public class EasyscapePlugin extends Plugin { - private static final int PURO_PURO_REGION_ID = 10307; - private static final int HOUSE_REGION_ID = 7513; private MenuEntry[] entries; + private boolean inHouse = false; @Inject private Client client; @Inject - private EasyscapePluginConfig config; + private EasyscapeConfig config; @Provides - EasyscapePluginConfig provideConfig(ConfigManager configManager) + EasyscapeConfig provideConfig(ConfigManager configManager) { - return configManager.getConfig(EasyscapePluginConfig.class); - } - - @Override - public void startUp() - { - log.debug("Easyscape Started."); - } - - @Override - public void shutDown() - { - log.debug("Easyscape Stopped."); + return configManager.getConfig(EasyscapeConfig.class); } @Subscribe public void onMenuEntryAdded(MenuEntryAdded event) { - if (client.getGameState() != GameState.LOGGED_IN) { return; @@ -111,17 +96,159 @@ public class EasyscapePlugin extends Plugin entries = client.getMenuEntries(); - if (config.getRemoveExamine()) - { - for (int i = entries.length - 1; i >= 0; i--) + Widget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR); + + if (config.getWithdrawOne()) { - if (entries[i].getOption().equals("Examine")) + for (String item : config.getWithdrawOneItems().split(",")) { - entries = ArrayUtils.remove(entries, i); - i--; + item = item.trim(); + if (target.equalsIgnoreCase(item)) + { + swap(client, "Withdraw-1", option, target); + swap(client, "Deposit-1", option, target); + } + } + } + + if (config.getWithdrawFive()) + { + for (String item : config.getWithdrawFiveItems().split(",")) + { + item = item.trim(); + if (target.equalsIgnoreCase(item)) + { + swap(client, "Withdraw-5", option, target); + swap(client, "Deposit-5", option, target); + } + } + } + + if (config.getWithdrawTen()) + { + for (String item : config.getWithdrawTenItems().split(",")) + { + item = item.trim(); + if (target.equalsIgnoreCase(item)) + { + swap(client, "Withdraw-10", option, target); + swap(client, "Deposit-10", option, target); + } + } + } + + if (config.getWithdrawX()) + { + for (String item : config.getWithdrawXItems().split(",")) + { + item = item.trim(); + if (target.equalsIgnoreCase(item)) + { + swap(client, "Withdraw-" + config.getWithdrawXAmount(), option, target); + swap(client, "Deposit-" + config.getWithdrawXAmount(), option, target); + } + } + } + + if (config.getWithdrawAll()) + { + for (String item : config.getWithdrawAllItems().split(",")) + { + item = item.trim(); + if (target.equalsIgnoreCase(item)) + { + swap(client, "Withdraw-All", option, target); + swap(client, "Deposit-All", option, target); + } + } + } + + if (config.getSwapBuyOne() && !config.getBuyOneItems().equals("")) + { + for (String item : config.getBuyOneItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Buy 1", option, target); + } + } + } + + if (config.getSwapBuyFive() && !config.getBuyFiveItems().equals("")) + { + for (String item : config.getBuyFiveItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Buy 5", option, target); + } + } + } + + if (config.getSwapBuyTen() && !config.getBuyTenItems().equals("")) + { + for (String item : config.getBuyTenItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Buy 10", option, target); + } + } + } + + if (config.getSwapBuyFifty() && !config.getBuyFiftyItems().equals("")) + { + for (String item : config.getBuyFiftyItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Buy 50", option, target); + } + } + } + + if (config.getSwapSellOne() && !config.getSellOneItems().equals("")) + { + for (String item : config.getSellOneItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Sell 1", option, target); + } + } + } + + if (config.getSwapSellFive() && !config.getSellFiveItems().equals("")) + { + for (String item : config.getSellFiveItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Sell 5", option, target); + } + } + } + + if (config.getSwapSellTen() && !config.getSellTenItems().equals("")) + { + for (String item : config.getSellTenItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Sell 10", option, target); + } + } + } + + if (config.getSwapSellFifty() && !config.getSellFiftyItems().equals("")) + { + for (String item : config.getSellFiftyItems().split(",")) + { + if (target.equalsIgnoreCase(item.trim())) + { + swap(client, "Sell 50", option, target); } } - client.setMenuEntries(entries); } if (config.getRemoveObjects() && !config.getRemovedObjects().equals("")) @@ -129,7 +256,11 @@ public class EasyscapePlugin extends Plugin for (String removed : config.getRemovedObjects().split(",")) { removed = removed.trim(); - if (target.contains("->")) + if (target.contains("(") && target.split(" \\(")[0].equalsIgnoreCase(removed)) + { + delete(event.getIdentifier()); + } + else if (target.contains("->")) { String trimmed = target.split("->")[1].trim(); if (trimmed.length() >= removed.length() && trimmed.substring(0, removed.length()).equalsIgnoreCase(removed)) @@ -138,7 +269,7 @@ public class EasyscapePlugin extends Plugin break; } } - if (target.length() >= removed.length() && target.substring(0, removed.length()).equalsIgnoreCase(removed)) + else if (target.length() >= removed.length() && target.substring(0, removed.length()).equalsIgnoreCase(removed)) { delete(event.getIdentifier()); break; @@ -152,7 +283,6 @@ public class EasyscapePlugin extends Plugin { MenuEntry menuEntry = entries[entries.length - 1]; menuEntry.setType(MenuAction.WALK.getId() + MENU_ACTION_DEPRIORITIZE_OFFSET); - client.setMenuEntries(entries); } else if (option.equalsIgnoreCase("examine")) { @@ -164,13 +294,12 @@ public class EasyscapePlugin extends Plugin } } - if (config.getEasyConstruction() && !config.getConstructionItems().equals("")) + if (config.getEasyConstruction() && !config.getConstructionItems().equals("") && inHouse) { if (event.getType() == WALK.getId()) { MenuEntry menuEntry = entries[entries.length - 1]; menuEntry.setType(MenuAction.WALK.getId() + MENU_ACTION_DEPRIORITIZE_OFFSET); - client.setMenuEntries(entries); } swap(client, "Build", option, target); @@ -193,17 +322,6 @@ public class EasyscapePlugin extends Plugin client.setMenuEntries(entries); } - if (config.getSwapShop() && !config.getSwappedItems().equals("")) - { - for (String item : config.getSwappedItems().split(",")) - { - if (target.equalsIgnoreCase(item.trim())) - { - swap(client, "Buy 50", option, target); - } - } - } - if (config.getSwapSmithing()) { if (option.equalsIgnoreCase("Smith 1")) @@ -221,11 +339,6 @@ public class EasyscapePlugin extends Plugin swap(client, "Tan All", option, target); } - if (config.getSwapCrafting() && option.equalsIgnoreCase("Make-1")) - { - swap(client, "Make-All", option, target); - } - if (config.getSwapSawmill() && target.equalsIgnoreCase("Sawmill operator")) { swap(client, "Buy-plank", option, target); @@ -236,12 +349,7 @@ public class EasyscapePlugin extends Plugin swap(client, "Buy All", option, target); } - if (config.getSwapStairs() && option.equalsIgnoreCase("Climb Stairs")) - { - swap(client, "Climb Up Stairs", option, target); - } - - if (option.equalsIgnoreCase("Clear-All") && target.equalsIgnoreCase("Bank Filler")) + if (option.equalsIgnoreCase("Clear-All") && target.equalsIgnoreCase("bank Filler")) { swap(client, "Clear", option, target); } @@ -256,7 +364,6 @@ public class EasyscapePlugin extends Plugin { if (isEssencePouch(target)) { - Widget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR); switch (config.getEssenceMode()) { case RUNECRAFTING: @@ -289,26 +396,7 @@ public class EasyscapePlugin extends Plugin { if (target.toLowerCase().contains("games necklace")) { - switch (config.getGamesNecklaceMode()) - { - case BURTHORPE: - swap(client, GamesNecklaceMode.BURTHORPE.toString(), option, target); - break; - case BARBARIAN_OUTPOST: - swap(client, GamesNecklaceMode.BARBARIAN_OUTPOST.toString(), option, target); - break; - case CORPOREAL_BEAST: - swap(client, GamesNecklaceMode.CORPOREAL_BEAST.toString(), option, target); - break; - case TEARS_OF_GUTHIX: - swap(client, GamesNecklaceMode.TEARS_OF_GUTHIX.toString(), option, target); - break; - case WINTERTODT: - swap(client, GamesNecklaceMode.WINTERTODT.toString(), option, target); - break; - default: - break; - } + swap(client, config.getGamesNecklaceMode().toString(), option, target); } } @@ -316,44 +404,7 @@ public class EasyscapePlugin extends Plugin { if (target.toLowerCase().contains("ring of dueling")) { - switch (config.getDuelingRingMode()) - { - case DUEL_ARENA: - swap(client, DuelingRingMode.DUEL_ARENA.toString(), option, target); - break; - case CASTLE_WARS: - swap(client, DuelingRingMode.CASTLE_WARS.toString(), option, target); - break; - case CLAN_WARS: - swap(client, DuelingRingMode.CLAN_WARS.toString(), option, target); - break; - default: - break; - } - } - } - - if (config.getWealthRing()) - { - if (target.toLowerCase().contains("ring of wealth")) - { - switch (config.getWealthRingMode()) - { - case MISCELLANIA: - swap(client, WealthRingMode.MISCELLANIA.toString(), option, target); - break; - case GRAND_EXCHANGE: - swap(client, WealthRingMode.GRAND_EXCHANGE.toString(), option, target); - break; - case FALADOR: - swap(client, WealthRingMode.FALADOR.toString(), option, target); - break; - case DONDAKAN: - swap(client, WealthRingMode.DONDAKAN.toString(), option, target); - break; - default: - break; - } + swap(client, config.getDuelingRingMode().toString(), option, target); } } @@ -361,37 +412,9 @@ public class EasyscapePlugin extends Plugin { if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) { - switch (config.getGloryMode()) - { - case EDGEVILLE: - swap(client, GloryMode.EDGEVILLE.toString(), option, target); - break; - case KARAMJA: - swap(client, GloryMode.KARAMJA.toString(), option, target); - break; - case DRAYNOR_VILLAGE: - swap(client, GloryMode.DRAYNOR_VILLAGE.toString(), option, target); - break; - case AL_KHARID: - swap(client, GloryMode.AL_KHARID.toString(), option, target); - break; - default: - break; - } + swap(client, config.getGloryMode().toString(), option, target); } } - - if (target.toLowerCase().contains("crafting cape") && config.getSwapCraftingCape()) - { - swap(client, "Teleport", option, target); - - } - - if (target.toLowerCase().contains("construct. cape") && config.getSwapConstructionCape()) - { - swap(client, "Tele to poh", option, target); - - } } private void delete(int target) @@ -409,12 +432,30 @@ public class EasyscapePlugin extends Plugin private boolean isEssencePouch(String target) { - return (target.equalsIgnoreCase("Small Pouch") || target.equalsIgnoreCase("Medium Pouch") || target.equalsIgnoreCase("Large Pouch") || target.equalsIgnoreCase("Giant Pouch")); + return (target.equalsIgnoreCase("Small Pouch") || + target.equalsIgnoreCase("Medium Pouch") || + target.equalsIgnoreCase("Large Pouch") || + target.equalsIgnoreCase("Giant Pouch")); } - private boolean isHouse() + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) { - return client.getMapRegions()[0] == HOUSE_REGION_ID; + final GameObject gameObject = event.getGameObject(); + if (PORTAL_4525 == gameObject.getId()) + { + this.inHouse = true; + } + } + + @Subscribe + public void onGameObjectDespawned(GameObjectDespawned event) + { + final GameObject gameObject = event.getGameObject(); + if (PORTAL_4525 == gameObject.getId()) + { + this.inHouse = false; + } } private boolean isPuroPuro() @@ -431,5 +472,4 @@ public class EasyscapePlugin extends Plugin return location.getRegionID() == PURO_PURO_REGION_ID; } } - -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java deleted file mode 100644 index ac0f61b361..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePluginConfig.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("easyscape") -public interface EasyscapePluginConfig extends Config -{ - - @ConfigItem( - keyName = "removeExamine", - name = "Remove Examine", - description = "", - position = 0 - ) - default boolean getRemoveExamine() - { - return true; - } - - @ConfigItem( - keyName = "swapShop", - name = "Easy Shop", - description = "Enables swapping of items in the shop with their buy-50 option.", - position = 1 - ) - default boolean getSwapShop() - { - return true; - } - - @ConfigItem( - keyName = "swappedItems", - name = "Shop Items", - description = "Items listed here will have their value and buy-50 options swapped.", - position = 2 - ) - default String getSwappedItems() - { - return ""; - } - - @ConfigItem( - keyName = "easyConstruction", - name = "Easy Construction", - description = "", - position = 3 - ) - - default boolean getEasyConstruction() - { - return true; - } - - @ConfigItem( - keyName = "constructionItems", - name = "Construction Items", - description = "", - position = 4 - ) - - default String getConstructionItems() - { - return ""; - } - - @ConfigItem( - keyName = "removeObjects", - name = "Remove Objects", - description = "", - position = 5 - ) - default boolean getRemoveObjects() - { - return true; - } - - @ConfigItem( - keyName = "removedObjects", - name = "Removed Objects", - description = "", - position = 6 - ) - default String getRemovedObjects() - { - return ""; - } - - @ConfigItem( - keyName = "swapSmithing", - name = "Swap Smithing", - description = "Enables swapping of smith-1 and smith-all options.", - position = 7 - ) - default boolean getSwapSmithing() - { - return true; - } - - @ConfigItem( - keyName = "swapTanning", - name = "Swap Tanning", - description = "Enables swapping of tan-1 and tan-all options.", - position = 8 - ) - default boolean getSwapTanning() - { - return true; - } - - @ConfigItem( - keyName = "swapCrafting", - name = "Swap Crafting", - description = "", - position = 9 - ) - default boolean getSwapCrafting() - { - return true; - } - - @ConfigItem( - keyName = "swapArdougneCape", - name = "Swap Ardougne Cape", - description = "Enables swapping of teleport and wear.", - position = 10 - ) - default boolean getSwapArdougneCape() - { - return true; - } - - @ConfigItem( - keyName = "swapStairs", - name = "Swap Stairs", - description = "", - position = 11 - ) - - default boolean getSwapStairs() - { - return true; - } - - @ConfigItem( - keyName = "swapSawmill", - name = "Swap Sawmill Operator", - description = "", - position = 12 - ) - default boolean getSwapSawmill() - { - return true; - } - - @ConfigItem( - keyName = "swapSawmillPlanks", - name = "Swap Buy Planks", - description = "", - position = 13 - ) - - default boolean getSwapSawmillPlanks() - { - return true; - } - - @ConfigItem( - keyName = "swapPuroPuro", - name = "Swap Puro Puro Wheat", - description = "", - position = 14 - ) - default boolean getSwapPuro() - { - return true; - } - - @ConfigItem( - keyName = "swapEssencePounch", - name = "Swap Essence Pouch", - description = "Enables swapping of fill and empty for essence pounch.", - position = 15 - ) - default boolean getSwapEssencePouch() - { - return true; - } - - @ConfigItem( - keyName = "essenceMode", - name = "Essence Pouch Mode", - description = "Runecrafting or essence mining mode.", - position = 16 - ) - - default EssenceMode getEssenceMode() - { - return EssenceMode.RUNECRAFTING; - } - - @ConfigItem( - keyName = "swapGamesNecklace", - name = "Swap Games Necklace", - description = "Enables swapping of games necklace.", - position = 17 - ) - default boolean getGamesNecklace() - { - return true; - } - - @ConfigItem( - keyName = "gamesNecklaceMode", - name = "Games Necklace Mode", - description = "Teleport location mode.", - position = 18 - ) - - default GamesNecklaceMode getGamesNecklaceMode() - { - return GamesNecklaceMode.BURTHORPE; - } - - @ConfigItem( - keyName = "swapDuelingRing", - name = "Swap Dueling Ring", - description = "Enables swapping of dueling ring.", - position = 19 - ) - default boolean getDuelingRing() - { - return true; - } - - @ConfigItem( - keyName = "duelingRingMode", - name = "Dueling Ring Mode", - description = "Teleport location mode.", - position = 20 - ) - - default DuelingRingMode getDuelingRingMode() - { - return DuelingRingMode.DUEL_ARENA; - } - - @ConfigItem( - keyName = "swapGlory", - name = "Swap Glory", - description = "Enables swapping of Amulet of Glory.", - position = 21 - ) - default boolean getGlory() - { - return true; - } - - @ConfigItem( - keyName = "gloryMode", - name = "Glory Mode", - description = "Teleport location mode.", - position = 22 - ) - - default GloryMode getGloryMode() - { - return GloryMode.EDGEVILLE; - } - - @ConfigItem( - keyName = "swapWealthRing", - name = "Swap Ring of Wealth", - description = "Enables swapping of Ring of Wealth.", - position = 23 - ) - default boolean getWealthRing() - { - return true; - } - - @ConfigItem( - keyName = "WealthRingMode", - name = "Wealth Ring Mode", - description = "Teleport location mode.", - position = 24 - ) - - default WealthRingMode getWealthRingMode() - { - return WealthRingMode.GRAND_EXCHANGE; - } - - @ConfigItem( - keyName = "swapConstructionCape", - name = "Swap Construction Cape", - description = "Enables swapping of teleport and wear.", - position = 25 - ) - default boolean getSwapConstructionCape() - { - return true; - } - - @ConfigItem( - keyName = "swapCraftingCape", - name = "Swap Crafting Cape", - description = "Enables swapping of teleport and wear.", - position = 26 - ) - default boolean getSwapCraftingCape() - { - return true; - } -} - diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java deleted file mode 100644 index 525aa5ee3c..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/WealthRingMode.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum WealthRingMode -{ - MISCELLANIA("Miscellania"), - GRAND_EXCHANGE("Grand Exchange"), - FALADOR("Falador"), - DONDAKAN("Dondakan"); - - private final String name; - - WealthRingMode(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/DuelingRingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DuelingRingMode.java similarity index 91% rename from runelite-client/src/main/java/net/runelite/client/plugins/easyscape/DuelingRingMode.java rename to runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DuelingRingMode.java index 1cb3651b5b..c3862fc8eb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/DuelingRingMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DuelingRingMode.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum DuelingRingMode -{ - DUEL_ARENA("Duel Arena"), - CASTLE_WARS("Castle Wars"), - CLAN_WARS("Clan Wars"); - - private final String name; - - DuelingRingMode(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } -} +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum DuelingRingMode +{ + DUEL_ARENA("Duel Arena"), + CASTLE_WARS("Castle Wars"), + CLAN_WARS("Clan Wars"); + + private final String name; + + DuelingRingMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EssenceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java similarity index 91% rename from runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EssenceMode.java rename to runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java index fe001dbea4..57f37b7ae5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EssenceMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum EssenceMode -{ - RUNECRAFTING("Runecrafting"), - ESSENCE_MINING("Essence Mining"); - - private final String name; - - EssenceMode(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } -} +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum EssenceMode +{ + RUNECRAFTING("Runecrafting"), + ESSENCE_MINING("Essence Mining"); + + private final String name; + + EssenceMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GamesNecklaceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/GamesNecklaceMode.java similarity index 92% rename from runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GamesNecklaceMode.java rename to runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/GamesNecklaceMode.java index 457fc100bc..0f4abfb9a6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GamesNecklaceMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/GamesNecklaceMode.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum GamesNecklaceMode -{ - BURTHORPE("Burthorpe"), - BARBARIAN_OUTPOST("Barbarian Outpost"), - CORPOREAL_BEAST("Corporeal Beast"), - TEARS_OF_GUTHIX("Tears of Guthix"), - WINTERTODT("Wintertodt Camp"); - - private final String name; - - GamesNecklaceMode(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } -} +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum GamesNecklaceMode +{ + BURTHORPE("Burthorpe"), + BARBARIAN_OUTPOST("Barbarian Outpost"), + CORPOREAL_BEAST("Corporeal Beast"), + TEARS_OF_GUTHIX("Tears of Guthix"), + WINTERTODT("Wintertodt Camp"); + + private final String name; + + GamesNecklaceMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GloryMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/GloryMode.java similarity index 91% rename from runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GloryMode.java rename to runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/GloryMode.java index f160c41c56..f3629af6cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/GloryMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/GloryMode.java @@ -1,46 +1,46 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * 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.easyscape; - -public enum GloryMode -{ - EDGEVILLE("Edgeville"), - KARAMJA("Karamja"), - DRAYNOR_VILLAGE("Draynor Village"), - AL_KHARID("Al Kharid"); - - private final String name; - - GloryMode(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } -} +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum GloryMode +{ + EDGEVILLE("Edgeville"), + KARAMJA("Karamja"), + DRAYNOR_VILLAGE("Draynor Village"), + AL_KHARID("Al Kharid"); + + private final String name; + + GloryMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file From d435fc51885cb6f9400b7505fb30048218ba1704 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sun, 19 May 2019 19:31:14 +0100 Subject: [PATCH 47/78] easyscape additions easyscape additions --- .../plugins/easyscape/EasyscapeConfig.java | 288 ++++++++++++++++-- .../plugins/easyscape/EasyscapePlugin.java | 76 +++++ .../easyscape/util/BurningAmuletMode.java | 45 +++ .../easyscape/util/CombatBraceletMode.java | 46 +++ .../easyscape/util/DigsitePendantMode.java | 45 +++ .../easyscape/util/NecklaceOfPassageMode.java | 45 +++ .../easyscape/util/SkillsNecklaceMode.java | 48 +++ .../easyscape/util/SlayerRingMode.java | 47 +++ .../easyscape/util/XericsTalismanMode.java | 47 +++ 9 files changed, 656 insertions(+), 31 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java index cba9a8baaf..dda9608138 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java @@ -32,7 +32,13 @@ import net.runelite.client.plugins.easyscape.util.DuelingRingMode; import net.runelite.client.plugins.easyscape.util.EssenceMode; import net.runelite.client.plugins.easyscape.util.GamesNecklaceMode; import net.runelite.client.plugins.easyscape.util.GloryMode; - +import net.runelite.client.plugins.easyscape.util.SkillsNecklaceMode; +import net.runelite.client.plugins.easyscape.util.NecklaceOfPassageMode; +import net.runelite.client.plugins.easyscape.util.DigsitePendantMode; +import net.runelite.client.plugins.easyscape.util.CombatBraceletMode; +import net.runelite.client.plugins.easyscape.util.SlayerRingMode; +import net.runelite.client.plugins.easyscape.util.BurningAmuletMode; +import net.runelite.client.plugins.easyscape.util.XericsTalismanMode; @ConfigGroup("easyscape") public interface EasyscapeConfig extends Config @@ -440,23 +446,11 @@ public interface EasyscapeConfig extends Config return false; } - @ConfigItem( - keyName = "swapArdougneCape", - name = "Swap Ardougne Cape", - description = "Enables swapping of teleport and wear.", - position = 34, - group = "Miscellaneous swapper" - ) - default boolean getSwapArdougneCape() - { - return false; - } - @ConfigItem( keyName = "swapSawmill", name = "Swap Sawmill Operator", description = "Makes Buy-plank the default option on the sawmill operator.", - position = 35, + position = 34, group = "Miscellaneous swapper" ) default boolean getSwapSawmill() @@ -468,7 +462,7 @@ public interface EasyscapeConfig extends Config keyName = "swapSawmillPlanks", name = "Swap Buy Planks", description = "Makes Buy All the default option in buy planks.", - position = 36, + position = 35, group = "Miscellaneous swapper" ) default boolean getSwapSawmillPlanks() @@ -480,7 +474,7 @@ public interface EasyscapeConfig extends Config keyName = "swapPuroPuro", name = "Swap Puro Puro Wheat", description = "", - position = 37, + position = 36, group = "Miscellaneous swapper" ) default boolean getSwapPuro() @@ -492,7 +486,7 @@ public interface EasyscapeConfig extends Config keyName = "swapEssencePounch", name = "Swap Essence Pouch", description = "", - position = 38, + position = 37, group = "Miscellaneous swapper" ) default boolean getSwapEssencePouch() @@ -504,20 +498,22 @@ public interface EasyscapeConfig extends Config keyName = "essenceMode", name = "Mode", description = "", - position = 39, - group = "Miscellaneous swapper" + position = 38, + group = "Jewellery swapper" ) default EssenceMode getEssenceMode() { return EssenceMode.RUNECRAFTING; } +// ----------------------------------------------------------- // + @ConfigItem( keyName = "swapGamesNecklace", name = "Swap Games Necklace", description = "", - position = 40, - group = "Miscellaneous swapper" + position = 39, + group = "Jewellery swapper" ) default boolean getGamesNecklace() { @@ -528,8 +524,8 @@ public interface EasyscapeConfig extends Config keyName = "gamesNecklaceMode", name = "Mode", description = "", - position = 41, - group = "Miscellaneous swapper" + position = 40, + group = "Jewellery swapper" ) default GamesNecklaceMode getGamesNecklaceMode() { @@ -540,8 +536,8 @@ public interface EasyscapeConfig extends Config keyName = "swapDuelingRing", name = "Swap Dueling Ring", description = "", - position = 42, - group = "Miscellaneous swapper" + position = 41, + group = "Jewellery swapper" ) default boolean getDuelingRing() { @@ -552,8 +548,8 @@ public interface EasyscapeConfig extends Config keyName = "duelingRingMode", name = "Mode", description = "", - position = 43, - group = "Miscellaneous swapper" + position = 42, + group = "Jewellery swapper" ) default DuelingRingMode getDuelingRingMode() { @@ -564,8 +560,8 @@ public interface EasyscapeConfig extends Config keyName = "swapGlory", name = "Swap Glory", description = "", - position = 44, - group = "Miscellaneous swapper" + position = 43, + group = "Jewellery swapper" ) default boolean getGlory() { @@ -576,11 +572,241 @@ public interface EasyscapeConfig extends Config keyName = "gloryMode", name = "Mode", description = "", - position = 45, - group = "Miscellaneous swapper" + position = 44, + group = "Jewellery swapper" ) default GloryMode getGloryMode() { return GloryMode.EDGEVILLE; } + + @ConfigItem( + keyName = "swapSkill", + name = "Swap Skill", + description = "", + position = 45, + group = "Jewellery swapper" + ) + default boolean getSkillsNecklace() + { + return false; + } + + @ConfigItem( + keyName = "skillsnecklacemode", + name = "Mode", + description = "", + position = 46, + group = "Jewellery swapper" + ) + default SkillsNecklaceMode getSkillsNecklaceMode() + { + return SkillsNecklaceMode.FARMING_GUILD; + } + + @ConfigItem( + keyName = "swapPassage", + name = "Swap Passage", + description = "", + position = 47, + group = "Jewellery swapper" + ) + default boolean getNecklaceofPassage() + { + return false; + } + + @ConfigItem( + keyName = "necklaceofpassagemode", + name = "Mode", + description = "", + position = 48, + group = "Jewellery swapper" + ) + default NecklaceOfPassageMode getNecklaceofPassageMode() + { + return NecklaceOfPassageMode.WIZARDS_TOWER; + } + + @ConfigItem( + keyName = "swapDigsite", + name = "Swap Digsite", + description = "", + position = 49, + group = "Jewellery swapper" + ) + default boolean getDigsitePendant() + { + return false; + } + + @ConfigItem( + keyName = "digsitependantmode", + name = "Mode", + description = "", + position = 50, + group = "Jewellery swapper" + ) + default DigsitePendantMode getDigsitePendantMode() + { + return DigsitePendantMode.FOSSIL_ISLAND; + } + + @ConfigItem( + keyName = "swapCombat", + name = "Swap Combat", + description = "", + position = 51, + group = "Jewellery swapper" + ) + default boolean getCombatBracelet() + { + return false; + } + + @ConfigItem( + keyName = "combatbraceletmode", + name = "Mode", + description = "", + position = 52, + group = "Jewellery swapper" + ) + default CombatBraceletMode getCombatBraceletMode() + { + return CombatBraceletMode.WARRIORS_GUILD; + } + + @ConfigItem( + keyName = "swapslayer", + name = "Swap slayer", + description = "", + position = 53, + group = "Jewellery swapper" + ) + default boolean getSlayerRing() + { + return false; + } + + @ConfigItem( + keyName = "slayerringmode", + name = "Mode", + description = "", + position = 54, + group = "Jewellery swapper" + ) + default SlayerRingMode getSlayerRingMode() + { + return SlayerRingMode.SLAYER_TOWER; + } + + @ConfigItem( + keyName = "swapburning", + name = "Swap burning", + description = "", + position = 55, + group = "Jewellery swapper" + ) + default boolean getBurningAmulet() + { + return false; + } + + @ConfigItem( + keyName = "burningamuletmode", + name = "Mode", + description = "", + position = 56, + group = "Jewellery swapper" + ) + default BurningAmuletMode getBurningAmuletMode() + { + return BurningAmuletMode.BANDIT_CAMP; + } + + @ConfigItem( + keyName = "swapxeric", + name = "Swap xeric", + description = "", + position = 57, + group = "Jewellery swapper" + ) + default boolean getXericsTalisman() + { + return false; + } + + @ConfigItem( + keyName = "xericstalismanmode", + name = "Mode", + description = "", + position = 58, + group = "Jewellery swapper" + ) + default XericsTalismanMode getXericsTalismanMode() + { + return XericsTalismanMode.XERICS_LOOKOUT; + } + +// ----------------------------------------------------------- // + + @ConfigItem( + keyName = "swapArdougneCape", + name = "Swap Ardougne Cape", + description = "Enables swapping of teleport and wear.", + position = 59, + group = "Equipment swapper" + ) + default boolean getSwapArdougneCape() + { + return false; + } + + @ConfigItem( + keyName = "swapConstructionCape", + name = "Swap Construction Cape", + description = "Enables swapping of teleport and wear.", + position = 60, + group = "Equipment swapper" + ) + default boolean getSwapConstructionCape() + { + return true; + } + + @ConfigItem( + keyName = "swapCraftingCape", + name = "Swap Crafting Cape", + description = "Enables swapping of teleport and wear.", + position = 61, + group = "Equipment swapper" + ) + default boolean getSwapCraftingCape() + { + return true; + } + + @ConfigItem( + keyName = "swapMagicCape", + name = "Swap Magic Cape", + description = "Enables swapping of spellbook and wear.", + position = 62, + group = "Equipment swapper" + ) + default boolean getSwapMagicCape() + { + return true; + } + + @ConfigItem( + keyName = "swapExplorersRing", + name = "Swap Explorers Ring", + description = "Enables swapping of spellbook and wear.", + position = 63, + group = "Equipment swapper" + ) + default boolean getExplorersRing() + { + return true; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 41476f163f..bb9a246415 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -359,6 +359,26 @@ public class EasyscapePlugin extends Plugin swap(client, "Kandarin Monastery", option, target); swap(client, "Monastery Teleport", option, target); } + + if (target.toLowerCase().contains("crafting cape") && config.getSwapCraftingCape()) + { + swap(client, "Teleport", option, target); + } + + if (target.toLowerCase().contains("construct. cape") && config.getSwapConstructionCape()) + { + swap(client, "Tele to poh", option, target); + } + + if (target.toLowerCase().contains("magic cape") && config.getSwapMagicCape()) + { + swap(client, "Spellbook", option, target); + } + + if (target.toLowerCase().contains("explorer's ring") && config.getSwapMagicCape()) + { + swap(client, "Teleport", option, target); + } if (config.getSwapEssencePouch()) { @@ -415,6 +435,62 @@ public class EasyscapePlugin extends Plugin swap(client, config.getGloryMode().toString(), option, target); } } + + if (config.getSkillsNecklace()) + { + if (target.toLowerCase().contains("skills necklace")) + { + swap(client, config.getSkillsNecklaceMode().toString(), option, target); + } + } + + if (config.getNecklaceofPassage()) + { + if (target.toLowerCase().contains("necklace of passage")) + { + swap(client, config.getNecklaceofPassageMode().toString(), option, target); + } + } + + if (config.getDigsitePendant()) + { + if (target.toLowerCase().contains("digsite pendant")) + { + swap(client, config.getDigsitePendantMode().toString(), option, target); + } + } + + if (config.getCombatBracelet()) + { + if (target.toLowerCase().contains("combat bracelet")) + { + swap(client, config.getCombatBraceletMode().toString(), option, target); + } + } + + if (config.getSlayerRing()) + { + if (target.toLowerCase().contains("slayer ring")) + { + swap(client, config.getSlayerRingMode().toString(), option, target); + } + } + + if (config.getBurningAmulet()) + { + if (target.toLowerCase().contains("burning amulet")) + { + swap(client, config.getBurningAmuletMode().toString(), option, target); + } + } + + if (config.getXericsTalisman()) + { + if (target.toLowerCase().contains("xeric's talisman")) + { + swap(client, config.getXericsTalismanMode().toString(), option, target); + } + } } private void delete(int target) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java new file mode 100644 index 0000000000..0001b9eccc --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum BurningAmuletMode +{ + CHAOS_TEMPLE("Chaos Temple"), + BANDIT_CAMP("Bandit Camp"), + LAVA_MAZE("Lava Maze"); + + private final String name; + + BurningAmuletMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java new file mode 100644 index 0000000000..01bfdd65c9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum CombatBraceletMode +{ + WARRIORS_GUILD("Warriors' Guild"), + CHAMPIONS_GUILD("Champions' Guild"), + EDGEVILLE_MONASTERY("Edgeville Monstery"), + RANGING_GUILD("Ranging Guild"); + + private final String name; + + CombatBraceletMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java new file mode 100644 index 0000000000..01a425cfe4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum DigsitePendantMode +{ + DIGSITE("Digsite"), + FOSSIL_ISLAND("Fossil Island"), + LITHKREN("Lithkren"); + + private final String name; + + DigsitePendantMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java new file mode 100644 index 0000000000..89311be01c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum NecklaceOfPassageMode +{ + WIZARDS_TOWER("Wizard's Tower"), + THE_OUTPOST("The Outpost"), + EAGLES_EYRIE("Eagle's Eyrie"); + + private final String name; + + NecklaceOfPassageMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java new file mode 100644 index 0000000000..3c8b2dd382 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum SkillsNecklaceMode +{ + FISHING_GUILD("Fishing Guild"), + MINING_GUILD("Mining Guild"), + CRAFTING_GUILD("Crafting Guild"), + COOKING_GUILD("Cooking Guild"), + WOODCUTTING_GUILD("Woodcutting Guild"), + FARMING_GUILD("Farming Guild"); + + private final String name; + + SkillsNecklaceMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java new file mode 100644 index 0000000000..56375a0bd1 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum SlayerRingMode +{ + SLAYER_TOWER("Slayer Tower"), + FREMENNIK_SLAYER_DUNGEON("Fremennik Slayer Dungeon"), + TARNS_LAIR("Tarn's Lair"), + STRONGHOLD_SLAYER_CAVE("Stronghold Slayer Cave"), + DARK_BEASTS("Dark Beasts"); + + private final String name; + + SlayerRingMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java new file mode 100644 index 0000000000..0e09fac145 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019, Alan Baumgartner + * 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.easyscape.util; + +public enum XericsTalismanMode +{ + XERICS_LOOKOUT("Xeric's Lookout"), + XERICS_GLADE("Xeric's Glade"), + XERICS_INFERNO("Xeric's Inferno"), + XERICS_HEART("Xeric's Heart"), + XERICS_HONOUR("Xeric's Honour"); + + private final String name; + + XericsTalismanMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file From 0fbf5170f7b187bb377d29cbe59419d1df228316 Mon Sep 17 00:00:00 2001 From: sdburns1998 <49877861+sdburns1998@users.noreply.github.com> Date: Sun, 19 May 2019 20:38:12 +0200 Subject: [PATCH 48/78] Align settings gear (#311) --- .../client/plugins/config/PluginListItem.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java index c52d85a575..3cd10af230 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java @@ -195,12 +195,16 @@ public class PluginListItem extends JPanel configButton.setVisible(true); configButton.setToolTipText("Edit plugin configuration"); } - if (!name.equals("RuneLitePlus")) + + toggleButton.setPreferredSize(new Dimension(25, 0)); + attachToggleButtonListener(toggleButton); + + if (name.equals("RuneLitePlus")) { - toggleButton.setPreferredSize(new Dimension(25, 0)); - attachToggleButtonListener(toggleButton); - buttonPanel.add(toggleButton); + toggleButton.setVisible(false); } + + buttonPanel.add(toggleButton); } private void attachToggleButtonListener(IconButton button) From 05bb85a93b769453a98613f774f9ddd750ee1915 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sun, 19 May 2019 20:31:06 +0100 Subject: [PATCH 49/78] added ring of wealth + updated licence added ring of wealth + updated licences on all files. --- .../plugins/easyscape/EasyscapeConfig.java | 43 +++++++++++++---- .../plugins/easyscape/EasyscapePlugin.java | 18 +++++-- .../easyscape/util/BurningAmuletMode.java | 3 +- .../easyscape/util/CombatBraceletMode.java | 3 +- .../easyscape/util/DigsitePendantMode.java | 3 +- .../easyscape/util/NecklaceOfPassageMode.java | 3 +- .../easyscape/util/RingOfWealthMode.java | 47 +++++++++++++++++++ .../easyscape/util/SkillsNecklaceMode.java | 3 +- .../easyscape/util/SlayerRingMode.java | 3 +- .../easyscape/util/XericsTalismanMode.java | 3 +- 10 files changed, 110 insertions(+), 19 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/RingOfWealthMode.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java index dda9608138..720d6258ce 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java @@ -1,6 +1,8 @@ /* - * Copyright (c) 2019, Owain van Brakel - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle + * Copyright (c) 2018, Owain van Brakel * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +41,7 @@ import net.runelite.client.plugins.easyscape.util.CombatBraceletMode; import net.runelite.client.plugins.easyscape.util.SlayerRingMode; import net.runelite.client.plugins.easyscape.util.BurningAmuletMode; import net.runelite.client.plugins.easyscape.util.XericsTalismanMode; +import net.runelite.client.plugins.easyscape.util.RingOfWealthMode; @ConfigGroup("easyscape") public interface EasyscapeConfig extends Config @@ -748,13 +751,37 @@ public interface EasyscapeConfig extends Config return XericsTalismanMode.XERICS_LOOKOUT; } + @ConfigItem( + keyName = "swapwealth", + name = "Swap wealth", + description = "", + position = 59, + group = "Jewellery swapper" + ) + default boolean getRingofWealth() + { + return false; + } + + @ConfigItem( + keyName = "ringofwealthmode", + name = "Mode", + description = "", + position = 60, + group = "Jewellery swapper" + ) + default RingOfWealthMode getRingofWealthMode() + { + return RingOfWealthMode.GRAND_EXCHANGE; + } + // ----------------------------------------------------------- // @ConfigItem( keyName = "swapArdougneCape", name = "Swap Ardougne Cape", description = "Enables swapping of teleport and wear.", - position = 59, + position = 61, group = "Equipment swapper" ) default boolean getSwapArdougneCape() @@ -766,7 +793,7 @@ public interface EasyscapeConfig extends Config keyName = "swapConstructionCape", name = "Swap Construction Cape", description = "Enables swapping of teleport and wear.", - position = 60, + position = 62, group = "Equipment swapper" ) default boolean getSwapConstructionCape() @@ -778,7 +805,7 @@ public interface EasyscapeConfig extends Config keyName = "swapCraftingCape", name = "Swap Crafting Cape", description = "Enables swapping of teleport and wear.", - position = 61, + position = 63, group = "Equipment swapper" ) default boolean getSwapCraftingCape() @@ -790,7 +817,7 @@ public interface EasyscapeConfig extends Config keyName = "swapMagicCape", name = "Swap Magic Cape", description = "Enables swapping of spellbook and wear.", - position = 62, + position = 64, group = "Equipment swapper" ) default boolean getSwapMagicCape() @@ -802,10 +829,10 @@ public interface EasyscapeConfig extends Config keyName = "swapExplorersRing", name = "Swap Explorers Ring", description = "Enables swapping of spellbook and wear.", - position = 63, + position = 65, group = "Equipment swapper" ) - default boolean getExplorersRing() + default boolean getSwapExplorersRing() { return true; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index bb9a246415..a14e303c0d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -1,6 +1,8 @@ /* - * Copyright (c) 2019, Owain van Brakel - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle + * Copyright (c) 2018, Owain van Brakel * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -375,7 +377,7 @@ public class EasyscapePlugin extends Plugin swap(client, "Spellbook", option, target); } - if (target.toLowerCase().contains("explorer's ring") && config.getSwapMagicCape()) + if (target.toLowerCase().contains("explorer's ring") && config.getSwapExplorersRing()) { swap(client, "Teleport", option, target); } @@ -490,7 +492,15 @@ public class EasyscapePlugin extends Plugin { swap(client, config.getXericsTalismanMode().toString(), option, target); } - } + } + + if (config.getRingofWealth()) + { + if (target.toLowerCase().contains("ring of wealth")) + { + swap(client, config.getRingofWealthMode().toString(), option, target); + } + } } private void delete(int target) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java index 0001b9eccc..e1552adb67 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/BurningAmuletMode.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java index 01bfdd65c9..000e8d8203 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/CombatBraceletMode.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java index 01a425cfe4..232feed044 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/DigsitePendantMode.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java index 89311be01c..74fae105d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/NecklaceOfPassageMode.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/RingOfWealthMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/RingOfWealthMode.java new file mode 100644 index 0000000000..f30e74a6e4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/RingOfWealthMode.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle + * 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.easyscape.util; + +public enum RingOfWealthMode +{ + MISCELLANIA("Miscellania"), + GRAND_EXCHANGE("Grand Exchange"), + FALADOR("Falador"), + DONDAKAN("Dondakan"); + + private final String name; + + RingOfWealthMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java index 3c8b2dd382..7d60d834c3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SkillsNecklaceMode.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java index 56375a0bd1..b86d4aba30 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java index 0e09fac145..0212271f36 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/XericsTalismanMode.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Alan Baumgartner + * Copyright (c) 2018, https://runelitepl.us + * Copyright (c) 2018, Kyle * All rights reserved. * * Redistribution and use in source and binary forms, with or without From b936559bcf99ff63a0ceebc88c6fb5b88e279543 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sun, 19 May 2019 21:32:57 +0100 Subject: [PATCH 50/78] oops --- .../net/runelite/client/plugins/easyscape/EasyscapeConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java index 720d6258ce..7b90681332 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java @@ -502,7 +502,7 @@ public interface EasyscapeConfig extends Config name = "Mode", description = "", position = 38, - group = "Jewellery swapper" + group = "Miscellaneous swapper" ) default EssenceMode getEssenceMode() { From 37d749c6882024147f9fe52ce9b9931b138777c1 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sun, 19 May 2019 22:26:55 +0100 Subject: [PATCH 51/78] remove pouch fill pouch fill exists in runecrafting plugin --- .../plugins/easyscape/EasyscapeConfig.java | 79 +++++++------------ .../plugins/easyscape/EasyscapePlugin.java | 32 -------- .../plugins/easyscape/util/EssenceMode.java | 44 ----------- 3 files changed, 27 insertions(+), 128 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java index 7b90681332..964d07f3f3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java @@ -31,7 +31,6 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.plugins.easyscape.util.DuelingRingMode; -import net.runelite.client.plugins.easyscape.util.EssenceMode; import net.runelite.client.plugins.easyscape.util.GamesNecklaceMode; import net.runelite.client.plugins.easyscape.util.GloryMode; import net.runelite.client.plugins.easyscape.util.SkillsNecklaceMode; @@ -485,37 +484,13 @@ public interface EasyscapeConfig extends Config return false; } - @ConfigItem( - keyName = "swapEssencePounch", - name = "Swap Essence Pouch", - description = "", - position = 37, - group = "Miscellaneous swapper" - ) - default boolean getSwapEssencePouch() - { - return false; - } - - @ConfigItem( - keyName = "essenceMode", - name = "Mode", - description = "", - position = 38, - group = "Miscellaneous swapper" - ) - default EssenceMode getEssenceMode() - { - return EssenceMode.RUNECRAFTING; - } - // ----------------------------------------------------------- // @ConfigItem( keyName = "swapGamesNecklace", name = "Swap Games Necklace", description = "", - position = 39, + position = 37, group = "Jewellery swapper" ) default boolean getGamesNecklace() @@ -527,7 +502,7 @@ public interface EasyscapeConfig extends Config keyName = "gamesNecklaceMode", name = "Mode", description = "", - position = 40, + position = 38, group = "Jewellery swapper" ) default GamesNecklaceMode getGamesNecklaceMode() @@ -539,7 +514,7 @@ public interface EasyscapeConfig extends Config keyName = "swapDuelingRing", name = "Swap Dueling Ring", description = "", - position = 41, + position = 39, group = "Jewellery swapper" ) default boolean getDuelingRing() @@ -551,7 +526,7 @@ public interface EasyscapeConfig extends Config keyName = "duelingRingMode", name = "Mode", description = "", - position = 42, + position = 40, group = "Jewellery swapper" ) default DuelingRingMode getDuelingRingMode() @@ -563,7 +538,7 @@ public interface EasyscapeConfig extends Config keyName = "swapGlory", name = "Swap Glory", description = "", - position = 43, + position = 41, group = "Jewellery swapper" ) default boolean getGlory() @@ -575,7 +550,7 @@ public interface EasyscapeConfig extends Config keyName = "gloryMode", name = "Mode", description = "", - position = 44, + position = 42, group = "Jewellery swapper" ) default GloryMode getGloryMode() @@ -587,7 +562,7 @@ public interface EasyscapeConfig extends Config keyName = "swapSkill", name = "Swap Skill", description = "", - position = 45, + position = 43, group = "Jewellery swapper" ) default boolean getSkillsNecklace() @@ -599,7 +574,7 @@ public interface EasyscapeConfig extends Config keyName = "skillsnecklacemode", name = "Mode", description = "", - position = 46, + position = 44, group = "Jewellery swapper" ) default SkillsNecklaceMode getSkillsNecklaceMode() @@ -611,7 +586,7 @@ public interface EasyscapeConfig extends Config keyName = "swapPassage", name = "Swap Passage", description = "", - position = 47, + position = 45, group = "Jewellery swapper" ) default boolean getNecklaceofPassage() @@ -623,7 +598,7 @@ public interface EasyscapeConfig extends Config keyName = "necklaceofpassagemode", name = "Mode", description = "", - position = 48, + position = 46, group = "Jewellery swapper" ) default NecklaceOfPassageMode getNecklaceofPassageMode() @@ -635,7 +610,7 @@ public interface EasyscapeConfig extends Config keyName = "swapDigsite", name = "Swap Digsite", description = "", - position = 49, + position = 47, group = "Jewellery swapper" ) default boolean getDigsitePendant() @@ -647,7 +622,7 @@ public interface EasyscapeConfig extends Config keyName = "digsitependantmode", name = "Mode", description = "", - position = 50, + position = 48, group = "Jewellery swapper" ) default DigsitePendantMode getDigsitePendantMode() @@ -659,7 +634,7 @@ public interface EasyscapeConfig extends Config keyName = "swapCombat", name = "Swap Combat", description = "", - position = 51, + position = 49, group = "Jewellery swapper" ) default boolean getCombatBracelet() @@ -671,7 +646,7 @@ public interface EasyscapeConfig extends Config keyName = "combatbraceletmode", name = "Mode", description = "", - position = 52, + position = 50, group = "Jewellery swapper" ) default CombatBraceletMode getCombatBraceletMode() @@ -683,7 +658,7 @@ public interface EasyscapeConfig extends Config keyName = "swapslayer", name = "Swap slayer", description = "", - position = 53, + position = 51, group = "Jewellery swapper" ) default boolean getSlayerRing() @@ -695,7 +670,7 @@ public interface EasyscapeConfig extends Config keyName = "slayerringmode", name = "Mode", description = "", - position = 54, + position = 52, group = "Jewellery swapper" ) default SlayerRingMode getSlayerRingMode() @@ -707,7 +682,7 @@ public interface EasyscapeConfig extends Config keyName = "swapburning", name = "Swap burning", description = "", - position = 55, + position = 53, group = "Jewellery swapper" ) default boolean getBurningAmulet() @@ -719,7 +694,7 @@ public interface EasyscapeConfig extends Config keyName = "burningamuletmode", name = "Mode", description = "", - position = 56, + position = 54, group = "Jewellery swapper" ) default BurningAmuletMode getBurningAmuletMode() @@ -731,7 +706,7 @@ public interface EasyscapeConfig extends Config keyName = "swapxeric", name = "Swap xeric", description = "", - position = 57, + position = 55, group = "Jewellery swapper" ) default boolean getXericsTalisman() @@ -743,7 +718,7 @@ public interface EasyscapeConfig extends Config keyName = "xericstalismanmode", name = "Mode", description = "", - position = 58, + position = 56, group = "Jewellery swapper" ) default XericsTalismanMode getXericsTalismanMode() @@ -755,7 +730,7 @@ public interface EasyscapeConfig extends Config keyName = "swapwealth", name = "Swap wealth", description = "", - position = 59, + position = 57, group = "Jewellery swapper" ) default boolean getRingofWealth() @@ -767,7 +742,7 @@ public interface EasyscapeConfig extends Config keyName = "ringofwealthmode", name = "Mode", description = "", - position = 60, + position = 58, group = "Jewellery swapper" ) default RingOfWealthMode getRingofWealthMode() @@ -781,7 +756,7 @@ public interface EasyscapeConfig extends Config keyName = "swapArdougneCape", name = "Swap Ardougne Cape", description = "Enables swapping of teleport and wear.", - position = 61, + position = 59, group = "Equipment swapper" ) default boolean getSwapArdougneCape() @@ -793,7 +768,7 @@ public interface EasyscapeConfig extends Config keyName = "swapConstructionCape", name = "Swap Construction Cape", description = "Enables swapping of teleport and wear.", - position = 62, + position = 60, group = "Equipment swapper" ) default boolean getSwapConstructionCape() @@ -805,7 +780,7 @@ public interface EasyscapeConfig extends Config keyName = "swapCraftingCape", name = "Swap Crafting Cape", description = "Enables swapping of teleport and wear.", - position = 63, + position = 61, group = "Equipment swapper" ) default boolean getSwapCraftingCape() @@ -817,7 +792,7 @@ public interface EasyscapeConfig extends Config keyName = "swapMagicCape", name = "Swap Magic Cape", description = "Enables swapping of spellbook and wear.", - position = 64, + position = 62, group = "Equipment swapper" ) default boolean getSwapMagicCape() @@ -829,7 +804,7 @@ public interface EasyscapeConfig extends Config keyName = "swapExplorersRing", name = "Swap Explorers Ring", description = "Enables swapping of spellbook and wear.", - position = 65, + position = 63, group = "Equipment swapper" ) default boolean getSwapExplorersRing() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index a14e303c0d..f386cb5bd5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -382,38 +382,6 @@ public class EasyscapePlugin extends Plugin swap(client, "Teleport", option, target); } - if (config.getSwapEssencePouch()) - { - if (isEssencePouch(target)) - { - switch (config.getEssenceMode()) - { - case RUNECRAFTING: - if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) - { - swap(client, "Empty", option, target); - } - else - { - swap(client, "Fill", option, target); - } - break; - case ESSENCE_MINING: - if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) - { - swap(client, "Fill", option, target); - } - else - { - swap(client, "Empty", option, target); - } - break; - default: - break; - } - } - } - if (config.getGamesNecklace()) { if (target.toLowerCase().contains("games necklace")) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java deleted file mode 100644 index 57f37b7ae5..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2019, Alan Baumgartner - * 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.easyscape.util; - -public enum EssenceMode -{ - RUNECRAFTING("Runecrafting"), - ESSENCE_MINING("Essence Mining"); - - private final String name; - - EssenceMode(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } -} \ No newline at end of file From e61731af139322fbfdf05a55ac795d3e07a627a1 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Mon, 20 May 2019 01:20:28 +0200 Subject: [PATCH 52/78] Add priority menu entries to menumanager and update some plugins to use it (#284) * Add priority menu entries to menumanager and update some plugins to use it * Don't check target for walk-here * Make mark-tile lower priority than walk here when shift is pressed * comment out shiftwalker unused code * More menu entry stuff * Check The Feud completion state to see if someone is able to blackjack * Revert changes to BATools (doesn't work) * Merge (and improve) Easyscape --- .../main/java/net/runelite/api/Varbits.java | 9 +- .../runelite/client/menus/MenuManager.java | 83 ++++- .../plugins/blackjack/BlackjackPlugin.java | 123 ++++---- .../plugins/easyscape/EasyscapeConfig.java | 25 -- .../plugins/easyscape/EasyscapePlugin.java | 290 +++++++----------- .../plugins/easyscape/util/EssenceMode.java | 44 --- .../groundmarkers/GroundMarkerPlugin.java | 9 +- .../MenuEntrySwapperPlugin.java | 27 -- .../shiftwalker/ShiftWalkerConfig.java | 4 +- .../shiftwalker/ShiftWalkerGroups.java | 64 ++-- .../shiftwalker/ShiftWalkerInputListener.java | 4 +- .../shiftwalker/ShiftWalkerPlugin.java | 130 +------- 12 files changed, 316 insertions(+), 496 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index dccdc89331..832b91b317 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -559,7 +559,7 @@ public enum Varbits QUEST_THE_EYES_OF_GLOUPHRIE(2497), QUEST_FAIRYTALE_I_GROWING_PAINS(1803), QUEST_FAIRYTALE_II_CURE_A_QUEEN(2326), - QUEST_THE_FEUD(334), + QUEST_THE_FEUD(334), // 14 = able to pickpocket QUEST_FORGETTABLE_TALE(822), QUEST_GARDEN_OF_TRANQUILLITY(961), QUEST_GHOSTS_AHOY(217), @@ -628,7 +628,12 @@ public enum Varbits /** * Spellbook filtering (1 = unfiltered, 0 = filtered) */ - FILTER_SPELLBOOK(6718); + FILTER_SPELLBOOK(6718), + + /** + * POH Building mode (1 = yes, 0 = no) + */ + BUILDING_MODE(2176); /** * The raw varbit ID. diff --git a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java index 955c3ef0e5..476cfcd148 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java @@ -31,8 +31,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; @@ -60,6 +62,7 @@ public class MenuManager */ private static final int IDX_LOWER = 4; private static final int IDX_UPPER = 8; + private static final Pattern LEVEL_PATTERN = Pattern.compile("\\(level-[0-9]*\\)"); private final Client client; private final EventBus eventBus; @@ -69,6 +72,7 @@ public class MenuManager //Used to manage custom non-player menu options private final Multimap managedMenuOptions = HashMultimap.create(); private final Set npcMenuOptions = new HashSet<>(); + private final Map> priorityEntries = new HashMap<>(); @Inject private MenuManager(Client client, EventBus eventBus) @@ -119,12 +123,12 @@ public class MenuManager { int widgetId = event.getActionParam1(); Collection options = managedMenuOptions.get(widgetId); + MenuEntry[] menuEntries = client.getMenuEntries(); for (WidgetMenuOption currentMenu : options) { if (!menuContainsCustomMenu(currentMenu))//Don't add if we have already added it to this widget { - MenuEntry[] menuEntries = client.getMenuEntries(); menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); @@ -136,6 +140,49 @@ public class MenuManager client.setMenuEntries(menuEntries); } } + + List menuEntryList = Arrays.asList(menuEntries); + boolean shouldPurge = menuEntryList.stream().anyMatch(m -> + { + String opt = Text.standardize(m.getOption()); + String tgt = Text.standardize(m.getTarget()); + tgt = LEVEL_PATTERN.matcher(tgt).replaceAll("").trim(); + + if (!priorityEntries.containsKey(opt)) + { + return false; + } + + return priorityEntries.get(opt).contains(tgt); + }); + + if (shouldPurge) + { + client.setMenuEntries(menuEntryList.stream().filter(m -> + { + String opt = Text.standardize(m.getOption()); + String tgt = Text.standardize(m.getTarget()); + tgt = LEVEL_PATTERN.matcher(tgt).replaceAll("").trim(); + + if (opt.equals("cancel")) + { + return true; + } + + if (!priorityEntries.containsKey(opt)) + { + return false; + } + + // Gets overridden by actor names + if (opt.equals("walk here")) + { + return true; + } + + return priorityEntries.get(opt).contains(tgt); + }).toArray(MenuEntry[]::new)); + } } public void addPlayerMenuItem(String menuText) @@ -307,4 +354,38 @@ public class MenuManager return index; } + + /** + * Adds to the map of menu entries which when present, will remove all entries except for this one + */ + public void addPriorityEntry(String option, String target) + { + option = Text.standardize(option); + target = Text.standardize(target); + + Set targets = priorityEntries.getOrDefault(option, new HashSet<>()); + + targets.add(target); + + priorityEntries.put(option, targets); + } + + public void removePriorityEntry(String option, String target) + { + option = Text.standardize(option); + target = Text.standardize(target); + + Set targets = priorityEntries.getOrDefault(option, new HashSet<>()); + + targets.remove(target); + + if (targets.isEmpty()) + { + priorityEntries.remove(option); + } + else + { + priorityEntries.put(option, targets); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java index 0bbac48f60..47379703f7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java @@ -27,20 +27,20 @@ package net.runelite.client.plugins.blackjack; import com.google.inject.Binder; import javax.inject.Inject; import javax.inject.Singleton; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; -import net.runelite.api.MenuEntry; -import net.runelite.api.Quest; -import net.runelite.api.QuestState; +import static net.runelite.api.Varbits.QUEST_THE_FEUD; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameTick; import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.VarbitChanged; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.menus.MenuManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; +import static net.runelite.client.util.MenuUtil.swap; /** * Authors gazivodag longstreet @@ -55,15 +55,21 @@ import net.runelite.client.plugins.PluginType; @Slf4j public class BlackjackPlugin extends Plugin { + private static final String PICKPOCKET = "Pickpocket"; + private static final String KNOCK_OUT = "Knock-out"; + private static final String LURE = "Lure"; + private static final String BANDIT = "Bandit"; + private static final String MENAPHITE = "Menaphite Thug"; @Inject - Client client; + private Client client; - private long timeSinceKnockout; - private long timeSinceAggro; + @Inject + private MenuManager menuManager; - @Getter - private long currentGameTick; + private int lastKnockout; + private boolean pickpocketing; + private boolean ableToBlackJack; @Override public void configure(Binder binder) @@ -73,80 +79,87 @@ public class BlackjackPlugin extends Plugin @Override protected void startUp() throws Exception { - currentGameTick = 0; + menuManager.addPriorityEntry(LURE, BANDIT); + menuManager.addPriorityEntry(LURE, MENAPHITE); + + menuManager.addPriorityEntry(KNOCK_OUT, BANDIT); + menuManager.addPriorityEntry(KNOCK_OUT, MENAPHITE); } @Override protected void shutDown() throws Exception { - currentGameTick = 0; + menuManager.removePriorityEntry(LURE, BANDIT); + menuManager.removePriorityEntry(LURE, MENAPHITE); + + menuManager.removePriorityEntry(PICKPOCKET, BANDIT); + menuManager.removePriorityEntry(PICKPOCKET, MENAPHITE); + + menuManager.removePriorityEntry(KNOCK_OUT, BANDIT); + menuManager.removePriorityEntry(KNOCK_OUT, MENAPHITE); } @Subscribe public void onGameTick(GameTick gameTick) { - currentGameTick++; + if (ableToBlackJack && pickpocketing && client.getTickCount() >= lastKnockout + 4) + { + pickpocketing = false; + + menuManager.removePriorityEntry(PICKPOCKET, BANDIT); + menuManager.removePriorityEntry(PICKPOCKET, MENAPHITE); + + menuManager.addPriorityEntry(KNOCK_OUT, BANDIT); + menuManager.addPriorityEntry(KNOCK_OUT, MENAPHITE); + } } + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + // Lure has higher priority than knock-out + if (event.getTarget().contains(MENAPHITE) || event.getTarget().contains(BANDIT) + && event.getOption().equals(LURE)) + { + swap(client, KNOCK_OUT, LURE, event.getTarget(), false); + } + } @Subscribe public void onChatMessage(ChatMessage chatMessage) { if (chatMessage.getType() == ChatMessageType.SPAM) { - if (chatMessage.getMessage().equals("You smack the bandit over the head and render them unconscious.")) + if (chatMessage.getMessage().equals("You smack the bandit over the head and render them unconscious.") + || chatMessage.getMessage().equals("Your blow only glances off the bandit's head.")) { - timeSinceKnockout = getCurrentGameTick(); - } - if (chatMessage.getMessage().equals("Your blow only glances off the bandit's head.")) - { - timeSinceAggro = getCurrentGameTick(); + menuManager.removePriorityEntry(KNOCK_OUT, BANDIT); + menuManager.removePriorityEntry(KNOCK_OUT, MENAPHITE); + + menuManager.addPriorityEntry(PICKPOCKET, BANDIT); + menuManager.addPriorityEntry(PICKPOCKET, MENAPHITE); + + lastKnockout = client.getTickCount(); + pickpocketing = true; } } } @Subscribe - public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) + public void onVarbitChanged(VarbitChanged event) { - String target = menuEntryAdded.getTarget().toLowerCase(); - if ((target.contains("bandit") || target.contains("menaphite thug"))) - { - Quest quest = Quest.THE_FEUD; - if (quest.getState(client) == QuestState.FINISHED) - { - if (currentGameTick < (timeSinceKnockout + 4)) - { - stripSpecificEntries("pickpocket"); - } - if (currentGameTick < (timeSinceAggro + 4)) - { - stripSpecificEntries("pickpocket"); - } - stripSpecificEntries("knock-out"); - } - } - } + ableToBlackJack = client.getVar(QUEST_THE_FEUD) >= 13; - private void stripSpecificEntries(String exceptFor) - { - MenuEntry[] currentEntires = client.getMenuEntries(); - MenuEntry[] newEntries = new MenuEntry[2]; - - for (MenuEntry currentEntry : currentEntires) + if (!ableToBlackJack) { - if (currentEntry.getOption().toLowerCase().equals(exceptFor.toLowerCase())) - { - newEntries[1] = currentEntry; - } - if (currentEntry.getOption().toLowerCase().equals("lure")) - { - newEntries[0] = currentEntry; - } - } + menuManager.removePriorityEntry(LURE, BANDIT); + menuManager.removePriorityEntry(LURE, MENAPHITE); - if (newEntries[0] != null && newEntries[1] != null) - { - client.setMenuEntries(newEntries); + menuManager.removePriorityEntry(KNOCK_OUT, BANDIT); + menuManager.removePriorityEntry(KNOCK_OUT, MENAPHITE); + + menuManager.removePriorityEntry(PICKPOCKET, BANDIT); + menuManager.removePriorityEntry(PICKPOCKET, MENAPHITE); } } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java index cba9a8baaf..c8db2bdcd2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java @@ -29,7 +29,6 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.plugins.easyscape.util.DuelingRingMode; -import net.runelite.client.plugins.easyscape.util.EssenceMode; import net.runelite.client.plugins.easyscape.util.GamesNecklaceMode; import net.runelite.client.plugins.easyscape.util.GloryMode; @@ -488,30 +487,6 @@ public interface EasyscapeConfig extends Config return false; } - @ConfigItem( - keyName = "swapEssencePounch", - name = "Swap Essence Pouch", - description = "", - position = 38, - group = "Miscellaneous swapper" - ) - default boolean getSwapEssencePouch() - { - return false; - } - - @ConfigItem( - keyName = "essenceMode", - name = "Mode", - description = "", - position = 39, - group = "Miscellaneous swapper" - ) - default EssenceMode getEssenceMode() - { - return EssenceMode.RUNECRAFTING; - } - @ConfigItem( keyName = "swapGamesNecklace", name = "Swap Games Necklace", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 41476f163f..ba73772839 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -25,23 +25,19 @@ */ package net.runelite.client.plugins.easyscape; +import com.google.common.base.Strings; import com.google.inject.Provides; import javax.inject.Inject; import net.runelite.api.Client; -import net.runelite.api.GameObject; import net.runelite.api.GameState; import net.runelite.api.MenuAction; import static net.runelite.api.MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET; import static net.runelite.api.MenuAction.WALK; import net.runelite.api.MenuEntry; -import static net.runelite.api.ObjectID.PORTAL_4525; import net.runelite.api.Player; +import static net.runelite.api.Varbits.BUILDING_MODE; import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.GameObjectDespawned; -import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; @@ -61,7 +57,6 @@ public class EasyscapePlugin extends Plugin private static final int PURO_PURO_REGION_ID = 10307; private MenuEntry[] entries; - private boolean inHouse = false; @Inject private Client client; @@ -75,6 +70,16 @@ public class EasyscapePlugin extends Plugin return configManager.getConfig(EasyscapeConfig.class); } + @Override + public void startUp() + { + } + + @Override + public void shutDown() + { + } + @Subscribe public void onMenuEntryAdded(MenuEntryAdded event) { @@ -83,27 +88,18 @@ public class EasyscapePlugin extends Plugin return; } - Widget loginScreenOne = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN); - Widget loginScreenTwo = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY); - - if (loginScreenOne != null || loginScreenTwo != null) - { - return; - } - - final String option = Text.removeTags(event.getOption()).toLowerCase(); - final String target = Text.removeTags(event.getTarget()).toLowerCase(); + final String option = Text.standardize(event.getOption()); + final String target = Text.standardize(event.getTarget()); entries = client.getMenuEntries(); - Widget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR); - + if (option.contains("withdraw") || option.contains("deposit")) + { if (config.getWithdrawOne()) { - for (String item : config.getWithdrawOneItems().split(",")) + for (String item : Text.fromCSV(config.getWithdrawOneItems())) { - item = item.trim(); - if (target.equalsIgnoreCase(item)) + if (target.equals(Text.standardize(item))) { swap(client, "Withdraw-1", option, target); swap(client, "Deposit-1", option, target); @@ -113,10 +109,9 @@ public class EasyscapePlugin extends Plugin if (config.getWithdrawFive()) { - for (String item : config.getWithdrawFiveItems().split(",")) + for (String item : Text.fromCSV(config.getWithdrawFiveItems())) { - item = item.trim(); - if (target.equalsIgnoreCase(item)) + if (target.equals(Text.standardize(item))) { swap(client, "Withdraw-5", option, target); swap(client, "Deposit-5", option, target); @@ -126,10 +121,9 @@ public class EasyscapePlugin extends Plugin if (config.getWithdrawTen()) { - for (String item : config.getWithdrawTenItems().split(",")) + for (String item : Text.fromCSV(config.getWithdrawTenItems())) { - item = item.trim(); - if (target.equalsIgnoreCase(item)) + if (target.equals(Text.standardize(item))) { swap(client, "Withdraw-10", option, target); swap(client, "Deposit-10", option, target); @@ -139,10 +133,9 @@ public class EasyscapePlugin extends Plugin if (config.getWithdrawX()) { - for (String item : config.getWithdrawXItems().split(",")) + for (String item : Text.fromCSV(config.getWithdrawXItems())) { - item = item.trim(); - if (target.equalsIgnoreCase(item)) + if (target.equals(Text.standardize(item))) { swap(client, "Withdraw-" + config.getWithdrawXAmount(), option, target); swap(client, "Deposit-" + config.getWithdrawXAmount(), option, target); @@ -152,111 +145,116 @@ public class EasyscapePlugin extends Plugin if (config.getWithdrawAll()) { - for (String item : config.getWithdrawAllItems().split(",")) + for (String item : Text.fromCSV(config.getWithdrawAllItems())) { - item = item.trim(); - if (target.equalsIgnoreCase(item)) + if (target.equals(Text.standardize(item))) { swap(client, "Withdraw-All", option, target); swap(client, "Deposit-All", option, target); } } } + } - if (config.getSwapBuyOne() && !config.getBuyOneItems().equals("")) + if (option.contains("buy")) { - for (String item : config.getBuyOneItems().split(",")) + if (config.getSwapBuyOne() && !config.getBuyOneItems().equals("")) { - if (target.equalsIgnoreCase(item.trim())) + for (String item : Text.fromCSV(config.getBuyOneItems())) { - swap(client, "Buy 1", option, target); + if (target.equals(Text.standardize(item))) + { + swap(client, "Buy 1", option, target); + } + } + } + + if (config.getSwapBuyFive() && !config.getBuyFiveItems().equals("")) + { + for (String item : Text.fromCSV(config.getBuyFiveItems())) + { + if (target.equals(Text.standardize(item))) + { + swap(client, "Buy 5", option, target); + } + } + } + + if (config.getSwapBuyTen() && !config.getBuyTenItems().equals("")) + { + for (String item : Text.fromCSV(config.getBuyTenItems())) + { + if (target.equals(Text.standardize(item))) + { + swap(client, "Buy 10", option, target); + } + } + } + + if (config.getSwapBuyFifty() && !config.getBuyFiftyItems().equals("")) + { + for (String item : Text.fromCSV(config.getBuyFiftyItems())) + { + if (target.equals(Text.standardize(item))) + { + swap(client, "Buy 50", option, target); + } } } } - - if (config.getSwapBuyFive() && !config.getBuyFiveItems().equals("")) + else if (option.contains("sell")) { - for (String item : config.getBuyFiveItems().split(",")) + if (config.getSwapSellOne() && !config.getSellOneItems().equals("")) { - if (target.equalsIgnoreCase(item.trim())) + for (String item : Text.fromCSV(config.getSellOneItems())) { - swap(client, "Buy 5", option, target); + if (target.equals(Text.standardize(item))) + { + swap(client, "Sell 1", option, target); + } } } - } - if (config.getSwapBuyTen() && !config.getBuyTenItems().equals("")) - { - for (String item : config.getBuyTenItems().split(",")) + if (config.getSwapSellFive() && !Strings.isNullOrEmpty(config.getSellFiveItems())) { - if (target.equalsIgnoreCase(item.trim())) + for (String item : Text.fromCSV(config.getSellFiveItems())) { - swap(client, "Buy 10", option, target); + if (target.equals(Text.standardize(item))) + { + swap(client, "Sell 5", option, target); + } } } - } - if (config.getSwapBuyFifty() && !config.getBuyFiftyItems().equals("")) - { - for (String item : config.getBuyFiftyItems().split(",")) + if (config.getSwapSellTen() && !Strings.isNullOrEmpty(config.getSellTenItems())) { - if (target.equalsIgnoreCase(item.trim())) + for (String item : Text.fromCSV(config.getSellTenItems())) { - swap(client, "Buy 50", option, target); + if (target.equals(Text.standardize(item))) + { + swap(client, "Sell 10", option, target); + } } } - } - if (config.getSwapSellOne() && !config.getSellOneItems().equals("")) - { - for (String item : config.getSellOneItems().split(",")) + if (config.getSwapSellFifty() && !Strings.isNullOrEmpty(config.getSellFiftyItems())) { - if (target.equalsIgnoreCase(item.trim())) + for (String item : Text.fromCSV(config.getSellFiftyItems())) { - swap(client, "Sell 1", option, target); - } - } - } - - if (config.getSwapSellFive() && !config.getSellFiveItems().equals("")) - { - for (String item : config.getSellFiveItems().split(",")) - { - if (target.equalsIgnoreCase(item.trim())) - { - swap(client, "Sell 5", option, target); - } - } - } - - if (config.getSwapSellTen() && !config.getSellTenItems().equals("")) - { - for (String item : config.getSellTenItems().split(",")) - { - if (target.equalsIgnoreCase(item.trim())) - { - swap(client, "Sell 10", option, target); - } - } - } - - if (config.getSwapSellFifty() && !config.getSellFiftyItems().equals("")) - { - for (String item : config.getSellFiftyItems().split(",")) - { - if (target.equalsIgnoreCase(item.trim())) - { - swap(client, "Sell 50", option, target); + if (target.equals(Text.standardize(item))) + { + swap(client, "Sell 50", option, target); + } } } } if (config.getRemoveObjects() && !config.getRemovedObjects().equals("")) { - for (String removed : config.getRemovedObjects().split(",")) + for (String removed : Text.fromCSV(config.getRemovedObjects())) { - removed = removed.trim(); - if (target.contains("(") && target.split(" \\(")[0].equalsIgnoreCase(removed)) + removed = Text.standardize(removed); + if (target.contains("(") && target.split(" \\(")[0].equals(removed)) { delete(event.getIdentifier()); } @@ -294,7 +292,7 @@ public class EasyscapePlugin extends Plugin } } - if (config.getEasyConstruction() && !config.getConstructionItems().equals("") && inHouse) + if (config.getEasyConstruction() && client.getVar(BUILDING_MODE) == 1 && !Strings.isNullOrEmpty(config.getConstructionItems())) { if (event.getType() == WALK.getId()) { @@ -306,9 +304,9 @@ public class EasyscapePlugin extends Plugin for (int i = entries.length - 1; i >= 0; i--) { - for (String item : config.getConstructionItems().split(",")) + for (String item : Text.fromCSV(config.getConstructionItems())) { - if (item.trim().equalsIgnoreCase(Text.removeTags(entries[i].getTarget()))) + if (item.equalsIgnoreCase(Text.removeTags(entries[i].getTarget()))) { if (!entries[i].getOption().equalsIgnoreCase("remove")) { @@ -322,7 +320,7 @@ public class EasyscapePlugin extends Plugin client.setMenuEntries(entries); } - if (config.getSwapSmithing()) + if (config.getSwapSmithing() && option.contains("smith")) { if (option.equalsIgnoreCase("Smith 1")) { @@ -334,86 +332,46 @@ public class EasyscapePlugin extends Plugin } } - if (config.getSwapTanning() && option.equalsIgnoreCase("Tan 1")) + else if (config.getSwapTanning() && option.equalsIgnoreCase("Tan 1")) { swap(client, "Tan All", option, target); } - if (config.getSwapSawmill() && target.equalsIgnoreCase("Sawmill operator")) + else if (config.getSwapSawmill() && target.equalsIgnoreCase("Sawmill operator")) { swap(client, "Buy-plank", option, target); } - if (config.getSwapSawmillPlanks() && option.equalsIgnoreCase("Buy 1")) + else if (config.getSwapSawmillPlanks() && option.equalsIgnoreCase("Buy 1")) { swap(client, "Buy All", option, target); } - if (option.equalsIgnoreCase("Clear-All") && target.equalsIgnoreCase("bank Filler")) + else if (option.equalsIgnoreCase("Clear-All") && target.equalsIgnoreCase("Bank Filler")) { swap(client, "Clear", option, target); } - if (target.toLowerCase().contains("ardougne cloak") && config.getSwapArdougneCape()) + else if (target.contains("ardougne cloak") && config.getSwapArdougneCape()) { swap(client, "Kandarin Monastery", option, target); swap(client, "Monastery Teleport", option, target); } - if (config.getSwapEssencePouch()) + else if (config.getGamesNecklace() && target.toLowerCase().contains("games necklace")) { - if (isEssencePouch(target)) - { - switch (config.getEssenceMode()) - { - case RUNECRAFTING: - if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) - { - swap(client, "Empty", option, target); - } - else - { - swap(client, "Fill", option, target); - } - break; - case ESSENCE_MINING: - if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) - { - swap(client, "Fill", option, target); - } - else - { - swap(client, "Empty", option, target); - } - break; - default: - break; - } - } + swap(client, config.getGamesNecklaceMode().toString(), option, target); } - if (config.getGamesNecklace()) + else if (config.getDuelingRing() && target.contains("ring of dueling")) { - if (target.toLowerCase().contains("games necklace")) - { - swap(client, config.getGamesNecklaceMode().toString(), option, target); - } + swap(client, config.getDuelingRingMode().toString(), option, target); } - if (config.getDuelingRing()) - { - if (target.toLowerCase().contains("ring of dueling")) - { - swap(client, config.getDuelingRingMode().toString(), option, target); - } - } - if (config.getGlory()) + else if (config.getGlory() && (target.contains("amulet of glory") || target.contains("amulet of eternal glory"))) { - if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) - { - swap(client, config.getGloryMode().toString(), option, target); - } + swap(client, config.getGloryMode().toString(), option, target); } } @@ -430,34 +388,6 @@ public class EasyscapePlugin extends Plugin client.setMenuEntries(entries); } - private boolean isEssencePouch(String target) - { - return (target.equalsIgnoreCase("Small Pouch") || - target.equalsIgnoreCase("Medium Pouch") || - target.equalsIgnoreCase("Large Pouch") || - target.equalsIgnoreCase("Giant Pouch")); - } - - @Subscribe - public void onGameObjectSpawned(GameObjectSpawned event) - { - final GameObject gameObject = event.getGameObject(); - if (PORTAL_4525 == gameObject.getId()) - { - this.inHouse = true; - } - } - - @Subscribe - public void onGameObjectDespawned(GameObjectDespawned event) - { - final GameObject gameObject = event.getGameObject(); - if (PORTAL_4525 == gameObject.getId()) - { - this.inHouse = false; - } - } - private boolean isPuroPuro() { Player player = client.getLocalPlayer(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java deleted file mode 100644 index 57f37b7ae5..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/EssenceMode.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2019, Alan Baumgartner - * 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.easyscape.util; - -public enum EssenceMode -{ - RUNECRAFTING("Runecrafting"), - ESSENCE_MINING("Essence Mining"); - - private final String name; - - EssenceMode(String name) - { - this.name = name; - } - - @Override - public String toString() - { - return name; - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index 02ccf85756..180fdc6bfc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -210,16 +210,17 @@ public class GroundMarkerPlugin extends Plugin { if (hotKeyPressed && event.getOption().equals(WALK_HERE)) { - MenuEntry[] menuEntries = client.getMenuEntries(); - menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); + // Can't insert into abstract list you get from Arrays.asList() + List menuEntries = new ArrayList<>(Arrays.asList(client.getMenuEntries())); - MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); + MenuEntry menuEntry = new MenuEntry(); menuEntry.setOption(MARK); menuEntry.setTarget(event.getTarget()); menuEntry.setType(MenuAction.CANCEL.getId()); - client.setMenuEntries(menuEntries); + menuEntries.add(menuEntries.size() - 1, menuEntry); + client.setMenuEntries(menuEntries.toArray(new MenuEntry[0])); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 0308323471..8f553a61ce 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -624,33 +624,6 @@ public class MenuEntrySwapperPlugin extends Plugin } } - private int searchIndex(MenuEntry[] entries, String option, String target, boolean strict) - { - for (int i = entries.length - 1; i >= 0; i--) - { - MenuEntry entry = entries[i]; - String entryOption = Text.removeTags(entry.getOption()).toLowerCase(); - String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase(); - - if (strict) - { - if (entryOption.equals(option) && entryTarget.equals(target)) - { - return i; - } - } - else - { - if (entryOption.contains(option.toLowerCase()) && entryTarget.equals(target)) - { - return i; - } - } - } - - return -1; - } - private void removeShiftClickCustomizationMenus() { menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java index 049dd866b7..bf903ed229 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerConfig.java @@ -26,11 +26,12 @@ package net.runelite.client.plugins.shiftwalker; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; +// import net.runelite.client.config.ConfigItem; @ConfigGroup("shiftwalkhere") public interface ShiftWalkerConfig extends Config { +/* @ConfigItem( keyName = "shiftWalkEverything", @@ -62,5 +63,6 @@ public interface ShiftWalkerConfig extends Config { return true; } +*/ } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerGroups.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerGroups.java index aff9c0efdb..04c918d763 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerGroups.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerGroups.java @@ -1,32 +1,32 @@ -package net.runelite.client.plugins.shiftwalker; - -import java.util.HashSet; - -public final class ShiftWalkerGroups -{ - //Specific Targets to limit the walking to - private static final String BOX_TRAP = "BOX TRAP"; - private static final String BOX_TRAP_SHAKING = "SHAKING BOX"; - - //Specific menu options to replace - private static final String BOX_TRAP_DISMANTLE = "DISMANTLE"; - private static final String BOX_TRAP_CHECK = "CHECK"; - - private static final String ATTACK_OPTIONS_ATTACK = "ATTACK"; - - public static final HashSet BOX_TRAP_TARGETS = new HashSet<>(); - public static final HashSet BOX_TRAP_KEYWORDS = new HashSet<>(); - public static final HashSet ATTACK_OPTIONS_KEYWORDS = new HashSet<>(); - - static - { - BOX_TRAP_TARGETS.add(BOX_TRAP); - BOX_TRAP_TARGETS.add(BOX_TRAP_SHAKING); - - BOX_TRAP_KEYWORDS.add(BOX_TRAP_DISMANTLE); - BOX_TRAP_KEYWORDS.add(BOX_TRAP_CHECK); - - ATTACK_OPTIONS_KEYWORDS.add(ATTACK_OPTIONS_ATTACK); - } - -} +package net.runelite.client.plugins.shiftwalker; + +// import java.util.HashSet; + +public final class ShiftWalkerGroups +{ + /*//Specific Targets to limit the walking to + private static final String BOX_TRAP = "BOX TRAP"; + private static final String BOX_TRAP_SHAKING = "SHAKING BOX"; + + //Specific menu options to replace + private static final String BOX_TRAP_DISMANTLE = "DISMANTLE"; + private static final String BOX_TRAP_CHECK = "CHECK"; + + private static final String ATTACK_OPTIONS_ATTACK = "ATTACK"; + + public static final HashSet BOX_TRAP_TARGETS = new HashSet<>(); + public static final HashSet BOX_TRAP_KEYWORDS = new HashSet<>(); + public static final HashSet ATTACK_OPTIONS_KEYWORDS = new HashSet<>(); + + static + { + BOX_TRAP_TARGETS.add(BOX_TRAP); + BOX_TRAP_TARGETS.add(BOX_TRAP_SHAKING); + + BOX_TRAP_KEYWORDS.add(BOX_TRAP_DISMANTLE); + BOX_TRAP_KEYWORDS.add(BOX_TRAP_CHECK); + + ATTACK_OPTIONS_KEYWORDS.add(ATTACK_OPTIONS_ATTACK); + }*/ + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java index 9c1cb5b521..a066da5d6e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerInputListener.java @@ -45,7 +45,7 @@ public class ShiftWalkerInputListener implements KeyListener { if (event.getKeyCode() == KeyEvent.VK_SHIFT) { - plugin.setHotKeyPressed(true); + plugin.startPrioritizing(); } } @@ -54,7 +54,7 @@ public class ShiftWalkerInputListener implements KeyListener { if (event.getKeyCode() == KeyEvent.VK_SHIFT) { - plugin.setHotKeyPressed(false); + plugin.stopPrioritizing(); } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java index ca460e98a2..9602c34d2b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java @@ -26,19 +26,14 @@ package net.runelite.client.plugins.shiftwalker; import com.google.inject.Provides; import javax.inject.Inject; -import lombok.Setter; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.MenuEntry; import net.runelite.api.events.FocusChanged; -import net.runelite.api.events.MenuEntryAdded; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyManager; +import net.runelite.client.menus.MenuManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; -import net.runelite.client.util.Text; /** * Shift Walker Plugin. Credit to MenuEntrySwapperPlugin for code some code structure used here. @@ -54,10 +49,6 @@ public class ShiftWalkerPlugin extends Plugin { private static final String WALK_HERE = "WALK HERE"; - private static final String CANCEL = "CANCEL"; - - @Inject - private Client client; @Inject private ShiftWalkerConfig config; @@ -66,14 +57,11 @@ public class ShiftWalkerPlugin extends Plugin private ShiftWalkerInputListener inputListener; @Inject - private ConfigManager configManager; + private MenuManager menuManager; @Inject private KeyManager keyManager; - @Setter - private boolean hotKeyPressed = false; - @Provides ShiftWalkerConfig provideConfig(ConfigManager configManager) { @@ -97,121 +85,17 @@ public class ShiftWalkerPlugin extends Plugin { if (!event.isFocused()) { - hotKeyPressed = false; + stopPrioritizing(); } } - /** - * Event when a new menu entry was added. - * - * @param event {@link MenuEntryAdded}. - */ - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded event) + void startPrioritizing() { - if (client.getGameState() != GameState.LOGGED_IN || !hotKeyPressed) - { - return; - } - - final String pOptionToReplace = Text.removeTags(event.getOption()).toUpperCase(); - - //If the option is already to walk there, or cancel we don't need to swap it with anything - if (pOptionToReplace.equals(CANCEL) || pOptionToReplace.equals(WALK_HERE)) - { - return; - } - - String target = Text.removeTags(event.getTarget().toUpperCase()); - - if (config.shiftWalkEverything()) - { - //swap(pOptionToReplace); //Swap everything with walk here - stripEntries(); - } - else if (config.shiftWalkBoxTraps() && ShiftWalkerGroups.BOX_TRAP_TARGETS.contains(target) - && ShiftWalkerGroups.BOX_TRAP_KEYWORDS.contains(pOptionToReplace)) - { - //swap(pOptionToReplace); //Swap only on box traps - stripEntries(); - } - else if (config.shiftWalkAttackOption() && ShiftWalkerGroups.ATTACK_OPTIONS_KEYWORDS.contains(pOptionToReplace)) - { - //swap(pOptionToReplace); //Swap on everything that has an attack keyword as the first option - stripEntries(); - } + menuManager.addPriorityEntry(WALK_HERE, ""); } - /** - * Strip everything except "Walk here" - * Other way was unconventional because if there was multiple targets in the menu entry it wouldn't swap correctly - */ - private void stripEntries() + void stopPrioritizing() { - MenuEntry walkkHereEntry = null; - - for (MenuEntry entry : client.getMenuEntries()) - { - if ("Walk here".equals(entry.getOption())) - { - walkkHereEntry = entry; - } - } - if (walkkHereEntry != null) - { - MenuEntry[] newEntries = new MenuEntry[1]; - newEntries[0] = walkkHereEntry; - client.setMenuEntries(newEntries); - } + menuManager.removePriorityEntry(WALK_HERE, ""); } - - /** - * Swaps menu entries if the entries could be found. This places Walk Here where the top level menu option was. - * - * @param pOptionToReplace The String containing the Menu Option that needs to be replaced. IE: "Attack", "Chop Down". - */ - private void swap(String pOptionToReplace) // Swap isn't currently used, and I don't know what's going on here so leaving for now - { - MenuEntry[] entries = client.getMenuEntries(); - - Integer walkHereEntry = searchIndex(entries, WALK_HERE); - Integer entryToReplace = searchIndex(entries, pOptionToReplace); - - if (walkHereEntry != null - && entryToReplace != null) - { - MenuEntry walkHereMenuEntry = entries[walkHereEntry]; - entries[walkHereEntry] = entries[entryToReplace]; - entries[entryToReplace] = walkHereMenuEntry; - - client.setMenuEntries(entries); - } - } - - /** - * Finds the index of the menu that contains the verbiage we are looking for. - * - * @param pMenuEntries The list of {@link MenuEntry}s. - * @param pMenuEntryToSearchFor The Option in the menu to search for. - * @return The index location or null if it was not found. - */ - private Integer searchIndex(MenuEntry[] pMenuEntries, String pMenuEntryToSearchFor) - { - Integer indexLocation = 0; - - for (MenuEntry menuEntry : pMenuEntries) - { - String entryOption = Text.removeTags(menuEntry.getOption()).toUpperCase(); - - if (entryOption.equals(pMenuEntryToSearchFor)) - { - return indexLocation; - } - - indexLocation++; - } - - return null; - } - } From 6e49cf410e9d9fd787ded39c3247a4141edfbfbe Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Mon, 20 May 2019 00:40:18 +0100 Subject: [PATCH 53/78] Update EasyscapePlugin.java --- .../plugins/easyscape/EasyscapePlugin.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 57166634a5..a9efab6d1b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -360,27 +360,27 @@ public class EasyscapePlugin extends Plugin swap(client, "Monastery Teleport", option, target); } - if (target.toLowerCase().contains("crafting cape") && config.getSwapCraftingCape()) + if (target.contains("crafting cape") && config.getSwapCraftingCape()) { swap(client, "Teleport", option, target); } - if (target.toLowerCase().contains("construct. cape") && config.getSwapConstructionCape()) + if (target.contains("construct. cape") && config.getSwapConstructionCape()) { swap(client, "Tele to poh", option, target); } - if (target.toLowerCase().contains("magic cape") && config.getSwapMagicCape()) + if (target.contains("magic cape") && config.getSwapMagicCape()) { swap(client, "Spellbook", option, target); } - if (target.toLowerCase().contains("explorer's ring") && config.getSwapExplorersRing()) + if (target.contains("explorer's ring") && config.getSwapExplorersRing()) { swap(client, "Teleport", option, target); } - if (config.getGamesNecklace() && target.toLowerCase().contains("games necklace")) + if (config.getGamesNecklace() && target.contains("games necklace")) { swap(client, config.getGamesNecklaceMode().toString(), option, target); } @@ -390,47 +390,47 @@ public class EasyscapePlugin extends Plugin swap(client, config.getDuelingRingMode().toString(), option, target); } - if (config.getGlory() && (target.contains("amulet of glory") || target.contains("amulet of eternal glory"))) + if (config.getGlory() && target.contains("amulet of glory") || target.contains("amulet of eternal glory"))) { swap(client, config.getGloryMode().toString(), option, target); } - if (config.getSkillsNecklace() && (target.contains("skills necklace")) + if (config.getSkillsNecklace() && target.contains("skills necklace")) { swap(client, config.getSkillsNecklaceMode().toString(), option, target); } - if (config.getNecklaceofPassage() && (target.contains("necklace of passage")) + if (config.getNecklaceofPassage() && target.contains("necklace of passage")) { swap(client, config.getNecklaceofPassageMode().toString(), option, target); } - if (config.getDigsitePendant() && (target.contains("digsite pendant")) + if (config.getDigsitePendant() && target.contains("digsite pendant")) { swap(client, config.getDigsitePendantMode().toString(), option, target); } - if (config.getCombatBracelet() && (target.contains("combat bracelet")) + if (config.getCombatBracelet() && target.contains("combat bracelet")) { swap(client, config.getCombatBraceletMode().toString(), option, target); } - if (config.getSlayerRing() && (target.contains("slayer ring")) + if (config.getSlayerRing() && target.contains("slayer ring")) { swap(client, config.getSlayerRingMode().toString(), option, target); } - if (config.getBurningAmulet() && (target.contains("burning amulet")) + if (config.getBurningAmulet() && target.contains("burning amulet")) { swap(client, config.getBurningAmuletMode().toString(), option, target); } - if (config.getXericsTalisman() && (target.contains("xeric's talisman")) + if (config.getXericsTalisman() && target.contains("xeric's talisman")) { swap(client, config.getXericsTalismanMode().toString(), option, target); } - if (config.getRingofWealth() && (target.contains("ring of wealth")) + if (config.getRingofWealth() && target.contains("ring of wealth")) { swap(client, config.getRingofWealthMode().toString(), option, target); } @@ -463,4 +463,4 @@ public class EasyscapePlugin extends Plugin return location.getRegionID() == PURO_PURO_REGION_ID; } } -} \ No newline at end of file +} From 66394cc708ce93abd6167a5988575eecb8f9d742 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Mon, 20 May 2019 00:45:43 +0100 Subject: [PATCH 54/78] Update EasyscapePlugin.java --- .../net/runelite/client/plugins/easyscape/EasyscapePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index a9efab6d1b..257230a6f6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -390,7 +390,7 @@ public class EasyscapePlugin extends Plugin swap(client, config.getDuelingRingMode().toString(), option, target); } - if (config.getGlory() && target.contains("amulet of glory") || target.contains("amulet of eternal glory"))) + if (config.getGlory() && target.contains("amulet of glory") || target.contains("amulet of eternal glory")) { swap(client, config.getGloryMode().toString(), option, target); } From b8b2f7f4c1209b14681803e5d79f76693433a8aa Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Mon, 20 May 2019 00:58:55 +0100 Subject: [PATCH 55/78] Checkstyle fix --- .../client/plugins/easyscape/EasyscapePlugin.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 257230a6f6..4c3b08ccc4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -378,8 +378,8 @@ public class EasyscapePlugin extends Plugin if (target.contains("explorer's ring") && config.getSwapExplorersRing()) { swap(client, "Teleport", option, target); - } - + } + if (config.getGamesNecklace() && target.contains("games necklace")) { swap(client, config.getGamesNecklaceMode().toString(), option, target); @@ -394,7 +394,7 @@ public class EasyscapePlugin extends Plugin { swap(client, config.getGloryMode().toString(), option, target); } - + if (config.getSkillsNecklace() && target.contains("skills necklace")) { swap(client, config.getSkillsNecklaceMode().toString(), option, target); @@ -404,12 +404,12 @@ public class EasyscapePlugin extends Plugin { swap(client, config.getNecklaceofPassageMode().toString(), option, target); } - + if (config.getDigsitePendant() && target.contains("digsite pendant")) { swap(client, config.getDigsitePendantMode().toString(), option, target); } - + if (config.getCombatBracelet() && target.contains("combat bracelet")) { swap(client, config.getCombatBraceletMode().toString(), option, target); From 1c92e67421dcb165359d029863f69b98037d21c5 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Mon, 20 May 2019 01:46:29 +0100 Subject: [PATCH 56/78] Update EasyscapeConfig.java --- .../runelite/client/plugins/easyscape/EasyscapeConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java index 964d07f3f3..5bf434e88a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapeConfig.java @@ -675,7 +675,7 @@ public interface EasyscapeConfig extends Config ) default SlayerRingMode getSlayerRingMode() { - return SlayerRingMode.SLAYER_TOWER; + return SlayerRingMode.CHECK; } @ConfigItem( @@ -811,4 +811,4 @@ public interface EasyscapeConfig extends Config { return true; } -} \ No newline at end of file +} From d97b15a8ae9cb1843ef28c1f99ad89c285236da0 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Mon, 20 May 2019 01:48:48 +0100 Subject: [PATCH 57/78] Update EasyscapePlugin.java Logic --- .../plugins/easyscape/EasyscapePlugin.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 4c3b08ccc4..481353b296 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -360,77 +360,77 @@ public class EasyscapePlugin extends Plugin swap(client, "Monastery Teleport", option, target); } - if (target.contains("crafting cape") && config.getSwapCraftingCape()) + else if (target.contains("crafting cape") && config.getSwapCraftingCape()) { swap(client, "Teleport", option, target); } - if (target.contains("construct. cape") && config.getSwapConstructionCape()) + else if (target.contains("construct. cape") && config.getSwapConstructionCape()) { swap(client, "Tele to poh", option, target); } - if (target.contains("magic cape") && config.getSwapMagicCape()) + else if (target.contains("magic cape") && config.getSwapMagicCape()) { swap(client, "Spellbook", option, target); } - if (target.contains("explorer's ring") && config.getSwapExplorersRing()) + else if (target.contains("explorer's ring") && config.getSwapExplorersRing()) { swap(client, "Teleport", option, target); } - if (config.getGamesNecklace() && target.contains("games necklace")) + else if (config.getGamesNecklace() && target.contains("games necklace")) { swap(client, config.getGamesNecklaceMode().toString(), option, target); } - if (config.getDuelingRing() && target.contains("ring of dueling")) + else if (config.getDuelingRing() && target.contains("ring of dueling")) { swap(client, config.getDuelingRingMode().toString(), option, target); } - if (config.getGlory() && target.contains("amulet of glory") || target.contains("amulet of eternal glory")) + else if (config.getGlory() && (target.contains("amulet of glory") || target.contains("amulet of eternal glory"))) { swap(client, config.getGloryMode().toString(), option, target); } - if (config.getSkillsNecklace() && target.contains("skills necklace")) + else if (config.getSkillsNecklace() && target.contains("skills necklace")) { swap(client, config.getSkillsNecklaceMode().toString(), option, target); } - if (config.getNecklaceofPassage() && target.contains("necklace of passage")) + else if (config.getNecklaceofPassage() && target.contains("necklace of passage")) { swap(client, config.getNecklaceofPassageMode().toString(), option, target); } - if (config.getDigsitePendant() && target.contains("digsite pendant")) + else if (config.getDigsitePendant() && target.contains("digsite pendant")) { swap(client, config.getDigsitePendantMode().toString(), option, target); } - if (config.getCombatBracelet() && target.contains("combat bracelet")) + else if (config.getCombatBracelet() && target.contains("combat bracelet")) { swap(client, config.getCombatBraceletMode().toString(), option, target); } - if (config.getSlayerRing() && target.contains("slayer ring")) + else if (config.getSlayerRing() && target.contains("slayer ring")) { swap(client, config.getSlayerRingMode().toString(), option, target); } - if (config.getBurningAmulet() && target.contains("burning amulet")) + else if (config.getBurningAmulet() && target.contains("burning amulet")) { swap(client, config.getBurningAmuletMode().toString(), option, target); } - if (config.getXericsTalisman() && target.contains("xeric's talisman")) + else if (config.getXericsTalisman() && target.contains("xeric's talisman")) { swap(client, config.getXericsTalismanMode().toString(), option, target); } - if (config.getRingofWealth() && target.contains("ring of wealth")) + else if (config.getRingofWealth() && target.contains("ring of wealth")) { swap(client, config.getRingofWealthMode().toString(), option, target); } From 43922285428005372cfc787e788df313da6cdd5e Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Mon, 20 May 2019 01:51:00 +0100 Subject: [PATCH 58/78] Update SlayerRingMode.java --- .../plugins/easyscape/util/SlayerRingMode.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java index b86d4aba30..f9d1864f0e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/util/SlayerRingMode.java @@ -27,11 +27,11 @@ package net.runelite.client.plugins.easyscape.util; public enum SlayerRingMode { - SLAYER_TOWER("Slayer Tower"), - FREMENNIK_SLAYER_DUNGEON("Fremennik Slayer Dungeon"), - TARNS_LAIR("Tarn's Lair"), - STRONGHOLD_SLAYER_CAVE("Stronghold Slayer Cave"), - DARK_BEASTS("Dark Beasts"); + CHECK("Check"), + TELEPORT("Teleport"), + MASTER("Master"), + PARTNER("Partner"), + LOG("Log"); private final String name; @@ -45,4 +45,4 @@ public enum SlayerRingMode { return name; } -} \ No newline at end of file +} From a545cd1ac0062ad45aa68cd638056c57fd8d5ffd Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Mon, 20 May 2019 03:06:05 +0200 Subject: [PATCH 59/78] Change slayer bracelet text position (#313) --- .../net/runelite/client/plugins/slayer/SlayerOverlay.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerOverlay.java index a084858458..386bbfcd79 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerOverlay.java @@ -46,7 +46,9 @@ class SlayerOverlay extends WidgetItemOverlay ItemID.SLAYER_RING_5, ItemID.SLAYER_RING_6, ItemID.SLAYER_RING_7, - ItemID.SLAYER_RING_8 + ItemID.SLAYER_RING_8, + ItemID.BRACELET_OF_SLAUGHTER, + ItemID.EXPEDITIOUS_BRACELET ); private final static Set ALL_SLAYER_ITEMS = ImmutableSet.of( @@ -122,7 +124,7 @@ class SlayerOverlay extends WidgetItemOverlay textComponent.setText(String.valueOf(amount)); - // Draw the counter in the bottom left for equipment, and top left for jewelry + // Draw the counter in the top left for equipment, and bottom left for jewelry textComponent.setPosition(new Point(bounds.x, bounds.y + (SLAYER_JEWELRY.contains(itemId) ? bounds.height : graphics.getFontMetrics().getHeight()))); From 646dac7b71693c6073e7fefb4653db6c56cffbc5 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 19 May 2019 23:43:13 +0200 Subject: [PATCH 60/78] Stop npe every game tick if you have defender timer turned off --- .../runelite/client/plugins/batools/BAToolsPlugin.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java index 5f7980900b..53059d47fa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java @@ -188,21 +188,20 @@ public class BAToolsPlugin extends Plugin implements KeyListener } pastCall = callWidget.getTextColor(); } - if (inGameBit == 1) + if (inGameBit == 1 && config.defTimer()) { if (tickNum > 9) { tickNum = 0; } + if (counter == null) { addCounter(); } counter.setCount(tickNum); - if (config.defTimer()) - { - tickNum++; - } + + tickNum++; } Widget weapon = client.getWidget(593, 1); From 17c2313b05fb2eeb29715bb759a8829f42bfeaab Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 20 May 2019 03:16:31 +0200 Subject: [PATCH 61/78] BATools: Remove antidrag, remove useless colors --- .../client/plugins/batools/BAToolsConfig.java | 20 ------------------- .../plugins/batools/BAToolsOverlay.java | 12 ++--------- .../client/plugins/batools/BAToolsPlugin.java | 18 +++++------------ 3 files changed, 7 insertions(+), 43 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java index 961eda4030..b2d7a8aeba 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java @@ -81,26 +81,6 @@ public interface BAToolsConfig extends Config return false; } - @ConfigItem( - keyName = "antiDrag", - name = "Anti Drag", - description = "asd" - ) - default boolean antiDrag() - { - return false; - } - - @ConfigItem( - keyName = "antiDragDelay", - name = "Anti Drag Delay", - description = "asd" - ) - default int antiDragDelay() - { - return 5; - } - @ConfigItem( keyName = "eggBoi", name = "Collector helper", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java index c3b4b7e5b5..3fcf59ba34 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java @@ -25,6 +25,8 @@ package net.runelite.client.plugins.batools; import java.awt.Color; +import static java.awt.Color.GREEN; +import static java.awt.Color.RED; import java.awt.Dimension; import java.awt.Graphics2D; import java.time.Duration; @@ -40,16 +42,6 @@ import net.runelite.client.ui.overlay.OverlayUtil; public class BAToolsOverlay extends Overlay { - private static final Color RED = new Color(221, 44, 0); - private static final Color GREEN = new Color(0, 200, 83); - private static final Color ORANGE = new Color(255, 109, 0); - private static final Color YELLOW = new Color(255, 214, 0); - private static final Color CYAN = new Color(0, 184, 212); - private static final Color BLUE = new Color(41, 98, 255); - private static final Color DEEP_PURPLE = new Color(98, 0, 234); - private static final Color PURPLE = new Color(170, 0, 255); - private static final Color GRAY = new Color(158, 158, 158); - private final BAToolsConfig config; private BAToolsPlugin plugin; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java index 53059d47fa..1c44373b0b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java @@ -140,7 +140,6 @@ public class BAToolsPlugin extends Plugin implements KeyListener wave_start = Instant.now(); lastInteracted = null; foodPressed.clear(); - client.setInventoryDragDelay(config.antiDragDelay()); keyManager.registerKeyListener(this); } @@ -152,7 +151,6 @@ public class BAToolsPlugin extends Plugin implements KeyListener inGameBit = 0; lastInteracted = null; overlayManager.remove(overlay); - client.setInventoryDragDelay(5); keyManager.unregisterKeyListener(this); shiftDown = false; } @@ -173,11 +171,6 @@ public class BAToolsPlugin extends Plugin implements KeyListener @Subscribe public void onGameTick(GameTick event) { - if (config.antiDrag()) - { - client.setInventoryDragDelay(config.antiDragDelay()); - } - Widget callWidget = getWidget(); if (callWidget != null) @@ -304,7 +297,9 @@ public class BAToolsPlugin extends Plugin implements KeyListener if (inGameBit != inGame) { - if (inGameBit == 1) + inGameBit = inGame; + + if (inGameBit == 0) { pastCall = 0; removeCounter(); @@ -315,8 +310,6 @@ public class BAToolsPlugin extends Plugin implements KeyListener addCounter(); } } - - inGameBit = inGame; } @Subscribe @@ -660,12 +653,11 @@ public class BAToolsPlugin extends Plugin implements KeyListener } } - @Subscribe public void onConfigChanged(ConfigChanged event) { - if (config.antiDrag()) + if (counter != null && !config.defTimer()) { - client.setInventoryDragDelay(config.antiDragDelay()); + removeCounter(); } } From 295e89f7f805e94f5f62706ff9451491c50cba8f Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 20 May 2019 03:55:23 +0200 Subject: [PATCH 62/78] Make BATools work with attack styles plugin --- .../client/plugins/batools/BAToolsPlugin.java | 178 ++++++++++-------- 1 file changed, 97 insertions(+), 81 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java index 1c44373b0b..59c968c53e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.batools; +import com.google.common.collect.ImmutableMap; import com.google.inject.Provides; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; @@ -61,8 +62,23 @@ import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetID; +import static net.runelite.api.widgets.WidgetID.BA_REWARD_GROUP_ID; import net.runelite.api.widgets.WidgetInfo; +import static net.runelite.api.widgets.WidgetInfo.BA_ATK_CALL_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_ATK_LISTEN_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_ATK_ROLE_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_COLL_CALL_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_COLL_LISTEN_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_COLL_ROLE_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_DEF_CALL_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_DEF_ROLE_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_HEAL_CALL_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_HEAL_LISTEN_TEXT; +import static net.runelite.api.widgets.WidgetInfo.BA_REWARD_TEXT; +import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_FOUR; +import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_ONE; +import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_THREE; +import static net.runelite.api.widgets.WidgetInfo.COMBAT_STYLE_TWO; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; @@ -92,6 +108,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener private int currentWave = 1; private static final int BA_WAVE_NUM_INDEX = 2; private final List entries = new ArrayList<>(); + private ImmutableMap originalAttackStyles; private HashMap foodPressed = new HashMap<>(); private CycleCounter counter; private Actor lastInteracted; @@ -158,9 +175,9 @@ public class BAToolsPlugin extends Plugin implements KeyListener @Subscribe public void onWidgetLoaded(WidgetLoaded event) { - if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID) + if (event.getGroupId() == BA_REWARD_GROUP_ID) { - Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT); + Widget rewardWidget = client.getWidget(BA_REWARD_TEXT); if (rewardWidget != null && rewardWidget.getText().contains("
5")) { tickNum = 0; @@ -203,61 +220,70 @@ public class BAToolsPlugin extends Plugin implements KeyListener && weapon != null && inGameBit == 1 && weapon.getText().contains("Crystal halberd") || weapon.getText().contains("Dragon claws") - && client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT) != null) + && client.getWidget(BA_ATK_LISTEN_TEXT) != null) { - String style = client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT).getText(); + if (originalAttackStyles == null) + { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + + builder.put(COMBAT_STYLE_ONE, client.getWidget(COMBAT_STYLE_ONE).isHidden()); + builder.put(COMBAT_STYLE_TWO, client.getWidget(COMBAT_STYLE_TWO).isHidden()); + builder.put(COMBAT_STYLE_THREE, client.getWidget(COMBAT_STYLE_THREE).isHidden()); + builder.put(COMBAT_STYLE_FOUR, client.getWidget(COMBAT_STYLE_FOUR).isHidden()); + + originalAttackStyles = builder.build(); + } + + String style = client.getWidget(BA_ATK_LISTEN_TEXT).getText(); if (style.contains("Defensive")) { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(false); + client.getWidget(COMBAT_STYLE_ONE).setHidden(true); + client.getWidget(COMBAT_STYLE_TWO).setHidden(true); + client.getWidget(COMBAT_STYLE_THREE).setHidden(true); + client.getWidget(COMBAT_STYLE_FOUR).setHidden(false); } else if (style.contains("Aggressive")) { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(true); + client.getWidget(COMBAT_STYLE_ONE).setHidden(true); + client.getWidget(COMBAT_STYLE_TWO).setHidden(false); + client.getWidget(COMBAT_STYLE_THREE).setHidden(true); + client.getWidget(COMBAT_STYLE_FOUR).setHidden(true); } else if (style.contains("Controlled")) { if (weapon.getText().contains("Crystal halberd")) { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(true); + client.getWidget(COMBAT_STYLE_ONE).setHidden(false); + client.getWidget(COMBAT_STYLE_THREE).setHidden(true); } else { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(false); + client.getWidget(COMBAT_STYLE_ONE).setHidden(true); + client.getWidget(COMBAT_STYLE_THREE).setHidden(false); } - client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(true); + client.getWidget(COMBAT_STYLE_TWO).setHidden(true); + client.getWidget(COMBAT_STYLE_FOUR).setHidden(true); } else if (style.contains("Accurate") && weapon.getText().contains("Dragon claws")) { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(true); - client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(true); + client.getWidget(COMBAT_STYLE_ONE).setHidden(false); + client.getWidget(COMBAT_STYLE_TWO).setHidden(true); + client.getWidget(COMBAT_STYLE_THREE).setHidden(true); + client.getWidget(COMBAT_STYLE_FOUR).setHidden(true); } else { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(false); + client.getWidget(COMBAT_STYLE_ONE).setHidden(false); + client.getWidget(COMBAT_STYLE_TWO).setHidden(false); + client.getWidget(COMBAT_STYLE_THREE).setHidden(false); + client.getWidget(COMBAT_STYLE_FOUR).setHidden(false); } } - else + else if (originalAttackStyles != null) { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(false); - client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(false); + originalAttackStyles.forEach((w, b) -> client.getWidget(w).setHidden(b)); } if (config.prayerMetronome() && isAnyPrayerActive()) @@ -271,21 +297,21 @@ public class BAToolsPlugin extends Plugin implements KeyListener private Widget getWidget() { - if (client.getWidget(WidgetInfo.BA_DEF_CALL_TEXT) != null) + if (client.getWidget(BA_DEF_CALL_TEXT) != null) { - return client.getWidget(WidgetInfo.BA_DEF_CALL_TEXT); + return client.getWidget(BA_DEF_CALL_TEXT); } - else if (client.getWidget(WidgetInfo.BA_ATK_CALL_TEXT) != null) + else if (client.getWidget(BA_ATK_CALL_TEXT) != null) { - return client.getWidget(WidgetInfo.BA_ATK_CALL_TEXT); + return client.getWidget(BA_ATK_CALL_TEXT); } - else if (client.getWidget(WidgetInfo.BA_COLL_CALL_TEXT) != null) + else if (client.getWidget(BA_COLL_CALL_TEXT) != null) { - return client.getWidget(WidgetInfo.BA_COLL_CALL_TEXT); + return client.getWidget(BA_COLL_CALL_TEXT); } - else if (client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) != null) + else if (client.getWidget(BA_HEAL_CALL_TEXT) != null) { - return client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT); + return client.getWidget(BA_HEAL_CALL_TEXT); } return null; } @@ -428,26 +454,26 @@ public class BAToolsPlugin extends Plugin implements KeyListener if (config.swapLadder() && option.equals("climb-down") && target.equals("ladder")) { - swap(client, "quick-start", option, target, true); + swap(client, "quick-start", option, target); } else if (config.removeBA() && client.getVar(Varbits.IN_GAME_BA) == 1 && !option.contains("tell-"))//if in barbarian assault and menu isnt from a horn { if (itemId == ItemID.LOGS && !target.contains("healing vial")) { - if (client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null) + if (client.getWidget(BA_DEF_ROLE_TEXT) == null) { - remove(new String[]{"take", "light"}, target, true); + remove(new String[]{"take", "light"}, target); } else //remove "Light" option (and "Take" option if not defender). { - remove("light", target, true); + remove("light", target); } } else if (option.equals("use")) { if (config.removeHealWrongFood()) { - Widget healer = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT); + Widget healer = client.getWidget(BA_HEAL_LISTEN_TEXT); if (healer != null) { String item = target.split("-")[0].trim(); @@ -474,12 +500,12 @@ public class BAToolsPlugin extends Plugin implements KeyListener { if (calledPoison != 0 && itemId != calledPoison)//if no call or chosen item is not the called one { - remove(new String[]{"use", "destroy", "examine"}, target, true);//remove options + remove(new String[]{"use", "destroy", "examine"}, target);//remove options } } else if (!target.contains("penance healer")) { - remove(option, target, true); + remove(option, target); } } else if (vials.contains(item))//if item is the healer's healing vial @@ -490,30 +516,30 @@ public class BAToolsPlugin extends Plugin implements KeyListener if (!target.contains("level") || target.contains("penance") || target.contains("queen spawn"))//if someone has "penance" or "queen spawn" in their name, gg... { - remove(option, target, true); + remove(option, target); } } } } } } - else if (option.equals("attack") && client.getWidget(WidgetInfo.BA_ATK_ROLE_TEXT) == null && !target.equals("queen spawn"))//if not attacker + else if (option.equals("attack") && client.getWidget(BA_ATK_ROLE_TEXT) == null && !target.equals("queen spawn"))//if not attacker { //remove attack option from everything but queen spawns - remove(option, target, true); + remove(option, target); } - else if ((option.equals("fix") || (option.equals("block") && target.equals("penance cave"))) && client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null)//if not defender + else if ((option.equals("fix") || (option.equals("block") && target.equals("penance cave"))) && client.getWidget(BA_DEF_ROLE_TEXT) == null)//if not defender { //the check for option requires checking target as well because defensive attack style option is also called "block". - remove(option, target, true); + remove(option, target); } - else if ((option.equals("load")) && client.getWidget(WidgetInfo.BA_COLL_ROLE_TEXT) == null)//if not collector, remove hopper options + else if ((option.equals("load")) && client.getWidget(BA_COLL_ROLE_TEXT) == null)//if not collector, remove hopper options { - remove(new String[]{option, "look-in"}, target, true); + remove(new String[]{option, "look-in"}, target); } else if (config.removeWrongEggs() && option.equals("take")) { - Widget eggToColl = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT); + Widget eggToColl = client.getWidget(BA_COLL_LISTEN_TEXT); if (eggToColl != null)//if we're a collector { List eggsToHide = new ArrayList<>(); @@ -535,15 +561,15 @@ public class BAToolsPlugin extends Plugin implements KeyListener } if (eggsToHide.contains(itemId)) { - remove(option, target, true);//hide wrong eggs + remove(option, target);//hide wrong eggs } } else { List defenderItems = Arrays.asList(ItemID.HAMMER, ItemID.TOFU, ItemID.CRACKERS, ItemID.WORMS);//logs are handled separately due to hiding "light" option too. - if (client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null || !defenderItems.contains(itemId))//if not defender, or item is not a defenderItem + if (client.getWidget(BA_DEF_ROLE_TEXT) == null || !defenderItems.contains(itemId))//if not defender, or item is not a defenderItem { - remove(option, target, true);//hide everything except hammer/logs and bait if Defender + remove(option, target);//hide everything except hammer/logs and bait if Defender } } } @@ -574,9 +600,9 @@ public class BAToolsPlugin extends Plugin implements KeyListener client.setMenuEntries(menuEntries); } - if (client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT) != null && inGameBit == 1 && config.eggBoi() && event.getTarget().endsWith("egg") && shiftDown) + if (client.getWidget(BA_COLL_LISTEN_TEXT) != null && inGameBit == 1 && config.eggBoi() && event.getTarget().endsWith("egg") && shiftDown) { - String[] currentCall = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT).getText().split(" "); + String[] currentCall = client.getWidget(BA_COLL_LISTEN_TEXT).getText().split(" "); MenuEntry[] menuEntries = client.getMenuEntries(); MenuEntry correctEgg = null; @@ -600,9 +626,9 @@ public class BAToolsPlugin extends Plugin implements KeyListener client.setMenuEntries(entries.toArray(new MenuEntry[0])); } - if (client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT) != null && inGameBit == 1 && config.osHelp() && event.getTarget().equals("Healer item machine") && shiftDown) + if (client.getWidget(BA_HEAL_LISTEN_TEXT) != null && inGameBit == 1 && config.osHelp() && event.getTarget().equals("Healer item machine") && shiftDown) { - String[] currentCall = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT).getText().split(" "); + String[] currentCall = client.getWidget(BA_HEAL_LISTEN_TEXT).getText().split(" "); if (!currentCall[0].contains("Pois.")) { @@ -632,12 +658,12 @@ public class BAToolsPlugin extends Plugin implements KeyListener @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { - if (!config.healerMenuOption() || !event.getMenuTarget().contains("Penance Healer") || client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) == null) + if (!config.healerMenuOption() || !event.getMenuTarget().contains("Penance Healer") || client.getWidget(BA_HEAL_CALL_TEXT) == null) { return; } - String currentCall = client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT).getText(); + String currentCall = client.getWidget(BA_HEAL_CALL_TEXT).getText(); String target = event.getMenuTarget(); if ((currentCall.equals("Pois. Worms") && (target.contains("Poisoned worms") && target.contains("->") && target.contains("Penance Healer"))) @@ -687,10 +713,10 @@ public class BAToolsPlugin extends Plugin implements KeyListener counter = null; } - private void remove(String option, String target, boolean strict) + private void remove(String option, String target) { MenuEntry[] entries = client.getMenuEntries(); - int idx = searchIndex(entries, option, target, strict); + int idx = searchIndex(entries, option, target); if (idx >= 0 && entries[idx] != null) { entries = ArrayUtils.removeElement(entries, entries[idx]); @@ -698,12 +724,12 @@ public class BAToolsPlugin extends Plugin implements KeyListener } } - private void remove(String[] options, String target, boolean strict) + private void remove(String[] options, String target) { MenuEntry[] entries = client.getMenuEntries(); for (String option : options) { - int idx = searchIndex(entries, option, target, strict); + int idx = searchIndex(entries, option, target); if (idx >= 0 && entries[idx] != null) { entries = ArrayUtils.removeElement(entries, entries[idx]); @@ -713,7 +739,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener client.setMenuEntries(entries); } - private int searchIndex(MenuEntry[] entries, String option, String target, boolean strict) + private int searchIndex(MenuEntry[] entries, String option, String target) { for (int i = entries.length - 1; i >= 0; i--) { @@ -721,19 +747,9 @@ public class BAToolsPlugin extends Plugin implements KeyListener String entryOption = Text.removeTags(entry.getOption()).toLowerCase(); String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase(); - if (strict) + if (entryOption.equals(option) && entryTarget.equals(target)) { - if (entryOption.equals(option) && entryTarget.equals(target)) - { - return i; - } - } - else - { - if (entryOption.contains(option.toLowerCase()) && entryTarget.equals(target)) - { - return i; - } + return i; } } From 03192933677c2f64516b057921cb051c0530f3ad Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 20 May 2019 08:10:34 +0200 Subject: [PATCH 63/78] Improve priority menu entries --- .../client/menus/AbstractMenuEntry.java | 100 ++++++++++++++ .../runelite/client/menus/MenuManager.java | 127 ++++++++++-------- 2 files changed, 172 insertions(+), 55 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java diff --git a/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java b/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java new file mode 100644 index 0000000000..14577265d4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java @@ -0,0 +1,100 @@ +package net.runelite.client.menus; + +import joptsimple.internal.Strings; +import lombok.Getter; +import net.runelite.api.MenuEntry; +import static net.runelite.client.menus.MenuManager.LEVEL_PATTERN; +import net.runelite.client.util.Text; + +class AbstractMenuEntry +{ + @Getter + private String option; + + @Getter + private String target; + + @Getter + private int id; + + @Getter + private int type; + + @Getter + private boolean strictOption; + + @Getter + private boolean strictTarget; + + AbstractMenuEntry(String option, String target) + { + this(option, target, -1, -1, true, true); + } + + AbstractMenuEntry(String option, String target, boolean strictTarget) + { + this(option, target, -1, -1, true, strictTarget); + } + + AbstractMenuEntry(String option, String target, int id, int type, boolean strictOption, boolean strictTarget) + { + this.option = option; + this.target = target; + this.id = id; + this.type = type; + this.strictOption = strictOption; + this.strictTarget = strictTarget; + } + + boolean matches(MenuEntry entry) + { + String opt = Text.standardize(entry.getOption()); + + if (strictOption && !opt.equals(option) || !strictOption && !opt.contains(option)) + { + return false; + } + + if (strictTarget || !Strings.isNullOrEmpty(target)) + { + String tgt = Text.standardize(LEVEL_PATTERN.matcher(entry.getTarget()).replaceAll("")); + + if (strictTarget && !tgt.equals(target) || !strictTarget && !tgt.contains(target)) + { + return false; + } + } + + if (id != -1) + { + int id = entry.getIdentifier(); + + if (this.id != id) + { + return false; + } + } + + if (type != -1) + { + int type = entry.getType(); + + if (this.type != type) + { + return false; + } + } + + return true; + } + + boolean equals(AbstractMenuEntry other) + { + return target.equals(other.getTarget()) + && option.equals(other.getOption()) + && id == other.getId() + && type == other.getType() + && strictOption == other.isStrictOption() + && strictTarget == other.isStrictTarget(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java index 476cfcd148..4fba85094b 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java @@ -27,6 +27,7 @@ package net.runelite.client.menus; import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -35,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; @@ -62,7 +64,20 @@ public class MenuManager */ private static final int IDX_LOWER = 4; private static final int IDX_UPPER = 8; - private static final Pattern LEVEL_PATTERN = Pattern.compile("\\(level-[0-9]*\\)"); + static final Pattern LEVEL_PATTERN = Pattern.compile("\\(level-[0-9]*\\)"); + + private static MenuEntry CANCEL() + { + MenuEntry cancel = new MenuEntry(); + cancel.setOption("Cancel"); + cancel.setTarget(""); + cancel.setIdentifier(0); + cancel.setType(MenuAction.CANCEL.getId()); + cancel.setParam0(0); + cancel.setParam1(0); + + return cancel; + } private final Client client; private final EventBus eventBus; @@ -72,7 +87,11 @@ public class MenuManager //Used to manage custom non-player menu options private final Multimap managedMenuOptions = HashMultimap.create(); private final Set npcMenuOptions = new HashSet<>(); - private final Map> priorityEntries = new HashMap<>(); + + private final Set priorityEntries = new HashSet<>(); + private final Set currentPriorityEntries = new HashSet<>(); + + private final Map swaps = new HashMap<>(); @Inject private MenuManager(Client client, EventBus eventBus) @@ -125,6 +144,12 @@ public class MenuManager Collection options = managedMenuOptions.get(widgetId); MenuEntry[] menuEntries = client.getMenuEntries(); + if (menuEntries.length == 1) + { + // Menu entries reset, so priority entries should reset as well + currentPriorityEntries.clear(); + } + for (WidgetMenuOption currentMenu : options) { if (!menuContainsCustomMenu(currentMenu))//Don't add if we have already added it to this widget @@ -141,48 +166,49 @@ public class MenuManager } } - List menuEntryList = Arrays.asList(menuEntries); - boolean shouldPurge = menuEntryList.stream().anyMatch(m -> - { - String opt = Text.standardize(m.getOption()); - String tgt = Text.standardize(m.getTarget()); - tgt = LEVEL_PATTERN.matcher(tgt).replaceAll("").trim(); + MenuEntry newestEntry = menuEntries[menuEntries.length - 1]; - if (!priorityEntries.containsKey(opt)) - { - return false; - } + boolean isPrio = priorityEntries.stream().anyMatch(p -> p.matches(newestEntry)); - return priorityEntries.get(opt).contains(tgt); - }); - - if (shouldPurge) + // If the last entry was a priority entry, keep track of it + if (isPrio) { - client.setMenuEntries(menuEntryList.stream().filter(m -> - { - String opt = Text.standardize(m.getOption()); - String tgt = Text.standardize(m.getTarget()); - tgt = LEVEL_PATTERN.matcher(tgt).replaceAll("").trim(); - - if (opt.equals("cancel")) - { - return true; - } - - if (!priorityEntries.containsKey(opt)) - { - return false; - } - - // Gets overridden by actor names - if (opt.equals("walk here")) - { - return true; - } - - return priorityEntries.get(opt).contains(tgt); - }).toArray(MenuEntry[]::new)); + currentPriorityEntries.add(newestEntry); } + + // Make a copy of the menu entries, cause you can't remove from Arrays.asList() + List copy = new ArrayList<>(Arrays.asList(menuEntries)); + + // If there are entries we want to prioritize, we have to remove the rest + if (!currentPriorityEntries.isEmpty()) + { + copy.retainAll(currentPriorityEntries); + + copy.add(CANCEL()); + } + + /*// Find the current entry in the swaps map + Optional swapEntry = swaps.keySet().stream().filter(e -> e.matches(newestEntry)).findFirst(); + + if (swapEntry.isPresent()) + { + AbstractMenuEntry swap = swapEntry.get(); + AbstractMenuEntry swapTarget = swaps.get(swap); + + // Find the target for the swap in current menu entries + Optional foundSwap = Lists.reverse(copy).stream().filter(swapTarget::matches).findFirst(); + + if (foundSwap.isPresent()) + { + // Swap + int index = copy.indexOf(foundSwap.get()); + + copy.set(index, newestEntry); + copy.set(copy.size() - 1, foundSwap.get()); + } + }*/ + + client.setMenuEntries(copy.toArray(new MenuEntry[0])); } public void addPlayerMenuItem(String menuText) @@ -356,18 +382,16 @@ public class MenuManager } /** - * Adds to the map of menu entries which when present, will remove all entries except for this one + * Adds to the set of menu entries which when present, will remove all entries except for this one */ public void addPriorityEntry(String option, String target) { option = Text.standardize(option); target = Text.standardize(target); - Set targets = priorityEntries.getOrDefault(option, new HashSet<>()); + AbstractMenuEntry entry = new AbstractMenuEntry(option, target); - targets.add(target); - - priorityEntries.put(option, targets); + priorityEntries.add(entry); } public void removePriorityEntry(String option, String target) @@ -375,17 +399,10 @@ public class MenuManager option = Text.standardize(option); target = Text.standardize(target); - Set targets = priorityEntries.getOrDefault(option, new HashSet<>()); + AbstractMenuEntry entry = new AbstractMenuEntry(option, target); - targets.remove(target); + Set toRemove = priorityEntries.stream().filter(entry::equals).collect(Collectors.toSet()); - if (targets.isEmpty()) - { - priorityEntries.remove(option); - } - else - { - priorityEntries.put(option, targets); - } + priorityEntries.removeAll(toRemove); } } From 041281128a6a45763ccc6bb2833692984ff211d6 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 20 May 2019 17:06:02 +1000 Subject: [PATCH 64/78] removed Getter for modifiers that no longer require it --- .../client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 7804079226..8cb4c4c2d6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -128,11 +128,9 @@ public class MenuEntrySwapperPlugin extends Plugin @Getter private boolean configuringShiftClick = false; - @Getter @Setter private boolean shiftModifier = false; - @Getter @Setter private boolean controlModifier = false; From dcb0626ed1c561aead982cee27e2b77a99e1e3e1 Mon Sep 17 00:00:00 2001 From: James Munson Date: Mon, 20 May 2019 03:03:19 -0700 Subject: [PATCH 65/78] Default Worldhopper --- .../worldhopper/WorldHopperConfig.java | 241 ++-- .../worldhopper/WorldHopperPlugin.java | 49 +- .../worldhopper/WorldSwitcherPanel.java | 1043 +++++++---------- .../plugins/worldhopper/WorldTableRow.java | 685 ++++++----- .../plugins/worldhopper/ping/IPHlpAPI.java | 40 + .../worldhopper/ping/IcmpEchoReply.java | 60 + .../client/plugins/worldhopper/ping/Ping.java | 103 ++ 7 files changed, 1060 insertions(+), 1161 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IPHlpAPI.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IcmpEchoReply.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java index ea770dadda..f7a75781fd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java @@ -1,126 +1,115 @@ -/* - * Copyright (c) 2018, Lotto - * 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.worldhopper; - -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.Keybind; - -@ConfigGroup(WorldHopperConfig.GROUP) -public interface WorldHopperConfig extends Config -{ - String GROUP = "worldhopper"; - - @ConfigItem( - keyName = "previousKey", - name = "Quick-hop previous", - description = "When you press this key you'll hop to the previous world", - position = 0 - ) - default Keybind previousKey() - { - return new Keybind(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); - } - - @ConfigItem( - keyName = "nextKey", - name = "Quick-hop next", - description = "When you press this key you'll hop to the next world", - position = 1 - ) - default Keybind nextKey() - { - return new Keybind(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); - } - - @ConfigItem( - keyName = "quickhopOutOfDanger", - name = "Quick-hop out of dangerous worlds", - description = "Don't hop to a PVP/high risk world when quick-hopping", - position = 2 - ) - default boolean quickhopOutOfDanger() - { - return true; - } - - @ConfigItem( - keyName = "showSidebar", - name = "Show world hopper sidebar", - description = "Show sidebar containing all worlds that mimics in-game interface", - position = 3 - ) - default boolean showSidebar() - { - return true; - } - - @ConfigItem( - keyName = "ping", - name = "Show world ping", - description = "Shows ping to each game world", - position = 4 - ) - default boolean ping() - { - return true; - } - - @ConfigItem( - keyName = "showMessage", - name = "Show world hop message in chat", - description = "Shows what world is being hopped to in the chat", - position = 5 - ) - default boolean showWorldHopMessage() - { - return true; - } - - @ConfigItem( - keyName = "subscriptionFilter", - name = "Show subscription types", - description = "Only show free worlds, member worlds, or both types of worlds in sidebar", - position = 6 - ) - default SubscriptionFilterMode subscriptionFilter() - { - return SubscriptionFilterMode.BOTH; - } - - @ConfigItem( - keyName = "showHistory", - name = "Show history tab", - description = "Shows the history tab", - position = 7 - ) - default boolean showHistory() - { - return true; - } -} +/* + * Copyright (c) 2018, Lotto + * 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.worldhopper; + +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Keybind; + +@ConfigGroup(WorldHopperConfig.GROUP) +public interface WorldHopperConfig extends Config +{ + String GROUP = "worldhopper"; + + @ConfigItem( + keyName = "previousKey", + name = "Quick-hop previous", + description = "When you press this key you'll hop to the previous world", + position = 0 + ) + default Keybind previousKey() + { + return new Keybind(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + } + + @ConfigItem( + keyName = "nextKey", + name = "Quick-hop next", + description = "When you press this key you'll hop to the next world", + position = 1 + ) + default Keybind nextKey() + { + return new Keybind(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + } + + @ConfigItem( + keyName = "quickhopOutOfDanger", + name = "Quick-hop out of dangerous worlds", + description = "Don't hop to a PVP/high risk world when quick-hopping", + position = 2 + ) + default boolean quickhopOutOfDanger() + { + return true; + } + + @ConfigItem( + keyName = "showSidebar", + name = "Show world hopper sidebar", + description = "Show sidebar containing all worlds that mimics in-game interface", + position = 3 + ) + default boolean showSidebar() + { + return true; + } + + @ConfigItem( + keyName = "ping", + name = "Show world ping", + description = "Shows ping to each game world", + position = 4 + ) + default boolean ping() + { + return true; + } + + @ConfigItem( + keyName = "showMessage", + name = "Show world hop message in chat", + description = "Shows what world is being hopped to in the chat", + position = 5 + ) + default boolean showWorldHopMessage() + { + return true; + } + + @ConfigItem( + keyName = "subscriptionFilter", + name = "Show subscription types", + description = "Only show free worlds, member worlds, or both types of worlds in sidebar", + position = 6 + ) + default SubscriptionFilterMode subscriptionFilter() + { + return SubscriptionFilterMode.BOTH; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index 33852bc40f..84abfcf9f5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -75,13 +75,13 @@ import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.worldhopper.ping.Ping; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.ExecutorServiceExceptionLogger; import net.runelite.client.util.HotkeyListener; import net.runelite.client.util.Text; import net.runelite.client.util.WorldUtil; -import net.runelite.client.util.ping.Ping; import net.runelite.http.api.worlds.World; import net.runelite.http.api.worlds.WorldClient; import net.runelite.http.api.worlds.WorldResult; @@ -258,49 +258,10 @@ public class WorldHopperPlugin extends Plugin panel.setFilterMode(config.subscriptionFilter()); updateList(); break; - case "showHistory": - panel.updateLayout(); - break; } } } - boolean showHistory() - { - return config.showHistory(); - } - - Map getHistory() - { - Map history = configManager.getConfiguration(WorldHopperConfig.GROUP, "history", Map.class); - if (history == null) - { - history = new HashMap(); - } - - return history; - } - - void clearHistory() - { - Map history = getHistory(); - history.clear(); - configManager.setConfiguration(WorldHopperConfig.GROUP, "history", history); - } - - void addToHistory() - { - addToHistory(client.getWorld()); - } - - void addToHistory(int world) - { - long unixTime = System.currentTimeMillis() / 1000L; - Map history = getHistory(); - history.put(String.valueOf(world), String.valueOf(unixTime)); - configManager.setConfiguration(WorldHopperConfig.GROUP, "history", history); - } - private void setFavoriteConfig(int world) { configManager.setConfiguration(WorldHopperConfig.GROUP, "favorite_" + world, true); @@ -457,12 +418,6 @@ public class WorldHopperPlugin extends Plugin lastWorld = newWorld; } } - - if (gameStateChanged.getGameState() == GameState.LOGGED_IN) - { - addToHistory(client.getWorld()); - panel.updateList(); - } } @Subscribe @@ -699,8 +654,6 @@ public class WorldHopperPlugin extends Plugin quickHopTargetWorld = rsWorld; displaySwitcherAttempts = 0; - - addToHistory(worldId); } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java index acfd4b25ea..27eb29b321 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java @@ -1,644 +1,399 @@ -/* - * Copyright (c) 2018, Psikoi - * 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.worldhopper; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.JTabbedPane; -import javax.swing.SwingUtilities; -import javax.swing.border.Border; -import lombok.AccessLevel; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.DynamicGridLayout; -import net.runelite.client.ui.PluginPanel; -import net.runelite.http.api.worlds.World; -import net.runelite.http.api.worlds.WorldType; - -@Slf4j -class WorldSwitcherPanel extends PluginPanel -{ - private static final Color ODD_ROW = new Color(44, 44, 44); - - private static final int WORLD_COLUMN_WIDTH = 60; - private static final int PLAYERS_COLUMN_WIDTH = 40; - private static final int PING_COLUMN_WIDTH = 47; - - private final JPanel headerContainer; - private final JPanel headerHistContainer; - private final JPanel listContainer = new JPanel(); - private final JPanel histContainer = new JPanel(); - - private WorldTableHeader worldHeader; - private WorldTableHeader playersHeader; - private WorldTableHeader activityHeader; - private WorldTableHeader pingHeader; - - private WorldOrder orderIndex = WorldOrder.WORLD; - private boolean ascendingOrder = true; - - private ArrayList rows = new ArrayList<>(); - private ArrayList histRows = new ArrayList<>(); - private WorldHopperPlugin plugin; - @Setter(AccessLevel.PACKAGE) - private SubscriptionFilterMode filterMode; - - WorldSwitcherPanel(WorldHopperPlugin plugin) - { - this.plugin = plugin; - - setBorder(null); - setLayout(new DynamicGridLayout(0, 1)); - - headerContainer = buildHeader(); - headerHistContainer = buildHistoryHeader(); - - listContainer.setLayout(new GridLayout(0, 1)); - histContainer.setLayout(new GridLayout(0, 1)); - - updateLayout(); - } - - void updateLayout() - { - if (this.getComponentCount() > 0) - { - for (Component c : this.getComponents()) - { - this.remove(c); - } - } - - if (plugin.showHistory()) - { - Component tabs = createTabs(); - add(tabs); - } - else - { - add(headerContainer); - add(listContainer); - } - } - - void switchCurrentHighlight(int newWorld, int lastWorld) - { - for (WorldTableRow row : rows) - { - if (row.getWorld().getId() == newWorld) - { - row.recolour(true); - } - else if (row.getWorld().getId() == lastWorld) - { - row.recolour(false); - } - } - - for (WorldTableRow row : histRows) - { - if (row.getWorld().getId() == newWorld) - { - row.recolour(true); - } - else if (row.getWorld().getId() == lastWorld) - { - row.recolour(false); - } - } - } - - void updateListData(Map worldData) - { - for (WorldTableRow worldTableRow : rows) - { - World world = worldTableRow.getWorld(); - Integer playerCount = worldData.get(world.getId()); - if (playerCount != null) - { - worldTableRow.updatePlayerCount(playerCount); - } - } - - for (WorldTableRow worldTableRow : histRows) - { - World world = worldTableRow.getWorld(); - Integer playerCount = worldData.get(world.getId()); - if (playerCount != null) - { - worldTableRow.updatePlayerCount(playerCount); - } - } - - // If the list is being ordered by player count, then it has to be re-painted - // to properly display the new data - if (orderIndex == WorldOrder.PLAYERS) - { - updateList(); - } - } - - void updatePing(int world, int ping) - { - for (WorldTableRow worldTableRow : rows) - { - if (worldTableRow.getWorld().getId() == world) - { - worldTableRow.setPing(ping); - - // If the panel is sorted by ping, re-sort it - if (orderIndex == WorldOrder.PING) - { - updateList(); - } - break; - } - } - - for (WorldTableRow worldTableRow : histRows) - { - if (worldTableRow.getWorld().getId() == world) - { - worldTableRow.setPing(ping); - - // If the panel is sorted by ping, re-sort it - if (orderIndex == WorldOrder.PING) - { - updateList(); - } - break; - } - } - } - - void hidePing() - { - for (WorldTableRow worldTableRow : rows) - { - worldTableRow.hidePing(); - } - - for (WorldTableRow worldTableRow : histRows) - { - worldTableRow.hidePing(); - } - } - - void showPing() - { - for (WorldTableRow worldTableRow : rows) - { - worldTableRow.showPing(); - } - - for (WorldTableRow worldTableRow : histRows) - { - worldTableRow.showPing(); - } - } - - void updateList() - { - rows.sort((r1, r2) -> - { - switch (orderIndex) - { - case PING: - return Integer.compare(r1.getPing(), r2.getPing()) * (ascendingOrder ? 1 : -1); - case WORLD: - return Integer.compare(r1.getWorld().getId(), r2.getWorld().getId()) * (ascendingOrder ? 1 : -1); - case PLAYERS: - return Integer.compare(r1.getUpdatedPlayerCount(), r2.getUpdatedPlayerCount()) * (ascendingOrder ? 1 : -1); - case ACTIVITY: - return r1.getWorld().getActivity().compareTo(r2.getWorld().getActivity()) * -1 * (ascendingOrder ? 1 : -1); - default: - return 0; - } - }); - - // Leave empty activity worlds on the bottom of the list - if (orderIndex == WorldOrder.ACTIVITY) - { - rows.sort((r1, r2) -> r1.getWorld().getActivity().equals("-") ? 1 : -1); - } - - rows.sort((r1, r2) -> - { - boolean b1 = plugin.isFavorite(r1.getWorld()); - boolean b2 = plugin.isFavorite(r2.getWorld()); - return Boolean.compare(b2, b1); - }); - - listContainer.removeAll(); - histContainer.removeAll(); - - Map history = plugin.getHistory(); - Map matchedHist = new HashMap<>(); - for (int i = 0; i < rows.size(); i++) - { - WorldTableRow row = rows.get(i); - row.setBackground(i % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); - listContainer.add(row); - - String worldNum = String.valueOf(row.getWorld().getId()); - if (history.containsKey(worldNum)) - { - // Add toa list that we can sort later - matchedHist.put(worldNum, history.get(worldNum)); - } - } - - // Sort by ascending - matchedHist = matchedHist.entrySet().stream() - .sorted(Map.Entry.comparingByValue().reversed()) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, - (e1, e2) -> e1, LinkedHashMap::new)); - - // Add matched rows to history list - Iterator it = matchedHist.entrySet().iterator(); - int histRowCount = 0; - while (it.hasNext()) - { - Map.Entry pair = (Map.Entry) it.next(); - for (WorldTableRow r : rows) - { - WorldTableRow histRow = r; - histRow.setBackground(histRowCount % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); - if (String.valueOf(r.getWorld().getId()).equals(pair.getKey())) - { - histContainer.add(r); - histRowCount++; - break; - } - } - it.remove(); - } - - listContainer.revalidate(); - listContainer.repaint(); - histContainer.revalidate(); - histContainer.repaint(); - } - - Component createTabs() - { - // Constraints for GB Layout - GridBagConstraints listConst = new GridBagConstraints(); - listConst.gridx = 0; - listConst.gridy = 1; - listConst.fill = GridBagConstraints.HORIZONTAL; - GridBagConstraints headConst = new GridBagConstraints(); - headConst.gridx = 0; - headConst.gridy = 0; - headConst.fill = GridBagConstraints.HORIZONTAL; - GridBagConstraints resetConst = new GridBagConstraints(); - resetConst.gridx = 0; - resetConst.gridy = 2; - resetConst.fill = GridBagConstraints.HORIZONTAL; - - // Border so that the scrollbar doesn't go over ping - Border paddingBorder = BorderFactory.createEmptyBorder(0, 0, 0, 5); - - // Clear history button - JButton resetBtn = new JButton("Clear History"); - resetBtn.addActionListener(e -> - { - plugin.clearHistory(); - plugin.addToHistory(); - updateList(); - }); - - // World Selector page - JPanel worldPanel = new JPanel(); - worldPanel.setBorder(paddingBorder); - worldPanel.setLayout(new GridBagLayout()); - worldPanel.add(headerContainer, headConst); - worldPanel.add(listContainer, listConst); - - // History page - JPanel histPanel = new JPanel(); - histPanel.setBorder(paddingBorder); - histPanel.setLayout(new GridBagLayout()); - histPanel.add(headerHistContainer, headConst); - histPanel.add(histContainer, listConst); - histPanel.add(resetBtn, resetConst); - - JTabbedPane worldTabs = new JTabbedPane(); - worldTabs.setName("tabs"); - worldTabs.addTab("Worlds", worldPanel); - worldTabs.addTab("History", histPanel); - - // This is a fix for preventing stretching of WorldTableRows - worldTabs.addChangeListener(e -> - { - switch (worldTabs.getSelectedIndex()) - { - case 0: - histPanel.remove(histContainer); - if (worldPanel.getComponentCount() < 2) - { - worldPanel.add(listContainer, listConst); - } - break; - case 1: - worldPanel.remove(listContainer); - if (histPanel.getComponentCount() < 3) - { - histPanel.add(histContainer, listConst); - } - break; - } - }); - - return worldTabs; - } - - void updateFavoriteMenu(int world, boolean favorite) - { - for (WorldTableRow row : rows) - { - if (row.getWorld().getId() == world) - { - row.setFavoriteMenu(favorite); - } - } - - for (WorldTableRow row : histRows) - { - if (row.getWorld().getId() == world) - { - row.setFavoriteMenu(favorite); - } - } - } - - void resetAllFavoriteMenus() - { - for (WorldTableRow row : rows) - { - row.setFavoriteMenu(false); - } - - for (WorldTableRow row : histRows) - { - row.setFavoriteMenu(false); - } - } - - void populate(List worlds) - { - Map pingHistory = new HashMap<>(); - - for (WorldTableRow row : rows) - { - pingHistory.put(row.getWorld().getId(), row.getPing()); - } - - rows.clear(); - - for (int i = 0; i < worlds.size(); i++) - { - World world = worlds.get(i); - - switch (filterMode) - { - case FREE: - if (world.getTypes().contains(WorldType.MEMBERS)) - { - continue; - } - break; - case MEMBERS: - if (!world.getTypes().contains(WorldType.MEMBERS)) - { - continue; - } - break; - } - - Integer ping = pingHistory.getOrDefault(world.getId(), 0); - rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld() && plugin.getLastWorld() != 0, plugin.isFavorite(world), ping)); - } - - updateList(); - } - - private void orderBy(WorldOrder order) - { - pingHeader.highlight(false, ascendingOrder); - worldHeader.highlight(false, ascendingOrder); - playersHeader.highlight(false, ascendingOrder); - activityHeader.highlight(false, ascendingOrder); - - switch (order) - { - case PING: - pingHeader.highlight(true, ascendingOrder); - break; - case WORLD: - worldHeader.highlight(true, ascendingOrder); - break; - case PLAYERS: - playersHeader.highlight(true, ascendingOrder); - break; - case ACTIVITY: - activityHeader.highlight(true, ascendingOrder); - break; - } - - orderIndex = order; - updateList(); - } - - /** - * Builds the entire table header. - */ - private JPanel buildHistoryHeader() - { - JPanel header = new JPanel(new BorderLayout()); - JPanel leftSide = new JPanel(new BorderLayout()); - JPanel rightSide = new JPanel(new BorderLayout()); - - WorldTableHeader pingHeader = new WorldTableHeader("Ping", false, ascendingOrder, plugin::refresh); - pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); - - WorldTableHeader worldHeader = new WorldTableHeader("World", false, ascendingOrder, plugin::refresh); - worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); - - WorldTableHeader playersHeader = new WorldTableHeader("#", false, ascendingOrder, plugin::refresh); - playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); - - WorldTableHeader activityHeader = new WorldTableHeader("Activity", false, ascendingOrder, plugin::refresh); - - leftSide.add(worldHeader, BorderLayout.WEST); - leftSide.add(playersHeader, BorderLayout.CENTER); - - rightSide.add(activityHeader, BorderLayout.CENTER); - rightSide.add(pingHeader, BorderLayout.EAST); - - header.add(leftSide, BorderLayout.WEST); - header.add(rightSide, BorderLayout.CENTER); - - return header; - } - - private JPanel buildHeader() - { - JPanel header = new JPanel(new BorderLayout()); - JPanel leftSide = new JPanel(new BorderLayout()); - JPanel rightSide = new JPanel(new BorderLayout()); - - pingHeader = new WorldTableHeader("Ping", orderIndex == WorldOrder.PING, ascendingOrder, plugin::refresh); - pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); - pingHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.PING || !ascendingOrder; - orderBy(WorldOrder.PING); - } - }); - - worldHeader = new WorldTableHeader("World", orderIndex == WorldOrder.WORLD, ascendingOrder, plugin::refresh); - worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); - worldHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.WORLD || !ascendingOrder; - orderBy(WorldOrder.WORLD); - } - }); - - playersHeader = new WorldTableHeader("#", orderIndex == WorldOrder.PLAYERS, ascendingOrder, plugin::refresh); - playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); - playersHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.PLAYERS || !ascendingOrder; - orderBy(WorldOrder.PLAYERS); - } - }); - - activityHeader = new WorldTableHeader("Activity", orderIndex == WorldOrder.ACTIVITY, ascendingOrder, plugin::refresh); - activityHeader.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - return; - } - ascendingOrder = orderIndex != WorldOrder.ACTIVITY || !ascendingOrder; - orderBy(WorldOrder.ACTIVITY); - } - }); - - leftSide.add(worldHeader, BorderLayout.WEST); - leftSide.add(playersHeader, BorderLayout.CENTER); - - rightSide.add(activityHeader, BorderLayout.CENTER); - rightSide.add(pingHeader, BorderLayout.EAST); - - header.add(leftSide, BorderLayout.WEST); - header.add(rightSide, BorderLayout.CENTER); - - return header; - } - - /** - * Builds a table row, that displays the world's information. - */ - private WorldTableRow buildRow(World world, boolean stripe, boolean current, boolean favorite, Integer ping) - { - WorldTableRow row = new WorldTableRow(world, current, favorite, - world1 -> - { - plugin.hopTo(world1); - }, - (world12, add) -> - { - if (add) - { - plugin.addToFavorites(world12); - } - else - { - plugin.removeFromFavorites(world12); - } - - updateList(); - } - ); - row.setBackground(stripe ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); - return row; - } - - /** - * Enumerates the multiple ordering options for the world list. - */ - private enum WorldOrder - { - WORLD, - PLAYERS, - ACTIVITY, - PING - } -} +/* + * Copyright (c) 2018, Psikoi + * 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.worldhopper; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import lombok.AccessLevel; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.DynamicGridLayout; +import net.runelite.client.ui.PluginPanel; +import net.runelite.http.api.worlds.World; +import net.runelite.http.api.worlds.WorldType; + +@Slf4j +class WorldSwitcherPanel extends PluginPanel +{ + private static final Color ODD_ROW = new Color(44, 44, 44); + + private static final int WORLD_COLUMN_WIDTH = 60; + private static final int PLAYERS_COLUMN_WIDTH = 40; + private static final int PING_COLUMN_WIDTH = 47; + + private final JPanel listContainer = new JPanel(); + + private WorldTableHeader worldHeader; + private WorldTableHeader playersHeader; + private WorldTableHeader activityHeader; + private WorldTableHeader pingHeader; + + private WorldOrder orderIndex = WorldOrder.WORLD; + private boolean ascendingOrder = true; + + private ArrayList rows = new ArrayList<>(); + private WorldHopperPlugin plugin; + @Setter(AccessLevel.PACKAGE) + private SubscriptionFilterMode filterMode; + + WorldSwitcherPanel(WorldHopperPlugin plugin) + { + this.plugin = plugin; + + setBorder(null); + setLayout(new DynamicGridLayout(0, 1)); + + JPanel headerContainer = buildHeader(); + + listContainer.setLayout(new GridLayout(0, 1)); + + add(headerContainer); + add(listContainer); + } + + void switchCurrentHighlight(int newWorld, int lastWorld) + { + for (WorldTableRow row : rows) + { + if (row.getWorld().getId() == newWorld) + { + row.recolour(true); + } + else if (row.getWorld().getId() == lastWorld) + { + row.recolour(false); + } + } + } + + void updateListData(Map worldData) + { + for (WorldTableRow worldTableRow : rows) + { + World world = worldTableRow.getWorld(); + Integer playerCount = worldData.get(world.getId()); + if (playerCount != null) + { + worldTableRow.updatePlayerCount(playerCount); + } + } + + // If the list is being ordered by player count, then it has to be re-painted + // to properly display the new data + if (orderIndex == WorldOrder.PLAYERS) + { + updateList(); + } + } + + void updatePing(int world, int ping) + { + for (WorldTableRow worldTableRow : rows) + { + if (worldTableRow.getWorld().getId() == world) + { + worldTableRow.setPing(ping); + + // If the panel is sorted by ping, re-sort it + if (orderIndex == WorldOrder.PING) + { + updateList(); + } + break; + } + } + } + + void hidePing() + { + for (WorldTableRow worldTableRow : rows) + { + worldTableRow.hidePing(); + } + } + + void showPing() + { + for (WorldTableRow worldTableRow : rows) + { + worldTableRow.showPing(); + } + } + + void updateList() + { + rows.sort((r1, r2) -> + { + switch (orderIndex) + { + case PING: + return Integer.compare(r1.getPing(), r2.getPing()) * (ascendingOrder ? 1 : -1); + case WORLD: + return Integer.compare(r1.getWorld().getId(), r2.getWorld().getId()) * (ascendingOrder ? 1 : -1); + case PLAYERS: + return Integer.compare(r1.getUpdatedPlayerCount(), r2.getUpdatedPlayerCount()) * (ascendingOrder ? 1 : -1); + case ACTIVITY: + return r1.getWorld().getActivity().compareTo(r2.getWorld().getActivity()) * -1 * (ascendingOrder ? 1 : -1); + default: + return 0; + } + }); + + // Leave empty activity worlds on the bottom of the list + if (orderIndex == WorldOrder.ACTIVITY) + { + rows.sort((r1, r2) -> r1.getWorld().getActivity().equals("-") ? 1 : -1); + } + + rows.sort((r1, r2) -> + { + boolean b1 = plugin.isFavorite(r1.getWorld()); + boolean b2 = plugin.isFavorite(r2.getWorld()); + return Boolean.compare(b2, b1); + }); + + listContainer.removeAll(); + + for (int i = 0; i < rows.size(); i++) + { + WorldTableRow row = rows.get(i); + row.setBackground(i % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); + listContainer.add(row); + } + + listContainer.revalidate(); + listContainer.repaint(); + } + + void updateFavoriteMenu(int world, boolean favorite) + { + for (WorldTableRow row : rows) + { + if (row.getWorld().getId() == world) + { + row.setFavoriteMenu(favorite); + } + } + } + + void resetAllFavoriteMenus() + { + for (WorldTableRow row : rows) + { + row.setFavoriteMenu(false); + } + + } + + void populate(List worlds) + { + rows.clear(); + + for (int i = 0; i < worlds.size(); i++) + { + World world = worlds.get(i); + + switch (filterMode) + { + case FREE: + if (world.getTypes().contains(WorldType.MEMBERS)) + { + continue; + } + break; + case MEMBERS: + if (!world.getTypes().contains(WorldType.MEMBERS)) + { + continue; + } + break; + } + + rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld() && plugin.getLastWorld() != 0, plugin.isFavorite(world))); + } + + updateList(); + } + + private void orderBy(WorldOrder order) + { + pingHeader.highlight(false, ascendingOrder); + worldHeader.highlight(false, ascendingOrder); + playersHeader.highlight(false, ascendingOrder); + activityHeader.highlight(false, ascendingOrder); + + switch (order) + { + case PING: + pingHeader.highlight(true, ascendingOrder); + break; + case WORLD: + worldHeader.highlight(true, ascendingOrder); + break; + case PLAYERS: + playersHeader.highlight(true, ascendingOrder); + break; + case ACTIVITY: + activityHeader.highlight(true, ascendingOrder); + break; + } + + orderIndex = order; + updateList(); + } + + /** + * Builds the entire table header. + */ + private JPanel buildHeader() + { + JPanel header = new JPanel(new BorderLayout()); + JPanel leftSide = new JPanel(new BorderLayout()); + JPanel rightSide = new JPanel(new BorderLayout()); + + pingHeader = new WorldTableHeader("Ping", orderIndex == WorldOrder.PING, ascendingOrder, plugin::refresh); + pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); + pingHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.PING || !ascendingOrder; + orderBy(WorldOrder.PING); + } + }); + + worldHeader = new WorldTableHeader("World", orderIndex == WorldOrder.WORLD, ascendingOrder, plugin::refresh); + worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); + worldHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.WORLD || !ascendingOrder; + orderBy(WorldOrder.WORLD); + } + }); + + playersHeader = new WorldTableHeader("#", orderIndex == WorldOrder.PLAYERS, ascendingOrder, plugin::refresh); + playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); + playersHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.PLAYERS || !ascendingOrder; + orderBy(WorldOrder.PLAYERS); + } + }); + + activityHeader = new WorldTableHeader("Activity", orderIndex == WorldOrder.ACTIVITY, ascendingOrder, plugin::refresh); + activityHeader.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + return; + } + ascendingOrder = orderIndex != WorldOrder.ACTIVITY || !ascendingOrder; + orderBy(WorldOrder.ACTIVITY); + } + }); + + leftSide.add(worldHeader, BorderLayout.WEST); + leftSide.add(playersHeader, BorderLayout.CENTER); + + rightSide.add(activityHeader, BorderLayout.CENTER); + rightSide.add(pingHeader, BorderLayout.EAST); + + header.add(leftSide, BorderLayout.WEST); + header.add(rightSide, BorderLayout.CENTER); + + return header; + } + + /** + * Builds a table row, that displays the world's information. + */ + private WorldTableRow buildRow(World world, boolean stripe, boolean current, boolean favorite) + { + WorldTableRow row = new WorldTableRow(world, current, favorite, + world1 -> + { + plugin.hopTo(world1); + }, + (world12, add) -> + { + if (add) + { + plugin.addToFavorites(world12); + } + else + { + plugin.removeFromFavorites(world12); + } + + updateList(); + } + ); + row.setBackground(stripe ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR); + return row; + } + + /** + * Enumerates the multiple ordering options for the world list. + */ + private enum WorldOrder + { + WORLD, + PLAYERS, + ACTIVITY, + PING + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java index 6dd39ccfeb..a664d6536c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java @@ -1,343 +1,342 @@ -/* - * Copyright (c) 2018, Psikoi - * 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.worldhopper; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.client.ui.FontManager; -import net.runelite.client.util.ImageUtil; -import net.runelite.http.api.worlds.World; -import net.runelite.http.api.worlds.WorldType; - -class WorldTableRow extends JPanel -{ - private static final ImageIcon FLAG_AUS; - private static final ImageIcon FLAG_UK; - private static final ImageIcon FLAG_US; - private static final ImageIcon FLAG_GER; - - private static final int WORLD_COLUMN_WIDTH = 60; - private static final int PLAYERS_COLUMN_WIDTH = 40; - private static final int PING_COLUMN_WIDTH = 35; - - private static final Color CURRENT_WORLD = new Color(66, 227, 17); - private static final Color UNAVAILABLE_WORLD = Color.GRAY.darker().darker(); - private static final Color DANGEROUS_WORLD = new Color(251, 62, 62); - private static final Color TOURNAMENT_WORLD = new Color(79, 145, 255); - private static final Color MEMBERS_WORLD = new Color(210, 193, 53); - private static final Color FREE_WORLD = new Color(200, 200, 200); - - static - { - FLAG_AUS = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_aus.png")); - FLAG_UK = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_uk.png")); - FLAG_US = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_us.png")); - FLAG_GER = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_ger.png")); - } - - private final JMenuItem favoriteMenuOption = new JMenuItem(); - - private JLabel worldField; - private JLabel playerCountField; - private JLabel activityField; - private JLabel pingField; - private BiConsumer onFavorite; - - @Getter - private final World world; - - @Getter(AccessLevel.PACKAGE) - private int updatedPlayerCount; - - private int ping; - - private Color lastBackground; - private boolean current; - - WorldTableRow(World world, boolean current, boolean favorite, Consumer onSelect, BiConsumer onFavorite) - { - this.current = current; - this.world = world; - this.onFavorite = onFavorite; - this.updatedPlayerCount = world.getPlayers(); - this. - - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(2, 0, 2, 0)); - - addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent mouseEvent) - { - if (mouseEvent.getClickCount() == 2) - { - if (onSelect != null) - { - onSelect.accept(world); - } - } - } - - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (mouseEvent.getClickCount() == 2) - { - setBackground(getBackground().brighter()); - } - } - - @Override - public void mouseReleased(MouseEvent mouseEvent) - { - if (mouseEvent.getClickCount() == 2) - { - setBackground(getBackground().darker()); - } - } - - @Override - public void mouseEntered(MouseEvent mouseEvent) - { - WorldTableRow.this.lastBackground = getBackground(); - setBackground(getBackground().brighter()); - } - - @Override - public void mouseExited(MouseEvent mouseEvent) - { - setBackground(lastBackground); - } - }); - - setFavoriteMenu(favorite); - - final JPopupMenu popupMenu = new JPopupMenu(); - popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); - popupMenu.add(favoriteMenuOption); - - setComponentPopupMenu(popupMenu); - - JPanel leftSide = new JPanel(new BorderLayout()); - JPanel rightSide = new JPanel(new BorderLayout()); - leftSide.setOpaque(false); - rightSide.setOpaque(false); - - JPanel worldField = buildWorldField(); - worldField.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); - worldField.setOpaque(false); - - JPanel pingField = buildPingField(); - pingField.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); - pingField.setOpaque(false); - - JPanel playersField = buildPlayersField(); - playersField.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); - playersField.setOpaque(false); - - JPanel activityField = buildActivityField(); - activityField.setBorder(new EmptyBorder(5, 5, 5, 5)); - activityField.setOpaque(false); - - recolour(current); - - leftSide.add(worldField, BorderLayout.WEST); - leftSide.add(playersField, BorderLayout.CENTER); - rightSide.add(activityField, BorderLayout.CENTER); - rightSide.add(pingField, BorderLayout.EAST); - - add(leftSide, BorderLayout.WEST); - add(rightSide, BorderLayout.CENTER); - } - - void setFavoriteMenu(boolean favorite) - { - String favoriteAction = favorite ? - "Remove " + world.getId() + " from favorites" : - "Add " + world.getId() + " to favorites"; - - favoriteMenuOption.setText(favoriteAction); - - for (ActionListener listener : favoriteMenuOption.getActionListeners()) - { - favoriteMenuOption.removeActionListener(listener); - } - - favoriteMenuOption.addActionListener(e -> - { - onFavorite.accept(world, !favorite); - }); - } - - void updatePlayerCount(int playerCount) - { - this.updatedPlayerCount = playerCount; - playerCountField.setText(String.valueOf(playerCount)); - } - - void setPing(int ping) - { - this.ping = ping; - pingField.setText(ping <= 0 ? "-" : Integer.toString(ping)); - } - - void hidePing() - { - pingField.setText("-"); - } - - void showPing() - { - setPing(ping); // to update pingField - } - - int getPing() - { - return ping; - } - - public void recolour(boolean current) - { - playerCountField.setForeground(current ? CURRENT_WORLD : Color.WHITE); - pingField.setForeground(current ? CURRENT_WORLD : Color.WHITE); - - if (current) - { - activityField.setForeground(CURRENT_WORLD); - worldField.setForeground(CURRENT_WORLD); - return; - } - else if (world.getTypes().contains(WorldType.PVP) - || world.getTypes().contains(WorldType.HIGH_RISK) - || world.getTypes().contains(WorldType.DEADMAN) - || world.getTypes().contains(WorldType.SEASONAL_DEADMAN)) - { - activityField.setForeground(DANGEROUS_WORLD); - } - else if (world.getTypes().contains(WorldType.TOURNAMENT)) - { - activityField.setForeground(TOURNAMENT_WORLD); - } - else - { - activityField.setForeground(Color.WHITE); - } - - worldField.setForeground(world.getTypes().contains(WorldType.MEMBERS) ? MEMBERS_WORLD : FREE_WORLD); - } - - /** - * Builds the players list field (containing the amount of players logged in that world). - */ - private JPanel buildPlayersField() - { - JPanel column = new JPanel(new BorderLayout()); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - playerCountField = new JLabel(world.getPlayers() + ""); - playerCountField.setFont(FontManager.getRunescapeSmallFont()); - - column.add(playerCountField, BorderLayout.WEST); - - return column; - } - - private JPanel buildPingField() - { - JPanel column = new JPanel(new BorderLayout()); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - pingField = new JLabel("-"); - pingField.setFont(FontManager.getRunescapeSmallFont()); - - column.add(pingField, BorderLayout.EAST); - - return column; - } - - /** - * Builds the activity list field (containing that world's activity/theme). - */ - private JPanel buildActivityField() - { - JPanel column = new JPanel(new BorderLayout()); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - activityField = new JLabel(world.getActivity()); - activityField.setFont(FontManager.getRunescapeSmallFont()); - - column.add(activityField, BorderLayout.WEST); - - return column; - } - - /** - * Builds the world list field (containing the country's flag and the world index). - */ - private JPanel buildWorldField() - { - JPanel column = new JPanel(new BorderLayout(7, 0)); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - worldField = new JLabel(world.getId() + ""); - - JLabel flag = new JLabel(getFlag(world.getLocation())); - - column.add(flag, BorderLayout.WEST); - column.add(worldField, BorderLayout.CENTER); - - return column; - } - - private ImageIcon getFlag(int locationId) - { - switch (locationId) - { - case 0: - return FLAG_US; - case 1: - return FLAG_UK; - case 3: - return FLAG_AUS; - default: - return FLAG_GER; - } - } -} +/* + * Copyright (c) 2018, Psikoi + * 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.worldhopper; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.border.EmptyBorder; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.client.ui.FontManager; +import net.runelite.client.util.ImageUtil; +import net.runelite.http.api.worlds.World; +import net.runelite.http.api.worlds.WorldType; + +class WorldTableRow extends JPanel +{ + private static final ImageIcon FLAG_AUS; + private static final ImageIcon FLAG_UK; + private static final ImageIcon FLAG_US; + private static final ImageIcon FLAG_GER; + + private static final int WORLD_COLUMN_WIDTH = 60; + private static final int PLAYERS_COLUMN_WIDTH = 40; + private static final int PING_COLUMN_WIDTH = 35; + + private static final Color CURRENT_WORLD = new Color(66, 227, 17); + private static final Color UNAVAILABLE_WORLD = Color.GRAY.darker().darker(); + private static final Color DANGEROUS_WORLD = new Color(251, 62, 62); + private static final Color TOURNAMENT_WORLD = new Color(79, 145, 255); + private static final Color MEMBERS_WORLD = new Color(210, 193, 53); + private static final Color FREE_WORLD = new Color(200, 200, 200); + + static + { + FLAG_AUS = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_aus.png")); + FLAG_UK = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_uk.png")); + FLAG_US = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_us.png")); + FLAG_GER = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_ger.png")); + } + + private final JMenuItem favoriteMenuOption = new JMenuItem(); + + private JLabel worldField; + private JLabel playerCountField; + private JLabel activityField; + private JLabel pingField; + private BiConsumer onFavorite; + + @Getter + private final World world; + + @Getter(AccessLevel.PACKAGE) + private int updatedPlayerCount; + + private int ping; + + private Color lastBackground; + private boolean current; + + WorldTableRow(World world, boolean current, boolean favorite, Consumer onSelect, BiConsumer onFavorite) + { + this.current = current; + this.world = world; + this.onFavorite = onFavorite; + this.updatedPlayerCount = world.getPlayers(); + + setLayout(new BorderLayout()); + setBorder(new EmptyBorder(2, 0, 2, 0)); + + addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent mouseEvent) + { + if (mouseEvent.getClickCount() == 2) + { + if (onSelect != null) + { + onSelect.accept(world); + } + } + } + + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (mouseEvent.getClickCount() == 2) + { + setBackground(getBackground().brighter()); + } + } + + @Override + public void mouseReleased(MouseEvent mouseEvent) + { + if (mouseEvent.getClickCount() == 2) + { + setBackground(getBackground().darker()); + } + } + + @Override + public void mouseEntered(MouseEvent mouseEvent) + { + WorldTableRow.this.lastBackground = getBackground(); + setBackground(getBackground().brighter()); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) + { + setBackground(lastBackground); + } + }); + + setFavoriteMenu(favorite); + + final JPopupMenu popupMenu = new JPopupMenu(); + popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); + popupMenu.add(favoriteMenuOption); + + setComponentPopupMenu(popupMenu); + + JPanel leftSide = new JPanel(new BorderLayout()); + JPanel rightSide = new JPanel(new BorderLayout()); + leftSide.setOpaque(false); + rightSide.setOpaque(false); + + JPanel worldField = buildWorldField(); + worldField.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); + worldField.setOpaque(false); + + JPanel pingField = buildPingField(); + pingField.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); + pingField.setOpaque(false); + + JPanel playersField = buildPlayersField(); + playersField.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); + playersField.setOpaque(false); + + JPanel activityField = buildActivityField(); + activityField.setBorder(new EmptyBorder(5, 5, 5, 5)); + activityField.setOpaque(false); + + recolour(current); + + leftSide.add(worldField, BorderLayout.WEST); + leftSide.add(playersField, BorderLayout.CENTER); + rightSide.add(activityField, BorderLayout.CENTER); + rightSide.add(pingField, BorderLayout.EAST); + + add(leftSide, BorderLayout.WEST); + add(rightSide, BorderLayout.CENTER); + } + + void setFavoriteMenu(boolean favorite) + { + String favoriteAction = favorite ? + "Remove " + world.getId() + " from favorites" : + "Add " + world.getId() + " to favorites"; + + favoriteMenuOption.setText(favoriteAction); + + for (ActionListener listener : favoriteMenuOption.getActionListeners()) + { + favoriteMenuOption.removeActionListener(listener); + } + + favoriteMenuOption.addActionListener(e -> + { + onFavorite.accept(world, !favorite); + }); + } + + void updatePlayerCount(int playerCount) + { + this.updatedPlayerCount = playerCount; + playerCountField.setText(String.valueOf(playerCount)); + } + + void setPing(int ping) + { + this.ping = ping; + pingField.setText(ping <= 0 ? "-" : Integer.toString(ping)); + } + + void hidePing() + { + pingField.setText("-"); + } + + void showPing() + { + setPing(ping); // to update pingField + } + + int getPing() + { + return ping; + } + + public void recolour(boolean current) + { + playerCountField.setForeground(current ? CURRENT_WORLD : Color.WHITE); + pingField.setForeground(current ? CURRENT_WORLD : Color.WHITE); + + if (current) + { + activityField.setForeground(CURRENT_WORLD); + worldField.setForeground(CURRENT_WORLD); + return; + } + else if (world.getTypes().contains(WorldType.PVP) + || world.getTypes().contains(WorldType.HIGH_RISK) + || world.getTypes().contains(WorldType.DEADMAN) + || world.getTypes().contains(WorldType.SEASONAL_DEADMAN)) + { + activityField.setForeground(DANGEROUS_WORLD); + } + else if (world.getTypes().contains(WorldType.TOURNAMENT)) + { + activityField.setForeground(TOURNAMENT_WORLD); + } + else + { + activityField.setForeground(Color.WHITE); + } + + worldField.setForeground(world.getTypes().contains(WorldType.MEMBERS) ? MEMBERS_WORLD : FREE_WORLD); + } + + /** + * Builds the players list field (containing the amount of players logged in that world). + */ + private JPanel buildPlayersField() + { + JPanel column = new JPanel(new BorderLayout()); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + playerCountField = new JLabel(world.getPlayers() + ""); + playerCountField.setFont(FontManager.getRunescapeSmallFont()); + + column.add(playerCountField, BorderLayout.WEST); + + return column; + } + + private JPanel buildPingField() + { + JPanel column = new JPanel(new BorderLayout()); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + pingField = new JLabel("-"); + pingField.setFont(FontManager.getRunescapeSmallFont()); + + column.add(pingField, BorderLayout.EAST); + + return column; + } + + /** + * Builds the activity list field (containing that world's activity/theme). + */ + private JPanel buildActivityField() + { + JPanel column = new JPanel(new BorderLayout()); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + activityField = new JLabel(world.getActivity()); + activityField.setFont(FontManager.getRunescapeSmallFont()); + + column.add(activityField, BorderLayout.WEST); + + return column; + } + + /** + * Builds the world list field (containing the country's flag and the world index). + */ + private JPanel buildWorldField() + { + JPanel column = new JPanel(new BorderLayout(7, 0)); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + worldField = new JLabel(world.getId() + ""); + + JLabel flag = new JLabel(getFlag(world.getLocation())); + + column.add(flag, BorderLayout.WEST); + column.add(worldField, BorderLayout.CENTER); + + return column; + } + + private ImageIcon getFlag(int locationId) + { + switch (locationId) + { + case 0: + return FLAG_US; + case 1: + return FLAG_UK; + case 3: + return FLAG_AUS; + default: + return FLAG_GER; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IPHlpAPI.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IPHlpAPI.java new file mode 100644 index 0000000000..109ea36f77 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IPHlpAPI.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Adam + * 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.worldhopper.ping; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; + +interface IPHlpAPI extends Library +{ + IPHlpAPI INSTANCE = Native.loadLibrary("IPHlpAPI", IPHlpAPI.class); + + Pointer IcmpCreateFile(); + + boolean IcmpCloseHandle(Pointer handle); + + int IcmpSendEcho(Pointer IcmpHandle, int DestinationAddress, Pointer RequestData, short RequestSize, Pointer RequestOptions, IcmpEchoReply ReplyBuffer, int ReplySize, int Timeout); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IcmpEchoReply.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IcmpEchoReply.java new file mode 100644 index 0000000000..0e1cc198a3 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/IcmpEchoReply.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, Adam + * 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.worldhopper.ping; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.WinDef; +import java.util.Arrays; +import java.util.List; + +public class IcmpEchoReply extends Structure +{ + private static final int IP_OPTION_INFO_SIZE = 1 + 1 + 1 + 1 + (Pointer.SIZE == 8 ? 12 : 4); // on 64bit vms add 4 byte padding + public static final int SIZE = 4 + 4 + 4 + 2 + 2 + Pointer.SIZE + IP_OPTION_INFO_SIZE; + + public WinDef.ULONG address; + public WinDef.ULONG status; + public WinDef.ULONG roundTripTime; + public WinDef.USHORT dataSize; + public WinDef.USHORT reserved; + public WinDef.PVOID data; + public WinDef.UCHAR ttl; + public WinDef.UCHAR tos; + public WinDef.UCHAR flags; + public WinDef.UCHAR optionsSize; + public WinDef.PVOID optionsData; + + IcmpEchoReply(Pointer p) + { + super(p); + } + + @Override + protected List getFieldOrder() + { + return Arrays.asList("address", "status", "roundTripTime", "dataSize", "reserved", "data", "ttl", "tos", "flags", "optionsSize", "optionsData"); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java new file mode 100644 index 0000000000..fd9a84fa57 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018, Adam + * 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.worldhopper.ping; + +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.util.OSType; +import net.runelite.http.api.worlds.World; + +@Slf4j +public class Ping +{ + private static final String RUNELITE_PING = "RuneLitePing"; + + private static final int TIMEOUT = 2000; + private static final int PORT = 43594; + + public static int ping(World world) + { + try + { + switch (OSType.getOSType()) + { + case Windows: + return windowsPing(world); + default: + return tcpPing(world); + } + } + catch (IOException ex) + { + log.warn("error pinging", ex); + return -1; + } + } + + private static int windowsPing(World world) throws UnknownHostException + { + IPHlpAPI ipHlpAPI = IPHlpAPI.INSTANCE; + Pointer ptr = ipHlpAPI.IcmpCreateFile(); + InetAddress inetAddress = InetAddress.getByName(world.getAddress()); + byte[] address = inetAddress.getAddress(); + String dataStr = RUNELITE_PING; + int dataLength = dataStr.length() + 1; + Pointer data = new Memory(dataLength); + data.setString(0L, dataStr); + IcmpEchoReply icmpEchoReply = new IcmpEchoReply(new Memory(IcmpEchoReply.SIZE + dataLength)); + assert icmpEchoReply.size() == IcmpEchoReply.SIZE; + int packed = (address[0] & 0xff) | ((address[1] & 0xff) << 8) | ((address[2] & 0xff) << 16) | ((address[3] & 0xff) << 24); + int ret = ipHlpAPI.IcmpSendEcho(ptr, packed, data, (short) (dataLength), Pointer.NULL, icmpEchoReply, IcmpEchoReply.SIZE + dataLength, TIMEOUT); + if (ret != 1) + { + ipHlpAPI.IcmpCloseHandle(ptr); + return -1; + } + + int rtt = Math.toIntExact(icmpEchoReply.roundTripTime.longValue()); + ipHlpAPI.IcmpCloseHandle(ptr); + + return rtt; + } + + private static int tcpPing(World world) throws IOException + { + try (Socket socket = new Socket()) + { + socket.setSoTimeout(TIMEOUT); + InetAddress inetAddress = InetAddress.getByName(world.getAddress()); + long start = System.nanoTime(); + socket.connect(new InetSocketAddress(inetAddress, PORT)); + long end = System.nanoTime(); + return (int) ((end - start) / 1000000L); + } + } +} From 97afe462c2db72f6b6d7c3fda1572ca9fa6a56f6 Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 20 May 2019 11:10:42 +0200 Subject: [PATCH 66/78] Add custom menu swaps to menu entry swapper --- .../client/menus/AbstractMenuEntry.java | 8 +- .../runelite/client/menus/MenuManager.java | 148 ++++++++++++++++-- .../MenuEntrySwapperConfig.java | 11 ++ .../MenuEntrySwapperPlugin.java | 127 ++++++++++++--- .../ShiftClickInputListener.java | 14 +- 5 files changed, 261 insertions(+), 47 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java b/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java index 14577265d4..6f5238c497 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java @@ -6,7 +6,7 @@ import net.runelite.api.MenuEntry; import static net.runelite.client.menus.MenuManager.LEVEL_PATTERN; import net.runelite.client.util.Text; -class AbstractMenuEntry +public class AbstractMenuEntry { @Getter private String option; @@ -26,17 +26,17 @@ class AbstractMenuEntry @Getter private boolean strictTarget; - AbstractMenuEntry(String option, String target) + public AbstractMenuEntry(String option, String target) { this(option, target, -1, -1, true, true); } - AbstractMenuEntry(String option, String target, boolean strictTarget) + public AbstractMenuEntry(String option, String target, boolean strictTarget) { this(option, target, -1, -1, true, strictTarget); } - AbstractMenuEntry(String option, String target, int id, int type, boolean strictOption, boolean strictTarget) + public AbstractMenuEntry(String option, String target, int id, int type, boolean strictOption, boolean strictTarget) { this.option = option; this.target = target; diff --git a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java index 4fba85094b..5467a9d8c5 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java @@ -26,6 +26,7 @@ package net.runelite.client.menus; import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; +import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import java.util.ArrayList; import java.util.Arrays; @@ -36,7 +37,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; -import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; @@ -168,7 +168,15 @@ public class MenuManager MenuEntry newestEntry = menuEntries[menuEntries.length - 1]; - boolean isPrio = priorityEntries.stream().anyMatch(p -> p.matches(newestEntry)); + boolean isPrio = false; + for (AbstractMenuEntry p : priorityEntries) + { + if (p.matches(newestEntry)) + { + isPrio = true; + break; + } + } // If the last entry was a priority entry, keep track of it if (isPrio) @@ -187,26 +195,42 @@ public class MenuManager copy.add(CANCEL()); } - /*// Find the current entry in the swaps map - Optional swapEntry = swaps.keySet().stream().filter(e -> e.matches(newestEntry)).findFirst(); - - if (swapEntry.isPresent()) + // Find the current entry in the swaps map + AbstractMenuEntry swapEntry = null; + for (AbstractMenuEntry e : swaps.keySet()) { - AbstractMenuEntry swap = swapEntry.get(); - AbstractMenuEntry swapTarget = swaps.get(swap); + if (e.matches(newestEntry)) + { + swapEntry = e; + break; + } + } + + if (swapEntry != null) + { + AbstractMenuEntry swapTarget = swaps.get(swapEntry); // Find the target for the swap in current menu entries - Optional foundSwap = Lists.reverse(copy).stream().filter(swapTarget::matches).findFirst(); + MenuEntry foundSwap = null; + for (MenuEntry entry : Lists.reverse(copy)) + { + if (swapTarget.matches(entry)) + { + foundSwap = entry; + break; + } + } - if (foundSwap.isPresent()) + if (foundSwap != null) { // Swap - int index = copy.indexOf(foundSwap.get()); + int index = copy.indexOf(foundSwap); + int newIndex = copy.indexOf(newestEntry); copy.set(index, newestEntry); - copy.set(copy.size() - 1, foundSwap.get()); + copy.set(newIndex, foundSwap); } - }*/ + } client.setMenuEntries(copy.toArray(new MenuEntry[0])); } @@ -394,6 +418,19 @@ public class MenuManager priorityEntries.add(entry); } + /** + * Adds to the set of menu entries which when present, will remove all entries except for this one + * This method will add one with strict option, but not-strict target (contains for target, equals for option) + */ + public void addPriorityEntry(String option) + { + option = Text.standardize(option); + + AbstractMenuEntry entry = new AbstractMenuEntry(option, "", false); + + priorityEntries.add(entry); + } + public void removePriorityEntry(String option, String target) { option = Text.standardize(option); @@ -401,8 +438,89 @@ public class MenuManager AbstractMenuEntry entry = new AbstractMenuEntry(option, target); - Set toRemove = priorityEntries.stream().filter(entry::equals).collect(Collectors.toSet()); + for (AbstractMenuEntry priorityEntry : priorityEntries) + { + if (entry.equals(priorityEntry)) + { + priorityEntries.remove(priorityEntry); + } + } + } - priorityEntries.removeAll(toRemove); + public void removePriorityEntry(String option) + { + option = Text.standardize(option); + + AbstractMenuEntry entry = new AbstractMenuEntry(option, "", false); + + for (AbstractMenuEntry priorityEntry : priorityEntries) + { + if (entry.equals(priorityEntry)) + { + priorityEntries.remove(priorityEntry); + } + } + } + + /** + * Adds to the map of swaps. - Strict option + target + */ + public void addSwap(String option, String target, String option2, String target2) + { + option = Text.standardize(option); + target = Text.standardize(target); + + option2 = Text.standardize(option2); + target2 = Text.standardize(target2); + + AbstractMenuEntry swapFrom = new AbstractMenuEntry(option, target); + AbstractMenuEntry swapTo = new AbstractMenuEntry(option2, target2); + + if (swapTo.equals(swapFrom)) + { + log.warn("You shouldn't try swapping an entry for itself"); + return; + } + + swaps.put(swapFrom, swapTo); + } + + /** + * Adds to the map of swaps - Pre-baked Abstract entry + */ + public void addSwap(AbstractMenuEntry swapFrom, AbstractMenuEntry swapTo) + { + if (swapTo.equals(swapFrom)) + { + log.warn("You shouldn't try swapping an entry for itself"); + return; + } + + swaps.put(swapFrom, swapTo); + } + + public void removeSwap(String option, String target, String option2, String target2) + { + option = Text.standardize(option); + target = Text.standardize(target); + + option2 = Text.standardize(option2); + target2 = Text.standardize(target2); + + AbstractMenuEntry swapFrom = new AbstractMenuEntry(option, target); + AbstractMenuEntry swapTo = new AbstractMenuEntry(option2, target2); + + removeSwap(swapFrom, swapTo); + } + + public void removeSwap(AbstractMenuEntry swapFrom, AbstractMenuEntry swapTo) + { + for (Map.Entry e : swaps.entrySet()) + { + if (e.getKey().equals(swapFrom) && e.getValue().equals(swapTo)) + { + swaps.remove(e.getKey()); + } + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java index f1a39f4427..e0fd5d28e4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java @@ -32,6 +32,17 @@ import net.runelite.client.config.ConfigItem; @ConfigGroup("menuentryswapper") public interface MenuEntrySwapperConfig extends Config { + @ConfigItem( + position = -3, + keyName = "customSwaps", + name = "Custom swaps", + description = "Add custom swaps here, 1 per line. Syntax: option, target : option, target
Note that the first entry should be the left click one!" + ) + default String customSwaps() + { + return ""; + } + @ConfigItem( position = -2, keyName = "shiftClickCustomization", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 155795761d..4c5d6ec01f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -25,10 +25,14 @@ */ package net.runelite.client.plugins.menuentryswapper; +import com.google.common.base.Splitter; import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import javax.inject.Inject; +import joptsimple.internal.Strings; import lombok.Getter; import lombok.Setter; import net.runelite.api.Client; @@ -51,6 +55,7 @@ import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemVariationMapping; import net.runelite.client.input.KeyManager; +import net.runelite.client.menus.AbstractMenuEntry; import net.runelite.client.menus.MenuManager; import net.runelite.client.menus.WidgetMenuOption; import net.runelite.client.plugins.Plugin; @@ -71,7 +76,6 @@ public class MenuEntrySwapperPlugin extends Plugin private static final String SAVE = "Save"; private static final String RESET = "Reset"; private static final String MENU_TARGET = "Shift-click"; - private static final String CONFIG_GROUP = "shiftclick"; private static final String ITEM_KEY_PREFIX = "item_"; @@ -101,6 +105,13 @@ public class MenuEntrySwapperPlugin extends Plugin MenuAction.NPC_FIFTH_OPTION, MenuAction.EXAMINE_NPC); + private static final Splitter NEWLINE_SPLITTER = Splitter + .on("\n") + .omitEmptyStrings() + .trimResults(); + + private final Map customSwaps = new HashMap<>(); + @Inject private Client client; @@ -131,9 +142,6 @@ public class MenuEntrySwapperPlugin extends Plugin @Setter private boolean shiftModifier = false; - @Setter - private boolean controlModifier = false; - @Provides MenuEntrySwapperConfig provideConfig(ConfigManager configManager) { @@ -160,6 +168,11 @@ public class MenuEntrySwapperPlugin extends Plugin { if (!CONFIG_GROUP.equals(event.getGroup())) { + if (event.getKey().equals("customSwaps")) + { + loadCustomSwaps(config.customSwaps()); + } + return; } @@ -455,20 +468,6 @@ public class MenuEntrySwapperPlugin extends Plugin } } - else if (option.equalsIgnoreCase("climb") && config.swapClimbUpDown()) - { - if (controlModifier ^ shiftModifier) - { - if (shiftModifier) - { - swap(client, "climb-up", option, target, true); - } - if (controlModifier) - { - swap(client, "climb-down", option, target, true); - } - } - } else if (config.swapTravel() && option.equals("pass") && target.equals("energy barrier")) { swap(client, "pay-toll(2-ecto)", option, target, true); @@ -667,4 +666,96 @@ public class MenuEntrySwapperPlugin extends Plugin menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE); } } + + private void loadCustomSwaps(String config) + { + Map tmp = new HashMap<>(); + + if (!Strings.isNullOrEmpty(config)) + { + Map split = NEWLINE_SPLITTER.withKeyValueSeparator(':').split(config); + + for (Map.Entry entry : split.entrySet()) + { + String from = entry.getKey(); + String to = entry.getValue(); + String[] splitFrom = Text.standardize(from).split(","); + String optionFrom = splitFrom[0].trim(); + String targetFrom; + if (splitFrom.length == 1) + { + targetFrom = ""; + } + else + { + targetFrom = splitFrom[1].trim(); + } + + AbstractMenuEntry fromEntry = new AbstractMenuEntry(optionFrom, targetFrom); + + String[] splitTo = Text.standardize(to).split(","); + String optionTo = splitTo[0].trim(); + String targetTo; + if (splitTo.length == 1) + { + targetTo = ""; + } + else + { + targetTo = splitTo[1].trim(); + } + + AbstractMenuEntry toEntry = new AbstractMenuEntry(optionTo, targetTo); + + tmp.put(fromEntry, toEntry); + } + } + + for (Map.Entry e : customSwaps.entrySet()) + { + AbstractMenuEntry key = e.getKey(); + AbstractMenuEntry value = e.getValue(); + menuManager.removeSwap(key, value); + } + + customSwaps.clear(); + customSwaps.putAll(tmp); + + for (Map.Entry entry : customSwaps.entrySet()) + { + AbstractMenuEntry a1 = entry.getKey(); + AbstractMenuEntry a2 = entry.getValue(); + menuManager.addSwap(a1, a2); + } + } + + void startShift() + { + if (!config.swapClimbUpDown()) + { + return; + } + + menuManager.addPriorityEntry("climb-up"); + } + + void stopShift() + { + menuManager.removePriorityEntry("climb-up"); + } + + void startControl() + { + if (!config.swapClimbUpDown()) + { + return; + } + + menuManager.addPriorityEntry("climb-down"); + } + + void stopControl() + { + menuManager.removePriorityEntry("climb-down"); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java index cea447b527..5df37f45b2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/ShiftClickInputListener.java @@ -26,18 +26,10 @@ package net.runelite.client.plugins.menuentryswapper; import java.awt.event.KeyEvent; import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.client.callback.ClientThread; import net.runelite.client.input.KeyListener; public class ShiftClickInputListener implements KeyListener { - @Inject - private ClientThread clientThread; - - @Inject - private Client client; - @Inject private MenuEntrySwapperPlugin plugin; @@ -53,10 +45,11 @@ public class ShiftClickInputListener implements KeyListener if (event.getKeyCode() == KeyEvent.VK_SHIFT) { plugin.setShiftModifier(true); + plugin.startShift(); } if (event.getKeyCode() == KeyEvent.VK_CONTROL) { - plugin.setControlModifier(true); + plugin.startControl(); } } @@ -66,10 +59,11 @@ public class ShiftClickInputListener implements KeyListener if (event.getKeyCode() == KeyEvent.VK_SHIFT) { plugin.setShiftModifier(false); + plugin.stopShift(); } if (event.getKeyCode() == KeyEvent.VK_CONTROL) { - plugin.setControlModifier(false); + plugin.stopControl(); } } } From 4f203b6507927d43cda9fcee57ac6d386256e933 Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 20 May 2019 13:12:38 +0200 Subject: [PATCH 67/78] Fix a dumb error --- .../client/menus/AbstractMenuEntry.java | 6 +- .../runelite/client/menus/MenuManager.java | 55 +++++++++++++------ .../shiftwalker/ShiftWalkerPlugin.java | 6 +- .../net/runelite/client/util/MenuUtil.java | 1 + 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java b/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java index 6f5238c497..a51b211542 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/AbstractMenuEntry.java @@ -1,11 +1,13 @@ package net.runelite.client.menus; import joptsimple.internal.Strings; +import lombok.EqualsAndHashCode; import lombok.Getter; import net.runelite.api.MenuEntry; import static net.runelite.client.menus.MenuManager.LEVEL_PATTERN; import net.runelite.client.util.Text; +@EqualsAndHashCode public class AbstractMenuEntry { @Getter @@ -88,7 +90,7 @@ public class AbstractMenuEntry return true; } - boolean equals(AbstractMenuEntry other) + /*boolean equals(AbstractMenuEntry other) { return target.equals(other.getTarget()) && option.equals(other.getOption()) @@ -96,5 +98,5 @@ public class AbstractMenuEntry && type == other.getType() && strictOption == other.isStrictOption() && strictTarget == other.isStrictTarget(); - } + }*/ } diff --git a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java index 5467a9d8c5..7e4e236faa 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java @@ -418,6 +418,29 @@ public class MenuManager priorityEntries.add(entry); } + public void removePriorityEntry(String option, String target) + { + option = Text.standardize(option); + target = Text.standardize(target); + + AbstractMenuEntry entry = new AbstractMenuEntry(option, target); + + Set toRemove = new HashSet<>(); + for (AbstractMenuEntry priorityEntry : priorityEntries) + { + if (entry.equals(priorityEntry)) + { + toRemove.add(entry); + } + } + + for (AbstractMenuEntry e : toRemove) + { + priorityEntries.remove(e); + } + } + + /** * Adds to the set of menu entries which when present, will remove all entries except for this one * This method will add one with strict option, but not-strict target (contains for target, equals for option) @@ -431,35 +454,25 @@ public class MenuManager priorityEntries.add(entry); } - public void removePriorityEntry(String option, String target) - { - option = Text.standardize(option); - target = Text.standardize(target); - - AbstractMenuEntry entry = new AbstractMenuEntry(option, target); - - for (AbstractMenuEntry priorityEntry : priorityEntries) - { - if (entry.equals(priorityEntry)) - { - priorityEntries.remove(priorityEntry); - } - } - } - public void removePriorityEntry(String option) { option = Text.standardize(option); AbstractMenuEntry entry = new AbstractMenuEntry(option, "", false); + Set toRemove = new HashSet<>(); for (AbstractMenuEntry priorityEntry : priorityEntries) { if (entry.equals(priorityEntry)) { - priorityEntries.remove(priorityEntry); + toRemove.add(entry); } } + + for (AbstractMenuEntry e : toRemove) + { + priorityEntries.remove(e); + } } /** @@ -515,12 +528,18 @@ public class MenuManager public void removeSwap(AbstractMenuEntry swapFrom, AbstractMenuEntry swapTo) { + Set toRemove = new HashSet<>(); for (Map.Entry e : swaps.entrySet()) { if (e.getKey().equals(swapFrom) && e.getValue().equals(swapTo)) { - swaps.remove(e.getKey()); + toRemove.add(e.getKey()); } } + + for (AbstractMenuEntry entry : toRemove) + { + swaps.remove(entry); + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java index 9602c34d2b..b7798d2b43 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/shiftwalker/ShiftWalkerPlugin.java @@ -48,7 +48,7 @@ import net.runelite.client.plugins.PluginType; public class ShiftWalkerPlugin extends Plugin { - private static final String WALK_HERE = "WALK HERE"; + private static final String WALK_HERE = "Walk here"; @Inject private ShiftWalkerConfig config; @@ -91,11 +91,11 @@ public class ShiftWalkerPlugin extends Plugin void startPrioritizing() { - menuManager.addPriorityEntry(WALK_HERE, ""); + menuManager.addPriorityEntry(WALK_HERE); } void stopPrioritizing() { - menuManager.removePriorityEntry(WALK_HERE, ""); + menuManager.removePriorityEntry(WALK_HERE); } } diff --git a/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java b/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java index e98c3d1dd3..1e7135e3ab 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java @@ -33,6 +33,7 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.MenuEntry; +@Deprecated @Slf4j public class MenuUtil { From b2ef6f99576732c1b3ada9f5289d8c994cd3d246 Mon Sep 17 00:00:00 2001 From: Scott Burns Date: Mon, 20 May 2019 18:01:52 +0200 Subject: [PATCH 68/78] Ground markers color groups --- .../groundmarkers/GroundMarkerConfig.java | 65 ++++-- .../GroundMarkerMinimapOverlay.java | 28 ++- .../groundmarkers/GroundMarkerOverlay.java | 49 +++-- .../groundmarkers/GroundMarkerPlugin.java | 187 +++++++++++++----- .../groundmarkers/GroundMarkerPoint.java | 30 ++- ...arker.java => GroundMarkerWorldPoint.java} | 11 +- 6 files changed, 267 insertions(+), 103 deletions(-) rename runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/{ColorTileMarker.java => GroundMarkerWorldPoint.java} (84%) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java index bc2a65f0d9..21969ec2c3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java @@ -23,6 +23,7 @@ * (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.groundmarkers; import java.awt.Color; @@ -30,6 +31,7 @@ import net.runelite.client.config.Alpha; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; @ConfigGroup("groundMarker") public interface GroundMarkerConfig extends Config @@ -37,31 +39,68 @@ public interface GroundMarkerConfig extends Config @Alpha @ConfigItem( keyName = "markerColor", - name = "Color of the tile", - description = "Configures the color of marked tile" + name = "Default Marked tile Color", + description = "Configures the default color of marked tiles" ) default Color markerColor() { return Color.YELLOW; } + @Alpha @ConfigItem( - keyName = "rememberTileColors", - name = "Remember color per tile", - description = "Color tiles using the color from time of placement" + keyName = "markerColor2", + name = "Group 2 tile color", + description = "Configures the color of the 2nd group of marked tiles" ) - default boolean rememberTileColors() + default Color markerColor2() + { + return Color.RED; + } + + @Alpha + @ConfigItem( + keyName = "markerColor3", + name = "Group 3 tile color", + description = "Configures the color of the 3rd group of marked tiles" + ) + default Color markerColor3() + { + return Color.BLUE; + } + + @Alpha + @ConfigItem( + keyName = "markerColor4", + name = "Group 4 tile color", + description = "Configures the color of the 4th group of marked tiles" + ) + default Color markerColor4() + { + return Color.GREEN; + } + + @ConfigItem( + keyName = "showMinimap", + name = "Show on minimap", + description = "Shows marked tiles on the minimap" + ) + default boolean showMinimap() { return false; } - @ConfigItem( - keyName = "drawOnMinimap", - name = "Draw tiles on minimap", - description = "Configures whether marked tiles should be drawn on minimap" + @Range( + min = 1, + max = 100 ) - default boolean drawTileOnMinimmap() + @ConfigItem( + keyName = "minimapOpacity", + name = "Minimap opacity", + description = "The opacity of the minimap markers" + ) + default int minimapOverlayOpacity() { - return false; + return 100; } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerMinimapOverlay.java index 04a762242e..4e53a7d966 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerMinimapOverlay.java @@ -27,7 +27,8 @@ package net.runelite.client.plugins.groundmarkers; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.util.Collection; +import static java.lang.Math.floor; +import java.util.List; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.Perspective; @@ -64,13 +65,13 @@ class GroundMarkerMinimapOverlay extends Overlay @Override public Dimension render(Graphics2D graphics) { - if (!config.drawTileOnMinimmap()) + if (!config.showMinimap()) { return null; } - final Collection points = plugin.getPoints(); - for (final ColorTileMarker point : points) + final List points = plugin.getPoints(); + for (final GroundMarkerWorldPoint point : points) { WorldPoint worldPoint = point.getWorldPoint(); if (worldPoint.getPlane() != client.getPlane()) @@ -78,13 +79,22 @@ class GroundMarkerMinimapOverlay extends Overlay continue; } - Color tileColor = point.getColor(); - if (tileColor == null || !config.rememberTileColors()) + Color color = config.markerColor(); + switch (point.getGroundMarkerPoint().getGroup()) { - // If this is an old tile which has no color, or rememberTileColors is off, use marker color - tileColor = config.markerColor(); + case 2: + color = config.markerColor2(); + break; + case 3: + color = config.markerColor3(); + break; + case 4: + color = config.markerColor4(); } + int opacity = (int) floor(config.minimapOverlayOpacity() * 2.55); + Color tileColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), opacity); + drawOnMinimap(graphics, worldPoint, tileColor); } @@ -114,4 +124,4 @@ class GroundMarkerMinimapOverlay extends Overlay OverlayUtil.renderMinimapRect(client, graphics, posOnMinimap, TILE_WIDTH, TILE_HEIGHT, color); } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java index ec1814bde4..f2760fc287 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java @@ -29,7 +29,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; -import java.util.Collection; +import java.util.List; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.Perspective; @@ -43,6 +43,7 @@ import net.runelite.client.ui.overlay.OverlayUtil; public class GroundMarkerOverlay extends Overlay { + private static final int MAX_DRAW_DISTANCE = 32; private final Client client; private final GroundMarkerConfig config; @@ -62,30 +63,28 @@ public class GroundMarkerOverlay extends Overlay @Override public Dimension render(Graphics2D graphics) { - final Collection points = plugin.getPoints(); - for (final ColorTileMarker point : points) + List points = plugin.getPoints(); + for (GroundMarkerWorldPoint groundMarkerWorldPoint : points) { - WorldPoint worldPoint = point.getWorldPoint(); - if (worldPoint.getPlane() != client.getPlane()) - { - continue; - } - - Color tileColor = point.getColor(); - if (tileColor == null || !config.rememberTileColors()) - { - // If this is an old tile which has no color, or rememberTileColors is off, use marker color - tileColor = config.markerColor(); - } - - drawTile(graphics, worldPoint, tileColor); + drawTile(graphics, groundMarkerWorldPoint); } return null; } - private void drawTile(Graphics2D graphics, WorldPoint point, Color color) + private void drawTile(Graphics2D graphics, GroundMarkerWorldPoint groundMarkerWorldPoint) { + WorldPoint point = groundMarkerWorldPoint.getWorldPoint(); + if (point.getPlane() != client.getPlane()) + { + return; + } + + WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); + if (point.distanceTo(playerLocation) >= MAX_DRAW_DISTANCE) + { + return; + } LocalPoint lp = LocalPoint.fromWorld(client, point); if (lp == null) @@ -99,6 +98,18 @@ public class GroundMarkerOverlay extends Overlay return; } + Color color = config.markerColor(); + switch (groundMarkerWorldPoint.getGroundMarkerPoint().getGroup()) + { + case 2: + color = config.markerColor2(); + break; + case 3: + color = config.markerColor3(); + break; + case 4: + color = config.markerColor4(); + } OverlayUtil.renderPolygon(graphics, poly, color); } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index 180fdc6bfc..e1282fd160 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -34,13 +34,16 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import static net.runelite.api.Constants.CHUNK_SIZE; import net.runelite.api.GameState; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; @@ -68,6 +71,8 @@ public class GroundMarkerPlugin extends Plugin { private static final String CONFIG_GROUP = "groundMarker"; private static final String MARK = "Mark tile"; + private static final Pattern GROUP_MATCHER = Pattern.compile(".*ark tile \\(Group (\\d)\\)"); + private static final String UNMARK = "Unmark tile"; private static final String WALK_HERE = "Walk here"; private static final String REGION_PREFIX = "region_"; @@ -78,14 +83,11 @@ public class GroundMarkerPlugin extends Plugin private boolean hotKeyPressed; @Getter(AccessLevel.PACKAGE) - private final List points = new ArrayList<>(); + private final List points = new ArrayList<>(); @Inject private Client client; - @Inject - private GroundMarkerConfig config; - @Inject private GroundMarkerInputListener inputListener; @@ -123,12 +125,11 @@ public class GroundMarkerPlugin extends Plugin { return Collections.emptyList(); } + return GSON.fromJson(json, new GroundMarkerListTypeToken().getType()); + } - // CHECKSTYLE:OFF - return GSON.fromJson(json, new TypeToken>() - { - }.getType()); - // CHECKSTYLE:ON + private static class GroundMarkerListTypeToken extends TypeToken> + { } @Provides @@ -153,35 +154,100 @@ public class GroundMarkerPlugin extends Plugin // load points for region log.debug("Loading points for region {}", regionId); Collection regionPoints = getPoints(regionId); - Collection colorTileMarkers = translateToColorTileMarker(regionPoints); - points.addAll(colorTileMarkers); + Collection worldPoints = translateToWorld(regionPoints); + points.addAll(worldPoints); } } /** - * Translate a collection of ground marker points to color tile markers, accounting for instances + * Translate a collection of ground marker points to world points, accounting for instances * - * @param points {@link GroundMarkerPoint}s to be converted to {@link ColorTileMarker}s - * @return A collection of color tile markers, converted from the passed ground marker points, accounting for local - * instance points. See {@link WorldPoint#toLocalInstance(Client, WorldPoint)} + * @param points + * @return */ - private Collection translateToColorTileMarker(Collection points) + private Collection translateToWorld(Collection points) { if (points.isEmpty()) { - return Collections.emptyList(); + return Collections.EMPTY_LIST; } - return points.stream() - .map(point -> new ColorTileMarker( - WorldPoint.fromRegion(point.getRegionId(), point.getRegionX(), point.getRegionY(), point.getZ()), - point.getColor())) - .flatMap(colorTile -> + List worldPoints = new ArrayList<>(); + for (GroundMarkerPoint point : points) + { + int regionId = point.getRegionId(); + int regionX = point.getRegionX(); + int regionY = point.getRegionY(); + int z = point.getZ(); + + WorldPoint worldPoint = WorldPoint.fromRegion(regionId, regionX, regionY, z); + + if (!client.isInInstancedRegion()) { - final Collection localWorldPoints = WorldPoint.toLocalInstance(client, colorTile.getWorldPoint()); - return localWorldPoints.stream().map(wp -> new ColorTileMarker(wp, colorTile.getColor())); - }) - .collect(Collectors.toList()); + worldPoints.add(new GroundMarkerWorldPoint(point, worldPoint)); + continue; + } + + // find instance chunks using the template point. there might be more than one. + int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); + for (int x = 0; x < instanceTemplateChunks[z].length; ++x) + { + for (int y = 0; y < instanceTemplateChunks[z][x].length; ++y) + { + int chunkData = instanceTemplateChunks[z][x][y]; + int rotation = chunkData >> 1 & 0x3; + int templateChunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; + int templateChunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; + if (worldPoint.getX() >= templateChunkX && worldPoint.getX() < templateChunkX + CHUNK_SIZE + && worldPoint.getY() >= templateChunkY && worldPoint.getY() < templateChunkY + CHUNK_SIZE) + { + WorldPoint p = new WorldPoint(client.getBaseX() + x * CHUNK_SIZE + (worldPoint.getX() & (CHUNK_SIZE - 1)), + client.getBaseY() + y * CHUNK_SIZE + (worldPoint.getY() & (CHUNK_SIZE - 1)), + worldPoint.getPlane()); + p = rotate(p, rotation); + worldPoints.add(new GroundMarkerWorldPoint(point, p)); + } + } + } + } + return worldPoints; + } + + /** + * Rotate the chunk containing the given point to rotation 0 + * + * @param point point + * @param rotation rotation + * @return world point + */ + private static WorldPoint rotateInverse(WorldPoint point, int rotation) + { + return rotate(point, 4 - rotation); + } + + /** + * Rotate the coordinates in the chunk according to chunk rotation + * + * @param point point + * @param rotation rotation + * @return world point + */ + private static WorldPoint rotate(WorldPoint point, int rotation) + { + int chunkX = point.getX() & ~(CHUNK_SIZE - 1); + int chunkY = point.getY() & ~(CHUNK_SIZE - 1); + int x = point.getX() & (CHUNK_SIZE - 1); + int y = point.getY() & (CHUNK_SIZE - 1); + switch (rotation) + { + case 1: + return new WorldPoint(chunkX + y, chunkY + (CHUNK_SIZE - 1 - x), point.getPlane()); + case 2: + return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - x), chunkY + (CHUNK_SIZE - 1 - y), point.getPlane()); + case 3: + return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - y), chunkY + x, point.getPlane()); + } + return point; } @Subscribe @@ -210,34 +276,59 @@ public class GroundMarkerPlugin extends Plugin { if (hotKeyPressed && event.getOption().equals(WALK_HERE)) { - // Can't insert into abstract list you get from Arrays.asList() - List menuEntries = new ArrayList<>(Arrays.asList(client.getMenuEntries())); + MenuEntry[] menuEntries = client.getMenuEntries(); + int lastIndex = menuEntries.length; + menuEntries = Arrays.copyOf(menuEntries, lastIndex + 4); - MenuEntry menuEntry = new MenuEntry(); + final Tile tile = client.getSelectedSceneTile(); + if (tile == null) + { + return; + } + final WorldPoint loc = WorldPoint.fromLocalInstance(client, tile.getLocalLocation()); + final int regionId = loc.getRegionID(); - menuEntry.setOption(MARK); - menuEntry.setTarget(event.getTarget()); - menuEntry.setType(MenuAction.CANCEL.getId()); + for (int i = 4; i > 0; i--) + { + MenuEntry menuEntry = menuEntries[lastIndex] = new MenuEntry(); - menuEntries.add(menuEntries.size() - 1, menuEntry); - client.setMenuEntries(menuEntries.toArray(new MenuEntry[0])); + final GroundMarkerPoint point = new GroundMarkerPoint(regionId, loc.getRegionX(), loc.getRegionY(), client.getPlane(), i); + final Optional stream = getPoints(regionId).stream().filter(x -> x.equals(point)).findAny(); + final String option = (stream.isPresent() && stream.get().getGroup() == i) ? UNMARK : MARK; + + menuEntry.setOption(option + (i == 1 ? "" : " (Group " + i + ")")); + menuEntry.setTarget(event.getTarget()); + menuEntry.setType(MenuAction.CANCEL.getId()); + + lastIndex++; + } + + client.setMenuEntries(menuEntries); } } @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { - if (!event.getMenuOption().equals(MARK)) + if (!event.getMenuOption().contains(MARK) && !event.getMenuOption().contains(UNMARK)) { return; } + int group = 1; + Matcher m = GROUP_MATCHER.matcher(event.getMenuOption()); + if (m.matches()) + { + group = Integer.parseInt(m.group(1)); + } + Tile target = client.getSelectedSceneTile(); + if (target == null) { return; } - markTile(target.getLocalLocation()); + markTile(target.getLocalLocation(), group); } @Override @@ -258,7 +349,7 @@ public class GroundMarkerPlugin extends Plugin points.clear(); } - private void markTile(LocalPoint localPoint) + protected void markTile(LocalPoint localPoint, int group) { if (localPoint == null) { @@ -268,21 +359,27 @@ public class GroundMarkerPlugin extends Plugin WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, localPoint); int regionId = worldPoint.getRegionID(); - GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), config.markerColor()); + GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), group); log.debug("Updating point: {} - {}", point, worldPoint); - List groundMarkerPoints = new ArrayList<>(getPoints(regionId)); - if (groundMarkerPoints.contains(point)) + List points = new ArrayList<>(getPoints(regionId)); + if (points.contains(point)) { - groundMarkerPoints.remove(point); + GroundMarkerPoint old = points.get(points.indexOf(point)); + points.remove(point); + + if (old.getGroup() != group) + { + points.add(point); + } } else { - groundMarkerPoints.add(point); + points.add(point); } - savePoints(regionId, groundMarkerPoints); + savePoints(regionId, points); loadPoints(); } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java index 53dce275ff..247c1e17dd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java @@ -23,22 +23,34 @@ * (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.groundmarkers; -import java.awt.Color; -import lombok.EqualsAndHashCode; import lombok.Value; -/** - * Used for serialization of ground marker points. - */ @Value -@EqualsAndHashCode(exclude = {"color"}) -class GroundMarkerPoint +public class GroundMarkerPoint { private int regionId; private int regionX; private int regionY; private int z; - private Color color; -} + private int group; + + @Override + public String toString() + { + return "GroundMarkerPoint(regionId=" + regionId + ",regionX=" + regionX + ",=regionY" + regionY + ",z=" + z + ")"; + } + + @Override + public boolean equals(Object o) + { + if (!(o instanceof GroundMarkerPoint)) + { + return false; + } + + return o.toString().equals(this.toString()); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/ColorTileMarker.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerWorldPoint.java similarity index 84% rename from runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/ColorTileMarker.java rename to runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerWorldPoint.java index 6a6a30a065..9ea9915459 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/ColorTileMarker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerWorldPoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Jordan Atwood + * Copyright (c) 2018, TheStonedTurtle * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,17 +24,12 @@ */ package net.runelite.client.plugins.groundmarkers; -import java.awt.Color; import lombok.Value; import net.runelite.api.coords.WorldPoint; -/** - * Used to denote marked tiles and their colors. - * Note: This is not used for serialization of ground markers; see {@link GroundMarkerPoint} - */ @Value -class ColorTileMarker +public class GroundMarkerWorldPoint { + private GroundMarkerPoint groundMarkerPoint; private WorldPoint worldPoint; - private Color color; } From 02cbe0d1a64d3be89c2de724e569fbcf0626705a Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 20 May 2019 18:05:40 +0200 Subject: [PATCH 69/78] Add option to type bank pin --- .../net/runelite/api/widgets/WidgetID.java | 18 ++ .../net/runelite/api/widgets/WidgetInfo.java | 16 +- .../runeliteplus/RuneLitePlusConfig.java | 10 + .../runeliteplus/RuneLitePlusPlugin.java | 173 +++++++++++++++++- 4 files changed, 215 insertions(+), 2 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index 12fe00ed39..22bd9731d4 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -41,6 +41,7 @@ public class WidgetID public static final int LOGOUT_PANEL_ID = 182; public static final int BANK_GROUP_ID = 12; public static final int BANK_INVENTORY_GROUP_ID = 15; + public static final int BANK_PIN_GROUP_ID = 213; public static final int GRAND_EXCHANGE_INVENTORY_GROUP_ID = 467; public static final int GRAND_EXCHANGE_GROUP_ID = 465; public static final int DEPOSIT_BOX_GROUP_ID = 192; @@ -353,6 +354,7 @@ public class WidgetID static final int MINIMAP = 3; static final int MINIMAP_DRAW_AREA = 8; static final int MULTICOMBAT_INDICATOR = 20; + static final int BANK_PIN = 21; static final int CLAN_CHAT_TAB = 31; static final int FRIENDS_TAB = 33; static final int IGNORES_TAB = 32; @@ -390,6 +392,7 @@ public class WidgetID static class ResizableViewport { static final int ITEMS_KEPT_ON_DEATH = 13; + static final int BANK_PIN = 13; static final int MULTICOMBAT_INDICATOR = 16; static final int CLAN_CHAT_TAB = 35; static final int FRIENDS_TAB = 37; @@ -425,6 +428,7 @@ public class WidgetID static class ResizableViewportBottomLine { + static final int BANK_PIN = 13; static final int LOGOUT_BUTTON_OVERLAY = 29; static final int CMB_TAB = 50; static final int CMB_ICON = 57; @@ -1062,4 +1066,18 @@ public class WidgetID public static final int TOTAL_TAX = 39; public static final int WINNINGS = 40; } + + public static class BankPin + { + public static final int BUTTON_1 = 16; + public static final int BUTTON_2 = 18; + public static final int BUTTON_3 = 20; + public static final int BUTTON_4 = 22; + public static final int BUTTON_5 = 24; + public static final int BUTTON_6 = 26; + public static final int BUTTON_7 = 28; + public static final int BUTTON_8 = 30; + public static final int BUTTON_9 = 32; + public static final int BUTTON_0 = 34; + } } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index a059fd9d49..9f6f929952 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -705,7 +705,21 @@ public enum WidgetInfo ITEMS_KEPT_SAFE_ZONE_CONTAINER(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.SAFE_ZONE_CONTAINER), ITEMS_KEPT_CUSTOM_TEXT_CONTAINER(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.CUSTOM_TEXT_CONTAINER), ITEMS_LOST_VALUE(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.LOST_ITEMS_VALUE), - ITEMS_KEPT_MAX(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.MAX_ITEMS_KEPT_ON_DEATH); + ITEMS_KEPT_MAX(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.MAX_ITEMS_KEPT_ON_DEATH), + + FIXED_BANK_PIN(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.FixedViewport.BANK_PIN), + RESIZABLE_BANK_PIN(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.ResizableViewport.BANK_PIN), + RESIZABLE_BOTTOM_LINE_BANK_PIN(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.BANK_PIN), + BANK_PIN_1(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_1), + BANK_PIN_2(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_2), + BANK_PIN_3(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_3), + BANK_PIN_4(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_4), + BANK_PIN_5(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_5), + BANK_PIN_6(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_6), + BANK_PIN_7(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_7), + BANK_PIN_8(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_8), + BANK_PIN_9(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_9), + BANK_PIN_0(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_0); private final int groupId; private final int childId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java index 7e666c19b2..8db739148c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java @@ -71,4 +71,14 @@ public interface RuneLitePlusConfig extends Config return 100; } + @ConfigItem( + keyName = "keyboardPin", + name = "Keyboard bank pin", + description = "Enables you to type your bank pin", + position = 3 + ) + default boolean keyboardPin() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java index 72c638588c..5be13a27c2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java @@ -27,18 +27,32 @@ package net.runelite.client.plugins.runeliteplus; +import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.util.Map; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.MenuAction; import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.RuneLiteProperties; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.discord.DiscordService; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.ui.ClientUI; +import org.apache.commons.lang3.ArrayUtils; @PluginDescriptor( loadWhenOutdated = true, // prevent users from disabling @@ -51,9 +65,63 @@ import net.runelite.client.ui.ClientUI; @Slf4j public class RuneLitePlusPlugin extends Plugin { + private class RuneLitePlusKeyListener implements KeyListener + { + private int lastKeyCycle; + + @Override + public void keyTyped(KeyEvent keyEvent) + { + if (!isNumber(keyEvent)) + { + return; + } + + if (client.getGameCycle() - lastKeyCycle <= 5) + { + keyEvent.consume(); + return; + } + + lastKeyCycle = client.getGameCycle(); + + clientThread.invoke(() -> handleKey(keyEvent.getKeyChar())); + keyEvent.consume(); + } + + @Override + public void keyPressed(KeyEvent keyEvent) + { + } + + @Override + public void keyReleased(KeyEvent keyEvent) + { + } + + private boolean isNumber(KeyEvent keyEvent) + { + char character = keyEvent.getKeyChar(); + return ArrayUtils.contains(numbers, character); + } + } + + private static final ImmutableSet buttons = ImmutableSet.of( + WidgetInfo.BANK_PIN_1, + WidgetInfo.BANK_PIN_2, + WidgetInfo.BANK_PIN_3, + WidgetInfo.BANK_PIN_4, + WidgetInfo.BANK_PIN_5, + WidgetInfo.BANK_PIN_6, + WidgetInfo.BANK_PIN_7, + WidgetInfo.BANK_PIN_8, + WidgetInfo.BANK_PIN_9, + WidgetInfo.BANK_PIN_0 + ); public static boolean customPresenceEnabled = false; public static final String rlPlusDiscordApp = "560644885250572289"; public static final String rlDiscordApp = "409416265891971072"; + private static final char[] numbers = "0123456789".toCharArray(); @Inject public RuneLitePlusConfig config; @@ -64,6 +132,14 @@ public class RuneLitePlusPlugin extends Plugin @Inject public DiscordService discordService; + @Inject + private KeyManager keyManager; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; @Provides RuneLitePlusConfig getConfig(ConfigManager configManager) @@ -71,6 +147,8 @@ public class RuneLitePlusPlugin extends Plugin return configManager.getConfig(RuneLitePlusConfig.class); } + private RuneLitePlusKeyListener keyListener; + @Override protected void startUp() throws Exception { @@ -122,13 +200,106 @@ public class RuneLitePlusPlugin extends Plugin discordService.close(); discordService.init(); } + + if (!config.keyboardPin()) + { + keyManager.unregisterKeyListener(keyListener); + } } } @Override protected void shutDown() throws Exception { - + keyManager.unregisterKeyListener(keyListener); } + @Subscribe + public void onWidgetLoaded(WidgetLoaded event) + { + if (!config.keyboardPin()) + { + return; + } + + if (event.getGroupId() == WidgetID.BANK_GROUP_ID) + { + // log.debug("Bank opened, removing key listener"); + keyManager.unregisterKeyListener(keyListener); + return; + } + else if (event.getGroupId() != WidgetID.BANK_PIN_GROUP_ID) + { + return; + } + + // log.debug("Registering key listener"); + keyListener = new RuneLitePlusKeyListener(); + keyManager.registerKeyListener(keyListener); + } + + private void handleKey(char c) + { + if (client.getWidget(WidgetID.BANK_PIN_GROUP_ID, 0) == null) + { + // log.debug("Key was pressed, but widget wasn't open"); + keyManager.unregisterKeyListener(keyListener); + return; + } + + Map buttonMap = new HashMap<>(); + Widget unknown = null; + + for (WidgetInfo w : buttons) + { + Widget widget = client.getWidget(w); + + if (widget == null) + { + // log.debug(w.toString() + " is null, returning early"); + continue; + } + else if (widget.getChild(1) == null || widget.getChild(1).isHidden()) + { + // log.debug(widget.getId() + " wasn't null, but either the text was missing or child was null"); + unknown = widget; + } + else + { + try + { + char number = widget.getChild(1).getText().charAt(0); + buttonMap.put(number, widget); + // log.debug(number + " is widget " + widget.getId()); + } + catch (IndexOutOfBoundsException e) + { + // log.debug("There was no text in widget " + widget.getId()); + unknown = widget; + } + } + } + + if (unknown != null && buttonMap.size() == 9) + { + for (char num : numbers) + { + if (!buttonMap.containsKey(num)) + { + // log.debug(num + " must be the unknown char for widget " + unknown.getId()); + buttonMap.put(num, unknown); + } + } + } + + if (buttonMap.size() != 10) + { + // log.debug("We didn't have 10 numbers, rip"); + return; + } + + Widget w = buttonMap.get(c); + + client.invokeMenuAction(0, w.getId(), MenuAction.WIDGET_DEFAULT.getId(), 1, "Select", "", w.getCanvasLocation().getX() + 32, w.getCanvasLocation().getY() + 32); + } } From e633bb89c02da9a0c1118fc8c5678170653625c0 Mon Sep 17 00:00:00 2001 From: Scott Burns Date: Mon, 20 May 2019 18:06:55 +0200 Subject: [PATCH 70/78] Mark / umark, tag / untag --- .../net/runelite/client/callback/Hooks.java | 13 ++++++ .../npchighlight/NpcIndicatorsPlugin.java | 7 ++- .../ObjectIndicatorsPlugin.java | 44 ++++++++++++++++++- .../tileindicators/TileIndicatorsOverlay.java | 13 ------ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index efe003367b..519adacadb 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -45,6 +45,7 @@ import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.MainBufferProvider; import net.runelite.api.NullItemID; +import net.runelite.api.Point; import net.runelite.api.RenderOverview; import net.runelite.api.Renderable; import net.runelite.api.WorldMapManager; @@ -396,6 +397,18 @@ public class Hooks implements Callbacks BufferedImage image = (BufferedImage) bufferProvider.getImage(); Graphics2D graphics2d = image.createGraphics(); + // Update selected scene tile + if (!client.isMenuOpen()) + { + Point p = client.getMouseCanvasPosition(); + p = new Point( + p.getX() - client.getViewportXOffset(), + p.getY() - client.getViewportYOffset()); + + client.setCheckClick(true); + client.setMouseCanvasHoverPosition(p); + } + try { renderer.render(graphics2d, OverlayLayer.ABOVE_SCENE); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java index 1e114c453c..14ccc92d17 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java @@ -82,6 +82,7 @@ public class NpcIndicatorsPlugin extends Plugin // Option added to NPC menu private static final String TAG = "Tag"; + private static final String UNTAG = "Untag"; private static final Set NPC_MENU_ACTIONS = ImmutableSet.of(MenuAction.NPC_FIRST_OPTION, MenuAction.NPC_SECOND_OPTION, MenuAction.NPC_THIRD_OPTION, MenuAction.NPC_FOURTH_OPTION, MenuAction.NPC_FIFTH_OPTION); @@ -271,7 +272,7 @@ public class NpcIndicatorsPlugin extends Plugin // Add tag option menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); final MenuEntry tagEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - tagEntry.setOption(TAG); + tagEntry.setOption(npcTags.contains(event.getIdentifier()) ? UNTAG : TAG); tagEntry.setTarget(event.getTarget()); tagEntry.setParam0(event.getActionParam0()); tagEntry.setParam1(event.getActionParam1()); @@ -284,7 +285,9 @@ public class NpcIndicatorsPlugin extends Plugin @Subscribe public void onMenuOptionClicked(MenuOptionClicked click) { - if (click.getMenuAction() != MenuAction.RUNELITE || !click.getMenuOption().equals(TAG)) + if (click.getMenuAction() != MenuAction.RUNELITE + || (!click.getMenuOption().equals(TAG) + && !click.getMenuOption().equals(UNTAG))) { return; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java index 3ab1377b8a..604c3fb065 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java @@ -80,6 +80,7 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener { private static final String CONFIG_GROUP = "objectindicators"; private static final String MARK = "Mark object"; + private static final String UNMARK = "Unmark object"; private final Gson GSON = new Gson(); @Getter(AccessLevel.PACKAGE) @@ -221,7 +222,44 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener MenuEntry[] menuEntries = client.getMenuEntries(); menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - menuEntry.setOption(MARK); + + String option = MARK; + + Scene scene = client.getScene(); + Tile[][][] tiles = scene.getTiles(); + final int x = event.getActionParam0(); + final int y = event.getActionParam1(); + final int z = client.getPlane(); + final Tile tile = tiles[z][x][y]; + final TileObject object = findTileObject(tile, event.getIdentifier()); + if (object != null) + { + final ObjectComposition objectDefinition = client.getObjectDefinition(object.getId()); + final String name = objectDefinition.getName(); + + if (!Strings.isNullOrEmpty(name)) + { + final WorldPoint loc = WorldPoint.fromLocalInstance(client, tile.getLocalLocation()); + final int regionId = loc.getRegionID(); + + final ObjectPoint point = new ObjectPoint( + name, + regionId, + loc.getX() & (REGION_SIZE - 1), + loc.getY() & (REGION_SIZE - 1), + client.getPlane()); + + final Set objectPoints = points.get(regionId); + + if (objectPoints != null && objectPoints.contains(point)) + { + option = UNMARK; + } + } + } + + menuEntry.setOption(option); + menuEntry.setTarget(event.getTarget()); menuEntry.setParam0(event.getActionParam0()); menuEntry.setParam1(event.getActionParam1()); @@ -233,7 +271,9 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { - if (event.getMenuAction() != MenuAction.RUNELITE || !event.getMenuOption().equals(MARK)) + if (event.getMenuAction() != MenuAction.RUNELITE + || (!event.getMenuOption().equals(MARK) + && !event.getMenuOption().equals(UNMARK))) { return; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java index a9e983656d..00e89241c3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java @@ -31,7 +31,6 @@ import java.awt.Polygon; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.Perspective; -import net.runelite.api.Point; import net.runelite.api.coords.LocalPoint; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; @@ -59,18 +58,6 @@ public class TileIndicatorsOverlay extends Overlay { if (config.highlightHoveredTile()) { - // Update selected scene tile - if (!client.isMenuOpen()) - { - Point p = client.getMouseCanvasPosition(); - p = new Point( - p.getX() - client.getViewportXOffset(), - p.getY() - client.getViewportYOffset()); - - client.setCheckClick(true); - client.setMouseCanvasHoverPosition(p); - } - // If we have tile "selected" render it if (client.getSelectedSceneTile() != null) { From 1a7cc1eeaa71a113bf97d452a7b43a44c64c3d1b Mon Sep 17 00:00:00 2001 From: sdburns1998 <49877861+sdburns1998@users.noreply.github.com> Date: Mon, 20 May 2019 18:29:05 +0200 Subject: [PATCH 71/78] Jslider (#325) * JSlider changes * Check style ConfigPanel --- .../client/plugins/cannon/CannonConfig.java | 4 ++++ .../client/plugins/config/ConfigPanel.java | 16 ++++++++++++---- .../EquipmentInspectorConfig.java | 7 ++++++- .../runelite/client/plugins/fps/FpsConfig.java | 5 +++++ .../runelite/client/plugins/zoom/ZoomConfig.java | 4 ++-- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java index 15f50725e6..c832ded86b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java @@ -29,6 +29,7 @@ import net.runelite.client.config.Alpha; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; @ConfigGroup("cannon") public interface CannonConfig extends Config @@ -84,6 +85,9 @@ public interface CannonConfig extends Config return true; } + @Range( + max = 29 + ) @ConfigItem( keyName = "ammoAmount", name = "Ammo left", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 276be04829..7874ad29b9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -75,8 +75,8 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigDescriptor; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.ConfigItemsGroup; import net.runelite.client.config.ConfigItemDescriptor; +import net.runelite.client.config.ConfigItemsGroup; import net.runelite.client.config.ConfigManager; import net.runelite.client.config.Keybind; import net.runelite.client.config.ModifierlessKeybind; @@ -430,11 +430,13 @@ public class ConfigPanel extends PluginPanel JLabel headerLabel = new JLabel(header); headerLabel.setForeground(Color.ORANGE); - headerLabel.setPreferredSize(new Dimension(PANEL_WIDTH, (int)headerLabel.getPreferredSize().getHeight())); + headerLabel.setPreferredSize(new Dimension(PANEL_WIDTH, (int) headerLabel.getPreferredSize().getHeight())); String sCollapsed = configManager.getConfiguration(cd.getGroup().value(), cig.getGroup() + "_collapse"); if (sCollapsed != null) + { collapsed = Boolean.parseBoolean(sCollapsed); + } JButton collapse = new JButton(collapsed ? "+" : "-"); collapse.setPreferredSize(new Dimension(20, 20)); @@ -451,7 +453,9 @@ public class ConfigPanel extends PluginPanel } if (collapsed) + { continue; + } for (ConfigItemDescriptor cid : cig.getItems()) { @@ -465,7 +469,7 @@ public class ConfigPanel extends PluginPanel item.setMinimumSize(new Dimension(PANEL_WIDTH, 0)); name = cid.getItem().name(); JLabel configEntryName = new JLabel(name); - configEntryName.setPreferredSize(new Dimension(PANEL_WIDTH, (int)configEntryName.getPreferredSize().getHeight())); + configEntryName.setPreferredSize(new Dimension(PANEL_WIDTH, (int) configEntryName.getPreferredSize().getHeight())); configEntryName.setForeground(Color.WHITE); configEntryName.setToolTipText("" + name + ":
" + cid.getItem().description() + ""); item.add(configEntryName, BorderLayout.CENTER); @@ -499,13 +503,15 @@ public class ConfigPanel extends PluginPanel { JSlider slider = new JSlider(min, max, value); configEntryName.setText(name.concat(": ").concat(String.valueOf(slider.getValue()))); - slider.setPreferredSize(new Dimension(topPanel.getPreferredSize().width, slider.getHeight())); + slider.setPreferredSize(new Dimension(100, 25)); String finalName = name; slider.addChangeListener((l) -> { configEntryName.setText(finalName.concat(": ").concat(String.valueOf(slider.getValue()))); if (!slider.getValueIsAdjusting()) + { changeConfiguration(listItem, config, slider, cd, cid); + } } ); item.add(slider, BorderLayout.EAST); @@ -726,7 +732,9 @@ public class ConfigPanel extends PluginPanel boolean collapse = true; if (sCollapsed != null) + { collapse = !Boolean.parseBoolean(sCollapsed); + } configManager.setConfiguration(cd.getGroup().value(), cig.getGroup() + "_collapse", collapse); openGroupConfigPanel(listItem, config, cd); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorConfig.java index c88eec0f71..a43592e5d7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.equipmentinspector; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; @ConfigGroup("grounditems") public interface EquipmentInspectorConfig extends Config @@ -42,9 +43,13 @@ public interface EquipmentInspectorConfig extends Config return true; } + @Range( + min = 1, + max = 4 + ) @ConfigItem( keyName = "protecteditems", - name = "# of protected items", + name = "protected items", description = "Limit 4", position = 2 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java index 0627f90354..5f737124ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.fps; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; @ConfigGroup(FpsPlugin.CONFIG_GROUP_KEY) public interface FpsConfig extends Config @@ -42,6 +43,10 @@ public interface FpsConfig extends Config return FpsLimitMode.NEVER; } + @Range( + min = 10, + max = 50 + ) @ConfigItem( keyName = "maxFps", name = "FPS target", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java index 825378cd57..d3fb50007b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java @@ -13,7 +13,7 @@ public interface ZoomConfig extends Config @ConfigItem( keyName = "inner", - name = "Expand inner zoom limit", + name = "Inner limit", description = "Configures whether or not the inner zoom limit is reduced", position = 1 ) @@ -28,7 +28,7 @@ public interface ZoomConfig extends Config ) @ConfigItem( keyName = "outerLimit", - name = "Expand outer zoom limit", + name = "Outer limit", description = "Configures how much the outer zoom limit is adjusted", position = 2 ) From bb55defb5055f709f059e318b11bbfa3b438472c Mon Sep 17 00:00:00 2001 From: sdburns1998 <49877861+sdburns1998@users.noreply.github.com> Date: Mon, 20 May 2019 18:29:46 +0200 Subject: [PATCH 72/78] Ground items (#323) * retrieve ItemLayer height in render rather than on spawn * Ground item timers * Loot notifications --- .../plugins/grounditems/GroundItem.java | 5 ++ .../grounditems/GroundItemsConfig.java | 80 ++++++++++++++--- .../grounditems/GroundItemsOverlay.java | 84 ++++++++++++++++++ .../grounditems/GroundItemsPlugin.java | 85 ++++++++++++++++++- .../grounditems/config/TimerDisplayMode.java | 45 ++++++++++ 5 files changed, 284 insertions(+), 15 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/grounditems/config/TimerDisplayMode.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java index 883d3e9df2..ce66dd8a8f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.grounditems; +import java.time.Instant; import lombok.Builder; import lombok.Data; import lombok.Value; @@ -45,6 +46,10 @@ class GroundItem private int offset; private boolean tradeable; private boolean isMine; + private int durationMillis; + private boolean isAlwaysPrivate; + private boolean isOwnedByPlayer; + private Instant droppedInstant; int getHaPrice() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java index c722b202f0..ffacca5af2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java @@ -32,6 +32,7 @@ import net.runelite.client.config.ConfigItem; import net.runelite.client.plugins.grounditems.config.ItemHighlightMode; import net.runelite.client.plugins.grounditems.config.MenuHighlightMode; import net.runelite.client.plugins.grounditems.config.PriceDisplayMode; +import net.runelite.client.plugins.grounditems.config.TimerDisplayMode; import net.runelite.client.plugins.grounditems.config.ValueCalculationMode; @ConfigGroup("grounditems") @@ -260,11 +261,22 @@ public interface GroundItemsConfig extends Config return 20000; } + @ConfigItem( + keyName = "notifyLowValueDrops", + name = "Notify for low value drops", + description = "Configures whether or not to notify for drops of low value", + position = 19 + ) + default boolean notifyLowValueDrops() + { + return false; + } + @ConfigItem( keyName = "mediumValueColor", name = "Medium value items color", description = "Configures the color for medium value items", - position = 19 + position = 20 ) default Color mediumValueColor() { @@ -275,18 +287,29 @@ public interface GroundItemsConfig extends Config keyName = "mediumValuePrice", name = "Medium value price", description = "Configures the start price for medium value items", - position = 20 + position = 21 ) default int mediumValuePrice() { return 100000; } + @ConfigItem( + keyName = "notifyMediumValueDrops", + name = "Notify for medium value drops", + description = "Configures whether or not to notify for drops of medium value", + position = 22 + ) + default boolean notifyMediumValueDrops() + { + return false; + } + @ConfigItem( keyName = "highValueColor", name = "High value items color", description = "Configures the color for high value items", - position = 21 + position = 23 ) default Color highValueColor() { @@ -297,18 +320,29 @@ public interface GroundItemsConfig extends Config keyName = "highValuePrice", name = "High value price", description = "Configures the start price for high value items", - position = 22 + position = 24 ) default int highValuePrice() { return 1000000; } + @ConfigItem( + keyName = "notifyHighValueDrops", + name = "Notify for high value drops", + description = "Configures whether or not to notify for drops of high value", + position = 25 + ) + default boolean notifyHighValueDrops() + { + return false; + } + @ConfigItem( keyName = "insaneValueColor", name = "Insane value items color", description = "Configures the color for insane value items", - position = 23 + position = 26 ) default Color insaneValueColor() { @@ -319,18 +353,29 @@ public interface GroundItemsConfig extends Config keyName = "insaneValuePrice", name = "Insane value price", description = "Configures the start price for insane value items", - position = 24 + position = 27 ) default int insaneValuePrice() { return 10000000; } + @ConfigItem( + keyName = "notifyInsaneValueDrops", + name = "Notify for insane value drops", + description = "Configures whether or not to notify for drops of insane value", + position = 28 + ) + default boolean notifyInsaneValueDrops() + { + return false; + } + @ConfigItem( keyName = "onlyShowLoot", name = "Only show loot", description = "Only shows drops from NPCs and players", - position = 25 + position = 29 ) default boolean onlyShowLoot() { @@ -341,7 +386,7 @@ public interface GroundItemsConfig extends Config keyName = "doubleTapDelay", name = "Delay for double-tap ALT to hide", description = "Decrease this number if you accidentally hide ground items often. (0 = Disabled)", - position = 26 + position = 30 ) default int doubleTapDelay() { @@ -352,7 +397,7 @@ public interface GroundItemsConfig extends Config keyName = "collapseEntries", name = "Collapse ground item menu entries", description = "Collapses ground item menu entries together and appends count", - position = 27 + position = 31 ) default boolean collapseEntries() { @@ -360,10 +405,10 @@ public interface GroundItemsConfig extends Config } @ConfigItem( - position = 27, keyName = "removeIgnored", name = "Hide Ignored", - description = "Remove take option for items that are on the hidden items list." + description = "Remove take option for items that are on the hidden items list.", + position = 32 ) default boolean removeIgnored() { @@ -374,10 +419,21 @@ public interface GroundItemsConfig extends Config keyName = "toggleOutline", name = "Text Outline", description = "Use an outline around text instead of a text shadow", - position = 29 + position = 33 ) default boolean toggleOutline() { return false; } + + @ConfigItem( + keyName = "showGroundItemDuration", + name = "Show time remaining", + description = "Turn on a countdown timer to show how long an item will remain on the ground", + position = 34 + ) + default TimerDisplayMode showGroundItemDuration() + { + return TimerDisplayMode.HOTKEY_PRESSED; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java index 4d7e2601cd..024d9455b1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java @@ -31,6 +31,8 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; +import java.time.Duration; +import java.time.Instant; import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Collection; @@ -41,15 +43,18 @@ import net.runelite.api.Client; import net.runelite.api.Perspective; import net.runelite.api.Player; import net.runelite.api.Point; +import net.runelite.api.Tile; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.MENU; import net.runelite.client.plugins.grounditems.config.PriceDisplayMode; +import net.runelite.client.plugins.grounditems.config.TimerDisplayMode; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.BackgroundComponent; +import net.runelite.client.ui.overlay.components.ProgressPieComponent; import net.runelite.client.ui.overlay.components.TextComponent; import net.runelite.client.util.StackFormatter; @@ -67,12 +72,20 @@ public class GroundItemsOverlay extends Overlay // Size of the hidden/highlight boxes private static final int RECTANGLE_SIZE = 8; + private static final int TIMER_OVERLAY_DIAMETER = 10; + private static final int PUBLIC_ITEM_DURATION_MILLIS = 60000; + private static final float WARNING_THRESHOLD = 0.25f; + private static final Color PUBLIC_TIMER_COLOR = Color.YELLOW; + private static final Color PRIVATE_TIMER_COLOR = Color.GREEN; + private static final Color PUBLIC_WARNING_TIMER_COLOR = Color.RED; + private final Client client; private final GroundItemsPlugin plugin; private final GroundItemsConfig config; private final StringBuilder itemStringBuilder = new StringBuilder(); private final BackgroundComponent backgroundComponent = new BackgroundComponent(); private final TextComponent textComponent = new TextComponent(); + private final ProgressPieComponent progressPieComponent = new ProgressPieComponent(); private final Map offsetMap = new HashMap<>(); @Inject @@ -259,6 +272,13 @@ public class GroundItemsOverlay extends Overlay final String itemString = itemStringBuilder.toString(); itemStringBuilder.setLength(0); + if (item.getHeight() == -1) + { + final Tile[][][] sceneTiles = client.getScene().getTiles(); + final Tile itemTile = sceneTiles[client.getPlane()][groundPoint.getSceneX()][groundPoint.getSceneY()]; + item.setHeight(itemTile.getItemLayer().getHeight()); + } + final Point textPoint = Perspective.getCanvasTextLocation(client, graphics, groundPoint, @@ -333,6 +353,12 @@ public class GroundItemsOverlay extends Overlay drawRectangle(graphics, itemHighlightBox, topItem && mouseInHighlightBox ? Color.GREEN : color, highlighted != null, false); } + if (config.showGroundItemDuration() == TimerDisplayMode.ALWAYS + || (config.showGroundItemDuration() == TimerDisplayMode.HOTKEY_PRESSED && plugin.isHotKeyPressed())) + { + drawTimerOverlay(graphics, new java.awt.Point(textX, textY), item); + } + if (config.toggleOutline()) { graphics.setColor(Color.BLACK); @@ -388,4 +414,62 @@ public class GroundItemsOverlay extends Overlay } + private void drawTimerOverlay(Graphics2D graphics, java.awt.Point location, GroundItem item) + { + progressPieComponent.setDiameter(TIMER_OVERLAY_DIAMETER); + + int x = (int) location.getX() - TIMER_OVERLAY_DIAMETER; + int y = (int) location.getY() - TIMER_OVERLAY_DIAMETER / 2; + + progressPieComponent.setPosition(new Point(x, y)); + + double millisOnGround = Duration.between(item.getDroppedInstant(), Instant.now()).toMillis(); + boolean isPubliclyVisible = !item.isAlwaysPrivate() && millisOnGround > item.getDurationMillis(); + double timeLeftRelative; + Color fillColor; + + if (isPubliclyVisible || !item.isOwnedByPlayer()) + { + if (item.isOwnedByPlayer()) + { + timeLeftRelative = getTimeLeftRelative(millisOnGround - PUBLIC_ITEM_DURATION_MILLIS, PUBLIC_ITEM_DURATION_MILLIS); + + } + else + { + timeLeftRelative = getTimeLeftRelative(millisOnGround, PUBLIC_ITEM_DURATION_MILLIS); + } + + if (timeLeftRelative < WARNING_THRESHOLD) + { + fillColor = PUBLIC_WARNING_TIMER_COLOR; + } + else + { + fillColor = PUBLIC_TIMER_COLOR; + } + } + else + { + timeLeftRelative = getTimeLeftRelative(millisOnGround, item.getDurationMillis()); + fillColor = PRIVATE_TIMER_COLOR; + + } + + // don't draw timer for any permanently spawned items or broken edge cases + if (timeLeftRelative > 1 || timeLeftRelative < 0) + { + return; + } + + progressPieComponent.setFill(fillColor); + progressPieComponent.setBorderColor(fillColor); + progressPieComponent.setProgress(timeLeftRelative); + progressPieComponent.render(graphics); + } + + private double getTimeLeftRelative(double millisOnGround, int duration) + { + return (duration - millisOnGround) / duration; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java index 35ee979085..3b8a06ec13 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java @@ -31,6 +31,7 @@ import com.google.inject.Provides; import java.awt.Color; import java.awt.Rectangle; import static java.lang.Boolean.TRUE; +import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -99,6 +100,15 @@ public class GroundItemsPlugin extends Plugin private static final float HIGH_ALCHEMY_CONSTANT = 0.6f; // ItemID for coins private static final int COINS = ItemID.COINS_995; + + // items stay on the ground for 30 mins in an instance + private static final int INSTANCE_DURATION_MILLIS = 45 * 60 * 1000; + //untradeables stay on the ground for 150 seconds (http://oldschoolrunescape.wikia.com/wiki/Item#Dropping_and_Destroying) + private static final int UNTRADEABLE_DURATION_MILLIS = 150 * 1000; + //items stay on the ground for 1 hour after death + private static final int DEATH_DURATION_MILLIS = 60 * 60 * 1000; + private static final int NORMAL_DURATION_MILLIS = 60 * 1000; + // Ground item menu options private static final int FIRST_OPTION = MenuAction.GROUND_ITEM_FIRST_OPTION.getId(); private static final int SECOND_OPTION = MenuAction.GROUND_ITEM_SECOND_OPTION.getId(); @@ -280,8 +290,19 @@ public class GroundItemsPlugin extends Plugin @Subscribe public void onNpcLootReceived(NpcLootReceived npcLootReceived) { + npcLootReceived.getItems().forEach(item -> + { + GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), npcLootReceived.getNpc().getWorldLocation()); + if (collectedGroundItems.containsKey(groundItemKey)) + { + collectedGroundItems.get(groundItemKey).setOwnedByPlayer(true); + } + } + ); + Collection items = npcLootReceived.getItems(); lootReceived(items); + lootNotifier(items); } @Subscribe @@ -289,6 +310,47 @@ public class GroundItemsPlugin extends Plugin { Collection items = playerLootReceived.getItems(); lootReceived(items); + lootNotifier(items); + } + + private void lootNotifier(Collection items) + { + ItemComposition composition; + for (ItemStack is : items) + { + composition = itemManager.getItemComposition(is.getId()); + Color itemColor = getHighlighted(composition.getName(), itemManager.getItemPrice(is.getId()) * is.getQuantity(), Math.round(composition.getPrice() * HIGH_ALCHEMY_CONSTANT) * is.getQuantity()); + if (itemColor != null) + { + if (config.notifyHighlightedDrops() && itemColor.equals(config.highlightedColor())) + { + sendLootNotification(composition.getName(), "highlighted"); + } + else if (config.notifyLowValueDrops() && itemColor.equals(config.lowValueColor())) + { + sendLootNotification(composition.getName(), "low value"); + } + else if (config.notifyMediumValueDrops() && itemColor.equals(config.mediumValueColor())) + { + sendLootNotification(composition.getName(), "medium value"); + } + else if (config.notifyHighValueDrops() && itemColor.equals(config.highValueColor())) + { + sendLootNotification(composition.getName(), "high value"); + } + else if (config.notifyInsaneValueDrops() && itemColor.equals(config.insaneValueColor())) + { + sendLootNotification(composition.getName(), "insane value"); + } + } + } + } + + private void sendLootNotification(String itemName, String message) + { + String notification = "[" + client.getLocalPlayer().getName() + "] " + + "Received a " + message + " item: " + itemName; + notifier.notify(notification); } @Subscribe @@ -370,6 +432,21 @@ public class GroundItemsPlugin extends Plugin final ItemComposition itemComposition = itemManager.getItemComposition(itemId); final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId; final int alchPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT); + int durationMillis; + if (client.isInInstancedRegion()) + { + durationMillis = INSTANCE_DURATION_MILLIS; + } + else if (!itemComposition.isTradeable() && realItemId != COINS) + { + durationMillis = UNTRADEABLE_DURATION_MILLIS; + } + else + { + durationMillis = NORMAL_DURATION_MILLIS; + } + + WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); final GroundItem groundItem = GroundItem.builder() .id(itemId) @@ -378,8 +455,12 @@ public class GroundItemsPlugin extends Plugin .quantity(item.getQuantity()) .name(itemComposition.getName()) .haPrice(alchPrice) - .height(tile.getItemLayer().getHeight()) + .height(-1) .tradeable(itemComposition.isTradeable()) + .droppedInstant(Instant.now()) + .durationMillis(durationMillis) + .isAlwaysPrivate(client.isInInstancedRegion() || (!itemComposition.isTradeable() && realItemId != COINS)) + .isOwnedByPlayer(tile.getWorldLocation().equals(playerLocation)) .build(); @@ -539,8 +620,6 @@ public class GroundItemsPlugin extends Plugin { return entries; } - - } void updateList(String item, boolean hiddenList) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/config/TimerDisplayMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/config/TimerDisplayMode.java new file mode 100644 index 0000000000..3a6773078e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/config/TimerDisplayMode.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Matthew Smith + * 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.grounditems.config; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TimerDisplayMode +{ + ALWAYS("Always"), + HOTKEY_PRESSED("When Hotkey Pressed"), + NEVER("Never"); + + private final String name; + + @Override + public String toString() + { + return name; + } +} \ No newline at end of file From 331594668e310474e10fe64f950f7e1ee47eff91 Mon Sep 17 00:00:00 2001 From: sdburns1998 <49877861+sdburns1998@users.noreply.github.com> Date: Mon, 20 May 2019 18:30:25 +0200 Subject: [PATCH 73/78] Check for NPE - ItemCharges (#324) --- .../plugins/itemcharges/ItemChargePlugin.java | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java index 94c5862bc2..9e165e639a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java @@ -39,6 +39,7 @@ import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; +import static net.runelite.api.ItemID.RING_OF_RECOIL; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameTick; @@ -57,8 +58,6 @@ import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.Text; -import static net.runelite.api.ItemID.RING_OF_RECOIL; - @PluginDescriptor( name = "Item Charges", description = "Show number of item charges remaining", @@ -411,26 +410,34 @@ public class ItemChargePlugin extends Plugin } } - ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); - ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); - ringOfRecoilAvailable = false; - ringOfRecoilEquipped = false; + ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); + ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); + ringOfRecoilAvailable = false; + ringOfRecoilEquipped = false; - Item ring = equipment.getItems()[net.runelite.api.EquipmentInventorySlot.RING.getSlotIdx()]; - if (ring.getId() == RING_OF_RECOIL) + Item ring = null; + if (equipment != null) + { + ring = equipment.getItems()[EquipmentInventorySlot.RING.getSlotIdx()]; + } + if (ring != null && ring.getId() == RING_OF_RECOIL) + { + ringOfRecoilEquipped = true; + ringOfRecoilAvailable = true; + } + Item[] items = new Item[0]; + if (inventory != null) + { + items = inventory.getItems(); + } + for (Item item : items) + { + if (item.getId() == RING_OF_RECOIL) { - ringOfRecoilEquipped = true; ringOfRecoilAvailable = true; + break; } - Item[] items = inventory.getItems(); - for (Item item : items) - { - if (item.getId() == RING_OF_RECOIL) - { - ringOfRecoilAvailable = true; - break; - } - } + } Widget dialog1 = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT); Widget dialog2 = client.getWidget(WidgetInfo.DIALOG2_SPRITE_TEXT); From f8c639d1852eea846d0bb28af549e4c60e21bb5d Mon Sep 17 00:00:00 2001 From: Scott Burns Date: Mon, 20 May 2019 18:59:36 +0200 Subject: [PATCH 74/78] Parent / child configs --- .../runelite/client/config/ConfigItem.java | 1 + .../client/config/ConfigPanelItem.java | 91 +++++++++++++++++++ .../java/net/runelite/client/config/Stub.java | 5 + .../client/plugins/config/ConfigPanel.java | 71 +++++++++++++-- 4 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/config/ConfigPanelItem.java create mode 100644 runelite-client/src/main/java/net/runelite/client/config/Stub.java diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java index 44b93f2e1c..70131819fe 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java @@ -49,4 +49,5 @@ public @interface ConfigItem String group() default ""; + String parent() default ""; } diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigPanelItem.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigPanelItem.java new file mode 100644 index 0000000000..fa7c338ed4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigPanelItem.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, Craftiii4 + * 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.config; + +import java.util.ArrayList; +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; + +public class ConfigPanelItem +{ + + @Getter(AccessLevel.PUBLIC) + private ConfigPanelItem parent; + + @Getter(AccessLevel.PUBLIC) + private List children; + + @Getter(AccessLevel.PUBLIC) + private ConfigItemDescriptor item; + + public ConfigPanelItem(ConfigPanelItem parent, ConfigItemDescriptor item) + { + this.parent = parent; + this.children = new ArrayList<>(); + this.item = item; + } + + public List getItemsAsList() + { + List items = new ArrayList<>(); + + items.add(this); + + for (ConfigPanelItem child : children) + { + items.addAll(child.getItemsAsList()); + } + return items; + } + + public int getDepth() + { + return (parent == null ? 0 : parent.getDepth() + 1); + } + + public boolean addChildIfMatchParent(ConfigItemDescriptor cid) + { + + if (item != null && item.getItem().keyName().equals(cid.getItem().parent())) + { + children.add(new ConfigPanelItem(this, cid)); + return true; + } + else + { + for (ConfigPanelItem child : children) + { + if (child.addChildIfMatchParent(cid)) + { + return true; + } + } + return false; + } + + } + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/config/Stub.java b/runelite-client/src/main/java/net/runelite/client/config/Stub.java new file mode 100644 index 0000000000..be68c83b34 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/config/Stub.java @@ -0,0 +1,5 @@ +package net.runelite.client.config; + +public class Stub +{ +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 276be04829..d67b20b7bd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -75,9 +75,10 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigDescriptor; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.ConfigItemsGroup; import net.runelite.client.config.ConfigItemDescriptor; +import net.runelite.client.config.ConfigItemsGroup; import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.ConfigPanelItem; import net.runelite.client.config.Keybind; import net.runelite.client.config.ModifierlessKeybind; import net.runelite.client.config.Range; @@ -417,6 +418,10 @@ public class ConfigPanel extends PluginPanel title.setToolTipText("" + name + ":
" + listItem.getDescription() + ""); topPanel.add(title); + ConfigPanelItem mainParent = new ConfigPanelItem(null, null); + List parents = new ArrayList<>(); + List allItems = new ArrayList<>(); + for (ConfigItemsGroup cig : cd.getItemGroups()) { boolean collapsed = false; @@ -430,11 +435,13 @@ public class ConfigPanel extends PluginPanel JLabel headerLabel = new JLabel(header); headerLabel.setForeground(Color.ORANGE); - headerLabel.setPreferredSize(new Dimension(PANEL_WIDTH, (int)headerLabel.getPreferredSize().getHeight())); + headerLabel.setPreferredSize(new Dimension(PANEL_WIDTH, (int) headerLabel.getPreferredSize().getHeight())); String sCollapsed = configManager.getConfiguration(cd.getGroup().value(), cig.getGroup() + "_collapse"); if (sCollapsed != null) + { collapsed = Boolean.parseBoolean(sCollapsed); + } JButton collapse = new JButton(collapsed ? "+" : "-"); collapse.setPreferredSize(new Dimension(20, 20)); @@ -451,21 +458,65 @@ public class ConfigPanel extends PluginPanel } if (collapsed) - continue; - - for (ConfigItemDescriptor cid : cig.getItems()) { - if (cid.getItem().hidden()) + continue; + } + + allItems.addAll(cig.getItems()); + + int maxDepth = 3; + do + { + for (ConfigItemDescriptor cid : new ArrayList<>(allItems)) { - continue; + + String parent = cid.getItem().parent(); + + if (parent.equals("")) + { + mainParent.getChildren().add(new ConfigPanelItem(mainParent, cid)); + allItems.remove(cid); + } + else + { + if (mainParent.addChildIfMatchParent(cid)) + { + allItems.remove(cid); + } + } + + } + + maxDepth--; + + } while (allItems.size() > 0 && maxDepth > 0); + + List orderedList = mainParent.getItemsAsList(); + + for (ConfigPanelItem cpi : orderedList) + { + ConfigItemDescriptor cid = cpi.getItem(); + + if (cid == null) + { + continue; // Ignore main 'parent' } JPanel item = new JPanel(); item.setLayout(new BorderLayout()); item.setMinimumSize(new Dimension(PANEL_WIDTH, 0)); name = cid.getItem().name(); + + StringBuilder depthOffset = new StringBuilder(); + for (int depth = 1; depth < cpi.getDepth(); depth++) + { + depthOffset.append(" "); + } + + name = depthOffset + name; + JLabel configEntryName = new JLabel(name); - configEntryName.setPreferredSize(new Dimension(PANEL_WIDTH, (int)configEntryName.getPreferredSize().getHeight())); + configEntryName.setPreferredSize(new Dimension(PANEL_WIDTH, (int) configEntryName.getPreferredSize().getHeight())); configEntryName.setForeground(Color.WHITE); configEntryName.setToolTipText("" + name + ":
" + cid.getItem().description() + ""); item.add(configEntryName, BorderLayout.CENTER); @@ -505,7 +556,9 @@ public class ConfigPanel extends PluginPanel { configEntryName.setText(finalName.concat(": ").concat(String.valueOf(slider.getValue()))); if (!slider.getValueIsAdjusting()) + { changeConfiguration(listItem, config, slider, cd, cid); + } } ); item.add(slider, BorderLayout.EAST); @@ -726,7 +779,9 @@ public class ConfigPanel extends PluginPanel boolean collapse = true; if (sCollapsed != null) + { collapse = !Boolean.parseBoolean(sCollapsed); + } configManager.setConfiguration(cd.getGroup().value(), cig.getGroup() + "_collapse", collapse); openGroupConfigPanel(listItem, config, cd); From 888ac75b18f476c0a87326ce7414f2a5b71f0505 Mon Sep 17 00:00:00 2001 From: Scott Burns Date: Mon, 20 May 2019 19:35:33 +0200 Subject: [PATCH 75/78] Make the title look better --- .../runelite/client/plugins/config/ConfigPanel.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index af01a3b4aa..359f80e7f3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -64,6 +64,8 @@ import javax.swing.ScrollPaneConstants; import javax.swing.SpinnerModel; import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; @@ -83,6 +85,7 @@ import net.runelite.client.config.Keybind; import net.runelite.client.config.ModifierlessKeybind; import net.runelite.client.config.Range; import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.config.Stub; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginInstantiationException; @@ -521,6 +524,15 @@ public class ConfigPanel extends PluginPanel configEntryName.setToolTipText("" + name + ":
" + cid.getItem().description() + ""); item.add(configEntryName, BorderLayout.CENTER); + if (cid.getType() == Stub.class) + { + Border border = item.getBorder(); + Border margin = new EmptyBorder(10,0,0,0); + item.setBorder(new CompoundBorder(border, margin)); + + configEntryName.setForeground(Color.ORANGE); + } + if (cid.getType() == boolean.class) { JCheckBox checkbox = new JCheckBox(); From 05028d4035ccde84b84b67d40366bd21137d450c Mon Sep 17 00:00:00 2001 From: Scott Burns Date: Mon, 20 May 2019 19:50:40 +0200 Subject: [PATCH 76/78] Hiding and unhiding --- .../runelite/client/config/ConfigItem.java | 2 ++ .../client/plugins/config/ConfigPanel.java | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java index 70131819fe..df7f1d318b 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java @@ -49,5 +49,7 @@ public @interface ConfigItem String group() default ""; + String unhide() default ""; + String parent() default ""; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 359f80e7f3..7410a085fa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -505,6 +505,29 @@ public class ConfigPanel extends PluginPanel continue; // Ignore main 'parent' } + if (cid.getItem().hidden()) + { + boolean show = false; + String unhideat = cid.getItem().unhide(); + + for (ConfigItemDescriptor cid2 : cd.getItems()) + { + + if (cid2.getItem().keyName().equals(unhideat)) + { + if (cid2.getType() == boolean.class) + { + show = Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().value(), cid2.getItem().keyName())); + } + } + } + + if (!show) + { + continue; + } + } + JPanel item = new JPanel(); item.setLayout(new BorderLayout()); item.setMinimumSize(new Dimension(PANEL_WIDTH, 0)); @@ -821,6 +844,18 @@ public class ConfigPanel extends PluginPanel { JCheckBox checkbox = (JCheckBox) component; configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), "" + checkbox.isSelected()); + + for (ConfigItemDescriptor cid2 : cd.getItems()) + { + if (cid2.getItem().hidden()) + { + if (cid2.getItem().unhide().equals(cid.getItem().keyName())) + { // If another options visibility changes depending on the value of this checkbox, then render the entire menu again + openGroupConfigPanel(listItem, config, cd); + return; + } + } + } } else if (component instanceof JSpinner) { From 34f1596e005c708eef41767e4572867727940db7 Mon Sep 17 00:00:00 2001 From: Scott Burns Date: Mon, 20 May 2019 19:51:42 +0200 Subject: [PATCH 77/78] Make the slider a little bit shorter --- .../java/net/runelite/client/plugins/config/ConfigPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 7410a085fa..14dfa2e725 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -585,7 +585,7 @@ public class ConfigPanel extends PluginPanel { JSlider slider = new JSlider(min, max, value); configEntryName.setText(name.concat(": ").concat(String.valueOf(slider.getValue()))); - slider.setPreferredSize(new Dimension(100, 25)); + slider.setPreferredSize(new Dimension(85, 25)); String finalName = name; slider.addChangeListener((l) -> { From 8e57433c748aee51f0ce3ca5b43f26730fe3475d Mon Sep 17 00:00:00 2001 From: Scott Burns Date: Mon, 20 May 2019 19:56:34 +0200 Subject: [PATCH 78/78] Checkstyle --- .../java/net/runelite/client/plugins/config/ConfigPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 14dfa2e725..b7ee7d790a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -550,7 +550,7 @@ public class ConfigPanel extends PluginPanel if (cid.getType() == Stub.class) { Border border = item.getBorder(); - Border margin = new EmptyBorder(10,0,0,0); + Border margin = new EmptyBorder(10, 0, 0, 0); item.setBorder(new CompoundBorder(border, margin)); configEntryName.setForeground(Color.ORANGE);