From 503847f644ba53ab35914f0ff996363043680ff3 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Fri, 4 Oct 2019 22:59:41 -0700 Subject: [PATCH 01/35] boosts: Hide restore timer when no boosts are visible Fixes runelite/runelite#6983 --- .../client/plugins/boosts/BoostIndicator.java | 7 +------ .../client/plugins/boosts/BoostsOverlay.java | 16 +++++++++------- .../client/plugins/boosts/BoostsPlugin.java | 17 +++++++++++++---- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostIndicator.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostIndicator.java index 00a0a97561..802c05eac7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostIndicator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostIndicator.java @@ -87,11 +87,6 @@ public class BoostIndicator extends InfoBox @Override public boolean render() { - if (config.displayInfoboxes() && plugin.canShowBoosts() && plugin.getShownSkills().contains(getSkill())) - { - return client.getBoostedSkillLevel(skill) != client.getRealSkillLevel(skill); - } - - return false; + return config.displayInfoboxes() && plugin.canShowBoosts() && plugin.getSkillsToDisplay().contains(getSkill()); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java index 49d9389462..8ebc077224 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.boosts; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; +import java.util.Set; import javax.inject.Inject; import net.runelite.api.Client; import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; @@ -89,18 +90,19 @@ class BoostsOverlay extends Overlay .build()); } + final Set boostedSkills = plugin.getSkillsToDisplay(); + + if (boostedSkills.isEmpty()) + { + return panelComponent.render(graphics); + } + if (plugin.canShowBoosts()) { - for (Skill skill : plugin.getShownSkills()) + for (Skill skill : boostedSkills) { final int boosted = client.getBoostedSkillLevel(skill); final int base = client.getRealSkillLevel(skill); - - if (boosted == base) - { - continue; - } - final int boost = boosted - base; final Color strColor = getTextColor(boost); String str; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java index aa7e46d00e..8d3cb34aef 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java @@ -27,7 +27,7 @@ package net.runelite.client.plugins.boosts; import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; import java.util.Arrays; -import java.util.HashSet; +import java.util.EnumSet; import java.util.Set; import javax.inject.Inject; import javax.inject.Singleton; @@ -92,7 +92,9 @@ public class BoostsPlugin extends Plugin private SkillIconManager skillIconManager; @Getter - private final Set shownSkills = new HashSet<>(); + private final Set skillsToDisplay = EnumSet.noneOf(Skill.class); + + private final Set shownSkills = EnumSet.noneOf(Skill.class); private boolean isChangedDown = false; private boolean isChangedUp = false; @@ -114,7 +116,6 @@ public class BoostsPlugin extends Plugin overlayManager.add(boostsOverlay); updateShownSkills(); - updateBoostedStats(); Arrays.fill(lastSkillLevels, -1); // Add infoboxes for everything at startup and then determine inside if it will be rendered @@ -140,6 +141,7 @@ public class BoostsPlugin extends Plugin lastChangeUp = -1; isChangedUp = false; isChangedDown = false; + skillsToDisplay.clear(); } @Subscribe @@ -282,6 +284,7 @@ public class BoostsPlugin extends Plugin shownSkills.addAll(BOOSTABLE_NON_COMBAT_SKILLS); break; } + updateBoostedStats(); } private void updateBoostedStats() @@ -289,11 +292,12 @@ public class BoostsPlugin extends Plugin // Reset is boosted isChangedDown = false; isChangedUp = false; + skillsToDisplay.clear(); // Check if we are still boosted for (final Skill skill : Skill.values()) { - if (!BOOSTABLE_COMBAT_SKILLS.contains(skill) && !BOOSTABLE_NON_COMBAT_SKILLS.contains(skill)) + if (!shownSkills.contains(skill)) { continue; } @@ -309,6 +313,11 @@ public class BoostsPlugin extends Plugin { isChangedDown = true; } + + if (boosted != base) + { + skillsToDisplay.add(skill); + } } } From 8dc0e752c8ee883266ed9a23a8330787a862c80e Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Fri, 4 Oct 2019 08:10:24 -0700 Subject: [PATCH 02/35] woodcutting: Reduce visibilities, mark Nullables --- .../client/plugins/woodcutting/WoodcuttingPlugin.java | 5 ++++- .../client/plugins/woodcutting/WoodcuttingSession.java | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java index a8a38d852e..82d0a730ce 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java @@ -32,6 +32,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; +import javax.annotation.Nullable; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; @@ -90,9 +91,11 @@ public class WoodcuttingPlugin extends Plugin private WoodcuttingConfig config; @Getter + @Nullable private WoodcuttingSession session; @Getter + @Nullable private Axe axe; @Getter @@ -258,4 +261,4 @@ public class WoodcuttingPlugin extends Plugin this.axe = axe; } } -} \ No newline at end of file +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java index ac5d66130e..aaf2919c01 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java @@ -26,16 +26,16 @@ package net.runelite.client.plugins.woodcutting; import java.time.Instant; -public class WoodcuttingSession +class WoodcuttingSession { private Instant lastLogCut; - public void setLastLogCut() + void setLastLogCut() { lastLogCut = Instant.now(); } - public Instant getLastLogCut() + Instant getLastLogCut() { return lastLogCut; } From 8a206e8c92f39970176f6f92690de5cc5b410765 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Fri, 4 Oct 2019 08:12:23 -0700 Subject: [PATCH 03/35] woodcutting: Add axe animation matching helper method --- .../java/net/runelite/client/plugins/woodcutting/Axe.java | 6 ++++++ .../client/plugins/woodcutting/WoodcuttingOverlay.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java index 4ad6d6e90f..24d7249a4d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java @@ -50,6 +50,7 @@ import static net.runelite.api.ItemID.MITHRIL_AXE; import static net.runelite.api.ItemID.RUNE_AXE; import static net.runelite.api.ItemID.STEEL_AXE; import static net.runelite.api.ItemID._3RD_AGE_AXE; +import net.runelite.api.Player; @AllArgsConstructor @Getter @@ -84,6 +85,11 @@ enum Axe AXE_ANIM_IDS = builder.build(); } + boolean matchesChoppingAnimation(final Player player) + { + return player != null && animId == player.getAnimation(); + } + static Axe findAxeByAnimId(int animId) { return AXE_ANIM_IDS.get(animId); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingOverlay.java index 5aa6f0cde2..6f863cdda7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingOverlay.java @@ -81,7 +81,7 @@ class WoodcuttingOverlay extends Overlay panelComponent.getChildren().clear(); Axe axe = plugin.getAxe(); - if (axe != null && axe.getAnimId() == client.getLocalPlayer().getAnimation()) + if (axe != null && axe.matchesChoppingAnimation(client.getLocalPlayer())) { panelComponent.getChildren().add(TitleComponent.builder() .text("Woodcutting") From dd771eaab752b877cd9dc7ea714caf0ac46c2df3 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Fri, 4 Oct 2019 08:12:55 -0700 Subject: [PATCH 04/35] woodcutting: Fix overlay hiding during long chop delays This fixes a bug where the overlay would become hidden when chopping at a tree without successfully chopping a log for longer than the configured timeout, and would display "NOT woodcutting" if a log was successfully chopped thereafter. Fixes runelite/runelite#7506 --- .../plugins/woodcutting/WoodcuttingPlugin.java | 12 +++++++++--- .../plugins/woodcutting/WoodcuttingSession.java | 10 +++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java index 82d0a730ce..750e887365 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java @@ -148,13 +148,19 @@ public class WoodcuttingPlugin extends Plugin respawns.removeIf(TreeRespawn::isExpired); - if (session == null || session.getLastLogCut() == null) + if (session == null || session.getLastChopping() == null) { return; } + if (axe != null && axe.matchesChoppingAnimation(client.getLocalPlayer())) + { + session.setLastChopping(); + return; + } + Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(session.getLastLogCut(), Instant.now()); + Duration sinceCut = Duration.between(session.getLastChopping(), Instant.now()); if (sinceCut.compareTo(statTimeout) >= 0) { @@ -175,7 +181,7 @@ public class WoodcuttingPlugin extends Plugin session = new WoodcuttingSession(); } - session.setLastLogCut(); + session.setLastChopping(); } if (event.getMessage().contains("A bird's nest falls out of the tree") && config.showNestNotification()) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java index aaf2919c01..39d3bafe29 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingSession.java @@ -28,15 +28,15 @@ import java.time.Instant; class WoodcuttingSession { - private Instant lastLogCut; + private Instant lastChopping; - void setLastLogCut() + void setLastChopping() { - lastLogCut = Instant.now(); + lastChopping = Instant.now(); } - Instant getLastLogCut() + Instant getLastChopping() { - return lastLogCut; + return lastChopping; } } From eb098792053145a2e44410b2c60475799d493890 Mon Sep 17 00:00:00 2001 From: Brandt Hill Date: Fri, 13 Mar 2020 19:15:40 -0700 Subject: [PATCH 05/35] fishing: Check player animation to update fishing status This commit adds an animation check to the other fishing status checks already present in the fishing overlay (interacting and fishing spot NPC name check) to ensure that the status correctly changes to "NOT fishing" when the player's fishing animation is interrupted by certain actions such as being presented with a level-up dialog. This commit causes one other behavioral change as a side effect, which is that the player's fishing status will be "NOT fishing" while running toward a distant fishing spot until they reach it and start their fishing animation. Fixes runelite/runelite#10900 --- .../java/net/runelite/api/AnimationID.java | 8 ++++++ .../plugins/fishing/FishingOverlay.java | 28 ++++++++++++++++++- 2 files changed, 35 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 60aa84382e..b53ff59a2a 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -103,6 +103,14 @@ public final class AnimationID public static final int FISHING_CRUSHING_INFERNAL_EELS = 7553; public static final int FISHING_CUTTING_SACRED_EELS = 7151; public static final int FISHING_BAREHAND = 6709; + public static final int FISHING_BAREHAND_WINDUP_1 = 6703; + public static final int FISHING_BAREHAND_WINDUP_2 = 6704; + public static final int FISHING_BAREHAND_CAUGHT_SHARK_1 = 6705; + public static final int FISHING_BAREHAND_CAUGHT_SHARK_2 = 6706; + public static final int FISHING_BAREHAND_CAUGHT_SWORDFISH_1 = 6707; + public static final int FISHING_BAREHAND_CAUGHT_SWORDFISH_2 = 6708; + public static final int FISHING_BAREHAND_CAUGHT_TUNA_1 = 6710; + public static final int FISHING_BAREHAND_CAUGHT_TUNA_2 = 6711; public static final int MINING_BRONZE_PICKAXE = 625; public static final int MINING_IRON_PICKAXE = 626; public static final int MINING_STEEL_PICKAXE = 627; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java index e6cb7bd1e2..96b023f95f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java @@ -27,7 +27,10 @@ package net.runelite.client.plugins.fishing; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; +import java.util.Set; import javax.inject.Inject; +import com.google.common.collect.ImmutableSet; +import net.runelite.api.AnimationID; import net.runelite.api.Client; import net.runelite.api.GraphicID; import static net.runelite.api.MenuAction.RUNELITE_OVERLAY; @@ -47,6 +50,28 @@ class FishingOverlay extends Overlay private static final String FISHING_SPOT = "Fishing spot"; static final String FISHING_RESET = "Reset"; + private static final Set FISHING_ANIMATIONS = ImmutableSet.of( + AnimationID.FISHING_BARBTAIL_HARPOON, + AnimationID.FISHING_BAREHAND, + AnimationID.FISHING_BAREHAND_CAUGHT_SHARK_1, + AnimationID.FISHING_BAREHAND_CAUGHT_SHARK_2, + AnimationID.FISHING_BAREHAND_CAUGHT_SWORDFISH_1, + AnimationID.FISHING_BAREHAND_CAUGHT_SWORDFISH_2, + AnimationID.FISHING_BAREHAND_CAUGHT_TUNA_1, + AnimationID.FISHING_BAREHAND_CAUGHT_TUNA_2, + AnimationID.FISHING_BAREHAND_WINDUP_1, + AnimationID.FISHING_BAREHAND_WINDUP_2, + AnimationID.FISHING_BIG_NET, + AnimationID.FISHING_CAGE, + AnimationID.FISHING_CRYSTAL_HARPOON, + AnimationID.FISHING_DRAGON_HARPOON, + AnimationID.FISHING_HARPOON, + AnimationID.FISHING_INFERNAL_HARPOON, + AnimationID.FISHING_KARAMBWAN, + AnimationID.FISHING_NET, + AnimationID.FISHING_OILY_ROD, + AnimationID.FISHING_POLE_CAST); + private final Client client; private final FishingPlugin plugin; private final FishingConfig config; @@ -78,7 +103,8 @@ class FishingOverlay extends Overlay panelComponent.getChildren().clear(); if (client.getLocalPlayer().getInteracting() != null && client.getLocalPlayer().getInteracting().getName().contains(FISHING_SPOT) - && client.getLocalPlayer().getInteracting().getGraphic() != GraphicID.FLYING_FISH) + && client.getLocalPlayer().getInteracting().getGraphic() != GraphicID.FLYING_FISH + && FISHING_ANIMATIONS.contains(client.getLocalPlayer().getAnimation())) { panelComponent.getChildren().add(TitleComponent.builder() .text("Fishing") From 01737bf7735de40614c77361839b9e368eea3f22 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Sat, 28 Mar 2020 21:33:42 +0000 Subject: [PATCH 06/35] clues: update Immenizz's master clue to reflect his NPC's name change --- .../runelite/client/plugins/cluescrolls/clues/AnagramClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java index 6974974982..accb87bdaa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/AnagramClue.java @@ -106,7 +106,7 @@ public class AnagramClue extends ClueScroll implements TextClueScroll, NpcClueSc new AnagramClue("I EAT ITS CHART HINTS DO U", "Shiratti the Custodian", new WorldPoint(3427, 2927, 0), "North of fountain, Nardah"), new AnagramClue("I EVEN", "Nieve", new WorldPoint(2432, 3422, 0), "The slayer master in Gnome Stronghold", "How many farming patches are there in Gnome stronghold?", "2"), new AnagramClue("I FAFFY RUN", "Fairy Nuff", new WorldPoint(3201, 3169, 0), "North of the bank in Zanaris"), - new AnagramClue("IM N ZEZIM", "Impling", new WorldPoint(2592, 4324, 0), "The Imp inside Puro-Puro"), + new AnagramClue("IM N ZEZIM", "Immenizz", new WorldPoint(2592, 4324, 0), "The Imp inside Puro-Puro"), new AnagramClue("KAY SIR", "Sir Kay", new WorldPoint(2760, 3496, 0), "The courtyard in Camelot Castle", "How many fountains are there within the grounds of Camelot castle.", "6"), new AnagramClue("LEAKEY", "Kaylee", new WorldPoint(2957, 3370, 0), "Rising Sun Inn in Falador", "How many chairs are there in the Rising Sun?", "18"), new AnagramClue("LAND DOOMD", "Odd Old Man", new WorldPoint(3359, 3506, 0), "Limestone mine northeast of Varrock"), From 32f6d2da2592fdd4de686fe4bc5e6a4d2948bac7 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 30 Mar 2020 09:40:06 +0100 Subject: [PATCH 07/35] api: add gilded axe animation --- runelite-api/src/main/java/net/runelite/api/AnimationID.java | 1 + 1 file changed, 1 insertion(+) 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 60aa84382e..f487be4f63 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -41,6 +41,7 @@ public final class AnimationID public static final int WOODCUTTING_MITHRIL = 871; public static final int WOODCUTTING_ADAMANT = 869; public static final int WOODCUTTING_RUNE = 867; + public static final int WOODCUTTING_GILDED = 8303; public static final int WOODCUTTING_DRAGON = 2846; public static final int WOODCUTTING_INFERNAL = 2117; public static final int WOODCUTTING_3A_AXE = 7264; From bd3c3be6f8e65bc5106f581d39ab762e2089b359 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 30 Mar 2020 09:40:18 +0100 Subject: [PATCH 08/35] woodcutting: add support for gilded axe --- .../main/java/net/runelite/client/plugins/woodcutting/Axe.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java index 4ad6d6e90f..040e551876 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java @@ -34,6 +34,7 @@ import static net.runelite.api.AnimationID.WOODCUTTING_BLACK; import static net.runelite.api.AnimationID.WOODCUTTING_BRONZE; import static net.runelite.api.AnimationID.WOODCUTTING_CRYSTAL; import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON; +import static net.runelite.api.AnimationID.WOODCUTTING_GILDED; import static net.runelite.api.AnimationID.WOODCUTTING_INFERNAL; import static net.runelite.api.AnimationID.WOODCUTTING_IRON; import static net.runelite.api.AnimationID.WOODCUTTING_MITHRIL; @@ -44,6 +45,7 @@ import static net.runelite.api.ItemID.BLACK_AXE; import static net.runelite.api.ItemID.BRONZE_AXE; import static net.runelite.api.ItemID.CRYSTAL_AXE; import static net.runelite.api.ItemID.DRAGON_AXE; +import static net.runelite.api.ItemID.GILDED_AXE; import static net.runelite.api.ItemID.INFERNAL_AXE; import static net.runelite.api.ItemID.IRON_AXE; import static net.runelite.api.ItemID.MITHRIL_AXE; @@ -62,6 +64,7 @@ enum Axe MITHRIL(WOODCUTTING_MITHRIL, MITHRIL_AXE), ADAMANT(WOODCUTTING_ADAMANT, ADAMANT_AXE), RUNE(WOODCUTTING_RUNE, RUNE_AXE), + GILDED(WOODCUTTING_GILDED, GILDED_AXE), DRAGON(WOODCUTTING_DRAGON, DRAGON_AXE), INFERNAL(WOODCUTTING_INFERNAL, INFERNAL_AXE), THIRDAGE(WOODCUTTING_3A_AXE, _3RD_AGE_AXE), From 7ca124da6b9dbdc1b82d1c1edd9c5f51b456ab99 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 30 Mar 2020 09:40:31 +0100 Subject: [PATCH 09/35] idle notifier: add support for gilded axe --- .../runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java | 1 + 1 file changed, 1 insertion(+) 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 1e26314f00..3dbc39bb54 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 @@ -135,6 +135,7 @@ public class IdleNotifierPlugin extends Plugin case WOODCUTTING_MITHRIL: case WOODCUTTING_ADAMANT: case WOODCUTTING_RUNE: + case WOODCUTTING_GILDED: case WOODCUTTING_DRAGON: case WOODCUTTING_INFERNAL: case WOODCUTTING_3A_AXE: From c41b80065043766c7ebf4f7a7ddeb5713323501e Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 30 Mar 2020 09:40:41 +0100 Subject: [PATCH 10/35] wintertodt: add support for gilded axe --- .../runelite/client/plugins/wintertodt/WintertodtPlugin.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java index 40dfeff441..f993505978 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java @@ -44,6 +44,7 @@ import static net.runelite.api.AnimationID.WOODCUTTING_BLACK; import static net.runelite.api.AnimationID.WOODCUTTING_BRONZE; import static net.runelite.api.AnimationID.WOODCUTTING_CRYSTAL; import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON; +import static net.runelite.api.AnimationID.WOODCUTTING_GILDED; import static net.runelite.api.AnimationID.WOODCUTTING_INFERNAL; import static net.runelite.api.AnimationID.WOODCUTTING_IRON; import static net.runelite.api.AnimationID.WOODCUTTING_MITHRIL; @@ -410,6 +411,7 @@ public class WintertodtPlugin extends Plugin case WOODCUTTING_MITHRIL: case WOODCUTTING_ADAMANT: case WOODCUTTING_RUNE: + case WOODCUTTING_GILDED: case WOODCUTTING_DRAGON: case WOODCUTTING_INFERNAL: case WOODCUTTING_3A_AXE: From 17da7adab88ef9dba165846eba2d2fc051d851d5 Mon Sep 17 00:00:00 2001 From: AaronPoon Date: Tue, 28 Jan 2020 10:34:37 -0800 Subject: [PATCH 11/35] agility: highlight 'Stick' in Werewolf Agility Course Co-authored-by: dekvall --- .../client/plugins/agility/AgilityConfig.java | 22 ++++++++++++ .../plugins/agility/AgilityOverlay.java | 34 ++++++++++++------- .../client/plugins/agility/AgilityPlugin.java | 20 ++++++++++- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java index b84f9b5c7b..a2302ad05b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java @@ -165,4 +165,26 @@ public interface AgilityConfig extends Config { return true; } + + @ConfigItem( + keyName = "highlightStick", + name = "Highlight Stick", + description = "Highlight the retrievable stick in the Werewolf Agility Course", + position = 12 + ) + default boolean highlightStick() + { + return true; + } + + @ConfigItem( + keyName = "stickHighlightColor", + name = "Stick Highlight Color", + description = "Color of highlighted stick", + position = 13 + ) + default Color stickHighlightColor() + { + return Color.RED; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java index 28120aa393..5a868b1b20 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java @@ -68,6 +68,8 @@ class AgilityOverlay extends Overlay LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation(); Point mousePosition = client.getMouseCanvasPosition(); final List marksOfGrace = plugin.getMarksOfGrace(); + final Tile stickTile = plugin.getStickTile(); + plugin.getObstacles().forEach((object, obstacle) -> { if (Obstacles.SHORTCUT_OBSTACLE_IDS.containsKey(object.getId()) && !config.highlightShortcuts() || @@ -122,21 +124,29 @@ class AgilityOverlay extends Overlay { for (Tile markOfGraceTile : marksOfGrace) { - if (markOfGraceTile.getPlane() == client.getPlane() && markOfGraceTile.getItemLayer() != null - && markOfGraceTile.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) - { - final Polygon poly = markOfGraceTile.getItemLayer().getCanvasTilePoly(); - - if (poly == null) - { - continue; - } - - OverlayUtil.renderPolygon(graphics, poly, config.getMarkColor()); - } + highlightTile(graphics, playerLocation, markOfGraceTile, config.getMarkColor()); } } + if (stickTile != null && config.highlightStick()) + { + highlightTile(graphics, playerLocation, stickTile, config.stickHighlightColor()); + } + return null; } + + private void highlightTile(Graphics2D graphics, LocalPoint playerLocation, Tile tile, Color color) + { + if (tile.getPlane() == client.getPlane() && tile.getItemLayer() != null + && tile.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) + { + final Polygon poly = tile.getItemLayer().getCanvasTilePoly(); + + if (poly != null) + { + OverlayUtil.renderPolygon(graphics, poly, color); + } + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java index dad500879d..621af6ca1f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java @@ -31,6 +31,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; +import lombok.AccessLevel; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; @@ -43,7 +44,6 @@ import net.runelite.api.Tile; import net.runelite.api.TileItem; import net.runelite.api.TileObject; import net.runelite.api.coords.WorldPoint; -import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.DecorativeObjectChanged; import net.runelite.api.events.DecorativeObjectDespawned; import net.runelite.api.events.DecorativeObjectSpawned; @@ -64,6 +64,7 @@ import net.runelite.api.events.WallObjectSpawned; import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.game.AgilityShortcut; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; @@ -127,6 +128,9 @@ public class AgilityPlugin extends Plugin @Getter private int agilityLevel; + @Getter(AccessLevel.PACKAGE) + private Tile stickTile; + @Provides AgilityConfig getConfig(ConfigManager configManager) { @@ -150,6 +154,7 @@ public class AgilityPlugin extends Plugin obstacles.clear(); session = null; agilityLevel = 0; + stickTile = null; } @Subscribe @@ -166,6 +171,7 @@ public class AgilityPlugin extends Plugin case LOADING: marksOfGrace.clear(); obstacles.clear(); + stickTile = null; break; case LOGGED_IN: if (!isInAgilityArena()) @@ -244,13 +250,25 @@ public class AgilityPlugin extends Plugin { marksOfGrace.add(tile); } + + if (item.getId() == ItemID.STICK) + { + stickTile = tile; + } } @Subscribe public void onItemDespawned(ItemDespawned itemDespawned) { + final TileItem item = itemDespawned.getItem(); final Tile tile = itemDespawned.getTile(); + marksOfGrace.remove(tile); + + if (item.getId() == ItemID.STICK && stickTile == tile) + { + stickTile = null; + } } @Subscribe From c69a6fbe2f903ae3e62cb11009789ad202d2f71b Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 30 Mar 2020 16:35:26 +0100 Subject: [PATCH 12/35] api: add gilded pickaxe animations --- runelite-api/src/main/java/net/runelite/api/AnimationID.java | 2 ++ 1 file changed, 2 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 f487be4f63..068a1325bd 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -111,6 +111,7 @@ public final class AnimationID public static final int MINING_MITHRIL_PICKAXE = 629; public static final int MINING_ADAMANT_PICKAXE = 628; public static final int MINING_RUNE_PICKAXE = 624; + public static final int MINING_GILDED_PICKAXE = 8313; public static final int MINING_DRAGON_PICKAXE = 7139; public static final int MINING_DRAGON_PICKAXE_UPGRADED = 642; public static final int MINING_DRAGON_PICKAXE_OR = 8346; @@ -124,6 +125,7 @@ public final class AnimationID public static final int MINING_MOTHERLODE_MITHRIL = 6757; public static final int MINING_MOTHERLODE_ADAMANT = 6756; public static final int MINING_MOTHERLODE_RUNE = 6752; + public static final int MINING_MOTHERLODE_GILDED = 8312; public static final int MINING_MOTHERLODE_DRAGON = 6758; public static final int MINING_MOTHERLODE_DRAGON_UPGRADED = 335; public static final int MINING_MOTHERLODE_DRAGON_OR = 8344; From 45ec248e6070ac1e76fbf9d3b3a86a65a46f455c Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 30 Mar 2020 16:35:43 +0100 Subject: [PATCH 13/35] idle notifier: add support for gilded pickaxe --- .../client/plugins/idlenotifier/IdleNotifierPlugin.java | 2 ++ 1 file changed, 2 insertions(+) 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 3dbc39bb54..206db46141 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 @@ -202,6 +202,7 @@ public class IdleNotifierPlugin extends Plugin case MINING_MITHRIL_PICKAXE: case MINING_ADAMANT_PICKAXE: case MINING_RUNE_PICKAXE: + case MINING_GILDED_PICKAXE: case MINING_DRAGON_PICKAXE: case MINING_DRAGON_PICKAXE_UPGRADED: case MINING_DRAGON_PICKAXE_OR: @@ -218,6 +219,7 @@ public class IdleNotifierPlugin extends Plugin case MINING_MOTHERLODE_MITHRIL: case MINING_MOTHERLODE_ADAMANT: case MINING_MOTHERLODE_RUNE: + case MINING_MOTHERLODE_GILDED: case MINING_MOTHERLODE_DRAGON: case MINING_MOTHERLODE_DRAGON_UPGRADED: case MINING_MOTHERLODE_DRAGON_OR: From 361efbafd1727b8e059e4107bc84f01393bde7d2 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Mon, 30 Mar 2020 16:35:59 +0100 Subject: [PATCH 14/35] motherlode: add support for gilded pickaxe --- .../client/plugins/motherlode/MotherlodeOverlay.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java index c06fdb1efe..7ac14372a3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java @@ -39,6 +39,7 @@ import static net.runelite.api.AnimationID.MINING_MOTHERLODE_CRYSTAL; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_OR; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_UPGRADED; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_GILDED; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_INFERNAL; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_IRON; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_MITHRIL; @@ -58,8 +59,9 @@ class MotherlodeOverlay extends Overlay private static final Set MINING_ANIMATION_IDS = ImmutableSet.of( MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL, MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT, - MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_DRAGON, MINING_MOTHERLODE_DRAGON_UPGRADED, - MINING_MOTHERLODE_DRAGON_OR, MINING_MOTHERLODE_INFERNAL, MINING_MOTHERLODE_CRYSTAL + MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_GILDED, MINING_MOTHERLODE_DRAGON, + MINING_MOTHERLODE_DRAGON_UPGRADED, MINING_MOTHERLODE_DRAGON_OR, MINING_MOTHERLODE_INFERNAL, + MINING_MOTHERLODE_CRYSTAL ); static final String MINING_RESET = "Reset"; From 65d63cd7548370a36afcc0cd45de0d99e34f3965 Mon Sep 17 00:00:00 2001 From: Deon Zhao Date: Tue, 24 Mar 2020 17:56:48 -0700 Subject: [PATCH 15/35] loottracker: Track herbiboar loot with an open herb sack When looting the herbiboar with an open herb sack, instead of receiving the herbs to your inventory, the herbs are deposited to the sack directly and the player receives chat messages indicating the herbs they received. This commit adds support for reading those chat messages when looting the herbiboar. This change incidentally fixes an issue which arose when the open herb sack was introduced to the game where any inventory change after looting the herbiboar would be tracked as herbiboar loot, such as drinking a stamina potion. Closes #10655 Fixes #10718 --- .../loottracker/LootTrackerPlugin.java | 39 ++++++++- .../loottracker/LootTrackerPluginTest.java | 85 ++++++++++++++++++- 2 files changed, 121 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index ae0237939a..afad2d6af8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -63,6 +63,7 @@ import net.runelite.api.GameState; import net.runelite.api.InventoryID; import net.runelite.api.ItemComposition; import net.runelite.api.ItemContainer; +import net.runelite.api.MessageNode; import net.runelite.api.NPC; import net.runelite.api.Player; import net.runelite.api.SpriteID; @@ -116,8 +117,10 @@ public class LootTrackerPlugin extends Plugin private static final int THEATRE_OF_BLOOD_REGION = 12867; // Herbiboar loot handling - private static final String HERBIBOAR_LOOTED_MESSAGE = "You harvest herbs from the herbiboar, whereupon it escapes."; + @VisibleForTesting + static final String HERBIBOAR_LOOTED_MESSAGE = "You harvest herbs from the herbiboar, whereupon it escapes."; private static final String HERBIBOAR_EVENT = "Herbiboar"; + private static final Pattern HERBIBOAR_HERB_SACK_PATTERN = Pattern.compile(".+(Grimy .+?) herb.+"); // Hespori loot handling private static final String HESPORI_LOOTED_MESSAGE = "You have successfully cleared this patch for new crops."; @@ -500,10 +503,14 @@ public class LootTrackerPlugin extends Plugin if (message.equals(HERBIBOAR_LOOTED_MESSAGE)) { + if (processHerbiboarHerbSackLoot(event.getTimestamp())) + { + return; + } + eventType = HERBIBOAR_EVENT; lootRecordType = LootRecordType.EVENT; takeInventorySnapshot(); - return; } @@ -677,6 +684,34 @@ public class LootTrackerPlugin extends Plugin } } + private boolean processHerbiboarHerbSackLoot(int timestamp) + { + List herbs = new ArrayList<>(); + + for (MessageNode messageNode : client.getMessages()) + { + if (messageNode.getTimestamp() != timestamp + || messageNode.getType() != ChatMessageType.SPAM) + { + continue; + } + + Matcher matcher = HERBIBOAR_HERB_SACK_PATTERN.matcher(messageNode.getValue()); + if (matcher.matches()) + { + herbs.add(new ItemStack(itemManager.search(matcher.group(1)).get(0).getId(), 1, client.getLocalPlayer().getLocalLocation())); + } + } + + if (herbs.isEmpty()) + { + return false; + } + + addLoot(HERBIBOAR_EVENT, -1, LootRecordType.EVENT, herbs); + return true; + } + void toggleItem(String name, boolean ignore) { final Set ignoredItemSet = new HashSet<>(ignoredItems); diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java index 4cb4e18a8f..2f30c315fc 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java @@ -24,32 +24,66 @@ */ package net.runelite.client.plugins.loottracker; +import com.google.common.collect.ImmutableMap; import com.google.inject.Guice; import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; +import net.runelite.api.ItemID; +import net.runelite.api.IterableHashTable; +import net.runelite.api.MessageNode; import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; import net.runelite.client.account.SessionManager; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemStack; import net.runelite.client.game.SpriteManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.http.api.item.ItemPrice; import net.runelite.http.api.loottracker.LootRecordType; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import org.mockito.Mock; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class LootTrackerPluginTest { + private static final Map HERB_IDS_TO_NAMES = ImmutableMap.builder() + .put(ItemID.GRIMY_GUAM_LEAF, "Grimy guam leaf") + .put(ItemID.GRIMY_MARRENTILL, "Grimy marrentill") + .put(ItemID.GRIMY_TARROMIN, "Grimy tarromin") + .put(ItemID.GRIMY_HARRALANDER, "Grimy harralander") + .put(ItemID.GRIMY_RANARR_WEED, "Grimy ranarr weed") + .put(ItemID.GRIMY_IRIT_LEAF, "Grimy irit leaf") + .put(ItemID.GRIMY_AVANTOE, "Grimy avantoe") + .put(ItemID.GRIMY_KWUARM, "Grimy kwuarm") + .put(ItemID.GRIMY_SNAPDRAGON, "Grimy snapdragon") + .put(ItemID.GRIMY_CADANTINE, "Grimy cadantine") + .put(ItemID.GRIMY_LANTADYME, "Grimy lantadyme") + .put(ItemID.GRIMY_DWARF_WEED, "Grimy dwarf weed") + .put(ItemID.GRIMY_TORSTOL, "Grimy torstol") + .build(); + @Mock @Bind private ScheduledExecutorService scheduledExecutorService; @@ -77,6 +111,10 @@ public class LootTrackerPluginTest @Bind private SessionManager sessionManager; + @Mock + @Bind + private ItemManager itemManager; + @Before public void setUp() { @@ -106,4 +144,49 @@ public class LootTrackerPluginTest assertEquals("Clue Scroll (Master)", lootTrackerPlugin.eventType); assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType); } -} \ No newline at end of file + + @Test + public void testHerbiboarHerbSack() + { + for (Map.Entry herb : HERB_IDS_TO_NAMES.entrySet()) + { + final int id = herb.getKey(); + final String name = herb.getValue(); + final String herbMessage = String.format("You put the %s herb into your herb sack.", name); + final String herbFullMessage = String.format("Your herb sack is too full to hold the %s herb.", name); + + final ItemPrice herbPrice = new ItemPrice(); + herbPrice.setId(id); + herbPrice.setName(name); + when(itemManager.search(name)).thenReturn(Collections.singletonList(herbPrice)); + + MessageNode node = mock(MessageNode.class); + when(node.getType()).thenReturn(ChatMessageType.SPAM); + when(node.getValue()).thenReturn(herbMessage); + + MessageNode nodeFull = mock(MessageNode.class); + when(nodeFull.getType()).thenReturn(ChatMessageType.SPAM); + when(nodeFull.getValue()).thenReturn(herbFullMessage); + + IterableHashTable messageTable = mock(IterableHashTable.class); + Iterator mockIterator = mock(Iterator.class); + when(mockIterator.hasNext()).thenReturn(true, true, false); + when(mockIterator.next()).thenReturn(node).thenReturn(nodeFull); + when(messageTable.iterator()).thenReturn(mockIterator); + when(client.getMessages()).thenReturn(messageTable); + + LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin); + doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(Collection.class)); + + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", LootTrackerPlugin.HERBIBOAR_LOOTED_MESSAGE, "", 0); + lootTrackerPluginSpy.onChatMessage(chatMessage); + + verify(lootTrackerPluginSpy).addLoot("Herbiboar", -1, LootRecordType.EVENT, Arrays.asList( + new ItemStack(id, 1, null), + new ItemStack(id, 1, null) + )); + // Check the event type is null, which means the plugin isn't waiting on an inventory change event + assertNull(lootTrackerPlugin.eventType); + } + } +} From d02ddfc1b2479134f660c507c73ecfb47e530e29 Mon Sep 17 00:00:00 2001 From: Alexsuperfly Date: Sat, 28 Mar 2020 12:03:37 -0400 Subject: [PATCH 16/35] OverlayRenderer: prevent moving DYNAMIC and TOOLTIP overlays --- .../client/ui/overlay/OverlayRenderer.java | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index 01cf3cec85..34b7715491 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -213,29 +213,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener for (Overlay overlay : overlays) { - OverlayPosition overlayPosition = overlay.getPosition(); - - if (overlay.getPreferredPosition() != null) - { - overlayPosition = overlay.getPreferredPosition(); - } - - if (!isResizeable) - { - // On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as - // BOTTOM_RIGHT and CANVAS_TOP_RIGHT is same as TOP_RIGHT. - // Just use BOTTOM_RIGHT and TOP_RIGHT to prevent overlays from - // drawing over each other. - switch (overlayPosition) - { - case CANVAS_TOP_RIGHT: - overlayPosition = OverlayPosition.TOP_RIGHT; - break; - case ABOVE_CHATBOX_RIGHT: - overlayPosition = OverlayPosition.BOTTOM_RIGHT; - break; - } - } + final OverlayPosition overlayPosition = getCorrectedOverlayPosition(overlay); if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) { @@ -333,6 +311,13 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener { for (Overlay overlay : overlayManager.getOverlays()) { + final OverlayPosition overlayPosition = getCorrectedOverlayPosition(overlay); + + if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) + { + continue; + } + if (overlay.getBounds().contains(mousePoint)) { if (SwingUtilities.isRightMouseButton(mouseEvent)) @@ -512,6 +497,35 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener overlay.getBounds().setSize(dimension); } + private OverlayPosition getCorrectedOverlayPosition(final Overlay overlay) + { + OverlayPosition overlayPosition = overlay.getPosition(); + + if (overlay.getPreferredPosition() != null) + { + overlayPosition = overlay.getPreferredPosition(); + } + + if (!isResizeable) + { + // On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as + // BOTTOM_RIGHT and CANVAS_TOP_RIGHT is same as TOP_RIGHT. + // Just use BOTTOM_RIGHT and TOP_RIGHT to prevent overlays from + // drawing over each other. + switch (overlayPosition) + { + case CANVAS_TOP_RIGHT: + overlayPosition = OverlayPosition.TOP_RIGHT; + break; + case ABOVE_CHATBOX_RIGHT: + overlayPosition = OverlayPosition.BOTTOM_RIGHT; + break; + } + } + + return overlayPosition; + } + private boolean shouldInvalidateBounds() { final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX); From 68e8b0df265d4212d4c416222220a91334a627b1 Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Tue, 31 Mar 2020 12:16:47 -0700 Subject: [PATCH 17/35] swingutil: Set button tooltip text in addModalTooltip Prior to this commit, addModalTooltip only added a button listener to update the tooltip when its state changed. This, however, did not set the initial tooltip and leaves modal tooltip buttons in the client lacking a tooltip until they are toggled. This commit sets the initial tooltip state using the same toggle check as is used in the listener. --- .../src/main/java/net/runelite/client/util/SwingUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java index 5eb7cef4af..2b5b5caf70 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java @@ -297,6 +297,7 @@ public class SwingUtil public static void addModalTooltip(AbstractButton button, String on, String off) { + button.setToolTipText(button.isSelected() ? on : off); button.addItemListener(l -> button.setToolTipText(button.isSelected() ? on : off)); } From ea71fcf4bfcd51f76630bc7066ce07a0402544bb Mon Sep 17 00:00:00 2001 From: Morgan Lewis Date: Tue, 31 Mar 2020 13:28:35 -0600 Subject: [PATCH 18/35] worldmap: Fix slayer ring teleport location Fix slayer tower location and add main surface icon for rellekka slayer cave. --- .../runelite/client/plugins/worldmap/TeleportLocationData.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java index dcd7ddbbe0..5a28519bc6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java @@ -98,8 +98,9 @@ enum TeleportLocationData GRAND_EXCHANGE(TeleportType.JEWELLERY, "Ring of Wealth" , "Grand Exchange", new WorldPoint(3162, 3480, 0), "ring_of_wealth_teleport_icon.png"), FALADOR_PARK(TeleportType.JEWELLERY, "Ring of Wealth" , "Falador Park", new WorldPoint(2995, 3375, 0), "ring_of_wealth_teleport_icon.png"), DONDAKAN(TeleportType.JEWELLERY, "Ring of Wealth" , "Dondakan", new WorldPoint(2831, 10165, 0), "ring_of_wealth_teleport_icon.png"), - SLAYER_TOWER(TeleportType.JEWELLERY, "Slayer Ring" , "Slayer Tower", new WorldPoint(3429, 3531, 0), "slayer_ring_teleport_icon.png"), + SLAYER_TOWER(TeleportType.JEWELLERY, "Slayer Ring" , "Slayer Tower", new WorldPoint(3423, 3536, 0), "slayer_ring_teleport_icon.png"), FREMENNIK_SLAYER_DUNGEON(TeleportType.JEWELLERY, "Slayer Ring" , "Fremennik Slayer Dungeon", new WorldPoint(2800, 9998, 0), "slayer_ring_teleport_icon.png"), + FREMENNIK_SLAYER_DUNGEON_OUTSIDE(TeleportType.JEWELLERY, "Slayer Ring" , "Fremennik Slayer Dungeon (inside)", new WorldPoint(2800, 3615, 0), "slayer_ring_teleport_icon.png"), TARNS_LAIR(TeleportType.JEWELLERY, "Slayer Ring" , "Tarn's Lair", new WorldPoint(3187, 4601, 0), "slayer_ring_teleport_icon.png"), STRONGHOLD_SLAYER_CAVE(TeleportType.JEWELLERY, "Slayer Ring" , "Stronghold Slayer Cave", new WorldPoint(2433, 3421, 0), "slayer_ring_teleport_icon.png"), DARK_BEASTS(TeleportType.JEWELLERY, "Slayer Ring" , "Dark Beasts", new WorldPoint(2028, 4638, 0), "slayer_ring_teleport_icon.png"), From 12c969cc0abd04c394962a412091ef165a99acd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20N=C3=B6nnig?= Date: Wed, 1 Apr 2020 01:11:40 +0200 Subject: [PATCH 19/35] prayer: Hide prayer flick indicator when minimap is hidden (#11138) --- .../net/runelite/client/plugins/prayer/PrayerFlickOverlay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickOverlay.java index 6a9bfbfd61..8853590724 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerFlickOverlay.java @@ -64,7 +64,7 @@ class PrayerFlickOverlay extends Overlay } Widget xpOrb = client.getWidget(WidgetInfo.MINIMAP_QUICK_PRAYER_ORB); - if (xpOrb == null) + if (xpOrb == null || xpOrb.isHidden()) { return null; } From 2d01dc21bdc9ea6cd367775756e83e8d53091d93 Mon Sep 17 00:00:00 2001 From: dekvall Date: Tue, 6 Aug 2019 02:11:43 +0200 Subject: [PATCH 20/35] prayer: display prayer time remaining in prayer orb --- .../net/runelite/api/widgets/WidgetID.java | 1 + .../net/runelite/api/widgets/WidgetInfo.java | 1 + .../client/plugins/prayer/PrayerConfig.java | 11 +++ .../plugins/prayer/PrayerDoseOverlay.java | 62 ++++------------- .../client/plugins/prayer/PrayerPlugin.java | 68 ++++++++++++++++++- 5 files changed, 95 insertions(+), 48 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index d957b3f8d5..d8d8a93f4d 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -324,6 +324,7 @@ public class WidgetID static final int HEALTH_ORB = 2; static final int PRAYER_ORB = 12; static final int QUICK_PRAYER_ORB = 14; // Has the "Quick-prayers" name + static final int PRAYER_ORB_TEXT = 15; static final int RUN_ORB = 20; static final int TOGGLE_RUN_ORB = 22; // Has the "Toggle run" name static final int RUN_ORB_TEXT = 23; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index ea559f8d37..754a93766d 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -165,6 +165,7 @@ public enum WidgetInfo MINIMAP_XP_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.XP_ORB), MINIMAP_PRAYER_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.PRAYER_ORB), MINIMAP_QUICK_PRAYER_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.QUICK_PRAYER_ORB), + MINIMAP_PRAYER_ORB_TEXT(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.PRAYER_ORB_TEXT), MINIMAP_RUN_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.RUN_ORB), MINIMAP_TOGGLE_RUN_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.TOGGLE_RUN_ORB), MINIMAP_RUN_ORB_TEXT(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.RUN_ORB_TEXT), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java index 9a22f48cc4..d2cad67fe5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java @@ -129,4 +129,15 @@ public interface PrayerConfig extends Config { return false; } + + @ConfigItem( + position = 9, + keyName = "replaceOrbText", + name = "Replace orb text with prayer time left", + description = "Show time remaining of current prayers in the prayer orb." + ) + default boolean replaceOrbText() + { + return false; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java index ab1d91fb16..dc18d47a98 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java @@ -37,7 +37,6 @@ import lombok.Setter; import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.Point; -import net.runelite.api.Prayer; import net.runelite.api.Skill; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -47,7 +46,6 @@ import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.tooltip.Tooltip; import net.runelite.client.ui.overlay.tooltip.TooltipManager; import net.runelite.client.util.ColorUtil; -import org.apache.commons.lang3.StringUtils; class PrayerDoseOverlay extends Overlay { @@ -57,13 +55,12 @@ class PrayerDoseOverlay extends Overlay private static final Color END_COLOR = new Color(0, 92, 92); private final Client client; + private final PrayerPlugin plugin; private final PrayerConfig config; private final TooltipManager tooltipManager; private Instant startOfLastTick = Instant.now(); private boolean trackTick = true; - @Setter(AccessLevel.PACKAGE) - private int prayerBonus; @Setter(AccessLevel.PACKAGE) private boolean hasPrayerRestore; @Setter(AccessLevel.PACKAGE) @@ -72,10 +69,11 @@ class PrayerDoseOverlay extends Overlay private boolean hasHolyWrench; @Inject - private PrayerDoseOverlay(final Client client, final TooltipManager tooltipManager, final PrayerConfig config) + private PrayerDoseOverlay(final Client client, final TooltipManager tooltipManager, final PrayerPlugin plugin, final PrayerConfig config) { this.client = client; this.tooltipManager = tooltipManager; + this.plugin = plugin; this.config = config; setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ABOVE_WIDGETS); @@ -114,11 +112,19 @@ class PrayerDoseOverlay extends Overlay if (config.showPrayerStatistics() && bounds.contains(mousePosition.getX(), mousePosition.getY())) { - final String tooltip = "Time Remaining: " + getEstimatedTimeRemaining() + - "
" + - "Prayer Bonus: " + prayerBonus; + final StringBuilder sb = new StringBuilder(); - tooltipManager.add(new Tooltip(tooltip)); + if (config.replaceOrbText()) + { + sb.append("Prayer points remaining: ").append(client.getBoostedSkillLevel(Skill.PRAYER)); + } + else + { + sb.append("Time Remaining: ").append(plugin.getEstimatedTimeRemaining(false)); + } + + sb.append("
").append("Prayer Bonus: ").append(plugin.getPrayerBonus()); + tooltipManager.add(new Tooltip(sb.toString())); } if (!config.showPrayerDoseIndicator() || !hasPrayerRestore) @@ -163,42 +169,4 @@ class PrayerDoseOverlay extends Overlay return new Dimension((int) bounds.getWidth(), (int) bounds.getHeight()); } - private double getPrayerDrainRate(Client client) - { - double drainRate = 0.0; - - for (Prayer prayer : Prayer.values()) - { - if (client.isPrayerActive(prayer)) - { - drainRate += prayer.getDrainRate(); - } - } - - return drainRate; - } - - private String getEstimatedTimeRemaining() - { - // Base data - final double drainRate = getPrayerDrainRate(client); - - if (drainRate == 0) - { - return "N/A"; - } - - final int currentPrayer = client.getBoostedSkillLevel(Skill.PRAYER); - - // Calculate how many seconds each prayer points last so the prayer bonus can be applied - final double secondsPerPoint = (60.0 / drainRate) * (1.0 + (prayerBonus / 30.0)); - - // Calculate the number of seconds left - final double secondsLeft = (currentPrayer * secondsPerPoint); - final int minutes = (int) Math.floor(secondsLeft / 60.0); - final int seconds = (int) Math.floor(secondsLeft - (minutes * 60.0)); - - // Return the text - return Integer.toString(minutes) + ":" + StringUtils.leftPad(Integer.toString(seconds), 2, "0"); - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java index eb5334177d..9622f7d809 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java @@ -28,6 +28,8 @@ package net.runelite.client.plugins.prayer; import com.google.inject.Provides; import java.time.Duration; import java.time.Instant; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; @@ -38,8 +40,11 @@ import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.Prayer; import net.runelite.client.events.ConfigChanged; +import net.runelite.api.Skill; import net.runelite.api.events.GameTick; import net.runelite.api.events.ItemContainerChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; @@ -64,6 +69,9 @@ public class PrayerPlugin extends Plugin @Getter(AccessLevel.PACKAGE) private boolean prayersActive = false; + @Getter(AccessLevel.PACKAGE) + private int prayerBonus; + @Inject private Client client; @@ -150,7 +158,7 @@ public class PrayerPlugin extends Plugin if (equipment != null) { - doseOverlay.setPrayerBonus(checkContainerForPrayer(equipment.getItems())); + prayerBonus = checkContainerForPrayer(equipment.getItems()); } } @@ -176,6 +184,11 @@ public class PrayerPlugin extends Plugin barOverlay.onTick(); } + if (config.replaceOrbText() && isAnyPrayerActive()) + { + setPrayerOrbText(getEstimatedTimeRemaining(true)); + } + if (!config.prayerIndicator()) { return; @@ -304,4 +317,57 @@ public class PrayerPlugin extends Plugin infoBoxManager.removeIf(entry -> entry instanceof PrayerCounter && ((PrayerCounter) entry).getPrayerType().isOverhead()); } + + private void setPrayerOrbText(String text) + { + Widget prayerOrbText = client.getWidget(WidgetInfo.MINIMAP_PRAYER_ORB_TEXT); + if (prayerOrbText != null) + { + prayerOrbText.setText(text); + } + } + + private static double getPrayerDrainRate(Client client) + { + double drainRate = 0.0; + + for (Prayer prayer : Prayer.values()) + { + if (client.isPrayerActive(prayer)) + { + drainRate += prayer.getDrainRate(); + } + } + + return drainRate; + } + + String getEstimatedTimeRemaining(boolean formatForOrb) + { + final double drainRate = getPrayerDrainRate(client); + + if (drainRate == 0) + { + return "N/A"; + } + + final int currentPrayer = client.getBoostedSkillLevel(Skill.PRAYER); + + // Calculate how many seconds each prayer points last so the prayer bonus can be applied + final double secondsPerPoint = (60.0 / drainRate) * (1.0 + (prayerBonus / 30.0)); + + // Calculate the number of seconds left + final double secondsLeft = (currentPrayer * secondsPerPoint); + + LocalTime timeLeft = LocalTime.ofSecondOfDay((long) secondsLeft); + + if (formatForOrb && timeLeft.getMinute() > 9) + { + return timeLeft.format(DateTimeFormatter.ofPattern("m")) + "m"; + } + else + { + return timeLeft.format(DateTimeFormatter.ofPattern("m:ss")); + } + } } From 0faf994f5467b07df2fead0841d3eb6915e79864 Mon Sep 17 00:00:00 2001 From: TheStonedTurtle Date: Sat, 21 Mar 2020 22:32:46 -0700 Subject: [PATCH 21/35] nightmarezone: Fix area check to exclude KBD lair Fixes #3692 --- .../client/plugins/nightmarezone/NightmareZonePlugin.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java index 4862ea3723..d683ec78a4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java @@ -243,6 +243,12 @@ public class NightmareZonePlugin extends Plugin public boolean isInNightmareZone() { - return Arrays.equals(client.getMapRegions(), NMZ_MAP_REGION); + if (client.getLocalPlayer() == null) + { + return false; + } + + // NMZ and the KBD lair uses the same region ID but NMZ uses planes 1-3 and KBD uses plane 0 + return client.getLocalPlayer().getWorldLocation().getPlane() > 0 && Arrays.equals(client.getMapRegions(), NMZ_MAP_REGION); } } From 7744056766e09aee1157a2014eb5d5092155a898 Mon Sep 17 00:00:00 2001 From: TheStonedTurtle Date: Thu, 26 Mar 2020 21:07:08 -0700 Subject: [PATCH 22/35] discord: Fix NMZ area check to exclude KBD lair NMZ reuses the KBD region ID but is always above plane 0 --- .../runelite/client/plugins/discord/DiscordPlugin.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 513ce7bff7..0c17f75a26 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 @@ -381,7 +381,15 @@ public class DiscordPlugin extends Plugin return; } - final DiscordGameEventType discordGameEventType = DiscordGameEventType.fromRegion(playerRegionID); + DiscordGameEventType discordGameEventType = DiscordGameEventType.fromRegion(playerRegionID); + + // NMZ uses the same region ID as KBD. KBD is always on plane 0 and NMZ is always above plane 0 + // Since KBD requires going through the wilderness there is no EventType for it + if (DiscordGameEventType.MG_NIGHTMARE_ZONE == discordGameEventType + && client.getLocalPlayer().getWorldLocation().getPlane() == 0) + { + discordGameEventType = null; + } if (discordGameEventType == null) { From b8ad248fcb88ccde5fe8195a1487143db270f22f Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Wed, 25 Mar 2020 01:45:09 +0000 Subject: [PATCH 23/35] runenergy: update graceful recovery rate logic Updates the energy recovery rate calculation to reflect the changes made in the 9th January 2020 game update. Each individual piece of graceful now boosts your recovery rate by 3%, with an extra 1% for the top and legs. With the full set, an extra boost of 10% is added, totalling 30%. Previously, there was no boost for individual pieces, instead the full set was required for a flat boost of 30%. --- .../plugins/runenergy/RunEnergyPlugin.java | 69 ++++++++++++++----- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java index 4fb960b748..bf911c2f35 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java @@ -26,7 +26,10 @@ package net.runelite.client.plugins.runenergy; import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; +import java.util.Arrays; import javax.inject.Inject; +import lombok.Getter; +import lombok.RequiredArgsConstructor; import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.EquipmentInventorySlot; @@ -94,6 +97,27 @@ public class RunEnergyPlugin extends Plugin AGILITY_CAPE, AGILITY_CAPET, MAX_CAPE ); + @RequiredArgsConstructor + @Getter + private enum GracefulEquipmentSlot + { + HEAD(EquipmentInventorySlot.HEAD.getSlotIdx(), ALL_GRACEFUL_HOODS, 3), + BODY(EquipmentInventorySlot.BODY.getSlotIdx(), ALL_GRACEFUL_TOPS, 4), + LEGS(EquipmentInventorySlot.LEGS.getSlotIdx(), ALL_GRACEFUL_LEGS, 4), + GLOVES(EquipmentInventorySlot.GLOVES.getSlotIdx(), ALL_GRACEFUL_GLOVES, 3), + BOOTS(EquipmentInventorySlot.BOOTS.getSlotIdx(), ALL_GRACEFUL_BOOTS, 3), + CAPE(EquipmentInventorySlot.CAPE.getSlotIdx(), ALL_GRACEFUL_CAPES, 3); + + private final int index; + private final ImmutableSet items; + private final int boost; + + private static final int TOTAL_BOOSTS = Arrays.stream(values()).mapToInt(GracefulEquipmentSlot::getBoost).sum(); + } + + // Full set grants an extra 10% boost to recovery rate + private static final int GRACEFUL_FULL_SET_BOOST_BONUS = 10; + @Inject private Client client; @@ -199,30 +223,45 @@ public class RunEnergyPlugin extends Plugin } } - private boolean isLocalPlayerWearingFullGraceful() + private int getGracefulRecoveryBoost() { final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT); if (equipment == null) { - return false; + return 0; } final Item[] items = equipment.getItems(); - // Check that the local player is wearing enough items to be using full Graceful - // (the Graceful boots will have the highest slot index in the worn set). - if (items == null || items.length <= EquipmentInventorySlot.BOOTS.getSlotIdx()) + if (items == null) { - return false; + return 0; } - return (ALL_GRACEFUL_HOODS.contains(items[EquipmentInventorySlot.HEAD.getSlotIdx()].getId()) && - ALL_GRACEFUL_TOPS.contains(items[EquipmentInventorySlot.BODY.getSlotIdx()].getId()) && - ALL_GRACEFUL_LEGS.contains(items[EquipmentInventorySlot.LEGS.getSlotIdx()].getId()) && - ALL_GRACEFUL_GLOVES.contains(items[EquipmentInventorySlot.GLOVES.getSlotIdx()].getId()) && - ALL_GRACEFUL_BOOTS.contains(items[EquipmentInventorySlot.BOOTS.getSlotIdx()].getId()) && - ALL_GRACEFUL_CAPES.contains(items[EquipmentInventorySlot.CAPE.getSlotIdx()].getId())); + int boost = 0; + + for (final GracefulEquipmentSlot slot : GracefulEquipmentSlot.values()) + { + if (items.length <= slot.getIndex()) + { + continue; + } + + final Item wornItem = items[slot.getIndex()]; + + if (wornItem != null && slot.getItems().contains(wornItem.getId())) + { + boost += slot.getBoost(); + } + } + + if (boost == GracefulEquipmentSlot.TOTAL_BOOSTS) + { + boost += GRACEFUL_FULL_SET_BOOST_BONUS; + } + + return boost; } int getEstimatedRecoverTimeRemaining() @@ -234,11 +273,7 @@ public class RunEnergyPlugin extends Plugin // Calculate the amount of energy recovered every second double recoverRate = (48 + client.getBoostedSkillLevel(Skill.AGILITY)) / 360.0; - - if (isLocalPlayerWearingFullGraceful()) - { - recoverRate *= 1.3; // 30% recover rate increase from Graceful set effect - } + recoverRate *= 1.0 + getGracefulRecoveryBoost() / 100.0; // Calculate the number of seconds left final double secondsLeft = (100 - client.getEnergy()) / recoverRate; From 0bf469eaf172bae99f460b2f01001d3edc1ce89d Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 1 Apr 2020 20:35:32 -0700 Subject: [PATCH 24/35] slayer plugin: add Jormungand's Prison 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 1667c71188..bb4fbcb7cf 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 @@ -198,6 +198,7 @@ enum Task "Fremennik Slayer Dungeon", "God Wars Dungeon", "Iorwerth Dungeon", + "Jormungand's Prison", "Kalphite Lair", "Karuulm Slayer Dungeon", "Keldagrim", From 5f585987f5887ac82311835e2480960842e14402 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Thu, 2 Apr 2020 00:07:17 -0600 Subject: [PATCH 25/35] Notifier: Reuse Clip instances This was leaking instances of Clip, which on linux/alsa+alsa-pulseaudio keeps a connection to pulseaudio open forever, for each notification which will eventually lock/crash the pulse daemon. If we just made it close the clip, it would become difficult to change the volume because the volume interface would go away as soon as the clip has stopped playing, so instead we keep the clip around after it has been loaded if the mtime of the file hasn't changed. --- .../java/net/runelite/client/Notifier.java | 92 +++++++++++++------ 1 file changed, 62 insertions(+), 30 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 5a61dd592a..cdb1d63cfe 100644 --- a/runelite-client/src/main/java/net/runelite/client/Notifier.java +++ b/runelite-client/src/main/java/net/runelite/client/Notifier.java @@ -104,6 +104,10 @@ public class Notifier private static final String appName = RuneLiteProperties.getTitle(); + private static final File NOTIFICATION_FILE = new File(RuneLite.RUNELITE_DIR, "notification.wav"); + private static final long CLIP_MTIME_UNLOADED = -2; + private static final long CLIP_MTIME_BUILTIN = -1; + private final Client client; private final RuneLiteConfig runeLiteConfig; private final ClientUI clientUI; @@ -114,6 +118,8 @@ public class Notifier private final boolean terminalNotifierAvailable; private Instant flashStart; private long mouseLastPressedMillis; + private long lastClipMTime = CLIP_MTIME_UNLOADED; + private Clip clip = null; @Inject private Notifier( @@ -408,47 +414,73 @@ public class Notifier } } - private void playCustomSound() + private synchronized void playCustomSound() { - Clip clip = null; - - // Try to load the user sound from ~/.runelite/notification.wav - File file = new File(RuneLite.RUNELITE_DIR, "notification.wav"); - if (file.exists()) + long currentMTime = NOTIFICATION_FILE.exists() ? NOTIFICATION_FILE.lastModified() : CLIP_MTIME_BUILTIN; + if (clip == null || currentMTime != lastClipMTime || !clip.isOpen()) { + if (clip != null) + { + clip.close(); + } + try - { - InputStream fileStream = new BufferedInputStream(new FileInputStream(file)); - try (AudioInputStream sound = AudioSystem.getAudioInputStream(fileStream)) - { - clip = AudioSystem.getClip(); - clip.open(sound); - } - } - catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) - { - clip = null; - log.warn("Unable to play notification sound", e); - } - } - - if (clip == null) - { - // Otherwise load from the classpath - InputStream fileStream = new BufferedInputStream(Notifier.class.getResourceAsStream("notification.wav")); - try (AudioInputStream sound = AudioSystem.getAudioInputStream(fileStream)) { clip = AudioSystem.getClip(); - clip.open(sound); } - catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) + catch (LineUnavailableException e) { - log.warn("Unable to play builtin notification sound", e); + lastClipMTime = CLIP_MTIME_UNLOADED; + log.warn("Unable to play notification", e); + Toolkit.getDefaultToolkit().beep(); + return; + } + lastClipMTime = currentMTime; + + if (!tryLoadNotification()) + { Toolkit.getDefaultToolkit().beep(); return; } } - clip.start(); + + // Using loop instead of start + setFramePosition prevents a the clip + // from not being played sometimes, presumably a race condition in the + // underlying line driver + clip.loop(1); + } + + private boolean tryLoadNotification() + { + if (NOTIFICATION_FILE.exists()) + { + try + { + InputStream fileStream = new BufferedInputStream(new FileInputStream(NOTIFICATION_FILE)); + try (AudioInputStream sound = AudioSystem.getAudioInputStream(fileStream)) + { + clip.open(sound); + return true; + } + } + catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) + { + log.warn("Unable to load notification sound", e); + } + } + + // Otherwise load from the classpath + InputStream fileStream = new BufferedInputStream(Notifier.class.getResourceAsStream("notification.wav")); + try (AudioInputStream sound = AudioSystem.getAudioInputStream(fileStream)) + { + clip.open(sound); + return true; + } + catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) + { + log.warn("Unable to load builtin notification sound", e); + } + return false; } } From b81caff06f7d623fbfbd878abf1add677fbe84d2 Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 2 Apr 2020 18:27:48 +0200 Subject: [PATCH 26/35] ge plugin: add fuzzy search option --- .../main/java/net/runelite/api/ScriptID.java | 6 + .../net/runelite/api/widgets/WidgetID.java | 1 + .../net/runelite/api/widgets/WidgetInfo.java | 1 + .../grandexchange/GrandExchangeConfig.java | 22 +++ .../grandexchange/GrandExchangePlugin.java | 187 +++++++++++++++++- .../GrandExchangeSearchMode.java | 34 ++++ 6 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchMode.java diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java index 494489fadc..1b6e93e33c 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java @@ -222,6 +222,12 @@ public final class ScriptID @ScriptArguments(integer = 15) public static final int GE_OFFERS_SETUP_BUILD = 779; + /** + * Builds the grand exchange item search widget + */ + @ScriptArguments(integer = 2) + public static final int GE_ITEM_SEARCH = 752; + /** * Builds the quest list inside the quest tab that shows each quest's progress */ diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index d8d8a93f4d..19a5945f67 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -466,6 +466,7 @@ public class WidgetID static final int CONTAINER = 40; static final int TITLE = 44; static final int FULL_INPUT = 45; + static final int GE_SEARCH_RESULTS = 53; static final int MESSAGES = 55; static final int TRANSPARENT_BACKGROUND_LINES = 56; static final int INPUT = 57; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 754a93766d..81eb08dd49 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -351,6 +351,7 @@ public enum WidgetInfo CHATBOX_BUTTONS(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.BUTTONS), CHATBOX_TITLE(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TITLE), CHATBOX_FULL_INPUT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.FULL_INPUT), + CHATBOX_GE_SEARCH_RESULTS(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.GE_SEARCH_RESULTS), CHATBOX_CONTAINER(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CONTAINER), CHATBOX_REPORT_TEXT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.REPORT_TEXT), CHATBOX_INPUT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.INPUT), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java index b1eb1e212c..272c1a7254 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java @@ -96,4 +96,26 @@ public interface GrandExchangeConfig extends Config { return false; } + + @ConfigItem( + position = 7, + keyName = "highlightSearchMatch", + name = "Highlight Search Match", + description = "Highlights the search match with an underline" + ) + default boolean highlightSearchMatch() + { + return true; + } + + @ConfigItem( + position = 8, + keyName = "geSearchMode", + name = "Search Mode", + description = "The search mode to use for the GE" + ) + default GrandExchangeSearchMode geSearchMode() + { + return GrandExchangeSearchMode.DEFAULT; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index 8dbe31bda5..f3629054bc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -2,6 +2,7 @@ * Copyright (c) 2019, Adam * Copyright (c) 2017, Robbie * Copyright (c) 2018, SomeoneWithAnInternetConnection + * Copyright (c) 2020, Dennis * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,13 +28,23 @@ package net.runelite.client.plugins.grandexchange; +import com.google.common.primitives.Shorts; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.inject.Provides; +import java.awt.Color; import java.awt.image.BufferedImage; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import javax.inject.Inject; import javax.swing.SwingUtilities; import lombok.AccessLevel; @@ -49,10 +60,12 @@ import net.runelite.api.ItemComposition; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; import net.runelite.api.ScriptID; +import net.runelite.api.VarClientStr; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GrandExchangeOfferChanged; +import net.runelite.api.events.GrandExchangeSearched; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.ScriptPostFired; @@ -75,6 +88,7 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ImageUtil; import net.runelite.client.util.QuantityFormatter; import net.runelite.client.util.Text; @@ -83,6 +97,7 @@ import net.runelite.http.api.ge.GrandExchangeTrade; import net.runelite.http.api.item.ItemStats; import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; import net.runelite.http.api.osbuddy.OSBGrandExchangeResult; +import org.apache.commons.text.similarity.FuzzyScore; @PluginDescriptor( name = "Grand Exchange", @@ -105,6 +120,12 @@ public class GrandExchangePlugin extends Plugin static final String SEARCH_GRAND_EXCHANGE = "Search Grand Exchange"; + private static final int MAX_RESULT_COUNT = 250; + + private static final FuzzyScore FUZZY = new FuzzyScore(Locale.ENGLISH); + + private static final Color FUZZY_HIGHLIGHT_COLOR = new Color(0x800000); + @Getter(AccessLevel.PACKAGE) private NavigationButton button; @@ -156,6 +177,48 @@ public class GrandExchangePlugin extends Plugin private GrandExchangeClient grandExchangeClient; + private boolean wasFuzzySearch; + + /** + * Logic from {@link org.apache.commons.text.similarity.FuzzyScore} + */ + private static List findFuzzyIndices(String term, String query) + { + List indices = new ArrayList<>(); + + // fuzzy logic is case insensitive. We normalize the Strings to lower + // case right from the start. Turning characters to lower case + // via Character.toLowerCase(char) is unfortunately insufficient + // as it does not accept a locale. + final String termLowerCase = term.toLowerCase(); + final String queryLowerCase = query.toLowerCase(); + + // the position in the term which will be scanned next for potential + // query character matches + int termIndex = 0; + + for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) + { + final char queryChar = queryLowerCase.charAt(queryIndex); + + for (; termIndex < termLowerCase.length(); termIndex++) + { + final char termChar = termLowerCase.charAt(termIndex); + + if (queryChar == termChar) + { + indices.add(termIndex); + + // we can leave the nested loop. Every character in the + // query can match at most one character in the term. + break; + } + } + } + + return indices; + } + private SavedOffer getOffer(int slot) { String offer = configManager.getConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot)); @@ -441,11 +504,131 @@ public class GrandExchangePlugin extends Plugin public void onScriptPostFired(ScriptPostFired event) { // GE offers setup init - if (event.getScriptId() != ScriptID.GE_OFFERS_SETUP_BUILD) + if (event.getScriptId() == ScriptID.GE_OFFERS_SETUP_BUILD) + { + rebuildGeText(); + } + else if (event.getScriptId() == ScriptID.GE_ITEM_SEARCH && config.highlightSearchMatch()) + { + highlightSearchMatches(); + } + } + + private void highlightSearchMatches() + { + if (!wasFuzzySearch) { return; } - rebuildGeText(); + String input = client.getVar(VarClientStr.INPUT_TEXT); + + String underlineTag = ""; + + Widget results = client.getWidget(WidgetInfo.CHATBOX_GE_SEARCH_RESULTS); + Widget[] children = results.getDynamicChildren(); + int resultCount = children.length / 3; + + for (int i = 0; i < resultCount; i++) + { + Widget itemNameWidget = children[i * 3 + 1]; + String itemName = itemNameWidget.getText(); + + List indices; + String otherName = itemName.replace('-', ' '); + if (!itemName.contains("-") || FUZZY.fuzzyScore(itemName, input) >= FUZZY.fuzzyScore(otherName, input)) + { + indices = findFuzzyIndices(itemName, input); + } + else + { + indices = findFuzzyIndices(otherName, input); + } + Collections.reverse(indices); + + StringBuilder newItemName = new StringBuilder(itemName); + for (int index : indices) + { + if (wasFuzzySearch && (itemName.charAt(index) == ' ' || itemName.charAt(index) == '-')) + { + continue; + } + newItemName.insert(index + 1, ""); + newItemName.insert(index, underlineTag); + } + + itemNameWidget.setText(newItemName.toString()); + } + } + + @Subscribe + public void onGrandExchangeSearched(GrandExchangeSearched event) + { + wasFuzzySearch = false; + + GrandExchangeSearchMode searchMode = config.geSearchMode(); + final String input = client.getVar(VarClientStr.INPUT_TEXT); + if (searchMode == GrandExchangeSearchMode.DEFAULT || input.isEmpty()) + { + return; + } + + event.consume(); + + client.setGeSearchResultIndex(0); + + int resultCount = 0; + if (searchMode == GrandExchangeSearchMode.FUZZY_FALLBACK) + { + List ids = IntStream.range(0, client.getItemCount()) + .mapToObj(itemManager::getItemComposition) + .filter(item -> item.isTradeable() && item.getNote() == -1 + && item.getName().toLowerCase().contains(input)) + .limit(MAX_RESULT_COUNT + 1) + .sorted(Comparator.comparing(ItemComposition::getName)) + .map(ItemComposition::getId) + .collect(Collectors.toList()); + if (ids.size() > MAX_RESULT_COUNT) + { + client.setGeSearchResultCount(-1); + client.setGeSearchResultIds(null); + } + else + { + resultCount = ids.size(); + client.setGeSearchResultCount(resultCount); + client.setGeSearchResultIds(Shorts.toArray(ids)); + } + } + + if (resultCount == 0) + { + // We do this so that for example the items "Anti-venom ..." are still at the top + // when searching "anti venom" + ToIntFunction getScore = item -> + { + int score = FUZZY.fuzzyScore(item.getName(), input); + if (item.getName().contains("-")) + { + return Math.max(FUZZY.fuzzyScore(item.getName().replace('-', ' '), input), score); + } + return score; + }; + + List ids = IntStream.range(0, client.getItemCount()) + .mapToObj(itemManager::getItemComposition) + .filter(item -> item.isTradeable() && item.getNote() == -1) + .filter(item -> getScore.applyAsInt(item) > 0) + .sorted(Comparator.comparingInt(getScore).reversed() + .thenComparing(ItemComposition::getName)) + .limit(MAX_RESULT_COUNT) + .map(ItemComposition::getId) + .collect(Collectors.toList()); + + client.setGeSearchResultCount(ids.size()); + client.setGeSearchResultIds(Shorts.toArray(ids)); + + wasFuzzySearch = true; + } } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchMode.java new file mode 100644 index 0000000000..6c09e4ddcf --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchMode.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Dennis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.grandexchange; + +public enum GrandExchangeSearchMode +{ + DEFAULT, + + FUZZY_FALLBACK, + + FUZZY_ONLY +} \ No newline at end of file From 85c5cf9a19c62a0208b5e418beebf8e2f7bf7cd3 Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 2 Apr 2020 17:26:21 +0000 Subject: [PATCH 27/35] music plugin: add option to mute prayer sounds --- .../java/net/runelite/api/SoundEffectID.java | 28 ++++++++++++- .../client/plugins/music/MusicConfig.java | 11 +++++ .../client/plugins/music/MusicPlugin.java | 41 +++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/SoundEffectID.java b/runelite-api/src/main/java/net/runelite/api/SoundEffectID.java index 6e794bab9b..6ccfd782e0 100644 --- a/runelite-api/src/main/java/net/runelite/api/SoundEffectID.java +++ b/runelite-api/src/main/java/net/runelite/api/SoundEffectID.java @@ -62,7 +62,33 @@ public final class SoundEffectID public final static int ZERO_DAMAGE_SPLAT = 511; public final static int TAKE_DAMAGE_SPLAT = 510; public final static int ATTACK_HIT = 2498; - public final static int PRAYER_ACTIVATE_VROOM = 2690; + + public final static int PRAYER_ACTIVATE_THICK_SKIN = 2690; + public final static int PRAYER_ACTIVATE_BURST_OF_STRENGTH = 2688; + public final static int PRAYER_ACTIVATE_CLARITY_OF_THOUGHT = 2664; + public final static int PRAYER_ACTIVATE_SHARP_EYE_RIGOUR = 2685; + public final static int PRAYER_ACTIVATE_MYSTIC_WILL_AUGURY = 2670; + public final static int PRAYER_ACTIVATE_ROCK_SKIN = 2684; + public final static int PRAYER_ACTIVATE_SUPERHUMAN_STRENGTH = 2689; + public final static int PRAYER_ACTIVATE_IMPROVED_REFLEXES = 2662; + public final static int PRAYER_ACTIVATE_RAPID_RESTORE_PRESERVE = 2679; + public final static int PRAYER_ACTIVATE_RAPID_HEAL = 2678; + public final static int PRAYER_ACTIVATE_PROTECT_ITEM = 1982; + public final static int PRAYER_ACTIVATE_HAWK_EYE = 2666; + public final static int PRAYER_ACTIVATE_MYSTIC_LORE = 2668; + public final static int PRAYER_ACTIVATE_STEEL_SKIN = 2687; + public final static int PRAYER_ACTIVATE_ULTIMATE_STRENGTH = 2691; + public final static int PRAYER_ACTIVATE_INCREDIBLE_REFLEXES = 2667; + public final static int PRAYER_ACTIVATE_PROTECT_FROM_MAGIC = 2675; + public final static int PRAYER_ACTIVATE_PROTECT_FROM_MISSILES = 2677; + public final static int PRAYER_ACTIVATE_PROTECT_FROM_MELEE = 2676; + public final static int PRAYER_ACTIVATE_EAGLE_EYE = 2665; + public final static int PRAYER_ACTIVATE_MYSTIC_MIGHT = 2669; + public final static int PRAYER_ACTIVATE_RETRIBUTION = 2682; + public final static int PRAYER_ACTIVATE_REDEMPTION = 2680; + public final static int PRAYER_ACTIVATE_SMITE = 2686; + public final static int PRAYER_ACTIVATE_CHIVALRY = 3826; + public final static int PRAYER_ACTIVATE_PIETY = 3825; public final static int PRAYER_DEACTIVE_VWOOP = 2663; public final static int PRAYER_DEPLETE_TWINKLE = 2672; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java index 16eea65c9f..594a1c7380 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java @@ -75,6 +75,17 @@ public interface MusicConfig extends Config return false; } + @ConfigItem( + keyName = "mutePrayerSounds", + name = "Mute prayer sounds", + description = "Mute prayer activation and deactivation sounds", + position = 4 + ) + default boolean mutePrayerSounds() + { + return false; + } + @ConfigItem( keyName = "musicVolume", name = "", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java index f6e78ef4b5..1bc8d0fa2d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java @@ -50,6 +50,7 @@ import net.runelite.api.SpriteID; import net.runelite.api.VarClientInt; import net.runelite.api.VarPlayer; import net.runelite.api.events.AreaSoundEffectPlayed; +import net.runelite.api.events.SoundEffectPlayed; import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.ScriptCallbackEvent; @@ -82,6 +83,36 @@ public class MusicPlugin extends Plugin SoundEffectID.TELEPORT_VWOOP ); + private static final Set PRAYER_SOUNDS = ImmutableSet.of( + SoundEffectID.PRAYER_ACTIVATE_THICK_SKIN, + SoundEffectID.PRAYER_ACTIVATE_BURST_OF_STRENGTH, + SoundEffectID.PRAYER_ACTIVATE_CLARITY_OF_THOUGHT, + SoundEffectID.PRAYER_ACTIVATE_SHARP_EYE_RIGOUR, + SoundEffectID.PRAYER_ACTIVATE_MYSTIC_WILL_AUGURY, + SoundEffectID.PRAYER_ACTIVATE_ROCK_SKIN, + SoundEffectID.PRAYER_ACTIVATE_SUPERHUMAN_STRENGTH, + SoundEffectID.PRAYER_ACTIVATE_IMPROVED_REFLEXES, + SoundEffectID.PRAYER_ACTIVATE_RAPID_RESTORE_PRESERVE, + SoundEffectID.PRAYER_ACTIVATE_RAPID_HEAL, + SoundEffectID.PRAYER_ACTIVATE_PROTECT_ITEM, + SoundEffectID.PRAYER_ACTIVATE_HAWK_EYE, + SoundEffectID.PRAYER_ACTIVATE_MYSTIC_LORE, + SoundEffectID.PRAYER_ACTIVATE_STEEL_SKIN, + SoundEffectID.PRAYER_ACTIVATE_ULTIMATE_STRENGTH, + SoundEffectID.PRAYER_ACTIVATE_INCREDIBLE_REFLEXES, + SoundEffectID.PRAYER_ACTIVATE_PROTECT_FROM_MAGIC, + SoundEffectID.PRAYER_ACTIVATE_PROTECT_FROM_MISSILES, + SoundEffectID.PRAYER_ACTIVATE_PROTECT_FROM_MELEE, + SoundEffectID.PRAYER_ACTIVATE_EAGLE_EYE, + SoundEffectID.PRAYER_ACTIVATE_MYSTIC_MIGHT, + SoundEffectID.PRAYER_ACTIVATE_RETRIBUTION, + SoundEffectID.PRAYER_ACTIVATE_REDEMPTION, + SoundEffectID.PRAYER_ACTIVATE_SMITE, + SoundEffectID.PRAYER_ACTIVATE_CHIVALRY, + SoundEffectID.PRAYER_ACTIVATE_PIETY, + SoundEffectID.PRAYER_DEACTIVE_VWOOP + ); + @Inject private Client client; @@ -590,4 +621,14 @@ public class MusicPlugin extends Plugin areaSoundEffectPlayed.consume(); } } + + @Subscribe + public void onSoundEffectPlayed(SoundEffectPlayed soundEffectPlayed) + { + if (musicConfig.mutePrayerSounds() + && PRAYER_SOUNDS.contains(soundEffectPlayed.getSoundId())) + { + soundEffectPlayed.consume(); + } + } } From b85675f6240acee68877a0629fac9329a9937e95 Mon Sep 17 00:00:00 2001 From: Lotto Date: Thu, 19 Mar 2020 00:12:28 +0100 Subject: [PATCH 28/35] api: remove Follow and Trade menu actions They are just the third and fourth player options but deprioritized by having 2000 added to them. --- runelite-api/src/main/java/net/runelite/api/MenuAction.java | 3 --- .../plugins/playerindicators/PlayerIndicatorsPlugin.java | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/MenuAction.java b/runelite-api/src/main/java/net/runelite/api/MenuAction.java index 450989d9c3..44bf09aa53 100644 --- a/runelite-api/src/main/java/net/runelite/api/MenuAction.java +++ b/runelite-api/src/main/java/net/runelite/api/MenuAction.java @@ -273,9 +273,6 @@ public enum MenuAction */ RUNELITE_OVERLAY_CONFIG(1502), - FOLLOW(2046), - TRADE(2047), - /** * Menu action triggered when the id is not defined in this class. */ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index e545f92dff..973e2dfbfa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -103,8 +103,8 @@ public class PlayerIndicatorsPlugin extends Plugin } int identifier = menuEntryAdded.getIdentifier(); - if (type == FOLLOW.getId() || type == TRADE.getId() - || type == SPELL_CAST_ON_PLAYER.getId() || type == ITEM_USE_ON_PLAYER.getId() + if (type == SPELL_CAST_ON_PLAYER.getId() + || type == ITEM_USE_ON_PLAYER.getId() || type == PLAYER_FIRST_OPTION.getId() || type == PLAYER_SECOND_OPTION.getId() || type == PLAYER_THIRD_OPTION.getId() From e7171ee3867c25478b50ce3cda5bcf9d4f090ce9 Mon Sep 17 00:00:00 2001 From: Lotto Date: Sun, 1 Mar 2020 21:35:37 +0100 Subject: [PATCH 29/35] player-indicators: break out decorating code into own methods --- .../PlayerIndicatorsPlugin.java | 123 +++++++++++------- 1 file changed, 78 insertions(+), 45 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index 973e2dfbfa..d0b3899f43 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.playerindicators; import com.google.inject.Provides; import java.awt.Color; import javax.inject.Inject; +import lombok.Value; import net.runelite.api.ClanMemberRank; import static net.runelite.api.ClanMemberRank.UNRANKED; import net.runelite.api.Client; @@ -115,7 +116,6 @@ public class PlayerIndicatorsPlugin extends Plugin || type == PLAYER_EIGTH_OPTION.getId() || type == RUNELITE.getId()) { - final Player localPlayer = client.getLocalPlayer(); Player[] players = client.getCachedPlayers(); Player player = null; @@ -129,57 +129,90 @@ public class PlayerIndicatorsPlugin extends Plugin return; } - int image = -1; - Color color = null; + Decorations decorations = getDecorations(player); - if (config.highlightFriends() && player.isFriend()) + if (decorations == null) { - color = config.getFriendColor(); - } - else if (config.drawClanMemberNames() && player.isClanMember()) - { - color = config.getClanMemberColor(); - - ClanMemberRank rank = clanManager.getRank(player.getName()); - if (rank != UNRANKED) - { - image = clanManager.getIconNumber(rank); - } - } - else if (config.highlightTeamMembers() && player.getTeam() > 0 && localPlayer.getTeam() == player.getTeam()) - { - color = config.getTeamMemberColor(); - } - else if (config.highlightNonClanMembers() && !player.isClanMember()) - { - color = config.getNonClanMemberColor(); + return; } - if (image != -1 || color != null) - { - MenuEntry[] menuEntries = client.getMenuEntries(); - MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; + MenuEntry[] menuEntries = client.getMenuEntries(); + MenuEntry entry = menuEntries[menuEntries.length - 1]; - if (color != null && config.colorPlayerMenu()) - { - // strip out existing '); - if (idx != -1) - { - target = target.substring(idx + 1); - } + String oldTarget = entry.getTarget(); + String newTarget = decorateTarget(oldTarget, decorations); - lastEntry.setTarget(ColorUtil.prependColorTag(target, color)); - } + entry.setTarget(newTarget); - if (image != -1 && config.showClanRanks()) - { - lastEntry.setTarget("" + lastEntry.getTarget()); - } - - client.setMenuEntries(menuEntries); - } + client.setMenuEntries(menuEntries); } } + + private Decorations getDecorations(Player player) + { + int image = -1; + Color color = null; + + if (config.highlightFriends() && player.isFriend()) + { + color = config.getFriendColor(); + } + else if (config.drawClanMemberNames() && player.isClanMember()) + { + color = config.getClanMemberColor(); + + ClanMemberRank rank = clanManager.getRank(player.getName()); + if (rank != UNRANKED) + { + image = clanManager.getIconNumber(rank); + } + } + else if (config.highlightTeamMembers() + && player.getTeam() > 0 && client.getLocalPlayer().getTeam() == player.getTeam()) + { + color = config.getTeamMemberColor(); + } + else if (config.highlightNonClanMembers() && !player.isClanMember()) + { + color = config.getNonClanMemberColor(); + } + + if (image == -1 && color == null) + { + return null; + } + + return new Decorations(image, color); + } + + private String decorateTarget(String oldTarget, Decorations decorations) + { + String newTarget = oldTarget; + + if (decorations.getColor() != null && config.colorPlayerMenu()) + { + // strip out existing '); + if (idx != -1) + { + newTarget = oldTarget.substring(idx + 1); + } + + newTarget = ColorUtil.prependColorTag(newTarget, decorations.getColor()); + } + + if (decorations.getImage() != -1 && config.showClanRanks()) + { + newTarget = "" + newTarget; + } + + return newTarget; + } + + @Value + private static class Decorations + { + private final int image; + private final Color color; + } } From d4f2753e0577142400abbfae6265970dd6ed39de Mon Sep 17 00:00:00 2001 From: Lotto Date: Thu, 19 Mar 2020 00:13:56 +0100 Subject: [PATCH 30/35] player-indicators: move menu logic to ClientTick --- .../PlayerIndicatorsPlugin.java | 97 ++++++++++--------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index d0b3899f43..f3ff69d7b0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -34,7 +34,7 @@ import net.runelite.api.Client; import static net.runelite.api.MenuAction.*; import net.runelite.api.MenuEntry; import net.runelite.api.Player; -import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.ClientTick; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ClanManager; @@ -94,56 +94,63 @@ public class PlayerIndicatorsPlugin extends Plugin } @Subscribe - public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) + public void onClientTick(ClientTick clientTick) { - int type = menuEntryAdded.getType(); + MenuEntry[] menuEntries = client.getMenuEntries(); + boolean modified = false; - if (type >= 2000) + for (MenuEntry entry : menuEntries) { - type -= 2000; + int type = entry.getType(); + + if (type >= MENU_ACTION_DEPRIORITIZE_OFFSET) + { + type -= MENU_ACTION_DEPRIORITIZE_OFFSET; + } + + int identifier = entry.getIdentifier(); + if (type == SPELL_CAST_ON_PLAYER.getId() + || type == ITEM_USE_ON_PLAYER.getId() + || type == PLAYER_FIRST_OPTION.getId() + || type == PLAYER_SECOND_OPTION.getId() + || type == PLAYER_THIRD_OPTION.getId() + || type == PLAYER_FOURTH_OPTION.getId() + || type == PLAYER_FIFTH_OPTION.getId() + || type == PLAYER_SIXTH_OPTION.getId() + || type == PLAYER_SEVENTH_OPTION.getId() + || type == PLAYER_EIGTH_OPTION.getId() + || type == RUNELITE.getId()) + { + Player[] players = client.getCachedPlayers(); + Player player = null; + + if (identifier >= 0 && identifier < players.length) + { + player = players[identifier]; + } + + if (player == null) + { + continue; + } + + Decorations decorations = getDecorations(player); + + if (decorations == null) + { + continue; + } + + String oldTarget = entry.getTarget(); + String newTarget = decorateTarget(oldTarget, decorations); + + entry.setTarget(newTarget); + modified = true; + } } - int identifier = menuEntryAdded.getIdentifier(); - if (type == SPELL_CAST_ON_PLAYER.getId() - || type == ITEM_USE_ON_PLAYER.getId() - || type == PLAYER_FIRST_OPTION.getId() - || type == PLAYER_SECOND_OPTION.getId() - || type == PLAYER_THIRD_OPTION.getId() - || type == PLAYER_FOURTH_OPTION.getId() - || type == PLAYER_FIFTH_OPTION.getId() - || type == PLAYER_SIXTH_OPTION.getId() - || type == PLAYER_SEVENTH_OPTION.getId() - || type == PLAYER_EIGTH_OPTION.getId() - || type == RUNELITE.getId()) + if (modified) { - Player[] players = client.getCachedPlayers(); - Player player = null; - - if (identifier >= 0 && identifier < players.length) - { - player = players[identifier]; - } - - if (player == null) - { - return; - } - - Decorations decorations = getDecorations(player); - - if (decorations == null) - { - return; - } - - MenuEntry[] menuEntries = client.getMenuEntries(); - MenuEntry entry = menuEntries[menuEntries.length - 1]; - - String oldTarget = entry.getTarget(); - String newTarget = decorateTarget(oldTarget, decorations); - - entry.setTarget(newTarget); - client.setMenuEntries(menuEntries); } } From bdb554e9a1bf42cdb18fc1fdb3edb13f7cb2b678 Mon Sep 17 00:00:00 2001 From: Lotto Date: Thu, 19 Mar 2020 00:14:31 +0100 Subject: [PATCH 31/35] player-indicators: highlight the 'Walk here' menu entry too --- .../playerindicators/PlayerIndicatorsPlugin.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index f3ff69d7b0..ffbccb4710 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -108,8 +108,8 @@ public class PlayerIndicatorsPlugin extends Plugin type -= MENU_ACTION_DEPRIORITIZE_OFFSET; } - int identifier = entry.getIdentifier(); - if (type == SPELL_CAST_ON_PLAYER.getId() + if (type == WALK.getId() + || type == SPELL_CAST_ON_PLAYER.getId() || type == ITEM_USE_ON_PLAYER.getId() || type == PLAYER_FIRST_OPTION.getId() || type == PLAYER_SECOND_OPTION.getId() @@ -124,6 +124,15 @@ public class PlayerIndicatorsPlugin extends Plugin Player[] players = client.getCachedPlayers(); Player player = null; + int identifier = entry.getIdentifier(); + + // 'Walk here' identifiers are offset by 1 because the default + // identifier for this option is 0, which is also a player index. + if (type == WALK.getId()) + { + identifier--; + } + if (identifier >= 0 && identifier < players.length) { player = players[identifier]; From 71488eaa2f5601b184cfe42a09f7d011520c8fb9 Mon Sep 17 00:00:00 2001 From: ypperlig Date: Tue, 31 Mar 2020 01:52:02 +0200 Subject: [PATCH 32/35] barrowsplugin: fix null pointer exception in region check 2020-03-31 01:01:39 [Client] WARN n.runelite.client.eventbus.EventBus - Uncaught exception in event subscriber java.lang.NullPointerException: null at net.runelite.client.plugins.barrows.BarrowsPlugin.isInCrypt(BarrowsPlugin.java:252) at net.runelite.client.plugins.barrows.BarrowsPlugin.onGameStateChanged(BarrowsPlugin.java:166) at net.runelite.client.eventbus.EventBus$Subscriber.invoke(EventBus.java:73) at net.runelite.client.eventbus.EventBus.post(EventBus.java:222) at net.runelite.client.callback.Hooks.post(Hooks.java:167) at client.oz(client.java:62117) at bn.ew(bn.java:1275) at client.zl(client.java:2476) at client.u(client.java:1114) at br.kq(br.java:336) at br.run(br.java:315) at java.lang.Thread.run(Thread.java:748) --- .../net/runelite/client/plugins/barrows/BarrowsPlugin.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java index f56bb123e6..149a7ac24e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java @@ -35,6 +35,7 @@ import net.runelite.api.GameState; import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; +import net.runelite.api.Player; import net.runelite.api.SpriteID; import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; @@ -249,6 +250,7 @@ public class BarrowsPlugin extends Plugin private boolean isInCrypt() { - return client.getLocalPlayer().getWorldLocation().getRegionID() == CRYPT_REGION_ID; + Player localPlayer = client.getLocalPlayer(); + return localPlayer != null && localPlayer.getWorldLocation().getRegionID() == CRYPT_REGION_ID; } } From babeed3293ed6542c9648371c1782f886a7ebdc4 Mon Sep 17 00:00:00 2001 From: Magic fTail Date: Fri, 3 Apr 2020 00:21:18 +0200 Subject: [PATCH 33/35] chatmessagemanager: use default timestamp if none is provided --- .../java/net/runelite/client/chat/ChatMessageManager.java | 6 +++++- 1 file changed, 5 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 34853d6f04..2642dbb162 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 @@ -585,7 +585,11 @@ public class ChatMessageManager // Update the message with RuneLite additions line.setRuneLiteFormatMessage(message.getRuneLiteFormattedMessage()); - line.setTimestamp(message.getTimestamp()); + + if (message.getTimestamp() != 0) + { + line.setTimestamp(message.getTimestamp()); + } update(line); } From 3bc66a060887f33291cf23524c6ebba8fc589b49 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 2 Apr 2020 18:29:33 -0400 Subject: [PATCH 34/35] questlist: Ensure filter has non-null state on startup Prior to this commit, the filter state was only set initially when logging in, causing NPEs and errant plugin behavior if toggled on when already logged in. --- .../net/runelite/client/plugins/questlist/QuestListPlugin.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java index 0ac160ac60..7243c24717 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java @@ -96,12 +96,14 @@ public class QuestListPlugin extends Plugin @Override protected void startUp() { + currentFilterState = QuestState.ALL; clientThread.invoke(this::addQuestButtons); } @Override protected void shutDown() { + currentFilterState = null; Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX); if (header != null) { From 0f66573fb21f02cd3046e24296b4085ebaa17c49 Mon Sep 17 00:00:00 2001 From: Crow <40111569+000000653@users.noreply.github.com> Date: Thu, 2 Apr 2020 21:32:26 -0500 Subject: [PATCH 35/35] NPC Agression Timer: fix typo in notification --- .../client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java index 1053ae0a5d..cf4830ebd7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java @@ -330,7 +330,7 @@ public class NpcAggroAreaPlugin extends Plugin { if (config.notifyExpire()) { - notifier.notify("NPC agression has expired!"); + notifier.notify("NPC aggression has expired!"); } notifyOnce = false;