From 98ca1bc0564cd64e78a09b0b1e18d8ffcfa15a88 Mon Sep 17 00:00:00 2001 From: William Maga Date: Sat, 19 Jan 2019 03:45:31 -0700 Subject: [PATCH 1/4] Add notification on NPC spawn --- .../plugins/npchighlight/MemorizedNpc.java | 9 +++ .../npchighlight/NpcIndicatorsConfig.java | 20 ++++++ .../npchighlight/NpcIndicatorsPlugin.java | 64 +++++++++++++++++-- .../plugins/npchighlight/NpcSceneOverlay.java | 23 ++----- .../npchighlight/NpcIndicatorsPluginTest.java | 6 ++ 5 files changed, 96 insertions(+), 26 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java index d9e1cad9a4..41ce059c42 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.npchighlight; +import java.time.Instant; import java.util.ArrayList; import java.util.List; import lombok.Getter; @@ -76,4 +77,12 @@ class MemorizedNpc this.npcSize = composition.getSize(); } } + + public double getSecondsFromRespawn(int tickCount, Instant lastTickUpdate) + { + final Instant now = Instant.now(); + final double baseTick = NpcIndicatorsPlugin.ESTIMATED_TICK_LENGTH * (diedOnTick + respawnTime - tickCount); + final double sinceLast = (now.toEpochMilli() - lastTickUpdate.toEpochMilli()) / 1000.0; + return Math.max(0.0, baseTick - sinceLast); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java index 3e6b298cbb..0eb7f333fb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java @@ -107,4 +107,24 @@ public interface NpcIndicatorsConfig extends Config { return false; } + + @ConfigItem( + position = 7, + keyName = "notifyOnRespawn", + name = "Notify on Respawn", + description = "Enable notification on respawn") + default boolean getNotifyOnRespawn() + { + return false; + } + + @ConfigItem( + position = 8, + keyName = "notifyOnRespawnDelay", + name = "Notification Delay", + description = "Notify when NPC is x ms from respawning") + default int getNotifyOnRespawnDelay() + { + return -1; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java index 63a130c70e..d2eb9a5ddf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java @@ -29,14 +29,11 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.inject.Provides; + +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.time.Instant; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; @@ -56,6 +53,7 @@ import net.runelite.api.events.GraphicsObjectCreated; import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; +import net.runelite.client.Notifier; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; @@ -76,6 +74,11 @@ public class NpcIndicatorsPlugin extends Plugin { private static final int MAX_ACTOR_VIEW_RANGE = 15; + public static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US); + + // Estimated time of a game tick in seconds + public static final double ESTIMATED_TICK_LENGTH = 0.6; + // Option added to NPC menu private static final String TAG = "Tag"; @@ -85,6 +88,11 @@ public class NpcIndicatorsPlugin extends Plugin // Regex for splitting the hidden items in the config. private static final Splitter COMMA_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults(); + static + { + ((DecimalFormat)TIME_LEFT_FORMATTER).applyPattern("#0.0"); + } + @Inject private Client client; @@ -112,12 +120,21 @@ public class NpcIndicatorsPlugin extends Plugin @Inject private ClientThread clientThread; + @Inject + private Notifier notifier; + /** * NPCs to highlight */ @Getter(AccessLevel.PACKAGE) private final Set highlightedNpcs = new HashSet<>(); + /** + * NPCs to notify when close to spawning + */ + @Getter(AccessLevel.PACKAGE) + private final Set pendingNotificationNpcs = new HashSet<>(); + /** * Dead NPCs that should be displayed with a respawn indicator if the config is on. */ @@ -203,6 +220,7 @@ public class NpcIndicatorsPlugin extends Plugin overlayManager.remove(npcSceneOverlay); overlayManager.remove(npcMinimapOverlay); deadNpcsToDisplay.clear(); + pendingNotificationNpcs.clear(); memorizedNpcs.clear(); spawnedNpcsThisTick.clear(); despawnedNpcsThisTick.clear(); @@ -220,6 +238,7 @@ public class NpcIndicatorsPlugin extends Plugin { highlightedNpcs.clear(); deadNpcsToDisplay.clear(); + pendingNotificationNpcs.clear(); memorizedNpcs.forEach((id, npc) -> npc.setDiedOnTick(-1)); lastPlayerLocation = null; skipNextSpawnCheck = true; @@ -319,6 +338,12 @@ public class NpcIndicatorsPlugin extends Plugin if (memorizedNpcs.containsKey(npc.getIndex())) { despawnedNpcsThisTick.add(npc); + MemorizedNpc mn = memorizedNpcs.get(npc.getIndex()); + + if (!mn.getPossibleRespawnLocations().isEmpty()) + { + pendingNotificationNpcs.add(mn); + } } highlightedNpcs.remove(npc); @@ -340,6 +365,7 @@ public class NpcIndicatorsPlugin extends Plugin { removeOldHighlightedRespawns(); validateSpawnedNpcs(); + checkNotifyNpcs(); lastTickUpdate = Instant.now(); lastPlayerLocation = client.getLocalPlayer().getWorldLocation(); } @@ -477,6 +503,29 @@ public class NpcIndicatorsPlugin extends Plugin } } + private void checkNotifyNpcs() + { + if (!config.getNotifyOnRespawn()) + { + return; + } + + final double notifyDelay = ((double)config.getNotifyOnRespawnDelay()) / 1000; + final int tickCount = client.getTickCount(); + final String notifyDelayStr = notifyDelay > 0 + ? " is less than " + TIME_LEFT_FORMATTER.format(notifyDelay) + " seconds from respawn" + : " respawned."; + + for (MemorizedNpc npc : pendingNotificationNpcs) + { + if (npc.getSecondsFromRespawn(tickCount, lastTickUpdate) <= notifyDelay) + { + pendingNotificationNpcs.remove(npc); + notifier.notify(npc.getNpcName() + notifyDelayStr); + } + } + } + private void validateSpawnedNpcs() { if (skipNextSpawnCheck) @@ -485,6 +534,7 @@ public class NpcIndicatorsPlugin extends Plugin } else { + for (NPC npc : despawnedNpcsThisTick) { if (!teleportGraphicsObjectSpawnedThisTick.isEmpty()) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index d4c8c356ec..ed3dd3170a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -30,10 +30,6 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.time.Instant; -import java.util.Locale; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.NPC; @@ -53,16 +49,6 @@ public class NpcSceneOverlay extends Overlay // a dark background private static final Color TEXT_COLOR = Color.WHITE; - // Estimated time of a game tick in seconds - private static final double ESTIMATED_TICK_LENGTH = 0.6; - - private static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US); - - static - { - ((DecimalFormat)TIME_LEFT_FORMATTER).applyPattern("#0.0"); - } - private final Client client; private final NpcIndicatorsConfig config; private final NpcIndicatorsPlugin plugin; @@ -121,11 +107,10 @@ public class NpcSceneOverlay extends Overlay OverlayUtil.renderPolygon(graphics, poly, color); } - final Instant now = Instant.now(); - final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * ESTIMATED_TICK_LENGTH; - final double sinceLast = (now.toEpochMilli() - plugin.getLastTickUpdate().toEpochMilli()) / 1000.0; - final double timeLeft = Math.max(0.0, baseTick - sinceLast); - final String timeLeftStr = TIME_LEFT_FORMATTER.format(timeLeft); + final String timeLeftStr = NpcIndicatorsPlugin.TIME_LEFT_FORMATTER.format(npc.getSecondsFromRespawn( + client.getTickCount(), + plugin.getLastTickUpdate() + )); final int textWidth = graphics.getFontMetrics().stringWidth(timeLeftStr); final int textHeight = graphics.getFontMetrics().getAscent(); diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java index 87f69cceb3..e1617e0b57 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java @@ -33,6 +33,8 @@ import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; import net.runelite.api.Client; import static org.junit.Assert.assertEquals; + +import net.runelite.client.Notifier; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,6 +57,10 @@ public class NpcIndicatorsPluginTest @Bind private NpcIndicatorsConfig npcIndicatorsConfig; + @Mock + @Bind + private Notifier notifier; + @Inject private NpcIndicatorsPlugin npcIndicatorsPlugin; From bee3299e1d9d54277f76f3043fee638e621b1273 Mon Sep 17 00:00:00 2001 From: William Maga Date: Sat, 19 Jan 2019 13:42:25 -0700 Subject: [PATCH 2/4] Refactor NpcIndicators functions --- .../plugins/npchighlight/MemorizedNpc.java | 9 ----- .../npchighlight/NpcIndicatorsPlugin.java | 36 +++++++++++++------ .../plugins/npchighlight/NpcSceneOverlay.java | 5 +-- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java index 41ce059c42..d9e1cad9a4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/MemorizedNpc.java @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.npchighlight; -import java.time.Instant; import java.util.ArrayList; import java.util.List; import lombok.Getter; @@ -77,12 +76,4 @@ class MemorizedNpc this.npcSize = composition.getSize(); } } - - public double getSecondsFromRespawn(int tickCount, Instant lastTickUpdate) - { - final Instant now = Instant.now(); - final double baseTick = NpcIndicatorsPlugin.ESTIMATED_TICK_LENGTH * (diedOnTick + respawnTime - tickCount); - final double sinceLast = (now.toEpochMilli() - lastTickUpdate.toEpochMilli()) / 1000.0; - return Math.max(0.0, baseTick - sinceLast); - } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java index d2eb9a5ddf..9f793204ad 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java @@ -74,10 +74,15 @@ public class NpcIndicatorsPlugin extends Plugin { private static final int MAX_ACTOR_VIEW_RANGE = 15; - public static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US); - // Estimated time of a game tick in seconds - public static final double ESTIMATED_TICK_LENGTH = 0.6; + private static final double ESTIMATED_TICK_LENGTH = 0.6; + + private static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.getDefault()); + + static + { + ((DecimalFormat)TIME_LEFT_FORMATTER).applyPattern("#0.0"); + } // Option added to NPC menu private static final String TAG = "Tag"; @@ -88,11 +93,6 @@ public class NpcIndicatorsPlugin extends Plugin // Regex for splitting the hidden items in the config. private static final Splitter COMMA_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults(); - static - { - ((DecimalFormat)TIME_LEFT_FORMATTER).applyPattern("#0.0"); - } - @Inject private Client client; @@ -417,6 +417,16 @@ public class NpcIndicatorsPlugin extends Plugin return new WorldPoint(currWP.getX() - dx, currWP.getY() - dy, currWP.getPlane()); } + public double getTimeLeftForNpc(MemorizedNpc npc) + { + final Instant now = Instant.now(); + final double baseTick = NpcIndicatorsPlugin.ESTIMATED_TICK_LENGTH * ( + npc.getDiedOnTick() + npc.getRespawnTime() - client.getTickCount() + ); + final double sinceLast = (now.toEpochMilli() - lastTickUpdate.toEpochMilli()) / 1000.0; + return Math.max(0.0, baseTick - sinceLast); + } + private void memorizeNpc(NPC npc) { final int npcIndex = npc.getIndex(); @@ -503,6 +513,11 @@ public class NpcIndicatorsPlugin extends Plugin } } + public String formatTime(double time) + { + return TIME_LEFT_FORMATTER.format(time); + } + private void checkNotifyNpcs() { if (!config.getNotifyOnRespawn()) @@ -511,14 +526,13 @@ public class NpcIndicatorsPlugin extends Plugin } final double notifyDelay = ((double)config.getNotifyOnRespawnDelay()) / 1000; - final int tickCount = client.getTickCount(); final String notifyDelayStr = notifyDelay > 0 - ? " is less than " + TIME_LEFT_FORMATTER.format(notifyDelay) + " seconds from respawn" + ? " is less than " + formatTime(notifyDelay) + " seconds from respawn" : " respawned."; for (MemorizedNpc npc : pendingNotificationNpcs) { - if (npc.getSecondsFromRespawn(tickCount, lastTickUpdate) <= notifyDelay) + if (getTimeLeftForNpc(npc) <= notifyDelay) { pendingNotificationNpcs.remove(npc); notifier.notify(npc.getNpcName() + notifyDelayStr); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index ed3dd3170a..81d4e7f06b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -107,10 +107,7 @@ public class NpcSceneOverlay extends Overlay OverlayUtil.renderPolygon(graphics, poly, color); } - final String timeLeftStr = NpcIndicatorsPlugin.TIME_LEFT_FORMATTER.format(npc.getSecondsFromRespawn( - client.getTickCount(), - plugin.getLastTickUpdate() - )); + final String timeLeftStr = plugin.formatTime(plugin.getTimeLeftForNpc(npc)); final int textWidth = graphics.getFontMetrics().stringWidth(timeLeftStr); final int textHeight = graphics.getFontMetrics().getAscent(); From 89e1ce55cb93eb7a6107bdaa104ea76849cdd5e9 Mon Sep 17 00:00:00 2001 From: f0rmatme Date: Mon, 21 Oct 2019 00:55:50 -0700 Subject: [PATCH 3/4] update --- .../plugins/npchighlight/NpcIndicatorsPlugin.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java index aff63ec15f..5393bcc191 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java @@ -231,6 +231,10 @@ public class NpcIndicatorsPlugin extends Plugin private boolean highlightMenuNames; @Getter(AccessLevel.PACKAGE) private boolean showRespawnTimer; + @Getter(AccessLevel.PACKAGE) + private boolean getNotifyOnRespawn; + @Getter(AccessLevel.PACKAGE) + private int getNotifyOnRespawnDelay; @Provides NpcIndicatorsConfig provideConfig(ConfigManager configManager) @@ -619,12 +623,12 @@ public class NpcIndicatorsPlugin extends Plugin private void checkNotifyNpcs() { - if (!config.getNotifyOnRespawn()) + if (!this.getNotifyOnRespawn) { return; } - final double notifyDelay = ((double)config.getNotifyOnRespawnDelay()) / 1000; + final double notifyDelay = ((double)this.getNotifyOnRespawnDelay) / 1000; final String notifyDelayStr = notifyDelay > 0 ? " is less than " + formatTime(notifyDelay) + " seconds from respawn" : " respawned."; @@ -736,5 +740,7 @@ public class NpcIndicatorsPlugin extends Plugin this.drawMinimapNames = config.drawMinimapNames(); this.highlightMenuNames = config.highlightMenuNames(); this.showRespawnTimer = config.showRespawnTimer(); + this.getNotifyOnRespawn = config.getNotifyOnRespawn(); + this.getNotifyOnRespawnDelay = config.getNotifyOnRespawnDelay(); } } From b60ecd8c474a43ff9ed7af6cc7f3430020843b12 Mon Sep 17 00:00:00 2001 From: f0rmatme Date: Mon, 21 Oct 2019 01:13:42 -0700 Subject: [PATCH 4/4] unused imports --- .../client/plugins/npchighlight/NpcSceneOverlay.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index 5f539664f8..29f1b7b75d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -31,15 +31,10 @@ import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Shape; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.time.Instant; import java.util.List; -import java.util.Locale; import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Client; -import net.runelite.api.Constants; import net.runelite.api.NPC; import net.runelite.api.NPCDefinition; import net.runelite.api.Perspective;