From 60c8377b2ef26e3b9eeacaddcc7f3ef580127206 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 5 Dec 2021 12:05:21 -0500 Subject: [PATCH 1/3] screenshot plugin: reorder config --- .../plugins/screenshot/ScreenshotConfig.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java index f7498f7af3..1b2de89441 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java @@ -74,6 +74,28 @@ public interface ScreenshotConfig extends Config return true; } + @ConfigItem( + keyName = "uploadScreenshot", + name = "Upload", + description = "Configures whether or not screenshots are uploaded to Imgur, or placed on your clipboard", + position = 3 + ) + default ImageUploadStyle uploadScreenshot() + { + return ImageUploadStyle.NEITHER; + } + + @ConfigItem( + keyName = "hotkey", + name = "Screenshot hotkey", + description = "When you press this key a screenshot will be taken", + position = 4 + ) + default Keybind hotkey() + { + return Keybind.NOT_SET; + } + @ConfigItem( keyName = "rewards", name = "Screenshot Rewards", @@ -122,17 +144,6 @@ public interface ScreenshotConfig extends Config return true; } - @ConfigItem( - keyName = "uploadScreenshot", - name = "Upload", - description = "Configures whether or not screenshots are uploaded to Imgur, or placed on your clipboard", - position = 7 - ) - default ImageUploadStyle uploadScreenshot() - { - return ImageUploadStyle.NEITHER; - } - @ConfigItem( keyName = "kills", name = "Screenshot PvP Kills", @@ -276,15 +287,4 @@ public interface ScreenshotConfig extends Config { return true; } - - @ConfigItem( - keyName = "hotkey", - name = "Screenshot hotkey", - description = "When you press this key a screenshot will be taken", - position = 20 - ) - default Keybind hotkey() - { - return Keybind.NOT_SET; - } } From 9564e13d0f57590c9e6ad9a5b18d8e9a5cffb613 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 5 Dec 2021 11:30:06 -0500 Subject: [PATCH 2/3] screenshot plugin: add combat achievements Co-authored-by: Evan <55665020+EvanDeadlySins@users.noreply.github.com> --- .../main/java/net/runelite/api/Varbits.java | 8 ++++ .../plugins/screenshot/ScreenshotConfig.java | 12 ++++++ .../plugins/screenshot/ScreenshotPlugin.java | 35 ++++++++++++++++ .../screenshot/ScreenshotPluginTest.java | 42 +++++++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index 084ee4468e..7c609f627d 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -626,6 +626,14 @@ public enum Varbits */ COLLECTION_LOG_NOTIFICATION(11959), + /** + * Combat Achievements popup settings whenever a new task is completed + * + * 0 = popup notification enabled + * 1 = popup notification disabled + */ + COMBAT_ACHIEVEMENTS_POPUP(12455), + /** * Show boss health overlay setting * 0 = on diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java index 1b2de89441..a461c1fc08 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java @@ -287,4 +287,16 @@ public interface ScreenshotConfig extends Config { return true; } + + @ConfigItem( + keyName = "combatAchievements", + name = "Screenshot combat achievements", + description = "Take a screenshot when completing a combat achievement task", + position = 20, + section = whatSection + ) + default boolean screenshotCombatAchievements() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java index 160e06518e..a716ff2e63 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java @@ -112,6 +112,7 @@ public class ScreenshotPlugin extends Plugin private static final Pattern DUEL_END_PATTERN = Pattern.compile("You have now (won|lost) ([0-9,]+) duels?\\."); private static final Pattern QUEST_PATTERN_1 = Pattern.compile(".+?ve\\.*? (?been|rebuilt|.+?ed)? ?(?:the )?'?(?.+?)'?(?: [Qq]uest)?[!.]?$"); private static final Pattern QUEST_PATTERN_2 = Pattern.compile("'?(?.+?)'?(?: [Qq]uest)? (?[a-z]\\w+?ed)?(?: f.*?)?[!.]?$"); + private static final Pattern COMBAT_ACHIEVEMENTS_PATTERN = Pattern.compile("Congratulations, you've completed an? (?\\w+) combat task: (?(.+))\\."); private static final ImmutableList RFD_TAGS = ImmutableList.of("Another Cook", "freed", "defeated", "saved"); private static final ImmutableList WORD_QUEST_IN_NAME_TAGS = ImmutableList.of("Another Cook", "Doric", "Heroes", "Legends", "Observatory", "Olaf", "Waterfall"); private static final ImmutableList PET_MESSAGES = ImmutableList.of("You have a funny feeling like you're being followed", @@ -134,6 +135,7 @@ public class ScreenshotPlugin extends Plugin private static final String SD_COLLECTION_LOG = "Collection Log"; private static final String SD_PVP_KILLS = "PvP Kills"; private static final String SD_DEATHS = "Deaths"; + private static final String SD_COMBAT_ACHIEVEMENTS = "Combat Achievements"; private String clueType; private Integer clueNumber; @@ -494,6 +496,15 @@ public class ScreenshotPlugin extends Plugin String fileName = "Collection log (" + entry + ")"; takeScreenshot(fileName, SD_COLLECTION_LOG); } + + if (chatMessage.contains("combat task") && config.screenshotCombatAchievements() && client.getVar(Varbits.COMBAT_ACHIEVEMENTS_POPUP) == 1) + { + String fileName = parseCombatAchievementWidget(chatMessage); + if (!fileName.isEmpty()) + { + takeScreenshot(fileName, SD_COMBAT_ACHIEVEMENTS); + } + } } @Subscribe @@ -652,6 +663,12 @@ public class ScreenshotPlugin extends Plugin String fileName = "Collection log (" + entry + ")"; takeScreenshot(fileName, SD_COLLECTION_LOG); } + if (topText.equalsIgnoreCase("Combat Task Completed!") && config.screenshotCombatAchievements() && client.getVar(Varbits.COMBAT_ACHIEVEMENTS_POPUP) == 0) + { + String entry = Text.removeTags(bottomText).substring("Task Completed: ".length()); + String fileName = "Combat task (" + entry.replaceAll("[:?]", "") + ")"; + takeScreenshot(fileName, SD_COMBAT_ACHIEVEMENTS); + } notificationStarted = false; break; } @@ -752,6 +769,24 @@ public class ScreenshotPlugin extends Plugin return "High Gamble(count not found)"; } + /** + * Parses a combat achievement success chat message into a filename-safe string. + * + * @param text A received chat message which may or may not be from completing a combat achievement. + * @return A formatted string of the achieved combat task name, or the empty string if the passed message + * is not a combat achievement completion message. + */ + @VisibleForTesting + static String parseCombatAchievementWidget(final String text) + { + final Matcher m = COMBAT_ACHIEVEMENTS_PATTERN.matcher(text); + if (m.matches()) + { + String task = m.group("task").replaceAll("[:?]", ""); + return "Combat task (" + task + ")"; + } + return ""; + } /** * Saves a screenshot of the client window to the screenshot folder as a PNG, diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java index 9ded0bfe8c..d1da52b7f4 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java @@ -353,6 +353,17 @@ public class ScreenshotPluginTest assertEquals("Quest(quest not found)", ScreenshotPlugin.parseQuestCompletedWidget("Sins of the Father forgiven!")); } + @Test + public void testCombatAchievementsParsing() + { + assertEquals("Combat task (Into the Den of Giants)", ScreenshotPlugin.parseCombatAchievementWidget("Congratulations, you've completed an easy combat task: Into the Den of Giants.")); + assertEquals("Combat task (I'd Rather Not Learn)", ScreenshotPlugin.parseCombatAchievementWidget("Congratulations, you've completed a medium combat task: I'd Rather Not Learn.")); + assertEquals("Combat task (Why Cook)", ScreenshotPlugin.parseCombatAchievementWidget("Congratulations, you've completed a hard combat task: Why Cook?.")); + assertEquals("Combat task (From Dusk...)", ScreenshotPlugin.parseCombatAchievementWidget("Congratulations, you've completed an elite combat task: From Dusk....")); + assertEquals("Combat task (Perfect Olm (Trio))", ScreenshotPlugin.parseCombatAchievementWidget("Congratulations, you've completed a master combat task: Perfect Olm (Trio).")); + assertEquals("Combat task (Chambers of Xeric CM (5-Scale) Speed-Runner)", ScreenshotPlugin.parseCombatAchievementWidget("Congratulations, you've completed a grandmaster combat task: Chambers of Xeric: CM (5-Scale) Speed-Runner.")); + } + @Test public void testBAHighGambleRewardParsing() { @@ -455,4 +466,35 @@ public class ScreenshotPluginTest verify(drawManager).requestNextFrameListener(any(Consumer.class)); } + + @Test + public void testCombatAchievementsPopup() + { + when(screenshotConfig.screenshotCombatAchievements()).thenReturn(true); + + ScriptPreFired notificationStart = new ScriptPreFired(ScriptID.NOTIFICATION_START); + screenshotPlugin.onScriptPreFired(notificationStart); + + when(client.getVar(VarClientStr.NOTIFICATION_TOP_TEXT)).thenReturn("Combat Task Completed!"); + when(client.getVar(VarClientStr.NOTIFICATION_BOTTOM_TEXT)).thenReturn("Task Completed: Handyman"); + + ScriptPreFired notificationDelay = new ScriptPreFired(ScriptID.NOTIFICATION_DELAY); + screenshotPlugin.onScriptPreFired(notificationDelay); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testCombatAchievementsChat() + { + when(screenshotConfig.screenshotCombatAchievements()).thenReturn(true); + + when(client.getVar(Varbits.COMBAT_ACHIEVEMENTS_POPUP)).thenReturn(1); + + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", + "Congratulations, you've completed an easy combat task: Handyman.", null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } } From a05655f4120ba24df002af0b17158d09ae030cab Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 5 Dec 2021 12:02:35 -0500 Subject: [PATCH 3/3] screenshot plugin: test screenshot filenames --- .../plugins/screenshot/ScreenshotPlugin.java | 3 +- .../screenshot/ScreenshotPluginTest.java | 57 ++++++++++--------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java index a716ff2e63..f9ecc59d02 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java @@ -795,7 +795,8 @@ public class ScreenshotPlugin extends Plugin * @param fileName Filename to use, without file extension. * @param subDir Subdirectory to store the captured screenshot in. */ - private void takeScreenshot(String fileName, String subDir) + @VisibleForTesting + void takeScreenshot(String fileName, String subDir) { if (client.getGameState() == GameState.LOGIN_SCREEN) { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java index d1da52b7f4..655fe4d42e 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java @@ -28,7 +28,6 @@ import com.google.inject.Guice; import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.BoundFieldModule; import java.util.concurrent.ScheduledExecutorService; -import java.util.function.Consumer; import javax.inject.Inject; import static net.runelite.api.ChatMessageType.GAMEMESSAGE; import static net.runelite.api.ChatMessageType.TRADE; @@ -57,15 +56,14 @@ import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import org.mockito.Mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import org.mockito.junit.MockitoJUnitRunner; @@ -132,6 +130,7 @@ public class ScreenshotPluginTest public void before() { Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + screenshotPlugin = spy(screenshotPlugin); when(screenshotConfig.screenshotLevels()).thenReturn(true); when(screenshotConfig.screenshotValuableDrop()).thenReturn(true); when(screenshotConfig.valuableDropThreshold()).thenReturn(1000); @@ -183,7 +182,7 @@ public class ScreenshotPluginTest widgetLoaded.setGroupId(WidgetID.THEATRE_OF_BLOOD_REWARD_GROUP_ID); screenshotPlugin.onWidgetLoaded(widgetLoaded); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Theatre of Blood(73)", "Boss Kills"); } @Test @@ -201,7 +200,7 @@ public class ScreenshotPluginTest widgetLoaded.setGroupId(WidgetID.THEATRE_OF_BLOOD_REWARD_GROUP_ID); screenshotPlugin.onWidgetLoaded(widgetLoaded); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Theatre of Blood Story Mode(73)", "Boss Kills"); } @Test @@ -219,7 +218,7 @@ public class ScreenshotPluginTest widgetLoaded.setGroupId(WidgetID.THEATRE_OF_BLOOD_REWARD_GROUP_ID); screenshotPlugin.onWidgetLoaded(widgetLoaded); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Theatre of Blood Hard Mode(73)", "Boss Kills"); } @Test @@ -228,12 +227,12 @@ public class ScreenshotPluginTest ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", NOT_SO_VALUABLE_DROP, null, 0); screenshotPlugin.onChatMessage(chatMessageEvent); - verifyNoInteractions(drawManager); + verify(screenshotPlugin, never()).takeScreenshot(anyString(), anyString()); when(screenshotConfig.valuableDropThreshold()).thenReturn(0); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Valuable drop 6 x Bronze arrow (42 coins)", "Valuable Drops"); } @Test @@ -243,12 +242,12 @@ public class ScreenshotPluginTest when(screenshotConfig.valuableDropThreshold()).thenReturn(100_000); screenshotPlugin.onChatMessage(chatMessageEvent); - verifyNoInteractions(drawManager); + verify(screenshotPlugin, never()).takeScreenshot(anyString(), anyString()); when(screenshotConfig.valuableDropThreshold()).thenReturn(1000); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Valuable drop Rune scimitar (25,600 coins)", "Valuable Drops"); } @Test @@ -257,7 +256,7 @@ public class ScreenshotPluginTest ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", UNTRADEABLE_DROP, null, 0); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Untradeable drop Rusty sword", "Untradeable Drops"); } @Test @@ -277,7 +276,7 @@ public class ScreenshotPluginTest GameTick tick = new GameTick(); screenshotPlugin.onGameTick(tick); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Hitpoints(99)", "Levels"); } @Test @@ -297,7 +296,7 @@ public class ScreenshotPluginTest GameTick tick = new GameTick(); screenshotPlugin.onGameTick(tick); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Firemaking(9)", "Levels"); } @Test @@ -317,7 +316,7 @@ public class ScreenshotPluginTest GameTick tick = new GameTick(); screenshotPlugin.onGameTick(tick); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Attack(70)", "Levels"); } @Test @@ -337,7 +336,7 @@ public class ScreenshotPluginTest GameTick tick = new GameTick(); screenshotPlugin.onGameTick(tick); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Hunter(2)", "Levels"); } @Test @@ -386,7 +385,7 @@ public class ScreenshotPluginTest screenshotPlugin.onGameTick(new GameTick()); - verify(drawManager, times(0)).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin, never()).takeScreenshot(anyString(), anyString()); } @Test @@ -405,7 +404,7 @@ public class ScreenshotPluginTest screenshotPlugin.onGameTick(new GameTick()); - verify(drawManager, times(0)).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin, never()).takeScreenshot(anyString(), anyString()); } @Test @@ -420,7 +419,7 @@ public class ScreenshotPluginTest ScriptPreFired notificationDelay = new ScriptPreFired(ScriptID.NOTIFICATION_DELAY); screenshotPlugin.onScriptPreFired(notificationDelay); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Collection log (Chompy bird hat)", "Collection Log"); } @Test @@ -431,12 +430,13 @@ public class ScreenshotPluginTest when(client.getVar(Varbits.COLLECTION_LOG_NOTIFICATION)).thenReturn(1); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Collection log (Chompy bird hat)", "Collection Log"); + reset(screenshotPlugin); when(client.getVar(Varbits.COLLECTION_LOG_NOTIFICATION)).thenReturn(3); screenshotPlugin.onChatMessage(chatMessageEvent); - verifyNoMoreInteractions(drawManager); + verify(screenshotPlugin, never()).takeScreenshot(anyString(), anyString()); } @Test @@ -445,12 +445,13 @@ public class ScreenshotPluginTest ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You won! You have now won 1,909 duels.", null, 0); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Duel won (1909)", "Duels"); + reset(screenshotPlugin); chatMessageEvent = new ChatMessage(null, TRADE, "", "You have lost 145 duels.", null, 0); screenshotPlugin.onChatMessage(chatMessageEvent); - verifyNoMoreInteractions(drawManager); + verify(screenshotPlugin, never()).takeScreenshot(anyString(), anyString()); } @Test @@ -459,12 +460,12 @@ public class ScreenshotPluginTest ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You were defeated! You have won 1,909 duels.", null, 0); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager, never()).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin, never()).takeScreenshot(anyString(), anyString()); chatMessageEvent = new ChatMessage(null, TRADE, "", "You have now lost 1,909 duels.", null, 0); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Duel lost (1909)", "Duels"); } @Test @@ -481,7 +482,7 @@ public class ScreenshotPluginTest ScriptPreFired notificationDelay = new ScriptPreFired(ScriptID.NOTIFICATION_DELAY); screenshotPlugin.onScriptPreFired(notificationDelay); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Combat task (Handyman)", "Combat Achievements"); } @Test @@ -495,6 +496,6 @@ public class ScreenshotPluginTest "Congratulations, you've completed an easy combat task: Handyman.", null, 0); screenshotPlugin.onChatMessage(chatMessageEvent); - verify(drawManager).requestNextFrameListener(any(Consumer.class)); + verify(screenshotPlugin).takeScreenshot("Combat task (Handyman)", "Combat Achievements"); } }