From 9e560d91e392fee9bf27ad148d21563b98b8e769 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sun, 26 Jan 2020 22:18:23 -0800 Subject: [PATCH] cluescroll plugin: Clear stale location clue hint arrows Location clue scrolls added a hint arrow when the player was nearby one of the clue's locations. It did not, however clear that arrow if the locations were changed and the previously-set hint arrow location was no longer marked. This commit updates this behavior to clear the active hint arrow each game tick before re-adding any location hint arrows. (and if no NPC hint arrows are set) Fixes runelite/runelite#10370 --- .../plugins/cluescrolls/ClueScrollPlugin.java | 11 +- .../cluescrolls/ClueScrollPluginTest.java | 104 +++++++++++++++++- 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java index 8e09fd6a85..49c8da9064 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java @@ -396,14 +396,17 @@ public class ClueScrollPlugin extends Plugin if (clue instanceof LocationClueScroll) { final WorldPoint[] locations = ((LocationClueScroll) clue).getLocations(); + final boolean npcHintArrowMarked = client.getHintArrowNpc() != null && npcsToMark.contains(client.getHintArrowNpc()); + + if (!npcHintArrowMarked) + { + client.clearHintArrow(); + } for (WorldPoint location : locations) { // Only set the location hint arrow if we do not already have more accurate location - if (location.isInScene(client) - && config.displayHintArrows() - && (client.getHintArrowNpc() == null - || !npcsToMark.contains(client.getHintArrowNpc()))) + if (location.isInScene(client) && config.displayHintArrows() && !npcHintArrowMarked) { client.setHintArrow(location); } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java index d1585382d4..3719dce654 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java @@ -25,13 +25,68 @@ */ package net.runelite.client.plugins.cluescrolls; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation; +import net.runelite.client.ui.overlay.OverlayManager; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) public class ClueScrollPluginTest { + @Mock + @Bind + Client client; + + @Inject + ClueScrollPlugin plugin; + + @Bind + @Named("developerMode") + boolean developerMode; + + @Mock + @Bind + ClueScrollConfig config; + + @Mock + @Bind + OverlayManager overlayManager; + + @Mock + @Bind + ItemManager itemManager; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + @Test public void getGetMirrorPoint() { @@ -61,4 +116,51 @@ public class ClueScrollPluginTest converted = ClueScrollPlugin.getMirrorPoint(point, false); assertEquals(point, converted); } -} \ No newline at end of file + + @Test + public void testLocationHintArrowCleared() + { + final Widget clueWidget = mock(Widget.class); + when(clueWidget.getText()).thenReturn("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Reldo may have a clue."); + final ChatMessage hotColdMessage = new ChatMessage(); + hotColdMessage.setType(ChatMessageType.GAMEMESSAGE); + final Player localPlayer = mock(Player.class); + + when(client.getWidget(WidgetInfo.CLUE_SCROLL_TEXT)).thenReturn(clueWidget); + when(client.getLocalPlayer()).thenReturn(localPlayer); + when(client.getPlane()).thenReturn(0); + when(client.getCachedNPCs()).thenReturn(new NPC[] {}); + when(config.displayHintArrows()).thenReturn(true); + + // The hint arrow should be reset each game tick from when the clue is read onward + // This is to verify the arrow is cleared the correct number of times during the clue updating process. + int clueSetupHintArrowClears = 0; + + // Initialize a beginner hot-cold clue (which will have an end point of LUMBRIDGE_COW_FIELD) + plugin.onGameTick(new GameTick()); + verify(client, times(++clueSetupHintArrowClears)).clearHintArrow(); + + // Perform the first hot-cold check in Lumbridge near sheep pen (get 2 possible points: LUMBRIDGE_COW_FIELD and DRAYNOR_WHEAT_FIELD) + when(localPlayer.getWorldLocation()).thenReturn(new WorldPoint(3208, 3254, 0)); + hotColdMessage.setMessage("The device is hot."); + plugin.onChatMessage(hotColdMessage); + + // Move to SW of DRAYNOR_WHEAT_FIELD (hint arrow should be visible here) + when(localPlayer.getWorldLocation()).thenReturn(new WorldPoint(3105, 3265, 0)); + when(client.getBaseX()).thenReturn(3056); + when(client.getBaseY()).thenReturn(3216); + plugin.onGameTick(new GameTick()); + verify(client, times(++clueSetupHintArrowClears)).clearHintArrow(); + verify(client).setHintArrow(HotColdLocation.DRAYNOR_WHEAT_FIELD.getWorldPoint()); + + // Test in that location (get 1 possible location: LUMBRIDGE_COW_FIELD) + hotColdMessage.setMessage("The device is hot, and warmer than last time."); + plugin.onChatMessage(hotColdMessage); + plugin.onGameTick(new GameTick()); + + // Hint arrow should be cleared and not re-set now as the only remaining location is outside of the current + // scene + verify(client, times(++clueSetupHintArrowClears)).clearHintArrow(); + verify(client, times(1)).setHintArrow(any(WorldPoint.class)); + } +}