From 9e8d8ada470005521362770e0b24ec4b40722f6d Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Mon, 1 Jun 2020 19:04:41 -0400 Subject: [PATCH 01/55] emoji: Add spoon emoji with trigger `--o` --- .../net/runelite/client/plugins/emojis/Emoji.java | 1 + .../net/runelite/client/plugins/emojis/spoon.png | Bin 0 -> 120 bytes 2 files changed, 1 insertion(+) create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java index acee57ab0f..d4dfcc788d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java @@ -91,6 +91,7 @@ enum Emoji GORILLA(":G"), PLEADING("(n_n)"), XD("Xd"), + SPOON("--o"), ; private static final Map emojiMap; diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png new file mode 100644 index 0000000000000000000000000000000000000000..c838403711a6adfdc32576a74d6585c359cf2c56 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI~0G|-oSo29!mTjE5YAX;)O4v#Q z#TiS2{DK)Ap4~_Ta-=+6978y+Cns!3XK4DL@Q6W+QE2l)*9-?vhE`vW@3#UqrT|qj Nc)I$ztaD0e0sy@ literal 0 HcmV?d00001 From e90b8293de3e37dc3c99578ce2d7438001492b1c Mon Sep 17 00:00:00 2001 From: Usman Akhtar Date: Mon, 25 Jan 2021 23:47:05 -0800 Subject: [PATCH 02/55] grounditems: Add despawn timer for items placed on tables --- .../grounditems/GroundItemsOverlay.java | 30 ++++++++++++++----- .../grounditems/GroundItemsPlugin.java | 25 ++++++++++++++-- .../client/plugins/grounditems/LootType.java | 1 + 3 files changed, 47 insertions(+), 9 deletions(-) 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 e2a69bec33..6f0b96aff9 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 @@ -75,6 +75,7 @@ public class GroundItemsOverlay extends Overlay private static final Duration DESPAWN_TIME_INSTANCE = Duration.ofMinutes(30); private static final Duration DESPAWN_TIME_LOOT = Duration.ofMinutes(2); private static final Duration DESPAWN_TIME_DROP = Duration.ofMinutes(3); + private static final Duration DESPAWN_TIME_TABLE = Duration.ofMinutes(10); private static final int KRAKEN_REGION = 9116; private static final int KBD_NMZ_REGION = 9033; private static final int ZILYANA_REGION = 11602; @@ -397,8 +398,11 @@ public class GroundItemsOverlay extends Overlay private Instant calculateDespawnTime(GroundItem groundItem) { - // We can only accurately guess despawn times for our own pvm loot and dropped items - if (groundItem.getLootType() != LootType.PVM && groundItem.getLootType() != LootType.DROPPED) + // We can only accurately guess despawn times for our own pvm loot, dropped items, + // and items we placed on tables + if (groundItem.getLootType() != LootType.PVM + && groundItem.getLootType() != LootType.DROPPED + && groundItem.getLootType() != LootType.TABLE) { return null; } @@ -461,9 +465,18 @@ public class GroundItemsOverlay extends Overlay } else { - despawnTime = spawnTime.plus(groundItem.getLootType() == LootType.DROPPED - ? DESPAWN_TIME_DROP - : DESPAWN_TIME_LOOT); + switch (groundItem.getLootType()) + { + case DROPPED: + despawnTime = spawnTime.plus(DESPAWN_TIME_DROP); + break; + case TABLE: + despawnTime = spawnTime.plus(DESPAWN_TIME_TABLE); + break; + default: + despawnTime = spawnTime.plus(DESPAWN_TIME_LOOT); + break; + } } if (now.isBefore(spawnTime) || now.isAfter(despawnTime)) @@ -477,8 +490,11 @@ public class GroundItemsOverlay extends Overlay private Color getItemTimerColor(GroundItem groundItem) { - // We can only accurately guess despawn times for our own pvm loot and dropped items - if (groundItem.getLootType() != LootType.PVM && groundItem.getLootType() != LootType.DROPPED) + // We can only accurately guess despawn times for our own pvm loot, dropped items, + // and items we placed on tables + if (groundItem.getLootType() != LootType.PVM + && groundItem.getLootType() != LootType.DROPPED + && groundItem.getLootType() != LootType.TABLE) { return null; } 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 0c8db3a0e1..e7e79b5186 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 @@ -52,7 +52,10 @@ import lombok.Setter; import lombok.Value; import net.runelite.api.Client; import net.runelite.api.GameState; +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.MenuAction; import net.runelite.api.MenuEntry; @@ -180,6 +183,7 @@ public class GroundItemsPlugin extends Plugin private LoadingCache highlightedItems; private LoadingCache hiddenItems; private final Queue droppedItemQueue = EvictingQueue.create(16); // recently dropped items + private int lastUsedItem; @Provides GroundItemsConfig provideConfig(ConfigManager configManager) @@ -194,6 +198,7 @@ public class GroundItemsPlugin extends Plugin mouseManager.registerMouseListener(inputListener); keyManager.registerKeyListener(inputListener); executor.execute(this::reset); + lastUsedItem = -1; } @Override @@ -384,6 +389,7 @@ public class GroundItemsPlugin extends Plugin final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId; final int alchPrice = itemComposition.getHaPrice(); final boolean dropped = tile.getWorldLocation().equals(client.getLocalPlayer().getWorldLocation()) && droppedItemQueue.remove(itemId); + final boolean table = itemId == lastUsedItem && tile.getItemLayer().getHeight() > 0; final GroundItem groundItem = GroundItem.builder() .id(itemId) @@ -394,12 +400,11 @@ public class GroundItemsPlugin extends Plugin .haPrice(alchPrice) .height(tile.getItemLayer().getHeight()) .tradeable(itemComposition.isTradeable()) - .lootType(dropped ? LootType.DROPPED : LootType.UNKNOWN) + .lootType(dropped ? LootType.DROPPED : (table ? LootType.TABLE : LootType.UNKNOWN)) .spawnTime(Instant.now()) .stackable(itemComposition.isStackable()) .build(); - // Update item price in case it is coins if (realItemId == COINS) { @@ -687,5 +692,21 @@ public class GroundItemsPlugin extends Plugin // item spawns that are drops droppedItemQueue.add(itemId); } + else if (menuOptionClicked.getMenuAction() == MenuAction.ITEM_USE_ON_GAME_OBJECT) + { + final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); + if (inventory == null) + { + return; + } + + final Item clickedItem = inventory.getItem(menuOptionClicked.getSelectedItemIndex()); + if (clickedItem == null) + { + return; + } + + lastUsedItem = clickedItem.getId(); + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java index b434298faf..604815732f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.grounditems; enum LootType { UNKNOWN, + TABLE, DROPPED, PVP, PVM; From 1ae07707059df298da4b17303a986d783879cacd Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 3 Feb 2021 12:49:34 -0500 Subject: [PATCH 03/55] bank tags: allow plugins to register their own tag names This also moves the clue tab logic into the clue plugin and inverts the bank tags -> clue plugin dependency --- .../client/plugins/banktags/BankTag.java | 31 ++++++++++ .../plugins/banktags/BankTagsPlugin.java | 3 - .../client/plugins/banktags/TagManager.java | 59 ++++--------------- .../plugins/cluescrolls/ClueScrollPlugin.java | 45 ++++++++++++++ 4 files changed, 89 insertions(+), 49 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTag.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTag.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTag.java new file mode 100644 index 0000000000..74926bc292 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTag.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, 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 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.banktags; + +public interface BankTag +{ + boolean contains(int itemId); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java index 1cffe75379..4e56358252 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java @@ -75,13 +75,11 @@ import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.input.MouseManager; import net.runelite.client.input.MouseWheelListener; import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDependency; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.banktags.tabs.TabInterface; import static net.runelite.client.plugins.banktags.tabs.TabInterface.FILTERED_CHARS; import net.runelite.client.plugins.banktags.tabs.TabSprites; import net.runelite.client.plugins.banktags.tabs.TagTab; -import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; import net.runelite.client.util.Text; @PluginDescriptor( @@ -89,7 +87,6 @@ import net.runelite.client.util.Text; description = "Enable tagging of bank items and searching of bank tags", tags = {"searching", "tagging"} ) -@PluginDependency(ClueScrollPlugin.class) public class BankTagsPlugin extends Plugin implements MouseWheelListener { public static final String CONFIG_GROUP = "banktags"; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java index fe697034d0..b03028e3d8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java @@ -27,24 +27,17 @@ package net.runelite.client.plugins.banktags; import com.google.common.base.Strings; import java.util.Collection; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Singleton; -import net.runelite.api.ItemID; import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemVariationMapping; import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP; -import net.runelite.client.plugins.cluescrolls.ClueScrollService; -import net.runelite.client.plugins.cluescrolls.clues.ClueScroll; -import net.runelite.client.plugins.cluescrolls.clues.CoordinateClue; -import net.runelite.client.plugins.cluescrolls.clues.EmoteClue; -import net.runelite.client.plugins.cluescrolls.clues.FairyRingClue; -import net.runelite.client.plugins.cluescrolls.clues.HotColdClue; -import net.runelite.client.plugins.cluescrolls.clues.MapClue; -import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import net.runelite.client.util.Text; @Singleton @@ -53,17 +46,15 @@ public class TagManager static final String ITEM_KEY_PREFIX = "item_"; private final ConfigManager configManager; private final ItemManager itemManager; - private final ClueScrollService clueScrollService; + private final Map customTags = new HashMap<>(); @Inject private TagManager( final ItemManager itemManager, - final ConfigManager configManager, - final ClueScrollService clueScrollService) + final ConfigManager configManager) { this.itemManager = itemManager; this.configManager = configManager; - this.clueScrollService = clueScrollService; } String getTagString(int itemId, boolean variation) @@ -123,9 +114,10 @@ public class TagManager boolean findTag(int itemId, String search) { - if (search.equals("clue") && testClue(itemId)) + BankTag bankTag = customTags.get(search); + if (bankTag != null) { - return true; + return bankTag.contains(itemId); } Collection tags = getTags(itemId, false); @@ -194,38 +186,13 @@ public class TagManager return itemId; } - private boolean testClue(int itemId) + public void registerTag(String name, BankTag tag) { - ClueScroll c = clueScrollService.getClue(); + customTags.put(name, tag); + } - if (c == null) - { - return false; - } - - if (c instanceof EmoteClue) - { - EmoteClue emote = (EmoteClue) c; - - for (ItemRequirement ir : emote.getItemRequirements()) - { - if (ir.fulfilledBy(itemId)) - { - return true; - } - } - } - else if (c instanceof CoordinateClue || c instanceof HotColdClue || c instanceof FairyRingClue) - { - return itemId == ItemID.SPADE; - } - else if (c instanceof MapClue) - { - MapClue mapClue = (MapClue) c; - - return mapClue.getObjectId() == -1 && itemId == ItemID.SPADE; - } - - return false; + public void unregisterTag(String name) + { + customTags.remove(name); } } 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 06dee6142a..da3a95a301 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 @@ -96,7 +96,10 @@ import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.OverlayMenuClicked; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDependency; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.banktags.BankTagsPlugin; +import net.runelite.client.plugins.banktags.TagManager; import net.runelite.client.plugins.cluescrolls.clues.AnagramClue; import net.runelite.client.plugins.cluescrolls.clues.BeginnerMapClue; import net.runelite.client.plugins.cluescrolls.clues.CipherClue; @@ -117,6 +120,7 @@ import net.runelite.client.plugins.cluescrolls.clues.ObjectClueScroll; import net.runelite.client.plugins.cluescrolls.clues.SkillChallengeClue; import net.runelite.client.plugins.cluescrolls.clues.TextClueScroll; import net.runelite.client.plugins.cluescrolls.clues.ThreeStepCrypticClue; +import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayUtil; @@ -131,6 +135,7 @@ import org.apache.commons.lang3.ArrayUtils; description = "Show answers to clue scroll riddles, anagrams, ciphers, and cryptic clues", tags = {"arrow", "hints", "world", "map", "coordinates", "emotes"} ) +@PluginDependency(BankTagsPlugin.class) @Slf4j public class ClueScrollPlugin extends Plugin { @@ -144,6 +149,7 @@ public class ClueScrollPlugin extends Plugin 13150, 9011, 13151, 9012 }; + private static final String CLUE_TAG_NAME = "clue"; @Getter private ClueScroll clue; @@ -191,6 +197,9 @@ public class ClueScrollPlugin extends Plugin @Inject private WorldMapPointManager worldMapPointManager; + @Inject + private TagManager tagManager; + @Inject @Named("developerMode") boolean developerMode; @@ -227,11 +236,13 @@ public class ClueScrollPlugin extends Plugin overlayManager.add(clueScrollEmoteOverlay); overlayManager.add(clueScrollWorldOverlay); overlayManager.add(clueScrollMusicOverlay); + tagManager.registerTag(CLUE_TAG_NAME, this::testClueTag); } @Override protected void shutDown() throws Exception { + tagManager.unregisterTag(CLUE_TAG_NAME); overlayManager.remove(clueScrollOverlay); overlayManager.remove(clueScrollEmoteOverlay); overlayManager.remove(clueScrollWorldOverlay); @@ -1109,4 +1120,38 @@ public class ClueScrollPlugin extends Plugin } return worldPoint; } + + private boolean testClueTag(int itemId) + { + ClueScroll c = clue; + if (c == null) + { + return false; + } + + if (c instanceof EmoteClue) + { + EmoteClue emote = (EmoteClue) c; + + for (ItemRequirement ir : emote.getItemRequirements()) + { + if (ir.fulfilledBy(itemId)) + { + return true; + } + } + } + else if (c instanceof CoordinateClue || c instanceof HotColdClue || c instanceof FairyRingClue) + { + return itemId == ItemID.SPADE; + } + else if (c instanceof MapClue) + { + MapClue mapClue = (MapClue) c; + + return mapClue.getObjectId() == -1 && itemId == ItemID.SPADE; + } + + return false; + } } From 7b5fb1fb7664015d44c455e6f0a2cc78fa1fb10a Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 4 Feb 2021 13:41:32 -0500 Subject: [PATCH 04/55] clue scroll plugin: fix test --- .../client/plugins/cluescrolls/ClueScrollPluginTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java index 3719dce654..1c3cd1ecd4 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java @@ -40,6 +40,7 @@ import net.runelite.api.events.GameTick; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.banktags.TagManager; import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation; import net.runelite.client.ui.overlay.OverlayManager; import static org.junit.Assert.assertEquals; @@ -81,6 +82,10 @@ public class ClueScrollPluginTest @Bind ItemManager itemManager; + @Mock + @Bind + TagManager tagManager; + @Before public void before() { From fc8360f6cc24c8a6eebae1000bef3fd9a7818abf Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 4 Feb 2021 16:18:18 -0500 Subject: [PATCH 05/55] config manager: require config group and key when setting configuration --- .../main/java/net/runelite/client/config/ConfigManager.java | 5 +++++ 1 file changed, 5 insertions(+) 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 a2a4eef25c..a1cc3ee8b5 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 @@ -507,6 +507,11 @@ public class ConfigManager public void setConfiguration(String groupName, String profile, String key, String value) { + if (Strings.isNullOrEmpty(groupName) || Strings.isNullOrEmpty(key)) + { + throw new IllegalArgumentException(); + } + assert !key.startsWith(RSPROFILE_GROUP + "."); String wholeKey = getWholeKey(groupName, profile, key); String oldValue = (String) properties.setProperty(wholeKey, value); From 29747b1ea7479e3fe377cd00a17966d36cce7b21 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 4 Feb 2021 17:54:21 -0500 Subject: [PATCH 06/55] api: add an addChatMessage method overload to allow skipping events --- .../src/main/java/net/runelite/api/Client.java | 15 ++++++++++++++- 1 file changed, 14 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 c08be0edbe..c665139862 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -120,8 +120,21 @@ public interface Client extends GameEngine * @param name the name of the player that sent the message * @param message the message contents * @param sender the sender/channel name + * @return the message node for the message */ - void addChatMessage(ChatMessageType type, String name, String message, String sender); + MessageNode addChatMessage(ChatMessageType type, String name, String message, String sender); + + /** + * Adds a new chat message to the chatbox. + * + * @param type the type of message + * @param name the name of the player that sent the message + * @param message the message contents + * @param sender the sender/channel name + * @param postEvent whether to post the chat message event + * @return the message node for the message + */ + MessageNode addChatMessage(ChatMessageType type, String name, String message, String sender, boolean postEvent); /** * Gets the current game state. From 236c23b25e014e5eab8ea70680a6356ae6d47885 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 4 Feb 2021 17:55:44 -0500 Subject: [PATCH 07/55] chat command manager: remove unnecessary null tests --- .../runelite/client/chat/ChatCommandManager.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java index 03bc5960b6..0c3a0bfcbc 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java @@ -106,11 +106,6 @@ public class ChatCommandManager implements ChatboxInputListener String message = chatMessage.getMessage(); String command = extractCommand(message); - if (command == null) - { - return; - } - ChatCommand chatCommand = commands.get(command.toLowerCase()); if (chatCommand == null) { @@ -137,11 +132,6 @@ public class ChatCommandManager implements ChatboxInputListener } String command = extractCommand(message); - if (command == null) - { - return false; - } - ChatCommand chatCommand = commands.get(command.toLowerCase()); if (chatCommand == null) { @@ -163,11 +153,6 @@ public class ChatCommandManager implements ChatboxInputListener final String message = privateMessageInput.getMessage(); String command = extractCommand(message); - if (command == null) - { - return false; - } - ChatCommand chatCommand = commands.get(command.toLowerCase()); if (chatCommand == null) { From a2b2d049ccaa2253fccd79b16325c229d9cf854f Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 4 Feb 2021 17:57:33 -0500 Subject: [PATCH 08/55] chat message manager: format runelite messages prior to adding This allows plugins listening for the chat message event to get the runelite formatted message --- .../client/chat/ChatMessageManager.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java index 7faa7ac564..b1795db6ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java @@ -39,20 +39,19 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicReference; import javax.inject.Inject; import javax.inject.Singleton; -import net.runelite.api.ChatLineBuffer; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.MessageNode; import net.runelite.api.Player; import net.runelite.api.Varbits; import net.runelite.api.events.ChatMessage; -import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.ResizeableChanged; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.VarbitChanged; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ChatColorConfig; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.ui.JagexColors; import net.runelite.client.util.ColorUtil; @@ -571,18 +570,15 @@ public class ChatMessageManager return; } + final String formattedMessage = formatRuneLiteMessage(message.getRuneLiteFormattedMessage(), message.getType()); + // this updates chat cycle - client.addChatMessage( + final MessageNode line = client.addChatMessage( message.getType(), MoreObjects.firstNonNull(message.getName(), ""), - MoreObjects.firstNonNull(message.getValue(), message.getRuneLiteFormattedMessage()), + MoreObjects.firstNonNull(formattedMessage, message.getValue()), message.getSender()); - // Get last message from line buffer (the one we just added) - final ChatLineBuffer chatLineBuffer = client.getChatLineMap().get(message.getType().getType()); - final MessageNode[] lines = chatLineBuffer.getLines(); - final MessageNode line = lines[0]; - // Update the message with RuneLite additions line.setRuneLiteFormatMessage(message.getRuneLiteFormattedMessage()); @@ -590,34 +586,38 @@ public class ChatMessageManager { line.setTimestamp(message.getTimestamp()); } - - update(line); } - public void update(final MessageNode target) + /** + * Rebuild the message node message from the RuneLite format message + * + * @param messageNode message node + */ + public void update(final MessageNode messageNode) { - if (Strings.isNullOrEmpty(target.getRuneLiteFormatMessage())) + String message = formatRuneLiteMessage(messageNode.getRuneLiteFormatMessage(), messageNode.getType()); + if (message != null) { - return; + messageNode.setValue(message); + } + } + + private String formatRuneLiteMessage(String runeLiteFormatMessage, ChatMessageType type) + { + if (Strings.isNullOrEmpty(runeLiteFormatMessage)) + { + return null; } final boolean transparent = client.isResized() && transparencyVarbit != 0; - final Collection chatColors = colorCache.get(target.getType()); + final Collection chatColors = colorCache.get(type); - // If we do not have any colors cached, simply set clean message if (chatColors == null || chatColors.isEmpty()) { - target.setValue(target.getRuneLiteFormatMessage()); - return; + return runeLiteFormatMessage; } - target.setValue(recolorMessage(transparent, target.getRuneLiteFormatMessage(), target.getType())); - } - - private String recolorMessage(boolean transparent, String message, ChatMessageType messageType) - { - final Collection chatColors = colorCache.get(messageType); - final AtomicReference resultMessage = new AtomicReference<>(message); + final AtomicReference resultMessage = new AtomicReference<>(runeLiteFormatMessage); // Replace custom formatting with actual colors chatColors.stream() From e71b18b02b124bff69cc347238551d2e0d3bf29b Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 4 Feb 2021 18:03:37 -0500 Subject: [PATCH 09/55] chat history: fix replaying runelite-formatted messages This stores the underlying message node, which may be updated much later with a new message value if a command is used, and replays that. Previously this was storing and replaying the raw RL formatted message, which is why colors would be stripped off of RL-formatted messages on replay. This also no longer triggers chat message events from history replay, which fixes commands incorrectly refiring from replay (and thus the nbsp hack), and fixes the chat notifier sending notifications for replayed messages. --- .../chathistory/ChatHistoryPlugin.java | 52 +++++-------------- 1 file changed, 14 insertions(+), 38 deletions(-) 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 8305c40bde..cc94cfc801 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 @@ -56,8 +56,6 @@ import net.runelite.api.widgets.WidgetInfo; import static net.runelite.api.widgets.WidgetInfo.TO_CHILD; import static net.runelite.api.widgets.WidgetInfo.TO_GROUP; 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; @@ -82,7 +80,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener private static final int CYCLE_HOTKEY = KeyEvent.VK_TAB; private static final int FRIENDS_MAX_SIZE = 5; - private Queue messageQueue; + private Queue messageQueue; private Deque friends; private String currentMessage = null; @@ -99,9 +97,6 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Inject private KeyManager keyManager; - @Inject - private ChatMessageManager chatMessageManager; - @Provides ChatHistoryConfig getConfig(ConfigManager configManager) { @@ -111,6 +106,9 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Override protected void startUp() { + // The client reuses MessageNodes after 100 chat messages of + // the same type, so this must be 100 (or maybe a map of + // size 100 evicting queues) messageQueue = EvictingQueue.create(100); friends = new ArrayDeque<>(FRIENDS_MAX_SIZE + 1); keyManager.registerKeyListener(this); @@ -140,11 +138,16 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener return; } - QueuedMessage queuedMessage; - - while ((queuedMessage = messageQueue.poll()) != null) + for (MessageNode queuedMessage : messageQueue) { - chatMessageManager.queue(queuedMessage); + final MessageNode node = client.addChatMessage( + queuedMessage.getType(), + queuedMessage.getName(), + queuedMessage.getValue(), + queuedMessage.getSender(), + false); + node.setRuneLiteFormatMessage(queuedMessage.getRuneLiteFormatMessage()); + node.setTimestamp(queuedMessage.getTimestamp()); } return; @@ -171,19 +174,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener case MODCHAT: case FRIENDSCHAT: case CONSOLE: - final QueuedMessage queuedMessage = QueuedMessage.builder() - .type(chatMessageType) - .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); - } + messageQueue.offer(chatMessage.getMessageNode()); } } @@ -348,21 +339,6 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener clearMessageQueue(tab); } - /** - * 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) { From e941bb72401fa3764dc2943a69b7ca936c2121a1 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 4 Feb 2021 22:29:04 -0500 Subject: [PATCH 10/55] friends chat: use return value of addChatMessage --- .../client/plugins/friendschat/FriendsChatPlugin.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java index 8413c225e6..6263518015 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java @@ -411,11 +411,7 @@ public class FriendsChatPlugin extends Plugin .append(textColor, member.getName() + activityMessage); final String messageString = message.build(); - client.addChatMessage(ChatMessageType.FRIENDSCHATNOTIFICATION, "", messageString, ""); - - final ChatLineBuffer chatLineBuffer = client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType()); - final MessageNode[] lines = chatLineBuffer.getLines(); - final MessageNode line = lines[0]; + final MessageNode line = client.addChatMessage(ChatMessageType.FRIENDSCHATNOTIFICATION, "", messageString, ""); MemberJoinMessage joinMessage = new MemberJoinMessage(line, line.getId(), client.getTickCount()); joinMessages.addLast(joinMessage); From bf69f263b02f4bb1a1f036feb6f774a296b95a14 Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Wed, 3 Feb 2021 20:43:22 -0500 Subject: [PATCH 11/55] chatnotifications: add private message notification --- .../chatnotifications/ChatNotificationsConfig.java | 11 +++++++++++ .../chatnotifications/ChatNotificationsPlugin.java | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java index 80044fc340..8c254a2c2a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java @@ -108,4 +108,15 @@ public interface ChatNotificationsConfig extends Config { return false; } + + @ConfigItem( + position = 7, + keyName = "notifyOnPM", + name = "Notify on private message", + description = "Notifies you whenever you receive a private message" + ) + default boolean notifyOnPM() + { + return false; + } } 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 afe574d3c6..092b8cf376 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 @@ -165,6 +165,13 @@ public class ChatNotificationsPlugin extends Plugin notifier.notify(Text.removeFormattingTags(broadcast)); } break; + case PRIVATECHAT: + case MODPRIVATECHAT: + if (config.notifyOnPM()) + { + notifier.notify(Text.removeTags(chatMessage.getName()) + ": " + chatMessage.getMessage()); + } + break; case CONSOLE: // Don't notify for notification messages if (chatMessage.getName().equals(runeliteTitle)) From aa6ac7cbc0ab5f20cdd3b133e8c49f073c619afe Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Thu, 4 Feb 2021 08:54:39 -0800 Subject: [PATCH 12/55] clues: Add Isle of Souls coordinate clues --- .../client/plugins/cluescrolls/clues/CoordinateClue.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 8d9a462118..5918f65343 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -205,6 +205,8 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(2484, 4016, 0), new CoordinateClueInfo("Northeast corner of the Island of Stone.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(2222, 3331, 0), new CoordinateClueInfo("Prifddinas, west of the Tower of Voices", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(3560, 3987, 0), new CoordinateClueInfo("Lithkren. Digsite pendant teleport if unlocked, otherwise take rowboat from west of Mushroom Meadow Mushtree.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) + .put(new WorldPoint(2318, 2954, 0), new CoordinateClueInfo("North-east corner of the Isle of Souls.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) + .put(new WorldPoint(2094, 2889, 0), new CoordinateClueInfo("West side of the Isle of Souls.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) // Master .put(new WorldPoint(2178, 3209, 0), new CoordinateClueInfo("South of Iorwerth Camp.", BRASSICAN_MAGE)) .put(new WorldPoint(2155, 3100, 0), new CoordinateClueInfo("South of Port Tyras (BJS if 76 Agility).", BRASSICAN_MAGE)) From f9a51a59e6517056e40511656e0e20ef595ae50e Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Wed, 3 Feb 2021 10:08:09 -0500 Subject: [PATCH 13/55] discord: Isle of Souls region additions --- .../runelite/client/plugins/discord/DiscordGameEventType.java | 3 +++ 1 file changed, 3 insertions(+) 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 7e07a12ee4..ec98c9495b 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 @@ -187,6 +187,7 @@ enum DiscordGameEventType DUNGEON_CRABCLAW_CAVES("Crabclaw Caves", DiscordAreaType.DUNGEONS, 6553, 6809), DUNGEON_CRANDOR("Crandor Dungeon", DiscordAreaType.DUNGEONS, 11414), DUNGEON_CRASH_SITE_CAVERN("Crash Site Cavern", DiscordAreaType.DUNGEONS, 8280, 8536), + DUNGEON_CRUMBLING_TOWER("Crumbling Tower", DiscordAreaType.DUNGEONS, 7827), DUNGEON_DAEYALT_ESSENCE_MINE("Daeyalt Essence Mine", DiscordAreaType.DUNGEONS, 14744), DUNGEON_DIGSITE("Digsite Dungeon", DiscordAreaType.DUNGEONS, 13464, 13465), DUNGEON_DORGESHKAAN("Dorgesh-Kaan South Dungeon", DiscordAreaType.DUNGEONS, 10833), @@ -210,6 +211,7 @@ enum DiscordGameEventType DUNGEON_HAM_STORE_ROOM("H.A.M. Store room", DiscordAreaType.DUNGEONS, 10321), DUNGEON_HEROES_GUILD("Heroes' Guild Mine", DiscordAreaType.DUNGEONS, 11674), DUNGEON_IORWERTH("Iorwerth Dungeon", DiscordAreaType.DUNGEONS, 12737, 12738, 12993, 12994), + DUNGEON_ISLE_OF_SOULS("Isle of Souls Dungeon", DiscordAreaType.DUNGEONS, 8593), DUNGEON_JATIZSO_MINES("Jatizso Mines", DiscordAreaType.DUNGEONS, 9631), DUNGEON_JIGGIG_BURIAL_TOMB("Jiggig Burial Tomb", DiscordAreaType.DUNGEONS, 9875, 9874), DUNGEON_JOGRE("Jogre Dungeon", DiscordAreaType.DUNGEONS, 11412), @@ -367,6 +369,7 @@ enum DiscordGameEventType REGION_ICYENE_GRAVEYARD("Icyene Graveyard", DiscordAreaType.REGIONS, 14641, 14897, 14898), REGION_ISAFDAR("Isafdar", DiscordAreaType.REGIONS, 8497, 8753, 8754, 9009, 9010), REGION_ISLAND_OF_STONE("Island of Stone", DiscordAreaType.REGIONS, 9790), + REGION_ISLE_OF_SOULS("Isle of Souls", DiscordAreaType.REGIONS, 8236, 8237, 8238, 8491, 8492, 8494, 8747, 8750, 9003, 9004, 9006, 9260, 9261, 9262), REGION_JIGGIG("Jiggig" , DiscordAreaType.REGIONS, 9775), REGION_KANDARIN("Kandarin", DiscordAreaType.REGIONS, 9014, 9263, 9264, 9519, 9524, 9527, 9776, 9783, 10037, 10290, 10294, 10546, 10551, 10805), REGION_KARAMJA("Karamja" , DiscordAreaType.REGIONS, 10801, 10802, 11054, 11311, 11312, 11313, 11566, 11567, 11568, 11569, 11822), From 26bbe8a9821c84f46aa7b62ff70560d4a3e6a1f2 Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Wed, 3 Feb 2021 10:09:35 -0500 Subject: [PATCH 14/55] fishing: add Isle of Souls NPC IDs to enum --- .../java/net/runelite/client/game/FishingSpot.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java b/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java index 14d7b96316..a3de9412a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java +++ b/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java @@ -29,6 +29,9 @@ import java.util.Map; import lombok.Getter; import net.runelite.api.ItemID; import static net.runelite.api.NpcID.FISHING_SPOT; +import static net.runelite.api.NpcID.FISHING_SPOT_10513; +import static net.runelite.api.NpcID.FISHING_SPOT_10514; +import static net.runelite.api.NpcID.FISHING_SPOT_10515; import static net.runelite.api.NpcID.FISHING_SPOT_1497; import static net.runelite.api.NpcID.FISHING_SPOT_1498; import static net.runelite.api.NpcID.FISHING_SPOT_1499; @@ -132,13 +135,14 @@ public enum FishingSpot FISHING_SPOT_1525, FISHING_SPOT_1528, FISHING_SPOT_1530, FISHING_SPOT_1544, FISHING_SPOT_3913, FISHING_SPOT_7155, FISHING_SPOT_7459, FISHING_SPOT_7462, FISHING_SPOT_7467, - FISHING_SPOT_7469, FISHING_SPOT_7947 + FISHING_SPOT_7469, FISHING_SPOT_7947, FISHING_SPOT_10513 ), LOBSTER("Lobster, Swordfish, Tuna", "Lobster", ItemID.RAW_LOBSTER, FISHING_SPOT_1510, FISHING_SPOT_1519, FISHING_SPOT_1522, FISHING_SPOT_3914, FISHING_SPOT_5820, FISHING_SPOT_7199, FISHING_SPOT_7460, FISHING_SPOT_7465, FISHING_SPOT_7470, - FISHING_SPOT_7946, FISHING_SPOT_9173, FISHING_SPOT_9174 + FISHING_SPOT_7946, FISHING_SPOT_9173, FISHING_SPOT_9174, + FISHING_SPOT_10515 ), SHARK("Shark, Bass", "Shark", ItemID.RAW_SHARK, FISHING_SPOT_1511, FISHING_SPOT_1520, FISHING_SPOT_3419, @@ -146,7 +150,7 @@ public enum FishingSpot FISHING_SPOT_5233, FISHING_SPOT_5234, FISHING_SPOT_5821, FISHING_SPOT_7200, FISHING_SPOT_7461, FISHING_SPOT_7466, FISHING_SPOT_8525, FISHING_SPOT_8526, FISHING_SPOT_8527, - FISHING_SPOT_9171, FISHING_SPOT_9172 + FISHING_SPOT_9171, FISHING_SPOT_9172, FISHING_SPOT_10514 ), MONKFISH("Monkfish", ItemID.RAW_MONKFISH, FISHING_SPOT_4316 From 7395e221ce7e33f082bd696a0d3fe9563e248b23 Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Wed, 3 Feb 2021 10:08:44 -0500 Subject: [PATCH 15/55] worldmap: add Isle of Souls locations --- .../client/plugins/worldmap/DungeonLocation.java | 2 ++ .../client/plugins/worldmap/FishingSpotLocation.java | 3 +++ .../client/plugins/worldmap/HunterAreaLocation.java | 3 +++ .../client/plugins/worldmap/MiningSiteLocation.java | 5 +++++ .../client/plugins/worldmap/RareTreeLocation.java | 10 ++++++++++ 5 files changed, 23 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java index 0df27cf60c..544cefd6c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java @@ -58,6 +58,7 @@ enum DungeonLocation CRABCLAW_CAVES_TUNNEL("Crabclaw Caves Tunnel (quest)", new WorldPoint(1671, 9800, 0)), CRANDOR("Crandor Dungeon", new WorldPoint(2833, 3256, 0)), CRASH_ISLAND("Crash Island Dungeon", new WorldPoint(2920, 2721, 0)), + CRUMBLING_TOWER("Crumbling Tower basement", new WorldPoint(2130, 2994, 0)), DEEP_WILDERNESS("Deep Wilderness Dungeon", new WorldPoint(3044, 3924, 0)), DRAYNOR_MANOR_E("Draynor Manor basement", new WorldPoint(3114, 3357, 0)), DRAYNOR_MANOR_W("Draynor Manor basement", new WorldPoint(3091, 3362, 0)), @@ -89,6 +90,7 @@ enum DungeonLocation ICE_QUEEN_W("Ice Queen's Lair", new WorldPoint(2822, 3510, 0)), ICE_TROLL_E("Ice Troll Caves", new WorldPoint(2400, 3889, 0)), ICE_TROLL_W("Ice Troll Caves", new WorldPoint(2315, 3894, 0)), + ISLE_OF_SOULS_DUNGEON("Isle of Souls Dungeon", new WorldPoint(2308, 2919, 0)), IORWERTH("Iorwerth Dungeon", new WorldPoint(3224, 6044, 0)), IORWERTH_CAMP_CAVE("Iorwerth Camp cave", new WorldPoint(2200, 3262, 0)), IORWERTH_CAMP_CAVE_PRIF("Iorwerth Camp cave", new WorldPoint(3224, 6014, 0)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java index 3180ca0973..4b04a4beea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java @@ -95,6 +95,9 @@ enum FishingSpotLocation IORWERTH_CAMP_OUTSIDE(FishingSpot.SALMON, new WorldPoint(2215, 3245, 0)), ISAFDAR_NORTH_EAST_INSIDE(FishingSpot.SALMON, new WorldPoint(3293, 6005, 0)), ISAFDAR_NORTH_EAST_OUTSIDE(FishingSpot.SALMON, new WorldPoint(2269, 3253, 0)), + ISLE_OF_SOULS_EAST(FishingSpot.SHARK, new WorldPoint(2281, 2841, 0)), + ISLE_OF_SOULS_NORTH(FishingSpot.LOBSTER, new WorldPoint(2280, 2975, 0)), + ISLE_OF_SOULS_SOUTH_WEST(FishingSpot.SHRIMP, new WorldPoint(2162, 2782, 0)), JATISZO(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER}, new WorldPoint(2400, 3780, 0), new WorldPoint(2412, 3780, 0), new WorldPoint(2419, 3789, 0)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java index 3f9ee919b8..5607170461 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java @@ -49,6 +49,9 @@ enum HunterAreaLocation FOSSIL_ISLAND_UNDERWATER(new WorldPoint(3743, 10295, 0), HunterCreature.FISH_SHOAL), GWENITH_HUNTER_AREA_OUTSIDE(new WorldPoint(2269, 3408, 0), HunterCreature.CARNIVOROUS_CHINCHOMPA), GWENITH_HUNTER_AREA_INSIDE(new WorldPoint(3293, 6160, 0), HunterCreature.CARNIVOROUS_CHINCHOMPA), + ISLE_OF_SOULS_NORTH(new WorldPoint(2207, 2964, 0), HunterCreature.COPPER_LONGTAIL), + ISLE_OF_SOULS_NORTH_WEST(new WorldPoint(2127, 2950, 0), HunterCreature.CHINCHOMPA), + ISLE_OF_SOULS_SOUTH_WEST(new WorldPoint(2158, 2822, 0), HunterCreature.CRIMSON_SWIFT), KARAMJA_HUNTER_AREA(new WorldPoint(2786, 3001, 0), HunterCreature.HORNED_GRAAHK), KEBOS_SWAMP(new WorldPoint(1184, 3595, 0), HunterCreature.CRIMSON_SWIFT), KOUREND_WOODLAND_CENTER(new WorldPoint(1512, 3478, 0), HunterCreature.RUBY_HARVEST), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java index bd647d2b1d..ef4db23372 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java @@ -117,6 +117,11 @@ enum MiningSiteLocation new Rock(10, Ore.CLAY), new Rock(11, Ore.COPPER), new Rock(4, Ore.TIN), new Rock(9, Ore.IRON), new Rock(2, Ore.SILVER)), ISAFDAR(new WorldPoint(2277, 3159, 0), new Rock(4, Ore.ADAMANTITE), new Rock(2, Ore.RUNITE)), + ISLE_OF_SOULS_DUNGEON_EAST(new WorldPoint(1831, 9109, 0), new Rock(1, Ore.RUNITE)), + ISLE_OF_SOULS_DUNGEON_WEST(new WorldPoint(1814, 9116, 0), new Rock(2, Ore.ADAMANTITE)), + ISLE_OF_SOULS_SOUTH(new WorldPoint(2195, 2793, 0), + new Rock(3, Ore.CLAY), new Rock(3, Ore.TIN), new Rock(3, Ore.COPPER), new Rock(10, Ore.IRON), + new Rock(3, Ore.SILVER), new Rock(6, Ore.COAL), new Rock(4, Ore.GOLD), new Rock(2, Ore.MITHRIL)), JATIZSO(new WorldPoint(2396, 3812, 0), new Rock(11, Ore.TIN), new Rock(7, Ore.IRON), new Rock(8, Ore.COAL), new Rock(15, Ore.MITHRIL), new Rock(11, Ore.ADAMANTITE)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java index addcda5af7..f7751bf5dd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java @@ -83,6 +83,9 @@ enum RareTreeLocation new WorldPoint(2748, 3466, 0), new WorldPoint(2710, 3570, 0), + // Isle of Souls + new WorldPoint(2254, 2808, 0), + // Prifddinas new WorldPoint(2209, 3427, 0), new WorldPoint(3233, 6179, 0)), @@ -111,6 +114,9 @@ enum RareTreeLocation // Mos Le'Harmless new WorldPoint(3810, 3058, 0), + // Isle of Souls + new WorldPoint(2194, 2991, 0), + // Karamja new WorldPoint(2821, 3084, 0)), @@ -180,6 +186,10 @@ enum RareTreeLocation new WorldPoint(3674, 3447, 0), new WorldPoint(3684, 3385, 0), + // Isle of Souls + new WorldPoint(2147, 2972, 0), + new WorldPoint(2165, 2863, 0), + // Zanaris new WorldPoint(2412, 4464, 0), new WorldPoint(2465, 4427, 0), From 28556cfae35f905ae41dbc6817afc9c3a8dec4ff Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Wed, 3 Feb 2021 11:54:36 -0500 Subject: [PATCH 16/55] slayer: add Isle of Souls task location --- .../src/main/java/net/runelite/client/plugins/slayer/Task.java | 1 + 1 file changed, 1 insertion(+) 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 8e02556440..29867dc042 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 @@ -202,6 +202,7 @@ enum Task "Fremennik Slayer Dungeon", "God Wars Dungeon", "Iorwerth Dungeon", + "Isle of Souls", "Jormungand's Prison", "Kalphite Lair", "Karuulm Slayer Dungeon", From 5031df9fb2040f7d7e9ba5c42477d7ab7bd1d76b Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Fri, 5 Feb 2021 17:15:27 +0000 Subject: [PATCH 17/55] clues: add Isle of Souls Hot/Cold location --- .../plugins/cluescrolls/clues/hotcold/HotColdLocation.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java index 02ef88a083..d2433db61a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java @@ -96,6 +96,7 @@ public enum HotColdLocation FREMENNIK_PROVINCE_LUNAR_VILLAGE(new WorldPoint(2084, 3916, 0), FREMENNIK_PROVINCE, "Lunar Isle, inside the village.", ANCIENT_WIZARDS), FREMENNIK_PROVINCE_LUNAR_NORTH(new WorldPoint(2106, 3949, 0), FREMENNIK_PROVINCE, "Lunar Isle, north of the village.", ANCIENT_WIZARDS), ICE_MOUNTAIN(new WorldPoint(3007, 3475, 0), MISTHALIN, "Atop Ice Mountain"), + ISLE_OF_SOULS_MINE(new WorldPoint(2189, 2794, 0), KANDARIN, "Isle of Souls Mine, south of the Soul Wars lobby"), KANDARIN_SINCLAR_MANSION(new WorldPoint(2730, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut.", BRASSICAN_MAGE), KANDARIN_CATHERBY(new WorldPoint(2774, 3436, 0), KANDARIN, "Catherby, between the bank and the beehives, near small rock formation.", BRASSICAN_MAGE), KANDARIN_GRAND_TREE(new WorldPoint(2448, 3503, 0), KANDARIN, "Grand Tree, just east of the terrorchick gnome enclosure.", BRASSICAN_MAGE), From f8612639fe2a16bbfbba26e9df9d01305180ab1a Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Sun, 17 Jan 2021 18:45:04 -0500 Subject: [PATCH 18/55] discord: Use regions instead of varbits for raiding activity --- .../runelite/client/plugins/discord/DiscordGameEventType.java | 4 ++-- .../net/runelite/client/plugins/discord/DiscordPlugin.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) 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 ec98c9495b..4f93882e58 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 @@ -309,8 +309,8 @@ enum DiscordGameEventType MG_VOLCANIC_MINE("Volcanic Mine", DiscordAreaType.MINIGAMES, 15263, 15262), // Raids - RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, Varbits.IN_RAID), - RAIDS_THEATRE_OF_BLOOD("Theatre of Blood", DiscordAreaType.RAIDS, Varbits.THEATRE_OF_BLOOD), + RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, 12889, 13136, 13137, 13138, 13139, 13140, 13141, 13145, 13393, 13394, 13395, 13396, 13397, 13401), + RAIDS_THEATRE_OF_BLOOD("Theatre of Blood", DiscordAreaType.RAIDS, 12611, 12612, 12613, 12867, 12869, 13122, 13123, 13125, 13379), // Other REGION_ABYSSAL_AREA("Abyssal Area", DiscordAreaType.REGIONS, 12108), 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 6f5ffbdcd1..2c114de643 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 @@ -447,6 +447,7 @@ public class DiscordPlugin extends Plugin case DUNGEONS: return config.showDungeonActivity(); case MINIGAMES: return config.showMinigameActivity(); case REGIONS: return config.showRegionsActivity(); + case RAIDS: return config.showRaidingActivity(); } return false; From dc99317b756888b08c820d4feac916bbccad64c4 Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Sun, 17 Jan 2021 19:01:09 -0500 Subject: [PATCH 19/55] discord: Remove code for handling of varbits By changing DiscordAreaType.RAIDS to use regions instead of varbits, it is no longer necessary for the discord plugin to have any varbit-related code --- .../plugins/discord/DiscordGameEventType.java | 38 ------------------- .../client/plugins/discord/DiscordPlugin.java | 17 --------- 2 files changed, 55 deletions(-) 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 4f93882e58..4bfe4652ed 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 @@ -26,16 +26,12 @@ */ package net.runelite.client.plugins.discord; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.util.List; import java.util.Map; import javax.annotation.Nullable; import lombok.AllArgsConstructor; import lombok.Getter; -import net.runelite.api.Client; import net.runelite.api.Skill; -import net.runelite.api.Varbits; @AllArgsConstructor @Getter @@ -433,20 +429,12 @@ enum DiscordGameEventType REGION_WRATH_ALTAR("Wrath Altar", DiscordAreaType.REGIONS, 9291); private static final Map FROM_REGION; - private static final List FROM_VARBITS; static { ImmutableMap.Builder regionMapBuilder = new ImmutableMap.Builder<>(); - ImmutableList.Builder fromVarbitsBuilder = ImmutableList.builder(); for (DiscordGameEventType discordGameEventType : DiscordGameEventType.values()) { - if (discordGameEventType.getVarbits() != null) - { - fromVarbitsBuilder.add(discordGameEventType); - continue; - } - if (discordGameEventType.getRegionIds() == null) { continue; @@ -458,7 +446,6 @@ enum DiscordGameEventType } } FROM_REGION = regionMapBuilder.build(); - FROM_VARBITS = fromVarbitsBuilder.build(); } @Nullable @@ -500,9 +487,6 @@ enum DiscordGameEventType @Nullable private DiscordAreaType discordAreaType; - @Nullable - private Varbits varbits; - @Nullable private int[] regionIds; @@ -544,15 +528,6 @@ enum DiscordGameEventType this(state, priority, true, false, false, true, false); } - DiscordGameEventType(String areaName, DiscordAreaType areaType, Varbits varbits) - { - this.state = exploring(areaType, areaName); - this.priority = -2; - this.discordAreaType = areaType; - this.varbits = varbits; - this.shouldClear = true; - } - private static String training(final Skill skill) { return training(skill.getName()); @@ -612,17 +587,4 @@ enum DiscordGameEventType { return FROM_REGION.get(regionId); } - - public static DiscordGameEventType fromVarbit(final Client client) - { - for (DiscordGameEventType fromVarbit : FROM_VARBITS) - { - if (client.getVar(fromVarbit.getVarbits()) != 0) - { - return fromVarbit; - } - } - - 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 2c114de643..cfc0aa80e9 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 @@ -46,7 +46,6 @@ import net.runelite.api.WorldType; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.StatChanged; -import net.runelite.api.events.VarbitChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.discord.DiscordService; import net.runelite.client.discord.events.DiscordJoinGame; @@ -210,22 +209,6 @@ public class DiscordPlugin extends Plugin } } - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - if (!config.showRaidingActivity()) - { - return; - } - - final DiscordGameEventType discordGameEventType = DiscordGameEventType.fromVarbit(client); - - if (discordGameEventType != null) - { - discordState.triggerEvent(discordGameEventType); - } - } - @Subscribe public void onDiscordReady(DiscordReady event) { From 18826a713c827bedaa95bdeb6f8e15682becfa56 Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Wed, 27 Jan 2021 21:03:23 -0500 Subject: [PATCH 20/55] ground items: add Nightmare instance to normal despawn timers --- .../client/plugins/grounditems/GroundItemsOverlay.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 6f0b96aff9..f565652b11 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 @@ -82,6 +82,7 @@ public class GroundItemsOverlay extends Overlay private static final int GRAARDOR_REGION = 11347; private static final int KRIL_TSUTSAROTH_REGION = 11603; private static final int KREEARRA_REGION = 11346; + private static final int NIGHTMARE_REGION = 15515; private final Client client; private final GroundItemsPlugin plugin; @@ -451,9 +452,9 @@ public class GroundItemsOverlay extends Overlay } } else if (playerRegionID == ZILYANA_REGION || playerRegionID == GRAARDOR_REGION || - playerRegionID == KRIL_TSUTSAROTH_REGION || playerRegionID == KREEARRA_REGION) + playerRegionID == KRIL_TSUTSAROTH_REGION || playerRegionID == KREEARRA_REGION || playerRegionID == NIGHTMARE_REGION) { - // GWD instances use the normal despawn timers + // GWD and Nightmare instances use the normal despawn timers despawnTime = spawnTime.plus(groundItem.getLootType() == LootType.DROPPED ? DESPAWN_TIME_DROP : DESPAWN_TIME_LOOT); From fce6f85d03e32c3411ecfc77c5c5f1381e39ab8f Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Fri, 5 Feb 2021 20:56:57 +0000 Subject: [PATCH 21/55] Release 1.6.39 --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index eaa5cc4bc1..ec55896861 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index e8ed1260ad..0240cc1987 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 88f64d466f..5898de6b8e 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 8ebea1f210..b7ab8bac9e 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 44f7340e3f..92085b5806 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 Web Service diff --git a/pom.xml b/pom.xml index e9c9fb5744..b72dc67652 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 pom RuneLite @@ -61,7 +61,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - HEAD + runelite-parent-1.6.39 diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 9fff909084..e841f1e01e 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 518749315a..ce6ad72802 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 47677f9a03..c64c47dbd2 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39-SNAPSHOT + 1.6.39 script-assembler-plugin From 7fba2eb095afe1238f6238533c7b7ac1d1547dbd Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Fri, 5 Feb 2021 20:57:06 +0000 Subject: [PATCH 22/55] Bump for 1.6.40-SNAPSHOT --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index ec55896861..782e4408cb 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 0240cc1987..20d0eb865c 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 5898de6b8e..305b0e3b7f 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index b7ab8bac9e..e864273049 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 92085b5806..4adddc284a 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index b72dc67652..9ee7f55c10 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT pom RuneLite @@ -61,7 +61,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - runelite-parent-1.6.39 + HEAD diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index e841f1e01e..6cc0d185cc 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index ce6ad72802..10000e6125 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index c64c47dbd2..016b2d854f 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.39 + 1.6.40-SNAPSHOT script-assembler-plugin From 73d481302b9eb72dad538921469ae9d81f5c9cb1 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 5 Feb 2021 23:23:19 -0500 Subject: [PATCH 23/55] icon text field: use only awt key listener This key listener wrapper is unnecssary and was using the RL key listener, which is meant for client keys, instead of the awt key listener --- .../skillcalculator/SkillCalculator.java | 11 +++++++- .../client/ui/components/IconTextField.java | 26 ------------------- 2 files changed, 10 insertions(+), 27 deletions(-) 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 64422ee34c..bd688d3788 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 @@ -30,6 +30,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.text.DecimalFormat; @@ -95,7 +97,14 @@ class SkillCalculator extends JPanel searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR); searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR); searchBar.addClearListener(this::onSearch); - searchBar.addKeyListener(e -> onSearch()); + searchBar.addKeyListener(new KeyAdapter() + { + @Override + public void keyTyped(KeyEvent e) + { + onSearch(); + } + }); setLayout(new DynamicGridLayout(0, 1, 0, 5)); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java index b4c2ff1127..05806ada73 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java @@ -33,14 +33,12 @@ import java.awt.Font; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; -import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -335,30 +333,6 @@ public class IconTextField extends JPanel clearListeners.add(clearListener); } - public void addKeyListener(Consumer keyEventConsumer) - { - addKeyListener(new net.runelite.client.input.KeyListener() - { - @Override - public void keyTyped(KeyEvent e) - { - keyEventConsumer.accept(e); - } - - @Override - public void keyPressed(KeyEvent e) - { - keyEventConsumer.accept(e); - } - - @Override - public void keyReleased(KeyEvent e) - { - keyEventConsumer.accept(e); - } - }); - } - @Override public void removeKeyListener(KeyListener keyListener) { From f13be14280d8fc7d6f12c05ea0f3807daabaddf4 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 5 Feb 2021 23:25:34 -0500 Subject: [PATCH 24/55] bank tags: fix tag named clue coexisting with the special "clue" tab --- .../java/net/runelite/client/plugins/banktags/TagManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java index b03028e3d8..3cfac27242 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java @@ -115,9 +115,9 @@ public class TagManager boolean findTag(int itemId, String search) { BankTag bankTag = customTags.get(search); - if (bankTag != null) + if (bankTag != null && bankTag.contains(itemId)) { - return bankTag.contains(itemId); + return true; } Collection tags = getTags(itemId, false); From fe51dfb05b7b27f2f51418b15436c11dab783f81 Mon Sep 17 00:00:00 2001 From: loldudester Date: Thu, 14 Jan 2021 09:52:28 +0000 Subject: [PATCH 25/55] TimeTracking: Move birdhouse schedule to ScheduledExecutorService --- .../client/plugins/timetracking/TimeTrackingPlugin.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java index 310c2e4e4a..f43f4a2d99 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java @@ -29,7 +29,6 @@ import com.google.inject.Inject; import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -58,7 +57,6 @@ import net.runelite.client.plugins.timetracking.clocks.ClockManager; import net.runelite.client.plugins.timetracking.farming.FarmingContractManager; import net.runelite.client.plugins.timetracking.farming.FarmingTracker; import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker; -import net.runelite.client.task.Schedule; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; @@ -102,6 +100,8 @@ public class TimeTrackingPlugin extends Plugin private ScheduledFuture panelUpdateFuture; + private ScheduledFuture notifierFuture; + private TimeTrackingPanel panel; private NavigationButton navButton; @@ -139,6 +139,7 @@ public class TimeTrackingPlugin extends Plugin clientToolbar.addNavigation(navButton); panelUpdateFuture = executorService.scheduleAtFixedRate(this::updatePanel, 200, 200, TimeUnit.MILLISECONDS); + notifierFuture = executorService.scheduleAtFixedRate(this::checkCompletion, 0, 10, TimeUnit.SECONDS); } @Override @@ -153,6 +154,7 @@ public class TimeTrackingPlugin extends Plugin panelUpdateFuture = null; } + notifierFuture.cancel(true); clientToolbar.removeNavigation(navButton); infoBoxManager.removeInfoBox(farmingContractManager.getInfoBox()); farmingContractManager.setInfoBox(null); @@ -260,8 +262,7 @@ public class TimeTrackingPlugin extends Plugin } } - @Schedule(period = 10, unit = ChronoUnit.SECONDS) - public void checkCompletion() + private void checkCompletion() { boolean birdHouseDataChanged = birdHouseTracker.checkCompletion(); From daf0d1c48b33db599162a3e0beafd9ceeee68614 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 6 Feb 2021 14:06:19 -0500 Subject: [PATCH 26/55] perspective: support rectangular tile areas --- .../java/net/runelite/api/Perspective.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Perspective.java b/runelite-api/src/main/java/net/runelite/api/Perspective.java index eab5323d38..8c309ccf3d 100644 --- a/runelite-api/src/main/java/net/runelite/api/Perspective.java +++ b/runelite-api/src/main/java/net/runelite/api/Perspective.java @@ -375,7 +375,7 @@ public class Perspective */ public static Polygon getCanvasTilePoly(@Nonnull Client client, @Nonnull LocalPoint localLocation, int zOffset) { - return getCanvasTileAreaPoly(client, localLocation, 1, zOffset); + return getCanvasTileAreaPoly(client, localLocation, 1, 1, zOffset); } /** @@ -388,7 +388,7 @@ public class Perspective */ public static Polygon getCanvasTileAreaPoly(@Nonnull Client client, @Nonnull LocalPoint localLocation, int size) { - return getCanvasTileAreaPoly(client, localLocation, size, 0); + return getCanvasTileAreaPoly(client, localLocation, size, size, 0); } /** @@ -396,23 +396,25 @@ public class Perspective * * @param client the game client * @param localLocation the center location of the AoE - * @param size the size of the area (ie. 3x3 AoE evaluates to size 3) + * @param sizeX the size of the area in tiles on the x axis + * @param sizeY the size of the area in tiles on the y axis * @param zOffset offset from ground plane * @return a polygon representing the tiles in the area */ public static Polygon getCanvasTileAreaPoly( @Nonnull Client client, @Nonnull LocalPoint localLocation, - int size, + int sizeX, + int sizeY, int zOffset) { final int plane = client.getPlane(); - final int swX = localLocation.getX() - (size * LOCAL_TILE_SIZE / 2); - final int swY = localLocation.getY() - (size * LOCAL_TILE_SIZE / 2); + final int swX = localLocation.getX() - (sizeX * LOCAL_TILE_SIZE / 2); + final int swY = localLocation.getY() - (sizeY * LOCAL_TILE_SIZE / 2); - final int neX = localLocation.getX() + (size * LOCAL_TILE_SIZE / 2); - final int neY = localLocation.getY() + (size * LOCAL_TILE_SIZE / 2); + final int neX = localLocation.getX() + (sizeX * LOCAL_TILE_SIZE / 2); + final int neY = localLocation.getY() + (sizeY * LOCAL_TILE_SIZE / 2); final int seX = swX; final int seY = neY; From 089756189f0eea885bb5223458de972b194f9230 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 6 Feb 2021 14:07:32 -0500 Subject: [PATCH 27/55] devtools: fix drawing game object overlays multiple times This also removes the player mesh overlay and the gameobject convex hull overlay since they are unnecessary --- .../plugins/devtools/DevToolsOverlay.java | 64 +++---------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java index b4a9f65337..208107e836 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java @@ -43,8 +43,6 @@ import net.runelite.api.Constants; import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; import net.runelite.api.GraphicsObject; -import net.runelite.api.TileItem; -import net.runelite.api.GroundObject; import net.runelite.api.ItemLayer; import net.runelite.api.NPC; import net.runelite.api.NPCComposition; @@ -55,7 +53,8 @@ import net.runelite.api.Point; import net.runelite.api.Projectile; import net.runelite.api.Scene; import net.runelite.api.Tile; -import net.runelite.api.WallObject; +import net.runelite.api.TileItem; +import net.runelite.api.TileObject; import net.runelite.api.coords.LocalPoint; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -154,7 +153,6 @@ class DevToolsOverlay extends Overlay String text = local.getName() + " (A: " + local.getAnimation() + ") (P: " + local.getPoseAnimation() + ") (G: " + local.getGraphic() + ")"; OverlayUtil.renderActorOverlay(graphics, local, text, CYAN); - renderPlayerWireframe(graphics, local, CYAN); } private void renderNpcs(Graphics2D graphics) @@ -214,7 +212,7 @@ class DevToolsOverlay extends Overlay if (plugin.getGroundObjects().isActive()) { - renderGroundObject(graphics, tile, player); + renderTileObject(graphics, tile.getGroundObject(), player, PURPLE); } if (plugin.getGameObjects().isActive()) @@ -224,7 +222,7 @@ class DevToolsOverlay extends Overlay if (plugin.getWalls().isActive()) { - renderWallObject(graphics, tile, player); + renderTileObject(graphics, tile.getWallObject(), player, GRAY); } if (plugin.getDecorations().isActive()) @@ -309,45 +307,21 @@ class DevToolsOverlay extends Overlay { for (GameObject gameObject : gameObjects) { - if (gameObject != null) + if (gameObject != null && gameObject.getSceneMinLocation().equals(tile.getSceneLocation())) { - if (player.getLocalLocation().distanceTo(gameObject.getLocalLocation()) <= MAX_DISTANCE) - { - OverlayUtil.renderTileOverlay(graphics, gameObject, "ID: " + gameObject.getId(), GREEN); - } - - // Draw a polygon around the convex hull - // of the model vertices - Shape p = gameObject.getConvexHull(); - if (p != null) - { - graphics.draw(p); - } + renderTileObject(graphics, gameObject, player, GREEN); } } } } - private void renderGroundObject(Graphics2D graphics, Tile tile, Player player) + private void renderTileObject(Graphics2D graphics, TileObject tileObject, Player player, Color color) { - GroundObject groundObject = tile.getGroundObject(); - if (groundObject != null) + if (tileObject != null) { - if (player.getLocalLocation().distanceTo(groundObject.getLocalLocation()) <= MAX_DISTANCE) + if (player.getLocalLocation().distanceTo(tileObject.getLocalLocation()) <= MAX_DISTANCE) { - OverlayUtil.renderTileOverlay(graphics, groundObject, "ID: " + groundObject.getId(), PURPLE); - } - } - } - - private void renderWallObject(Graphics2D graphics, Tile tile, Player player) - { - WallObject wallObject = tile.getWallObject(); - if (wallObject != null) - { - if (player.getLocalLocation().distanceTo(wallObject.getLocalLocation()) <= MAX_DISTANCE) - { - OverlayUtil.renderTileOverlay(graphics, wallObject, "ID: " + wallObject.getId(), GRAY); + OverlayUtil.renderTileOverlay(graphics, tileObject, "ID: " + tileObject.getId(), color); } } } @@ -447,22 +421,4 @@ class DevToolsOverlay extends Overlay } } } - - private void renderPlayerWireframe(Graphics2D graphics, Player player, Color color) - { - Polygon[] polys = player.getPolygons(); - - if (polys == null) - { - return; - } - - graphics.setColor(color); - - for (Polygon p : polys) - { - graphics.drawPolygon(p); - } - } - } From 19db6bf8caf9e621bb5ed960d405ba5e11ec3d02 Mon Sep 17 00:00:00 2001 From: loldudester Date: Thu, 14 Jan 2021 09:46:46 +0000 Subject: [PATCH 28/55] TimeTracking: Add farming notifications --- .../runelite/client/config/ConfigManager.java | 5 + .../timetracking/TimeTrackingConfig.java | 1 + .../timetracking/TimeTrackingPlugin.java | 4 +- .../plugins/timetracking/TimeablePanel.java | 30 ++- .../timetracking/farming/FarmingPatch.java | 13 +- .../timetracking/farming/FarmingRegion.java | 4 +- .../timetracking/farming/FarmingTabPanel.java | 49 +++-- .../timetracking/farming/FarmingTracker.java | 172 ++++++++++++++++-- .../timetracking/farming/FarmingWorld.java | 72 ++++---- .../timetracking/farming/ProfilePatch.java | 34 ++++ .../plugins/timetracking/notify_icon.png | Bin 0 -> 463 bytes .../timetracking/notify_selected_icon.png | Bin 0 -> 310 bytes 12 files changed, 319 insertions(+), 65 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/ProfilePatch.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_icon.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_selected_icon.png 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 a1cc3ee8b5..549ef0b123 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 @@ -152,6 +152,11 @@ public class ConfigManager scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS); } + public String getRSProfileKey() + { + return rsProfileKey; + } + public final void switchSession(AccountSession session) { // Ensure existing config is saved diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java index 28704ff3ce..aa284ee86c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java @@ -41,6 +41,7 @@ public interface TimeTrackingConfig extends Config String TIMERS = "timers"; String STOPWATCHES = "stopwatches"; String PREFER_SOONEST = "preferSoonest"; + String NOTIFY = "notify"; @ConfigItem( keyName = "timeFormatMode", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java index f43f4a2d99..7eee98df8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java @@ -139,7 +139,7 @@ public class TimeTrackingPlugin extends Plugin clientToolbar.addNavigation(navButton); panelUpdateFuture = executorService.scheduleAtFixedRate(this::updatePanel, 200, 200, TimeUnit.MILLISECONDS); - notifierFuture = executorService.scheduleAtFixedRate(this::checkCompletion, 0, 10, TimeUnit.SECONDS); + notifierFuture = executorService.scheduleAtFixedRate(this::checkCompletion, 10, 10, TimeUnit.SECONDS); } @Override @@ -270,6 +270,8 @@ public class TimeTrackingPlugin extends Plugin { panel.update(); } + + farmingTracker.checkCompletion(); } private void updatePanel() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java index e7584a6e27..9796146500 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java @@ -29,22 +29,29 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; +import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JToggleButton; import javax.swing.border.EmptyBorder; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.Constants; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.components.ThinProgressBar; import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.SwingUtil; +@Slf4j @Getter public class TimeablePanel extends JPanel { private final T timeable; private final JLabel icon = new JLabel(); private final JLabel farmingContractIcon = new JLabel(); + private final JToggleButton notifyButton = new JToggleButton(); private final JLabel estimate = new JLabel(); private final ThinProgressBar progress = new ThinProgressBar(); private final JLabel text; @@ -79,8 +86,29 @@ public class TimeablePanel extends JPanel infoPanel.add(text); infoPanel.add(estimate); + ImageIcon notifyIcon = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_icon.png")); + ImageIcon notifySelectedIcon = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_selected_icon.png")); + + notifyButton.setPreferredSize(new Dimension(30, 16)); + notifyButton.setBorder(new EmptyBorder(0, 0, 0, 10)); + notifyButton.setIcon(notifyIcon); + notifyButton.setSelectedIcon(notifySelectedIcon); + SwingUtil.removeButtonDecorations(notifyButton); + SwingUtil.addModalTooltip(notifyButton, "Disable notifications", "Enable notifications"); + + JPanel notifyPanel = new JPanel(); + notifyPanel.setLayout(new BorderLayout()); + notifyPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + notifyPanel.add(notifyButton, BorderLayout.CENTER); + + JPanel iconPanel = new JPanel(); + iconPanel.setLayout(new BorderLayout()); + iconPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + iconPanel.add(notifyPanel, BorderLayout.EAST); + iconPanel.add(farmingContractIcon, BorderLayout.WEST); + + topContainer.add(iconPanel, BorderLayout.EAST); topContainer.add(icon, BorderLayout.WEST); - topContainer.add(farmingContractIcon, BorderLayout.EAST); topContainer.add(infoPanel, BorderLayout.CENTER); progress.setValue(0); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java index 8c24588917..25b29ba01f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java @@ -29,6 +29,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import net.runelite.api.Varbits; +import net.runelite.client.plugins.timetracking.TimeTrackingConfig; @RequiredArgsConstructor( access = AccessLevel.PACKAGE @@ -41,4 +42,14 @@ class FarmingPatch private final String name; private final Varbits varbit; private final PatchImplementation implementation; -} + + String configKey() + { + return region.getRegionID() + "." + varbit.getId(); + } + + String notifyConfigKey() + { + return TimeTrackingConfig.NOTIFY + "." + region.getRegionID() + "." + varbit.getId(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java index a759d2c31b..bb149af373 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java @@ -33,13 +33,15 @@ public class FarmingRegion { private final String name; private final int regionID; + private final boolean definite; private final FarmingPatch[] patches; private final Varbits[] varbits; - FarmingRegion(String name, int regionID, FarmingPatch... patches) + FarmingRegion(String name, int regionID, boolean definite, FarmingPatch... patches) { this.name = name; this.regionID = regionID; + this.definite = definite; this.patches = patches; this.varbits = new Varbits[patches.length]; for (int i = 0; i < patches.length; i++) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java index 1c068790c8..18d525c1e0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java @@ -33,8 +33,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.swing.JLabel; +import javax.swing.JToggleButton; import javax.swing.border.EmptyBorder; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.ItemID; +import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.timetracking.TabContentPanel; import net.runelite.client.plugins.timetracking.TimeTrackingConfig; @@ -42,10 +45,12 @@ import net.runelite.client.plugins.timetracking.TimeablePanel; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; +@Slf4j public class FarmingTabPanel extends TabContentPanel { private final FarmingTracker farmingTracker; private final ItemManager itemManager; + private final ConfigManager configManager; private final TimeTrackingConfig config; private final List> patchPanels; private final FarmingContractManager farmingContractManager; @@ -53,6 +58,7 @@ public class FarmingTabPanel extends TabContentPanel FarmingTabPanel( FarmingTracker farmingTracker, ItemManager itemManager, + ConfigManager configManager, TimeTrackingConfig config, Set patches, FarmingContractManager farmingContractManager @@ -60,6 +66,7 @@ public class FarmingTabPanel extends TabContentPanel { this.farmingTracker = farmingTracker; this.itemManager = itemManager; + this.configManager = configManager; this.config = config; this.patchPanels = new ArrayList<>(); this.farmingContractManager = farmingContractManager; @@ -103,6 +110,18 @@ public class FarmingTabPanel extends TabContentPanel lastImpl = patch.getImplementation(); } + // Set toggle state of notification menu on icon click; + JToggleButton toggleNotify = p.getNotifyButton(); + String configKey = patch.notifyConfigKey(); + + toggleNotify.addActionListener(e -> + { + if (configManager.getRSProfileKey() != null) + { + configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, configKey, toggleNotify.isSelected()); + } + }); + patchPanels.add(p); add(p, c); c.gridy++; @@ -197,18 +216,26 @@ public class FarmingTabPanel extends TabContentPanel { panel.getProgress().setVisible(false); } - JLabel farmingContractIcon = panel.getFarmingContractIcon(); - if (farmingContractManager.shouldHighlightFarmingTabPanel(patch)) - { - itemManager.getImage(ItemID.SEED_PACK).addTo(farmingContractIcon); - farmingContractIcon.setToolTipText(farmingContractManager.getContract().getName()); - } - else - { - farmingContractIcon.setIcon(null); - farmingContractIcon.setToolTipText(""); - } } + + JLabel farmingContractIcon = panel.getFarmingContractIcon(); + if (farmingContractManager.shouldHighlightFarmingTabPanel(patch)) + { + itemManager.getImage(ItemID.SEED_PACK).addTo(farmingContractIcon); + farmingContractIcon.setToolTipText(farmingContractManager.getContract().getName()); + } + else + { + farmingContractIcon.setIcon(null); + farmingContractIcon.setToolTipText(""); + } + + String configKey = patch.notifyConfigKey(); + JToggleButton toggleNotify = panel.getNotifyButton(); + boolean notifyEnabled = Boolean.TRUE + .equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, configKey, Boolean.class)); + + toggleNotify.setSelected(notifyEnabled); } } } 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 a5c953f324..e01c451b8d 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 @@ -29,20 +29,28 @@ import com.google.inject.Singleton; import java.time.Instant; import java.util.Collection; import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.GameState; import net.runelite.api.Varbits; import net.runelite.api.coords.WorldPoint; import net.runelite.api.vars.Autoweed; import net.runelite.api.widgets.WidgetModalMode; +import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneScapeProfile; +import net.runelite.client.config.RuneScapeProfileType; 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; +import net.runelite.client.util.Text; @Slf4j @Singleton @@ -53,6 +61,7 @@ public class FarmingTracker private final ConfigManager configManager; private final TimeTrackingConfig config; private final FarmingWorld farmingWorld; + private final Notifier notifier; private final Map summaries = new EnumMap<>(Tab.class); @@ -61,23 +70,26 @@ public class FarmingTracker * or {@code -1} if we have no data about any patch of the given type. */ private final Map completionTimes = new EnumMap<>(Tab.class); + Map wasNotified = new HashMap<>(); private boolean newRegionLoaded; private Collection lastRegions; + private boolean firstNotifyCheck = true; @Inject - private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, TimeTrackingConfig config, FarmingWorld farmingWorld) + private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, TimeTrackingConfig config, FarmingWorld farmingWorld, Notifier notifier) { this.client = client; this.itemManager = itemManager; this.configManager = configManager; this.config = config; this.farmingWorld = farmingWorld; + this.notifier = notifier; } public FarmingTabPanel createTabPanel(Tab tab, FarmingContractManager farmingContractManager) { - return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab), farmingContractManager); + return new FarmingTabPanel(this, itemManager, configManager, config, farmingWorld.getTabs().get(tab), farmingContractManager); } /** @@ -130,7 +142,7 @@ public class FarmingTracker { // 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 = region.getRegionID() + "." + varbit.getId(); + String key = patch.configKey(); String strVarbit = Integer.toString(client.getVar(varbit)); String storedValue = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key); @@ -189,6 +201,12 @@ public class FarmingTracker configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET, offsetMins); } } + if (currentPatchState.getTickRate() != 0 + // Don't set wasNotified to false if witnessing a check-health action + && !(previousPatchState.getCropState() == CropState.GROWING && currentPatchState.getCropState() == CropState.HARVESTABLE && currentPatchState.getProduce().getPatchImplementation().isHealthCheckRequired())) + { + wasNotified.put(new ProfilePatch(patch, configManager.getRSProfileKey()), false); + } } else { @@ -258,17 +276,23 @@ public class FarmingTracker @Nullable public PatchPrediction predictPatch(FarmingPatch patch) + { + return predictPatch(patch, configManager.getRSProfileKey()); + } + + @Nullable + public PatchPrediction predictPatch(FarmingPatch patch, String profile) { long unixNow = Instant.now().getEpochSecond(); boolean autoweed = Integer.toString(Autoweed.ON.ordinal()) - .equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.AUTOWEED)); + .equals(configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.AUTOWEED)); boolean botanist = Boolean.TRUE - .equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.BOTANIST, Boolean.class)); + .equals(configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.BOTANIST, Boolean.class)); - String key = patch.getRegion().getRegionID() + "." + patch.getVarbit().getId(); - String storedValue = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key); + String key = patch.configKey(); + String storedValue = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, key); if (storedValue == null) { @@ -323,11 +347,11 @@ public class FarmingTracker long doneEstimate = 0; if (tickrate > 0) { - long tickNow = getTickTime(tickrate, 0, unixNow); - long tickTime = getTickTime(tickrate, 0, unixTime); + long tickNow = getTickTime(tickrate, 0, unixNow, profile); + long tickTime = getTickTime(tickrate, 0, unixTime, profile); int delta = (int) (tickNow - tickTime) / (tickrate * 60); - doneEstimate = getTickTime(tickrate, stages - 1 - stage, tickTime); + doneEstimate = getTickTime(tickrate, stages - 1 - stage, tickTime, profile); stage += delta; if (stage >= stages) @@ -347,13 +371,13 @@ public class FarmingTracker public long getTickTime(int tickRate, int ticks) { - return getTickTime(tickRate, ticks, Instant.now().getEpochSecond()); + return getTickTime(tickRate, ticks, Instant.now().getEpochSecond(), configManager.getRSProfileKey()); } - public long getTickTime(int tickRate, int ticks, long requestedTime) + public long getTickTime(int tickRate, int ticks, long requestedTime, String profile) { - Integer offsetPrecisionMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class); - Integer offsetTimeMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET, int.class); + Integer offsetPrecisionMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class); + Integer offsetTimeMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.FARM_TICK_OFFSET, int.class); //All offsets are negative but are stored as positive long calculatedOffsetTime = 0L; @@ -465,4 +489,124 @@ public class FarmingTracker completionTimes.put(tab.getKey(), completionTime); } } + + public void checkCompletion() + { + List rsProfiles = configManager.getRSProfiles(); + long unixNow = Instant.now().getEpochSecond(); + + for (RuneScapeProfile profile : rsProfiles) + { + Integer offsetPrecisionMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class); + Integer offsetTimeMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), TimeTrackingConfig.FARM_TICK_OFFSET, int.class); + + RuneScapeProfileType profileType = profile.getType(); + + for (Map.Entry> tab : farmingWorld.getTabs().entrySet()) + { + for (FarmingPatch patch : tab.getValue()) + { + ProfilePatch profilePatch = new ProfilePatch(patch, profile.getKey()); + boolean patchNotified = (wasNotified.get(profilePatch) != null ? wasNotified.get(profilePatch) : false); + String configKey = patch.notifyConfigKey(); + boolean shouldNotify = Boolean.TRUE + .equals(configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), configKey, Boolean.class)); + PatchPrediction prediction = predictPatch(patch, profile.getKey()); + + if (prediction == null) + { + continue; + } + + int tickRate = prediction.getProduce().getTickrate(); + + if (offsetPrecisionMins == null || offsetTimeMins == null || (offsetPrecisionMins < tickRate && offsetPrecisionMins < 40) || prediction.getProduce() == Produce.WEEDS + || unixNow <= prediction.getDoneEstimate() || patchNotified || prediction.getCropState() == CropState.FILLING) + { + continue; + } + + wasNotified.put(profilePatch, true); + + if (!firstNotifyCheck && shouldNotify) + { + final StringBuilder notificationStringBuilder = new StringBuilder(); + // Same RS account + if (client.getGameState() == GameState.LOGGED_IN && profile.getDisplayName().equals(client.getLocalPlayer().getName())) + { + // Same RS account but different profile type + if (profileType != RuneScapeProfileType.getCurrent(client)) + { + notificationStringBuilder.append("(") + .append(Text.titleCase(profile.getType())) + .append(") "); + } + // Same RS account AND profile falls through here so no bracketed prefix is added + } + else + { + // Different RS account AND profile type + if (profileType != RuneScapeProfileType.getCurrent(client) || client.getGameState() == GameState.LOGIN_SCREEN) + { + //Don't print profile type when logged out if is STANDARD + if (client.getGameState() == GameState.LOGIN_SCREEN && profileType == RuneScapeProfileType.STANDARD) + { + notificationStringBuilder.append("(") + .append(profile.getDisplayName()) + .append(") "); + } + else + { + notificationStringBuilder.append("(") + .append(profile.getDisplayName()) + .append(" - ") + .append(Text.titleCase(profile.getType())) + .append(") "); + } + } + // Different RS account but same profile type + else + { + notificationStringBuilder.append("(") + .append(profile.getDisplayName()) + .append(") "); + } + } + + notificationStringBuilder + .append("Your ") + .append(prediction.getProduce().getName()); + + switch (prediction.getCropState()) + { + case HARVESTABLE: + case GROWING: + if (prediction.getProduce().getName().toLowerCase(Locale.ENGLISH).contains("compost")) + { + notificationStringBuilder.append(" is ready to collect in "); + } + else + { + notificationStringBuilder.append(" is ready to harvest in "); + } + break; + case DISEASED: + notificationStringBuilder.append(" has become diseased in "); + break; + case DEAD: + notificationStringBuilder.append(" has died in "); + break; + } + + notificationStringBuilder.append(patch.getRegion().isDefinite() ? "the " : "") + .append(patch.getRegion().getName()) + .append("."); + + notifier.notify(notificationStringBuilder.toString()); + } + } + } + } + firstNotifyCheck = false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java index 7ca46e130c..5429240775 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java @@ -64,14 +64,14 @@ class FarmingWorld { // Some of these patches get updated in multiple regions. // It may be worth it to add a specialization for these patches - add(new FarmingRegion("Al Kharid", 13106, + add(new FarmingRegion("Al Kharid", 13106, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CACTUS) ), 13362, 13105); - add(new FarmingRegion("Ardougne", 10290, + add(new FarmingRegion("Ardougne", 10290, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH) ), 10546); - add(new FarmingRegion("Ardougne", 10548, + add(new FarmingRegion("Ardougne", 10548, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -79,12 +79,12 @@ class FarmingWorld new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) )); - add(new FarmingRegion("Brimhaven", 11058, + add(new FarmingRegion("Brimhaven", 11058, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE) ), 11057); - add(new FarmingRegion("Catherby", 11062, + add(new FarmingRegion("Catherby", 11062, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -103,7 +103,7 @@ class FarmingWorld return true; } }, 11061, 11318, 11317); - add(new FarmingRegion("Catherby", 11317, + add(new FarmingRegion("Catherby", 11317, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE) ) { @@ -115,27 +115,27 @@ class FarmingWorld } }); - add(new FarmingRegion("Champions' Guild", 12596, + add(new FarmingRegion("Champions' Guild", 12596, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH) )); - add(new FarmingRegion("Draynor Manor", 12340, + add(new FarmingRegion("Draynor Manor", 12340, false, new FarmingPatch("Belladonna", Varbits.FARMING_4771, PatchImplementation.BELLADONNA) )); - add(new FarmingRegion("Entrana", 11060, + add(new FarmingRegion("Entrana", 11060, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) ), 11316); - add(new FarmingRegion("Etceteria", 10300, + add(new FarmingRegion("Etceteria", 10300, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE) )); - add(new FarmingRegion("Falador", 11828, + add(new FarmingRegion("Falador", 11828, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 12084); - add(new FarmingRegion("Falador", 12083, + add(new FarmingRegion("Falador", 12083, false, new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -151,7 +151,7 @@ class FarmingWorld } }); - add(new FarmingRegion("Fossil Island", 14651, + add(new FarmingRegion("Fossil Island", 14651, false, new FarmingPatch("East", Varbits.FARMING_4771, PatchImplementation.HARDWOOD_TREE), new FarmingPatch("Middle", Varbits.FARMING_4772, PatchImplementation.HARDWOOD_TREE), new FarmingPatch("West", Varbits.FARMING_4773, PatchImplementation.HARDWOOD_TREE) @@ -179,22 +179,22 @@ class FarmingWorld return loc.getPlane() == 0; } }, 14907, 14908, 15164, 14652, 14906, 14650, 15162, 15163); - add(new FarmingRegion("Seaweed", 15008, + add(new FarmingRegion("Seaweed", 15008, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.SEAWEED), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.SEAWEED) )); - add(new FarmingRegion("Gnome Stronghold", 9781, + add(new FarmingRegion("Gnome Stronghold", 9781, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.FRUIT_TREE) ), 9782, 9526, 9525); - add(new FarmingRegion("Harmony", 15148, + add(new FarmingRegion("Harmony", 15148, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.HERB) )); - add(new FarmingRegion("Kourend", 6967, + add(new FarmingRegion("Kourend", 6967, false, new FarmingPatch("North East", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -202,7 +202,7 @@ class FarmingWorld new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST), new FarmingPatch("", Varbits.FARMING_7904, PatchImplementation.SPIRIT_TREE) ), 6711); - add(new FarmingRegion("Kourend", 7223, + add(new FarmingRegion("Kourend", 7223, false, new FarmingPatch("East 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES), new FarmingPatch("East 2", Varbits.GRAPES_4954, PatchImplementation.GRAPES), new FarmingPatch("East 3", Varbits.GRAPES_4955, PatchImplementation.GRAPES), @@ -217,21 +217,21 @@ class FarmingWorld new FarmingPatch("West 6", Varbits.GRAPES_4964, PatchImplementation.GRAPES) )); - add(new FarmingRegion("Lletya", 9265, + add(new FarmingRegion("Lletya", 9265, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE) ), 11103); - add(new FarmingRegion("Lumbridge", 12851, + add(new FarmingRegion("Lumbridge", 12851, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) )); - add(new FarmingRegion("Lumbridge", 12594, + add(new FarmingRegion("Lumbridge", 12594, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 12850); - add(new FarmingRegion("Morytania", 13622, + add(new FarmingRegion("Morytania", 13622, false, new FarmingPatch("Mushroom", Varbits.FARMING_4771, PatchImplementation.MUSHROOM) ), 13878); - add(new FarmingRegion("Morytania", 14391, + add(new FarmingRegion("Morytania", 14391, false, new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -239,7 +239,7 @@ class FarmingWorld new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) ), 14390); - add(new FarmingRegion("Port Sarim", 12082, + add(new FarmingRegion("Port Sarim", 12082, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE) ) { @@ -250,48 +250,48 @@ class FarmingWorld } }, 12083); - add(new FarmingRegion("Rimmington", 11570, + add(new FarmingRegion("Rimmington", 11570, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH) ), 11826); - add(new FarmingRegion("Seers' Village", 10551, + add(new FarmingRegion("Seers' Village", 10551, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) ), 10550); - add(new FarmingRegion("Tai Bwo Wannai", 11056, + add(new FarmingRegion("Tai Bwo Wannai", 11056, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CALQUAT) )); - add(new FarmingRegion("Taverley", 11573, + add(new FarmingRegion("Taverley", 11573, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 11829); - add(new FarmingRegion("Tree Gnome Village", 9777, + add(new FarmingRegion("Tree Gnome Village", 9777, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE) ), 10033); - add(new FarmingRegion("Troll Stronghold", 11321, + add(new FarmingRegion("Troll Stronghold", 11321, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB) )); - add(new FarmingRegion("Varrock", 12854, + add(new FarmingRegion("Varrock", 12854, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 12853); - add(new FarmingRegion("Yanille", 10288, + add(new FarmingRegion("Yanille", 10288, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) )); - add(new FarmingRegion("Weiss", 11325, + add(new FarmingRegion("Weiss", 11325, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB) )); - add(new FarmingRegion("Farming Guild", 5021, + add(new FarmingRegion("Farming Guild", 5021, true, new FarmingPatch("Hespori", Varbits.FARMING_7908, PatchImplementation.HESPORI) )); //Full 3x3 region area centered on farming guild - add(farmingGuildRegion = new FarmingRegion("Farming Guild", 4922, + add(farmingGuildRegion = new FarmingRegion("Farming Guild", 4922, true, new FarmingPatch("", Varbits.FARMING_7905, PatchImplementation.TREE), new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.HERB), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.BUSH), @@ -308,7 +308,7 @@ class FarmingWorld ), 5177, 5178, 5179, 4921, 4923, 4665, 4666, 4667); //All of Prifddinas, and all of Prifddinas Underground - add(new FarmingRegion("Prifddinas", 13151, + add(new FarmingRegion("Prifddinas", 13151, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/ProfilePatch.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/ProfilePatch.java new file mode 100644 index 0000000000..d928c1f8e0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/ProfilePatch.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Hannah Ryan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 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 lombok.Value; + +@Value +class ProfilePatch +{ + FarmingPatch patch; + String rsProfileKey; +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4a4667bedb0951701f740880f10c36ac304018c4 GIT binary patch literal 463 zcmV;=0WkiFP)VHnEt9wX6PnW9nfDX0>j2x>#9^H|2VB4{t_y2dxWi&w;1uq$KOnak zx#>2*GpuF0U&VPF;7JD7({WSaWbTX#T8g8o1&+t4(-JMv%n6d> zIlM(aU6WMcJ>aQmiYtK$@>=Tn20Jl-EW`uVk07*qo IM6N<$g56t(YybcN literal 0 HcmV?d00001 From 5de258310a3b89de62c172e4561a12d373b0dd12 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sat, 6 Feb 2021 12:00:48 -0700 Subject: [PATCH 29/55] http-api: allow gsoning classes outside of net.runelite This broke plugin hub plugins using our gson, which is valid since you can reflect into any unnamed module. --- .../http/api/gson/IllegalReflectionExclusion.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/http-api/src/main/java/net/runelite/http/api/gson/IllegalReflectionExclusion.java b/http-api/src/main/java/net/runelite/http/api/gson/IllegalReflectionExclusion.java index d7611cf83f..a25ffb79f7 100644 --- a/http-api/src/main/java/net/runelite/http/api/gson/IllegalReflectionExclusion.java +++ b/http-api/src/main/java/net/runelite/http/api/gson/IllegalReflectionExclusion.java @@ -27,13 +27,26 @@ package net.runelite.http.api.gson; import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Set; public class IllegalReflectionExclusion implements ExclusionStrategy { + private static final Set PRIVATE_CLASSLOADERS = new HashSet<>(); + + static + { + for (ClassLoader cl = ClassLoader.getSystemClassLoader(); cl != null; ) + { + cl = cl.getParent(); + PRIVATE_CLASSLOADERS.add(cl); + } + } + @Override public boolean shouldSkipField(FieldAttributes f) { - if (f.getDeclaringClass().getName().startsWith("net.runelite")) + if (!PRIVATE_CLASSLOADERS.contains(f.getDeclaringClass().getClassLoader())) { return false; } From 37838ac836db6d8c98f2c776c1b2e537c83dcd85 Mon Sep 17 00:00:00 2001 From: Liam Schmidt Date: Mon, 1 Feb 2021 21:33:52 -0500 Subject: [PATCH 30/55] screenshot: Add valuable drop threshold config --- .../plugins/screenshot/ScreenshotConfig.java | 20 ++++++++++++--- .../plugins/screenshot/ScreenshotPlugin.java | 12 ++++++--- .../screenshot/ScreenshotPluginTest.java | 25 ++++++++++++++++++- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java index 269eb8554a..44d9d58b51 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java @@ -205,11 +205,23 @@ public interface ScreenshotConfig extends Config return false; } + @ConfigItem( + keyName = "valuableDropThreshold", + name = "Valuable Threshold", + description = "The minimum value to save screenshots of valuable drops.", + position = 14, + section = whatSection + ) + default int valuableDropThreshold() + { + return 0; + } + @ConfigItem( keyName = "untradeableDrop", name = "Screenshot Untradeable drops", description = "Configures whether or not screenshots are automatically taken when you receive an untradeable drop.", - position = 14, + position = 15, section = whatSection ) default boolean screenshotUntradeableDrop() @@ -221,7 +233,7 @@ public interface ScreenshotConfig extends Config keyName = "ccKick", name = "Screenshot Kicks from FC", description = "Take a screenshot when you kick a user from a friends chat.", - position = 15, + position = 16, section = whatSection ) default boolean screenshotKick() @@ -233,7 +245,7 @@ public interface ScreenshotConfig extends Config keyName = "baHighGamble", name = "Screenshot BA high gambles", description = "Take a screenshot of your reward from a high gamble at Barbarian Assault.", - position = 16, + position = 17, section = whatSection ) default boolean screenshotHighGamble() @@ -245,7 +257,7 @@ public interface ScreenshotConfig extends Config keyName = "hotkey", name = "Screenshot hotkey", description = "When you press this key a screenshot will be taken", - position = 17 + position = 18 ) default Keybind hotkey() { 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 b199248c39..0dada91ae6 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 @@ -99,7 +99,7 @@ public class ScreenshotPlugin extends Plugin 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 VALUABLE_DROP_PATTERN = Pattern.compile(".*Valuable drop: ([^<>]+?\\(((?:\\d+,?)+) coins\\))(?:)?"); 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 Pattern QUEST_PATTERN_1 = Pattern.compile(".+?ve\\.*? (?been|rebuilt|.+?ed)? ?(?:the )?'?(?.+?)'?(?: [Qq]uest)?[!.]?$"); @@ -417,9 +417,13 @@ public class ScreenshotPlugin extends Plugin Matcher m = VALUABLE_DROP_PATTERN.matcher(chatMessage); if (m.matches()) { - String valuableDropName = m.group(1); - String fileName = "Valuable drop " + valuableDropName; - takeScreenshot(fileName, "Valuable Drops"); + int valuableDropValue = Integer.parseInt(m.group(2).replaceAll(",", "")); + if (valuableDropValue >= config.valuableDropThreshold()) + { + String valuableDropName = m.group(1); + String fileName = "Valuable drop " + valuableDropName; + takeScreenshot(fileName, "Valuable Drops"); + } } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java index 5386db8202..edd5101817 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java @@ -57,6 +57,7 @@ import org.mockito.Mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import org.mockito.junit.MockitoJUnitRunner; @@ -67,7 +68,8 @@ public class ScreenshotPluginTest private static final String BARROWS_CHEST = "Your Barrows chest count is 310"; private static final String CHAMBERS_OF_XERIC_CHEST = "Your completed Chambers of Xeric count is: 489."; private static final String THEATRE_OF_BLOOD_CHEST = "Your completed Theatre of Blood count is: 73."; - private static final String VALUABLE_DROP = "Valuable drop: 6 x Bronze arrow (42 coins)"; + private static final String NOT_SO_VALUABLE_DROP = "Valuable drop: 6 x Bronze arrow (42 coins)"; + private static final String VALUABLE_DROP = "Valuable drop: Rune scimitar (25,600 coins)"; private static final String UNTRADEABLE_DROP = "Untradeable drop: Rusty sword"; private static final String BA_HIGH_GAMBLE_REWARD = "Raw shark (x 300)!
High level gamble count: 100"; private static final String HUNTER_LEVEL_2_TEXT = "Congratulations, you've just advanced a Hunter level.

Your Hunter level is now 2."; @@ -121,6 +123,7 @@ public class ScreenshotPluginTest Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); when(screenshotConfig.screenshotLevels()).thenReturn(true); when(screenshotConfig.screenshotValuableDrop()).thenReturn(true); + when(screenshotConfig.valuableDropThreshold()).thenReturn(1000); when(screenshotConfig.screenshotUntradeableDrop()).thenReturn(true); } @@ -161,10 +164,30 @@ public class ScreenshotPluginTest assertEquals(73, screenshotPlugin.gettheatreOfBloodNumber()); } + @Test + public void testNotSoValuableDrop() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", NOT_SO_VALUABLE_DROP, null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verifyNoInteractions(drawManager); + + when(screenshotConfig.valuableDropThreshold()).thenReturn(0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + @Test public void testValuableDrop() { ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", VALUABLE_DROP, null, 0); + when(screenshotConfig.valuableDropThreshold()).thenReturn(100_000); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verifyNoInteractions(drawManager); + + when(screenshotConfig.valuableDropThreshold()).thenReturn(1000); screenshotPlugin.onChatMessage(chatMessageEvent); verify(drawManager).requestNextFrameListener(any(Consumer.class)); From 5a529568d66bb056801df1368ec6d46b17751887 Mon Sep 17 00:00:00 2001 From: Alexsuperfly Date: Sun, 24 Jan 2021 17:26:50 -0500 Subject: [PATCH 31/55] timers: Remove cannon timer when cannon is destroyed --- .../java/net/runelite/client/plugins/timers/TimersPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 fb8572a853..341c1c35a0 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 @@ -89,6 +89,7 @@ public class TimersPlugin extends Plugin private static final String CANNON_FURNACE_MESSAGE = "You add the furnace."; private static final String CANNON_PICKUP_MESSAGE = "You pick up the cannon. It's really heavy."; private static final String CANNON_REPAIR_MESSAGE = "You repair your cannon, restoring it to working order."; + private static final String CANNON_DESTROYED_MESSAGE = "Your cannon has been destroyed!"; private static final String CHARGE_EXPIRED_MESSAGE = "Your magical charge fades away."; private static final String CHARGE_MESSAGE = "You feel charged with magic power."; private static final String EXTENDED_ANTIFIRE_DRINK_MESSAGE = "You drink some of your extended antifire potion."; @@ -517,7 +518,7 @@ public class TimersPlugin extends Plugin cannonTimer.setTooltip(cannonTimer.getTooltip() + " - World " + client.getWorld()); } - if (config.showCannon() && message.equals(CANNON_PICKUP_MESSAGE)) + if (config.showCannon() && (message.equals(CANNON_PICKUP_MESSAGE) || message.equals(CANNON_DESTROYED_MESSAGE))) { removeGameTimer(CANNON); } From ecb47ff50b5bdfe148e1051e7fccbf578c6e4021 Mon Sep 17 00:00:00 2001 From: Alexsuperfly Date: Sun, 24 Jan 2021 17:28:01 -0500 Subject: [PATCH 32/55] cannon: Remove cannon when it is destroyed --- .../java/net/runelite/client/plugins/cannon/CannonPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 4d426ae9b6..1f9aeeaa25 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 @@ -304,7 +304,8 @@ public class CannonPlugin extends Plugin } if (event.getMessage().contains("You pick up the cannon") - || event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!")) + || event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!") + || event.getMessage().contains("Your cannon has been destroyed!")) { cannonPlaced = false; cballsLeft = 0; From ca76056feeca9075fecd8bbf17dc5581e8b86837 Mon Sep 17 00:00:00 2001 From: Auenc Date: Tue, 9 Feb 2021 03:56:11 +0000 Subject: [PATCH 33/55] idle notifier: Add Ectofuntus animations (#13177) --- .../src/main/java/net/runelite/api/AnimationID.java | 6 ++++++ .../client/plugins/idlenotifier/IdleNotifierPlugin.java | 4 ++++ 2 files changed, 10 insertions(+) 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 cb2981e15c..9358aa4a9f 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -209,6 +209,12 @@ public final class AnimationID public static final int HOME_MAKE_TABLET = 4067; public static final int DRAGONFIRE_SHIELD_SPECIAL = 6696; + // Ectofuntus animations + public static final int ECTOFUNTUS_FILL_SLIME_BUCKET = 4471; + public static final int ECTOFUNTUS_GRIND_BONES = 1648; + public static final int ECTOFUNTUS_INSERT_BONES = 1649; + public static final int ECTOFUNTUS_EMPTY_BIN = 1650; + // NPC animations public static final int TZTOK_JAD_MAGIC_ATTACK = 2656; public static final int TZTOK_JAD_RANGE_ATTACK = 2652; 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 e9d2d01896..6e3be57ee4 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 @@ -268,6 +268,10 @@ public class IdleNotifierPlugin extends Plugin case MAGIC_ENCHANTING_BOLTS: /* Prayer */ case USING_GILDED_ALTAR: + case ECTOFUNTUS_FILL_SLIME_BUCKET: + case ECTOFUNTUS_INSERT_BONES: + case ECTOFUNTUS_GRIND_BONES: + case ECTOFUNTUS_EMPTY_BIN: /* Farming */ case FARMING_MIX_ULTRACOMPOST: case FARMING_HARVEST_BUSH: From 2a953b497bc7658264a3e6ba73832b2d9748eb55 Mon Sep 17 00:00:00 2001 From: Cyborger1 <45152844+Cyborger1@users.noreply.github.com> Date: Tue, 9 Feb 2021 00:29:34 -0500 Subject: [PATCH 34/55] clues: Improve Lovakengj Sulphur Mine area descriptions (#13180) --- .../client/plugins/cluescrolls/clues/CoordinateClue.java | 2 +- .../plugins/cluescrolls/clues/hotcold/HotColdLocation.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 5918f65343..5c0e093b6c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -229,7 +229,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(2202, 3825, 0), new CoordinateClueInfo("Pirates' Cove, between Lunar Isle and Rellekka.", ANCIENT_WIZARDS)) .put(new WorldPoint(1761, 3853, 0), new CoordinateClueInfo("Arceuus essence mine (CIS).", BRASSICAN_MAGE)) .put(new WorldPoint(2090, 3863, 0), new CoordinateClueInfo("South of Lunar Isle, west of Astral altar.", ANCIENT_WIZARDS)) - .put(new WorldPoint(1442, 3878, 0), new CoordinateClueInfo("Sulphur Mine.", BRASSICAN_MAGE)) + .put(new WorldPoint(1442, 3878, 0), new CoordinateClueInfo("Northern area of the Lovakengj Sulphur Mine. Facemask or Slayer Helmet recommended.", BRASSICAN_MAGE)) .put(new WorldPoint(3380, 3929, 0), new CoordinateClueInfo("Wilderness. Near Volcano.", ANCIENT_WIZARDS)) .put(new WorldPoint(3188, 3939, 0), new CoordinateClueInfo("Wilderness. Resource Area.", BRASSICAN_MAGE)) .put(new WorldPoint(3304, 3941, 0), new CoordinateClueInfo("Wilderness. East of Rogues' Castle.", ANCIENT_WIZARDS)) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java index d2433db61a..74e71b934d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java @@ -165,7 +165,7 @@ public enum HotColdLocation ZEAH_BLASTMINE_NORTH(new WorldPoint(1488, 3881, 0), ZEAH, "Northern part of the Lovakengj blast mine.", BRASSICAN_MAGE), ZEAH_LOVAKITE_FURNACE(new WorldPoint(1507, 3819, 0), ZEAH, "Next to the lovakite furnace in Lovakengj.", ANCIENT_WIZARDS), ZEAH_LOVAKENGJ_MINE(new WorldPoint(1477, 3778, 0), ZEAH, "Next to mithril rock in the Lovakengj mine.", ANCIENT_WIZARDS), - ZEAH_SULPHR_MINE(new WorldPoint(1428, 3869, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine.", BRASSICAN_MAGE), + ZEAH_SULPHR_MINE(new WorldPoint(1428, 3869, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine. Facemask or Slayer Helmet recommended.", BRASSICAN_MAGE), ZEAH_SHAYZIEN_BANK(new WorldPoint(1517, 3603, 0), ZEAH, "South-east of the bank in Shayzien.", ANCIENT_WIZARDS), ZEAH_OVERPASS(new WorldPoint(1467, 3714, 0), ZEAH, "Overpass between Lovakengj and Shayzien.", BRASSICAN_MAGE), ZEAH_LIZARDMAN(new WorldPoint(1490, 3698, 0), ZEAH, "Within Lizardman Canyon, east of the ladder. Requires 5% favour with Shayzien.", ANCIENT_WIZARDS), From 525c64b8dfa239b9bba5e8e7e12ee8684ac130ef Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 9 Feb 2021 11:43:12 -0500 Subject: [PATCH 35/55] farming tracker: don't send notifications for empty crop state --- .../timetracking/farming/FarmingTracker.java | 168 ++++++++++-------- .../farming/FarmingTrackerTest.java | 132 ++++++++++++++ 2 files changed, 221 insertions(+), 79 deletions(-) create mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/timetracking/farming/FarmingTrackerTest.java 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 e01c451b8d..4a381220b2 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 @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.timetracking.farming; +import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; import com.google.inject.Singleton; import java.time.Instant; @@ -500,14 +501,12 @@ public class FarmingTracker Integer offsetPrecisionMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class); Integer offsetTimeMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), TimeTrackingConfig.FARM_TICK_OFFSET, int.class); - RuneScapeProfileType profileType = profile.getType(); - for (Map.Entry> tab : farmingWorld.getTabs().entrySet()) { for (FarmingPatch patch : tab.getValue()) { ProfilePatch profilePatch = new ProfilePatch(patch, profile.getKey()); - boolean patchNotified = (wasNotified.get(profilePatch) != null ? wasNotified.get(profilePatch) : false); + boolean patchNotified = wasNotified.getOrDefault(profilePatch, false); String configKey = patch.notifyConfigKey(); boolean shouldNotify = Boolean.TRUE .equals(configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), configKey, Boolean.class)); @@ -519,94 +518,105 @@ public class FarmingTracker } int tickRate = prediction.getProduce().getTickrate(); - + if (offsetPrecisionMins == null || offsetTimeMins == null || (offsetPrecisionMins < tickRate && offsetPrecisionMins < 40) || prediction.getProduce() == Produce.WEEDS - || unixNow <= prediction.getDoneEstimate() || patchNotified || prediction.getCropState() == CropState.FILLING) + || unixNow <= prediction.getDoneEstimate() || patchNotified || prediction.getCropState() == CropState.FILLING || prediction.getCropState() == CropState.EMPTY) { continue; } wasNotified.put(profilePatch, true); - if (!firstNotifyCheck && shouldNotify) + if (!firstNotifyCheck && shouldNotify) { - final StringBuilder notificationStringBuilder = new StringBuilder(); - // Same RS account - if (client.getGameState() == GameState.LOGGED_IN && profile.getDisplayName().equals(client.getLocalPlayer().getName())) - { - // Same RS account but different profile type - if (profileType != RuneScapeProfileType.getCurrent(client)) - { - notificationStringBuilder.append("(") - .append(Text.titleCase(profile.getType())) - .append(") "); - } - // Same RS account AND profile falls through here so no bracketed prefix is added - } - else - { - // Different RS account AND profile type - if (profileType != RuneScapeProfileType.getCurrent(client) || client.getGameState() == GameState.LOGIN_SCREEN) - { - //Don't print profile type when logged out if is STANDARD - if (client.getGameState() == GameState.LOGIN_SCREEN && profileType == RuneScapeProfileType.STANDARD) - { - notificationStringBuilder.append("(") - .append(profile.getDisplayName()) - .append(") "); - } - else - { - notificationStringBuilder.append("(") - .append(profile.getDisplayName()) - .append(" - ") - .append(Text.titleCase(profile.getType())) - .append(") "); - } - } - // Different RS account but same profile type - else - { - notificationStringBuilder.append("(") - .append(profile.getDisplayName()) - .append(") "); - } - } - - notificationStringBuilder - .append("Your ") - .append(prediction.getProduce().getName()); - - switch (prediction.getCropState()) - { - case HARVESTABLE: - case GROWING: - if (prediction.getProduce().getName().toLowerCase(Locale.ENGLISH).contains("compost")) - { - notificationStringBuilder.append(" is ready to collect in "); - } - else - { - notificationStringBuilder.append(" is ready to harvest in "); - } - break; - case DISEASED: - notificationStringBuilder.append(" has become diseased in "); - break; - case DEAD: - notificationStringBuilder.append(" has died in "); - break; - } - - notificationStringBuilder.append(patch.getRegion().isDefinite() ? "the " : "") - .append(patch.getRegion().getName()) - .append("."); - - notifier.notify(notificationStringBuilder.toString()); + sendNotification(profile, prediction, patch); } } } } firstNotifyCheck = false; } + + @VisibleForTesting + void sendNotification(RuneScapeProfile profile, PatchPrediction prediction, FarmingPatch patch) + { + final RuneScapeProfileType profileType = profile.getType(); + + final StringBuilder stringBuilder = new StringBuilder(); + // Same RS account + if (client.getGameState() == GameState.LOGGED_IN && profile.getDisplayName().equals(client.getLocalPlayer().getName())) + { + // Same RS account but different profile type + if (profileType != RuneScapeProfileType.getCurrent(client)) + { + stringBuilder.append("(") + .append(Text.titleCase(profile.getType())) + .append(") "); + } + // Same RS account AND profile falls through here so no bracketed prefix is added + } + else + { + // Different RS account AND profile type + if (profileType != RuneScapeProfileType.getCurrent(client) || client.getGameState() == GameState.LOGIN_SCREEN) + { + //Don't print profile type when logged out if is STANDARD + if (client.getGameState() == GameState.LOGIN_SCREEN && profileType == RuneScapeProfileType.STANDARD) + { + stringBuilder.append("(") + .append(profile.getDisplayName()) + .append(") "); + } + else + { + stringBuilder.append("(") + .append(profile.getDisplayName()) + .append(" - ") + .append(Text.titleCase(profile.getType())) + .append(") "); + } + } + // Different RS account but same profile type + else + { + stringBuilder.append("(") + .append(profile.getDisplayName()) + .append(") "); + } + } + + stringBuilder + .append("Your ") + .append(prediction.getProduce().getName()); + + switch (prediction.getCropState()) + { + case HARVESTABLE: + case GROWING: + if (prediction.getProduce().getName().toLowerCase(Locale.ENGLISH).contains("compost")) + { + stringBuilder.append(" is ready to collect in "); + } + else + { + stringBuilder.append(" is ready to harvest in "); + } + break; + case DISEASED: + stringBuilder.append(" has become diseased in "); + break; + case DEAD: + stringBuilder.append(" has died in "); + break; + default: + // EMPTY and FILLING are caught above + throw new IllegalStateException(); + } + + stringBuilder.append(patch.getRegion().isDefinite() ? "the " : "") + .append(patch.getRegion().getName()) + .append("."); + + notifier.notify(stringBuilder.toString()); + } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/timetracking/farming/FarmingTrackerTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/timetracking/farming/FarmingTrackerTest.java new file mode 100644 index 0000000000..f407fd0a34 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/timetracking/farming/FarmingTrackerTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021, 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.timetracking.farming; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.EnumSet; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Player; +import net.runelite.api.Varbits; +import net.runelite.api.WorldType; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneScapeProfile; +import net.runelite.client.config.RuneScapeProfileType; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.TimeTrackingConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class FarmingTrackerTest +{ + @Inject + private FarmingTracker farmingTracker; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private ConfigManager configManager; + + @Mock + @Bind + private TimeTrackingConfig config; + + @Mock + @Bind + private FarmingWorld farmingWorld; + + @Mock + @Bind + private Notifier notifier; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + when(client.getWorldType()).thenReturn(EnumSet.noneOf(WorldType.class)); + + Player player = mock(Player.class); + when(player.getName()).thenReturn("Adam"); + when(client.getLocalPlayer()).thenReturn(player); + } + + @Test(expected = IllegalStateException.class) + public void testEmptyNotification() + { + RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, null); + + PatchPrediction patchPrediction = new PatchPrediction(Produce.EMPTY_COMPOST_BIN, CropState.EMPTY, 0L, 0, 0); + FarmingRegion region = new FarmingRegion("Ardougne", 10548, false, + new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), + new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), + new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), + new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB), + new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) + ); + FarmingPatch patch = region.getPatches()[4]; + patch.setRegion(region); + farmingTracker.sendNotification(runeScapeProfile, patchPrediction, patch); + } + + @Test + public void testHarvestableNotification() + { + RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, null); + + PatchPrediction patchPrediction = new PatchPrediction(Produce.RANARR, CropState.HARVESTABLE, 0L, 0, 0); + FarmingRegion region = new FarmingRegion("Ardougne", 10548, false, + new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), + new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), + new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), + new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB), + new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) + ); + FarmingPatch patch = region.getPatches()[3]; + patch.setRegion(region); + farmingTracker.sendNotification(runeScapeProfile, patchPrediction, patch); + + verify(notifier).notify("Your Ranarr is ready to harvest in Ardougne."); + } +} \ No newline at end of file From 0163f79248f5fd063ef081a127ed74ae215d3eb2 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 9 Feb 2021 19:25:23 +0100 Subject: [PATCH 36/55] menu entry swapper: Add battlestaff use swap (#13140) --- .../menuentryswapper/MenuEntrySwapperConfig.java | 11 +++++++++++ .../menuentryswapper/MenuEntrySwapperPlugin.java | 2 ++ 2 files changed, 13 insertions(+) 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 dda54b3c21..63b2e569b5 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 @@ -144,6 +144,17 @@ public interface MenuEntrySwapperConfig extends Config return false; } + @ConfigItem( + keyName = "swapBattlestaves", + name = "Battlestaff", + description = "Swap Wield with Use on Battlestaves without orbs", + section = itemSection + ) + default boolean swapBattlestaves() + { + return false; + } + @ConfigItem( keyName = "swapPrayerBook", name = "Recite-Prayer", 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 b72c138391..b6cb75aa15 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 @@ -334,6 +334,8 @@ public class MenuEntrySwapperPlugin extends Plugin swap("bury", "use", config::swapBones); + swap("wield", "battlestaff", "use", config::swapBattlestaves); + swap("clean", "use", config::swapHerbs); swap("read", "recite-prayer", config::swapPrayerBook); From c3e96d72f11f48e116233af76d239de264d0faca Mon Sep 17 00:00:00 2001 From: ObsoleteXero <51947152+ObsoleteXero@users.noreply.github.com> Date: Tue, 9 Feb 2021 23:56:22 +0530 Subject: [PATCH 37/55] idle notifier: Add Loom crafting animation (#13154) --- runelite-api/src/main/java/net/runelite/api/AnimationID.java | 1 + .../client/plugins/idlenotifier/IdleNotifierPlugin.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) 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 9358aa4a9f..7c4d40e61c 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -97,6 +97,7 @@ public final class AnimationID public static final int CRAFTING_SPINNING = 894; public static final int CRAFTING_POTTERS_WHEEL = 883; public static final int CRAFTING_POTTERY_OVEN = 24975; + public static final int CRAFTING_LOOM = 2270; public static final int SMITHING_SMELTING = 899; public static final int SMITHING_CANNONBALL = 827; //cball smithing uses this and SMITHING_SMELTING public static final int SMITHING_ANVIL = 898; 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 6e3be57ee4..79ca4413e3 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 @@ -147,7 +147,7 @@ public class IdleNotifierPlugin extends Plugin case COOKING_FIRE: case COOKING_RANGE: case COOKING_WINE: - /* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves, Pottery) */ + /* Crafting(Gem Cutting, Glassblowing, Spinning, Weaving, Battlestaves, Pottery) */ case GEM_CUTTING_OPAL: case GEM_CUTTING_JADE: case GEM_CUTTING_REDTOPAZ: @@ -158,6 +158,7 @@ public class IdleNotifierPlugin extends Plugin case GEM_CUTTING_AMETHYST: case CRAFTING_GLASSBLOWING: case CRAFTING_SPINNING: + case CRAFTING_LOOM: case CRAFTING_BATTLESTAVES: case CRAFTING_LEATHER: case CRAFTING_POTTERS_WHEEL: From 8d543933c901eb021428643393c0e074e1a76ddb Mon Sep 17 00:00:00 2001 From: Anjaneya Bhardwaj Date: Tue, 9 Feb 2021 14:01:11 -0500 Subject: [PATCH 38/55] fishing: Add minnows flying fish notification (#13126) --- .../client/plugins/fishing/FishingConfig.java | 13 ++++++++++++- .../client/plugins/fishing/FishingPlugin.java | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java index e48d80edbd..6e68c4270a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java @@ -150,6 +150,17 @@ public interface FishingConfig extends Config @ConfigItem( position = 10, + keyName = "flyingFishNotification", + name = "Flying fish notification", + description = "Send a notification when a flying fish spawns on your fishing spot." + ) + default boolean flyingFishNotification() + { + return true; + } + + @ConfigItem( + position = 11, keyName = "trawlerNotification", name = "Trawler activity notification", description = "Send a notification when fishing trawler activity drops below 15%." @@ -160,7 +171,7 @@ public interface FishingConfig extends Config } @ConfigItem( - position = 11, + position = 12, keyName = "trawlerTimer", name = "Trawler timer in MM:SS", description = "Trawler Timer will display a more accurate timer in MM:SS format." 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 1311021c29..0c5fa99dc2 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 @@ -215,6 +215,11 @@ public class FishingPlugin extends Plugin spotOverlay.setHidden(false); fishingSpotMinimapOverlay.setHidden(false); } + + if (event.getMessage().equals("A flying fish jumps up and eats some of your minnows!") && config.flyingFishNotification()) + { + notifier.notify("A flying fish is eating your minnows!"); + } } @Subscribe From 7656cafc70682a7801c5e8314adc66423e07ce64 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 9 Feb 2021 13:45:39 -0500 Subject: [PATCH 39/55] chat commands: comma separate values in several commands --- .../plugins/chatcommands/ChatCommandsPlugin.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 8923f1684a..8c06945a66 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 @@ -666,7 +666,7 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append(" kill count: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(kc)) + .append(String.format("%,d", kc)) .build(); log.debug("Setting response {}", response); @@ -748,15 +748,15 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append("Duel Arena wins: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(wins)) + .append(String.format("%,d", wins)) .append(ChatColorType.NORMAL) .append(" losses: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(losses)) + .append(String.format("%,d", losses)) .append(ChatColorType.NORMAL) .append(" streak: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString((winningStreak != 0 ? winningStreak : -losingStreak))) + .append(String.format("%,d", winningStreak != 0 ? winningStreak : -losingStreak)) .build(); log.debug("Setting response {}", response); @@ -957,7 +957,7 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append("Barbarian Assault High-level gambles: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(gc)) + .append(String.format("%,d", gc)) .build(); log.debug("Setting response {}", response); @@ -1420,7 +1420,7 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append("Clue scroll (" + level + ")").append(": ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(quantity)); + .append(String.format("%,d", quantity)); if (rank != -1) { From bfc9af5526861e6c2b21163702329814c42fbf80 Mon Sep 17 00:00:00 2001 From: loldudester Date: Tue, 9 Feb 2021 21:31:16 +0000 Subject: [PATCH 40/55] TimeTracking: Return shortened weekdays in doneEstimates --- .../runelite/client/plugins/timetracking/TabContentPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java index dd3a2bba5b..88b6362e26 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java @@ -77,7 +77,7 @@ public abstract class TabContentPanel extends JPanel LocalDateTime currentTime = LocalDateTime.now(); if (endTime.getDayOfWeek() != currentTime.getDayOfWeek()) { - sb.append(endTime.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault())).append(" "); + sb.append(endTime.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.getDefault())).append(" "); } sb.append("at "); sb.append(formatter.format(endTime)); From 80e5d442432fe220acefeb485842e0831c35774a Mon Sep 17 00:00:00 2001 From: Nick Wolff Date: Tue, 9 Feb 2021 21:50:35 -0800 Subject: [PATCH 41/55] emoji: Add weary face emoji --- .../net/runelite/client/plugins/emojis/Emoji.java | 1 + .../runelite/client/plugins/emojis/weary_face.png | Bin 0 -> 339 bytes 2 files changed, 1 insertion(+) create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/emojis/weary_face.png diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java index 97e94e40bf..8eb163ba53 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java @@ -92,6 +92,7 @@ enum Emoji PLEADING("(n_n)"), XD("Xd"), SPOON("--o"), + WEARY_FACE("Dx"), ; private static final Map emojiMap; diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/weary_face.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/weary_face.png new file mode 100644 index 0000000000000000000000000000000000000000..f8b113ea2d7d09c6b2bce31ae2abf2a0b7a8adc4 GIT binary patch literal 339 zcmV-Z0j&OsP)@W)t48Jm$7QnQ|Jqjw!j1D%-3(_{K{0#7O$bO1X|I`^ZbZk}R=@ zCV*TG>A6CJUJkK{CcBU;`^ihwrZ=E?9o(%u+pRmHc^=oPIq|?o;j%vS!AF>K9g}=Z zqmO3w!$^&7C(XmG)y%ol$+f<=>Px# z0(4SNQvd*Vlg&5)003u6L_t&t9R zW^0KKY=3R&jIZ Date: Tue, 9 Feb 2021 14:25:46 +0000 Subject: [PATCH 42/55] ground markers: show existing label when labeling a marker --- .../groundmarkers/GroundMarkerPlugin.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) 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 cfb6171941..81ac210bfc 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,6 +34,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import javax.inject.Inject; import lombok.AccessLevel; @@ -313,21 +314,22 @@ public class GroundMarkerPlugin extends Plugin WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, localPoint); final int regionId = worldPoint.getRegionID(); + GroundMarkerPoint searchPoint = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), null, null); + Collection points = getPoints(regionId); + GroundMarkerPoint existing = points.stream() + .filter(p -> p.equals(searchPoint)) + .findFirst().orElse(null); + if (existing == null) + { + return; + } + chatboxPanelManager.openTextInput("Tile label") + .value(Optional.ofNullable(existing.getLabel()).orElse("")) .onDone((input) -> { input = Strings.emptyToNull(input); - GroundMarkerPoint searchPoint = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), null, null); - Collection points = getPoints(regionId); - GroundMarkerPoint existing = points.stream() - .filter(p -> p.equals(searchPoint)) - .findFirst().orElse(null); - if (existing == null) - { - return; - } - GroundMarkerPoint newPoint = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), existing.getColor(), input); points.remove(searchPoint); points.add(newPoint); From 13efaa6a0c7294b1526ae8d25471708d45d248d6 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 10 Feb 2021 21:01:53 -0500 Subject: [PATCH 43/55] gpu: add opencl support for macos This allows using opencl as an alternative to opengl compute shaders on macos, which does not support compute shaders. Now, macos can finally use the extended draw distance feature of the gpu plugin. This also includes code for using opencl with Windows and Linux if we want to enable that in the future. A copy of the existing compute shaders have been checked in and ported to opencl, keeping support for opengl compute shaders on Windows and Linux. Co-authored-by: Paul Norton --- runelite-client/pom.xml | 19 + .../runelite/client/plugins/gpu/GLBuffer.java | 40 ++ .../client/plugins/gpu/GpuPlugin.java | 399 ++++++++------ .../client/plugins/gpu/OpenCLManager.java | 521 ++++++++++++++++++ .../runelite/client/plugins/gpu/cl_types.cl | 55 ++ .../net/runelite/client/plugins/gpu/common.cl | 104 ++++ .../net/runelite/client/plugins/gpu/comp.cl | 97 ++++ .../client/plugins/gpu/comp_unordered.cl | 87 +++ .../client/plugins/gpu/priority_render.cl | 298 ++++++++++ 9 files changed, 1445 insertions(+), 175 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLBuffer.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/gpu/OpenCLManager.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/gpu/cl_types.cl create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/gpu/common.cl create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.cl create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.cl create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.cl diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 10000e6125..48eb8825ce 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -177,6 +177,25 @@ 2.4.0-rc-20210117 runtime + + net.runelite.jocl + jocl + 1.0 + + + net.runelite.jocl + jocl + 1.0 + macos-x64 + runtime + + + net.runelite.jocl + jocl + 1.0 + macos-arm64 + runtime + net.runelite archive-patcher diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLBuffer.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLBuffer.java new file mode 100644 index 0000000000..cd3b7288ed --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLBuffer.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, 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 org.jocl.Pointer; +import org.jocl.cl_mem; + +class GLBuffer +{ + int glBufferId = -1; + int size = -1; + cl_mem cl_mem; + + Pointer ptr() + { + return cl_mem != null ? Pointer.to(cl_mem) : null; + } +} 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 a6be4e5872..8ba9db5a67 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 @@ -29,6 +29,11 @@ import com.google.inject.Provides; import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; import com.jogamp.nativewindow.awt.JAWTWindow; import com.jogamp.opengl.GL; +import static com.jogamp.opengl.GL.GL_ARRAY_BUFFER; +import static com.jogamp.opengl.GL.GL_DYNAMIC_DRAW; +import static com.jogamp.opengl.GL2ES2.GL_STREAM_DRAW; +import static com.jogamp.opengl.GL2ES3.GL_STATIC_COPY; +import static com.jogamp.opengl.GL2ES3.GL_UNIFORM_BUFFER; import com.jogamp.opengl.GL4; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLContext; @@ -45,6 +50,7 @@ import java.awt.Image; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; @@ -93,6 +99,10 @@ import net.runelite.client.plugins.gpu.config.UIScalingMode; import net.runelite.client.plugins.gpu.template.Template; import net.runelite.client.ui.DrawManager; import net.runelite.client.util.OSType; +import org.jocl.CL; +import static org.jocl.CL.CL_MEM_READ_ONLY; +import static org.jocl.CL.CL_MEM_WRITE_ONLY; +import static org.jocl.CL.clCreateFromGLBuffer; @PluginDescriptor( name = "GPU", @@ -105,8 +115,8 @@ import net.runelite.client.util.OSType; public class GpuPlugin extends Plugin implements DrawCallbacks { // This is the maximum number of triangles the compute shaders support - private static final int MAX_TRIANGLE = 4096; - private static final int SMALL_TRIANGLE_COUNT = 512; + static final int MAX_TRIANGLE = 4096; + static final int SMALL_TRIANGLE_COUNT = 512; private static final int FLAG_SCENE_BUFFER = Integer.MIN_VALUE; private static final int DEFAULT_DISTANCE = 25; static final int MAX_DISTANCE = 90; @@ -115,6 +125,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Inject private Client client; + @Inject + private OpenCLManager openCLManager; + @Inject private ClientThread clientThread; @@ -133,7 +146,14 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Inject private PluginManager pluginManager; - private boolean useComputeShaders; + enum ComputeMode + { + NONE, + OPENGL, + OPENCL + } + + private ComputeMode computeMode = ComputeMode.NONE; private Canvas canvas; private JAWTWindow jawtWindow; @@ -182,23 +202,22 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int texSceneHandle; private int rboSceneHandle; - // scene vertex buffer id - private int bufferId; - // scene uv buffer id - private int uvBufferId; + // scene vertex buffer + private final GLBuffer sceneVertexBuffer = new GLBuffer(); + // scene uv buffer + private final GLBuffer sceneUvBuffer = new GLBuffer(); - private int tmpBufferId; // temporary scene vertex buffer - private int tmpUvBufferId; // temporary scene uv buffer - private int tmpModelBufferId; // scene model buffer, large - private int tmpModelBufferSmallId; // scene model buffer, small - private int tmpModelBufferUnorderedId; - private int tmpOutBufferId; // target vertex buffer for compute shaders - private int tmpOutUvBufferId; // target uv buffer for compute shaders + private final GLBuffer tmpVertexBuffer = new GLBuffer(); // temporary scene vertex buffer + private final GLBuffer tmpUvBuffer = new GLBuffer(); // temporary scene uv buffer + private final GLBuffer tmpModelBufferLarge = new GLBuffer(); // scene model buffer, large + private final GLBuffer tmpModelBufferSmall = new GLBuffer(); // scene model buffer, small + private final GLBuffer tmpModelBufferUnordered = new GLBuffer(); // scene model buffer, unordered + private final GLBuffer tmpOutBuffer = new GLBuffer(); // target vertex buffer for compute shaders + private final GLBuffer tmpOutUvBuffer = new GLBuffer(); // target uv buffer for compute shaders private int textureArrayId; - private int uniformBufferId; - private final IntBuffer uniformBuffer = GpuIntBuffer.allocateDirect(5 + 3 + 2048 * 4); + private final GLBuffer uniformBuffer = new GLBuffer(); private final float[] textureOffsets = new float[128]; private GpuIntBuffer vertexBuffer; @@ -278,7 +297,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks { try { - bufferId = uvBufferId = uniformBufferId = tmpBufferId = tmpUvBufferId = tmpModelBufferId = tmpModelBufferSmallId = tmpModelBufferUnorderedId = tmpOutBufferId = tmpOutUvBufferId = -1; texSceneHandle = fboSceneHandle = rboSceneHandle = -1; // AA FBO unorderedModels = smallModels = largeModels = 0; drawingModel = false; @@ -290,8 +308,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks return false; } - // OSX supports up to OpenGL 4.1, however 4.3 is required for compute shaders - useComputeShaders = config.useComputeShaders() && OSType.getOSType() != OSType.MacOS; + computeMode = config.useComputeShaders() + ? (OSType.getOSType() == OSType.MacOS ? ComputeMode.OPENCL : ComputeMode.OPENGL) + : ComputeMode.NONE; canvas.setIgnoreRepaint(true); @@ -397,7 +416,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks if (client.getGameState() == GameState.LOGGED_IN) { - uploadScene(); + invokeOnMainThread(this::uploadScene); } } catch (Throwable e) @@ -433,6 +452,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks invokeOnMainThread(() -> { + openCLManager.cleanup(); + if (gl != null) { if (textureArrayId != -1) @@ -441,11 +462,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks textureArrayId = -1; } - if (uniformBufferId != -1) - { - glDeleteBuffer(gl, uniformBufferId); - uniformBufferId = -1; - } + destroyGlBuffer(uniformBuffer); shutdownBuffers(); shutdownInterfaceTexture(); @@ -519,12 +536,16 @@ public class GpuPlugin extends Plugin implements DrawCallbacks glProgram = PROGRAM.compile(gl, template); glUiProgram = UI_PROGRAM.compile(gl, template); - if (useComputeShaders) + if (computeMode == ComputeMode.OPENGL) { glComputeProgram = COMPUTE_PROGRAM.compile(gl, template); glSmallComputeProgram = SMALL_COMPUTE_PROGRAM.compile(gl, template); glUnorderedComputeProgram = UNORDERED_COMPUTE_PROGRAM.compile(gl, template); } + else if (computeMode == ComputeMode.OPENCL) + { + openCLManager.init(gl); + } initUniforms(); } @@ -593,8 +614,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks -1f, 1f, 0.0f, 0.0f, 0f // top left }); vboUiBuf.rewind(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboUiHandle); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vboUiBuf.capacity() * Float.BYTES, vboUiBuf, gl.GL_STATIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vboUiHandle); + gl.glBufferData(GL_ARRAY_BUFFER, vboUiBuf.capacity() * Float.BYTES, vboUiBuf, gl.GL_STATIC_DRAW); // position attribute gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, false, 5 * Float.BYTES, 0); @@ -605,7 +626,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glEnableVertexAttribArray(1); // unbind VBO - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0); + gl.glBindBuffer(GL_ARRAY_BUFFER, 0); } private void shutdownVao() @@ -622,71 +643,49 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void initBuffers() { - bufferId = glGenBuffers(gl); - uvBufferId = glGenBuffers(gl); - tmpBufferId = glGenBuffers(gl); - tmpUvBufferId = glGenBuffers(gl); - tmpModelBufferId = glGenBuffers(gl); - tmpModelBufferSmallId = glGenBuffers(gl); - tmpModelBufferUnorderedId = glGenBuffers(gl); - tmpOutBufferId = glGenBuffers(gl); - tmpOutUvBufferId = glGenBuffers(gl); + initGlBuffer(sceneVertexBuffer); + initGlBuffer(sceneUvBuffer); + initGlBuffer(tmpVertexBuffer); + initGlBuffer(tmpUvBuffer); + initGlBuffer(tmpModelBufferLarge); + initGlBuffer(tmpModelBufferSmall); + initGlBuffer(tmpModelBufferUnordered); + initGlBuffer(tmpOutBuffer); + initGlBuffer(tmpOutUvBuffer); + } + + private void initGlBuffer(GLBuffer glBuffer) + { + glBuffer.glBufferId = glGenBuffers(gl); } private void shutdownBuffers() { - if (bufferId != -1) - { - glDeleteBuffer(gl, bufferId); - bufferId = -1; - } + destroyGlBuffer(sceneVertexBuffer); + destroyGlBuffer(sceneUvBuffer); - if (uvBufferId != -1) - { - glDeleteBuffer(gl, uvBufferId); - uvBufferId = -1; - } + destroyGlBuffer(tmpVertexBuffer); + destroyGlBuffer(tmpUvBuffer); + destroyGlBuffer(tmpModelBufferLarge); + destroyGlBuffer(tmpModelBufferSmall); + destroyGlBuffer(tmpModelBufferUnordered); + destroyGlBuffer(tmpOutBuffer); + destroyGlBuffer(tmpOutUvBuffer); + } - if (tmpBufferId != -1) + private void destroyGlBuffer(GLBuffer glBuffer) + { + if (glBuffer.glBufferId != -1) { - glDeleteBuffer(gl, tmpBufferId); - tmpBufferId = -1; + glDeleteBuffer(gl, glBuffer.glBufferId); + glBuffer.glBufferId = -1; } + glBuffer.size = -1; - if (tmpUvBufferId != -1) + if (glBuffer.cl_mem != null) { - glDeleteBuffer(gl, tmpUvBufferId); - tmpUvBufferId = -1; - } - - if (tmpModelBufferId != -1) - { - glDeleteBuffer(gl, tmpModelBufferId); - tmpModelBufferId = -1; - } - - if (tmpModelBufferSmallId != -1) - { - glDeleteBuffer(gl, tmpModelBufferSmallId); - tmpModelBufferSmallId = -1; - } - - if (tmpModelBufferUnorderedId != -1) - { - glDeleteBuffer(gl, tmpModelBufferUnorderedId); - tmpModelBufferUnorderedId = -1; - } - - if (tmpOutBufferId != -1) - { - glDeleteBuffer(gl, tmpOutBufferId); - tmpOutBufferId = -1; - } - - if (tmpOutUvBufferId != -1) - { - glDeleteBuffer(gl, tmpOutUvBufferId); - tmpOutUvBufferId = -1; + CL.clReleaseMemObject(glBuffer.cl_mem); + glBuffer.cl_mem = null; } } @@ -709,21 +708,21 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void initUniformBuffer() { - uniformBufferId = glGenBuffers(gl); - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, uniformBufferId); - uniformBuffer.clear(); - uniformBuffer.put(new int[8]); + initGlBuffer(uniformBuffer); + + IntBuffer uniformBuf = GpuIntBuffer.allocateDirect(8 + 2048 * 4); + uniformBuf.put(new int[8]); // uniform block final int[] pad = new int[2]; for (int i = 0; i < 2048; i++) { - uniformBuffer.put(Perspective.SINE[i]); - uniformBuffer.put(Perspective.COSINE[i]); - uniformBuffer.put(pad); + uniformBuf.put(Perspective.SINE[i]); + uniformBuf.put(Perspective.COSINE[i]); + uniformBuf.put(pad); // ivec2 alignment in std140 is 16 bytes } - uniformBuffer.flip(); + uniformBuf.flip(); - gl.glBufferData(gl.GL_UNIFORM_BUFFER, uniformBuffer.limit() * Integer.BYTES, uniformBuffer, gl.GL_DYNAMIC_DRAW); - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0); + updateBuffer(uniformBuffer, GL_UNIFORM_BUFFER, uniformBuf.limit() * Integer.BYTES, uniformBuf, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + gl.glBindBuffer(GL_UNIFORM_BUFFER, 0); } private void initAAFbo(int width, int height, int aaSamples) @@ -785,9 +784,11 @@ public class GpuPlugin extends Plugin implements DrawCallbacks invokeOnMainThread(() -> { // UBO. Only the first 32 bytes get modified here, the rest is the constant sin/cos table. - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, uniformBufferId); - uniformBuffer.clear(); - uniformBuffer + // We can reuse the vertex buffer since it isn't used yet. + vertexBuffer.clear(); + vertexBuffer.ensureCapacity(32); + IntBuffer uniformBuf = vertexBuffer.getBuffer(); + uniformBuf .put(yaw) .put(pitch) .put(client.getCenterX()) @@ -796,12 +797,14 @@ public class GpuPlugin extends Plugin implements DrawCallbacks .put(cameraX) .put(cameraY) .put(cameraZ); - uniformBuffer.flip(); + uniformBuf.flip(); - gl.glBufferSubData(gl.GL_UNIFORM_BUFFER, 0, uniformBuffer.limit() * Integer.BYTES, uniformBuffer); - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0); + gl.glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer.glBufferId); + gl.glBufferSubData(GL_UNIFORM_BUFFER, 0, uniformBuf.limit() * Integer.BYTES, uniformBuf); + gl.glBindBuffer(GL_UNIFORM_BUFFER, 0); - gl.glBindBufferBase(gl.GL_UNIFORM_BUFFER, 0, uniformBufferId); + gl.glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer.glBufferId); + uniformBuf.clear(); }); } @@ -813,7 +816,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void postDraw() { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { // Upload buffers vertexBuffer.flip(); @@ -822,12 +825,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks IntBuffer vertexBuffer = this.vertexBuffer.getBuffer(); FloatBuffer uvBuffer = this.uvBuffer.getBuffer(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpUvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, gl.GL_DYNAMIC_DRAW); - + updateBuffer(tmpVertexBuffer, GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, GL_DYNAMIC_DRAW, 0L); + updateBuffer(tmpUvBuffer, GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, GL_DYNAMIC_DRAW, 0L); return; } @@ -844,79 +843,91 @@ public class GpuPlugin extends Plugin implements DrawCallbacks IntBuffer modelBufferSmall = this.modelBufferSmall.getBuffer(); IntBuffer modelBufferUnordered = this.modelBufferUnordered.getBuffer(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, gl.GL_DYNAMIC_DRAW); + // temp buffers + updateBuffer(tmpVertexBuffer, GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + updateBuffer(tmpUvBuffer, GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpUvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpModelBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, modelBuffer.limit() * Integer.BYTES, modelBuffer, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpModelBufferSmallId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, modelBufferSmall.limit() * Integer.BYTES, modelBufferSmall, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpModelBufferUnorderedId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, modelBufferUnordered.limit() * Integer.BYTES, modelBufferUnordered, gl.GL_DYNAMIC_DRAW); + // model buffers + updateBuffer(tmpModelBufferLarge, GL_ARRAY_BUFFER, modelBuffer.limit() * Integer.BYTES, modelBuffer, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + updateBuffer(tmpModelBufferSmall, GL_ARRAY_BUFFER, modelBufferSmall.limit() * Integer.BYTES, modelBufferSmall, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + updateBuffer(tmpModelBufferUnordered, GL_ARRAY_BUFFER, modelBufferUnordered.limit() * Integer.BYTES, modelBufferUnordered, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); // Output buffers - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpOutBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, + updateBuffer(tmpOutBuffer, + GL_ARRAY_BUFFER, targetBufferOffset * 16, // each vertex is an ivec4, which is 16 bytes null, - gl.GL_STREAM_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpOutUvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, - targetBufferOffset * 16, + GL_STREAM_DRAW, + CL_MEM_WRITE_ONLY); + updateBuffer(tmpOutUvBuffer, + GL_ARRAY_BUFFER, + targetBufferOffset * 16, // each vertex is an ivec4, which is 16 bytes null, - gl.GL_STREAM_DRAW); + GL_STREAM_DRAW, + CL_MEM_WRITE_ONLY); - // Bind UBO to compute programs - gl.glUniformBlockBinding(glSmallComputeProgram, uniBlockSmall, 0); - gl.glUniformBlockBinding(glComputeProgram, uniBlockLarge, 0); + if (computeMode == ComputeMode.OPENCL) + { + // The docs for clEnqueueAcquireGLObjects say all pending GL operations must be completed before calling + // clEnqueueAcquireGLObjects, and recommends calling glFinish() as the only portable way to do that. + // However no issues have been observed from not calling it, and so will leave disabled for now. + // gl.glFinish(); + + openCLManager.compute( + unorderedModels, smallModels, largeModels, + sceneVertexBuffer, sceneUvBuffer, + tmpVertexBuffer, tmpUvBuffer, + tmpModelBufferUnordered, tmpModelBufferSmall, tmpModelBufferLarge, + tmpOutBuffer, tmpOutUvBuffer, + uniformBuffer); + return; + } /* * Compute is split into three separate programs: 'unordered', 'small', and 'large' * to save on GPU resources. Small will sort <= 512 faces, large will do <= 4096. */ + // Bind UBO to compute programs + gl.glUniformBlockBinding(glSmallComputeProgram, uniBlockSmall, 0); + gl.glUniformBlockBinding(glComputeProgram, uniBlockLarge, 0); + // unordered gl.glUseProgram(glUnorderedComputeProgram); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferUnorderedId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferUnordered.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, sceneVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, sceneUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBuffer.glBufferId); gl.glDispatchCompute(unorderedModels, 1, 1); // small gl.glUseProgram(glSmallComputeProgram); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferSmallId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferSmall.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, sceneVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, sceneUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBuffer.glBufferId); gl.glDispatchCompute(smallModels, 1, 1); // large gl.glUseProgram(glComputeProgram); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferLarge.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, sceneVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, sceneUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBuffer.glBufferId); gl.glDispatchCompute(largeModels, 1, 1); } @@ -926,7 +937,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks SceneTilePaint paint, int tileZ, int tileX, int tileY, int zoom, int centerX, int centerY) { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { targetBufferOffset += sceneUploader.upload(paint, tileZ, tileX, tileY, @@ -963,7 +974,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks SceneTileModel model, int tileZ, int tileX, int tileY, int zoom, int centerX, int centerY) { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { targetBufferOffset += sceneUploader.upload(model, tileX, tileY, @@ -1131,7 +1142,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks // 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; @@ -1195,27 +1206,36 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glBindVertexArray(vaoHandle); int vertexBuffer, uvBuffer; - if (useComputeShaders) + if (computeMode != ComputeMode.NONE) { - // Before reading the SSBOs written to from postDrawScene() we must insert a barrier - gl.glMemoryBarrier(gl.GL_SHADER_STORAGE_BARRIER_BIT); + if (computeMode == ComputeMode.OPENGL) + { + // Before reading the SSBOs written to from postDrawScene() we must insert a barrier + gl.glMemoryBarrier(gl.GL_SHADER_STORAGE_BARRIER_BIT); + } + else + { + // Wait for the command queue to finish, so that we know the compute is done + openCLManager.finish(); + } + // Draw using the output buffer of the compute - vertexBuffer = tmpOutBufferId; - uvBuffer = tmpOutUvBufferId; + vertexBuffer = tmpOutBuffer.glBufferId; + uvBuffer = tmpOutUvBuffer.glBufferId; } else { // Only use the temporary buffers, which will contain the full scene - vertexBuffer = tmpBufferId; - uvBuffer = tmpUvBufferId; + vertexBuffer = tmpVertexBuffer.glBufferId; + uvBuffer = tmpUvBuffer.glBufferId; } gl.glEnableVertexAttribArray(0); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vertexBuffer); + gl.glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); gl.glVertexAttribIPointer(0, 4, gl.GL_INT, 0, 0); gl.glEnableVertexAttribArray(1); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, uvBuffer); + gl.glBindBuffer(GL_ARRAY_BUFFER, uvBuffer); gl.glVertexAttribPointer(1, 4, gl.GL_FLOAT, false, 0, 0); gl.glDrawArrays(gl.GL_TRIANGLES, 0, targetBufferOffset); @@ -1400,12 +1420,12 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Subscribe public void onGameStateChanged(GameStateChanged gameStateChanged) { - if (!useComputeShaders || gameStateChanged.getGameState() != GameState.LOGGED_IN) + if (computeMode == ComputeMode.NONE || gameStateChanged.getGameState() != GameState.LOGGED_IN) { return; } - uploadScene(); + invokeOnMainThread(this::uploadScene); } private void uploadScene() @@ -1421,13 +1441,10 @@ public class GpuPlugin extends Plugin implements DrawCallbacks IntBuffer vertexBuffer = this.vertexBuffer.getBuffer(); FloatBuffer uvBuffer = this.uvBuffer.getBuffer(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, bufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, gl.GL_STATIC_COPY); + updateBuffer(sceneVertexBuffer, GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, GL_STATIC_COPY, CL_MEM_READ_ONLY); + updateBuffer(sceneUvBuffer, GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, GL_STATIC_COPY, CL_MEM_READ_ONLY); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, uvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, gl.GL_STATIC_COPY); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0); + gl.glBindBuffer(GL_ARRAY_BUFFER, 0); vertexBuffer.clear(); uvBuffer.clear(); @@ -1492,7 +1509,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Override public void draw(Renderable renderable, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash) { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { Model model = renderable instanceof Model ? (Model) renderable : renderable.getModel(); if (model != null) @@ -1673,7 +1690,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int getDrawDistance() { - final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE; + final int limit = computeMode != ComputeMode.NONE ? MAX_DISTANCE : DEFAULT_DISTANCE; return Ints.constrainToRange(config.drawDistance(), 0, limit); } @@ -1688,4 +1705,36 @@ public class GpuPlugin extends Plugin implements DrawCallbacks runnable.run(); } } + + private void updateBuffer(GLBuffer glBuffer, int target, int size, Buffer data, int usage, long clFlags) + { + gl.glBindBuffer(target, glBuffer.glBufferId); + if (size > glBuffer.size) + { + log.trace("Buffer resize: {} {} -> {}", glBuffer, glBuffer.size, size); + + glBuffer.size = size; + gl.glBufferData(target, size, data, usage); + + if (computeMode == ComputeMode.OPENCL) + { + if (glBuffer.cl_mem != null) + { + CL.clReleaseMemObject(glBuffer.cl_mem); + } + if (size == 0) + { + glBuffer.cl_mem = null; + } + else + { + glBuffer.cl_mem = clCreateFromGLBuffer(openCLManager.context, clFlags, glBuffer.glBufferId, null); + } + } + } + else if (data != null) + { + gl.glBufferSubData(target, 0, size, data); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/OpenCLManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/OpenCLManager.java new file mode 100644 index 0000000000..77c2f9b575 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/OpenCLManager.java @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2021, 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 com.google.common.base.Charsets; +import com.jogamp.nativewindow.NativeSurface; +import com.jogamp.opengl.GL4; +import com.jogamp.opengl.GLContext; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; +import javax.inject.Singleton; +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.egl.EGLContext; +import jogamp.opengl.macosx.cgl.CGL; +import jogamp.opengl.windows.wgl.WindowsWGLContext; +import jogamp.opengl.x11.glx.X11GLXContext; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.plugins.gpu.template.Template; +import net.runelite.client.util.OSType; +import org.jocl.CL; +import static org.jocl.CL.*; +import org.jocl.CLException; +import org.jocl.Pointer; +import org.jocl.Sizeof; +import org.jocl.cl_command_queue; +import org.jocl.cl_context; +import org.jocl.cl_context_properties; +import org.jocl.cl_device_id; +import org.jocl.cl_event; +import org.jocl.cl_kernel; +import org.jocl.cl_mem; +import org.jocl.cl_platform_id; +import org.jocl.cl_program; + +@Singleton +@Slf4j +class OpenCLManager +{ + private static final String GL_SHARING_PLATFORM_EXT = "cl_khr_gl_sharing"; + + private static final String KERNEL_NAME_UNORDERED = "computeUnordered"; + private static final String KERNEL_NAME_LARGE = "computeLarge"; + + private static final int MIN_WORK_GROUP_SIZE = 256; + private static final int SMALL_SIZE = GpuPlugin.SMALL_TRIANGLE_COUNT; + private static final int LARGE_SIZE = GpuPlugin.MAX_TRIANGLE; + // struct shared_data { + // int totalNum[12]; + // int totalDistance[12]; + // int totalMappedNum[18]; + // int min10; + // int dfs[0]; + // }; + private static final int SHARED_SIZE = 12 + 12 + 18 + 1; // in ints + + // The number of faces each worker processes in the two kernels + private int largeFaceCount; + private int smallFaceCount; + + private cl_platform_id platform; + private cl_device_id device; + cl_context context; + private cl_command_queue commandQueue; + + private cl_program programUnordered; + private cl_program programSmall; + private cl_program programLarge; + + private cl_kernel kernelUnordered; + private cl_kernel kernelSmall; + private cl_kernel kernelLarge; + + void init(GL4 gl) + { + CL.setExceptionsEnabled(true); + + switch (OSType.getOSType()) + { + case Windows: + case Linux: + initPlatform(); + initDevice(); + initContext(gl); + break; + case MacOS: + initMacOS(gl); + break; + default: + throw new RuntimeException("Unsupported OS Type " + OSType.getOSType().name()); + } + ensureMinWorkGroupSize(); + initQueue(); + compilePrograms(); + } + + void cleanup() + { + if (programUnordered != null) + { + CL.clReleaseProgram(programUnordered); + programUnordered = null; + } + + if (programSmall != null) + { + CL.clReleaseProgram(programSmall); + programSmall = null; + } + + if (programLarge != null) + { + CL.clReleaseProgram(programLarge); + programLarge = null; + } + + if (kernelUnordered != null) + { + CL.clReleaseKernel(kernelUnordered); + kernelUnordered = null; + } + + if (kernelSmall != null) + { + CL.clReleaseKernel(kernelSmall); + kernelSmall = null; + } + + if (kernelLarge != null) + { + CL.clReleaseKernel(kernelLarge); + kernelLarge = null; + } + + if (commandQueue != null) + { + CL.clReleaseCommandQueue(commandQueue); + commandQueue = null; + } + + if (context != null) + { + CL.clReleaseContext(context); + context = null; + } + + if (device != null) + { + CL.clReleaseDevice(device); + device = null; + } + } + + private String logPlatformInfo(cl_platform_id platform, int param) + { + long[] size = new long[1]; + clGetPlatformInfo(platform, param, 0, null, size); + + byte[] buffer = new byte[(int) size[0]]; + clGetPlatformInfo(platform, param, buffer.length, Pointer.to(buffer), null); + String platformInfo = new String(buffer, Charsets.UTF_8); + log.debug("Platform: {}, {}", stringFor_cl_platform_info(param), platformInfo); + return platformInfo; + } + + private void logBuildInfo(cl_program program, int param) + { + long[] size = new long[1]; + clGetProgramBuildInfo(program, device, param, 0, null, size); + + ByteBuffer buffer = ByteBuffer.allocateDirect((int) size[0]); + clGetProgramBuildInfo(program, device, param, buffer.limit(), Pointer.toBuffer(buffer), null); + + switch (param) + { + case CL_PROGRAM_BUILD_STATUS: + log.debug("Build status: {}, {}", stringFor_cl_program_build_info(param), stringFor_cl_build_status(buffer.getInt())); + break; + case CL_PROGRAM_BINARY_TYPE: + log.debug("Binary type: {}, {}", stringFor_cl_program_build_info(param), stringFor_cl_program_binary_type(buffer.getInt())); + break; + case CL_PROGRAM_BUILD_LOG: + String buildLog = StandardCharsets.US_ASCII.decode(buffer).toString(); + log.trace("Build log: {}, {}", stringFor_cl_program_build_info(param), buildLog); + break; + case CL_PROGRAM_BUILD_OPTIONS: + String message = StandardCharsets.US_ASCII.decode(buffer).toString(); + log.debug("Build options: {}, {}", stringFor_cl_program_build_info(param), message); + break; + default: + throw new IllegalArgumentException(); + } + } + + private void initPlatform() + { + int[] platformCount = new int[1]; + clGetPlatformIDs(0, null, platformCount); + if (platformCount[0] == 0) + { + throw new RuntimeException("No compute platforms found"); + } + + cl_platform_id[] platforms = new cl_platform_id[platformCount[0]]; + clGetPlatformIDs(platforms.length, platforms, null); + + for (cl_platform_id platform : platforms) + { + log.debug("Found cl_platform_id {}", platform); + logPlatformInfo(platform, CL_PLATFORM_PROFILE); + logPlatformInfo(platform, CL_PLATFORM_VERSION); + logPlatformInfo(platform, CL_PLATFORM_NAME); + logPlatformInfo(platform, CL_PLATFORM_VENDOR); + String[] extensions = logPlatformInfo(platform, CL_PLATFORM_EXTENSIONS).split(" "); + if (Arrays.stream(extensions).noneMatch(s -> s.equals(GL_SHARING_PLATFORM_EXT))) + { + throw new RuntimeException("Platform does not support OpenGL buffer sharing"); + } + } + + platform = platforms[0]; + log.debug("Selected cl_platform_id {}", platform); + } + + private void initDevice() + { + int[] deviceCount = new int[1]; + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, null, deviceCount); + if (deviceCount[0] == 0) + { + throw new RuntimeException("No compute devices found"); + } + + cl_device_id[] devices = new cl_device_id[(int) deviceCount[0]]; + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, devices.length, devices, null); + + for (cl_device_id device : devices) + { + long[] size = new long[1]; + clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, null, size); + + byte[] devInfoBuf = new byte[(int) size[0]]; + clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, devInfoBuf.length, Pointer.to(devInfoBuf), null); + + log.debug("Found cl_device_id: {}", device); + log.debug("Device extensions: {}", new String(devInfoBuf, Charsets.UTF_8)); + } + + device = devices[0]; + log.debug("Selected cl_device_id {}", device); + } + + private void initContext(GL4 gl) + { + // set computation platform + cl_context_properties contextProps = new cl_context_properties(); + contextProps.addProperty(CL_CONTEXT_PLATFORM, platform); + + // pull gl context + GLContext glContext = gl.getContext(); + log.debug("Got GLContext of type {}", glContext.getClass().getSimpleName()); + if (!glContext.isCurrent()) + { + throw new RuntimeException("Can't create OpenCL context from inactive GL Context"); + } + + // get correct props based on os + long glContextHandle = glContext.getHandle(); + GLContextImpl glContextImpl = (GLContextImpl) glContext; + GLDrawableImpl glDrawableImpl = glContextImpl.getDrawableImpl(); + NativeSurface nativeSurface = glDrawableImpl.getNativeSurface(); + + if (glContext instanceof X11GLXContext) + { + long displayHandle = nativeSurface.getDisplayHandle(); + contextProps.addProperty(CL_GL_CONTEXT_KHR, glContextHandle); + contextProps.addProperty(CL_GLX_DISPLAY_KHR, displayHandle); + } + else if (glContext instanceof WindowsWGLContext) + { + long surfaceHandle = nativeSurface.getSurfaceHandle(); + contextProps.addProperty(CL_GL_CONTEXT_KHR, glContextHandle); + contextProps.addProperty(CL_WGL_HDC_KHR, surfaceHandle); + } + else if (glContext instanceof EGLContext) + { + long displayHandle = nativeSurface.getDisplayHandle(); + contextProps.addProperty(CL_GL_CONTEXT_KHR, glContextHandle); + contextProps.addProperty(CL_EGL_DISPLAY_KHR, displayHandle); + } + + log.debug("Creating context with props: {}", contextProps); + context = clCreateContext(contextProps, 1, new cl_device_id[]{device}, null, null, null); + log.debug("Created compute context {}", context); + } + + private void initMacOS(GL4 gl) + { + // get sharegroup from gl context + GLContext glContext = gl.getContext(); + if (!glContext.isCurrent()) + { + throw new RuntimeException("Can't create context from inactive GL"); + } + long cglContext = CGL.CGLGetCurrentContext(); + long cglShareGroup = CGL.CGLGetShareGroup(cglContext); + + // build context props + cl_context_properties contextProps = new cl_context_properties(); + contextProps.addProperty(CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, cglShareGroup); + + // ask macos to make the context for us + log.debug("Creating context with props: {}", contextProps); + context = clCreateContext(contextProps, 0, null, null, null, null); + + // pull the compute device out of the provided context + device = new cl_device_id(); + clGetGLContextInfoAPPLE(context, cglContext, CL_CGL_DEVICE_FOR_CURRENT_VIRTUAL_SCREEN_APPLE, Sizeof.cl_device_id, Pointer.to(device), null); + + log.debug("Got macOS CLGL compute device {}", device); + } + + private void ensureMinWorkGroupSize() + { + long[] maxWorkGroupSize = new long[1]; + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, Sizeof.size_t, Pointer.to(maxWorkGroupSize), null); + log.debug("Device CL_DEVICE_MAX_WORK_GROUP_SIZE: {}", maxWorkGroupSize[0]); + + if (maxWorkGroupSize[0] < MIN_WORK_GROUP_SIZE) + { + throw new RuntimeException("Compute device does not support min work group size " + MIN_WORK_GROUP_SIZE); + } + + // Largest power of 2 less than or equal to maxWorkGroupSize + int groupSize = 0x80000000 >>> Integer.numberOfLeadingZeros((int) maxWorkGroupSize[0]); + largeFaceCount = LARGE_SIZE / (Math.min(groupSize, LARGE_SIZE)); + smallFaceCount = SMALL_SIZE / (Math.min(groupSize, SMALL_SIZE)); + + log.debug("Face counts: small: {}, large: {}", smallFaceCount, largeFaceCount); + } + + private void initQueue() + { + long[] l = new long[1]; + clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, Sizeof.cl_long, Pointer.to(l), null); + + commandQueue = clCreateCommandQueue(context, device, l[0] & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, null); + log.debug("Created command_queue {}, properties {}", commandQueue, l[0] & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE); + } + + private cl_program compileProgram(String programSource) + { + log.trace("Compiling program:\n {}", programSource); + cl_program program = clCreateProgramWithSource(context, 1, new String[]{programSource}, null, null); + + try + { + clBuildProgram(program, 0, null, null, null, null); + } + catch (CLException e) + { + logBuildInfo(program, CL_PROGRAM_BUILD_LOG); + throw e; + } + + logBuildInfo(program, CL_PROGRAM_BUILD_STATUS); + logBuildInfo(program, CL_PROGRAM_BINARY_TYPE); + logBuildInfo(program, CL_PROGRAM_BUILD_OPTIONS); + logBuildInfo(program, CL_PROGRAM_BUILD_LOG); + return program; + } + + private cl_kernel getKernel(cl_program program, String kernelName) + { + cl_kernel kernel = clCreateKernel(program, kernelName, null); + log.debug("Loaded kernel {} for program {}", kernelName, program); + return kernel; + } + + private void compilePrograms() + { + Template templateSmall = new Template() + .addInclude(OpenCLManager.class) + .add(key -> key.equals("FACE_COUNT") ? ("#define FACE_COUNT " + smallFaceCount) : null); + Template templateLarge = new Template() + .addInclude(OpenCLManager.class) + .add(key -> key.equals("FACE_COUNT") ? ("#define FACE_COUNT " + largeFaceCount) : null); + + String unordered = new Template() + .addInclude(OpenCLManager.class) + .load("comp_unordered.cl"); + String small = templateSmall.load("comp.cl"); + String large = templateLarge.load("comp.cl"); + + programUnordered = compileProgram(unordered); + programSmall = compileProgram(small); + programLarge = compileProgram(large); + + kernelUnordered = getKernel(programUnordered, KERNEL_NAME_UNORDERED); + kernelSmall = getKernel(programSmall, KERNEL_NAME_LARGE); + kernelLarge = getKernel(programLarge, KERNEL_NAME_LARGE); + } + + void compute(int unorderedModels, int smallModels, int largeModels, + GLBuffer sceneVertexBuffer, + GLBuffer sceneUvBuffer, + GLBuffer vertexBuffer, + GLBuffer uvBuffer, + GLBuffer unorderedBuffer, + GLBuffer smallBuffer, + GLBuffer largeBuffer, + GLBuffer outVertexBuffer, + GLBuffer outUvBuffer, + GLBuffer uniformBuffer + ) + { + cl_mem[] glBuffersAll = { + sceneVertexBuffer.cl_mem, + sceneUvBuffer.cl_mem, + unorderedBuffer.cl_mem, + smallBuffer.cl_mem, + largeBuffer.cl_mem, + vertexBuffer.cl_mem, + uvBuffer.cl_mem, + outVertexBuffer.cl_mem, + outUvBuffer.cl_mem, + uniformBuffer.cl_mem, + }; + cl_mem[] glBuffers = Arrays.stream(glBuffersAll) + .filter(Objects::nonNull) + .toArray(cl_mem[]::new); + + cl_event acquireGLBuffers = new cl_event(); + clEnqueueAcquireGLObjects(commandQueue, glBuffers.length, glBuffers, 0, null, acquireGLBuffers); + + cl_event[] computeEvents = { + new cl_event(), + new cl_event(), + new cl_event() + }; + int numComputeEvents = 0; + + if (unorderedModels > 0) + { + clSetKernelArg(kernelUnordered, 0, Sizeof.cl_mem, unorderedBuffer.ptr()); + clSetKernelArg(kernelUnordered, 1, Sizeof.cl_mem, sceneVertexBuffer.ptr()); + clSetKernelArg(kernelUnordered, 2, Sizeof.cl_mem, vertexBuffer.ptr()); + clSetKernelArg(kernelUnordered, 3, Sizeof.cl_mem, sceneUvBuffer.ptr()); + clSetKernelArg(kernelUnordered, 4, Sizeof.cl_mem, uvBuffer.ptr()); + clSetKernelArg(kernelUnordered, 5, Sizeof.cl_mem, outVertexBuffer.ptr()); + clSetKernelArg(kernelUnordered, 6, Sizeof.cl_mem, outUvBuffer.ptr()); + + // queue compute call after acquireGLBuffers + clEnqueueNDRangeKernel(commandQueue, kernelUnordered, 1, null, + new long[]{unorderedModels * 6L}, new long[]{6}, 1, new cl_event[]{acquireGLBuffers}, computeEvents[numComputeEvents++]); + } + + if (smallModels > 0) + { + clSetKernelArg(kernelSmall, 0, (SHARED_SIZE + SMALL_SIZE) * Integer.BYTES, null); + clSetKernelArg(kernelSmall, 1, Sizeof.cl_mem, smallBuffer.ptr()); + clSetKernelArg(kernelSmall, 2, Sizeof.cl_mem, sceneVertexBuffer.ptr()); + clSetKernelArg(kernelSmall, 3, Sizeof.cl_mem, vertexBuffer.ptr()); + clSetKernelArg(kernelSmall, 4, Sizeof.cl_mem, sceneUvBuffer.ptr()); + clSetKernelArg(kernelSmall, 5, Sizeof.cl_mem, uvBuffer.ptr()); + clSetKernelArg(kernelSmall, 6, Sizeof.cl_mem, outVertexBuffer.ptr()); + clSetKernelArg(kernelSmall, 7, Sizeof.cl_mem, outUvBuffer.ptr()); + clSetKernelArg(kernelSmall, 8, Sizeof.cl_mem, uniformBuffer.ptr()); + + clEnqueueNDRangeKernel(commandQueue, kernelSmall, 1, null, + new long[]{smallModels * (SMALL_SIZE / smallFaceCount)}, new long[]{SMALL_SIZE / smallFaceCount}, 1, new cl_event[]{acquireGLBuffers}, computeEvents[numComputeEvents++]); + } + + if (largeModels > 0) + { + clSetKernelArg(kernelLarge, 0, (SHARED_SIZE + LARGE_SIZE) * Integer.BYTES, null); + clSetKernelArg(kernelLarge, 1, Sizeof.cl_mem, largeBuffer.ptr()); + clSetKernelArg(kernelLarge, 2, Sizeof.cl_mem, sceneVertexBuffer.ptr()); + clSetKernelArg(kernelLarge, 3, Sizeof.cl_mem, vertexBuffer.ptr()); + clSetKernelArg(kernelLarge, 4, Sizeof.cl_mem, sceneUvBuffer.ptr()); + clSetKernelArg(kernelLarge, 5, Sizeof.cl_mem, uvBuffer.ptr()); + clSetKernelArg(kernelLarge, 6, Sizeof.cl_mem, outVertexBuffer.ptr()); + clSetKernelArg(kernelLarge, 7, Sizeof.cl_mem, outUvBuffer.ptr()); + clSetKernelArg(kernelLarge, 8, Sizeof.cl_mem, uniformBuffer.ptr()); + + clEnqueueNDRangeKernel(commandQueue, kernelLarge, 1, null, + new long[]{(long) largeModels * (LARGE_SIZE / largeFaceCount)}, new long[]{LARGE_SIZE / largeFaceCount}, 1, new cl_event[]{acquireGLBuffers}, computeEvents[numComputeEvents++]); + } + + clEnqueueReleaseGLObjects(commandQueue, glBuffers.length, glBuffers, numComputeEvents, computeEvents, null); + } + + void finish() + { + clFinish(commandQueue); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/cl_types.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/cl_types.cl new file mode 100644 index 0000000000..7f41acab49 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/cl_types.cl @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021, 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. + */ + +struct uniform { + int cameraYaw; + int cameraPitch; + int centerX; + int centerY; + int zoom; + int cameraX; + int cameraY; + int cameraZ; + int4 sinCosTable[2048]; +}; + +struct shared_data { + int totalNum[12]; // number of faces with a given priority + int totalDistance[12]; // sum of distances to faces of a given priority + int totalMappedNum[18]; // number of faces with a given adjusted priority + int min10; // minimum distance to a face of priority 10 + int dfs[0]; // packed face id and distance, size 512 for small, 4096 for large +}; + +struct modelinfo { + int offset; // offset into buffer + int uvOffset; // offset into uv buffer + int size; // length in faces + int idx; // write idx in target buffer + int flags; // radius, orientation + int x; // scene position x + int y; // scene position y + int z; // scene position z +}; diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/common.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/common.cl new file mode 100644 index 0000000000..f499599cd2 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/common.cl @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021, 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. + */ + +#define PI 3.1415926535897932384626433832795f +#define UNIT PI / 1024.0f + +float3 toScreen(int4 vertex, int cameraYaw, int cameraPitch, int centerX, int centerY, int zoom) { + float yawSin = sin(cameraYaw * UNIT); + float yawCos = cos(cameraYaw * UNIT); + + float pitchSin = sin(cameraPitch * UNIT); + float pitchCos = cos(cameraPitch * UNIT); + + float rotatedX = (vertex.z * yawSin) + (vertex.x * yawCos); + float rotatedZ = (vertex.z * yawCos) - (vertex.x * yawSin); + + float var13 = (vertex.y * pitchCos) - (rotatedZ * pitchSin); + float var12 = (vertex.y * pitchSin) + (rotatedZ * pitchCos); + + float x = rotatedX * zoom / var12 + centerX; + float y = var13 * zoom / var12 + centerY; + float z = -var12; // in OpenGL depth is negative + + return (float3) (x, y, z); +} + +/* + * Rotate a vertex by a given orientation in JAU + */ +int4 rotate_vertex(__constant struct uniform *uni, int4 vertex, int orientation) { + int4 sinCos = uni->sinCosTable[orientation]; + int s = sinCos.x; + int c = sinCos.y; + int x = vertex.z * s + vertex.x * c >> 16; + int z = vertex.z * c - vertex.x * s >> 16; + return (int4)(x, vertex.y, z, vertex.w); +} + +/* + * Calculate the distance to a vertex given the camera angle + */ +int vertex_distance(int4 vertex, int cameraYaw, int cameraPitch) { + int yawSin = (int)(65536.0f * sin(cameraYaw * UNIT)); + int yawCos = (int)(65536.0f * cos(cameraYaw * UNIT)); + + int pitchSin = (int)(65536.0f * sin(cameraPitch * UNIT)); + int pitchCos = (int)(65536.0f * cos(cameraPitch * UNIT)); + + int j = vertex.z * yawCos - vertex.x * yawSin >> 16; + int l = vertex.y * pitchSin + j * pitchCos >> 16; + + return l; +} + +/* + * Calculate the distance to a face + */ +int face_distance(int4 vA, int4 vB, int4 vC, int cameraYaw, int cameraPitch) { + int dvA = vertex_distance(vA, cameraYaw, cameraPitch); + int dvB = vertex_distance(vB, cameraYaw, cameraPitch); + int dvC = vertex_distance(vC, cameraYaw, cameraPitch); + int faceDistance = (dvA + dvB + dvC) / 3; + return faceDistance; +} + +/* + * Test if a face is visible (not backward facing) + */ +bool face_visible(__constant struct uniform *uni, int4 vA, int4 vB, int4 vC, int4 position) { + // Move model to scene location, and account for camera offset + int4 cameraPos = (int4)(uni->cameraX, uni->cameraY, uni->cameraZ, 0); + vA += position - cameraPos; + vB += position - cameraPos; + vC += position - cameraPos; + + float3 sA = toScreen(vA, uni->cameraYaw, uni->cameraPitch, uni->centerX, uni->centerY, uni->zoom); + float3 sB = toScreen(vB, uni->cameraYaw, uni->cameraPitch, uni->centerX, uni->centerY, uni->zoom); + float3 sC = toScreen(vC, uni->cameraYaw, uni->cameraPitch, uni->centerX, uni->centerY, uni->zoom); + + return (sA.x - sB.x) * (sC.y - sB.y) - (sC.x - sB.x) * (sA.y - sB.y) > 0; +} + diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.cl new file mode 100644 index 0000000000..1212123f25 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.cl @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021, 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. + */ + +#include FACE_COUNT + +#include cl_types.cl +#include to_screen.cl +#include common.cl +#include priority_render.cl + +__kernel +__attribute__((work_group_size_hint(256, 1, 1))) +void computeLarge( + __local struct shared_data *shared, + __global const struct modelinfo *ol, + __global const int4 *vb, + __global const int4 *tempvb, + __global const float4 *uv, + __global const float4 *tempuv, + __global int4 *vout, + __global float4 *uvout, + __constant struct uniform *uni) { + + size_t groupId = get_group_id(0); + size_t localId = get_local_id(0) * FACE_COUNT; + struct modelinfo minfo = ol[groupId]; + int4 pos = (int4)(minfo.x, minfo.y, minfo.z, 0); + + if (localId == 0) { + shared->min10 = 1600; + for (int i = 0; i < 12; ++i) { + shared->totalNum[i] = 0; + shared->totalDistance[i] = 0; + } + for (int i = 0; i < 18; ++i) { + shared->totalMappedNum[i] = 0; + } + } + + int prio[FACE_COUNT]; + int dis[FACE_COUNT]; + int4 v1[FACE_COUNT]; + int4 v2[FACE_COUNT]; + int4 v3[FACE_COUNT]; + + for (int i = 0; i < FACE_COUNT; i++) { + get_face(shared, uni, vb, tempvb, localId + i, minfo, uni->cameraYaw, uni->cameraPitch, &prio[i], &dis[i], &v1[i], &v2[i], &v3[i]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = 0; i < FACE_COUNT; i++) { + add_face_prio_distance(shared, uni, localId + i, minfo, v1[i], v2[i], v3[i], prio[i], dis[i], pos); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + int prioAdj[FACE_COUNT]; + int idx[FACE_COUNT]; + for (int i = 0; i < FACE_COUNT; i++) { + idx[i] = map_face_priority(shared, localId + i, minfo, prio[i], dis[i], &prioAdj[i]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = 0; i < FACE_COUNT; i++) { + insert_dfs(shared, localId + i, minfo, prioAdj[i], dis[i], idx[i]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = 0; i < FACE_COUNT; i++) { + sort_and_insert(shared, uv, tempuv, vout, uvout, localId + i, minfo, prioAdj[i], dis[i], v1[i], v2[i], v3[i]); + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.cl new file mode 100644 index 0000000000..436f9a7d72 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.cl @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021, 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. + */ + +#include cl_types.cl + +__kernel +__attribute__((reqd_work_group_size(6, 1, 1))) +void computeUnordered(__global const struct modelinfo *ol, + __global const int4 *vb, + __global const int4 *tempvb, + __global const float4 *uv, + __global const float4 *tempuv, + __global int4 *vout, + __global float4 *uvout) { + size_t groupId = get_group_id(0); + size_t localId = get_local_id(0); + struct modelinfo minfo = ol[groupId]; + + int offset = minfo.offset; + int size = minfo.size; + int outOffset = minfo.idx; + int uvOffset = minfo.uvOffset; + int flags = minfo.flags; + int4 pos = (int4)(minfo.x, minfo.y, minfo.z, 0); + + if (localId >= size) { + return; + } + + uint ssboOffset = localId; + int4 thisA, thisB, thisC; + + // Grab triangle vertices from the correct buffer + if (flags < 0) { + thisA = vb[offset + ssboOffset * 3]; + thisB = vb[offset + ssboOffset * 3 + 1]; + thisC = vb[offset + ssboOffset * 3 + 2]; + } else { + thisA = tempvb[offset + ssboOffset * 3]; + thisB = tempvb[offset + ssboOffset * 3 + 1]; + thisC = tempvb[offset + ssboOffset * 3 + 2]; + } + + uint myOffset = localId; + + // position vertices in scene and write to out buffer + vout[outOffset + myOffset * 3] = pos + thisA; + vout[outOffset + myOffset * 3 + 1] = pos + thisB; + vout[outOffset + myOffset * 3 + 2] = pos + thisC; + + if (uvOffset < 0) { + uvout[outOffset + myOffset * 3] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + uvout[outOffset + myOffset * 3 + 1] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + uvout[outOffset + myOffset * 3 + 2] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + } else if (flags >= 0) { + uvout[outOffset + myOffset * 3] = tempuv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = tempuv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = tempuv[uvOffset + localId * 3 + 2]; + } else { + uvout[outOffset + myOffset * 3] = uv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = uv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = uv[uvOffset + localId * 3 + 2]; + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.cl new file mode 100644 index 0000000000..6f1a04470c --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.cl @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2021, 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. + */ + +// Calculate adjusted priority for a face with a given priority, distance, and +// model global min10 and face distance averages. This allows positioning faces +// with priorities 10/11 into the correct 'slots' resulting in 18 possible +// adjusted priorities +int priority_map(int p, int distance, int _min10, int avg1, int avg2, int avg3) { + // (10, 11) 0 1 2 (10, 11) 3 4 (10, 11) 5 6 7 8 9 (10, 11) + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + switch (p) { + case 0: return 2; + case 1: return 3; + case 2: return 4; + case 3: return 7; + case 4: return 8; + case 5: return 11; + case 6: return 12; + case 7: return 13; + case 8: return 14; + case 9: return 15; + case 10: + if (distance > avg1) { + return 0; + } else if (distance > avg2) { + return 5; + } else if (distance > avg3) { + return 9; + } else { + return 16; + } + case 11: + if (distance > avg1 && _min10 > avg1) { + return 1; + } else if (distance > avg2 && (_min10 > avg1 || _min10 > avg2)) { + return 6; + } else if (distance > avg3 && (_min10 > avg1 || _min10 > avg2 || _min10 > avg3)) { + return 10; + } else { + return 17; + } + default: + return -1; + } +} + +// calculate the number of faces with a lower adjusted priority than +// the given adjusted priority +int count_prio_offset(__local struct shared_data *shared, int priority) { + int total = 0; + switch (priority) { + case 17: + total += shared->totalMappedNum[16]; + case 16: + total += shared->totalMappedNum[15]; + case 15: + total += shared->totalMappedNum[14]; + case 14: + total += shared->totalMappedNum[13]; + case 13: + total += shared->totalMappedNum[12]; + case 12: + total += shared->totalMappedNum[11]; + case 11: + total += shared->totalMappedNum[10]; + case 10: + total += shared->totalMappedNum[9]; + case 9: + total += shared->totalMappedNum[8]; + case 8: + total += shared->totalMappedNum[7]; + case 7: + total += shared->totalMappedNum[6]; + case 6: + total += shared->totalMappedNum[5]; + case 5: + total += shared->totalMappedNum[4]; + case 4: + total += shared->totalMappedNum[3]; + case 3: + total += shared->totalMappedNum[2]; + case 2: + total += shared->totalMappedNum[1]; + case 1: + total += shared->totalMappedNum[0]; + case 0: + return total; + } +} + +void get_face( + __local struct shared_data *shared, + __constant struct uniform *uni, + __global const int4 *vb, + __global const int4 *tempvb, + uint localId, struct modelinfo minfo, int cameraYaw, int cameraPitch, + /* out */ int *prio, int *dis, int4 *o1, int4 *o2, int4 *o3) { + int size = minfo.size; + int offset = minfo.offset; + int flags = minfo.flags; + uint ssboOffset; + + if (localId < size) { + ssboOffset = localId; + } else { + ssboOffset = 0; + } + + int4 thisA; + int4 thisB; + int4 thisC; + + // Grab triangle vertices from the correct buffer + if (flags < 0) { + thisA = vb[offset + ssboOffset * 3]; + thisB = vb[offset + ssboOffset * 3 + 1]; + thisC = vb[offset + ssboOffset * 3 + 2]; + } else { + thisA = tempvb[offset + ssboOffset * 3]; + thisB = tempvb[offset + ssboOffset * 3 + 1]; + thisC = tempvb[offset + ssboOffset * 3 + 2]; + } + + if (localId < size) { + int radius = (flags & 0x7fffffff) >> 12; + int orientation = flags & 0x7ff; + + // rotate for model orientation + int4 thisrvA = rotate_vertex(uni, thisA, orientation); + int4 thisrvB = rotate_vertex(uni, thisB, orientation); + int4 thisrvC = rotate_vertex(uni, thisC, orientation); + + // calculate distance to face + int thisPriority = (thisA.w >> 16) & 0xff;// all vertices on the face have the same priority + int thisDistance; + if (radius == 0) { + thisDistance = 0; + } else { + thisDistance = face_distance(thisrvA, thisrvB, thisrvC, cameraYaw, cameraPitch) + radius; + } + + *o1 = thisrvA; + *o2 = thisrvB; + *o3 = thisrvC; + + *prio = thisPriority; + *dis = thisDistance; + } else { + *o1 = (int4)(0, 0, 0, 0); + *o2 = (int4)(0, 0, 0, 0); + *o3 = (int4)(0, 0, 0, 0); + *prio = 0; + *dis = 0; + } +} + +void add_face_prio_distance( + __local struct shared_data *shared, + __constant struct uniform *uni, + uint localId, struct modelinfo minfo, int4 thisrvA, int4 thisrvB, int4 thisrvC, int thisPriority, int thisDistance, int4 pos) { + if (localId < minfo.size) { + // if the face is not culled, it is calculated into priority distance averages + if (face_visible(uni, thisrvA, thisrvB, thisrvC, pos)) { + atomic_add(&shared->totalNum[thisPriority], 1); + atomic_add(&shared->totalDistance[thisPriority], thisDistance); + + // calculate minimum distance to any face of priority 10 for positioning the 11 faces later + if (thisPriority == 10) { + atomic_min(&shared->min10, thisDistance); + } + } + } +} + +int map_face_priority(__local struct shared_data *shared, uint localId, struct modelinfo minfo, int thisPriority, int thisDistance, int *prio) { + int size = minfo.size; + + // Compute average distances for 0/2, 3/4, and 6/8 + + if (localId < size) { + int avg1 = 0; + int avg2 = 0; + int avg3 = 0; + + if (shared->totalNum[1] > 0 || shared->totalNum[2] > 0) { + avg1 = (shared->totalDistance[1] + shared->totalDistance[2]) / (shared->totalNum[1] + shared->totalNum[2]); + } + + if (shared->totalNum[3] > 0 || shared->totalNum[4] > 0) { + avg2 = (shared->totalDistance[3] + shared->totalDistance[4]) / (shared->totalNum[3] + shared->totalNum[4]); + } + + if (shared->totalNum[6] > 0 || shared->totalNum[8] > 0) { + avg3 = (shared->totalDistance[6] + shared->totalDistance[8]) / (shared->totalNum[6] + shared->totalNum[8]); + } + + int adjPrio = priority_map(thisPriority, thisDistance, shared->min10, avg1, avg2, avg3); + int prioIdx = atomic_add(&shared->totalMappedNum[adjPrio], 1); + + *prio = adjPrio; + return prioIdx; + } + + *prio = 0; + return 0; +} + +void insert_dfs(__local struct shared_data *shared, uint localId, struct modelinfo minfo, int adjPrio, int distance, int prioIdx) { + int size = minfo.size; + + if (localId < size) { + // calculate base offset into dfs based on number of faces with a lower priority + int baseOff = count_prio_offset(shared, adjPrio); + // store into face array offset array by unique index + shared->dfs[baseOff + prioIdx] = ((int) localId << 16) | distance; + } +} + +void sort_and_insert( + __local struct shared_data *shared, + __global const float4 *uv, + __global const float4 *tempuv, + __global int4 *vout, + __global float4 *uvout, + uint localId, struct modelinfo minfo, int thisPriority, int thisDistance, int4 thisrvA, int4 thisrvB, int4 thisrvC) { + /* compute face distance */ + int size = minfo.size; + + if (localId < size) { + int outOffset = minfo.idx; + int uvOffset = minfo.uvOffset; + int flags = minfo.flags; + int4 pos = (int4)(minfo.x, minfo.y, minfo.z, 0); + + const int priorityOffset = count_prio_offset(shared, thisPriority); + const int numOfPriority = shared->totalMappedNum[thisPriority]; + int start = priorityOffset; // index of first face with this priority + int end = priorityOffset + numOfPriority; // index of last face with this priority + int myOffset = priorityOffset; + + // we only have to order faces against others of the same priority + // calculate position this face will be in + for (int i = start; i < end; ++i) { + int d1 = shared->dfs[i]; + int theirId = d1 >> 16; + int theirDistance = d1 & 0xffff; + + // the closest faces draw last, so have the highest index + // if two faces have the same distance, the one with the + // higher id draws last + if ((theirDistance > thisDistance) + || (theirDistance == thisDistance && theirId < localId)) { + ++myOffset; + } + } + + // position vertices in scene and write to out buffer + vout[outOffset + myOffset * 3] = pos + thisrvA; + vout[outOffset + myOffset * 3 + 1] = pos + thisrvB; + vout[outOffset + myOffset * 3 + 2] = pos + thisrvC; + + if (uvOffset < 0) { + uvout[outOffset + myOffset * 3] = (float4)(0, 0, 0, 0); + uvout[outOffset + myOffset * 3 + 1] = (float4)(0, 0, 0, 0); + uvout[outOffset + myOffset * 3 + 2] = (float4)(0, 0, 0, 0); + } else if (flags >= 0) { + uvout[outOffset + myOffset * 3] = tempuv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = tempuv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = tempuv[uvOffset + localId * 3 + 2]; + } else { + uvout[outOffset + myOffset * 3] = uv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = uv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = uv[uvOffset + localId * 3 + 2]; + } + } +} From 5545b9d0ad020912569f5add959838c145965c21 Mon Sep 17 00:00:00 2001 From: buttonpoker Date: Fri, 12 Feb 2021 17:16:44 -0800 Subject: [PATCH 44/55] cannon: Remove Mourner Headquarters elf cannon spot (#13196) Following the release of the Song of the Elves quest, the mourners found in the Mourner Headquarters can no longer be hit by a cannon before, during, or after completion of the quest. [This is evidently a known issue with multi-NPCs.][1] [1]: https://twitter.com/JagexAsh/status/1359968976760094721 --- .../java/net/runelite/client/plugins/cannon/CannonSpots.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java index f5b6f4a4a2..4596cd4e35 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java @@ -49,7 +49,7 @@ enum CannonSpots DUST_DEVIL(new WorldPoint(3218, 9366, 0)), EARTH_WARRIOR(new WorldPoint(3120, 9987, 0)), ELDER_CHAOS_DRUID(new WorldPoint(3237, 3622, 0)), - ELVES(new WorldPoint(2044, 4635, 0), new WorldPoint(3278, 6098, 0)), + ELVES(new WorldPoint(3278, 6098, 0)), FIRE_GIANTS(new WorldPoint(2393, 9782, 0), new WorldPoint(2412, 9776, 0), new WorldPoint(2401, 9780, 0), new WorldPoint(3047, 10340, 0)), GREATER_DEMONS(new WorldPoint(1435, 10086, 2), new WorldPoint(3224, 10132, 0)), GREEN_DRAGON(new WorldPoint(3225, 10068, 0)), From 77757229a5c671b3230044eef77cc9c5ce20bb3c Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 13 Feb 2021 09:50:12 -0500 Subject: [PATCH 45/55] entity hider: add option to hide ignored players This is diabled in pvp to avoid abuse. This additionally allows the "hide" options to be set without hiding others now. --- .../main/java/net/runelite/api/Client.java | 11 ++++- .../entityhider/EntityHiderConfig.java | 39 +++++++++++------ .../entityhider/EntityHiderPlugin.java | 43 +++++-------------- 3 files changed, 45 insertions(+), 48 deletions(-) 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 c665139862..77f3903001 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1475,7 +1475,7 @@ public interface Client extends GameEngine * * @param state the new player hidden state */ - void setPlayersHidden(boolean state); + void setOthersHidden(boolean state); /** * Sets whether 2D sprites related to the other players are hidden. @@ -1483,7 +1483,7 @@ public interface Client extends GameEngine * * @param state the new player 2D hidden state */ - void setPlayersHidden2D(boolean state); + void setOthersHidden2D(boolean state); /** * Sets whether or not friends are hidden. @@ -1499,6 +1499,13 @@ public interface Client extends GameEngine */ void setFriendsChatMembersHidden(boolean state); + /** + * Sets whether or not ignored players are hidden. + * + * @param state the new ignored player hidden state + */ + void setIgnoresHidden(boolean state); + /** * Sets whether the local player is hidden. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java index d3ee118b8c..a18c211da3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java @@ -29,16 +29,18 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -@ConfigGroup("entityhider") +@ConfigGroup(EntityHiderConfig.GROUP) public interface EntityHiderConfig extends Config { + String GROUP = "entityhider"; + @ConfigItem( position = 1, keyName = "hidePlayers", - name = "Hide Players", - description = "Configures whether or not players are hidden" + name = "Hide Others", + description = "Configures whether or not other players are hidden" ) - default boolean hidePlayers() + default boolean hideOthers() { return true; } @@ -46,10 +48,10 @@ public interface EntityHiderConfig extends Config @ConfigItem( position = 2, keyName = "hidePlayers2D", - name = "Hide Players 2D", - description = "Configures whether or not players 2D elements are hidden" + name = "Hide Others 2D", + description = "Configures whether or not other players 2D elements are hidden" ) - default boolean hidePlayers2D() + default boolean hideOthers2D() { return true; } @@ -78,6 +80,17 @@ public interface EntityHiderConfig extends Config @ConfigItem( position = 5, + keyName = "hideIgnores", + name = "Hide Ignores", + description = "Configures whether or not ignored players are hidden" + ) + default boolean hideIgnores() + { + return false; + } + + @ConfigItem( + position = 6, keyName = "hideLocalPlayer", name = "Hide Local Player", description = "Configures whether or not the local player is hidden" @@ -88,7 +101,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 6, + position = 7, keyName = "hideLocalPlayer2D", name = "Hide Local Player 2D", description = "Configures whether or not the local player's 2D elements are hidden" @@ -99,7 +112,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 7, + position = 8, keyName = "hideNPCs", name = "Hide NPCs", description = "Configures whether or not NPCs are hidden" @@ -110,7 +123,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 8, + position = 9, keyName = "hideNPCs2D", name = "Hide NPCs 2D", description = "Configures whether or not NPCs 2D elements are hidden" @@ -121,7 +134,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 9, + position = 10, keyName = "hidePets", name = "Hide Pets", description = "Configures whether or not other player pets are hidden" @@ -132,7 +145,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 10, + position = 11, keyName = "hideAttackers", name = "Hide Attackers", description = "Configures whether or not NPCs/players attacking you are hidden" @@ -143,7 +156,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 11, + position = 12, keyName = "hideProjectiles", name = "Hide Projectiles", description = "Configures whether or not projectiles are hidden" diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java index 155bc6cc38..79a9dc160f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java @@ -28,13 +28,9 @@ package net.runelite.client.plugins.entityhider; import com.google.inject.Provides; import javax.inject.Inject; import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.Player; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -67,27 +63,22 @@ public class EntityHiderPlugin extends Plugin @Subscribe public void onConfigChanged(ConfigChanged e) { - updateConfig(); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGGED_IN) + if (e.getGroup().equals(EntityHiderConfig.GROUP)) { - client.setIsHidingEntities(isPlayerRegionAllowed()); + updateConfig(); } } private void updateConfig() { - client.setIsHidingEntities(isPlayerRegionAllowed()); + client.setIsHidingEntities(true); - client.setPlayersHidden(config.hidePlayers()); - client.setPlayersHidden2D(config.hidePlayers2D()); + client.setOthersHidden(config.hideOthers()); + client.setOthersHidden2D(config.hideOthers2D()); client.setFriendsHidden(config.hideFriends()); client.setFriendsChatMembersHidden(config.hideFriendsChatMembers()); + client.setIgnoresHidden(config.hideIgnores()); client.setLocalPlayerHidden(config.hideLocalPlayer()); client.setLocalPlayerHidden2D(config.hideLocalPlayer2D()); @@ -107,11 +98,12 @@ public class EntityHiderPlugin extends Plugin { client.setIsHidingEntities(false); - client.setPlayersHidden(false); - client.setPlayersHidden2D(false); + client.setOthersHidden(false); + client.setOthersHidden2D(false); client.setFriendsHidden(false); client.setFriendsChatMembersHidden(false); + client.setIgnoresHidden(false); client.setLocalPlayerHidden(false); client.setLocalPlayerHidden2D(false); @@ -125,19 +117,4 @@ public class EntityHiderPlugin extends Plugin client.setProjectilesHidden(false); } - - private boolean isPlayerRegionAllowed() - { - final Player localPlayer = client.getLocalPlayer(); - - if (localPlayer == null) - { - return true; - } - - final int playerRegionID = WorldPoint.fromLocalInstance(client, localPlayer.getLocalLocation()).getRegionID(); - - // 9520 = Castle Wars - return playerRegionID != 9520; - } } From fadfc15cd08a182702865319da38a047f21d8046 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 6 Feb 2021 14:10:28 -0800 Subject: [PATCH 46/55] cluescrolls: Fix beginner/master clue step reset Commit 36bb7c8401fdd9ae88a185e9e193b4f7183aed54 improved the clue scroll plugin by resetting the active clue step when a beginner or master clue item was displayed in the chat dialog when receiving a new step. This commit caused a new bug, however, in that it became possible to click on a new clue step while the new step dialog was open such that the new step dialog persisted through a GameTick due to client-server delay, causing the saved clue item ID to be lost. This commit fixes that issue by resetting only the active clue object, but not the recorded clue item ID, as beginner and master clues only use a single item ID. --- .../runelite/client/plugins/cluescrolls/ClueScrollPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 da3a95a301..7a3ee36e66 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 @@ -580,7 +580,7 @@ public class ClueScrollPlugin extends Plugin if (chatDialogClueItem != null && (chatDialogClueItem.getItemId() == ItemID.CLUE_SCROLL_BEGINNER || chatDialogClueItem.getItemId() == ItemID.CLUE_SCROLL_MASTER)) { - resetClue(true); + resetClue(false); } final Widget clueScrollText = client.getWidget(WidgetInfo.CLUE_SCROLL_TEXT); From 0fa078d8f1b83494412a9345ca1b8129d01bf131 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 6 Feb 2021 17:19:40 -0800 Subject: [PATCH 47/55] notifier: Add username to tray notification title This also removes the player's ingame name from notifications which are referring to the active player in favor of the title. --- .../java/net/runelite/client/Notifier.java | 20 +++++++++++++++- .../client/plugins/fishing/FishingPlugin.java | 2 +- .../grounditems/GroundItemsPlugin.java | 6 +---- .../idlenotifier/IdleNotifierPlugin.java | 24 +++++++++---------- .../plugins/regenmeter/RegenMeterPlugin.java | 2 +- .../grounditems/GroundItemsPluginTest.java | 10 ++------ .../idlenotifier/IdleNotifierPluginTest.java | 13 ++++------ 7 files changed, 41 insertions(+), 36 deletions(-) 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 8184cf9f98..53963e4b1b 100644 --- a/runelite-client/src/main/java/net/runelite/client/Notifier.java +++ b/runelite-client/src/main/java/net/runelite/client/Notifier.java @@ -59,6 +59,7 @@ import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.GameState; +import net.runelite.api.Player; import net.runelite.client.chat.ChatColorType; import net.runelite.client.chat.ChatMessageBuilder; import net.runelite.client.chat.ChatMessageManager; @@ -175,7 +176,7 @@ public class Notifier if (runeLiteConfig.enableTrayNotifications()) { - sendNotification(appName, message, type); + sendNotification(buildTitle(), message, type); } switch (runeLiteConfig.notificationSound()) @@ -210,6 +211,23 @@ public class Notifier log.debug(message); } + private String buildTitle() + { + Player player = client.getLocalPlayer(); + if (player == null) + { + return appName; + } + + String name = player.getName(); + if (Strings.isNullOrEmpty(name)) + { + return appName; + } + + return appName + " - " + name; + } + public void processFlash(final Graphics2D graphics) { FlashNotification flashNotification = runeLiteConfig.flashNotification(); 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 0c5fa99dc2..e782b81428 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 @@ -377,7 +377,7 @@ public class FishingPlugin extends Plugin { if (!trawlerNotificationSent) { - notifier.notify("[" + client.getLocalPlayer().getName() + "] has low Fishing Trawler activity!"); + notifier.notify("You have low Fishing Trawler activity!"); trawlerNotificationSent = true; } } 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 e7e79b5186..b7a8fc6500 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 @@ -59,7 +59,6 @@ import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; -import net.runelite.api.Player; import net.runelite.api.Tile; import net.runelite.api.TileItem; import net.runelite.api.coords.WorldPoint; @@ -643,11 +642,8 @@ public class GroundItemsPlugin extends Plugin return; } - final Player local = client.getLocalPlayer(); final StringBuilder notificationStringBuilder = new StringBuilder() - .append('[') - .append(local.getName()) - .append("] received a ") + .append("You received a ") .append(dropType) .append(" drop: ") .append(item.getName()); 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 79ca4413e3..6d7dcec442 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 @@ -438,64 +438,64 @@ public class IdleNotifierPlugin extends Plugin if (config.logoutIdle() && checkIdleLogout()) { - notifier.notify("[" + local.getName() + "] is about to log out from idling too long!"); + notifier.notify("You are about to log out from idling too long!"); } if (check6hrLogout()) { - notifier.notify("[" + local.getName() + "] is about to log out from being online for 6 hours!"); + notifier.notify("You are about to log out from being online for 6 hours!"); } if (config.animationIdle() && checkAnimationIdle(waitDuration, local)) { - notifier.notify("[" + local.getName() + "] is now idle!"); + notifier.notify("You are now idle!"); } if (config.movementIdle() && checkMovementIdle(waitDuration, local)) { - notifier.notify("[" + local.getName() + "] has stopped moving!"); + notifier.notify("You have stopped moving!"); } if (config.interactionIdle() && checkInteractionIdle(waitDuration, local)) { if (lastInteractWasCombat) { - notifier.notify("[" + local.getName() + "] is now out of combat!"); + notifier.notify("You are now out of combat!"); } else { - notifier.notify("[" + local.getName() + "] is now idle!"); + notifier.notify("You are now idle!"); } } if (checkLowHitpoints()) { - notifier.notify("[" + local.getName() + "] has low hitpoints!"); + notifier.notify("You have low hitpoints!"); } if (checkLowPrayer()) { - notifier.notify("[" + local.getName() + "] has low prayer!"); + notifier.notify("You have low prayer!"); } if (checkLowEnergy()) { - notifier.notify("[" + local.getName() + "] has low run energy!"); + notifier.notify("You have low run energy!"); } if (checkHighEnergy()) { - notifier.notify("[" + local.getName() + "] has restored run energy!"); + notifier.notify("You have restored run energy!"); } if (checkLowOxygen()) { - notifier.notify("[" + local.getName() + "] has low oxygen!"); + notifier.notify("You have low oxygen!"); } if (checkFullSpecEnergy()) { - notifier.notify("[" + local.getName() + "] has restored spec energy!"); + notifier.notify("You have restored spec energy!"); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java index 6339ce5486..2160148401 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java @@ -166,7 +166,7 @@ public class RegenMeterPlugin extends Plugin if (config.getNotifyBeforeHpRegenSeconds() > 0 && currentHP < maxHP && shouldNotifyHpRegenThisTick(ticksPerHPRegen)) { - notifier.notify("[" + client.getLocalPlayer().getName() + "] regenerates their next hitpoint soon!"); + notifier.notify("Your next hitpoint will regenerate soon!"); } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java index bc9c2536a1..48d6296ca5 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java @@ -109,13 +109,7 @@ public class GroundItemsPluginTest return null; }).when(executor).execute(any(Runnable.class)); - when(client.getLocalPlayer()).then(a -> - { - Player player = mock(Player.class); - when(player.getName()).thenReturn("Adam"); - return player; - }); - + when(client.getLocalPlayer()).thenReturn(mock(Player.class)); when(config.getHiddenItems()).thenReturn(""); } @@ -149,6 +143,6 @@ public class GroundItemsPluginTest groundItemsPlugin.onItemSpawned(new ItemSpawned(tile, tileItem)); - verify(notifier).notify("[Adam] received a highlighted drop: Abyssal whip"); + verify(notifier).notify("You received a highlighted drop: Abyssal whip"); } } \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java index 59c84d3086..bb91fffcb8 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java @@ -62,8 +62,6 @@ import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class IdleNotifierPluginTest { - private static final String PLAYER_NAME = "Deathbeam"; - @Mock @Bind private Client client; @@ -116,7 +114,6 @@ public class IdleNotifierPluginTest when(fishingSpot.getName()).thenReturn("Fishing spot"); // Mock player - when(player.getName()).thenReturn(PLAYER_NAME); when(player.getAnimation()).thenReturn(AnimationID.IDLE); when(client.getLocalPlayer()).thenReturn(player); @@ -145,7 +142,7 @@ public class IdleNotifierPluginTest when(player.getAnimation()).thenReturn(AnimationID.IDLE); plugin.onAnimationChanged(animationChanged); plugin.onGameTick(new GameTick()); - verify(notifier).notify("[" + PLAYER_NAME + "] is now idle!"); + verify(notifier).notify("You are now idle!"); } @Test @@ -201,7 +198,7 @@ public class IdleNotifierPluginTest when(player.getInteracting()).thenReturn(null); plugin.onInteractingChanged(new InteractingChanged(player, null)); plugin.onGameTick(new GameTick()); - verify(notifier).notify("[" + PLAYER_NAME + "] is now out of combat!"); + verify(notifier).notify("You are now out of combat!"); } @Test @@ -292,7 +289,7 @@ public class IdleNotifierPluginTest plugin.onInteractingChanged(new InteractingChanged(player, null)); plugin.onGameTick(new GameTick()); - verify(notifier).notify("[" + PLAYER_NAME + "] is now idle!"); + verify(notifier).notify("You are now idle!"); } @Test @@ -306,7 +303,7 @@ public class IdleNotifierPluginTest when(client.getVar(eq(VarPlayer.SPECIAL_ATTACK_PERCENT))).thenReturn(500); // 50% plugin.onGameTick(new GameTick()); - verify(notifier).notify(eq("[" + PLAYER_NAME + "] has restored spec energy!")); + verify(notifier).notify(eq("You have restored spec energy!")); } @Test @@ -321,6 +318,6 @@ public class IdleNotifierPluginTest // No movement here plugin.onGameTick(new GameTick()); - verify(notifier).notify(eq("[" + PLAYER_NAME + "] has stopped moving!")); + verify(notifier).notify(eq("You have stopped moving!")); } } \ No newline at end of file From 63cbe6ae09f926669d20810db8ca3715b1138296 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Thu, 11 Feb 2021 15:45:33 +0000 Subject: [PATCH 48/55] chat color: fix usernames not being recoloured if they have an icon --- .../client/chat/ChatMessageManager.java | 4 +- .../client/chat/ChatMessageManagerTest.java | 64 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java index b1795db6ac..6e888ce8f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java @@ -54,6 +54,7 @@ import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ConfigChanged; import net.runelite.client.ui.JagexColors; import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.Text; @Singleton public class ChatMessageManager @@ -125,7 +126,8 @@ public class ChatMessageManager case PUBLICCHAT: case MODCHAT: { - boolean isFriend = client.isFriended(chatMessage.getName(), true) && !client.getLocalPlayer().getName().equals(chatMessage.getName()); + String sanitizedUsername = Text.removeTags(chatMessage.getName()); + boolean isFriend = client.isFriended(sanitizedUsername, true) && !client.getLocalPlayer().getName().equals(sanitizedUsername); if (isFriend) { diff --git a/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java b/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java index 24e3539106..823290e730 100644 --- a/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java @@ -32,6 +32,7 @@ import java.awt.Color; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.MessageNode; +import net.runelite.api.Player; import net.runelite.api.events.ChatMessage; import net.runelite.client.config.ChatColorConfig; import org.junit.Before; @@ -84,4 +85,67 @@ public class ChatMessageManagerTest verify(messageNode).setValue(eq("Your dodgy necklace protects you. It has 1 charge left.")); } + + @Test + public void testPublicFriendUsernameRecolouring() + { + final String localPlayerName = "RuneLite"; + final String friendName = "Zezima"; + + when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000")); + + chatMessageManager.loadColors(); + + // Setup message + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setName(friendName); + + MessageNode messageNode = mock(MessageNode.class); + chatMessage.setMessageNode(messageNode); + when(messageNode.getName()).thenReturn(friendName); + + // Setup friend checking + Player localPlayer = mock(Player.class); + + when(client.isFriended(friendName, true)).thenReturn(true); + when(client.getLocalPlayer()).thenReturn(localPlayer); + when(localPlayer.getName()).thenReturn(localPlayerName); + + chatMessageManager.onChatMessage(chatMessage); + + verify(messageNode).setName("" + friendName + ""); + } + + @Test + public void testPublicIronmanFriendUsernameRecolouring() + { + final String localPlayerName = "RuneLite"; + final String friendName = "BuddhaPuck"; + final String sanitizedFriendName = "BuddhaPuck"; + + when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000")); + + chatMessageManager.loadColors(); + + // Setup message + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setName(friendName); + + MessageNode messageNode = mock(MessageNode.class); + chatMessage.setMessageNode(messageNode); + when(messageNode.getName()).thenReturn(friendName); + + // Setup friend checking + Player localPlayer = mock(Player.class); + + when(client.isFriended(sanitizedFriendName, true)).thenReturn(true); + when(client.getLocalPlayer()).thenReturn(localPlayer); + when(localPlayer.getName()).thenReturn(localPlayerName); + + chatMessageManager.onChatMessage(chatMessage); + + verify(messageNode).setName("" + friendName + ""); + } } \ No newline at end of file From 5e14d666e00b661d71b97c53efda402c24c6aa58 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Sat, 13 Feb 2021 15:57:00 +0000 Subject: [PATCH 49/55] chat color: fix nonsensical test --- .../net/runelite/client/chat/ChatMessageManagerTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java b/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java index 823290e730..b75c79b277 100644 --- a/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java @@ -38,7 +38,6 @@ import net.runelite.client.config.ChatColorConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import static org.mockito.ArgumentMatchers.eq; import org.mockito.Mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -68,14 +67,14 @@ public class ChatMessageManagerTest } @Test - public void onChatMessage() + public void testMessageRecoloring() { - when(chatColorConfig.opaquePublicChat()).thenReturn(Color.decode("#b20000")); + when(chatColorConfig.opaqueServerMessage()).thenReturn(Color.decode("#b20000")); chatMessageManager.loadColors(); ChatMessage chatMessage = new ChatMessage(); - chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setType(ChatMessageType.GAMEMESSAGE); MessageNode messageNode = mock(MessageNode.class); chatMessage.setMessageNode(messageNode); @@ -83,7 +82,7 @@ public class ChatMessageManagerTest when(messageNode.getValue()).thenReturn("Your dodgy necklace protects you. It has 1 charge left."); chatMessageManager.onChatMessage(chatMessage); - verify(messageNode).setValue(eq("Your dodgy necklace protects you. It has 1 charge left.")); + verify(messageNode).setValue("Your dodgy necklace protects you. It has 1 charge left."); } @Test From 778dc07181839faec0415e351e033b572c8f1289 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 13 Feb 2021 11:21:07 -0500 Subject: [PATCH 50/55] Bump to 1.7.0-SNAPSHOT --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 2 +- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 782e4408cb..206c42e1ed 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 20d0eb865c..2a1bc72387 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 305b0e3b7f..62d2513870 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index e864273049..936a689ced 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 4adddc284a..e0e383d518 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index 9ee7f55c10..62fb44946e 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT pom RuneLite diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 6cc0d185cc..dd96cd1c8c 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 48eb8825ce..b8e92e238d 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 016b2d854f..3df1814484 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.6.40-SNAPSHOT + 1.7.0-SNAPSHOT script-assembler-plugin From 2cdfdf0284bbb36012df5505c2ec684bc0c795ea Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 30 Jan 2021 15:22:03 -0800 Subject: [PATCH 51/55] cluescrolls: Re-check named object highlights after hopping --- .../client/plugins/cluescrolls/ClueScrollPlugin.java | 5 +++++ 1 file changed, 5 insertions(+) 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 7a3ee36e66..d33a0e6b29 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 @@ -495,6 +495,10 @@ public class ClueScrollPlugin extends Plugin { resetClue(true); } + else if (state == GameState.HOPPING) + { + namedObjectCheckThisTick = true; + } } @Subscribe @@ -561,6 +565,7 @@ public class ClueScrollPlugin extends Plugin } // Load the current plane's tiles if a tick has elapsed since the player has changed planes + // or upon reaching a logged in state after hopping worlds if (namedObjectCheckThisTick) { namedObjectCheckThisTick = false; From 826f99679c572d69bdbd51bf37f82c96de6de9f1 Mon Sep 17 00:00:00 2001 From: Cyborger1 <45152844+Cyborger1@users.noreply.github.com> Date: Fri, 12 Feb 2021 22:36:45 -0800 Subject: [PATCH 52/55] emoji: Replace spoon and fork-and-knife emojis Without a shadow, these emojis were nearly unreadable on the fixed chat background. These hand-drawn replacements are detailed enough to be clearly understood against all kinds of backgrounds. --- .../client/plugins/emojis/fork_and_knife.png | Bin 116 -> 134 bytes .../runelite/client/plugins/emojis/spoon.png | Bin 120 -> 129 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fork_and_knife.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fork_and_knife.png index f82589d6c3c51be592bc41ec81d12c3cf56593c3..6f1140081662f1d3c1906ba828a4cfc2d2b0ca57 100644 GIT binary patch delta 116 zcmXSEW1Jw7$HdIQz`)zopr01&qur~m)} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png index c838403711a6adfdc32576a74d6585c359cf2c56..dc40dd32d41911365fb6d9c5824fb0eaea2a923e 100644 GIT binary patch delta 99 zcmby6l(7tF>WNww+68Q~44r57>UoeBivm0qZj+&>7V+hCfwr2KJYD@<);T3K0RZdm BA5Z`Q delta 90 zcmZoo{Y09#VGgoZ|B1s8bNd^W6#*!evU Date: Sat, 13 Feb 2021 14:16:19 -0500 Subject: [PATCH 53/55] emoji plugin: set message node message instead of rl format message The replaced message has no rl-format tags, and using the rl-format message causes it to lose color whenever the message node is refreshed due to not containing any rl-format tags --- .../net/runelite/client/plugins/emojis/EmojiPlugin.java | 8 +------- .../runelite/client/plugins/emojis/EmojiPluginTest.java | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java index e63a97c3cc..9fc33d8647 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java @@ -40,7 +40,6 @@ import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.OverheadTextChanged; import net.runelite.client.callback.ClientThread; -import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -63,9 +62,6 @@ public class EmojiPlugin extends Plugin @Inject private ClientThread clientThread; - @Inject - private ChatMessageManager chatMessageManager; - private int modIconsStart = -1; @Override @@ -145,9 +141,7 @@ public class EmojiPlugin extends Plugin return; } - messageNode.setRuneLiteFormatMessage(updatedMessage); - chatMessageManager.update(messageNode); - client.refreshChat(); + messageNode.setValue(updatedMessage); } @Subscribe diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/emojis/EmojiPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/emojis/EmojiPluginTest.java index 326ea07a38..99fc2dc174 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/emojis/EmojiPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/emojis/EmojiPluginTest.java @@ -89,7 +89,7 @@ public class EmojiPluginTest emojiPlugin.onChatMessage(chatMessage); - verify(messageNode).setRuneLiteFormatMessage(" "); + verify(messageNode).setValue(" "); } @Test @@ -113,7 +113,7 @@ public class EmojiPluginTest emojiPlugin.onChatMessage(chatMessage); - verify(messageNode).setRuneLiteFormatMessage(""); + verify(messageNode).setValue(""); } @Test From c6dc52d940f0dec945de4749f7f6b9b64b52b736 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Sat, 13 Feb 2021 21:40:36 +0000 Subject: [PATCH 54/55] Release 1.7.0 --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 206c42e1ed..377c5e5832 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 2a1bc72387..366f8da7d2 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 62d2513870..3c47730b91 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 936a689ced..ae4dcc347a 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index e0e383d518..7c667af7db 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 Web Service diff --git a/pom.xml b/pom.xml index 62fb44946e..820414b6e5 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 pom RuneLite @@ -61,7 +61,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - HEAD + runelite-parent-1.7.0 diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index dd96cd1c8c..b89bcb6d22 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index b8e92e238d..5c06128f1b 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 3df1814484..a1cc42542b 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0-SNAPSHOT + 1.7.0 script-assembler-plugin From 1684eccd006560f984474ffea1248dd8666df78c Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Sat, 13 Feb 2021 21:40:44 +0000 Subject: [PATCH 55/55] Bump for 1.7.1-SNAPSHOT --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 377c5e5832..dda9747db8 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 366f8da7d2..daabcfeec2 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 3c47730b91..40d121afe9 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index ae4dcc347a..9ac04bacbf 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 7c667af7db..ac41551a3a 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index 820414b6e5..51d715e468 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT pom RuneLite @@ -61,7 +61,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - runelite-parent-1.7.0 + HEAD diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index b89bcb6d22..58aa0a549a 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 5c06128f1b..35d74b8b6f 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index a1cc42542b..17e6be9199 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.7.0 + 1.7.1-SNAPSHOT script-assembler-plugin