diff --git a/cache/src/main/java/net/runelite/cache/definitions/SequenceDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/SequenceDefinition.java index 3f280f31c2..d596b66a90 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/SequenceDefinition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/SequenceDefinition.java @@ -31,17 +31,17 @@ public class SequenceDefinition { private final int id; public int[] frameIDs; // top 16 bits are FrameDefinition ids - public int[] field3048; + public int[] chatFrameIds; public int[] frameLenghts; - public int rightHandItem = -1; + public int[] frameSounds; + public int frameStep = -1; public int[] interleaveLeave; public boolean stretches = false; public int forcedPriority = 5; - public int maxLoops = 99; - public int[] field3056; - public int precedenceAnimating = -1; public int leftHandItem = -1; - public int replyMode = 2; - public int frameStep = -1; + public int rightHandItem = -1; + public int maxLoops = 99; + public int precedenceAnimating = -1; public int priority = -1; + public int replyMode = 2; } diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/SequenceLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/SequenceLoader.java index 987cbd4204..a5676270c6 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/SequenceLoader.java +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/SequenceLoader.java @@ -26,13 +26,9 @@ package net.runelite.cache.definitions.loaders; import net.runelite.cache.definitions.SequenceDefinition; import net.runelite.cache.io.InputStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class SequenceLoader { - private static final Logger logger = LoggerFactory.getLogger(SequenceLoader.class); - public SequenceDefinition load(int id, byte[] b) { SequenceDefinition def = new SequenceDefinition(id); @@ -129,26 +125,26 @@ public class SequenceLoader else if (opcode == 12) { var3 = stream.readUnsignedByte(); - def.field3048 = new int[var3]; + def.chatFrameIds = new int[var3]; for (var4 = 0; var4 < var3; ++var4) { - def.field3048[var4] = stream.readUnsignedShort(); + def.chatFrameIds[var4] = stream.readUnsignedShort(); } for (var4 = 0; var4 < var3; ++var4) { - def.field3048[var4] += stream.readUnsignedShort() << 16; + def.chatFrameIds[var4] += stream.readUnsignedShort() << 16; } } else if (opcode == 13) { var3 = stream.readUnsignedByte(); - def.field3056 = new int[var3]; + def.frameSounds = new int[var3]; for (var4 = 0; var4 < var3; ++var4) { - def.field3056[var4] = stream.read24BitInt(); + def.frameSounds[var4] = stream.read24BitInt(); } } 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 46b5b4a218..a3280b8fb0 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 @@ -1180,8 +1180,9 @@ public class WidgetID static class Lms { - static final int INFO = 2; + static final int INFO = 3; } + static class LmsKDA { static final int INFO = 4; @@ -1213,4 +1214,4 @@ public class WidgetID { static final int CONTAINER = 0; } -} \ No newline at end of file +} diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java index 17c8c3d1ef..a4e5114356 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java @@ -45,6 +45,7 @@ public class RuneLiteProperties private static final String TROUBLESHOOTING_LINK = "runelite.wiki.troubleshooting.link"; private static final String BUILDING_LINK = "runelite.wiki.building.link"; private static final String DNS_CHANGE_LINK = "runelite.dnschange.link"; + private static final String IMGUR_CLIENT_ID = "runelite.imgur.client.id"; private static final Properties properties = new Properties(); @@ -137,4 +138,9 @@ public class RuneLiteProperties String launcherVersion = properties.getProperty(LAUNCHER_VERSION_PROPERTY); return launcherVersion.equals("-1") ? null : launcherVersion; } + + public static String getImgurClientId() + { + return properties.getProperty(IMGUR_CLIENT_ID); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigItemDescriptor.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigItemDescriptor.java index c60d66f21a..852d9fa873 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigItemDescriptor.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigItemDescriptor.java @@ -33,4 +33,5 @@ public class ConfigItemDescriptor private final Class type; private final Range range; private final Alpha alpha; + private final Units units; } diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index 8b65b580c7..3c8e585af8 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -350,7 +350,8 @@ public class ConfigManager m.getDeclaredAnnotation(ConfigItem.class), m.getReturnType(), m.getDeclaredAnnotation(Range.class), - m.getDeclaredAnnotation(Alpha.class) + m.getDeclaredAnnotation(Alpha.class), + m.getDeclaredAnnotation(Units.class) )) .sorted((a, b) -> ComparisonChain.start() .compare(a.getItem().position(), b.getItem().position()) diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java index 7b68c00896..c0dee57a81 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java @@ -332,6 +332,17 @@ public interface RuneLiteConfig extends Config return true; } + @ConfigItem( + keyName = "tooltipPosition", + name = "Tooltip Position", + description = "Configures whether to show the tooltip above or under the cursor", + position = 35 + ) + default TooltipPositionType tooltipPosition() + { + return TooltipPositionType.UNDER_CURSOR; + } + @ConfigItem( keyName = "infoBoxVertical", name = "Display infoboxes vertically", @@ -358,11 +369,12 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "infoBoxSize", - name = "Infobox size (px)", + name = "Infobox size", description = "Configures the size of each infobox in pixels", position = 28, titleSection = "infoboxTitle" ) + @Units(Units.PIXELS) default int infoBoxSize() { return 35; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/UploadStyle.java b/runelite-client/src/main/java/net/runelite/client/config/TooltipPositionType.java similarity index 84% rename from runelite-client/src/main/java/net/runelite/client/plugins/screenshot/UploadStyle.java rename to runelite-client/src/main/java/net/runelite/client/config/TooltipPositionType.java index cf3e964c56..6fb81fd72c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/UploadStyle.java +++ b/runelite-client/src/main/java/net/runelite/client/config/TooltipPositionType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Alexsuperfly + * Copyright (c) 2020, Crypthead * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,23 +22,23 @@ * (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.screenshot; +package net.runelite.client.config; import lombok.RequiredArgsConstructor; +import lombok.Getter; +@Getter @RequiredArgsConstructor -public enum UploadStyle +public enum TooltipPositionType { - NEITHER("Neither"), - IMGUR("Imgur"), - CLIPBOARD("Clipboard"); + ABOVE_CURSOR("Above cursor"), + UNDER_CURSOR("Under cursor"); - private final String name; + private final String type; @Override public String toString() { - return name; + return type; } -} \ No newline at end of file +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/Units.java b/runelite-client/src/main/java/net/runelite/client/config/Units.java new file mode 100644 index 0000000000..45d54df164 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/config/Units.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, Hydrox6 + * 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.config; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used with ConfigItem, defines what units are shown to the side of the box. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@Documented +public @interface Units +{ + String MILLISECONDS = "ms"; + String MINUTES = " mins"; + String PERCENT = "%"; + String PIXELS = "px"; + String SECONDS = "s"; + String TICKS = " ticks"; + + String value(); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java index fddb364e9e..d941e2575a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java @@ -87,4 +87,8 @@ public abstract class Plugin implements Module { subs.forEach(s -> s.subscribe(eventBus, this)); } + + public void resetConfiguration() + { + } } 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 60db4d7974..3ba78fce76 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 @@ -30,6 +30,7 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigTitleSection; import net.runelite.client.config.Title; +import net.runelite.client.config.Units; @ConfigGroup("agility") public interface AgilityConfig extends Config @@ -91,6 +92,7 @@ public interface AgilityConfig extends Config hidden = true, unhide = "showLapCount" ) + @Units(Units.MINUTES) default int lapTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java index 7c3c680b31..b913b86a03 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java @@ -30,6 +30,7 @@ package net.runelite.client.plugins.banktags; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; +import com.google.common.collect.Lists; import com.google.inject.Provides; import java.awt.event.KeyEvent; import java.awt.event.MouseWheelEvent; @@ -100,6 +101,7 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis public static final String CONFIG_GROUP = "banktags"; public static final String TAG_SEARCH = "tag:"; public static final String ICON_SEARCH = "icon_"; + public static final String TAG_TABS_CONFIG = "tagtabs"; public static final String VAR_TAG_SUFFIX = "*"; private static final String EDIT_TAGS_MENU_OPTION = "Edit-tags"; private static final String NUMBER_REGEX = "[0-9]+(\\.[0-9]+)?[kmb]?"; @@ -162,6 +164,36 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis return configManager.getConfig(BankTagsConfig.class); } + @Override + public void resetConfiguration() + { + List extraKeys = Lists.newArrayList( + CONFIG_GROUP + "." + TagManager.ITEM_KEY_PREFIX, + CONFIG_GROUP + "." + ICON_SEARCH, + CONFIG_GROUP + "." + TAG_TABS_CONFIG + ); + + for (String prefix : extraKeys) + { + List keys = configManager.getConfigurationKeys(prefix); + for (String key : keys) + { + String[] str = key.split("\\.", 2); + if (str.length == 2) + { + configManager.unsetConfiguration(str[0], str[1]); + } + } + } + + clientThread.invokeLater(() -> + { + tabInterface.destroy(); + tabInterface.init(); + }); + } + + @Override public void startUp() { @@ -481,7 +513,7 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis @Subscribe private void onConfigChanged(ConfigChanged configChanged) { - if (configChanged.getGroup().equals("banktags") && configChanged.getKey().equals("useTabs")) + if (configChanged.getGroup().equals(CONFIG_GROUP) && configChanged.getKey().equals("useTabs")) { if (config.tabs()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java index 5f8f299c1a..a5340a7658 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java @@ -50,7 +50,7 @@ import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; @Singleton public class TagManager { - private static final String ITEM_KEY_PREFIX = "item_"; + static final String ITEM_KEY_PREFIX = "item_"; private final ConfigManager configManager; private final ItemManager itemManager; private final ClueScrollService clueScrollService; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabManager.java index 12466c6c32..1b6040d396 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabManager.java @@ -40,13 +40,12 @@ import net.runelite.api.util.Text; import net.runelite.client.config.ConfigManager; import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP; import static net.runelite.client.plugins.banktags.BankTagsPlugin.ICON_SEARCH; +import static net.runelite.client.plugins.banktags.BankTagsPlugin.TAG_TABS_CONFIG; import org.apache.commons.lang3.math.NumberUtils; @Singleton class TabManager { - private static final String TAG_TABS_CONFIG = "tagtabs"; - @Getter(AccessLevel.PACKAGE) private final List tabs = new ArrayList<>(); private final ConfigManager configManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index 2903bdfcdb..5983a448fe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -41,6 +41,7 @@ import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; @@ -88,6 +89,7 @@ import net.runelite.client.config.ConfigTitleSection; import net.runelite.client.config.Keybind; import net.runelite.client.config.ModifierlessKeybind; import net.runelite.client.config.Range; +import net.runelite.client.config.Units; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.PluginChanged; import net.runelite.client.plugins.PluginManager; @@ -641,6 +643,16 @@ class ConfigPanel extends PluginPanel spinnerTextField.setColumns(SPINNER_FIELD_WIDTH); spinner.addChangeListener(ce -> changeConfiguration(spinner, cd, cid)); + Units units = cid.getUnits(); + if (units != null) + { + DecimalFormat df = ((JSpinner.NumberEditor) spinner.getEditor()).getFormat(); + df.setPositiveSuffix(units.value()); + df.setNegativeSuffix(units.value()); + // Force update the spinner to have it add the units initially + spinnerTextField.setValue(value); + } + item.add(spinner, BorderLayout.EAST); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java index 2a12ac1ede..a1281a8e89 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingConfig.java @@ -28,6 +28,7 @@ package net.runelite.client.plugins.cooking; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("cooking") public interface CookingConfig extends Config @@ -35,9 +36,10 @@ public interface CookingConfig extends Config @ConfigItem( position = 1, keyName = "statTimeout", - name = "Reset stats (minutes)", + name = "Reset stats", description = "Configures the time until the session resets and the overlay is hidden (0 = Disable feature)" ) + @Units(Units.MINUTES) default int statTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java index a2ebe63099..f4e0878985 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java @@ -27,16 +27,18 @@ package net.runelite.client.plugins.discord; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("discord") public interface DiscordConfig extends Config { @ConfigItem( keyName = "actionTimeout", - name = "Action timeout (minutes)", + name = "Action timeout", description = "Configures after how long of not updating status will be reset (in minutes)", position = 0 ) + @Units(Units.MINUTES) default int actionTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java index 62d5e4937b..afd76fbed2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/experiencedrop/XpDropConfig.java @@ -28,6 +28,7 @@ import java.awt.Color; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("xpdrop") public interface XpDropConfig extends Config @@ -89,6 +90,7 @@ public interface XpDropConfig extends Config description = "Configures how many ticks should pass between fake XP drops, 0 to disable", position = 4 ) + @Units(Units.TICKS) default int fakeXpDropDelay() { return 0; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java index 5ccee0e752..4c9153f42a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java @@ -28,6 +28,7 @@ import java.awt.Color; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("fishing") public interface FishingConfig extends Config @@ -112,9 +113,10 @@ public interface FishingConfig extends Config @ConfigItem( position = 7, keyName = "statTimeout", - name = "Reset stats (minutes)", + name = "Reset stats", description = "The time until fishing session data is reset in minutes." ) + @Units(Units.MINUTES) default int statTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java index afd1586d15..7454ca056a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java @@ -32,6 +32,7 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigTitleSection; import net.runelite.client.config.Title; +import net.runelite.client.config.Units; import net.runelite.client.plugins.grounditems.config.ItemHighlightMode; import net.runelite.client.plugins.grounditems.config.MenuHighlightMode; import net.runelite.client.plugins.grounditems.config.PriceDisplayMode; @@ -600,6 +601,7 @@ public interface GroundItemsConfig extends Config position = 46, titleSection = "miscTitle" ) + @Units(Units.MILLISECONDS) default int doubleTapDelay() { return 250; 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 320a108e49..3c8667d33e 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 @@ -28,6 +28,7 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigSection; +import net.runelite.client.config.Units; @ConfigGroup("idlenotifier") public interface IdleNotifierConfig extends Config @@ -144,10 +145,11 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "timeout", - name = "Idle Notification Delay (ms)", + name = "Idle Notification Delay", description = "The notification delay after the player is idle", position = 11 ) + @Units(Units.MILLISECONDS) default int getIdleNotificationDelay() { return 5000; @@ -203,6 +205,7 @@ public interface IdleNotifierConfig extends Config description = "The amount of remaining oxygen to send a notification at. A value of 0 will disable notification.", position = 16 ) + @Units(Units.PERCENT) default int getOxygenThreshold() { return 0; @@ -214,6 +217,7 @@ public interface IdleNotifierConfig extends Config description = "The amount of spec energy reached to send a notification at. A value of 0 will disable notification.", position = 17 ) + @Units(Units.PERCENT) default int getSpecEnergyThreshold() { return 0; 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 2bf947033d..9e365d4ef8 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 @@ -782,6 +782,11 @@ public class IdleNotifierPlugin extends Plugin { lastInteract = null; lastInteracting = null; + + // prevent animation notifications from firing too + lastAnimation = IDLE; + lastAnimating = null; + return true; } } @@ -869,6 +874,11 @@ public class IdleNotifierPlugin extends Plugin { lastAnimation = IDLE; lastAnimating = null; + + // prevent interaction notifications from firing too + lastInteract = null; + lastInteracting = null; + return true; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeConfig.java index 3263a9c033..f5b24ac1a4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeConfig.java @@ -28,6 +28,7 @@ package net.runelite.client.plugins.motherlode; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("motherlode") public interface MotherlodeConfig extends Config @@ -54,9 +55,10 @@ public interface MotherlodeConfig extends Config @ConfigItem( keyName = "statTimeout", - name = "Reset stats (minutes)", + name = "Reset stats", description = "Configures the time until statistics are reset" ) + @Units(Units.MINUTES) default int statTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java index 408ded39f3..154c0ee7be 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java @@ -31,6 +31,7 @@ import java.awt.Graphics2D; import javax.inject.Singleton; import lombok.AccessLevel; import lombok.Getter; +import lombok.NonNull; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @@ -43,7 +44,7 @@ public class ScreenMarkerOverlay extends Overlay private final ScreenMarker marker; private final ScreenMarkerRenderable screenMarkerRenderable; - ScreenMarkerOverlay(final ScreenMarker marker) + ScreenMarkerOverlay(@NonNull ScreenMarker marker) { this.marker = marker; this.screenMarkerRenderable = new ScreenMarkerRenderable(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java index 3e50540ee2..e0b3fd6cd0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java @@ -36,6 +36,7 @@ import java.awt.image.BufferedImage; import java.time.Instant; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.inject.Inject; @@ -188,9 +189,10 @@ public class ScreenMarkerPlugin extends Plugin public void finishCreation(boolean aborted) { - if (!aborted && currentMarker != null) + ScreenMarker marker = currentMarker; + if (!aborted && marker != null) { - final ScreenMarkerOverlay screenMarkerOverlay = new ScreenMarkerOverlay(currentMarker); + final ScreenMarkerOverlay screenMarkerOverlay = new ScreenMarkerOverlay(marker); screenMarkerOverlay.setPreferredLocation(overlay.getBounds().getLocation()); screenMarkerOverlay.setPreferredSize(overlay.getBounds().getSize()); @@ -258,6 +260,6 @@ public class ScreenMarkerPlugin extends Plugin { }.getType()); - return screenMarkerData.stream().map(ScreenMarkerOverlay::new); + return screenMarkerData.stream().filter(Objects::nonNull).map(ScreenMarkerOverlay::new); } } 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 1f03b2aa81..05acb0ca64 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 @@ -28,6 +28,7 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.Keybind; +import net.runelite.client.util.ImageUploadStyle; @ConfigGroup("screenshot") public interface ScreenshotConfig extends Config @@ -115,9 +116,9 @@ public interface ScreenshotConfig extends Config description = "Configures whether or not screenshots are uploaded to Imgur, or placed on your clipboard", position = 7 ) - default UploadStyle uploadScreenshot() + default ImageUploadStyle uploadScreenshot() { - return UploadStyle.NEITHER; + return ImageUploadStyle.NEITHER; } @ConfigItem( 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 2aacbcd7d3..98d18ce7a0 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 @@ -32,26 +32,17 @@ import com.google.inject.Provides; import java.awt.Desktop; import java.awt.Graphics; import java.awt.Image; -import java.awt.Toolkit; -import java.awt.TrayIcon; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.StringSelection; import java.awt.image.BufferedImage; -import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.util.Date; -import java.util.EnumSet; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.imageio.ImageIO; import javax.inject.Inject; import javax.inject.Singleton; import javax.swing.SwingUtilities; @@ -66,7 +57,6 @@ import net.runelite.api.Player; import net.runelite.api.Point; import net.runelite.api.SpriteID; import net.runelite.api.Varbits; -import net.runelite.api.WorldType; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; @@ -96,24 +86,14 @@ import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.screenshot.imgur.ImageUploadRequest; -import net.runelite.client.plugins.screenshot.imgur.ImageUploadResponse; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.DrawManager; import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.HotkeyListener; +import net.runelite.client.util.ImageCapture; import net.runelite.client.util.ImageUtil; -import net.runelite.http.api.RuneLiteAPI; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.HttpUrl; -import okhttp3.MediaType; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @PluginDescriptor( @@ -126,10 +106,6 @@ import org.jetbrains.annotations.Nullable; @Singleton public class ScreenshotPlugin extends Plugin { - private static final String IMGUR_CLIENT_ID = "30d71e5f6860809"; - private static final HttpUrl IMGUR_IMAGE_UPLOAD_URL = HttpUrl.parse("https://api.imgur.com/3/image"); - private static final MediaType JSON = MediaType.parse("application/json"); - private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)"); @@ -196,6 +172,9 @@ public class ScreenshotPlugin extends Plugin @Inject private SpriteManager spriteManager; + @Inject + private ImageCapture imageCapture; + @Getter(AccessLevel.PACKAGE) private BufferedImage reportButton; @@ -206,7 +185,7 @@ public class ScreenshotPlugin extends Plugin @Override public void hotkeyPressed() { - takeScreenshot(format(new Date())); + takeScreenshot(""); } }; @@ -220,7 +199,6 @@ public class ScreenshotPlugin extends Plugin private boolean screenshotLevels; private boolean screenshotKingdom; private boolean screenshotPet; - private UploadStyle uploadScreenshot; private boolean screenshotKills; private boolean screenshotBossKills; private boolean screenshotFriendDeath; @@ -253,7 +231,7 @@ public class ScreenshotPlugin extends Plugin .tab(false) .tooltip("Take screenshot") .icon(iconImage) - .onClick(() -> takeScreenshot(format(new Date()))) + .onClick(() -> takeScreenshot("")) .popup(ImmutableMap .builder() .put("Open screenshot folder...", () -> @@ -353,7 +331,7 @@ public class ScreenshotPlugin extends Plugin { final Player player = playerLootReceived.getPlayer(); final String name = player.getName(); - String fileName = "Kill " + name + " " + format(new Date()); + String fileName = "Kill " + name; takeScreenshot(fileName); } } @@ -421,7 +399,7 @@ public class ScreenshotPlugin extends Plugin if (this.screenshotPet && PET_MESSAGES.stream().anyMatch(chatMessage::contains)) { - String fileName = "Pet " + format(new Date()); + String fileName = "Pet"; takeScreenshot(fileName); } @@ -443,7 +421,7 @@ public class ScreenshotPlugin extends Plugin if (m.matches()) { String valuableDropName = m.group(1); - String fileName = "Valuable drop " + valuableDropName + " " + format(new Date()); + String fileName = "Valuable drop " + valuableDropName; takeScreenshot(fileName); } } @@ -454,7 +432,7 @@ public class ScreenshotPlugin extends Plugin if (m.matches()) { String untradeableDropName = m.group(1); - String fileName = "Untradeable drop " + untradeableDropName + " " + format(new Date()); + String fileName = "Untradeable drop " + untradeableDropName; takeScreenshot(fileName); } } @@ -703,135 +681,7 @@ public class ScreenshotPlugin extends Plugin // Draw the game onto the screenshot graphics.drawImage(image, gameOffsetX, gameOffsetY, null); - - File playerFolder; - if (client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) - { - final EnumSet worldTypes = client.getWorldType(); - - String playerDir = client.getLocalPlayer().getName(); - if (worldTypes.contains(WorldType.DEADMAN)) - { - playerDir += "-Deadman"; - } - else if (worldTypes.contains(WorldType.LEAGUE)) - { - playerDir += "-League"; - } - playerFolder = new File(SCREENSHOT_DIR, playerDir); - } - else - { - playerFolder = SCREENSHOT_DIR; - } - - playerFolder.mkdirs(); - - if (subdirectory != null) - { - //uhh just tried to do this as workaround, not sure if it's the best idea tho - File actualplayerFolder = new File(playerFolder, subdirectory); - actualplayerFolder.mkdir(); - playerFolder = actualplayerFolder; - } - - try - { - File screenshotFile = new File(playerFolder, fileName + ".png"); - - // To make sure that screenshots don't get overwritten, check if file exists, - // and if it does create file with same name and suffix. - int i = 1; - while (screenshotFile.exists()) - { - screenshotFile = new File(playerFolder, fileName + String.format("(%d)", i++) + ".png"); - } - - ImageIO.write(screenshot, "PNG", screenshotFile); - UploadStyle uploadStyle = this.uploadScreenshot; - - if (uploadStyle == UploadStyle.IMGUR) - { - uploadScreenshot(screenshotFile); - } - else if (uploadStyle == UploadStyle.CLIPBOARD) - { - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - TransferableBufferedImage transferableBufferedImage = new TransferableBufferedImage(screenshot); - clipboard.setContents(transferableBufferedImage, null); - - if (this.notifyWhenTaken) - { - notifier.notify("A screenshot was saved and inserted into your clipboard!", TrayIcon.MessageType.INFO); - } - } - else if (this.notifyWhenTaken) - { - notifier.notify("A screenshot was saved to " + screenshotFile, TrayIcon.MessageType.INFO); - } - } - catch (IOException ex) - { - log.warn("error writing screenshot", ex); - } - } - - /** - * Uploads a screenshot to the Imgur image-hosting service, - * and copies the image link to the clipboard. - * - * @param screenshotFile Image file to upload. - * @throws IOException Thrown if the file cannot be read. - */ - /** - * Uploads a screenshot to the Imgur image-hosting service, - * and copies the image link to the clipboard. - * - * @param screenshotFile Image file to upload. - * @throws IOException Thrown if the file cannot be read. - */ - private void uploadScreenshot(File screenshotFile) throws IOException - { - String json = RuneLiteAPI.GSON.toJson(new ImageUploadRequest(screenshotFile)); - - Request request = new Request.Builder() - .url(IMGUR_IMAGE_UPLOAD_URL) - .addHeader("Authorization", "Client-ID " + IMGUR_CLIENT_ID) - .post(RequestBody.create(JSON, json)) - .build(); - - RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() - { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException ex) - { - log.warn("error uploading screenshot", ex); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException - { - try (InputStream in = response.body().byteStream()) - { - ImageUploadResponse imageUploadResponse = RuneLiteAPI.GSON - .fromJson(new InputStreamReader(in), ImageUploadResponse.class); - - if (imageUploadResponse.isSuccess()) - { - String link = imageUploadResponse.getData().getLink(); - - StringSelection selection = new StringSelection(link); - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - clipboard.setContents(selection, selection); - - if (notifyWhenTaken) - { - notifier.notify("A screenshot was uploaded and inserted into your clipboard!", TrayIcon.MessageType.INFO); - } - } - } - } - }); + imageCapture.takeScreenshot(screenshot, fileName, config.notifyWhenTaken(), config.uploadScreenshot()); } @VisibleForTesting @@ -890,7 +740,6 @@ public class ScreenshotPlugin extends Plugin this.screenshotLevels = config.screenshotLevels(); this.screenshotKingdom = config.screenshotKingdom(); this.screenshotPet = config.screenshotPet(); - this.uploadScreenshot = config.uploadScreenshot(); this.screenshotKills = config.screenshotKills(); this.screenshotBossKills = config.screenshotBossKills(); this.screenshotFriendDeath = config.screenshotFriendDeath(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java index 1eb825f4ec..2398784c02 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java @@ -29,6 +29,7 @@ import java.awt.Color; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("slayer") public interface SlayerConfig extends Config @@ -70,9 +71,10 @@ public interface SlayerConfig extends Config @ConfigItem( position = 4, keyName = "statTimeout", - name = "InfoBox Expiry (minutes)", + name = "InfoBox Expiry", description = "Set the time until the InfoBox expires" ) + @Units(Units.MINUTES) default int statTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java index 9671f29e1a..8a0004a06e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/smelting/SmeltingConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.smelting; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("smelting") public interface SmeltingConfig extends Config @@ -34,9 +35,10 @@ public interface SmeltingConfig extends Config @ConfigItem( position = 1, keyName = "statTimeout", - name = "Reset stats (minutes)", + name = "Reset stats", description = "The time it takes for the current smelting session to be reset" ) + @Units(Units.MINUTES) default int statTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/statusorbs/StatusOrbsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/statusorbs/StatusOrbsConfig.java index 6968024f2f..47c89e1ca7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/statusorbs/StatusOrbsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/statusorbs/StatusOrbsConfig.java @@ -30,6 +30,7 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigTitleSection; import net.runelite.client.config.Title; +import net.runelite.client.config.Units; @ConfigGroup("statusorbs") public interface StatusOrbsConfig extends Config @@ -83,11 +84,12 @@ public interface StatusOrbsConfig extends Config @ConfigItem( keyName = "notifyBeforeHpRegenDuration", - name = "Hitpoint Regen Notification (seconds)", + name = "Hitpoint Regen Notification", description = "Notify approximately when your next hitpoint is about to regen. A value of 0 will disable notification.", titleSection = "hp", position = 4 ) + @Units(Units.SECONDS) default int getNotifyBeforeHpRegenSeconds() { return 0; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/StretchedModeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/StretchedModeConfig.java index fc79768cf2..3e3433d33b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/StretchedModeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stretchedmode/StretchedModeConfig.java @@ -28,6 +28,7 @@ package net.runelite.client.plugins.stretchedmode; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("stretchedmode") public interface StretchedModeConfig extends Config @@ -64,9 +65,10 @@ public interface StretchedModeConfig extends Config @ConfigItem( keyName = "scalingFactor", - name = "Resizable Scaling (%)", + name = "Resizable Scaling", description = "In resizable mode, the game is reduced in size this much before it's stretched." ) + @Units(Units.PERCENT) default int scalingFactor() { return 50; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java index 056217673f..099c7a8f70 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.timetracking; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("timetracking") public interface TimeTrackingConfig extends Config @@ -72,10 +73,11 @@ public interface TimeTrackingConfig extends Config @ConfigItem( keyName = "defaultTimerMinutes", - name = "Default Time (Minutes)", + name = "Default Time", description = "The default time for the timer in minutes", position = 4 ) + @Units(Units.MINUTES) default int defaultTimerMinutes() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/imgur/ImageUploadRequest.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiConfig.java similarity index 71% rename from runelite-client/src/main/java/net/runelite/client/plugins/screenshot/imgur/ImageUploadRequest.java rename to runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiConfig.java index 28c8d4f2f3..5462023f14 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/imgur/ImageUploadRequest.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Lotto + * Copyright (c) 2020, Henry Darnell * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,23 +22,23 @@ * (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.screenshot.imgur; +package net.runelite.client.plugins.wiki; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.Base64; -import lombok.Data; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; -@Data -public class ImageUploadRequest +@ConfigGroup(WikiPlugin.CONFIG_GROUP_KEY) +public interface WikiConfig extends Config { - private final String image; - private final String type; - - public ImageUploadRequest(File imageFile) throws IOException + @ConfigItem( + keyName = "leftClickSearch", + name = "Left Click Search", + description = "Swap left-click on the Wiki button to Search", + position = 1 + ) + default boolean leftClickSearch() { - this.image = Base64.getEncoder().encodeToString(Files.readAllBytes(imageFile.toPath())); - this.type = "base64"; + return false; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java index 868d8b2a83..d0296b24fc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.wiki; +import com.google.inject.Provides; import javax.inject.Inject; import javax.inject.Provider; import lombok.extern.slf4j.Slf4j; @@ -48,7 +49,9 @@ import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetPositionMode; import net.runelite.api.widgets.WidgetType; import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.game.ItemManager; import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; @@ -86,6 +89,9 @@ public class WikiPlugin extends Plugin @Inject private SpriteManager spriteManager; + @Inject + private WikiConfig config; + @Inject private ClientThread clientThread; @@ -102,6 +108,14 @@ public class WikiPlugin extends Plugin private boolean wikiSelected = false; + static final String CONFIG_GROUP_KEY = "wiki"; + + @Provides + WikiConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(WikiConfig.class); + } + @Override public void startUp() { @@ -111,29 +125,32 @@ public class WikiPlugin extends Plugin @Override public void shutDown() { - clientThread.invokeLater(() -> + clientThread.invokeLater(this::removeWidgets); + } + + private void removeWidgets() + { + + Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS); + if (minimapOrbs == null) { - Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS); - if (minimapOrbs == null) - { - return; - } - Widget[] children = minimapOrbs.getChildren(); - if (children == null || children.length < 1) - { - return; - } - children[0] = null; + return; + } + Widget[] children = minimapOrbs.getChildren(); + if (children == null || children.length < 1) + { + return; + } + children[0] = null; - Widget vanilla = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER); - if (vanilla != null) - { - vanilla.setHidden(false); - } + Widget vanilla = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER); + if (vanilla != null) + { + vanilla.setHidden(false); + } - onDeselect(); - client.setSpellSelected(false); - }); + onDeselect(); + client.setSpellSelected(false); } @Subscribe @@ -178,14 +195,17 @@ public class WikiPlugin extends Plugin icon.setSpriteId(SpriteID.WIKI_SELECTED); client.setAllWidgetsAreOpTargetable(true); }); - icon.setAction(5, "Search"); // Start at option 5 so the target op is ontop + + final int searchIndex = config.leftClickSearch() ? 4 : 5; + icon.setAction(searchIndex, "Search"); icon.setOnOpListener((JavaScriptCallback) ev -> { - if (ev.getOp() == 6) + if (ev.getOp() == searchIndex + 1) { openSearchInput(); } }); + // This doesn't always run because we cancel the menuop icon.setOnTargetLeaveListener((JavaScriptCallback) ev -> onDeselect()); icon.revalidate(); @@ -200,6 +220,19 @@ public class WikiPlugin extends Plugin } } + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals(CONFIG_GROUP_KEY)) + { + clientThread.invokeLater(() -> + { + removeWidgets(); + addWidgets(); + }); + } + } + private void onDeselect() { client.setAllWidgetsAreOpTargetable(false); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java index 6b1adb7e9d..65a26893bc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java @@ -30,6 +30,7 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.Range; +import net.runelite.client.config.Units; import net.runelite.client.plugins.wintertodt.config.WintertodtNotifyMode; @ConfigGroup("wintertodt") @@ -66,6 +67,7 @@ public interface WintertodtConfig extends Config @Range( max = 60 ) + @Units(Units.SECONDS) default int roundNotification() { return 5; 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 206f8774e1..7247071a1c 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 @@ -311,8 +311,8 @@ public class WintertodtPlugin extends Plugin chatMessageManager.update(messageNode); client.refreshChat(); - // all actions except woodcutting are interrupted from damage - if (currentActivity != WintertodtActivity.WOODCUTTING) + // all actions except woodcutting and idle are interrupted from damage + if (currentActivity != WintertodtActivity.WOODCUTTING && currentActivity != WintertodtActivity.IDLE) { wasInterrupted = true; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingConfig.java index 74c1f50830..44886ccd9d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.woodcutting; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("woodcutting") public interface WoodcuttingConfig extends Config @@ -34,9 +35,10 @@ public interface WoodcuttingConfig extends Config @ConfigItem( position = 1, keyName = "statTimeout", - name = "Reset stats (minutes)", + name = "Reset stats", description = "Configures the time until statistic is reset. Also configures when tree indicator is hidden" ) + @Units(Units.MINUTES) default int statTimeout() { return 5; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java index ba8eb1dfd8..ab6dc6cc33 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java @@ -29,6 +29,7 @@ import net.runelite.client.config.Alpha; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("xpglobes") public interface XpGlobesConfig extends Config @@ -152,6 +153,7 @@ public interface XpGlobesConfig extends Config description = "Change the stroke width of the progress arc", position = 10 ) + @Units(Units.PIXELS) default int progressArcStrokeWidth() { return 2; @@ -163,6 +165,7 @@ public interface XpGlobesConfig extends Config description = "Change the size of the xp orbs", position = 11 ) + @Units(Units.PIXELS) default int xpOrbSize() { return 40; @@ -174,6 +177,7 @@ public interface XpGlobesConfig extends Config description = "Change the duration the xp orbs are visible", position = 12 ) + @Units(Units.SECONDS) default int xpOrbDuration() { return 10; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java index 9f4cedef32..7a4ccf8406 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java @@ -28,6 +28,7 @@ import lombok.AllArgsConstructor; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Units; @ConfigGroup("xpTracker") public interface XpTrackerConfig extends Config @@ -87,6 +88,7 @@ public interface XpTrackerConfig extends Config name = "Auto pause after", description = "Configures how many minutes passes before pausing a skill while in game and there's no XP, 0 means disabled" ) + @Units(Units.MINUTES) default int pauseSkillAfter() { return 0; diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java index 14df56db2c..f0f635c54e 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetItemOverlay.java @@ -26,6 +26,7 @@ package net.runelite.client.ui.overlay; import java.awt.Dimension; import java.awt.Graphics2D; +import java.awt.Rectangle; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -61,6 +62,8 @@ public abstract class WidgetItemOverlay extends Overlay public Dimension render(Graphics2D graphics) { final List itemWidgets = overlayManager.getItemWidgets(); + final Rectangle originalClipBounds = graphics.getClipBounds(); + Widget curClipParent = null; for (WidgetItem widgetItem : itemWidgets) { Widget widget = widgetItem.getWidget(); @@ -74,6 +77,29 @@ public abstract class WidgetItemOverlay extends Overlay continue; } + Widget parent = widget.getParent(); + Rectangle parentBounds = parent.getBounds(); + Rectangle itemCanvasBounds = widgetItem.getCanvasBounds(); + + boolean shouldClip; + shouldClip = itemCanvasBounds.y < parentBounds.y && itemCanvasBounds.y + itemCanvasBounds.height >= parentBounds.y; + shouldClip |= itemCanvasBounds.y < parentBounds.y + parentBounds.height && itemCanvasBounds.y + itemCanvasBounds.height >= parentBounds.y + parentBounds.height; + shouldClip |= itemCanvasBounds.x < parentBounds.x && (itemCanvasBounds.x + itemCanvasBounds.width) >= parentBounds.x; + shouldClip |= itemCanvasBounds.x < parentBounds.x + parentBounds.width && itemCanvasBounds.x + itemCanvasBounds.width >= parentBounds.x + parentBounds.width; + if (shouldClip) + { + if (curClipParent != parent) + { + graphics.setClip(parentBounds); + curClipParent = parent; + } + } + else if (curClipParent != null && curClipParent != parent) + { + graphics.setClip(originalClipBounds); + curClipParent = null; + } + renderItemOverlay(graphics, widgetItem.getId(), widgetItem); } return null; diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/tooltip/TooltipOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/tooltip/TooltipOverlay.java index da1600450e..f269a797b5 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/tooltip/TooltipOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/tooltip/TooltipOverlay.java @@ -32,6 +32,8 @@ import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Client; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.config.TooltipPositionType; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @@ -41,16 +43,19 @@ import net.runelite.client.ui.overlay.components.TooltipComponent; @Singleton public class TooltipOverlay extends Overlay { - private static final int OFFSET = 24; + private static final int UNDER_OFFSET = 24; + private static final int ABOVE_OFFSET = -20; private static final int PADDING = 2; private final TooltipManager tooltipManager; private final Client client; + private final RuneLiteConfig runeLiteConfig; @Inject - private TooltipOverlay(Client client, TooltipManager tooltipManager) + private TooltipOverlay(Client client, TooltipManager tooltipManager, final RuneLiteConfig runeLiteConfig) { this.client = client; this.tooltipManager = tooltipManager; + this.runeLiteConfig = runeLiteConfig; setPosition(OverlayPosition.TOOLTIP); setPriority(OverlayPriority.HIGHEST); setLayer(OverlayLayer.ALWAYS_ON_TOP); @@ -81,7 +86,8 @@ public class TooltipOverlay extends Overlay { final Rectangle clientCanvasBounds = new Rectangle(client.getRealDimensions()); final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition(); - final Point mousePosition = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY() + OFFSET); + final int offset = runeLiteConfig.tooltipPosition() == TooltipPositionType.UNDER_CURSOR ? UNDER_OFFSET : ABOVE_OFFSET; + final Point mousePosition = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY() + offset); final Rectangle bounds = new Rectangle(getBounds()); bounds.setLocation(mousePosition); @@ -94,7 +100,7 @@ public class TooltipOverlay extends Overlay if (boundsY > clientY) { - graphics.translate(0, -bounds.height - OFFSET); + graphics.translate(0, -bounds.height - offset); } if (boundsX > clientX) @@ -113,7 +119,7 @@ public class TooltipOverlay extends Overlay if (newBounds.contains(mousePosition)) { - mousePosition.move(mouseCanvasPosition.getX(), mouseCanvasPosition.getY() + OFFSET + newBounds.height); + mousePosition.move(mouseCanvasPosition.getX(), mouseCanvasPosition.getY() + offset + newBounds.height); } tooltipComponent.setPosition(mousePosition); diff --git a/runelite-client/src/main/java/net/runelite/client/util/ImageCapture.java b/runelite-client/src/main/java/net/runelite/client/util/ImageCapture.java new file mode 100644 index 0000000000..0331d6a50e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/ImageCapture.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2018, Lotto + * Copyright (c) 2019, Alexsuperfly + * 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.util; + +import java.awt.Toolkit; +import java.awt.TrayIcon; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; +import java.util.EnumSet; +import javax.imageio.ImageIO; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.WorldType; +import net.runelite.client.Notifier; +import static net.runelite.client.RuneLite.SCREENSHOT_DIR; +import net.runelite.client.RuneLiteProperties; +import net.runelite.http.api.RuneLiteAPI; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +@Slf4j +@Singleton +public class ImageCapture +{ + private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); + private static final HttpUrl IMGUR_IMAGE_UPLOAD_URL = HttpUrl.parse("https://api.imgur.com/3/image"); + private static final MediaType JSON = MediaType.parse("application/json"); + + @Inject + private Client client; + + @Inject + private Notifier notifier; + + /** + * Saves a screenshot of the client window to the screenshot folder as a PNG, + * and optionally uploads it to an image-hosting service. + * + * @param screenshot BufferedImage to capture. + * @param fileName Filename to use, without file extension. + * @param notify Send a notification to the system tray when the image is captured. + * @param imageUploadStyle which method to use to upload the screenshot (Imgur or directly to clipboard). + */ + public void takeScreenshot(BufferedImage screenshot, String fileName, boolean notify, ImageUploadStyle imageUploadStyle) + { + if (client.getGameState() == GameState.LOGIN_SCREEN) + { + // Prevent the screenshot from being captured + log.info("Login screenshot prevented"); + return; + } + + File playerFolder; + if (client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) + { + final EnumSet worldTypes = client.getWorldType(); + + String playerDir = client.getLocalPlayer().getName(); + if (worldTypes.contains(WorldType.DEADMAN)) + { + playerDir += "-Deadman"; + } + else if (worldTypes.contains(WorldType.LEAGUE)) + { + playerDir += "-League"; + } + playerFolder = new File(SCREENSHOT_DIR, playerDir); + } + else + { + playerFolder = SCREENSHOT_DIR; + } + + playerFolder.mkdirs(); + + fileName += " " + format(new Date()); + + try + { + File screenshotFile = new File(playerFolder, fileName + ".png"); + + // To make sure that screenshots don't get overwritten, check if file exists, + // and if it does create file with same name and suffix. + int i = 1; + while (screenshotFile.exists()) + { + screenshotFile = new File(playerFolder, fileName + String.format("(%d)", i++) + ".png"); + } + + ImageIO.write(screenshot, "PNG", screenshotFile); + + if (imageUploadStyle == ImageUploadStyle.IMGUR) + { + uploadScreenshot(screenshotFile, notify); + } + else if (imageUploadStyle == ImageUploadStyle.CLIPBOARD) + { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + TransferableBufferedImage transferableBufferedImage = new TransferableBufferedImage(screenshot); + clipboard.setContents(transferableBufferedImage, null); + + if (notify) + { + notifier.notify("A screenshot was saved and inserted into your clipboard!", TrayIcon.MessageType.INFO); + } + } + else if (notify) + { + notifier.notify("A screenshot was saved to " + screenshotFile, TrayIcon.MessageType.INFO); + } + } + catch (IOException ex) + { + log.warn("error writing screenshot", ex); + } + } + + /** + * Uploads a screenshot to the Imgur image-hosting service, + * and copies the image link to the clipboard. + * + * @param screenshotFile Image file to upload. + * @throws IOException Thrown if the file cannot be read. + */ + private void uploadScreenshot(File screenshotFile, boolean notify) throws IOException + { + String json = RuneLiteAPI.GSON.toJson(new ImageUploadRequest(screenshotFile)); + + Request request = new Request.Builder() + .url(IMGUR_IMAGE_UPLOAD_URL) + .addHeader("Authorization", "Client-ID " + RuneLiteProperties.getImgurClientId()) + .post(RequestBody.create(JSON, json)) + .build(); + + RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException ex) + { + log.warn("error uploading screenshot", ex); + } + + @Override + public void onResponse(Call call, Response response) throws IOException + { + try (InputStream in = response.body().byteStream()) + { + ImageUploadResponse imageUploadResponse = RuneLiteAPI.GSON + .fromJson(new InputStreamReader(in), ImageUploadResponse.class); + + if (imageUploadResponse.isSuccess()) + { + String link = imageUploadResponse.getData().getLink(); + + StringSelection selection = new StringSelection(link); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(selection, selection); + + if (notify) + { + notifier.notify("A screenshot was uploaded and inserted into your clipboard!", TrayIcon.MessageType.INFO); + } + } + } + } + }); + } + + private static String format(Date date) + { + synchronized (TIME_FORMAT) + { + return TIME_FORMAT.format(date); + } + } + + @Data + private static class ImageUploadResponse + { + private Data data; + private boolean success; + + @lombok.Data + private static class Data + { + private String link; + } + } + + @Data + private static class ImageUploadRequest + { + private final String image; + private final String type; + + ImageUploadRequest(File imageFile) throws IOException + { + this.image = Base64.getEncoder().encodeToString(Files.readAllBytes(imageFile.toPath())); + this.type = "base64"; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/imgur/ImageUploadResponse.java b/runelite-client/src/main/java/net/runelite/client/util/ImageUploadStyle.java similarity index 82% rename from runelite-client/src/main/java/net/runelite/client/plugins/screenshot/imgur/ImageUploadResponse.java rename to runelite-client/src/main/java/net/runelite/client/util/ImageUploadStyle.java index 820ed2aded..6d5a5c1c98 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/imgur/ImageUploadResponse.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ImageUploadStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Lotto + * Copyright (c) 2019, Alexsuperfly * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,19 +22,12 @@ * (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.screenshot.imgur; -import lombok.Data; +package net.runelite.client.util; -@Data -public class ImageUploadResponse +public enum ImageUploadStyle { - private Data data; - private boolean success; - - @lombok.Data - public static class Data - { - private String link; - } -} + NEITHER, + IMGUR, + CLIPBOARD +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/TransferableBufferedImage.java b/runelite-client/src/main/java/net/runelite/client/util/TransferableBufferedImage.java similarity index 97% rename from runelite-client/src/main/java/net/runelite/client/plugins/screenshot/TransferableBufferedImage.java rename to runelite-client/src/main/java/net/runelite/client/util/TransferableBufferedImage.java index 88499fd77b..d29aace857 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/TransferableBufferedImage.java +++ b/runelite-client/src/main/java/net/runelite/client/util/TransferableBufferedImage.java @@ -24,7 +24,7 @@ * 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.screenshot; +package net.runelite.client.util; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; diff --git a/runelite-client/src/main/resources/open.osrs.properties b/runelite-client/src/main/resources/open.osrs.properties index 946d2db797..b716579265 100644 --- a/runelite-client/src/main/resources/open.osrs.properties +++ b/runelite-client/src/main/resources/open.osrs.properties @@ -12,3 +12,4 @@ runelite.wiki.troubleshooting.link=https://github.com/open-osrs/runelite/wiki/Tr runelite.wiki.building.link=https://github.com/open-osrs/runelite/wiki/Building-with-IntelliJ-IDEA runelite.dnschange.link=https://1.1.1.1/dns/ launcher.version=@launcher.version@ +runelite.imgur.client.id=30d71e5f6860809 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 dff30ddf14..6eeeb1dbbe 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 @@ -52,8 +52,10 @@ 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.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -95,6 +97,9 @@ public class IdleNotifierPluginTest @Mock private NPC randomEvent; + @Mock + private NPC fishingSpot; + @Mock private Player player; @@ -115,6 +120,13 @@ public class IdleNotifierPluginTest when(randomEventComp.getActions()).thenReturn(randomEventActions); when(randomEvent.getDefinition()).thenReturn(randomEventComp); + // Mock Fishing Spot + final String[] fishingSpotActions = new String[] { "Use-rod", "Examine" }; + final NPCDefinition fishingSpotComp = mock(NPCDefinition.class); + when(fishingSpotComp.getActions()).thenReturn(fishingSpotActions); + when(fishingSpot.getDefinition()).thenReturn(fishingSpotComp); + when(fishingSpot.getName()).thenReturn("Fishing spot"); + // Mock player when(player.getName()).thenReturn(PLAYER_NAME); when(player.getAnimation()).thenReturn(AnimationID.IDLE); @@ -271,6 +283,31 @@ public class IdleNotifierPluginTest verify(notifier, times(1)).notify(any()); } + @Test + public void testSendOneNotificationForAnimationAndInteract() + { + when(player.getInteracting()).thenReturn(fishingSpot); + when(player.getAnimation()).thenReturn(AnimationID.FISHING_POLE_CAST); + + AnimationChanged animationChanged = new AnimationChanged(); + animationChanged.setActor(player); + + plugin.onInteractingChanged(new InteractingChanged(player, fishingSpot)); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(GameTick.INSTANCE); + + verify(notifier, never()).notify(anyString()); + + when(player.getAnimation()).thenReturn(AnimationID.IDLE); + lenient().when(player.getInteracting()).thenReturn(null); + + plugin.onAnimationChanged(animationChanged); + plugin.onInteractingChanged(new InteractingChanged(player, null)); + plugin.onGameTick(GameTick.INSTANCE); + + verify(notifier).notify("[" + PLAYER_NAME + "] is now idle!"); + } + @Test public void testSpecRegen() {