From ed17bdaed351549e7547238e354a145154da3668 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Sun, 1 Sep 2019 22:41:28 +0100 Subject: [PATCH] idle notifer: add movement idle notification Co-authored-by: Adam --- .../idlenotifier/IdleNotifierConfig.java | 23 +++++++--- .../idlenotifier/IdleNotifierPlugin.java | 42 ++++++++++++++++++- .../idlenotifier/IdleNotifierPluginTest.java | 17 ++++++++ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java index 7d846b9db9..200d00da4f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java @@ -53,11 +53,22 @@ public interface IdleNotifierConfig extends Config return true; } + @ConfigItem( + keyName = "movementidle", + name = "Idle Movement Notifications", + description = "Configures if idle movement notifications are enabled e.g. running, walking", + position = 3 + ) + default boolean movementIdle() + { + return false; + } + @ConfigItem( keyName = "logoutidle", name = "Idle Logout Notifications", description = "Configures if the idle logout notifications are enabled", - position = 3 + position = 4 ) default boolean logoutIdle() { @@ -68,7 +79,7 @@ public interface IdleNotifierConfig extends Config keyName = "timeout", name = "Idle Notification Delay (ms)", description = "The notification delay after the player is idle", - position = 4 + position = 5 ) default int getIdleNotificationDelay() { @@ -79,7 +90,7 @@ public interface IdleNotifierConfig extends Config keyName = "hitpoints", name = "Hitpoints Notification Threshold", description = "The amount of hitpoints to send a notification at. A value of 0 will disable notification.", - position = 5 + position = 6 ) default int getHitpointsThreshold() { @@ -90,7 +101,7 @@ public interface IdleNotifierConfig extends Config keyName = "prayer", name = "Prayer Notification Threshold", description = "The amount of prayer points to send a notification at. A value of 0 will disable notification.", - position = 6 + position = 7 ) default int getPrayerThreshold() { @@ -100,7 +111,7 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "oxygen", name = "Oxygen Notification Threshold", - position = 7, + position = 8, description = "The amount of remaining oxygen to send a notification at. A value of 0 will disable notification." ) default int getOxygenThreshold() @@ -111,7 +122,7 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "spec", name = "Special Attack Energy Notification Threshold", - position = 8, + position = 9, description = "The amount of spec energy reached to send a notification at. A value of 0 will disable notification." ) default int getSpecEnergyThreshold() 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 db2699d6d6..8d4efcdac6 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 @@ -45,6 +45,7 @@ import net.runelite.api.Player; import net.runelite.api.Skill; import net.runelite.api.VarPlayer; import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.AnimationChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; @@ -88,6 +89,9 @@ public class IdleNotifierPlugin extends Plugin private int lastAnimation = AnimationID.IDLE; private Instant lastInteracting; private Actor lastInteract; + private Instant lastMoving; + private WorldPoint lastPosition; + private boolean notifyPosition = false; private boolean notifyHitpoints = true; private boolean notifyPrayer = true; private boolean notifyOxygen = true; @@ -400,6 +404,11 @@ public class IdleNotifierPlugin extends Plugin notifier.notify("[" + local.getName() + "] is now idle!"); } + if (config.movementIdle() && checkMovementIdle(waitDuration, local)) + { + notifier.notify("[" + local.getName() + "] has stopped moving!"); + } + if (config.interactionIdle() && checkInteractionIdle(waitDuration, local)) { if (lastInteractWasCombat) @@ -638,6 +647,37 @@ public class IdleNotifierPlugin extends Plugin return false; } + private boolean checkMovementIdle(Duration waitDuration, Player local) + { + if (lastPosition == null) + { + lastPosition = local.getWorldLocation(); + return false; + } + + WorldPoint position = local.getWorldLocation(); + + if (lastPosition.equals(position)) + { + if (notifyPosition + && local.getAnimation() == IDLE + && Instant.now().compareTo(lastMoving.plus(waitDuration)) >= 0) + { + notifyPosition = false; + // Return true only if we weren't just breaking out of an animation + return lastAnimation == IDLE; + } + } + else + { + notifyPosition = true; + lastPosition = position; + lastMoving = Instant.now(); + } + + return false; + } + private void resetTimers() { final Player local = client.getLocalPlayer(); @@ -656,4 +696,4 @@ public class IdleNotifierPlugin extends Plugin lastInteract = null; } } -} \ No newline at end of file +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java index 39af7a8e28..f1f21f2898 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java @@ -36,6 +36,7 @@ import net.runelite.api.NPC; import net.runelite.api.NPCComposition; import net.runelite.api.Player; import net.runelite.api.VarPlayer; +import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.AnimationChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; @@ -47,6 +48,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Matchers; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import org.mockito.Mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -272,4 +274,19 @@ public class IdleNotifierPluginTest plugin.onGameTick(new GameTick()); verify(notifier).notify(Matchers.eq("[" + PLAYER_NAME + "] has restored spec energy!")); } + + @Test + public void testMovementIdle() + { + when(config.movementIdle()).thenReturn(true); + + when(player.getWorldLocation()).thenReturn(new WorldPoint(0, 0, 0)); + plugin.onGameTick(new GameTick()); + when(player.getWorldLocation()).thenReturn(new WorldPoint(1, 0, 0)); + plugin.onGameTick(new GameTick()); + // No movement here + plugin.onGameTick(new GameTick()); + + verify(notifier).notify(eq("[" + PLAYER_NAME + "] has stopped moving!")); + } } \ No newline at end of file