From ff6a2fd66028583c4addd76ca761f57a13753c1a Mon Sep 17 00:00:00 2001 From: Ron Young Date: Fri, 1 Feb 2019 10:20:34 -0600 Subject: [PATCH 001/102] TabInterface: remove deprecated widget calls --- .../plugins/banktags/tabs/TabInterface.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java index 148b965043..f9c69940de 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java @@ -64,7 +64,6 @@ import net.runelite.api.SpriteID; import net.runelite.api.VarClientInt; import net.runelite.api.VarClientStr; import net.runelite.api.Varbits; -import net.runelite.api.widgets.WidgetType; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.vars.InputType; @@ -73,6 +72,8 @@ import net.runelite.api.widgets.JavaScriptCallback; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetConfig; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetType; import net.runelite.client.Notifier; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; @@ -111,6 +112,8 @@ public class TabInterface private static final int BUTTON_HEIGHT = 20; private static final int MARGIN = 1; private static final int SCROLL_TICK = 500; + private static final int INCINERATOR_WIDTH = 48; + private static final int INCINERATOR_HEIGHT = 39; private final Client client; private final ClientThread clientThread; @@ -805,17 +808,18 @@ public class TabInterface if (incinerator != null && !incinerator.isHidden()) { - // This is the required way to move incinerator, don't change it! - incinerator.setOriginalHeight(39); - incinerator.setOriginalWidth(48); - incinerator.setRelativeY(itemContainer.getHeight()); - incinerator.revalidate(); + incinerator.setOriginalHeight(INCINERATOR_HEIGHT); + incinerator.setOriginalWidth(INCINERATOR_WIDTH); + incinerator.setOriginalY(INCINERATOR_HEIGHT); Widget child = incinerator.getDynamicChildren()[0]; - child.setHeight(39); - child.setWidth(48); + child.setOriginalHeight(INCINERATOR_HEIGHT); + child.setOriginalWidth(INCINERATOR_WIDTH); + child.setWidthMode(WidgetSizeMode.ABSOLUTE); + child.setHeightMode(WidgetSizeMode.ABSOLUTE); child.setType(WidgetType.GRAPHIC); child.setSpriteId(TabSprites.INCINERATOR.getSpriteId()); + incinerator.revalidate(); bounds.setSize(TAB_WIDTH + MARGIN * 2, height - incinerator.getHeight()); } @@ -900,7 +904,6 @@ public class TabInterface private void updateWidget(Widget t, int y) { t.setOriginalY(y); - t.setRelativeY(y); t.setHidden(y < (bounds.y + BUTTON_HEIGHT + MARGIN) || y > (bounds.y + bounds.height - TAB_HEIGHT - MARGIN - BUTTON_HEIGHT)); t.revalidate(); } From d405b2572edc21a9bb32e65c786e5fb4d0c785bc Mon Sep 17 00:00:00 2001 From: Ron Young Date: Fri, 1 Feb 2019 10:25:39 -0600 Subject: [PATCH 002/102] TabInterface: move icon search into method TabManager: add remove/set icon --- .../plugins/banktags/tabs/TabInterface.java | 23 +++++++------------ .../plugins/banktags/tabs/TabManager.java | 11 +++++++++ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java index f9c69940de..f141a0514c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java @@ -76,13 +76,10 @@ import net.runelite.api.widgets.WidgetSizeMode; import net.runelite.api.widgets.WidgetType; import net.runelite.client.Notifier; import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.plugins.banktags.BankTagsConfig; import net.runelite.client.plugins.banktags.BankTagsPlugin; -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_SEARCH; import static net.runelite.client.plugins.banktags.BankTagsPlugin.VAR_TAG_SUFFIX; import net.runelite.client.plugins.banktags.TagManager; @@ -118,7 +115,6 @@ public class TabInterface private final Client client; private final ClientThread clientThread; private final ItemManager itemManager; - private final ConfigManager configManager; private final TagManager tagManager; private final TabManager tabManager; private final ChatboxPanelManager chatboxPanelManager; @@ -151,7 +147,6 @@ public class TabInterface final Client client, final ClientThread clientThread, final ItemManager itemManager, - final ConfigManager configManager, final TagManager tagManager, final TabManager tabManager, final ChatboxPanelManager chatboxPanelManager, @@ -162,7 +157,6 @@ public class TabInterface this.client = client; this.clientThread = clientThread; this.itemManager = itemManager; - this.configManager = configManager; this.tagManager = tagManager; this.tabManager = tabManager; this.chatboxPanelManager = chatboxPanelManager; @@ -214,7 +208,7 @@ public class TabInterface if (config.rememberTab() && !Strings.isNullOrEmpty(config.tab())) { - openTag(TAG_SEARCH + config.tab()); + openTag(config.tab()); } } @@ -242,7 +236,7 @@ public class TabInterface tagManager.addTag(item, activeTab.getTag(), false); } - openTag(TAG_SEARCH + activeTab.getTag()); + openTag(activeTab.getTag()); } return; @@ -295,7 +289,7 @@ public class TabInterface final Iterator dataIter = Text.fromCSV(dataString).iterator(); final String name = dataIter.next(); final String icon = dataIter.next(); - configManager.setConfiguration(CONFIG_GROUP, ICON_SEARCH + name, icon); + tabManager.setIcon(name, icon); while (dataIter.hasNext()) { @@ -553,7 +547,7 @@ public class TabInterface int itemId = itemManager.canonicalize(item.getId()); iconToSet.setIconItemId(itemId); iconToSet.getIcon().setItemId(itemId); - configManager.setConfiguration(CONFIG_GROUP, ICON_SEARCH + iconToSet.getTag(), itemId + ""); + tabManager.setIcon(iconToSet.getTag(), itemId + ""); event.consume(); } @@ -600,7 +594,7 @@ public class TabInterface { if (activeTab != null && tags.contains(activeTab.getTag())) { - openTag(TAG_SEARCH + activeTab.getTag()); + openTag(activeTab.getTag()); } } @@ -715,7 +709,6 @@ public class TabInterface } tabManager.remove(tag); - configManager.unsetConfiguration(CONFIG_GROUP, ICON_SEARCH + tag); tabManager.save(); updateBounds(); @@ -916,10 +909,10 @@ public class TabInterface return itemManager.getItemComposition(item.getId()); } - private void openTag(String tag) + private void openTag(final String tag) { - bankSearch.search(InputType.SEARCH, tag, true); - activateTab(tabManager.find(tag.substring(TAG_SEARCH.length()))); + bankSearch.search(InputType.SEARCH, TAG_SEARCH + tag, true); + activateTab(tabManager.find(tag)); // When tab is selected with search window open, the search window closes but the search button // stays highlighted, this solves that issue 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 3f1430dd7c..e1995a5095 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 @@ -115,6 +115,7 @@ class TabManager { tagTab.setHidden(true); tabs.remove(tagTab); + removeIcon(tag); } } @@ -124,6 +125,16 @@ class TabManager configManager.setConfiguration(CONFIG_GROUP, TAG_TABS_CONFIG, tags); } + void removeIcon(final String tag) + { + configManager.unsetConfiguration(CONFIG_GROUP, ICON_SEARCH + Text.standardize(tag)); + } + + void setIcon(final String tag, final String icon) + { + configManager.setConfiguration(CONFIG_GROUP, ICON_SEARCH + Text.standardize(tag), icon); + } + int size() { return tabs.size(); From 91d5d32d2ee875c0e183a780fa494b5d2e60d38f Mon Sep 17 00:00:00 2001 From: Tanner Chauncy <45087016+dog-of-wisdom@users.noreply.github.com> Date: Fri, 1 Feb 2019 10:26:39 -0600 Subject: [PATCH 003/102] banktags: add tag tab renaming --- .../client/plugins/banktags/TagManager.java | 14 ++++ .../plugins/banktags/tabs/MenuIndexes.java | 1 + .../plugins/banktags/tabs/TabInterface.java | 64 ++++++++++++++++++- .../client/plugins/banktags/tabs/TagTab.java | 2 +- 4 files changed, 78 insertions(+), 3 deletions(-) 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 c20974758d..c1d5ff8c11 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 @@ -167,6 +167,20 @@ public class TagManager } } + public void renameTag(String oldTag, String newTag) + { + List items = getItemsForTag(Text.standardize(oldTag)); + items.forEach(id -> + { + Collection tags = getTags(id, id < 0); + + tags.remove(Text.standardize(oldTag)); + tags.add(Text.standardize(newTag)); + + setTags(id, tags, id < 0); + }); + } + private int getItemId(int itemId, boolean variation) { itemId = Math.abs(itemId); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java index afa8f6e276..51e179b143 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/MenuIndexes.java @@ -39,5 +39,6 @@ class MenuIndexes static final int CHANGE_ICON = 3; static final int DELETE_TAB = 4; static final int EXPORT_TAB = 5; + static final int RENAME_TAB = 6; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java index f141a0514c..2daaf0f5c6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java @@ -100,6 +100,7 @@ public class TabInterface private static final String EXPORT_TAB = "Export tag tab"; private static final String IMPORT_TAB = "Import tag tab"; private static final String VIEW_TAB = "View tag tab"; + private static final String RENAME_TAB = "Rename tag tab"; private static final String CHANGE_ICON = "Change icon"; private static final String REMOVE_TAG = "Remove-tag"; private static final String TAG_GEAR = "Tag-equipment"; @@ -303,7 +304,7 @@ public class TabInterface if (activeTab != null && name.equals(activeTab.getTag())) { - openTag(TAG_SEARCH + activeTab.getTag()); + openTag(activeTab.getTag()); } notifier.notify("Tag tab " + name + " has been imported from your clipboard!"); @@ -333,7 +334,7 @@ public class TabInterface } else { - openTag(TAG_SEARCH + Text.removeTags(clicked.getName())); + openTag(Text.removeTags(clicked.getName())); } client.playSoundEffect(SoundEffectID.UI_BOOP); @@ -370,6 +371,10 @@ public class TabInterface Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); notifier.notify("Tag tab " + tagTab.getTag() + " has been copied to your clipboard!"); break; + case Tab.RENAME_TAB: + String renameTarget = Text.standardize(event.getOpbase()); + renameTab(renameTarget); + break; } } @@ -680,6 +685,7 @@ public class TabInterface btn.setAction(2, CHANGE_ICON); btn.setAction(3, REMOVE_TAB); btn.setAction(4, EXPORT_TAB); + btn.setAction(5, RENAME_TAB); btn.setOnOpListener((JavaScriptCallback) this::handleTagTab); tagTab.setBackground(btn); } @@ -715,6 +721,60 @@ public class TabInterface scrollTab(0); } + private void renameTab(String oldTag) + { + chatboxPanelManager.openTextInput("Enter new tag name for tag \"" + oldTag + "\":") + .onDone((newTag) -> clientThread.invoke(() -> + { + if (!Strings.isNullOrEmpty(newTag) && !newTag.equalsIgnoreCase(oldTag)) + { + if (tabManager.find(newTag) == null) + { + TagTab tagTab = tabManager.find(oldTag); + tagTab.setTag(newTag); + + final String coloredName = ColorUtil.wrapWithColorTag(newTag, HILIGHT_COLOR); + tagTab.getIcon().setName(coloredName); + tagTab.getBackground().setName(coloredName); + + tabManager.removeIcon(oldTag); + tabManager.setIcon(newTag, tagTab.getIconItemId() + ""); + + tabManager.save(); + tagManager.renameTag(oldTag, newTag); + + if (activeTab != null && activeTab.equals(tagTab)) + { + openTag(newTag); + } + } + else + { + chatboxPanelManager.openTextMenuInput("The specified bank tag already exists.") + .option("1. Merge into existing tag \"" + newTag + "\".", () -> + clientThread.invoke(() -> + { + tagManager.renameTag(oldTag, newTag); + final String activeTag = activeTab != null ? activeTab.getTag() : ""; + deleteTab(oldTag); + + if (activeTag.equals(oldTag)) + { + openTag(newTag); + } + }) + ) + .option("2. Choose a different name.", () -> + clientThread.invoke(() -> + renameTab(oldTag)) + ) + .build(); + } + } + })) + .build(); + } + private void scrollTick(int direction) { // This ensures that dragging on scroll buttons do not scrolls too fast diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java index d3d417f465..004e5f45ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TagTab.java @@ -33,7 +33,7 @@ import net.runelite.api.widgets.Widget; @EqualsAndHashCode(of = "tag") class TagTab { - private final String tag; + private String tag; private int iconItemId; private Widget background; private Widget icon; From 8d821abfa4c252859e8b9c90f518ffd7bf0e5449 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Mon, 4 Feb 2019 13:15:21 +0000 Subject: [PATCH 004/102] Add .getBounds() to LayoutableRenderableEntity Signed-off-by: Tomas Slusny --- .../screenmarkers/ScreenMarkerRenderable.java | 5 ++++ .../ui/overlay/components/ImageComponent.java | 11 +++++++- .../overlay/components/InfoBoxComponent.java | 17 ++++++++----- .../LayoutableRenderableEntity.java | 2 ++ .../ui/overlay/components/LineComponent.java | 25 +++++++++++++------ .../ui/overlay/components/PanelComponent.java | 23 +++++++++-------- .../components/ProgressBarComponent.java | 19 +++++++++----- .../ui/overlay/components/TitleComponent.java | 21 ++++++++++++---- 8 files changed, 88 insertions(+), 35 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerRenderable.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerRenderable.java index 0d44e01345..95b2da1207 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerRenderable.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerRenderable.java @@ -28,6 +28,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.Rectangle; import java.awt.Stroke; import lombok.AccessLevel; import lombok.Getter; @@ -55,6 +56,9 @@ public class ScreenMarkerRenderable implements LayoutableRenderableEntity @Setter(AccessLevel.PACKAGE) private Stroke stroke; + @Getter + private final Rectangle bounds = new Rectangle(); + @Override public Dimension render(Graphics2D graphics) { @@ -72,6 +76,7 @@ public class ScreenMarkerRenderable implements LayoutableRenderableEntity graphics.setColor(color); graphics.setStroke(stroke); graphics.drawRect(offset, offset, width - thickness, height - thickness); + bounds.setSize(preferredSize); return preferredSize; } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java index 05ddc35395..39ec431697 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java @@ -27,7 +27,9 @@ package net.runelite.client.ui.overlay.components; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.Rectangle; import java.awt.image.BufferedImage; +import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; @@ -36,6 +38,10 @@ import lombok.Setter; public class ImageComponent implements LayoutableRenderableEntity { private final BufferedImage image; + + @Getter + private final Rectangle bounds = new Rectangle(); + private Point preferredLocation = new Point(); @Override @@ -47,7 +53,10 @@ public class ImageComponent implements LayoutableRenderableEntity } graphics.drawImage(image, preferredLocation.x, preferredLocation.y, null); - return new Dimension(image.getWidth(), image.getHeight()); + final Dimension dimension = new Dimension(image.getWidth(), image.getHeight()); + bounds.setLocation(preferredLocation); + bounds.setSize(dimension); + return dimension; } @Override diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java index ca6c55d3be..af54d78296 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java @@ -50,6 +50,9 @@ public class InfoBoxComponent implements LayoutableRenderableEntity @Setter private Dimension preferredSize = new Dimension(DEFAULT_SIZE, DEFAULT_SIZE); + @Getter + private final Rectangle bounds = new Rectangle(); + private String text; private Color color = Color.WHITE; private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; @@ -64,12 +67,14 @@ public class InfoBoxComponent implements LayoutableRenderableEntity } graphics.setFont(getSize() < DEFAULT_SIZE ? FontManager.getRunescapeSmallFont() : FontManager.getRunescapeFont()); - graphics.translate(preferredLocation.x, preferredLocation.y); + + final int baseX = preferredLocation.x; + final int baseY = preferredLocation.y; // Calculate dimensions final FontMetrics metrics = graphics.getFontMetrics(); final int size = getSize(); - final Rectangle bounds = new Rectangle(size, size); + final Rectangle bounds = new Rectangle(baseX, baseY, size, size); // Render background final BackgroundComponent backgroundComponent = new BackgroundComponent(); @@ -80,18 +85,18 @@ public class InfoBoxComponent implements LayoutableRenderableEntity // Render image graphics.drawImage( image, - (size - image.getWidth(null)) / 2, - (size - image.getHeight(null)) / 2, + baseX + (size - image.getWidth(null)) / 2, + baseY + (size - image.getHeight(null)) / 2, null); // Render caption final TextComponent textComponent = new TextComponent(); textComponent.setColor(color); textComponent.setText(text); - textComponent.setPosition(new Point(((size - metrics.stringWidth(text)) / 2), size - SEPARATOR)); + textComponent.setPosition(new Point(baseX + ((size - metrics.stringWidth(text)) / 2), baseY + size - SEPARATOR)); textComponent.render(graphics); - graphics.translate(-preferredLocation.x, -preferredLocation.y); + this.bounds.setBounds(bounds); return bounds.getSize(); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java index ba7f1e7717..7a736686d0 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java @@ -26,10 +26,12 @@ package net.runelite.client.ui.overlay.components; import java.awt.Dimension; import java.awt.Point; +import java.awt.Rectangle; import net.runelite.client.ui.overlay.RenderableEntity; public interface LayoutableRenderableEntity extends RenderableEntity { + Rectangle getBounds(); void setPreferredLocation(Point position); void setPreferredSize(Dimension dimension); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java index efe7f407a6..f6c2f5e77c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java @@ -31,7 +31,9 @@ import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.Rectangle; import lombok.Builder; +import lombok.Getter; import lombok.Setter; @Setter @@ -53,17 +55,22 @@ public class LineComponent implements LayoutableRenderableEntity @Builder.Default private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); + @Builder.Default + @Getter + private final Rectangle bounds = new Rectangle(); + @Override public Dimension render(Graphics2D graphics) { - graphics.translate(preferredLocation.x, preferredLocation.y); // Prevent NPEs final String left = MoreObjects.firstNonNull(this.left, ""); final String right = MoreObjects.firstNonNull(this.right, ""); final FontMetrics metrics = graphics.getFontMetrics(); - int x = 0; - int y = metrics.getHeight(); + final int baseX = preferredLocation.x; + final int baseY = preferredLocation.y + metrics.getHeight(); + int x = baseX; + int y = baseY; final int leftFullWidth = getLineWidth(left, metrics); final int rightFullWidth = getLineWidth(right, metrics); @@ -112,8 +119,10 @@ public class LineComponent implements LayoutableRenderableEntity y += metrics.getHeight(); } - graphics.translate(-preferredLocation.x, -preferredLocation.y); - return new Dimension(preferredSize.width, y - metrics.getHeight()); + final Dimension dimension = new Dimension(preferredSize.width, y - baseY); + bounds.setLocation(preferredLocation); + bounds.setSize(dimension); + return dimension; } final TextComponent leftLineComponent = new TextComponent(); @@ -129,8 +138,10 @@ public class LineComponent implements LayoutableRenderableEntity rightLineComponent.render(graphics); y += metrics.getHeight(); - graphics.translate(-preferredLocation.x, -preferredLocation.y); - return new Dimension(preferredSize.width, y - metrics.getHeight()); + final Dimension dimension = new Dimension(preferredSize.width, y - baseY); + bounds.setLocation(preferredLocation); + bounds.setSize(dimension); + return dimension; } private static int getLineWidth(final String line, final FontMetrics metrics) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java index 974ec37240..5ea81f2006 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java @@ -43,9 +43,8 @@ public class PanelComponent implements LayoutableRenderableEntity VERTICAL; } - @Setter - @Nullable - private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; + @Getter + private final Rectangle bounds = new Rectangle(); @Setter private Point preferredLocation = new Point(); @@ -53,8 +52,12 @@ public class PanelComponent implements LayoutableRenderableEntity @Setter private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); + @Setter + @Nullable + private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; + @Getter - private List children = new ArrayList<>(); + private final List children = new ArrayList<>(); @Setter private Orientation orientation = Orientation.VERTICAL; @@ -82,8 +85,6 @@ public class PanelComponent implements LayoutableRenderableEntity return null; } - graphics.translate(preferredLocation.x, preferredLocation.y); - // Calculate panel dimension final Dimension dimension = new Dimension( border.x + childDimensions.width + border.width, @@ -93,14 +94,14 @@ public class PanelComponent implements LayoutableRenderableEntity if (backgroundColor != null) { final BackgroundComponent backgroundComponent = new BackgroundComponent(); - backgroundComponent.setRectangle(new Rectangle(dimension)); + backgroundComponent.setRectangle(new Rectangle(preferredLocation, dimension)); backgroundComponent.setBackgroundColor(backgroundColor); backgroundComponent.render(graphics); } // Offset children - final int baseX = border.x; - final int baseY = border.y; + final int baseX = preferredLocation.x + border.x; + final int baseY = preferredLocation.y + border.y; int width = 0; int height = 0; int x = baseX; @@ -174,7 +175,9 @@ public class PanelComponent implements LayoutableRenderableEntity // Cache children bounds childDimensions.setSize(totalWidth, totalHeight); - graphics.translate(-preferredLocation.x, -preferredLocation.y); + // Cache bounds + bounds.setLocation(preferredLocation); + bounds.setSize(dimension); return dimension; } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java index 0db182739a..ba4634deec 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java @@ -29,7 +29,9 @@ import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.Rectangle; import java.text.DecimalFormat; +import lombok.Getter; import lombok.Setter; @Setter @@ -43,6 +45,7 @@ public class ProgressBarComponent implements LayoutableRenderableEntity private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.0"); private static final DecimalFormat DECIMAL_FORMAT_ABS = new DecimalFormat("#0"); + private long minimum; private long maximum = 100; private double value; @@ -53,14 +56,16 @@ public class ProgressBarComponent implements LayoutableRenderableEntity private Point preferredLocation = new Point(); private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 16); + @Getter + private final Rectangle bounds = new Rectangle(); + @Override public Dimension render(Graphics2D graphics) { - graphics.translate(preferredLocation.x, preferredLocation.y); final FontMetrics metrics = graphics.getFontMetrics(); - final int barX = 0; - final int barY = 0; + final int barX = preferredLocation.x; + final int barY = preferredLocation.y; final long span = maximum - minimum; final double currentValue = value - minimum; @@ -82,7 +87,7 @@ public class ProgressBarComponent implements LayoutableRenderableEntity final int progressTextY = barY + ((height - metrics.getHeight()) / 2) + metrics.getHeight(); final int progressFill = (int) (width * Math.min(1, pc)); - //Draw bar + // Draw bar graphics.setColor(backgroundColor); graphics.fillRect(barX, barY, width, height); graphics.setColor(foregroundColor); @@ -94,7 +99,9 @@ public class ProgressBarComponent implements LayoutableRenderableEntity textComponent.setText(textToWrite); textComponent.render(graphics); - graphics.translate(-preferredLocation.x, -preferredLocation.y); - return new Dimension(width, height); + final Dimension dimension = new Dimension(width, height); + bounds.setLocation(preferredLocation); + bounds.setSize(dimension); + return dimension; } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TitleComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TitleComponent.java index 093d596fe9..fa4c9bc3bb 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TitleComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TitleComponent.java @@ -29,7 +29,9 @@ import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.Rectangle; import lombok.Builder; +import lombok.Getter; import lombok.Setter; @Setter @@ -47,17 +49,26 @@ public class TitleComponent implements LayoutableRenderableEntity @Builder.Default private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); + @Builder.Default + @Getter + private final Rectangle bounds = new Rectangle(); + @Override public Dimension render(Graphics2D graphics) { - graphics.translate(preferredLocation.x, preferredLocation.y); + final int baseX = preferredLocation.x; + final int baseY = preferredLocation.y; final FontMetrics metrics = graphics.getFontMetrics(); final TextComponent titleComponent = new TextComponent(); titleComponent.setText(text); titleComponent.setColor(color); - titleComponent.setPosition(new Point((preferredSize.width - metrics.stringWidth(text)) / 2, metrics.getHeight())); - final Dimension dimension = titleComponent.render(graphics); - graphics.translate(-preferredLocation.x, -preferredLocation.y); - return new Dimension(preferredSize.width, dimension.height); + titleComponent.setPosition(new Point( + baseX + ((preferredSize.width - metrics.stringWidth(text)) / 2), + baseY + metrics.getHeight())); + final Dimension rendered = titleComponent.render(graphics); + final Dimension dimension = new Dimension(preferredSize.width, rendered.height); + bounds.setLocation(preferredLocation); + bounds.setSize(dimension); + return dimension; } } From a536c9e775e8433cf84b365f4bb31e52a8633379 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Mon, 4 Feb 2019 20:54:40 +0100 Subject: [PATCH 005/102] Use new LayoutableRenderableEntity#getBounds in InfoboxOverlay Signed-off-by: Tomas Slusny --- .../ui/overlay/components/InfoBoxComponent.java | 13 ++----------- .../client/ui/overlay/infobox/InfoBoxOverlay.java | 10 ++-------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java index af54d78296..be055179bb 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java @@ -44,15 +44,11 @@ public class InfoBoxComponent implements LayoutableRenderableEntity @Getter private String tooltip; - @Getter - private Point preferredLocation = new Point(); - - @Setter - private Dimension preferredSize = new Dimension(DEFAULT_SIZE, DEFAULT_SIZE); - @Getter private final Rectangle bounds = new Rectangle(); + private Point preferredLocation = new Point(); + private Dimension preferredSize = new Dimension(DEFAULT_SIZE, DEFAULT_SIZE); private String text; private Color color = Color.WHITE; private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; @@ -100,11 +96,6 @@ public class InfoBoxComponent implements LayoutableRenderableEntity return bounds.getSize(); } - public Dimension getPreferredSize() - { - return new Dimension(getSize(), getSize()); - } - private int getSize() { return Math.max(preferredSize.width, preferredSize.height); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java index 15165a4edb..fecd9f1090 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java @@ -37,7 +37,6 @@ import net.runelite.api.Client; import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.InfoBoxComponent; import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -116,15 +115,10 @@ public class InfoBoxOverlay extends Overlay if (!Strings.isNullOrEmpty(component.getTooltip())) { - final Rectangle intersectionRectangle = new Rectangle(component.getPreferredLocation(), component.getPreferredSize()); - - // Move the intersection based on overlay position + // Create intersection rectangle + final Rectangle intersectionRectangle = new Rectangle(component.getBounds()); intersectionRectangle.translate(getBounds().x, getBounds().y); - // Move the intersection based on overlay "orientation" - final Point transformed = OverlayUtil.transformPosition(getPosition(), intersectionRectangle.getSize()); - intersectionRectangle.translate(transformed.x, transformed.y); - if (intersectionRectangle.contains(mouse)) { tooltipManager.add(new Tooltip(component.getTooltip())); From b000818393c026f73ac7e473f143817446b30b4d Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Thu, 7 Feb 2019 23:09:56 -0800 Subject: [PATCH 006/102] item stats: Represent boost data as ints Particularly since exposing StatBoosts and StatChanges through the item stats service, it has become evident that storing stat change data as a human-readable string is not especially useful for consumers of the service as they must handle string processing, particularly for special cases such as range stat boosts or spicy stews. This patch changes StatChanges to expose their relative, theoretical, and absolute change values as ints instead for ease of consumption, and adds methods to get human-readable versions of these relative and theoretical values for display purposes. Fixes runelite/runelite#6594 --- .../plugins/itemstats/ItemStatOverlay.java | 4 +- .../plugins/itemstats/RangeStatBoost.java | 34 ++--- .../plugins/itemstats/RangeStatChange.java | 117 ++++++++++++++++++ .../client/plugins/itemstats/StatBoost.java | 7 +- .../client/plugins/itemstats/StatChange.java | 35 +++++- .../plugins/itemstats/special/SpicyStew.java | 12 +- .../plugins/statusbars/StatusBarsOverlay.java | 20 +-- 7 files changed, 173 insertions(+), 56 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatChange.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java index 986321e966..73113bd0ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatOverlay.java @@ -258,7 +258,7 @@ public class ItemStatOverlay extends Overlay if (config.relative()) { - b.append(c.getRelative()); + b.append(c.getFormattedRelative()); } if (config.theoretical()) @@ -267,7 +267,7 @@ public class ItemStatOverlay extends Overlay { b.append("/"); } - b.append(c.getTheoretical()); + b.append(c.getFormattedTheoretical()); } if (config.absolute() && (config.relative() || config.theoretical())) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatBoost.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatBoost.java index abe47cea1c..13011b9f6a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatBoost.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatBoost.java @@ -42,33 +42,21 @@ public class RangeStatBoost extends SingleEffect @Override public StatChange effect(Client client) { - final StatChange a = this.a.effect(client); - final StatChange b = this.b.effect(client); + final StatChange changeA = this.a.effect(client); + final StatChange changeB = this.b.effect(client); - final StatChange r = new StatChange(); - r.setAbsolute(concat(a.getAbsolute(), b.getAbsolute())); - r.setRelative(concat(a.getRelative(), b.getRelative())); - r.setTheoretical(concat(a.getTheoretical(), b.getTheoretical())); - r.setStat(a.getStat()); + final RangeStatChange r = new RangeStatChange(); + r.setMinAbsolute(Math.min(changeA.getAbsolute(), changeB.getAbsolute())); + r.setAbsolute(Math.max(changeA.getAbsolute(), changeB.getAbsolute())); + r.setMinRelative(Math.min(changeA.getRelative(), changeB.getRelative())); + r.setRelative(Math.max(changeA.getRelative(), changeB.getRelative())); + r.setMinTheoretical(Math.min(changeA.getTheoretical(), changeB.getTheoretical())); + r.setTheoretical(Math.max(changeA.getTheoretical(), changeB.getTheoretical())); + r.setStat(changeA.getStat()); - final int avg = (a.getPositivity().ordinal() + b.getPositivity().ordinal()) / 2; + final int avg = (changeA.getPositivity().ordinal() + changeB.getPositivity().ordinal()) / 2; r.setPositivity(Positivity.values()[avg]); return r; } - - private String concat(String a, String b) - { - // If they share a operator, strip b's duplicate - if (a.length() > 1 && b.length() > 1) - { - final char a0 = a.charAt(0); - if ((a0 == '+' || a0 == '-' || a0 == '±') && b.charAt(0) == a0) - { - b = b.substring(1); - } - } - - return a + "~" + b; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatChange.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatChange.java new file mode 100644 index 0000000000..90b614bf10 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/RangeStatChange.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016-2019, Jordan Atwood + * 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.plugins.itemstats; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * A stat change which can result in different magnitudes of change to the stat + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class RangeStatChange extends StatChange +{ + /** + * Minimum relative change that will occur if the stat boost is applied now. + * In this class, {@code relative} is representative of the maximum relative change that will + * occur. + */ + private int minRelative; + + /** + * Minimum theoretical change that can occur before boost cap is enforced. + * In this class, {@code theoretical} is representative of the maximum theoretical change that + * will occur. + */ + private int minTheoretical; + + /** + * Minimum absolute total of the stat after applying the boost. + * In this class, {@code absolute} is representative of the maximum absolute change that will + * occur. + */ + private int minAbsolute; + + /** + * Returns a human-readable formatted relative boost. + * Should be the boost range in the format "±N" (for minimum -N and maximum +N values), + * "+MIN~MAX" (for minimum and maximum values of the same sign), + * "-MIN~+MAX" (for negative minimum and positive maximum values), or + * "+MAX" (for equal minimum and maximum values). + * + * @return The formatted relative boost amount + */ + @Override + public String getFormattedRelative() + { + return concat(minRelative, getRelative()); + } + + /** + * Returns a human-readable formatted theoretical boost. + * Should be the boost range in the format "±N" (for minimum -N and maximum +N values), + * "+MIN~MAX" (for minimum and maximum values of the same sign), + * "-MIN~+MAX" (for negative minimum and positive maximum values), or + * "+MAX" (for equal minimum and maximum values). + * + * @return The formatted theoretical boost amount + */ + @Override + public String getFormattedTheoretical() + { + return concat(minTheoretical, getTheoretical()); + } + + private static String concat(int changeA, int changeB) + { + if (changeA == changeB) + { + return formatBoost(changeA); + } + else if (changeA * -1 == changeB) + { + return "±" + Math.abs(changeA); + } + + final StringBuilder sb = new StringBuilder(); + + sb.append(String.format("%+d", changeA)); + sb.append('~'); + + // If they share a operator, strip b's duplicate + if (changeA < 0 && changeB < 0 + || changeA >= 0 && changeB >= 0) + { + sb.append(Math.abs(changeB)); + } + else + { + sb.append(String.format("%+d", changeB)); + } + + return sb.toString(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java index 1bc59d7412..cc5f7797f2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatBoost.java @@ -88,10 +88,9 @@ public abstract class StatBoost extends SingleEffect { out.setPositivity(Positivity.WORSE); } - out.setAbsolute(Integer.toString(newValue)); - out.setRelative(String.format("%+d", delta)); - out.setTheoretical(String.format("%+d", calcedDelta)); + out.setAbsolute(newValue); + out.setRelative(delta); + out.setTheoretical(calcedDelta); return out; } - } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatChange.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatChange.java index 3157748083..e9453984f4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatChange.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/StatChange.java @@ -40,23 +40,48 @@ public class StatChange /** * Relative change that will occur if the stat boost is applied now. - * Should be a number prefixed by "+" or "-". */ - private String relative; + private int relative; /** * Theoretical change that can occur before boost cap is enforced. - * Should be a number prefixed by "+" or "-". */ - private String theoretical; + private int theoretical; /** * Absolute total of the stat after applying the boost. */ - private String absolute; + private int absolute; /** * How beneficial this stat boost will be to the player. */ private Positivity positivity; + + /** + * Returns a human-readable formatted relative boost. + * Should be the boost amount prefixed by "+" or "-". + * + * @return The formatted relative boost amount + */ + public String getFormattedRelative() + { + return formatBoost(relative); + } + + /** + * Returns a human-readable formatted theoretical boost. + * Should be the boost amount prefixed by "+" or "-". + * + * @return The formatted theoretical boost amount + */ + public String getFormattedTheoretical() + { + return formatBoost(theoretical); + } + + static String formatBoost(int boost) + { + return String.format("%+d", boost); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java index 8dab7fd601..7eee548751 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java @@ -132,11 +132,14 @@ public class SpicyStew implements Effect int currentBoost = currentValue - currentBase; // Can be negative int spiceBoostCapped = (currentBoost <= 0) ? spiceBoost : Math.max(0, spiceBoost - currentBoost); - StatChange change = new StatChange(); + final RangeStatChange change = new RangeStatChange(); change.setStat(stat); - change.setRelative("±" + spiceBoostCapped); - change.setTheoretical("±" + spiceBoost); - change.setAbsolute(String.valueOf(stat.getValue(client) + spiceBoostCapped)); + change.setMinRelative(-spiceBoost); + change.setRelative(spiceBoostCapped); + change.setMinTheoretical(-spiceBoost); + change.setTheoretical(spiceBoost); + change.setMinAbsolute(Math.max(-spiceBoost, -currentValue)); + change.setAbsolute(stat.getValue(client) + spiceBoostCapped); Positivity positivity; if (spiceBoostCapped == 0) @@ -155,5 +158,4 @@ public class SpicyStew implements Effect return change; } - } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsOverlay.java index 0deb55c2ab..ada42169ad 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsOverlay.java @@ -24,8 +24,6 @@ */ package net.runelite.client.plugins.statusbars; -import com.google.common.base.Strings; -import com.google.common.primitives.Ints; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; @@ -196,28 +194,16 @@ class StatusBarsOverlay extends Overlay for (final StatChange c : statsChanges.getStatChanges()) { - final String strVar = c.getTheoretical(); - - if (Strings.isNullOrEmpty(strVar)) - { - continue; - } - - final Integer value = Ints.tryParse(strVar.startsWith("+") ? strVar.substring(1) : strVar); - - if (value == null) - { - continue; - } + final int theoreticalBoost = c.getTheoretical(); if (c.getStat().getName().equals(Skill.HITPOINTS.getName())) { - foodHealValue = value; + foodHealValue = theoreticalBoost; } if (c.getStat().getName().equals(Skill.PRAYER.getName())) { - prayerHealValue = value; + prayerHealValue = theoreticalBoost; } if (foodHealValue != 0 && prayerHealValue != 0) From 860aa89a4d12a0f73843796b6bf623759dae70fa Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 9 Feb 2019 11:41:30 -0500 Subject: [PATCH 007/102] http api: rename OSB ge classes with OSB prefix --- ...andExchangeClient.java => OSBGrandExchangeClient.java} | 6 +++--- ...andExchangeResult.java => OSBGrandExchangeResult.java} | 2 +- ...ngeController.java => OSBGrandExchangeController.java} | 6 +++--- ...dExchangeService.java => OSBGrandExchangeService.java} | 4 ++-- .../client/plugins/grandexchange/GrandExchangePlugin.java | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) rename http-api/src/main/java/net/runelite/http/api/osbuddy/{GrandExchangeClient.java => OSBGrandExchangeClient.java} (92%) rename http-api/src/main/java/net/runelite/http/api/osbuddy/{GrandExchangeResult.java => OSBGrandExchangeResult.java} (97%) rename http-service/src/main/java/net/runelite/http/service/osbuddy/{GrandExchangeController.java => OSBGrandExchangeController.java} (92%) rename http-service/src/main/java/net/runelite/http/service/osbuddy/{GrandExchangeService.java => OSBGrandExchangeService.java} (97%) diff --git a/http-api/src/main/java/net/runelite/http/api/osbuddy/GrandExchangeClient.java b/http-api/src/main/java/net/runelite/http/api/osbuddy/OSBGrandExchangeClient.java similarity index 92% rename from http-api/src/main/java/net/runelite/http/api/osbuddy/GrandExchangeClient.java rename to http-api/src/main/java/net/runelite/http/api/osbuddy/OSBGrandExchangeClient.java index d80a739d29..ffdfad2035 100644 --- a/http-api/src/main/java/net/runelite/http/api/osbuddy/GrandExchangeClient.java +++ b/http-api/src/main/java/net/runelite/http/api/osbuddy/OSBGrandExchangeClient.java @@ -35,9 +35,9 @@ import okhttp3.Request; import okhttp3.Response; @Slf4j -public class GrandExchangeClient +public class OSBGrandExchangeClient { - public GrandExchangeResult lookupItem(int itemId) throws IOException + public OSBGrandExchangeResult lookupItem(int itemId) throws IOException { final HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() .addPathSegment("osb") @@ -59,7 +59,7 @@ public class GrandExchangeClient } final InputStream in = response.body().byteStream(); - return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), GrandExchangeResult.class); + return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), OSBGrandExchangeResult.class); } catch (JsonParseException ex) { diff --git a/http-api/src/main/java/net/runelite/http/api/osbuddy/GrandExchangeResult.java b/http-api/src/main/java/net/runelite/http/api/osbuddy/OSBGrandExchangeResult.java similarity index 97% rename from http-api/src/main/java/net/runelite/http/api/osbuddy/GrandExchangeResult.java rename to http-api/src/main/java/net/runelite/http/api/osbuddy/OSBGrandExchangeResult.java index 993ee0d567..13e5f5e8e4 100644 --- a/http-api/src/main/java/net/runelite/http/api/osbuddy/GrandExchangeResult.java +++ b/http-api/src/main/java/net/runelite/http/api/osbuddy/OSBGrandExchangeResult.java @@ -28,7 +28,7 @@ import java.time.Instant; import lombok.Data; @Data -public class GrandExchangeResult +public class OSBGrandExchangeResult { private int item_id; private int buy_average; diff --git a/http-service/src/main/java/net/runelite/http/service/osbuddy/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/osbuddy/OSBGrandExchangeController.java similarity index 92% rename from http-service/src/main/java/net/runelite/http/service/osbuddy/GrandExchangeController.java rename to http-service/src/main/java/net/runelite/http/service/osbuddy/OSBGrandExchangeController.java index 92ba9093e7..847c415772 100644 --- a/http-service/src/main/java/net/runelite/http/service/osbuddy/GrandExchangeController.java +++ b/http-service/src/main/java/net/runelite/http/service/osbuddy/OSBGrandExchangeController.java @@ -35,12 +35,12 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/osb/ge") -public class GrandExchangeController +public class OSBGrandExchangeController { - private final GrandExchangeService grandExchangeService; + private final OSBGrandExchangeService grandExchangeService; @Autowired - public GrandExchangeController(GrandExchangeService grandExchangeService) + public OSBGrandExchangeController(OSBGrandExchangeService grandExchangeService) { this.grandExchangeService = grandExchangeService; } diff --git a/http-service/src/main/java/net/runelite/http/service/osbuddy/GrandExchangeService.java b/http-service/src/main/java/net/runelite/http/service/osbuddy/OSBGrandExchangeService.java similarity index 97% rename from http-service/src/main/java/net/runelite/http/service/osbuddy/GrandExchangeService.java rename to http-service/src/main/java/net/runelite/http/service/osbuddy/OSBGrandExchangeService.java index f7addee899..797d7e76e2 100644 --- a/http-service/src/main/java/net/runelite/http/service/osbuddy/GrandExchangeService.java +++ b/http-service/src/main/java/net/runelite/http/service/osbuddy/OSBGrandExchangeService.java @@ -40,7 +40,7 @@ import org.sql2o.Sql2o; @Service @Slf4j -public class GrandExchangeService +public class OSBGrandExchangeService { private static final String CREATE_GRAND_EXCHANGE_PRICES = "CREATE TABLE IF NOT EXISTS `osb_ge` (\n" + " `item_id` int(11) NOT NULL,\n" @@ -56,7 +56,7 @@ public class GrandExchangeService private final Sql2o sql2o; @Autowired - public GrandExchangeService(@Qualifier("Runelite SQL2O") Sql2o sql2o) + public OSBGrandExchangeService(@Qualifier("Runelite SQL2O") Sql2o sql2o) { this.sql2o = sql2o; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index cd4f3f050e..c26e39ebb5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -73,8 +73,8 @@ import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.ImageUtil; import net.runelite.client.util.StackFormatter; import net.runelite.client.util.Text; -import net.runelite.http.api.osbuddy.GrandExchangeClient; -import net.runelite.http.api.osbuddy.GrandExchangeResult; +import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; +import net.runelite.http.api.osbuddy.OSBGrandExchangeResult; @PluginDescriptor( name = "Grand Exchange", @@ -86,7 +86,7 @@ public class GrandExchangePlugin extends Plugin { private static final int OFFER_CONTAINER_ITEM = 21; private static final int OFFER_DEFAULT_ITEM_ID = 6512; - private static final GrandExchangeClient CLIENT = new GrandExchangeClient(); + private static final OSBGrandExchangeClient CLIENT = new OSBGrandExchangeClient(); private static final String OSB_GE_TEXT = "
OSBuddy Actively traded price: "; private static final String BUY_LIMIT_GE_TEXT = "
Buy limit: "; @@ -346,7 +346,7 @@ public class GrandExchangePlugin extends Plugin try { - final GrandExchangeResult result = CLIENT.lookupItem(itemId); + final OSBGrandExchangeResult result = CLIENT.lookupItem(itemId); final String text = geText.getText() + OSB_GE_TEXT + StackFormatter.formatNumber(result.getOverall_average()); geText.setText(text); } From 31e1e2563b7b7cca4b66d5d9f20d8bc00a2854b9 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 10 Feb 2019 12:35:18 -0500 Subject: [PATCH 008/102] api: add method to find instanced tiles in the scene Use in groundmarkers plugin --- .../net/runelite/api/coords/WorldPoint.java | 47 ++++++++- .../groundmarkers/GroundMarkerPlugin.java | 96 ++++--------------- 2 files changed, 62 insertions(+), 81 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java b/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java index 3f164c1845..a0a23e6674 100644 --- a/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java +++ b/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java @@ -25,6 +25,10 @@ */ package net.runelite.api.coords; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import lombok.Value; import net.runelite.api.Client; import static net.runelite.api.Constants.CHUNK_SIZE; @@ -150,7 +154,8 @@ public class WorldPoint } /** - * Gets the coordinate of the tile that contains the passed local point. + * Gets the coordinate of the tile that contains the passed local point, + * accounting for instances. * * @param client the client * @param localPoint the local coordinate @@ -190,6 +195,46 @@ public class WorldPoint } } + /** + * Get occurrences of a tile on the scene, accounting for instances. There may be + * more than one if the same template chunk occurs more than once on the scene. + * @param client + * @param worldPoint + * @return + */ + public static Collection toLocalInstance(Client client, WorldPoint worldPoint) + { + if (!client.isInInstancedRegion()) + { + return Collections.singleton(worldPoint); + } + + // find instance chunks using the template point. there might be more than one. + List worldPoints = new ArrayList<>(); + final int z = client.getPlane(); + int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); + for (int x = 0; x < instanceTemplateChunks[z].length; ++x) + { + for (int y = 0; y < instanceTemplateChunks[z][x].length; ++y) + { + int chunkData = instanceTemplateChunks[z][x][y]; + int rotation = chunkData >> 1 & 0x3; + int templateChunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; + int templateChunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; + if (worldPoint.getX() >= templateChunkX && worldPoint.getX() < templateChunkX + CHUNK_SIZE + && worldPoint.getY() >= templateChunkY && worldPoint.getY() < templateChunkY + CHUNK_SIZE) + { + WorldPoint p = new WorldPoint(client.getBaseX() + x * CHUNK_SIZE + (worldPoint.getX() & (CHUNK_SIZE - 1)), + client.getBaseY() + y * CHUNK_SIZE + (worldPoint.getY() & (CHUNK_SIZE - 1)), + worldPoint.getPlane()); + p = rotate(p, rotation); + worldPoints.add(p); + } + } + } + return worldPoints; + } + /** * Rotate the coordinates in the chunk according to chunk rotation * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index 12ceda382a..2cb7ebf1c2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -34,13 +34,13 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; -import static net.runelite.api.Constants.CHUNK_SIZE; import net.runelite.api.GameState; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; @@ -155,87 +155,23 @@ public class GroundMarkerPlugin extends Plugin return Collections.EMPTY_LIST; } - List worldPoints = new ArrayList<>(); - for (GroundMarkerPoint point : points) - { - int regionId = point.getRegionId(); - int regionX = point.getRegionX(); - int regionY = point.getRegionY(); - int z = point.getZ(); - - // world point of the tile marker - WorldPoint worldPoint = new WorldPoint( - ((regionId >>> 8) << 6) + regionX, - ((regionId & 0xff) << 6) + regionY, - z - ); - - if (!client.isInInstancedRegion()) + return points.stream() + .map(point -> { - worldPoints.add(worldPoint); - continue; - } + int regionId = point.getRegionId(); + int regionX = point.getRegionX(); + int regionY = point.getRegionY(); + int z = point.getZ(); - // find instance chunks using the template point. there might be more than one. - int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); - for (int x = 0; x < instanceTemplateChunks[z].length; ++x) - { - for (int y = 0; y < instanceTemplateChunks[z][x].length; ++y) - { - int chunkData = instanceTemplateChunks[z][x][y]; - int rotation = chunkData >> 1 & 0x3; - int templateChunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; - int templateChunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; - if (worldPoint.getX() >= templateChunkX && worldPoint.getX() < templateChunkX + CHUNK_SIZE - && worldPoint.getY() >= templateChunkY && worldPoint.getY() < templateChunkY + CHUNK_SIZE) - { - WorldPoint p = new WorldPoint(client.getBaseX() + x * CHUNK_SIZE + (worldPoint.getX() & (CHUNK_SIZE - 1)), - client.getBaseY() + y * CHUNK_SIZE + (worldPoint.getY() & (CHUNK_SIZE - 1)), - worldPoint.getPlane()); - p = rotate(p, rotation); - worldPoints.add(p); - } - } - } - } - return worldPoints; - } - - /** - * Rotate the chunk containing the given point to rotation 0 - * - * @param point point - * @param rotation rotation - * @return world point - */ - private static WorldPoint rotateInverse(WorldPoint point, int rotation) - { - return rotate(point, 4 - rotation); - } - - /** - * Rotate the coordinates in the chunk according to chunk rotation - * - * @param point point - * @param rotation rotation - * @return world point - */ - private static WorldPoint rotate(WorldPoint point, int rotation) - { - int chunkX = point.getX() & ~(CHUNK_SIZE - 1); - int chunkY = point.getY() & ~(CHUNK_SIZE - 1); - int x = point.getX() & (CHUNK_SIZE - 1); - int y = point.getY() & (CHUNK_SIZE - 1); - switch (rotation) - { - case 1: - return new WorldPoint(chunkX + y, chunkY + (CHUNK_SIZE - 1 - x), point.getPlane()); - case 2: - return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - x), chunkY + (CHUNK_SIZE - 1 - y), point.getPlane()); - case 3: - return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - y), chunkY + x, point.getPlane()); - } - return point; + // world point of the tile marker + return new WorldPoint( + ((regionId >>> 8) << 6) + regionX, + ((regionId & 0xff) << 6) + regionY, + z + ); + }) + .flatMap(wp -> WorldPoint.toLocalInstance(client, wp).stream()) + .collect(Collectors.toList()); } @Subscribe From 0559d0d5b4c0d40dd7ce6b92a93a90e76c7d6809 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 5 Feb 2019 12:46:28 +0000 Subject: [PATCH 009/102] Use CLANCHAT_INFO for party messages This makes more sense for party messages, mainly if we will be sending party-related messages with source in future. Signed-off-by: Tomas Slusny --- .../net/runelite/client/plugins/party/PartyPlugin.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java index 73abcdb172..0e910ff338 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java @@ -191,7 +191,7 @@ public class PartyPlugin extends Plugin implements KeyListener .build(); chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.GAME) + .type(ChatMessageType.CLANCHAT_INFO) .runeLiteFormattedMessage(leaveMessage) .build()); } @@ -381,7 +381,7 @@ public class PartyPlugin extends Plugin implements KeyListener .build(); chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.GAME) + .type(ChatMessageType.CLANCHAT_INFO) .runeLiteFormattedMessage(joinMessage) .build()); @@ -430,7 +430,7 @@ public class PartyPlugin extends Plugin implements KeyListener .build(); chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.GAME) + .type(ChatMessageType.CLANCHAT_INFO) .runeLiteFormattedMessage(joinMessage) .build()); } @@ -519,7 +519,7 @@ public class PartyPlugin extends Plugin implements KeyListener .build(); chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.GAME) + .type(ChatMessageType.CLANCHAT_INFO) .runeLiteFormattedMessage(helpMessage) .build()); } From 4d35ea0c20a863769fda40af4ea0b5997da70067 Mon Sep 17 00:00:00 2001 From: Noah Pittinger Date: Mon, 11 Feb 2019 23:51:13 -0500 Subject: [PATCH 010/102] Add EqualsAndHashCode to Lombok data/value that do not extend Object --- .../main/java/net/runelite/http/api/ws/messages/party/Join.java | 2 ++ .../java/net/runelite/http/api/ws/messages/party/UserJoin.java | 2 ++ .../java/net/runelite/http/api/ws/messages/party/UserPart.java | 2 ++ .../java/net/runelite/http/api/ws/messages/party/UserSync.java | 2 ++ .../runelite/protocol/api/handshake/LoginHandshakePacket.java | 2 ++ .../runelite/protocol/api/handshake/UpdateHandshakePacket.java | 2 ++ .../src/main/java/net/runelite/client/events/ChatboxInput.java | 2 ++ .../java/net/runelite/client/events/PrivateMessageInput.java | 2 ++ .../net/runelite/client/plugins/discord/DiscordUserInfo.java | 2 ++ .../runelite/client/plugins/party/messages/LocationUpdate.java | 2 ++ .../net/runelite/client/plugins/party/messages/TilePing.java | 2 ++ 11 files changed, 22 insertions(+) diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Join.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Join.java index 1c4cf2f73a..21aed0f653 100644 --- a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Join.java +++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/Join.java @@ -25,10 +25,12 @@ package net.runelite.http.api.ws.messages.party; import java.util.UUID; +import lombok.EqualsAndHashCode; import lombok.Value; import net.runelite.http.api.ws.WebsocketMessage; @Value +@EqualsAndHashCode(callSuper = true) public class Join extends WebsocketMessage { private final UUID partyId; diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java index 05d27b6790..81abe76827 100644 --- a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java +++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java @@ -25,10 +25,12 @@ package net.runelite.http.api.ws.messages.party; import java.util.UUID; +import lombok.EqualsAndHashCode; import lombok.Value; import net.runelite.http.api.ws.WebsocketMessage; @Value +@EqualsAndHashCode(callSuper = true) public class UserJoin extends WebsocketMessage { private final UUID memberId; diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserPart.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserPart.java index e3efbe4a9c..e80c6002bd 100644 --- a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserPart.java +++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserPart.java @@ -25,10 +25,12 @@ package net.runelite.http.api.ws.messages.party; import java.util.UUID; +import lombok.EqualsAndHashCode; import lombok.Value; import net.runelite.http.api.ws.WebsocketMessage; @Value +@EqualsAndHashCode(callSuper = true) public class UserPart extends WebsocketMessage { private final UUID memberId; diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserSync.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserSync.java index eca9844845..c95038c9fa 100644 --- a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserSync.java +++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserSync.java @@ -24,9 +24,11 @@ */ package net.runelite.http.api.ws.messages.party; +import lombok.EqualsAndHashCode; import lombok.Value; @Value +@EqualsAndHashCode(callSuper = true) public class UserSync extends PartyMemberMessage { } diff --git a/protocol-api/src/main/java/net/runelite/protocol/api/handshake/LoginHandshakePacket.java b/protocol-api/src/main/java/net/runelite/protocol/api/handshake/LoginHandshakePacket.java index 4a6090504e..16ccb85694 100644 --- a/protocol-api/src/main/java/net/runelite/protocol/api/handshake/LoginHandshakePacket.java +++ b/protocol-api/src/main/java/net/runelite/protocol/api/handshake/LoginHandshakePacket.java @@ -25,8 +25,10 @@ package net.runelite.protocol.api.handshake; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) public class LoginHandshakePacket extends HandshakePacket { diff --git a/protocol-api/src/main/java/net/runelite/protocol/api/handshake/UpdateHandshakePacket.java b/protocol-api/src/main/java/net/runelite/protocol/api/handshake/UpdateHandshakePacket.java index 9d1b20c8f2..86b39d41e8 100644 --- a/protocol-api/src/main/java/net/runelite/protocol/api/handshake/UpdateHandshakePacket.java +++ b/protocol-api/src/main/java/net/runelite/protocol/api/handshake/UpdateHandshakePacket.java @@ -26,9 +26,11 @@ package net.runelite.protocol.api.handshake; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @Data +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor public class UpdateHandshakePacket extends HandshakePacket diff --git a/runelite-client/src/main/java/net/runelite/client/events/ChatboxInput.java b/runelite-client/src/main/java/net/runelite/client/events/ChatboxInput.java index 6388c8b433..cad7d38077 100644 --- a/runelite-client/src/main/java/net/runelite/client/events/ChatboxInput.java +++ b/runelite-client/src/main/java/net/runelite/client/events/ChatboxInput.java @@ -25,8 +25,10 @@ package net.runelite.client.events; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) public abstract class ChatboxInput extends ChatInput { private final String value; diff --git a/runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java b/runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java index fc31fae7f1..80a189f273 100644 --- a/runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java +++ b/runelite-client/src/main/java/net/runelite/client/events/PrivateMessageInput.java @@ -25,8 +25,10 @@ package net.runelite.client.events; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) public abstract class PrivateMessageInput extends ChatInput { private final String target; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordUserInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordUserInfo.java index b358a7d01e..360d58652e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordUserInfo.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordUserInfo.java @@ -24,10 +24,12 @@ */ package net.runelite.client.plugins.discord; +import lombok.EqualsAndHashCode; import lombok.Value; import net.runelite.http.api.ws.messages.party.PartyMemberMessage; @Value +@EqualsAndHashCode(callSuper = true) class DiscordUserInfo extends PartyMemberMessage { private final String userId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/LocationUpdate.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/LocationUpdate.java index 0ff6569379..f5bf7131ce 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/LocationUpdate.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/LocationUpdate.java @@ -24,11 +24,13 @@ */ package net.runelite.client.plugins.party.messages; +import lombok.EqualsAndHashCode; import lombok.Value; import net.runelite.api.coords.WorldPoint; import net.runelite.http.api.ws.messages.party.PartyMemberMessage; @Value +@EqualsAndHashCode(callSuper = true) public class LocationUpdate extends PartyMemberMessage { private final WorldPoint worldPoint; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/TilePing.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/TilePing.java index 1378403333..fb4f812a81 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/TilePing.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/messages/TilePing.java @@ -24,11 +24,13 @@ */ package net.runelite.client.plugins.party.messages; +import lombok.EqualsAndHashCode; import lombok.Value; import net.runelite.api.coords.WorldPoint; import net.runelite.http.api.ws.messages.party.PartyMemberMessage; @Value +@EqualsAndHashCode(callSuper = true) public class TilePing extends PartyMemberMessage { private final WorldPoint point; From 6941b697324bacf9aecacbaac617242da9db3f85 Mon Sep 17 00:00:00 2001 From: Ryan Bohannon Date: Mon, 11 Feb 2019 23:55:14 -0700 Subject: [PATCH 011/102] Add agility shortcut entry for Taverly Dungeon upper level --- .../client/plugins/worldmap/AgilityShortcutLocation.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java index dd2e3771b6..c0b95cfa32 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java @@ -118,6 +118,7 @@ enum AgilityShortcutLocation SHILO_VILLAGE_STEPPING_STONES("Stepping Stones", 77, new WorldPoint(2863, 2974, 0)), KHARAZI_JUNGLE_VINE_CLIMB("Vine", 79, new WorldPoint(2897, 2939, 0)), TAVERLEY_DUNGEON_SPIKED_BLADES("Strange Floor", 80, new WorldPoint(2877, 9813, 0)), + TAVERLEY_DUNGEON_ROCKS("Rocks", 70, new WorldPoint(2887, 9823, 0)), SLAYER_DUNGEON_CHASM_JUMP("Spiked Blades", 81, new WorldPoint(2770, 10003, 0)), LAVA_MAZE_NORTH_JUMP("Stepping Stone", 82, new WorldPoint(3092, 3880, 0)), BRIMHAVEN_DUNGEON_EAST_STEPPING_NORTH("Stepping Stones", 83, new WorldPoint(2685, 9547, 0)), From a690e1aadfbd22717e562e0dde7fe55387d2dc8a Mon Sep 17 00:00:00 2001 From: rejectedpromise <28940139+rejectedpromise@users.noreply.github.com> Date: Tue, 12 Feb 2019 00:27:51 -0700 Subject: [PATCH 012/102] Add new lines at .rs2asm to resolve build warnings (#7812) --- runelite-client/src/main/scripts/BankSearchFilter.rs2asm | 2 +- runelite-client/src/main/scripts/SendPrivateMessage.rs2asm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/scripts/BankSearchFilter.rs2asm b/runelite-client/src/main/scripts/BankSearchFilter.rs2asm index 60b9f12aa6..80a0db4021 100644 --- a/runelite-client/src/main/scripts/BankSearchFilter.rs2asm +++ b/runelite-client/src/main/scripts/BankSearchFilter.rs2asm @@ -67,4 +67,4 @@ LABEL34: load_int 1 return load_int -1 - return \ No newline at end of file + return diff --git a/runelite-client/src/main/scripts/SendPrivateMessage.rs2asm b/runelite-client/src/main/scripts/SendPrivateMessage.rs2asm index f2102c1328..3e1e3a8d47 100644 --- a/runelite-client/src/main/scripts/SendPrivateMessage.rs2asm +++ b/runelite-client/src/main/scripts/SendPrivateMessage.rs2asm @@ -31,4 +31,4 @@ sload 0 sload 1 privmsg - return \ No newline at end of file + return From 5b03cf3a688f6b94d0ca58e50363777b5ce25e0b Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 12 Feb 2019 08:54:58 +0100 Subject: [PATCH 013/102] Fix unmapped target property "time" warning Signed-off-by: Tomas Slusny --- .../src/main/java/net/runelite/http/service/xp/XpMapper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/http-service/src/main/java/net/runelite/http/service/xp/XpMapper.java b/http-service/src/main/java/net/runelite/http/service/xp/XpMapper.java index ad72f43c47..068c6e5438 100644 --- a/http-service/src/main/java/net/runelite/http/service/xp/XpMapper.java +++ b/http-service/src/main/java/net/runelite/http/service/xp/XpMapper.java @@ -38,6 +38,8 @@ public interface XpMapper XpData xpEntityToXpData(XpEntity xpEntity); + @Mapping(target = "time", ignore = true) + @Mapping(source = "attack.experience", target = "attack_xp") @Mapping(source = "defence.experience", target = "defence_xp") @Mapping(source = "strength.experience", target = "strength_xp") From 1715a369c0ceea64a5b53650ebc5437066e1291e Mon Sep 17 00:00:00 2001 From: Max Weber Date: Tue, 12 Feb 2019 04:03:10 -0700 Subject: [PATCH 014/102] mixins: Fix DecorativeObject ConvexHulls --- .../net/runelite/api/DecorativeObject.java | 1 + .../mixins/RSDecorativeObjectMixin.java | 39 ++++++++++++++++++- .../runelite/rs/api/RSDecorativeObject.java | 6 +++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java b/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java index c2bbd14cf3..145531fa5d 100644 --- a/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java +++ b/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java @@ -38,6 +38,7 @@ public interface DecorativeObject extends TileObject * @see net.runelite.api.model.Jarvis */ Polygon getConvexHull(); + Polygon getConvexHull2(); Renderable getRenderable(); Renderable getRenderable2(); diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSDecorativeObjectMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSDecorativeObjectMixin.java index f278609c9b..7ae4685ef3 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSDecorativeObjectMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSDecorativeObjectMixin.java @@ -82,6 +82,29 @@ public abstract class RSDecorativeObjectMixin implements RSDecorativeObject return model; } + @Inject + private RSModel getModel2() + { + RSRenderable renderable = getRenderable2(); + if (renderable == null) + { + return null; + } + + RSModel model; + + if (renderable instanceof Model) + { + model = (RSModel) renderable; + } + else + { + model = renderable.getModel(); + } + + return model; + } + @Inject @Override public Area getClickbox() @@ -100,6 +123,20 @@ public abstract class RSDecorativeObjectMixin implements RSDecorativeObject return null; } - return model.getConvexHull(getX(), getY(), getOrientation()); + return model.getConvexHull(getX() + getXOffset(), getY() + getYOffset(), 0); + } + + @Inject + @Override + public Polygon getConvexHull2() + { + RSModel model = getModel2(); + + if (model == null) + { + return null; + } + + return model.getConvexHull(getX(), getY(), 0); } } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSDecorativeObject.java b/runescape-api/src/main/java/net/runelite/rs/api/RSDecorativeObject.java index 1a53a49cb9..910c5acc1b 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSDecorativeObject.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSDecorativeObject.java @@ -39,6 +39,12 @@ public interface RSDecorativeObject extends DecorativeObject @Import("y") int getY(); + @Import("offsetX") + int getXOffset(); + + @Import("offsetY") + int getYOffset(); + @Import("rotation") int getOrientation(); From 29e971887db6dbfb1ca89fe39d6668c97808445c Mon Sep 17 00:00:00 2001 From: Max Weber Date: Tue, 12 Feb 2019 04:03:41 -0700 Subject: [PATCH 015/102] DevTools: draw both DecorativeObject Renderables --- .../runelite/client/plugins/devtools/DevToolsOverlay.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java index 0b9be07b7e..fd96de011c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java @@ -347,6 +347,12 @@ class DevToolsOverlay extends Overlay { graphics.drawPolygon(p); } + + p = decorObject.getConvexHull2(); + if (p != null) + { + graphics.drawPolygon(p); + } } } From d186632c4c95cfcf46ce8589b3ea96a8b8258a75 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 12 Feb 2019 11:55:20 +0000 Subject: [PATCH 016/102] Use ItemVariations when using Reset option for shift-click Signed-off-by: Tomas Slusny --- .../client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index e6420bdc99..8300333570 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -179,6 +179,7 @@ public class MenuEntrySwapperPlugin extends Plugin private void unsetSwapConfig(int itemId) { + itemId = ItemVariationMapping.map(itemId); configManager.unsetConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId); } From 90b00b234fce06c2622f101209799992c54b3773 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 26 Nov 2018 01:20:14 -0700 Subject: [PATCH 017/102] runelite-client: centralize sprite overrides --- .../runelite/client/game/SpriteManager.java | 36 ++++++++++++++++ .../runelite/client/game/SpriteOverride.java | 42 +++++++++++++++++++ .../plugins/banktags/BankTagsPlugin.java | 12 +++--- .../plugins/banktags/tabs/TabSprites.java | 33 +++------------ .../net/runelite/client/util/ImageUtil.java | 16 ++++++- 5 files changed, 104 insertions(+), 35 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/game/SpriteOverride.java diff --git a/runelite-client/src/main/java/net/runelite/client/game/SpriteManager.java b/runelite-client/src/main/java/net/runelite/client/game/SpriteManager.java index f0df8286cd..f177377818 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/SpriteManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/SpriteManager.java @@ -28,6 +28,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.inject.Inject; import java.awt.image.BufferedImage; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import javax.annotation.Nullable; @@ -36,11 +37,14 @@ import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.SwingUtilities; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.SpritePixels; import net.runelite.client.callback.ClientThread; +import net.runelite.client.util.ImageUtil; +@Slf4j @Singleton public class SpriteManager { @@ -127,4 +131,36 @@ public class SpriteManager }); }); } + + public void addSpriteOverrides(SpriteOverride[] add) + { + if (add.length <= 0) + { + return; + } + + clientThread.invokeLater(() -> + { + Map overrides = client.getSpriteOverrides(); + Class owner = add[0].getClass(); + for (SpriteOverride o : add) + { + BufferedImage image = ImageUtil.getResourceStreamFromClass(owner, o.getFileName()); + SpritePixels sp = ImageUtil.getImageSpritePixels(image, client); + overrides.put(o.getSpriteId(), sp); + } + }); + } + + public void removeSpriteOverrides(SpriteOverride[] remove) + { + clientThread.invokeLater(() -> + { + Map overrides = client.getSpriteOverrides(); + for (SpriteOverride o : remove) + { + overrides.remove(o.getSpriteId()); + } + }); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/game/SpriteOverride.java b/runelite-client/src/main/java/net/runelite/client/game/SpriteOverride.java new file mode 100644 index 0000000000..a4f894d5c0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/game/SpriteOverride.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018 Abex + * 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.game; + +import net.runelite.api.SpriteID; + +public interface SpriteOverride +{ + /** + * An ID for a sprite. Negative numbers are used by RuneLite specific sprites + * + * @see SpriteID + */ + int getSpriteId(); + + /** + * The file name for the resource to be loaded, relative to the implementing class + */ + String getFileName(); +} 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 620cc586be..6a3a7f3416 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 @@ -60,6 +60,7 @@ import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.input.KeyListener; import net.runelite.client.input.KeyManager; @@ -125,6 +126,9 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis @Inject private KeyManager keyManager; + @Inject + private SpriteManager spriteManager; + private boolean shiftPressed = false; @Provides @@ -139,7 +143,7 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis keyManager.registerKeyListener(this); mouseManager.registerMouseWheelListener(this); clientThread.invokeLater(tabInterface::init); - client.getSpriteOverrides().putAll(TabSprites.toMap(client)); + spriteManager.addSpriteOverrides(TabSprites.values()); } @Override @@ -148,11 +152,7 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis keyManager.unregisterKeyListener(this); mouseManager.unregisterMouseWheelListener(this); clientThread.invokeLater(tabInterface::destroy); - - for (TabSprites value : TabSprites.values()) - { - client.getSpriteOverrides().remove(value.getSpriteId()); - } + spriteManager.removeSpriteOverrides(TabSprites.values()); shiftPressed = false; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabSprites.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabSprites.java index e7706679b0..20f9d0dfb6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabSprites.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabSprites.java @@ -25,17 +25,12 @@ */ package net.runelite.client.plugins.banktags.tabs; -import java.awt.image.BufferedImage; -import java.util.HashMap; -import java.util.Map; import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.SpritePixels; -import net.runelite.client.util.ImageUtil; +import lombok.RequiredArgsConstructor; +import net.runelite.client.game.SpriteOverride; -@Slf4j -public enum TabSprites +@RequiredArgsConstructor +public enum TabSprites implements SpriteOverride { INCINERATOR(-200, "incinerator.png"), TAB_BACKGROUND(-201, "tag-tab.png"), @@ -46,23 +41,7 @@ public enum TabSprites @Getter private final int spriteId; - private final BufferedImage image; - TabSprites(final int spriteId, final String imageName) - { - this.spriteId = spriteId; - this.image = ImageUtil.getResourceStreamFromClass(this.getClass(), imageName); - } - - public static Map toMap(Client client) - { - final Map map = new HashMap<>(); - - for (TabSprites value : values()) - { - map.put(value.spriteId, ImageUtil.getImageSpritePixels(value.image, client)); - } - - return map; - } + @Getter + private final String fileName; } diff --git a/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java index 1fa63d815e..16a6b1c78a 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java @@ -30,6 +30,7 @@ import java.awt.Image; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; +import java.awt.image.DirectColorModel; import java.awt.image.PixelGrabber; import java.awt.image.RescaleOp; import java.io.IOException; @@ -426,8 +427,19 @@ public class ImageUtil try { - new PixelGrabber(image, 0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth()) - .grabPixels(); + PixelGrabber g = new PixelGrabber(image, 0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth()); + g.setColorModel(new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000)); + g.grabPixels(); + + // Make any fully transparent pixels fully black, because the sprite draw routines + // check for == 0, not actual transparency + for (int i = 0; i < pixels.length; i++) + { + if ((pixels[i] & 0xFF000000) == 0) + { + pixels[i] = 0; + } + } } catch (InterruptedException ex) { From e287a34a574ea3f9e86c437a4f84e70412a3b13e Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sat, 1 Dec 2018 16:14:44 -0700 Subject: [PATCH 018/102] ChatboxTextInput: Don't set built in update update is desgined to be fully replaced by child classes, so it should not access private state --- .../net/runelite/client/game/chatbox/ChatboxTextInput.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java index e340027d1a..848f461288 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java @@ -95,12 +95,13 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse @Getter private int fontID = FontID.QUILL_8; + @Getter + private boolean built = false; + // This is a lambda so I can have atomic updates for it's captures private ToIntFunction getCharOffset = null; private Predicate isInBounds = null; - private boolean built = false; - @Inject protected ChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread) { @@ -209,7 +210,6 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse protected void update() { - this.built = true; Widget container = chatboxPanelManager.getContainerWidget(); container.deleteAllChildren(); @@ -369,6 +369,7 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse @Override protected void open() { + this.built = true; update(); } From d2713c2138e4940e0cd0bd3c4afcf028e3ea807c Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 12 Feb 2019 22:49:01 +0100 Subject: [PATCH 019/102] Add offset to loot tracker API Signed-off-by: Tomas Slusny --- .../http/service/loottracker/LootTrackerController.java | 4 ++-- .../http/service/loottracker/LootTrackerService.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java index 36e0a2333d..d5a09f44d2 100644 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java @@ -66,7 +66,7 @@ public class LootTrackerController } @RequestMapping - public Collection getLootRecords(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "count", defaultValue = "1024") int count) throws IOException + public Collection getLootRecords(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "count", defaultValue = "1024") int count, @RequestParam(value = "start", defaultValue = "0") int start) throws IOException { SessionEntry e = auth.handle(request, response); if (e == null) @@ -75,7 +75,7 @@ public class LootTrackerController return null; } - return service.get(e.getUser(), count); + return service.get(e.getUser(), count, start); } @DeleteMapping diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java index d39e159228..86b7115a80 100644 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java @@ -66,7 +66,7 @@ public class LootTrackerService private static final String INSERT_KILL_QUERY = "INSERT INTO kills (accountId, type, eventId) VALUES (:accountId, :type, :eventId)"; private static final String INSERT_DROP_QUERY = "INSERT INTO drops (killId, itemId, itemQuantity) VALUES (LAST_INSERT_ID(), :itemId, :itemQuantity)"; - private static final String SELECT_LOOT_QUERY = "SELECT killId,time,type,eventId,itemId,itemQuantity FROM kills JOIN drops ON drops.killId = kills.id WHERE accountId = :accountId ORDER BY TIME DESC LIMIT :limit"; + private static final String SELECT_LOOT_QUERY = "SELECT killId,time,type,eventId,itemId,itemQuantity FROM kills JOIN drops ON drops.killId = kills.id WHERE accountId = :accountId ORDER BY TIME DESC LIMIT :limit OFFSET :offset"; private static final String DELETE_LOOT_ACCOUNT = "DELETE FROM kills WHERE accountId = :accountId"; private static final String DELETE_LOOT_ACCOUNT_EVENTID = "DELETE FROM kills WHERE accountId = :accountId AND eventId = :eventId"; @@ -119,7 +119,7 @@ public class LootTrackerService } } - public Collection get(int accountId, int limit) + public Collection get(int accountId, int limit, int offset) { List lootResults; @@ -128,6 +128,7 @@ public class LootTrackerService lootResults = con.createQuery(SELECT_LOOT_QUERY) .addParameter("accountId", accountId) .addParameter("limit", limit) + .addParameter("offset", offset) .executeAndFetch(LootResult.class); } From 35e6e341bb9db6bbe8dab17e7bacfde709bbcdc9 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 26 Nov 2018 19:33:30 -0700 Subject: [PATCH 020/102] Add Wiki plugin This has the side affect of making the click mask around the run orb correct in fixed mode --- .../main/java/net/runelite/api/Client.java | 5 + .../main/java/net/runelite/api/SpriteID.java | 2 +- .../java/net/runelite/api/widgets/Widget.java | 52 +++ .../runelite/api/widgets/WidgetConfig.java | 51 +++ .../net/runelite/api/widgets/WidgetID.java | 9 + .../net/runelite/api/widgets/WidgetInfo.java | 7 +- .../devtools/WidgetInfoTableModel.java | 3 + .../client/plugins/wiki/WikiPlugin.java | 289 +++++++++++++++++ .../wiki/WikiSearchChatboxTextInput.java | 302 ++++++++++++++++++ .../client/plugins/wiki/WikiSprite.java | 44 +++ .../wiki/fixed_mode_minimap_clickmask.png | Bin 0 -> 2027 bytes .../net/runelite/client/plugins/wiki/wiki.png | Bin 0 -> 3092 bytes .../client/plugins/wiki/wiki_selected.png | Bin 0 -> 3025 bytes .../java/net/runelite/rs/api/RSClient.java | 4 + .../java/net/runelite/rs/api/RSWidget.java | 36 +++ 15 files changed, 802 insertions(+), 2 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSprite.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/wiki/fixed_mode_minimap_clickmask.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki_selected.png diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index ca51dc74a9..652eb00806 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1569,4 +1569,9 @@ public interface Client extends GameEngine int getRasterizer3D_clipMidY2(); void checkClickbox(Model model, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash); + + /** + * Sets if a widget is in target mode + */ + void setSpellSelected(boolean selected); } diff --git a/runelite-api/src/main/java/net/runelite/api/SpriteID.java b/runelite-api/src/main/java/net/runelite/api/SpriteID.java index 2c4ac4f878..e707854c12 100644 --- a/runelite-api/src/main/java/net/runelite/api/SpriteID.java +++ b/runelite-api/src/main/java/net/runelite/api/SpriteID.java @@ -1172,7 +1172,7 @@ public final class SpriteID public static final int MINIMAP_ORB_XP_ACTIVATED = 1197; public static final int MINIMAP_ORB_XP_HOVERED = 1198; public static final int MINIMAP_ORB_XP_ACTIVATED_HOVERED = 1199; - public static final int UNKNOWN_BLACK_BLOBS = 1200; + public static final int MINIMAP_CLICK_MASK = 1200; public static final int OPTIONS_ZOOM_SLIDER_THUMB = 1201; public static final int EMOTE_SIT_UP = 1202; public static final int EMOTE_STAR_JUMP = 1203; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index 3aa6e23f13..ed4277a2a3 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -79,6 +79,7 @@ public interface Widget /** * Gets the current click configuration of the widget. + * @see WidgetConfig * * @see WidgetConfig */ @@ -551,6 +552,13 @@ public interface Widget */ void setOnMouseOverListener(Object... args); + /** + * Sets a script to be ran every frame when the mouse is in the widget bounds + * + * @param args A ScriptID, then the args for the script + */ + void setOnMouseRepeatListener(Object... args); + /** * Sets a script to be ran when the mouse leaves the widget bounds * @@ -565,6 +573,20 @@ public interface Widget */ void setOnTimerListener(Object... args); + /** + * Sets a script to be ran when the target mode has been activated for this widget + * + * @param args A ScriptID, then the args for the script + */ + void setOnTargetEnterListener(Object... args); + + /** + * Sets a script to be ran when the target mode has been deactivated for this widget + * + * @param args A ScriptID, then the args for the script + */ + void setOnTargetLeaveListener(Object... args); + /** * If this widget has any listeners on it */ @@ -769,4 +791,34 @@ public interface Widget * Sets if the rectangle is filled or just stroked */ void setFilled(boolean filled); + + /** + * Verb for spell targets + */ + String getTargetVerb(); + + /** + * Verb for spell targets + */ + void setTargetVerb(String targetVerb); + + /** + * Can widgets under this widgets be clicked in this widgets bounding box + */ + boolean getNoClickThrough(); + + /** + * Can widgets under this widgets be clicked in this widgets bounding box + */ + void setNoClickThrough(boolean noClickThrough); + + /** + * Can widgets under this widgets be scrolled in this widgets bounding box + */ + boolean getNoScrollThrough(); + + /** + * Can widgets under this widgets be scrolled in this widgets bounding box + */ + void setNoScrollThrough(boolean noScrollThrough); } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java index 0b8f6a587d..31829b5417 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java @@ -24,6 +24,8 @@ */ package net.runelite.api.widgets; +import net.runelite.api.MenuAction; + /** * Utility class used for defining options to be used on the click mask * of a {@link Widget}. @@ -36,12 +38,61 @@ public class WidgetConfig * Enables displaying a ninth option on a menu. */ public static final int SHOW_MENU_OPTION_NINE = 1 << 9; + + /** + * Can this widget be used on a item on the floor + */ + public static final int USE_GROUND_ITEM = 1 << 11; + + /** + * Can this widget be used on a NPC + */ + public static final int USE_NPC = 2 << 11; + + /** + * Can this widget be used on a game object + */ + public static final int USE_OBJECT = 4 << 11; + + /** + * Can this widget be used on a player + */ + public static final int USE_PLAYER = 8 << 11; + + /** + * Can this widget be used on a item in your inventory + */ + public static final int USE_ITEM = 16 << 11; + + /** + * Can this widget be used on a widget with the WIDGET_USE_TARGET flag + */ + public static final int USE_WIDGET = 32 << 11; + /** * Controls whether or not a widget can have another dragged onto it. */ public static final int DRAG_ON = 1 << 17; + /** * Controls whether or not a widget can be dragged around. */ public static final int DRAG = 1 << 20; + + /** + * Can widgets with USE_WIDGET be used on this widget + */ + public static final int WIDGET_USE_TARGET = 1 << 21; + + /** + * Is the widget an (inventory?) item + */ + public static final int ITEM = 1 << 30; + + /** + * Add a USE option + * + * @see MenuAction#ITEM_USE + */ + public static final int ITEM_USE_OP = 1 << 31; } 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 9f07f9ba37..e919c0f992 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 @@ -125,6 +125,7 @@ public class WidgetID public static final int SKOTIZO_GROUP_ID = 308; public static final int ENTERING_HOUSE_GROUP_ID = 71; public static final int FULLSCREEN_MAP_GROUP_ID = 165; + public static final int QUESTLIST_GROUP_ID = 399; static class WorldMap { @@ -292,6 +293,7 @@ public class WidgetID static final int TOGGLE_RUN_ORB = 22; // Has the "Toggle run" name static final int RUN_ORB_TEXT = 23; static final int SPEC_ORB = 28; + static final int WORLDMAP_ORB = 40; } static class LoginClickToPlayScreen @@ -747,4 +749,11 @@ public class WidgetID { static final int ROOT = 25; } + + static class QuestList + { + static final int FREE_CONTAINER = 9; + static final int MEMBERS_CONTAINER = 10; + static final int MINIQUEST_CONTAINER = 11; + } } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 556dc57bf5..7808e06cba 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -159,6 +159,7 @@ public enum WidgetInfo MINIMAP_RUN_ORB_TEXT(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.RUN_ORB_TEXT), MINIMAP_HEALTH_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.HEALTH_ORB), MINIMAP_SPEC_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_ORB), + MINIMAP_WORLDMAP_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), LOGIN_CLICK_TO_PLAY_SCREEN(WidgetID.LOGIN_CLICK_TO_PLAY_GROUP_ID, 0), LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY(WidgetID.LOGIN_CLICK_TO_PLAY_GROUP_ID, WidgetID.LoginClickToPlayScreen.MESSAGE_OF_THE_DAY), @@ -463,7 +464,11 @@ public enum WidgetInfo SKOTIZO_CONTAINER(WidgetID.SKOTIZO_GROUP_ID, WidgetID.Skotizo.CONTAINER), - FULLSCREEN_MAP_ROOT(WidgetID.FULLSCREEN_MAP_GROUP_ID, WidgetID.FullScreenMap.ROOT); + FULLSCREEN_MAP_ROOT(WidgetID.FULLSCREEN_MAP_GROUP_ID, WidgetID.FullScreenMap.ROOT), + + QUESTLIST_FREE_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.FREE_CONTAINER), + QUESTLIST_MEMBERS_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MEMBERS_CONTAINER), + QUESTLIST_MINIQUEST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MINIQUEST_CONTAINER); private final int groupId; private final int childId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java index 79bb99bc5a..acd8851c0b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java @@ -183,6 +183,9 @@ public class WidgetInfoTableModel extends AbstractTableModel out.add(new WidgetField<>("ScrollHeight", Widget::getScrollHeight, Widget::setScrollHeight, Integer.class)); out.add(new WidgetField<>("DragDeadZone", Widget::getDragDeadZone, Widget::setDragDeadZone, Integer.class)); out.add(new WidgetField<>("DragDeadTime", Widget::getDragDeadTime, Widget::setDragDeadTime, Integer.class)); + out.add(new WidgetField<>("NoClickThrough", Widget::getNoClickThrough, Widget::setNoClickThrough, Boolean.class)); + out.add(new WidgetField<>("NoScrollThrough", Widget::getNoScrollThrough, Widget::setNoScrollThrough, Boolean.class)); + out.add(new WidgetField<>("TargetVerb", Widget::getTargetVerb, Widget::setTargetVerb, String.class)); return out; } 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 new file mode 100644 index 0000000000..e6b21437e0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2018 Abex + * 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.plugins.wiki; + +import com.google.common.primitives.Ints; +import java.net.URLEncoder; +import java.util.Arrays; +import javax.inject.Inject; +import javax.inject.Provider; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetConfig; +import net.runelite.api.widgets.WidgetID; +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.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.game.chatbox.ChatboxPanelManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.LinkBrowser; +import net.runelite.client.util.Text; +import okhttp3.HttpUrl; + +@Slf4j +@PluginDescriptor( + name = "Wiki", + description = "Adds a Wiki button that takes you to the OSRS Wiki" +) +public class WikiPlugin extends Plugin +{ + private static final int[] QUESTLIST_WIDGET_IDS = new int[] + { + WidgetInfo.QUESTLIST_FREE_CONTAINER.getId(), + WidgetInfo.QUESTLIST_MEMBERS_CONTAINER.getId(), + WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER.getId(), + }; + + static final String WIKI_BASE = "https://oldschool.runescape.wiki"; + static final HttpUrl WIKI_RSLOOKUP = HttpUrl.parse(WIKI_BASE + "/w/Special:Lookup"); + static final HttpUrl WIKI_API = HttpUrl.parse(WIKI_BASE + "/api.php"); + static final String UTM_SORUCE_KEY = "utm_source"; + static final String UTM_SORUCE_VALUE = "runelite"; + static final String UTM_PARAMS = UTM_SORUCE_KEY + "=" + UTM_SORUCE_VALUE; + + private static final String MENUOP_GUIDE = "Guide"; + private static final String MENUOP_QUICKGUIDE = "Quick Guide"; + + @Inject + private SpriteManager spriteManager; + + @Inject + private ClientThread clientThread; + + @Inject + private Client client; + + @Inject + private ChatboxPanelManager chatboxPanelManager; + + @Inject + private ItemManager itemManager; + + @Inject + private Provider wikiSearchChatboxTextInputProvider; + + private Widget icon; + + private boolean wikiSelected = false; + + @Override + public void startUp() + { + spriteManager.addSpriteOverrides(WikiSprite.values()); + clientThread.invokeLater(this::addWidgets); + } + + @Override + public void shutDown() + { + spriteManager.removeSpriteOverrides(WikiSprite.values()); + clientThread.invokeLater(() -> + { + 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; + }); + } + + @Subscribe + private void onWidgetLoaded(WidgetLoaded l) + { + if (l.getGroupId() == WidgetID.MINIMAP_GROUP_ID) + { + addWidgets(); + } + } + + private void addWidgets() + { + Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS); + if (minimapOrbs == null) + { + return; + } + + icon = minimapOrbs.createChild(0, WidgetType.GRAPHIC); + icon.setSpriteId(WikiSprite.WIKI_ICON.getSpriteId()); + icon.setOriginalX(0); + icon.setOriginalY(2); + icon.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); + icon.setYPositionMode(WidgetPositionMode.ABSOLUTE_BOTTOM); + icon.setOriginalWidth(42); + icon.setOriginalHeight(16); + icon.setTargetVerb("Lookup"); + icon.setName("Wiki"); + icon.setClickMask(WidgetConfig.USE_GROUND_ITEM | WidgetConfig.USE_ITEM | WidgetConfig.USE_NPC); + icon.setNoClickThrough(true); + icon.setOnTargetEnterListener((JavaScriptCallback) ev -> + { + wikiSelected = true; + icon.setSpriteId(WikiSprite.WIKI_SELECTED_ICON.getSpriteId()); + }); + icon.setAction(5, "Search"); // Start at option 5 so the target op is ontop + icon.setOnOpListener((JavaScriptCallback) ev -> + { + switch (ev.getOp()) + { + case 6: + openSearchInput(); + break; + } + }); + // This doesn't always run because we cancel the menuop + icon.setOnTargetLeaveListener((JavaScriptCallback) ev -> onDeselect()); + icon.revalidate(); + } + + private void onDeselect() + { + wikiSelected = false; + icon.setSpriteId(WikiSprite.WIKI_ICON.getSpriteId()); + } + + @Subscribe + private void onMenuOptionClicked(MenuOptionClicked ev) + { + if (wikiSelected) + { + onDeselect(); + client.setSpellSelected(false); + ev.consume(); + + String type; + int id; + String name; + switch (ev.getMenuAction()) + { + case CANCEL: + return; + case ITEM_USE_ON_WIDGET: + case SPELL_CAST_ON_GROUND_ITEM: + { + type = "item"; + id = itemManager.canonicalize(ev.getId()); + name = itemManager.getItemComposition(id).getName(); + break; + } + case SPELL_CAST_ON_NPC: + { + type = "npc"; + NPC npc = client.getCachedNPCs()[ev.getId()]; + NPCComposition nc = npc.getTransformedComposition(); + id = nc.getId(); + name = nc.getName(); + break; + } + default: + log.info("Unknown menu option: {} {} {}", ev, ev.getMenuAction(), ev.getMenuAction() == MenuAction.CANCEL); + return; + } + + HttpUrl url = WIKI_RSLOOKUP.newBuilder() + .addQueryParameter("type", type) + .addQueryParameter("id", "" + id) + .addQueryParameter("name", name) + .addQueryParameter(UTM_SORUCE_KEY, UTM_SORUCE_VALUE) + .build(); + + LinkBrowser.browse(url.toString()); + return; + } + + if (ev.getMenuAction() == MenuAction.RUNELITE) + { + String quickguide = ""; + switch (ev.getMenuOption()) + { + case MENUOP_QUICKGUIDE: + quickguide = "/Quick_guide"; + //fallthrough; + case MENUOP_GUIDE: + ev.consume(); + String quest = Text.removeTags(ev.getMenuTarget()); + LinkBrowser.browse(WIKI_BASE + "/w/" + URLEncoder.encode(quest.replace(' ', '_')) + quickguide + "?" + UTM_PARAMS); + break; + } + } + } + + private void openSearchInput() + { + wikiSearchChatboxTextInputProvider.get() + .build(); + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded event) + { + int widgetIndex = event.getActionParam0(); + int widgetID = event.getActionParam1(); + + if (!Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) || !"Read Journal:".equals(event.getOption())) + { + return; + } + + MenuEntry[] menuEntries = client.getMenuEntries(); + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 2); + + MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); + menuEntry.setTarget(event.getTarget()); + menuEntry.setOption(MENUOP_GUIDE); + menuEntry.setParam0(widgetIndex); + menuEntry.setParam1(widgetID); + menuEntry.setType(MenuAction.RUNELITE.getId()); + + menuEntry = menuEntries[menuEntries.length - 2] = new MenuEntry(); + menuEntry.setTarget(event.getTarget()); + menuEntry.setOption(MENUOP_QUICKGUIDE); + menuEntry.setParam0(widgetIndex); + menuEntry.setParam1(widgetID); + menuEntry.setType(MenuAction.RUNELITE.getId()); + + client.setMenuEntries(menuEntries); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java new file mode 100644 index 0000000000..51ea075d2f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2018 Abex + * 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.plugins.wiki; + +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.inject.Inject; +import java.awt.event.KeyEvent; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.inject.Named; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.game.chatbox.ChatboxPanelManager; +import net.runelite.client.game.chatbox.ChatboxTextInput; +import net.runelite.client.util.LinkBrowser; +import net.runelite.http.api.RuneLiteAPI; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; + +@Slf4j +public class WikiSearchChatboxTextInput extends ChatboxTextInput +{ + private static final int LINE_HEIGHT = 20; + private static final int CHATBOX_HEIGHT = 120; + private static final int MAX_NUM_PREDICTIONS = (CHATBOX_HEIGHT / LINE_HEIGHT) - 2; // 1 title, 1 edit + + private static final int PREDICTION_DEBOUNCE_DELAY_MS = 200; + + private final ChatboxPanelManager chatboxPanelManager; + private final Gson gson = new Gson(); + + private Future runningRequest = null; + private List predictions = ImmutableList.of(); + + private int selectedPrediction = -1; + private String offPrediction = null; + + @Inject + public WikiSearchChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread, + ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode) + { + super(chatboxPanelManager, clientThread); + this.chatboxPanelManager = chatboxPanelManager; + + prompt("OSRS Wiki Search"); + onDone(string -> + { + if (string != null && string.length() > 0) + { + search(string); + } + }); + onChanged(searchString -> + { + selectedPrediction = -1; + Future rr = runningRequest; + if (rr != null) + { + rr.cancel(false); + } + if (searchString.length() <= 1) + { + runningRequest = null; + clientThread.invokeLater(() -> + { + predictions = ImmutableList.of(); + update(); + }); + return; + } + runningRequest = scheduledExecutorService.schedule(() -> + { + HttpUrl url = WikiPlugin.WIKI_API.newBuilder() + .addQueryParameter("action", "opensearch") + .addQueryParameter("search", searchString) + .addQueryParameter("redirects", "resolve") + .addQueryParameter("format", "json") + .addQueryParameter("warningsaserror", Boolean.toString(developerMode)) + .build(); + + Request req = new Request.Builder() + .url(url) + .build(); + + RuneLiteAPI.CLIENT.newCall(req).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException e) + { + log.warn("error searching wiki", e); + } + + @Override + public void onResponse(Call call, Response response) throws IOException + { + String body = response.body().string(); + try + { + JsonArray jar = new JsonParser().parse(body).getAsJsonArray(); + List apredictions = gson.fromJson(jar.get(1), new TypeToken>() + { + }.getType()); + + if (apredictions.size() > MAX_NUM_PREDICTIONS) + { + apredictions = apredictions.subList(0, MAX_NUM_PREDICTIONS); + } + + final List bpredictions = apredictions; + + clientThread.invokeLater(() -> + { + predictions = bpredictions; + update(); + }); + } + catch (JsonParseException | IllegalStateException | IndexOutOfBoundsException e) + { + log.warn("error parsing wiki response {}", body, e); + } + finally + { + response.close(); + } + } + }); + + runningRequest = null; + }, PREDICTION_DEBOUNCE_DELAY_MS, TimeUnit.MILLISECONDS); + }); + } + + @Override + protected void update() + { + Widget container = chatboxPanelManager.getContainerWidget(); + container.deleteAllChildren(); + + Widget promptWidget = container.createChild(-1, WidgetType.TEXT); + promptWidget.setText(getPrompt()); + promptWidget.setTextColor(0x800000); + promptWidget.setFontId(getFontID()); + promptWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + promptWidget.setOriginalX(0); + promptWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + promptWidget.setOriginalY(5); + promptWidget.setOriginalHeight(LINE_HEIGHT); + promptWidget.setXTextAlignment(WidgetTextAlignment.CENTER); + promptWidget.setYTextAlignment(WidgetTextAlignment.CENTER); + promptWidget.setWidthMode(WidgetSizeMode.MINUS); + promptWidget.revalidate(); + + buildEdit(0, 5 + LINE_HEIGHT, container.getWidth(), LINE_HEIGHT); + + Widget separator = container.createChild(-1, WidgetType.LINE); + separator.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + separator.setOriginalX(0); + separator.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + separator.setOriginalY(4 + (LINE_HEIGHT * 2)); + separator.setOriginalHeight(0); + separator.setOriginalWidth(16); + separator.setWidthMode(WidgetSizeMode.MINUS); + separator.revalidate(); + + for (int i = 0; i < predictions.size(); i++) + { + String pred = predictions.get(i); + int y = 6 + (LINE_HEIGHT * (2 + i)); + + Widget bg = container.createChild(-1, WidgetType.RECTANGLE); + bg.setTextColor(0x4444DD); + bg.setFilled(true); + bg.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + bg.setOriginalX(1); + bg.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + bg.setOriginalY(y); + bg.setOriginalHeight(LINE_HEIGHT); + bg.setOriginalWidth(16); + bg.setWidthMode(WidgetSizeMode.MINUS); + bg.revalidate(); + bg.setName("" + pred); + bg.setAction(0, "Open"); + bg.setHasListener(true); + bg.setOnOpListener((JavaScriptCallback) ev -> search(pred)); + + Widget text = container.createChild(-1, WidgetType.TEXT); + text.setText(pred); + text.setFontId(getFontID()); + text.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + text.setOriginalX(0); + text.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + text.setOriginalY(y); + text.setOriginalHeight(LINE_HEIGHT); + text.setXTextAlignment(WidgetTextAlignment.CENTER); + text.setYTextAlignment(WidgetTextAlignment.CENTER); + text.setWidthMode(WidgetSizeMode.MINUS); + text.revalidate(); + + if (i == selectedPrediction) + { + text.setTextColor(0xFFFFFF); + } + else + { + bg.setOpacity(255); + text.setTextColor(0x000000); + bg.setOnMouseRepeatListener((JavaScriptCallback) ev -> text.setTextColor(0xFFFFFF)); + bg.setOnMouseLeaveListener((JavaScriptCallback) ev -> text.setTextColor(0x000000)); + } + } + } + + @Override + public void keyPressed(KeyEvent ev) + { + switch (ev.getKeyCode()) + { + case KeyEvent.VK_UP: + ev.consume(); + if (selectedPrediction > -1) + { + selectedPrediction--; + if (selectedPrediction == -1) + { + value(offPrediction); + } + else + { + value(predictions.get(selectedPrediction)); + } + } + break; + case KeyEvent.VK_DOWN: + ev.consume(); + + if (selectedPrediction == -1) + { + offPrediction = getValue(); + } + + selectedPrediction++; + if (selectedPrediction >= predictions.size()) + { + selectedPrediction = predictions.size() - 1; + } + + if (selectedPrediction != -1) + { + value(predictions.get(selectedPrediction)); + } + break; + default: + super.keyPressed(ev); + } + } + + private void search(String search) + { + LinkBrowser.browse(WikiPlugin.WIKI_BASE + "?search=" + URLEncoder.encode(search) + "&" + WikiPlugin.UTM_PARAMS); + chatboxPanelManager.close(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSprite.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSprite.java new file mode 100644 index 0000000000..188d54837b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSprite.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Abex + * 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.plugins.wiki; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.runelite.api.SpriteID; +import net.runelite.client.game.SpriteOverride; + +@RequiredArgsConstructor +public enum WikiSprite implements SpriteOverride +{ + WIKI_ICON(-300, "wiki.png"), + WIKI_SELECTED_ICON(-301, "wiki_selected.png"), + FIXED_MODE_MINIMAP_CLICKMASK(SpriteID.MINIMAP_CLICK_MASK, "fixed_mode_minimap_clickmask.png"); + + @Getter + private final int spriteId; + + @Getter + private final String fileName; +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/fixed_mode_minimap_clickmask.png b/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/fixed_mode_minimap_clickmask.png new file mode 100644 index 0000000000000000000000000000000000000000..e4f5fcbe48dab813a165f99d60a28acb3c4cb4ec GIT binary patch literal 2027 zcmcIlTWB0r7@la9B#@f45`wj1cCruEc6QFpUS?1yMev3cMSPKB>Y2TzN*eRx!r3`< z<~!g2egFCApPA8-;qI>cx-bmuP73ifx>nJ6qvLM$f6uk0pU|b#6rQj#Y{!Z_+Fswc zV>gD~^^2CtI@#0_UN(w8Q86UwD;G_K#;^m2%BCofK?j#$PSYdAuOEIw;F=O4jt5g9 zWyWA$6Q(S9Y-%JUPmRf(LL54XA1L#Ppa>liFBc2C&6guYjh9DrcbOva8pIik5JPT2 zJewNDV}=Fspf5zqbb!HG&PRs;#{~A{44_#GuoUel0nLLD@8|Hwk3i8ZMdj1+!;M(z zE<)rT$K)xhR4VyOexG6GD4OFq3NRGIkO)EAle#08N!=c7GQ^=RTbk);hK{?8qGXIa z5dtZ#TPT_>THS7>2_=jwizY?;fNQA0U`U$D0FGw>@25$?@&MGKDO3fD=!n|` z8;Yh*ZU>r5@k!lwL|ul-c!WTre43{4Qjk?uT4l)~U;xQT0fm&pVMt0rh6zBRNDQmi zbfNumLmqdN=kBi;tzyWCqm>`tAMgWO1`?@+0zs070h#20#E@ZC3c`>Kf$XQ7Y)35( zy*FavR#sP)f*56m4YI6XCRs`3$dDQUq!gfK(k})9%LD>UkoFU}BJ-+Y6-87fT2ahF z%G7fNzM&>&6bvh6C@AL$y|JE*#YQbd)e7i=ogR+j$wVwfbDSx%o$5YwukP_gxlr?9GD< z7yI6S`uyCfFT0Q4Twh&$b>_y;18uva?>>_Cu62F>pg5P^=Y6}9hzcE@p66zJc1EKD z?yaoc8C(7B?2>S)@>VLd54*cP z-rDYtPPEXov$jxaM|A%n-V__X18v?6+n{Oku6*x->ip!AtFSU#J|gsfbbU|w1L03@ zzWuYs)9-zA=Gv8qs%QGAzV6$#ync0MW$D{zY1-?h>HW3Q-&cL?65;Xc{nf8__qmFj zLHG0yxCFMbUo)=G^eaSnp@YnkCGs3CGi62gG qB+eiI%DxT4gcN!948Ya@$=CqpZ^xa46!9fH5jwbZ(M#Btkgk&>#X1u*ym&-64S_9g}c79tem!A~?W! zAjb%ZhzR0=g5tylWx-)p@L&`L2R$(tFF7>xB1fP?y6U>-v9rvsTTJDfup=4E5gnr0FKKMYX?a|m3`gm_<` z2i^fyAb4vc0}xQ?R6G+TQW#{AO1HvO$rL7u%p_500GYxjGuSi`Kl&kHvngO9+tYE? z=v>$vhagg^(z38RcpB^RM8R4GC~ z5yyDAr-O7r>AT`Zw?}l5NfS7cdHog%Mu@< zF`gf`Kqw&dLAnqCK?)OK3g|EZ(wJDNLK>4V#(!a$rzE1_PiHDH_vbGO%!6#7eBf5u?k<3)wvS zBoX6>y~&0InkB&@2sB*L1UuN}Bg!1Rb_utpxDMDtoDGuCpPlZup~<7se%m+e8nt*y6Q(}P zBF7U~wxvF?k1-6{+r9geVO&6cz=ac%pfu%9otd-p4g&gy$J~>Oq1u4CRe8qu<1>?o ze)?%jY<$BU|1*`g?%Uei!XoS1o1%XCeJ~Ao^*K^>Xx_?$Ss*;=j z7bDNO$7Z4gPn}za^R6Guhy~p16ZON^KJ*-_Nu%weh|DTl6|(dhuz+(@Ou=;Qr*TR=!CWpY+(hpR(z$Byu1KUv+d4UV9vA zkGi~0mR(n^47{Kndp9B56Wl|8sUyuD9Xp-tqz7uAYqbWWSzMiiwUKhE=c_!v=%rvxZGS3Jm6_;M>1BQ@$q!dJsvmNqVU13W34*&g>E{#e{2Cg zqNhEPuQjvFaVL5dY{TUTD!U?Q&Yh_j>ycb=e8}7Xf^v0ODpxt_>emCCLlCCU;p6e| zy|#P#cLoJtiEQfUWtYr7s8(C<(k)CY+EUbaJ2v4Cu8R%l&b2 z)!N@fg0-UqlA;ezIviurSQ^=vt=(Y-yV>Cu_EJxn$Z@Uwj$8emleeGHUToW6R8ri0 z)i37Jw$9Sl0nuU~y&r!+diOi&&I%QMYWQ2X1lztBb?v4VEZ=(}d7<~5YD>z_6ue!$ z?c18fnyzV2E10UIV8ahjC#mft9@_lF=3z6-@W<)7(-mO}MwNne(>j1yzun~Ng2MFh^xsmZqs0_f_! zlOO2!?KE%gt=n<9cZ*(Nf1~OChKv(SZkPu^UFQ#^yh~Yhvan`dsLHp-=-dioPdX~~ zI}FdJ?f%=Hs0#(J9+e>uo6h)347jCeMZe)JtthMYDYn9;Ez;Z~`3+0G6*))hH`hgX zdZ?e75pQ$2&a2%gzno6*bWG6`$HNLXlnml-<>0QQF&Sk?MCOO+nvaq&$ujYTdtCPE9p?yH~ALf0np8x;= literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..80838fb5c4f5f4406f0570212fb7e9825664b7ee GIT binary patch literal 3025 zcmcIm3s@6Z8V#VxLoA?(unHkytCq=|yh;>EKq5pbusp;ElbHzwl1#`1608)#7b=1l z7b>(A5d|Mu1XNg-mx9=86(4AqsuZo7x+se%MHJi#uXVfXy8C^bFO!+M_uO;O`Tzgk zn{7eMms(jkS`Y{XE0Mo27{4#VFKaVX{5P8PXcvAnSNTU`1cK#E!(~Ls|7s3_V0uy( z8lj002l60PK?Y$|f{=9z6^ih!P}5rsR`)>l#T!8O$ezdx)uGl>mvA z`L9zWA?uchLhIroE=*donCPkF;RFgq0}^!#xf0{)_@q%@9{y}-rjUrE5KTOvMdi|&?nFA3#->o&6dD7d(s)!BkHIC5e@OUjYFNq( z7W$3Pg}?Dhu^NqvN1D#p z#m8j#q#G4aphiFqst!d_`9z|ECRm690dYaNObMe}Y@tEVI2;jz8iY^6bH)K^G=ROb7rOY!JZP5GoyHND!uER2M#8h(d{m;2Fk`6)lWHILBms zc#ssLO1MlZz~$1|02^Y$0GGkWtx6eeiB!U1Nm$YewiRj_zHUJI>#PPe;I~nIC*>-g&+yzPjVS? zv^IGlWLOe>5@e_a1SX9)%ia*?_cJs`tBpl)(sxwJ7z{(D8ZD?sykqc`{D&H(yiGa= zCcRrY6JgOk*dBOBIS2x9U?u|qsS*(2a6LF|CY#HZcpwwT{|~~)Lkh)$$`}OSTPdXf z-OBrw`df1F`^ER)=itp&D25GnthOk>FT2sc*EU}~iK9*Uj&69IJWBAF$-@Xy;!#rL zN6nE-3u+03Da|6Gcc_0`M{cUWByv`pYr2_@i;r7|wT;kc(=Ia?q1&zuGm?+7%{DKg z(AwO_+pW0u)}Jy?9JKNH&ZLuuT)N5Ax4>1m$hv+2W>zWw^D@^i~nsl}z!r0%oZpG?Us zGRkq_C400Upfs7z3+rq;*3#42Z*;g)9ouXz7A@3ZoFc!jOjQcWru=Sbnps!Amw zef3>8pPcOv?YVchJEy!tMBL=j^>-KX?ymX8seE}8=Z;%#?qc1uvi-%jNsqUZYDzzH zNO3$Va*VznH#ILf#r$E|A<*^bORE))#ZFLB`i!XC+8d$;r)p-HmIQkdiWaEjTHuU$ z_=@G7r-OxQl#&6~jc+#D8`tHpB)2p9%cPY1b1MG2IKcSEu)6ox0q4)Ra(C-SIG!1V z<+a9P4Nj-ILj_lb^79`mHpr?R=86vo1nsYB(DN4>cjWHzZhvliZJ}+*@_lAo>?|Uj zRCIPquIG*idK`7f-LA5OeR@x`&Z^qkS$}W1BhV(+NL|t3G!*wd&~jGV zGU`*$d23q-zs<;LaZJc<*gB$O<&4x;mCVggD7;{EKH{;1Ywm5gV}jXFUR;o=ho9#nx9x&(tK;XPwR*I=3q6HaUKSdCDb^c83e957z3cJm>k6KDr=vT{hpn@rSaz zKv_6>nmBUmU}C=8+3dp7J1)K>VV&B9!ZpbHgL#8c{;Qa&aGi6SV)^kXME9)q)&b<*;&D21yBDzHf(18@$Hs5ro#o9 z+y6%P=F=UjpTuJ=$wQ^*?mW%1hK~3Abo_@PVRj|dwr24s+ZEBzAM_5?1v?$s9{6bS zXL~wtnSW3gS}Waj-Zo~C__MeTYJ6c;&s`DlaiHVQS^EnDYb}eC_E761(lu zwEE6JZl<>$PLF%KcZxoF{Vu3?$K|e6+t1U0%F2561Fy)lTV`Af_}XiFTKcS<3v`gk=-Jp>yYA}UD2Um(w#Qn z++5zj8z)pIB{j_r!hT(g0B06!)@7Lq+&_0 fO4qLVCVkjy5t=M<8GgCO@TXhkyIgq8Cp!Hfq9Brt literal 0 HcmV?d00001 diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index 04ac90d398..23c2558a16 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -921,4 +921,8 @@ public interface RSClient extends RSGameEngine, Client @Import("endY") int getEndY(); + + @Import("spellSelected") + @Override + void setSpellSelected(boolean selected); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index 75315b0514..0dd5b24d4f 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -328,6 +328,10 @@ public interface RSWidget extends Widget @Override void setOnMouseOverListener(Object... args); + @Import("onMouseRepeatListener") + @Override + void setOnMouseRepeatListener(Object... args); + @Import("onMouseLeaveListener") @Override void setOnMouseLeaveListener(Object... args); @@ -336,6 +340,14 @@ public interface RSWidget extends Widget @Override void setOnTimerListener(Object... args); + @Import("onTargetEnterListener") + @Override + void setOnTargetEnterListener(Object... args); + + @Import("onTargetLeaveListener") + @Override + void setOnTargetLeaveListener(Object... args); + @Import("fontId") @Override int getFontId(); @@ -435,4 +447,28 @@ public interface RSWidget extends Widget @Import("filled") @Override void setFilled(boolean filled); + + @Import("targetVerb") + @Override + String getTargetVerb(); + + @Import("targetVerb") + @Override + void setTargetVerb(String targetVerb); + + @Import("noClickThrough") + @Override + boolean getNoClickThrough(); + + @Import("noClickThrough") + @Override + void setNoClickThrough(boolean noClickThrough); + + @Import("noScrollThrough") + @Override + boolean getNoScrollThrough(); + + @Import("noScrollThrough") + @Override + void setNoScrollThrough(boolean noScrollThrough); } From da67381ba771869325adaf5ad6069209c71239f0 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 9 Feb 2019 11:42:40 -0500 Subject: [PATCH 021/102] Add GE history tracker Add http service to log completed trades, and submit trades when completed. --- .../http/api/ge/GrandExchangeClient.java | 78 ++++++++++ .../http/api/ge/GrandExchangeTrade.java | 38 +++++ .../service/ge/GrandExchangeController.java | 111 ++++++++++++++ .../http/service/ge/GrandExchangeService.java | 113 +++++++++++++++ .../runelite/http/service/ge/TradeAction.java | 31 ++++ .../runelite/http/service/ge/TradeEntry.java | 40 ++++++ .../grandexchange/GrandExchangePlugin.java | 136 +++++++++++++++++- .../plugins/grandexchange/SavedOffer.java | 39 +++++ 8 files changed, 583 insertions(+), 3 deletions(-) create mode 100644 http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java create mode 100644 http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java create mode 100644 http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java create mode 100644 http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java create mode 100644 http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java create mode 100644 http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/SavedOffer.java diff --git a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java new file mode 100644 index 0000000000..a1b97bc390 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.api.ge; + +import com.google.gson.Gson; +import java.io.IOException; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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 +@AllArgsConstructor +public class GrandExchangeClient +{ + private static final MediaType JSON = MediaType.parse("application/json"); + private static final Gson GSON = RuneLiteAPI.GSON; + + private final UUID uuid; + + public void submit(GrandExchangeTrade grandExchangeTrade) + { + final HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() + .addPathSegment("ge") + .build(); + + Request request = new Request.Builder() + .header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString()) + .post(RequestBody.create(JSON, GSON.toJson(grandExchangeTrade))) + .url(url) + .build(); + + RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException e) + { + log.debug("unable to submit trade", e); + } + + @Override + public void onResponse(Call call, Response response) + { + log.debug("Submitted trade"); + response.close(); + } + }); + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java new file mode 100644 index 0000000000..b5d0012b16 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.api.ge; + +import java.time.Instant; +import lombok.Data; + +@Data +public class GrandExchangeTrade +{ + private boolean buy; + private int itemId; + private int quantity; + private int price; + private Instant time; +} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java new file mode 100644 index 0000000000..94c759b130 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.ge; + +import java.io.IOException; +import java.util.Collection; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import net.runelite.http.api.ge.GrandExchangeTrade; +import net.runelite.http.service.account.AuthFilter; +import net.runelite.http.service.account.beans.SessionEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/ge") +public class GrandExchangeController +{ + private final GrandExchangeService grandExchangeService; + private final AuthFilter authFilter; + + @Autowired + public GrandExchangeController(GrandExchangeService grandExchangeService, AuthFilter authFilter) + { + this.grandExchangeService = grandExchangeService; + this.authFilter = authFilter; + } + + @PostMapping + public void submit(HttpServletRequest request, HttpServletResponse response, @RequestBody GrandExchangeTrade grandExchangeTrade) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return; + } + + grandExchangeService.add(session.getUser(), grandExchangeTrade); + } + + @GetMapping + public Collection get(HttpServletRequest request, HttpServletResponse response, + @RequestParam(required = false, defaultValue = "1024") int limit, + @RequestParam(required = false, defaultValue = "0") int offset) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return null; + } + + return grandExchangeService.get(session.getUser(), limit, offset).stream() + .map(GrandExchangeController::convert) + .collect(Collectors.toList()); + } + + private static GrandExchangeTrade convert(TradeEntry tradeEntry) + { + GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); + grandExchangeTrade.setBuy(tradeEntry.getAction() == TradeAction.BUY); + grandExchangeTrade.setItemId(tradeEntry.getItem()); + grandExchangeTrade.setQuantity(tradeEntry.getQuantity()); + grandExchangeTrade.setPrice(tradeEntry.getPrice()); + grandExchangeTrade.setTime(tradeEntry.getTime()); + return grandExchangeTrade; + } + + @DeleteMapping + public void delete(HttpServletRequest request, HttpServletResponse response) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return; + } + + grandExchangeService.delete(session.getUser()); + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java new file mode 100644 index 0000000000..6456beb85f --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeService.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.ge; + +import java.util.Collection; +import net.runelite.http.api.ge.GrandExchangeTrade; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.sql2o.Connection; +import org.sql2o.Sql2o; + +@Service +public class GrandExchangeService +{ + private static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS `ge_trades` (\n" + + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + + " `user` int(11) NOT NULL,\n" + + " `action` enum('BUY','SELL') NOT NULL,\n" + + " `item` int(11) NOT NULL,\n" + + " `quantity` int(11) NOT NULL,\n" + + " `price` int(11) NOT NULL,\n" + + " `time` timestamp NOT NULL DEFAULT current_timestamp(),\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `user_time` (`user`, `time`),\n" + + " KEY `time` (`time`),\n" + + " CONSTRAINT `ge_trades_ibfk_1` FOREIGN KEY (`user`) REFERENCES `users` (`id`)\n" + + ") ENGINE=InnoDB;"; + + private final Sql2o sql2o; + + @Autowired + public GrandExchangeService(@Qualifier("Runelite SQL2O") Sql2o sql2o) + { + this.sql2o = sql2o; + + // Ensure necessary tables exist + try (Connection con = sql2o.open()) + { + con.createQuery(CREATE_TABLE).executeUpdate(); + } + } + + public void add(int userId, GrandExchangeTrade grandExchangeTrade) + { + try (Connection con = sql2o.open()) + { + con.createQuery("insert into ge_trades (user, action, item, quantity, price) values (:user," + + " :action, :item, :quantity, :price)") + .addParameter("user", userId) + .addParameter("action", grandExchangeTrade.isBuy() ? "BUY" : "SELL") + .addParameter("item", grandExchangeTrade.getItemId()) + .addParameter("quantity", grandExchangeTrade.getQuantity()) + .addParameter("price", grandExchangeTrade.getPrice()) + .executeUpdate(); + } + } + + public Collection get(int userId, int limit, int offset) + { + try (Connection con = sql2o.open()) + { + return con.createQuery("select id, user, action, item, quantity, price, time from ge_trades where user = :user limit :limit offset :offset") + .addParameter("user", userId) + .addParameter("limit", limit) + .addParameter("offset", offset) + .executeAndFetch(TradeEntry.class); + } + } + + public void delete(int userId) + { + try (Connection con = sql2o.open()) + { + con.createQuery("delete from ge_trades where user = :user") + .addParameter("user", userId) + .executeUpdate(); + } + } + + @Scheduled(fixedDelay = 60 * 60 * 1000) + public void expire() + { + try (Connection con = sql2o.open()) + { + con.createQuery("delete from ge_trades where time < current_timestamp - interval 1 month") + .executeUpdate(); + } + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java b/http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java new file mode 100644 index 0000000000..fcc96d615f --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/ge/TradeAction.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.ge; + +enum TradeAction +{ + BUY, + SELL; +} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java b/http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java new file mode 100644 index 0000000000..bca3869811 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/ge/TradeEntry.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.ge; + +import java.time.Instant; +import lombok.Data; + +@Data +class TradeEntry +{ + private int id; + private int user; + private TradeAction action; + private int item; + private int quantity; + private int price; + private Instant time; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index c26e39ebb5..5a59ede074 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -1,5 +1,5 @@ /* - * + * Copyright (c) 2019, Adam * Copyright (c) 2017, Robbie * Copyright (c) 2018, SomeoneWithAnInternetConnection * All rights reserved. @@ -46,6 +46,7 @@ import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.GrandExchangeOffer; +import net.runelite.api.GrandExchangeOfferState; import net.runelite.api.ItemComposition; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; @@ -56,11 +57,15 @@ import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.GrandExchangeOfferChanged; import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.SessionClose; +import net.runelite.api.events.SessionOpen; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.Notifier; +import net.runelite.client.account.AccountSession; +import net.runelite.client.account.SessionManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; @@ -73,6 +78,8 @@ import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.ImageUtil; import net.runelite.client.util.StackFormatter; import net.runelite.client.util.Text; +import net.runelite.http.api.ge.GrandExchangeClient; +import net.runelite.http.api.ge.GrandExchangeTrade; import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; import net.runelite.http.api.osbuddy.OSBGrandExchangeResult; @@ -134,10 +141,38 @@ public class GrandExchangePlugin extends Plugin @Inject private ScheduledExecutorService executorService; + @Inject + private SessionManager sessionManager; + + @Inject + private ConfigManager configManager; + private Widget grandExchangeText; private Widget grandExchangeItem; private Map itemGELimits; + private GrandExchangeClient grandExchangeClient; + + private SavedOffer getOffer(int slot) + { + String offer = configManager.getConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot)); + if (offer == null) + { + return null; + } + return GSON.fromJson(offer, SavedOffer.class); + } + + private void setOffer(int slot, SavedOffer offer) + { + configManager.setConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot), GSON.toJson(offer)); + } + + private void deleteOffer(int slot) + { + configManager.unsetConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot)); + } + @Provides GrandExchangeConfig provideConfig(ConfigManager configManager) { @@ -167,6 +202,12 @@ public class GrandExchangePlugin extends Plugin mouseManager.registerMouseListener(inputListener); keyManager.registerKeyListener(inputListener); } + + AccountSession accountSession = sessionManager.getAccountSession(); + if (accountSession != null) + { + grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); + } } @Override @@ -178,6 +219,27 @@ public class GrandExchangePlugin extends Plugin grandExchangeText = null; grandExchangeItem = null; itemGELimits = null; + grandExchangeClient = null; + } + + @Subscribe + public void onSessionOpen(SessionOpen sessionOpen) + { + AccountSession accountSession = sessionManager.getAccountSession(); + if (accountSession.getUuid() != null) + { + grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); + } + else + { + grandExchangeClient = null; + } + } + + @Subscribe + public void onSessionClose(SessionClose sessionClose) + { + grandExchangeClient = null; } @Subscribe @@ -204,11 +266,79 @@ public class GrandExchangePlugin extends Plugin @Subscribe public void onGrandExchangeOfferChanged(GrandExchangeOfferChanged offerEvent) { - GrandExchangeOffer offer = offerEvent.getOffer(); + final int slot = offerEvent.getSlot(); + final GrandExchangeOffer offer = offerEvent.getOffer(); + ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId()); boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1; BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack); - SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offerEvent.getOffer(), offerEvent.getSlot())); + SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offer, slot)); + + submitTrades(slot, offer); + + updateConfig(slot, offer); + } + + private void submitTrades(int slot, GrandExchangeOffer offer) + { + if (grandExchangeClient == null) + { + return; + } + + // Only interested in offers which are fully bought/sold + if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD) + { + return; + } + + SavedOffer savedOffer = getOffer(slot); + if (!shouldUpdate(savedOffer, offer)) + { + return; + } + + // getPrice() is the price of the offer, not necessarily what the item bought at + int priceEach = offer.getSpent() / offer.getTotalQuantity(); + + GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); + grandExchangeTrade.setBuy(offer.getState() == GrandExchangeOfferState.BOUGHT); + grandExchangeTrade.setItemId(offer.getItemId()); + grandExchangeTrade.setQuantity(offer.getTotalQuantity()); + grandExchangeTrade.setPrice(priceEach); + + log.debug("Submitting trade: {}", grandExchangeTrade); + grandExchangeClient.submit(grandExchangeTrade); + } + + private void updateConfig(int slot, GrandExchangeOffer offer) + { + if (offer.getState() == GrandExchangeOfferState.EMPTY) + { + deleteOffer(slot); + } + else + { + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(offer.getItemId()); + savedOffer.setQuantitySold(offer.getQuantitySold()); + savedOffer.setTotalQuantity(offer.getTotalQuantity()); + savedOffer.setPrice(offer.getPrice()); + savedOffer.setSpent(offer.getSpent()); + savedOffer.setState(offer.getState()); + setOffer(slot, savedOffer); + } + } + + private boolean shouldUpdate(SavedOffer savedOffer, GrandExchangeOffer grandExchangeOffer) + { + if (savedOffer == null) + { + return false; + } + + // Only update offer if state has changed + return savedOffer.getState() != grandExchangeOffer.getState(); } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/SavedOffer.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/SavedOffer.java new file mode 100644 index 0000000000..58a4055fed --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/SavedOffer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Adam + * 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.plugins.grandexchange; + +import lombok.Data; +import net.runelite.api.GrandExchangeOfferState; + +@Data +class SavedOffer +{ + private int itemId; + private int quantitySold; + private int totalQuantity; + private int price; + private int spent; + private GrandExchangeOfferState state; +} From d59e7846d757718dea1c0c7acffd02dc448c0bd6 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 12 Feb 2019 12:24:02 +0000 Subject: [PATCH 022/102] Export ItemCompositionCache Signed-off-by: Tomas Slusny --- runelite-api/src/main/java/net/runelite/api/Client.java | 5 +++++ .../src/main/java/net/runelite/rs/api/RSClient.java | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 652eb00806..a410eb96a6 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1574,4 +1574,9 @@ public interface Client extends GameEngine * Sets if a widget is in target mode */ void setSpellSelected(boolean selected); + + /** + * Returns client item composition cache + */ + NodeCache getItemCompositionCache(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index 23c2558a16..587eceb6e1 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -785,6 +785,10 @@ public interface RSClient extends RSGameEngine, Client @Override RSNodeCache getWidgetSpriteCache(); + @Import("items") + @Override + RSNodeCache getItemCompositionCache(); + @Import("oculusOrbState") @Override int getOculusOrbState(); From 09d324e12960a7aec297abea1b6c87f95f48ae3e Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 12 Feb 2019 12:24:15 +0000 Subject: [PATCH 023/102] Reset item composition cache on menu shift click change Signed-off-by: Tomas Slusny --- .../net/runelite/client/game/ItemManager.java | 9 +++++++ .../MenuEntrySwapperPlugin.java | 27 +++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index ad06024a7d..c91de9262c 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -256,6 +256,15 @@ public class ItemManager itemCompositions.put(event.getItemComposition().getId(), event.getItemComposition()); } + /** + * Invalidates internal item manager item composition cache (but not client item composition cache) + * @see Client#getItemCompositionCache() + */ + public void invalidateItemCompositionCache() + { + itemCompositions.invalidateAll(); + } + /** * Look up an item's price * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 8300333570..ca62eca65e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -45,8 +45,10 @@ import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.events.PostItemComposition; import net.runelite.api.events.WidgetMenuOptionClicked; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemVariationMapping; import net.runelite.client.input.KeyManager; import net.runelite.client.menus.MenuManager; @@ -101,6 +103,9 @@ public class MenuEntrySwapperPlugin extends Plugin @Inject private Client client; + @Inject + private ClientThread clientThread; + @Inject private MenuEntrySwapperConfig config; @@ -116,6 +121,9 @@ public class MenuEntrySwapperPlugin extends Plugin @Inject private MenuManager menuManager; + @Inject + private ItemManager itemManager; + @Getter private boolean configuringShiftClick = false; @@ -146,6 +154,11 @@ public class MenuEntrySwapperPlugin extends Plugin @Subscribe public void onConfigChanged(ConfigChanged event) { + if (!CONFIG_GROUP.equals(event.getGroup())) + { + return; + } + if (event.getKey().equals("shiftClickCustomization")) { if (config.shiftClickCustomization()) @@ -157,6 +170,16 @@ public class MenuEntrySwapperPlugin extends Plugin disableCustomization(); } } + else if (event.getKey().startsWith(ITEM_KEY_PREFIX)) + { + clientThread.invoke(this::resetItemCompositionCache); + } + } + + private void resetItemCompositionCache() + { + itemManager.invalidateItemCompositionCache(); + client.getItemCompositionCache().reset(); } private Integer getSwapConfig(int itemId) @@ -187,6 +210,7 @@ public class MenuEntrySwapperPlugin extends Plugin { keyManager.registerKeyListener(inputListener); refreshShiftClickCustomizationMenus(); + clientThread.invoke(this::resetItemCompositionCache); } private void disableCustomization() @@ -194,6 +218,7 @@ public class MenuEntrySwapperPlugin extends Plugin keyManager.unregisterKeyListener(inputListener); removeShiftClickCustomizationMenus(); configuringShiftClick = false; + clientThread.invoke(this::resetItemCompositionCache); } @Subscribe @@ -291,7 +316,6 @@ public class MenuEntrySwapperPlugin extends Plugin if (option.equals(RESET) && target.equals(MENU_TARGET)) { unsetSwapConfig(itemId); - itemComposition.resetShiftClickActionIndex(); return; } @@ -324,7 +348,6 @@ public class MenuEntrySwapperPlugin extends Plugin if (valid) { setSwapConfig(itemId, index); - itemComposition.setShiftClickActionIndex(index); } } From 9030a7eb6a20971db81b27e19f8ac1d76046c4fc Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Wed, 13 Feb 2019 16:24:09 +0100 Subject: [PATCH 024/102] Normalize CoX CM naming from boss long and chat message Signed-off-by: Tomas Slusny --- .../client/plugins/chatcommands/ChatCommandsPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index 42a3a9baba..dbfd779673 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -299,7 +299,7 @@ public class ChatCommandsPlugin extends Plugin Widget boss = bossChildren[i]; Widget kill = killsChildren[i]; - String bossName = boss.getText(); + String bossName = boss.getText().replace(":", ""); int kc = Integer.parseInt(kill.getText().replace(",", "")); if (kc != getKc(bossName)) { From 0529d5d144f75ab36a642a354c53a20e7ef20478 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Wed, 13 Feb 2019 10:01:20 +0100 Subject: [PATCH 025/102] loottracker service: include time in loot record Signed-off-by: Tomas Slusny --- .../java/net/runelite/http/api/loottracker/LootRecord.java | 2 ++ .../http/service/loottracker/LootTrackerService.java | 4 ++-- .../client/plugins/loottracker/LootTrackerPlugin.java | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java index fb43a1605a..fc945220f1 100644 --- a/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java +++ b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java @@ -24,6 +24,7 @@ */ package net.runelite.http.api.loottracker; +import java.time.Instant; import java.util.Collection; import lombok.AllArgsConstructor; import lombok.Data; @@ -37,4 +38,5 @@ public class LootRecord private String eventId; private LootRecordType type; private Collection drops; + private Instant time; } diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java index 86b7115a80..b999f4eabb 100644 --- a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java @@ -142,7 +142,7 @@ public class LootTrackerService { if (!gameItems.isEmpty()) { - LootRecord lootRecord = new LootRecord(current.getEventId(), current.getType(), gameItems); + LootRecord lootRecord = new LootRecord(current.getEventId(), current.getType(), gameItems, current.getTime()); lootRecords.add(lootRecord); gameItems = new ArrayList<>(); @@ -157,7 +157,7 @@ public class LootTrackerService if (!gameItems.isEmpty()) { - LootRecord lootRecord = new LootRecord(current.getEventId(), current.getType(), gameItems); + LootRecord lootRecord = new LootRecord(current.getEventId(), current.getType(), gameItems, current.getTime()); lootRecords.add(lootRecord); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index acb725db64..30d4a25ba5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -28,6 +28,7 @@ package net.runelite.client.plugins.loottracker; import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -274,7 +275,7 @@ public class LootTrackerPlugin extends Plugin if (lootTrackerClient != null && config.saveLoot()) { - LootRecord lootRecord = new LootRecord(name, LootRecordType.NPC, toGameItems(items)); + LootRecord lootRecord = new LootRecord(name, LootRecordType.NPC, toGameItems(items), Instant.now()); lootTrackerClient.submit(lootRecord); } } @@ -291,7 +292,7 @@ public class LootTrackerPlugin extends Plugin if (lootTrackerClient != null && config.saveLoot()) { - LootRecord lootRecord = new LootRecord(name, LootRecordType.PLAYER, toGameItems(items)); + LootRecord lootRecord = new LootRecord(name, LootRecordType.PLAYER, toGameItems(items), Instant.now()); lootTrackerClient.submit(lootRecord); } } @@ -350,7 +351,7 @@ public class LootTrackerPlugin extends Plugin if (lootTrackerClient != null && config.saveLoot()) { - LootRecord lootRecord = new LootRecord(eventType, LootRecordType.EVENT, toGameItems(items)); + LootRecord lootRecord = new LootRecord(eventType, LootRecordType.EVENT, toGameItems(items), Instant.now()); lootTrackerClient.submit(lootRecord); } } From c012db502ee973a5a1ba3cf6e1b4681edd157a99 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 14 Feb 2019 11:54:12 +0000 Subject: [PATCH 026/102] [maven-release-plugin] prepare release runelite-parent-1.5.12 --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- protocol-api/pom.xml | 2 +- protocol/pom.xml | 2 +- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-mixins/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- runescape-api/pom.xml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index f4381ce9ae..67ec40ba7c 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 63450786f6..32add00114 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 947dd7b667..b2386f89b3 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 5ab155acba..0b2e8167be 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 081195944c..05163c3804 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 Web Service diff --git a/pom.xml b/pom.xml index 0c1f89dc1a..602a24ca63 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 pom RuneLite @@ -59,7 +59,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - HEAD + runelite-parent-1.5.12 diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index 551b441ed7..23e0b58191 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index 5255e7bacb..8fff180967 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 903322a106..05b99540ce 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 6306dc3763..393b7840e1 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 client diff --git a/runelite-mixins/pom.xml b/runelite-mixins/pom.xml index 2bbd0bb214..13fc541f53 100644 --- a/runelite-mixins/pom.xml +++ b/runelite-mixins/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 mixins diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 5ce6ad3a0a..bc3531ffd3 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 script-assembler-plugin diff --git a/runescape-api/pom.xml b/runescape-api/pom.xml index 10f3c0e190..131a8720a9 100644 --- a/runescape-api/pom.xml +++ b/runescape-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12-SNAPSHOT + 1.5.12 net.runelite.rs From 1b50e24738ef22bf672a883faed334c1dd5571ed Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 14 Feb 2019 11:54:18 +0000 Subject: [PATCH 027/102] [maven-release-plugin] prepare for next development iteration --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- protocol-api/pom.xml | 2 +- protocol/pom.xml | 2 +- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-mixins/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- runescape-api/pom.xml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 67ec40ba7c..21e66169bc 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 32add00114..0ea164ee8d 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index b2386f89b3..17a7524427 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 0b2e8167be..0829178ece 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 05163c3804..75e257d32d 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index 602a24ca63..44828e6d8e 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT pom RuneLite @@ -59,7 +59,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - runelite-parent-1.5.12 + HEAD diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index 23e0b58191..46d1cd9593 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index 8fff180967..91084dfbe6 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 05b99540ce..34afe917d0 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 393b7840e1..3cb78ed8f2 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT client diff --git a/runelite-mixins/pom.xml b/runelite-mixins/pom.xml index 13fc541f53..bd4ddb5801 100644 --- a/runelite-mixins/pom.xml +++ b/runelite-mixins/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT mixins diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index bc3531ffd3..9b274b38f5 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT script-assembler-plugin diff --git a/runescape-api/pom.xml b/runescape-api/pom.xml index 131a8720a9..03417c67e0 100644 --- a/runescape-api/pom.xml +++ b/runescape-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.12 + 1.5.13-SNAPSHOT net.runelite.rs From 463e1d0da20d2386df5cb7d13d6f53ecfe417745 Mon Sep 17 00:00:00 2001 From: Will Thomas Date: Thu, 14 Feb 2019 18:56:21 +0000 Subject: [PATCH 028/102] screenshot plugin: Add Challenge Mode raid support Signed-off-by: Will Thomas --- .../plugins/screenshot/ScreenshotPlugin.java | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 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 e4c6fd2ec9..ee78f3cc22 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 @@ -145,6 +145,8 @@ public class ScreenshotPlugin extends Plugin private Integer chambersOfXericNumber; + private Integer chambersOfXericChallengeNumber; + private Integer theatreOfBloodNumber; private boolean shouldTakeScreenshot; @@ -347,6 +349,16 @@ public class ScreenshotPlugin extends Plugin } } + if (chatMessage.startsWith("Your completed Chambers of Xeric Challenge Mode count is:")) + { + Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); + if (m.find()) + { + chambersOfXericChallengeNumber = Integer.valueOf(m.group()); + return; + } + } + if (chatMessage.startsWith("Your completed Theatre of Blood count is:")) { Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage)); @@ -453,14 +465,22 @@ public class ScreenshotPlugin extends Plugin } case CHAMBERS_OF_XERIC_REWARD_GROUP_ID: { - if (chambersOfXericNumber == null) + if (chambersOfXericNumber != null) + { + fileName = "Chambers of Xeric(" + chambersOfXericNumber + ")"; + chambersOfXericNumber = null; + break; + } + else if (chambersOfXericChallengeNumber != null) + { + fileName = "Chambers of Xeric Challenge Mode(" + chambersOfXericChallengeNumber + ")"; + chambersOfXericChallengeNumber = null; + break; + } + else { return; } - - fileName = "Chambers of Xeric(" + chambersOfXericNumber + ")"; - chambersOfXericNumber = null; - break; } case THEATRE_OF_BLOOD_REWARD_GROUP_ID: { @@ -720,6 +740,12 @@ public class ScreenshotPlugin extends Plugin return chambersOfXericNumber; } + @VisibleForTesting + int getChambersOfXericChallengeNumber() + { + return chambersOfXericChallengeNumber; + } + @VisibleForTesting int gettheatreOfBloodNumber() { From b7e0c689fcf7cfcb280ee9ebeee8b6eb8eaf91ec Mon Sep 17 00:00:00 2001 From: Minghan Li Date: Fri, 15 Feb 2019 07:01:44 -0500 Subject: [PATCH 029/102] Add new Kourend quests to world map plugin (#7864) --- .../runelite/client/plugins/worldmap/QuestStartLocation.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java index 66dde6666b..c62eeaff15 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java @@ -30,6 +30,7 @@ import net.runelite.api.coords.WorldPoint; enum QuestStartLocation { + //Free Quests COOKS_ASSISTANT_RFD("Cook's Assistant", new WorldPoint(3211, 3216, 0)), THE_CORSAIR_CURSE("The Corsair Curse", new WorldPoint(3029, 3273, 0)), DEMON_SLAYER("Demon Slayer", new WorldPoint(3204, 3424, 0)), @@ -48,8 +49,11 @@ enum QuestStartLocation SHIELD_OF_ARRAV("Shield of Arrav", new WorldPoint(3208, 3495, 0)), VAMPIRE_SLAYER("Vampire Slayer", new WorldPoint(3096, 3266, 0)), WITCHS_POTION("Witch's Potion", new WorldPoint(2967, 3203, 0)), + + //Members' Quests ANIMAL_MAGNETISM("Animal Magnetism", new WorldPoint(3094, 3360, 0)), ANOTHER_SLICE_OF_HAM("Another Slice of H.A.M.", new WorldPoint(2799, 5428, 0)), + THE_ASCENT_OF_ARCEUUS("The Ascent of Arceuus", new WorldPoint(1700, 3742, 0)), BETWEEN_A_ROCK("Between a Rock...", new WorldPoint(2823, 10168, 0)), BIG_CHOMPY_BIRD_HUNTING("Big Chompy Bird Hunting", new WorldPoint(2629, 2981, 0)), BIOHAZARD("Biohazard", new WorldPoint(2591, 3335, 0)), @@ -84,6 +88,7 @@ enum QuestStartLocation FISHING_CONTEST_1("Fishing Contest", new WorldPoint(2875, 3483, 0)), FISHING_CONTEST_2("Fishing Contest", new WorldPoint(2820, 3487, 0)), FORGETTABLE_TALE("Forgettable Tale...", new WorldPoint(2826, 10215, 0)), + THE_FORSAKEN_TOWER("The Forsaken Tower", new WorldPoint(1484, 3747, 0)), THE_FREMENNIK_ISLES("The Fremennik Isles", new WorldPoint(2645, 3711, 0)), THE_FREMENNIK_TRIALS("The Fremennik Trials", new WorldPoint(2657, 3669, 0)), GARDEN_OF_TRANQUILLITY("Garden of Tranquillity", new WorldPoint(3227, 3477, 0)), From a0e61433e0f4377aa4f06019a0273cda830400ab Mon Sep 17 00:00:00 2001 From: Jaysc Date: Thu, 29 Nov 2018 22:57:52 +0000 Subject: [PATCH 030/102] Make color of hovered tile highlight configurable Signed-off-by: Tomas Slusny --- .../plugins/tileindicators/TileIndicatorsConfig.java | 11 +++++++++++ .../plugins/tileindicators/TileIndicatorsOverlay.java | 3 +-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java index 9d9cd96e69..9a5e0bad33 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java @@ -54,6 +54,17 @@ public interface TileIndicatorsConfig extends Config return true; } + @Alpha + @ConfigItem( + keyName = "highlightHoveredColor", + name = "Color of current hovered highlighting", + description = "Configures the highlight color of hovered tile" + ) + default Color highlightHoveredColor() + { + return new Color(0, 0, 0, 0); + } + @ConfigItem( keyName = "highlightHoveredTile", name = "Highlight hovered tile", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java index f92a76f6de..a9e983656d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsOverlay.java @@ -41,7 +41,6 @@ import net.runelite.client.ui.overlay.OverlayUtil; public class TileIndicatorsOverlay extends Overlay { - private static final Color EMPTY = new Color(0, 0, 0, 0); private final Client client; private final TileIndicatorsConfig config; @@ -75,7 +74,7 @@ public class TileIndicatorsOverlay extends Overlay // If we have tile "selected" render it if (client.getSelectedSceneTile() != null) { - renderTile(graphics, client.getSelectedSceneTile().getLocalLocation(), EMPTY); + renderTile(graphics, client.getSelectedSceneTile().getLocalLocation(), config.highlightHoveredColor()); } } From 8f1ef00c395d8bb764a4305d63f15ca8c75e2721 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 15 Feb 2019 21:04:22 +0100 Subject: [PATCH 031/102] Use default PanelComponent size in Cooking plugin So it is consistent with rest of plugins, mainly session ones. Signed-off-by: Tomas Slusny --- .../java/net/runelite/client/plugins/cooking/CookingOverlay.java | 1 - 1 file changed, 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java index af0a5a8b62..7e25f3ad31 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingOverlay.java @@ -78,7 +78,6 @@ class CookingOverlay extends Overlay return null; } - panelComponent.setPreferredSize(new Dimension(145, 0)); panelComponent.getChildren().clear(); if (isCooking() || Duration.between(session.getLastCookingAction(), Instant.now()).getSeconds() < COOK_TIMEOUT) From 6914d8806d93eb6abe39d121d773331ad5eb6afb Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 15 Feb 2019 21:37:26 +0100 Subject: [PATCH 032/102] Make party stats overlay consistent with other overlays - Remove invisible border - Add standard gap Signed-off-by: Tomas Slusny --- .../net/runelite/client/plugins/party/PartyStatsOverlay.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyStatsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyStatsOverlay.java index 2b9e1820f3..693b23cb89 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyStatsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyStatsOverlay.java @@ -27,6 +27,8 @@ package net.runelite.client.plugins.party; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; import java.util.Map; import java.util.UUID; import javax.inject.Inject; @@ -34,6 +36,7 @@ import net.runelite.api.MenuAction; import net.runelite.client.plugins.party.data.PartyData; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.components.ComponentConstants; import net.runelite.client.ui.overlay.components.PanelComponent; import net.runelite.client.ui.overlay.components.ProgressBarComponent; import net.runelite.client.ui.overlay.components.TitleComponent; @@ -58,6 +61,8 @@ public class PartyStatsOverlay extends Overlay this.plugin = plugin; this.party = party; this.config = config; + body.setBorder(new Rectangle()); + body.setGap(new Point(0, ComponentConstants.STANDARD_BORDER / 2)); getMenuEntries().add(new OverlayMenuEntry(MenuAction.RUNELITE_OVERLAY, "Leave", "Party")); } From 5c546fd1d45cb50dddc02c753d4619f2a0913393 Mon Sep 17 00:00:00 2001 From: Robert <43491258+lyzrds@users.noreply.github.com> Date: Fri, 15 Feb 2019 16:17:58 -0600 Subject: [PATCH 033/102] Add support for third floor timer to Raids plugin (Challenge Mode) (#7871) --- .../client/plugins/raids/RaidsPlugin.java | 2 +- .../client/plugins/raids/RaidsTimer.java | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 72a386f5c7..d0c0d7c16c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -236,7 +236,7 @@ public class RaidsPlugin extends Plugin { if (timer != null) { - timer.timeFloor(); + timer.timeOlm(); timer.setStopped(true); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java index 8b40b09e10..8df3087054 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsTimer.java @@ -41,6 +41,7 @@ public class RaidsTimer extends InfoBox private LocalTime time; private LocalTime firstFloorTime; private LocalTime secondFloorTime; + private LocalTime thirdFloorTime; private LocalTime olmTime; @Setter @@ -66,14 +67,20 @@ public class RaidsTimer extends InfoBox { secondFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); } - else if (olmTime == null) + else if (thirdFloorTime == null) { - olmTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); + thirdFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); } floorTime = Instant.now(); } + public void timeOlm() + { + Duration elapsed = Duration.between(floorTime, Instant.now()); + olmTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); + } + @Override public String getText() { @@ -126,6 +133,12 @@ public class RaidsTimer extends InfoBox builder.append(secondFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); } + if (thirdFloorTime != null) + { + builder.append("
Third floor: "); + builder.append(thirdFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); + } + if (olmTime != null) { builder.append("
Olm: "); From 56d583f70ab873980e4de92a5bbd0758c65636dc Mon Sep 17 00:00:00 2001 From: Usernamerino Date: Tue, 8 Jan 2019 23:26:39 +0100 Subject: [PATCH 034/102] Add chat command shorthand for challenge mode raids killcount --- .../plugins/chatcommands/ChatCommandsPlugin.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index dbfd779673..7295577e34 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -1089,6 +1089,7 @@ public class ChatCommandsPlugin extends Plugin case "barrows": return "Barrows Chests"; + // cox case "cox": case "xeric": case "chambers": @@ -1096,6 +1097,15 @@ public class ChatCommandsPlugin extends Plugin case "raids": return "Chambers of Xeric"; + // cox cm + case "cox cm": + case "xeric cm": + case "chambers cm": + case "olm cm": + case "raids cm": + return "Chambers of Xeric Challenge Mode"; + + // tob case "tob": case "theatre": case "verzik": From bc0ec093dc49b994a9eb0958af48c0d6fbbac85c Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 15 Feb 2019 21:04:42 -0500 Subject: [PATCH 035/102] xptracker: limit how often the same players are looked up Use player rank to set how often the same player is allowed to be looked up. Replace the ConcurrentLinkedDeque with a synchronized ArrayDeque which has a constant time size(). --- .../http/service/xp/XpTrackerService.java | 103 ++++++++++++++---- .../http/service/xp/beans/PlayerEntity.java | 2 + .../net/runelite/http/service/xp/schema.sql | 10 +- 3 files changed, 89 insertions(+), 26 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java b/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java index 391d37d1bf..5ef7e829e4 100644 --- a/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java +++ b/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java @@ -29,8 +29,8 @@ import com.google.common.hash.Funnels; import java.nio.charset.Charset; import java.time.Duration; import java.time.Instant; +import java.util.ArrayDeque; import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ExecutionException; import lombok.extern.slf4j.Slf4j; import net.runelite.http.api.hiscore.HiscoreEndpoint; @@ -50,8 +50,8 @@ import org.sql2o.Sql2o; @Slf4j public class XpTrackerService { - private static final int QUEUE_LIMIT = 100_000; - private static final Duration UPDATE_TIME = Duration.ofMinutes(5); + private static final int QUEUE_LIMIT = 32768; + private static final int BLOOMFILTER_EXPECTED_INSERTIONS = 100_000; @Autowired @Qualifier("Runelite XP Tracker SQL2O") @@ -60,7 +60,7 @@ public class XpTrackerService @Autowired private HiscoreService hiscoreService; - private final Queue usernameUpdateQueue = new ConcurrentLinkedDeque<>(); + private final Queue usernameUpdateQueue = new ArrayDeque<>(); private BloomFilter usernameFilter = createFilter(); public void update(String username) throws ExecutionException @@ -76,13 +76,37 @@ public class XpTrackerService return; } - if (usernameUpdateQueue.size() >= QUEUE_LIMIT) + try (Connection con = sql2o.open()) { - log.warn("Username update queue is full ({})", QUEUE_LIMIT); - return; + PlayerEntity playerEntity = findOrCreatePlayer(con, username); + Duration frequency = updateFrequency(playerEntity); + Instant now = Instant.now(); + Duration timeSinceLastUpdate = Duration.between(playerEntity.getLast_updated(), now); + if (timeSinceLastUpdate.toMillis() < frequency.toMillis()) + { + log.debug("User {} updated too recently", username); + usernameFilter.put(username); + return; + } + + synchronized (usernameUpdateQueue) + { + if (usernameUpdateQueue.size() >= QUEUE_LIMIT) + { + log.warn("Username update queue is full ({})", QUEUE_LIMIT); + return; + } + } + + con.createQuery("update player set last_updated = CURRENT_TIMESTAMP where id = :id") + .addParameter("id", playerEntity.getId()) + .executeUpdate(); } - usernameUpdateQueue.add(username); + synchronized (usernameUpdateQueue) + { + usernameUpdateQueue.add(username); + } usernameFilter.put(username); } @@ -104,13 +128,6 @@ public class XpTrackerService log.debug("Hiscore for {} already up to date", username); return; } - - Duration difference = Duration.between(currentXp.getTime(), now); - if (difference.compareTo(UPDATE_TIME) <= 0) - { - log.debug("Updated {} too recently", username); - return; - } } con.createQuery("insert into xp (player,attack_xp,defence_xp,strength_xp,hitpoints_xp,ranged_xp,prayer_xp,magic_xp,cooking_xp,woodcutting_xp," @@ -172,6 +189,11 @@ public class XpTrackerService .addParameter("construction_rank", hiscoreResult.getConstruction().getRank()) .addParameter("overall_rank", hiscoreResult.getOverall().getRank()) .executeUpdate(); + + con.createQuery("update player set rank = :rank where id = :id") + .addParameter("id", playerEntity.getId()) + .addParameter("rank", hiscoreResult.getOverall().getRank()) + .executeUpdate(); } } @@ -197,6 +219,7 @@ public class XpTrackerService playerEntity.setId(id); playerEntity.setName(username); playerEntity.setTracked_since(now); + playerEntity.setLast_updated(now); return playerEntity; } @@ -220,18 +243,21 @@ public class XpTrackerService @Scheduled(fixedDelay = 1000) public void update() throws ExecutionException { - String next = usernameUpdateQueue.poll(); + String next; + synchronized (usernameUpdateQueue) + { + next = usernameUpdateQueue.poll(); + } if (next == null) { return; } - HiscoreResult hiscoreResult = hiscoreService.lookupUsername(next, HiscoreEndpoint.NORMAL); - update(next, hiscoreResult); + update(next); } - @Scheduled(fixedDelay = 3 * 60 * 60 * 1000) // 3 hours + @Scheduled(fixedDelay = 6 * 60 * 60 * 1000) // 6 hours public void clearFilter() { usernameFilter = createFilter(); @@ -241,14 +267,47 @@ public class XpTrackerService { final BloomFilter filter = BloomFilter.create( Funnels.stringFunnel(Charset.defaultCharset()), - 100_000 + BLOOMFILTER_EXPECTED_INSERTIONS ); - for (String toUpdate : usernameUpdateQueue) + synchronized (usernameUpdateQueue) { - filter.put(toUpdate); + for (String toUpdate : usernameUpdateQueue) + { + filter.put(toUpdate); + } } return filter; } + + /** + * scale how often to check hiscore updates for players based on their rank + * @param playerEntity + * @return + */ + private static Duration updateFrequency(PlayerEntity playerEntity) + { + Integer rank = playerEntity.getRank(); + if (rank == null) + { + return Duration.ofDays(7); + } + else if (rank < 10_000) + { + return Duration.ofHours(6); + } + else if (rank < 50_000) + { + return Duration.ofDays(2); + } + else if (rank < 100_000) + { + return Duration.ofDays(5); + } + else + { + return Duration.ofDays(7); + } + } } diff --git a/http-service/src/main/java/net/runelite/http/service/xp/beans/PlayerEntity.java b/http-service/src/main/java/net/runelite/http/service/xp/beans/PlayerEntity.java index d07d1d4640..11bec532d7 100644 --- a/http-service/src/main/java/net/runelite/http/service/xp/beans/PlayerEntity.java +++ b/http-service/src/main/java/net/runelite/http/service/xp/beans/PlayerEntity.java @@ -33,4 +33,6 @@ public class PlayerEntity private Integer id; private String name; private Instant tracked_since; + private Instant last_updated; + private Integer rank; } diff --git a/http-service/src/main/resources/net/runelite/http/service/xp/schema.sql b/http-service/src/main/resources/net/runelite/http/service/xp/schema.sql index ba4c395d62..70f83a30fd 100644 --- a/http-service/src/main/resources/net/runelite/http/service/xp/schema.sql +++ b/http-service/src/main/resources/net/runelite/http/service/xp/schema.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.16 Distrib 10.2.9-MariaDB, for Linux (x86_64) +-- MySQL dump 10.16 Distrib 10.2.18-MariaDB, for Linux (x86_64) -- -- Host: localhost Database: xptracker -- ------------------------------------------------------ --- Server version 10.2.9-MariaDB +-- Server version 10.2.18-MariaDB /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -26,6 +26,8 @@ CREATE TABLE `player` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `tracked_since` timestamp NOT NULL DEFAULT current_timestamp(), + `last_updated` timestamp NOT NULL DEFAULT current_timestamp(), + `rank` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; @@ -116,7 +118,7 @@ CREATE TABLE `xp` ( `overall_rank` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `player_time` (`player`,`time`), - INDEX `idx_time` (`time`), + KEY `idx_time` (`time`), CONSTRAINT `fk_player` FOREIGN KEY (`player`) REFERENCES `player` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -130,4 +132,4 @@ CREATE TABLE `xp` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2018-01-20 18:37:09 +-- Dump completed on 2019-02-15 21:01:17 \ No newline at end of file From 60e17c2ac160ff4bb193f8d2064d31a8df82dd47 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sat, 16 Feb 2019 04:43:03 +0100 Subject: [PATCH 036/102] Log only exception message on feed lookup failures Seeing same exceptions over and over again is not very useful, mainly when their stacktraces are not useful too. Signed-off-by: Tomas Slusny --- .../java/net/runelite/http/service/feed/FeedController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java b/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java index 8b55d1b93a..fa641d3714 100644 --- a/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java +++ b/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java @@ -71,7 +71,7 @@ public class FeedController } catch (IOException e) { - log.warn(null, e); + log.warn(e.getMessage()); } try @@ -80,7 +80,7 @@ public class FeedController } catch (IOException e) { - log.warn(null, e); + log.warn(e.getMessage()); } try @@ -89,7 +89,7 @@ public class FeedController } catch (IOException e) { - log.warn(null, e); + log.warn(e.getMessage()); } feedResult = new FeedResult(items); From e8019d0517e577ffbacfea3ce1062dd75754e8de Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sat, 16 Feb 2019 03:56:33 +0100 Subject: [PATCH 037/102] Null-check cache when getting items in http service It is not very useful exception and cache entry is null-checked everywhere else. Replace the exception with simple warning in logs. Signed-off-by: Tomas Slusny --- .../java/net/runelite/http/service/cache/CacheService.java | 6 ++++++ .../java/net/runelite/http/service/item/ItemService.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java b/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java index 882e90c460..e0fca4ac21 100644 --- a/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java +++ b/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java @@ -41,6 +41,7 @@ import java.io.InputStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import lombok.extern.slf4j.Slf4j; import net.runelite.cache.ConfigType; @@ -233,6 +234,11 @@ public class CacheService public List getItems() throws IOException { CacheEntry cache = findMostRecent(); + if (cache == null) + { + return Collections.emptyList(); + } + IndexEntry indexEntry = findIndexForCache(cache, IndexType.CONFIGS.getNumber()); ArchiveEntry archiveEntry = findArchiveForIndex(indexEntry, ConfigType.ITEM.getId()); ArchiveFiles archiveFiles = getArchiveFiles(archiveEntry); diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemService.java b/http-service/src/main/java/net/runelite/http/service/item/ItemService.java index 2da7a50028..32569b0517 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemService.java +++ b/http-service/src/main/java/net/runelite/http/service/item/ItemService.java @@ -489,10 +489,16 @@ public class ItemService public void reloadItems() throws IOException { List items = cacheService.getItems(); + if (items.isEmpty()) + { + log.warn("Failed to load any items from cache, item price updating will be disabled"); + } + tradeableItems = items.stream() .filter(item -> item.isTradeable) .mapToInt(item -> item.id) .toArray(); + log.debug("Loaded {} tradeable items", tradeableItems.length); } From bd9dfb17308e84b11a140f3bad899a7cedbdc996 Mon Sep 17 00:00:00 2001 From: Nokkasiili <46995454+Nokkasiili@users.noreply.github.com> Date: Sat, 16 Feb 2019 22:05:43 +0200 Subject: [PATCH 038/102] Add X Marks the Spot quest to world map plugin (#7877) --- .../net/runelite/client/plugins/worldmap/QuestStartLocation.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java index c62eeaff15..c1d9e9fb88 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java @@ -49,6 +49,7 @@ enum QuestStartLocation SHIELD_OF_ARRAV("Shield of Arrav", new WorldPoint(3208, 3495, 0)), VAMPIRE_SLAYER("Vampire Slayer", new WorldPoint(3096, 3266, 0)), WITCHS_POTION("Witch's Potion", new WorldPoint(2967, 3203, 0)), + X_MARKS_THE_SPOT("X Marks the Spot", new WorldPoint(3227, 3242, 0)), //Members' Quests ANIMAL_MAGNETISM("Animal Magnetism", new WorldPoint(3094, 3360, 0)), From 19a2f7f5653c366e247ef6df70e775f9cfafda74 Mon Sep 17 00:00:00 2001 From: Desetude Date: Thu, 14 Feb 2019 14:50:32 +0000 Subject: [PATCH 039/102] Use xdg-open for link browsing on Linux --- .../net/runelite/client/util/LinkBrowser.java | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java index 173a383bbe..194b1974b2 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java +++ b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java @@ -43,6 +43,8 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class LinkBrowser { + private static boolean shouldAttemptXdg = OSType.getOSType() == OSType.Linux; + /** * Tries to navigate to specified URL in browser. In case operation fails, displays message box with message * and copies link to clipboard to navigate to. @@ -56,9 +58,55 @@ public class LinkBrowser return false; } + if (attemptDesktopBrowse(url)) + { + log.debug("Opened browser through Desktop#browse to {}", url); + return true; + } + + if (shouldAttemptXdg && attemptXdgOpen(url)) + { + log.debug("Opened browser through xdg-open to {}", url); + return true; + } + + showMessageBox("Unable to open link. Press 'OK' and link will be copied to your clipboard.", url); + return false; + } + + private static boolean attemptXdgOpen(String url) + { + try + { + final Process exec = Runtime.getRuntime().exec(new String[]{"xdg-open", url}); + exec.waitFor(); + + final int ret = exec.exitValue(); + if (ret == 0) + { + return true; + } + + log.warn("xdg-open {} returned with error code {}", url, ret); + return false; + } + catch (IOException ex) + { + // xdg-open not found + shouldAttemptXdg = false; + return false; + } + catch (InterruptedException ex) + { + log.warn("Interrupted while waiting for xdg-open {} to execute", url); + return false; + } + } + + private static boolean attemptDesktopBrowse(String url) + { if (!Desktop.isDesktopSupported()) { - showMessageBox("Desktop is not supported. Press 'OK' and link will be copied to your clipboard.", url); return false; } @@ -66,20 +114,17 @@ public class LinkBrowser if (!desktop.isSupported(Desktop.Action.BROWSE)) { - showMessageBox("Desktop browser is not supported. Press 'OK' and link will be copied to your clipboard.", url); return false; } try { desktop.browse(new URI(url)); - log.debug("Opened browser to {}", url); return true; } catch (IOException | URISyntaxException ex) { - log.warn("Unable to open URL {}. Error: {}", url, ex); - showMessageBox("Unable to open a URL. Press 'OK' and link will be copied to your clipboard.", url); + log.warn("Failed to open Desktop#browser {}", url, ex); return false; } } From af9733f2e20d344905fd3c2fb9278263c0e6b932 Mon Sep 17 00:00:00 2001 From: Ron Young Date: Thu, 24 Jan 2019 21:52:56 -0600 Subject: [PATCH 040/102] ChatboxTextInput: rename this.cursor to this.cursorStart --- .../client/game/chatbox/ChatboxTextInput.java | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java index 848f461288..3300002c4d 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java @@ -40,14 +40,14 @@ import java.util.function.ToIntFunction; import javax.swing.SwingUtilities; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import net.runelite.api.FontTypeFace; import net.runelite.api.FontID; -import net.runelite.api.widgets.WidgetType; +import net.runelite.api.FontTypeFace; import net.runelite.api.widgets.JavaScriptCallback; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetPositionMode; import net.runelite.api.widgets.WidgetSizeMode; import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.api.widgets.WidgetType; import net.runelite.client.callback.ClientThread; import net.runelite.client.input.KeyListener; import net.runelite.client.input.MouseListener; @@ -72,7 +72,7 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse private StringBuffer value = new StringBuffer(); @Getter - private int cursor = 0; + private int cursorStart = 0; @Getter private int cursorEnd = 0; @@ -158,7 +158,7 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse end = v; } - this.cursor = start; + this.cursorStart = start; this.cursorEnd = end; if (built) @@ -234,8 +234,8 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse { Widget container = chatboxPanelManager.getContainerWidget(); - String lt = Text.escapeJagex(value.substring(0, this.cursor)); - String mt = Text.escapeJagex(value.substring(this.cursor, this.cursorEnd)); + String lt = Text.escapeJagex(value.substring(0, this.cursorStart)); + String mt = Text.escapeJagex(value.substring(this.cursorStart, this.cursorEnd)); String rt = Text.escapeJagex(value.substring(this.cursorEnd)); Widget leftText = container.createChild(-1, WidgetType.TEXT); @@ -399,12 +399,12 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse char c = e.getKeyChar(); if (charValidator.test(c)) { - if (cursor != cursorEnd) + if (cursorStart != cursorEnd) { - value.delete(cursor, cursorEnd); + value.delete(cursorStart, cursorEnd); } - value.insert(cursor, c); - cursorAt(cursor + 1); + value.insert(cursorStart, c); + cursorAt(cursorStart + 1); if (onChanged != null) { onChanged.accept(getValue()); @@ -422,13 +422,13 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse { case KeyEvent.VK_X: case KeyEvent.VK_C: - if (cursor != cursorEnd) + if (cursorStart != cursorEnd) { - String s = value.substring(cursor, cursorEnd); + String s = value.substring(cursorStart, cursorEnd); if (code == KeyEvent.VK_X) { - value.delete(cursor, cursorEnd); - cursorAt(cursor); + value.delete(cursorStart, cursorEnd); + cursorAt(cursorStart); } Toolkit.getDefaultToolkit() .getSystemClipboard() @@ -442,20 +442,20 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse .getSystemClipboard() .getData(DataFlavor.stringFlavor) .toString(); - if (cursor != cursorEnd) + if (cursorStart != cursorEnd) { - value.delete(cursor, cursorEnd); + value.delete(cursorStart, cursorEnd); } for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (charValidator.test(ch)) { - value.insert(cursor, ch); - cursor++; + value.insert(cursorStart, ch); + cursorStart++; } } - cursorAt(cursor); + cursorAt(cursorStart); if (onChanged != null) { onChanged.accept(getValue()); @@ -469,13 +469,13 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse } return; } - int newPos = cursor; + int newPos = cursorStart; if (ev.isShiftDown()) { if (selectionEnd == -1 || selectionStart == -1) { - selectionStart = cursor; - selectionEnd = cursor; + selectionStart = cursorStart; + selectionEnd = cursorStart; } newPos = selectionEnd; } @@ -487,20 +487,20 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse switch (code) { case KeyEvent.VK_DELETE: - if (cursor != cursorEnd) + if (cursorStart != cursorEnd) { - value.delete(cursor, cursorEnd); - cursorAt(cursor); + value.delete(cursorStart, cursorEnd); + cursorAt(cursorStart); if (onChanged != null) { onChanged.accept(getValue()); } return; } - if (cursor < value.length()) + if (cursorStart < value.length()) { - value.deleteCharAt(cursor); - cursorAt(cursor); + value.deleteCharAt(cursorStart); + cursorAt(cursorStart); if (onChanged != null) { onChanged.accept(getValue()); @@ -508,20 +508,20 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse } return; case KeyEvent.VK_BACK_SPACE: - if (cursor != cursorEnd) + if (cursorStart != cursorEnd) { - value.delete(cursor, cursorEnd); - cursorAt(cursor); + value.delete(cursorStart, cursorEnd); + cursorAt(cursorStart); if (onChanged != null) { onChanged.accept(getValue()); } return; } - if (cursor > 0) + if (cursorStart > 0) { - value.deleteCharAt(cursor - 1); - cursorAt(cursor - 1); + value.deleteCharAt(cursorStart - 1); + cursorAt(cursorStart - 1); if (onChanged != null) { onChanged.accept(getValue()); @@ -554,9 +554,9 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse return; case KeyEvent.VK_ESCAPE: ev.consume(); - if (cursor != cursorEnd) + if (cursorStart != cursorEnd) { - cursorAt(cursor); + cursorAt(cursorStart); return; } chatboxPanelManager.close(); @@ -603,7 +603,7 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse } if (isInBounds == null || !isInBounds.test(mouseEvent)) { - if (cursor != cursorEnd) + if (cursorStart != cursorEnd) { selectionStart = -1; selectionEnd = -1; From b7a4033712c10386539edbcfbbd273118c73501b Mon Sep 17 00:00:00 2001 From: Ron Young Date: Fri, 25 Jan 2019 00:18:49 -0600 Subject: [PATCH 041/102] ChatboxTextInput: support line wrapping --- .../client/game/chatbox/ChatboxTextInput.java | 302 +++++++++++++----- 1 file changed, 217 insertions(+), 85 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java index 3300002c4d..193e5667e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java @@ -24,7 +24,10 @@ */ package net.runelite.client.game.chatbox; +import com.google.common.base.Strings; +import com.google.common.primitives.Ints; import com.google.inject.Inject; +import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; @@ -33,11 +36,15 @@ import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; import java.util.function.IntPredicate; import java.util.function.Predicate; import java.util.function.ToIntFunction; +import java.util.regex.Pattern; import javax.swing.SwingUtilities; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.FontID; @@ -57,6 +64,7 @@ import net.runelite.client.util.Text; public class ChatboxTextInput extends ChatboxInput implements KeyListener, MouseListener { private static final int CURSOR_FLASH_RATE_MILLIS = 1000; + private static final Pattern BREAK_MATCHER = Pattern.compile("[^a-zA-Z0-9']"); private final ChatboxPanelManager chatboxPanelManager; private final ClientThread clientThread; @@ -66,9 +74,20 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse return i -> i >= 32 && i < 127; } + @AllArgsConstructor + private static class Line + { + private final int start; + private final int end; + private final String text; + } + @Getter private String prompt; + @Getter + private int lines; + private StringBuffer value = new StringBuffer(); @Getter @@ -98,9 +117,9 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse @Getter private boolean built = false; - // This is a lambda so I can have atomic updates for it's captures - private ToIntFunction getCharOffset = null; + // These are lambdas for atomic updates private Predicate isInBounds = null; + private ToIntFunction getCharOffset = null; @Inject protected ChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread) @@ -109,6 +128,16 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse this.clientThread = clientThread; } + public ChatboxTextInput lines(int lines) + { + this.lines = lines; + if (built) + { + clientThread.invoke(this::update); + } + return this; + } + public ChatboxTextInput prompt(String prompt) { this.prompt = prompt; @@ -232,103 +261,209 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse protected void buildEdit(int x, int y, int w, int h) { + final List editLines = new ArrayList<>(); + Widget container = chatboxPanelManager.getContainerWidget(); - String lt = Text.escapeJagex(value.substring(0, this.cursorStart)); - String mt = Text.escapeJagex(value.substring(this.cursorStart, this.cursorEnd)); - String rt = Text.escapeJagex(value.substring(this.cursorEnd)); - - Widget leftText = container.createChild(-1, WidgetType.TEXT); - Widget cursor = container.createChild(-1, WidgetType.RECTANGLE); - Widget middleText = container.createChild(-1, WidgetType.TEXT); - Widget rightText = container.createChild(-1, WidgetType.TEXT); - - leftText.setFontId(fontID); - FontTypeFace font = leftText.getFont(); + final Widget cursor = container.createChild(-1, WidgetType.RECTANGLE); + long start = System.currentTimeMillis(); + cursor.setOnTimerListener((JavaScriptCallback) ev -> + { + boolean on = (System.currentTimeMillis() - start) % CURSOR_FLASH_RATE_MILLIS > (CURSOR_FLASH_RATE_MILLIS / 2); + cursor.setOpacity(on ? 255 : 0); + }); + cursor.setTextColor(0xFFFFFF); + cursor.setHasListener(true); + cursor.setFilled(true); + cursor.setFontId(fontID); + FontTypeFace font = cursor.getFont(); if (h <= 0) { h = font.getBaseline(); } - int ltw = font.getTextWidth(lt); - int mtw = font.getTextWidth(mt); - int rtw = font.getTextWidth(rt); + final int oy = y; + final int ox = x; + final int oh = h; - int fullWidth = ltw + mtw + rtw; - - int ox = x; - if (w > 0) + int breakIndex = -1; + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < value.length(); i++) { - x += (w - fullWidth) / 2; - } - - int ltx = x; - int mtx = ltx + ltw; - int rtx = mtx + mtw; - - leftText.setText(lt); - leftText.setOriginalX(ltx); - leftText.setOriginalY(y); - leftText.setOriginalWidth(ltw); - leftText.setOriginalHeight(h); - leftText.revalidate(); - - if (!mt.isEmpty()) - { - cursor.setTextColor(0x113399); - } - else - { - cursor.setTextColor(0xFFFFFF); - long start = System.currentTimeMillis(); - cursor.setOnTimerListener((JavaScriptCallback) ev -> + int count = i - sb.length(); + final String c = value.charAt(i) + ""; + sb.append(c); + if (BREAK_MATCHER.matcher(c).matches()) { - boolean on = (System.currentTimeMillis() - start) % CURSOR_FLASH_RATE_MILLIS > (CURSOR_FLASH_RATE_MILLIS / 2); - cursor.setOpacity(on ? 255 : 0); - }); - cursor.setHasListener(true); + breakIndex = sb.length(); + } + + if (i == value.length() - 1) + { + Line line = new Line(count, count + sb.length() - 1, sb.toString()); + editLines.add(line); + break; + } + + if (font.getTextWidth(sb.toString() + value.charAt(i + 1)) < w) + { + continue; + } + + if (editLines.size() < this.lines - 1 || this.lines == 0) + { + if (breakIndex > 1) + { + String str = sb.substring(0, breakIndex); + Line line = new Line(count, count + str.length() - 1, str); + editLines.add(line); + + sb.replace(0, breakIndex, ""); + breakIndex = -1; + continue; + } + + Line line = new Line(count, count + sb.length() - 1, sb.toString()); + editLines.add(line); + sb.replace(0, sb.length(), ""); + } } - cursor.setFilled(true); - cursor.setOriginalX(mtx - 1); - cursor.setOriginalY(y); - cursor.setOriginalWidth(2 + mtw); - cursor.setOriginalHeight(h); - cursor.revalidate(); - middleText.setText(mt); - middleText.setFontId(fontID); - middleText.setOriginalX(mtx); - middleText.setOriginalY(y); - middleText.setOriginalWidth(mtw); - middleText.setOriginalHeight(h); - middleText.setTextColor(0xFFFFFF); - middleText.revalidate(); + Rectangle bounds = new Rectangle(container.getCanvasLocation().getX() + container.getWidth(), y, 0, editLines.size() * oh); + for (int i = 0; i < editLines.size() || i == 0; i++) + { + final Line line = editLines.size() > 0 ? editLines.get(i) : new Line(0, 0, ""); + final String text = line.text; + final int len = text.length(); - rightText.setText(rt); - rightText.setFontId(fontID); - rightText.setOriginalX(rtx); - rightText.setOriginalY(y); - rightText.setOriginalWidth(rtw); - rightText.setOriginalHeight(h); - rightText.revalidate(); + String lt = Text.escapeJagex(text); + String mt = ""; + String rt = ""; + + final boolean isStartLine = cursorOnLine(cursorStart, line.start, line.end) + || (cursorOnLine(cursorStart, line.start, line.end + 1) && i == editLines.size() - 1); + + final boolean isEndLine = cursorOnLine(cursorEnd, line.start, line.end); + + if (isStartLine || isEndLine || (cursorEnd > line.end && cursorStart < line.start)) + { + final int cIdx = Ints.constrainToRange(cursorStart - line.start, 0, len); + final int ceIdx = Ints.constrainToRange(cursorEnd - line.start, 0, len); + + lt = Text.escapeJagex(text.substring(0, cIdx)); + mt = Text.escapeJagex(text.substring(cIdx, ceIdx)); + rt = Text.escapeJagex(text.substring(ceIdx)); + } + + final int ltw = font.getTextWidth(lt); + final int mtw = font.getTextWidth(mt); + final int rtw = font.getTextWidth(rt); + final int fullWidth = ltw + mtw + rtw; + + int ltx = ox; + if (w > 0) + { + ltx += (w - fullWidth) / 2; + } + + final int mtx = ltx + ltw; + final int rtx = mtx + mtw; + + if (ltx < bounds.x) + { + bounds.setLocation(ltx, bounds.y); + } + + if (fullWidth > bounds.width) + { + bounds.setSize(fullWidth, bounds.height); + } + + if (editLines.size() == 0 || isStartLine) + { + cursor.setOriginalX(mtx - 1); + cursor.setOriginalY(y); + cursor.setOriginalWidth(2); + cursor.setOriginalHeight(h); + cursor.revalidate(); + } + + if (!Strings.isNullOrEmpty(lt)) + { + final Widget leftText = container.createChild(-1, WidgetType.TEXT); + leftText.setFontId(fontID); + leftText.setText(lt); + leftText.setOriginalX(ltx); + leftText.setOriginalY(y); + leftText.setOriginalWidth(ltw); + leftText.setOriginalHeight(h); + leftText.revalidate(); + } + + if (!Strings.isNullOrEmpty(mt)) + { + final Widget background = container.createChild(-1, WidgetType.RECTANGLE); + background.setTextColor(0x113399); + background.setFilled(true); + background.setOriginalX(mtx - 1); + background.setOriginalY(y); + background.setOriginalWidth(2 + mtw); + background.setOriginalHeight(h); + background.revalidate(); + + final Widget middleText = container.createChild(-1, WidgetType.TEXT); + middleText.setText(mt); + middleText.setFontId(fontID); + middleText.setOriginalX(mtx); + middleText.setOriginalY(y); + middleText.setOriginalWidth(mtw); + middleText.setOriginalHeight(h); + middleText.setTextColor(0xFFFFFF); + middleText.revalidate(); + } + + if (!Strings.isNullOrEmpty(rt)) + { + final Widget rightText = container.createChild(-1, WidgetType.TEXT); + rightText.setText(rt); + rightText.setFontId(fontID); + rightText.setOriginalX(rtx); + rightText.setOriginalY(y); + rightText.setOriginalWidth(rtw); + rightText.setOriginalHeight(h); + rightText.revalidate(); + } + + y += h; + } net.runelite.api.Point ccl = container.getCanvasLocation(); - int canvasX = ltx + ccl.getX(); - Rectangle bounds = new Rectangle(ccl.getX() + ox, ccl.getY() + y, w > 0 ? w : fullWidth, h); - String tsValue = value.toString(); - isInBounds = ev -> bounds.contains(ev.getPoint()); + isInBounds = ev -> bounds.contains(new Point(ev.getX() - ccl.getX(), ev.getY() - ccl.getY())); getCharOffset = ev -> { - if (fullWidth <= 0) + if (bounds.width <= 0) { return 0; } - int cx = ev.getX() - canvasX; + int cx = ev.getX() - ccl.getX() - ox; + int cy = ev.getY() - ccl.getY() - oy; - int charIndex = (tsValue.length() * cx) / fullWidth; + int currentLine = Ints.constrainToRange(cy / oh, 0, editLines.size() - 1); + + final Line line = editLines.get(currentLine); + final String tsValue = line.text; + int charIndex = tsValue.length(); + int fullWidth = font.getTextWidth(tsValue); + + int tx = ox; + if (w > 0) + { + tx += (w - fullWidth) / 2; + } + cx -= tx; // `i` is used to track max execution time incase there is a font with ligature width data that causes this to fail for (int i = tsValue.length(); i >= 0 && charIndex >= 0 && charIndex <= tsValue.length(); i--) @@ -353,19 +488,16 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse break; } - if (charIndex < 0) - { - charIndex = 0; - } - if (charIndex > tsValue.length()) - { - charIndex = tsValue.length(); - } - - return charIndex; + charIndex = Ints.constrainToRange(charIndex, 0, tsValue.length()); + return line.start + charIndex; }; } + private boolean cursorOnLine(final int cursor, final int start, final int end) + { + return (cursor >= start) && (cursor <= end); + } + @Override protected void open() { From d7eb3fec36a218d2043e66ffea665412f087fc76 Mon Sep 17 00:00:00 2001 From: Ron Young Date: Fri, 25 Jan 2019 00:19:16 -0600 Subject: [PATCH 042/102] ChatboxTextInput: support moving between lines with up/down keys --- .../client/game/chatbox/ChatboxTextInput.java | 75 +++++++++++++++++-- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java index 193e5667e9..e59e47059d 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java @@ -119,7 +119,8 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse // These are lambdas for atomic updates private Predicate isInBounds = null; - private ToIntFunction getCharOffset = null; + private ToIntFunction getLineOffset = null; + private ToIntFunction getPointCharOffset = null; @Inject protected ChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread) @@ -441,15 +442,15 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse net.runelite.api.Point ccl = container.getCanvasLocation(); isInBounds = ev -> bounds.contains(new Point(ev.getX() - ccl.getX(), ev.getY() - ccl.getY())); - getCharOffset = ev -> + getPointCharOffset = p -> { if (bounds.width <= 0) { return 0; } - int cx = ev.getX() - ccl.getX() - ox; - int cy = ev.getY() - ccl.getY() - oy; + int cx = p.x - ccl.getX() - ox; + int cy = p.y - ccl.getY() - oy; int currentLine = Ints.constrainToRange(cy / oh, 0, editLines.size() - 1); @@ -491,6 +492,48 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse charIndex = Ints.constrainToRange(charIndex, 0, tsValue.length()); return line.start + charIndex; }; + + getLineOffset = code -> + { + if (editLines.size() < 2) + { + return cursorStart; + } + + int currentLine = -1; + for (int i = 0; i < editLines.size(); i++) + { + Line l = editLines.get(i); + if (cursorOnLine(cursorStart, l.start, l.end) + || (cursorOnLine(cursorStart, l.start, l.end + 1) && i == editLines.size() - 1)) + { + currentLine = i; + break; + } + } + + if (currentLine == -1 + || (code == KeyEvent.VK_UP && currentLine == 0) + || (code == KeyEvent.VK_DOWN && currentLine == editLines.size() - 1)) + { + return cursorStart; + } + + final Line line = editLines.get(currentLine); + final int direction = code == KeyEvent.VK_UP ? -1 : 1; + final Point dest = new Point(cursor.getCanvasLocation().getX(), cursor.getCanvasLocation().getY() + (direction * oh)); + final int charOffset = getPointCharOffset.applyAsInt(dest); + + // Place cursor on right line if whitespace keep it on the same line or skip a line + final Line nextLine = editLines.get(currentLine + direction); + if ((direction == -1 && charOffset >= line.start) + || (direction == 1 && (charOffset > nextLine.end && (currentLine + direction != editLines.size() - 1)))) + { + return nextLine.end; + } + + return charOffset; + }; } private boolean cursorOnLine(final int cursor, final int start, final int end) @@ -498,6 +541,16 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse return (cursor >= start) && (cursor <= end); } + private int getCharOffset(MouseEvent ev) + { + if (getPointCharOffset == null) + { + return 0; + } + + return getPointCharOffset.applyAsInt(ev.getPoint()); + } + @Override protected void open() { @@ -668,6 +721,14 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse ev.consume(); newPos++; break; + case KeyEvent.VK_UP: + ev.consume(); + newPos = getLineOffset.applyAsInt(code); + break; + case KeyEvent.VK_DOWN: + ev.consume(); + newPos = getLineOffset.applyAsInt(code); + break; case KeyEvent.VK_HOME: ev.consume(); newPos = 0; @@ -739,12 +800,12 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse { selectionStart = -1; selectionEnd = -1; - cursorAt(getCharOffset.applyAsInt(mouseEvent)); + cursorAt(getCharOffset(mouseEvent)); } return mouseEvent; } - int nco = getCharOffset.applyAsInt(mouseEvent); + int nco = getCharOffset(mouseEvent); if (mouseEvent.isShiftDown() && selectionEnd != -1) { @@ -786,7 +847,7 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse return mouseEvent; } - int nco = getCharOffset.applyAsInt(mouseEvent); + int nco = getCharOffset(mouseEvent); if (selectionStart != -1) { selectionEnd = nco; From 4effbba361c638ebf7dfd4ba7112c7ea7e9a8bf7 Mon Sep 17 00:00:00 2001 From: Ron Young Date: Wed, 13 Feb 2019 20:44:11 -0600 Subject: [PATCH 043/102] Limit wiki input lines to 1 --- .../runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java index 51ea075d2f..cc68aef20b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java @@ -82,6 +82,7 @@ public class WikiSearchChatboxTextInput extends ChatboxTextInput super(chatboxPanelManager, clientThread); this.chatboxPanelManager = chatboxPanelManager; + lines(1); prompt("OSRS Wiki Search"); onDone(string -> { From b855371d8b6859f7616f56391b159a32ad348ad6 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 Feb 2019 19:02:50 -0500 Subject: [PATCH 044/102] xptracker: treat players with rank -1 as unranked --- .../java/net/runelite/http/service/xp/XpTrackerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java b/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java index 5ef7e829e4..9f4e639964 100644 --- a/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java +++ b/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java @@ -289,7 +289,7 @@ public class XpTrackerService private static Duration updateFrequency(PlayerEntity playerEntity) { Integer rank = playerEntity.getRank(); - if (rank == null) + if (rank == null || rank == -1) { return Duration.ofDays(7); } From fe2eba06a70737528daea372a26283ded5ae654e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 Feb 2019 21:14:17 -0500 Subject: [PATCH 045/102] http service: use gson instead of jackson for json serialization This fixes deserailization of the loot timestamps for the loot tracker, and maybe other things. Note this does not use the same Gson instance as http-api as Spring creates its own Gson, however they are both default Gson instances. --- ...gurer.java => SpringWebMvcConfigurer.java} | 21 +++++++++++++++---- .../src/test/resources/application.properties | 3 +-- 2 files changed, 18 insertions(+), 6 deletions(-) rename http-service/src/main/java/net/runelite/http/service/{SpringContentNegotiationConfigurer.java => SpringWebMvcConfigurer.java} (77%) diff --git a/http-service/src/main/java/net/runelite/http/service/SpringContentNegotiationConfigurer.java b/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java similarity index 77% rename from http-service/src/main/java/net/runelite/http/service/SpringContentNegotiationConfigurer.java rename to http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java index ed055d0bdf..4402ea6e89 100644 --- a/http-service/src/main/java/net/runelite/http/service/SpringContentNegotiationConfigurer.java +++ b/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java @@ -24,22 +24,35 @@ */ package net.runelite.http.service; +import java.util.List; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -/** - * Configure .js as application/json to trick Cloudflare into caching json responses - */ @Configuration @EnableWebMvc -public class SpringContentNegotiationConfigurer extends WebMvcConfigurerAdapter +public class SpringWebMvcConfigurer extends WebMvcConfigurerAdapter { + /** + * Configure .js as application/json to trick Cloudflare into caching json responses + */ @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.mediaType("js", MediaType.APPLICATION_JSON); } + + /** + * Use GSON instead of Jackson for JSON serialization + * @param converters + */ + @Override + public void configureMessageConverters(List> converters) + { + converters.add(new GsonHttpMessageConverter()); + } } diff --git a/http-service/src/test/resources/application.properties b/http-service/src/test/resources/application.properties index cb3dcc0507..ded3472a5c 100644 --- a/http-service/src/test/resources/application.properties +++ b/http-service/src/test/resources/application.properties @@ -7,5 +7,4 @@ minio.bucket=runelite runelite.twitter.consumerkey=moo runelite.twitter.secretkey=cow runelite.twitter.listid=968949795153948673 -logging.level.net.runelite=DEBUG -spring.jackson.serialization.indent_output=true \ No newline at end of file +logging.level.net.runelite=DEBUG \ No newline at end of file From 7f3584e155a951488c2d0f04b123dae74c45b10b Mon Sep 17 00:00:00 2001 From: mabel5 Date: Thu, 7 Feb 2019 02:30:17 -0500 Subject: [PATCH 046/102] Added decoration objects to object markers Fixes #7711 --- .../ObjectIndicatorsOverlay.java | 16 ++++- .../ObjectIndicatorsPlugin.java | 66 +++++++++++++------ 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java index af9431038e..f111a6f94f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java @@ -29,6 +29,7 @@ import java.awt.Graphics2D; import java.awt.Polygon; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; import net.runelite.api.TileObject; import net.runelite.client.ui.overlay.Overlay; @@ -65,22 +66,31 @@ class ObjectIndicatorsOverlay extends Overlay } final Polygon polygon; + Polygon polygon2 = null; if (object instanceof GameObject) { polygon = ((GameObject) object).getConvexHull(); } + else if (object instanceof DecorativeObject) + { + polygon = ((DecorativeObject) object).getConvexHull(); + polygon2 = ((DecorativeObject) object).getConvexHull2(); + } else { polygon = object.getCanvasTilePoly(); } - if (polygon == null) + if (polygon != null) { - continue; + OverlayUtil.renderPolygon(graphics, polygon, config.markerColor()); } - OverlayUtil.renderPolygon(graphics, polygon, config.markerColor()); + if (polygon2 != null) + { + OverlayUtil.renderPolygon(graphics, polygon2, config.markerColor()); + } } return null; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java index a352d728db..05fd84d0d8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java @@ -43,6 +43,7 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import static net.runelite.api.Constants.REGION_SIZE; +import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; import net.runelite.api.GameState; import net.runelite.api.MenuAction; @@ -58,6 +59,8 @@ import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.DecorativeObjectSpawned; +import net.runelite.api.events.DecorativeObjectDespawned; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyListener; @@ -158,26 +161,15 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener @Subscribe public void onGameObjectSpawned(GameObjectSpawned event) { - final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, event.getGameObject().getLocalLocation()); - final Set objectPoints = points.get(worldPoint.getRegionID()); + final GameObject eventObject = event.getGameObject(); + checkObjectPoints(eventObject); + } - if (objectPoints == null) - { - return; - } - - for (ObjectPoint objectPoint : objectPoints) - { - if ((worldPoint.getX() & (REGION_SIZE - 1)) == objectPoint.getRegionX() - && (worldPoint.getY() & (REGION_SIZE - 1)) == objectPoint.getRegionY()) - { - if (objectPoint.getName().equals(client.getObjectDefinition(event.getGameObject().getId()).getName())) - { - objects.add(event.getGameObject()); - break; - } - } - } + @Subscribe + public void onDecorativeObjectSpawned(DecorativeObjectSpawned event) + { + final DecorativeObject eventObject = event.getDecorativeObject(); + checkObjectPoints(eventObject); } @Subscribe @@ -186,6 +178,12 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener objects.remove(event.getGameObject()); } + @Subscribe + public void onDecorativeObjectDespawned(DecorativeObjectDespawned event) + { + objects.remove(event.getDecorativeObject()); + } + @Subscribe public void onGameStateChanged(GameStateChanged gameStateChanged) { @@ -263,6 +261,30 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener markObject(name, object); } + private void checkObjectPoints(TileObject object) + { + final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, object.getLocalLocation()); + final Set objectPoints = points.get(worldPoint.getRegionID()); + + if (objectPoints == null) + { + return; + } + + for (ObjectPoint objectPoint : objectPoints) + { + if ((worldPoint.getX() & (REGION_SIZE - 1)) == objectPoint.getRegionX() + && (worldPoint.getY() & (REGION_SIZE - 1)) == objectPoint.getRegionY()) + { + if (objectPoint.getName().equals(client.getObjectDefinition(object.getId()).getName())) + { + objects.add(object); + break; + } + } + } + } + private TileObject findTileObject(Tile tile, int id) { if (tile == null) @@ -271,6 +293,12 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener } final GameObject[] tileGameObjects = tile.getGameObjects(); + final DecorativeObject tileDecorativeObject = tile.getDecorativeObject(); + + if (tileDecorativeObject != null && tileDecorativeObject.getId() == id) + { + return tileDecorativeObject; + } for (GameObject object : tileGameObjects) { From 38ab5694226cd5cd652e845b291a1d4b0d8c6b12 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sat, 16 Feb 2019 20:35:59 -0700 Subject: [PATCH 047/102] mixins: Include game crash string in log This lets the client print the cs2 vm stack to our logs --- .../main/java/net/runelite/mixins/ProcessClientErrorMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/ProcessClientErrorMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/ProcessClientErrorMixin.java index a4498ea814..eb3e971a3a 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/ProcessClientErrorMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/ProcessClientErrorMixin.java @@ -55,7 +55,7 @@ public abstract class ProcessClientErrorMixin implements RSClient throwableToScan = ((RSRunException) throwable).getParent(); } - client.getLogger().error("Game crash", throwableToScan); + client.getLogger().error("Game crash: {}", string, throwableToScan); StackTraceElement[] stackTrace = throwableToScan.getStackTrace(); From e5387a37e25e04850da45f49a10b01c639919a38 Mon Sep 17 00:00:00 2001 From: Yani Date: Sun, 17 Feb 2019 04:47:26 +0100 Subject: [PATCH 048/102] Update Rimmington yew tree location after Veos moved (#7889) --- .../net/runelite/client/plugins/worldmap/RareTreeLocation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java index ca30b23271..d32dee4c32 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java @@ -140,7 +140,7 @@ enum RareTreeLocation new WorldPoint(3018, 3316, 0), new WorldPoint(3041, 3320, 0), new WorldPoint(3052, 3272, 0), - new WorldPoint(2933, 3234, 0), + new WorldPoint(2931, 3231, 0), // Misthalin new WorldPoint(3085, 3481, 0), From a26197e91e5f194b65cb8451568792eec9339ec1 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 17 Feb 2019 21:57:50 +0100 Subject: [PATCH 049/102] Log infobox removal only if infobox was removed Debug log infobox removal from infobox manager only if infobox was really removed. Signed-off-by: Tomas Slusny --- .../runelite/client/ui/overlay/infobox/InfoBoxManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java index 8cea4cc94e..4fd1c1ca11 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java @@ -76,18 +76,18 @@ public class InfoBoxManager public void removeInfoBox(InfoBox infoBox) { - log.debug("Removing InfoBox {}", infoBox); if (infoBoxes.remove(infoBox)) { + log.debug("Removed InfoBox {}", infoBox); refreshInfoBoxes(); } } public void removeIf(Predicate filter) { - log.debug("Removing InfoBoxes for filter {}", filter); if (infoBoxes.removeIf(filter)) { + log.debug("Removed InfoBoxes for filter {}", filter); refreshInfoBoxes(); } } From 2a41d88c29beda2f681c58f404040c6b449a6c2f Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 17 Feb 2019 10:05:39 -0500 Subject: [PATCH 050/102] http service: use spring datasource configuration --- http-service/pom.xml | 9 ++ .../service/SpringBootWebApplication.java | 88 +++++++++++++++---- .../src/main/resources/application.yaml | 7 ++ .../service/SpringBootWebApplicationTest.java | 48 ++-------- .../src/test/resources/application.properties | 10 --- .../src/test/resources/application.yaml | 35 ++++++++ http-service/src/test/resources/dev.yaml | 19 ++++ 7 files changed, 146 insertions(+), 70 deletions(-) create mode 100644 http-service/src/main/resources/application.yaml delete mode 100644 http-service/src/test/resources/application.properties create mode 100644 http-service/src/test/resources/application.yaml create mode 100644 http-service/src/test/resources/dev.yaml diff --git a/http-service/pom.xml b/http-service/pom.xml index 75e257d32d..32dc046a4c 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -55,6 +55,10 @@ spring-boot-devtools true + + org.springframework + spring-jdbc + org.mapstruct @@ -130,6 +134,11 @@ 3.7.0 test + + com.h2database + h2 + test + diff --git a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java index 562d93445a..bfdac0a254 100644 --- a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java +++ b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java @@ -25,13 +25,11 @@ package net.runelite.http.service; import ch.qos.logback.classic.LoggerContext; +import com.google.common.base.Strings; import java.io.IOException; import java.time.Instant; import java.util.HashMap; import java.util.Map; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -44,11 +42,17 @@ import okhttp3.Cache; import okhttp3.OkHttpClient; import org.slf4j.ILoggerFactory; import org.slf4j.impl.StaticLoggerBinder; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; +import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup; import org.springframework.scheduling.annotation.EnableScheduling; import org.sql2o.Sql2o; import org.sql2o.converters.Converter; @@ -56,6 +60,7 @@ import org.sql2o.quirks.NoQuirks; @SpringBootApplication @EnableScheduling +@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) @Slf4j public class SpringBootWebApplication extends SpringBootServletInitializer { @@ -96,35 +101,80 @@ public class SpringBootWebApplication extends SpringBootServletInitializer }; } - private Context getContext() throws NamingException + @ConfigurationProperties(prefix = "datasource.runelite") + @Bean("dataSourceRuneLite") + public DataSourceProperties dataSourceProperties() { - Context initCtx = new InitialContext(); - return (Context) initCtx.lookup("java:comp/env"); + return new DataSourceProperties(); + } + + @ConfigurationProperties(prefix = "datasource.runelite-cache") + @Bean("dataSourceRuneLiteCache") + public DataSourceProperties dataSourcePropertiesCache() + { + return new DataSourceProperties(); + } + + @ConfigurationProperties(prefix = "datasource.runelite-tracker") + @Bean("dataSourceRuneLiteTracker") + public DataSourceProperties dataSourcePropertiesTracker() + { + return new DataSourceProperties(); + } + + @Bean(value = "runelite", destroyMethod = "") + public DataSource runeliteDataSource(@Qualifier("dataSourceRuneLite") DataSourceProperties dataSourceProperties) + { + return getDataSource(dataSourceProperties); + } + + @Bean(value = "runelite-cache", destroyMethod = "") + public DataSource runeliteCache2DataSource(@Qualifier("dataSourceRuneLiteCache") DataSourceProperties dataSourceProperties) + { + return getDataSource(dataSourceProperties); + } + + @Bean(value = "runelite-tracker", destroyMethod = "") + public DataSource runeliteTrackerDataSource(@Qualifier("dataSourceRuneLiteTracker") DataSourceProperties dataSourceProperties) + { + return getDataSource(dataSourceProperties); } @Bean("Runelite SQL2O") - Sql2o sql2o() throws NamingException + public Sql2o sql2o(@Qualifier("runelite") DataSource dataSource) { - DataSource dataSource = (DataSource) getContext().lookup("jdbc/runelite"); - Map converters = new HashMap<>(); - converters.put(Instant.class, new InstantConverter()); - return new Sql2o(dataSource, new NoQuirks(converters)); + return createSql2oFromDataSource(dataSource); } @Bean("Runelite Cache SQL2O") - Sql2o cacheSql2o() throws NamingException + public Sql2o cacheSql2o(@Qualifier("runelite-cache") DataSource dataSource) { - DataSource dataSource = (DataSource) getContext().lookup("jdbc/runelite-cache2"); - Map converters = new HashMap<>(); - converters.put(Instant.class, new InstantConverter()); - return new Sql2o(dataSource, new NoQuirks(converters)); + return createSql2oFromDataSource(dataSource); } @Bean("Runelite XP Tracker SQL2O") - Sql2o trackerSql2o() throws NamingException + public Sql2o trackerSql2o(@Qualifier("runelite-tracker") DataSource dataSource) { - DataSource dataSource = (DataSource) getContext().lookup("jdbc/runelite-tracker"); - Map converters = new HashMap<>(); + return createSql2oFromDataSource(dataSource); + } + + private static DataSource getDataSource(DataSourceProperties dataSourceProperties) + { + if (!Strings.isNullOrEmpty(dataSourceProperties.getJndiName())) + { + // Use JNDI provided datasource, which is already configured with pooling + JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup(); + return dataSourceLookup.getDataSource(dataSourceProperties.getJndiName()); + } + else + { + return dataSourceProperties.initializeDataSourceBuilder().build(); + } + } + + private static Sql2o createSql2oFromDataSource(final DataSource dataSource) + { + final Map converters = new HashMap<>(); converters.put(Instant.class, new InstantConverter()); return new Sql2o(dataSource, new NoQuirks(converters)); } diff --git a/http-service/src/main/resources/application.yaml b/http-service/src/main/resources/application.yaml new file mode 100644 index 0000000000..7b6785a325 --- /dev/null +++ b/http-service/src/main/resources/application.yaml @@ -0,0 +1,7 @@ +datasource: + runelite: + jndiName: java:comp/env/jdbc/runelite + runelite-cache: + jndiName: java:comp/env/jdbc/runelite-cache2 + runelite-tracker: + jndiName: java:comp/env/jdbc/runelite-tracker \ No newline at end of file diff --git a/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java b/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java index 0503c075d8..d2d488e1e6 100644 --- a/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java +++ b/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Adam + * Copyright (c) 2019, Adam * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,57 +24,23 @@ */ package net.runelite.http.service; -import java.time.Instant; -import java.util.HashMap; -import java.util.Map; -import javax.naming.NamingException; -import net.runelite.http.service.util.InstantConverter; import org.junit.Ignore; import org.junit.Test; import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.sql2o.Sql2o; -import org.sql2o.converters.Converter; -import org.sql2o.quirks.NoQuirks; -@SpringBootApplication -@EnableScheduling public class SpringBootWebApplicationTest { - @Bean("Runelite SQL2O") - Sql2o sql2o() - { - Map converters = new HashMap<>(); - converters.put(Instant.class, new InstantConverter()); - return new Sql2o("jdbc:mysql://192.168.1.2/runelite", "runelite", "runelite", new NoQuirks(converters)); - } - - @Bean("Runelite Cache SQL2O") - Sql2o cacheSql2o() throws NamingException - { - Map converters = new HashMap<>(); - converters.put(Instant.class, new InstantConverter()); - return new Sql2o("jdbc:mysql://192.168.1.2/cache", "runelite", "runelite", new NoQuirks(converters)); - } - - @Bean("Runelite XP Tracker SQL2O") - Sql2o xpSql2o() throws NamingException - { - Map converters = new HashMap<>(); - converters.put(Instant.class, new InstantConverter()); - return new Sql2o("jdbc:mysql://192.168.1.2/xptracker", "runelite", "runelite", new NoQuirks(converters)); - } - @Test @Ignore - public void test() throws InterruptedException + public void run() throws InterruptedException { - SpringApplication.run(SpringBootWebApplicationTest.class, new String[0]); + String[] args = new String[]{ + "--spring.config.location=classpath:/application.yaml,classpath:/dev.yaml" + }; + SpringApplication.run(SpringBootWebApplication.class, args); for (;;) { Thread.sleep(100L); } } -} +} \ No newline at end of file diff --git a/http-service/src/test/resources/application.properties b/http-service/src/test/resources/application.properties deleted file mode 100644 index ded3472a5c..0000000000 --- a/http-service/src/test/resources/application.properties +++ /dev/null @@ -1,10 +0,0 @@ -oauth.client-id=moo -oauth.client-secret=cow -minio.endpoint=http://10.96.22.171:9000 -minio.accesskey=AM54M27O4WZK65N6F8IP -minio.secretkey=/PZCxzmsJzwCHYlogcymuprniGCaaLUOET2n6yMP -minio.bucket=runelite -runelite.twitter.consumerkey=moo -runelite.twitter.secretkey=cow -runelite.twitter.listid=968949795153948673 -logging.level.net.runelite=DEBUG \ No newline at end of file diff --git a/http-service/src/test/resources/application.yaml b/http-service/src/test/resources/application.yaml new file mode 100644 index 0000000000..128e64d8ef --- /dev/null +++ b/http-service/src/test/resources/application.yaml @@ -0,0 +1,35 @@ +oauth: + client-id: moo + client-secret: cow + +minio: + endpoint: http://10.96.22.171:9000 + accesskey: AM54M27O4WZK65N6F8IP + secretkey: /PZCxzmsJzwCHYlogcymuprniGCaaLUOET2n6yMP + bucket: runelite + +runelite: + twitter: + consumerkey: moo + secretkey: cow + listid: 968949795153948673 + +logging: + level: + net: + runelite: + DEBUG + +datasource: + runelite: + driverClassName: org.h2.Driver + type: org.h2.jdbcx.JdbcDataSource + url: jdbc:h2:mem:runelite + runelite-cache: + driverClassName: org.h2.Driver + type: org.h2.jdbcx.JdbcDataSource + url: jdbc:h2:mem:cache + runelite-tracker: + driverClassName: org.h2.Driver + type: org.h2.jdbcx.JdbcDataSource + url: jdbc:h2:mem:xptracker diff --git a/http-service/src/test/resources/dev.yaml b/http-service/src/test/resources/dev.yaml new file mode 100644 index 0000000000..e4967ccee4 --- /dev/null +++ b/http-service/src/test/resources/dev.yaml @@ -0,0 +1,19 @@ +datasource: + runelite: + driverClassName: com.mysql.jdbc.Driver + type: com.mysql.jdbc.jdbc2.optional.MysqlDataSource + url: jdbc:mysql://192.168.1.2/runelite + username: runelite + password: runelite + runelite-cache: + driverClassName: com.mysql.jdbc.Driver + type: com.mysql.jdbc.jdbc2.optional.MysqlDataSource + url: jdbc:mysql://192.168.1.2/cache + username: runelite + password: runelite + runelite-tracker: + driverClassName: com.mysql.jdbc.Driver + type: com.mysql.jdbc.jdbc2.optional.MysqlDataSource + url: jdbc:mysql://192.168.1.2/xptracker + username: runelite + password: runelite From c55491cc117a65c043213ee68163008424930972 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 17 Feb 2019 12:47:41 -0500 Subject: [PATCH 051/102] http service: add loottracker controller test --- .../LootTrackerControllerTest.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java diff --git a/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java b/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java new file mode 100644 index 0000000000..e708de0c29 --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/loottracker/LootTrackerControllerTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.loottracker; + +import java.io.IOException; +import java.time.Instant; +import java.util.Collections; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import net.runelite.http.api.RuneLiteAPI; +import net.runelite.http.api.loottracker.GameItem; +import net.runelite.http.api.loottracker.LootRecord; +import net.runelite.http.api.loottracker.LootRecordType; +import net.runelite.http.service.account.AuthFilter; +import net.runelite.http.service.account.beans.SessionEntry; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest(LootTrackerController.class) +@Slf4j +public class LootTrackerControllerTest +{ + @Autowired + private MockMvc mockMvc; + + @MockBean + private LootTrackerService lootTrackerService; + + @MockBean + private AuthFilter authFilter; + + @Before + public void before() throws IOException + { + when(authFilter.handle(any(HttpServletRequest.class), any(HttpServletResponse.class))) + .thenReturn(mock(SessionEntry.class)); + } + + @Test + public void storeLootRecord() throws Exception + { + LootRecord lootRecord = new LootRecord(); + lootRecord.setType(LootRecordType.NPC); + lootRecord.setTime(Instant.now()); + lootRecord.setDrops(Collections.singletonList(new GameItem(4151, 1))); + + String data = RuneLiteAPI.GSON.toJson(lootRecord); + mockMvc.perform(post("/loottracker").content(data).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + + verify(lootTrackerService).store(eq(lootRecord), anyInt()); + } +} \ No newline at end of file From 38cdbfcb6b9dc24556c6db3cd5a68f132ba32369 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 17 Feb 2019 17:51:14 -0500 Subject: [PATCH 052/102] http service: use http-api gson instance --- .../net/runelite/http/service/SpringWebMvcConfigurer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java b/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java index 4402ea6e89..f0fd4ed99c 100644 --- a/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java +++ b/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java @@ -25,6 +25,7 @@ package net.runelite.http.service; import java.util.List; +import net.runelite.http.api.RuneLiteAPI; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; @@ -53,6 +54,8 @@ public class SpringWebMvcConfigurer extends WebMvcConfigurerAdapter @Override public void configureMessageConverters(List> converters) { - converters.add(new GsonHttpMessageConverter()); + GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter(); + gsonHttpMessageConverter.setGson(RuneLiteAPI.GSON); + converters.add(gsonHttpMessageConverter); } } From f0c5e0d1f70454c56b3d92052641e4f9b208b7e3 Mon Sep 17 00:00:00 2001 From: Dennis Date: Mon, 18 Feb 2019 13:41:05 +0100 Subject: [PATCH 053/102] gpu: remove unnecessary texture bind --- .../main/java/net/runelite/client/plugins/gpu/GpuPlugin.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index a7871f95da..93d8a522d9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -1151,8 +1151,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, width, height, gl.GL_BGRA, gl.GL_UNSIGNED_INT_8_8_8_8_REV, interfaceBuffer); } - gl.glBindTexture(gl.GL_TEXTURE_2D, interfaceTexture); - if (client.isStretchedEnabled()) { Dimension dim = client.getStretchedDimensions(); From 1fd617c35977e58a292ec65856cf80a4f47077d4 Mon Sep 17 00:00:00 2001 From: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> Date: Mon, 18 Feb 2019 07:13:40 -0800 Subject: [PATCH 054/102] Add PM Target Cycling to Chat History plugin --- .../main/java/net/runelite/api/ScriptID.java | 18 +++ .../java/net/runelite/api/VarClientStr.java | 1 + .../java/net/runelite/api/vars/InputType.java | 1 + .../chathistory/ChatHistoryPlugin.java | 143 ++++++++++++++---- 4 files changed, 137 insertions(+), 26 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java index 778b271036..05c057a38d 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java @@ -45,6 +45,24 @@ public final class ScriptID */ public static final int CHATBOX_INPUT = 96; + /** + * Opens the Private Message chat interface + * + * Jagex refers to this script as {@code meslayer_mode6} + *
    + *
  • String Player to send private message to
  • + *
+ */ + public static final int OPEN_PRIVATE_MESSAGE_INTERFACE = 107; + + /** + * Rebuilds the text input widget inside the chat interface + *
    + *
  • String Message Prefix. Only used inside the GE search interfaces + *
+ */ + public static final int CHAT_TEXT_INPUT_REBUILD = 222; + /** * Layouts the bank widgets * diff --git a/runelite-api/src/main/java/net/runelite/api/VarClientStr.java b/runelite-api/src/main/java/net/runelite/api/VarClientStr.java index b3bf1b09b6..72f4ee0303 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarClientStr.java +++ b/runelite-api/src/main/java/net/runelite/api/VarClientStr.java @@ -36,6 +36,7 @@ public enum VarClientStr { CHATBOX_TYPED_TEXT(1), INPUT_TEXT(22), + PRIVATE_MESSAGE_TARGET(23), RECENT_CLAN_CHAT(129); private final int index; diff --git a/runelite-api/src/main/java/net/runelite/api/vars/InputType.java b/runelite-api/src/main/java/net/runelite/api/vars/InputType.java index db1301b281..c94ccd79ef 100644 --- a/runelite-api/src/main/java/net/runelite/api/vars/InputType.java +++ b/runelite-api/src/main/java/net/runelite/api/vars/InputType.java @@ -38,6 +38,7 @@ public enum InputType RUNELITE_CHATBOX_PANEL(-3), RUNELITE(-2), NONE(0), + PRIVATE_MESSAGE(6), SEARCH(11); private final int type; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java index 6ac89bf605..77fcb70df0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java @@ -25,39 +25,53 @@ package net.runelite.client.plugins.chathistory; import com.google.common.collect.EvictingQueue; -import com.google.common.collect.Sets; +import java.awt.event.KeyEvent; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; import java.util.Queue; -import java.util.Set; import javax.inject.Inject; import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.ScriptID; +import net.runelite.api.VarClientInt; +import net.runelite.api.VarClientStr; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.vars.InputType; +import net.runelite.client.callback.ClientThread; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.QueuedMessage; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.Text; @PluginDescriptor( name = "Chat History", - description = "Retain your chat history when logging in/out or world hopping" + description = "Retain your chat history when logging in/out or world hopping", + tags = {"chat", "history", "retain", "cycle", "pm"} ) -public class ChatHistoryPlugin extends Plugin +public class ChatHistoryPlugin extends Plugin implements KeyListener { private static final String WELCOME_MESSAGE = "Welcome to Old School RuneScape."; private static final String CLEAR_HISTORY = "Clear history"; private static final String CLEAR_PRIVATE = "Private:"; - private static final Set ALLOWED_HISTORY = Sets.newHashSet( - ChatMessageType.PUBLIC, - ChatMessageType.PUBLIC_MOD, - ChatMessageType.CLANCHAT, - ChatMessageType.PRIVATE_MESSAGE_RECEIVED, - ChatMessageType.PRIVATE_MESSAGE_SENT, - ChatMessageType.PRIVATE_MESSAGE_RECEIVED_MOD, - ChatMessageType.GAME - ); + private static final int CYCLE_HOTKEY = KeyEvent.VK_TAB; private Queue messageQueue; + private Deque friends; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private KeyManager keyManager; @Inject private ChatMessageManager chatMessageManager; @@ -66,6 +80,8 @@ public class ChatHistoryPlugin extends Plugin protected void startUp() { messageQueue = EvictingQueue.create(100); + friends = new ArrayDeque<>(5); + keyManager.registerKeyListener(this); } @Override @@ -73,6 +89,9 @@ public class ChatHistoryPlugin extends Plugin { messageQueue.clear(); messageQueue = null; + friends.clear(); + friends = null; + keyManager.unregisterKeyListener(this); } @Subscribe @@ -92,21 +111,33 @@ public class ChatHistoryPlugin extends Plugin return; } - if (ALLOWED_HISTORY.contains(chatMessage.getType())) + switch (chatMessage.getType()) { - final QueuedMessage queuedMessage = QueuedMessage.builder() - .type(chatMessage.getType()) - .name(chatMessage.getName()) - .sender(chatMessage.getSender()) - .value(nbsp(chatMessage.getMessage())) - .runeLiteFormattedMessage(nbsp(chatMessage.getMessageNode().getRuneLiteFormatMessage())) - .timestamp(chatMessage.getTimestamp()) - .build(); + case PRIVATE_MESSAGE_SENT: + case PRIVATE_MESSAGE_RECEIVED: + case PRIVATE_MESSAGE_RECEIVED_MOD: + final String name = Text.removeTags(chatMessage.getName()); + // Remove to ensure uniqueness & its place in history + friends.remove(name); + friends.add(name); + // intentional fall-through + case PUBLIC: + case PUBLIC_MOD: + case CLANCHAT: + case GAME: + final QueuedMessage queuedMessage = QueuedMessage.builder() + .type(chatMessage.getType()) + .name(chatMessage.getName()) + .sender(chatMessage.getSender()) + .value(nbsp(chatMessage.getMessage())) + .runeLiteFormattedMessage(nbsp(chatMessage.getMessageNode().getRuneLiteFormatMessage())) + .timestamp(chatMessage.getTimestamp()) + .build(); - if (!messageQueue.contains(queuedMessage)) - { - messageQueue.offer(queuedMessage); - } + if (!messageQueue.contains(queuedMessage)) + { + messageQueue.offer(queuedMessage); + } } } @@ -143,4 +174,64 @@ public class ChatHistoryPlugin extends Plugin return null; } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() != CYCLE_HOTKEY) + { + return; + } + + if (client.getVar(VarClientInt.INPUT_TYPE) != InputType.PRIVATE_MESSAGE.getType()) + { + return; + } + + clientThread.invoke(() -> + { + final String target = findPreviousFriend(); + if (target == null) + { + return; + } + + final String currentMessage = client.getVar(VarClientStr.INPUT_TEXT); + + client.runScript(ScriptID.OPEN_PRIVATE_MESSAGE_INTERFACE, target); + + client.setVar(VarClientStr.INPUT_TEXT, currentMessage); + client.runScript(ScriptID.CHAT_TEXT_INPUT_REBUILD, ""); + }); + } + + @Override + public void keyTyped(KeyEvent e) + { + } + + @Override + public void keyReleased(KeyEvent e) + { + } + + private String findPreviousFriend() + { + final String currentTarget = client.getVar(VarClientStr.PRIVATE_MESSAGE_TARGET); + if (currentTarget == null || friends.isEmpty()) + { + return null; + } + + for (Iterator it = friends.descendingIterator(); it.hasNext(); ) + { + String friend = it.next(); + if (friend.equals(currentTarget)) + { + return it.hasNext() ? it.next() : friends.getLast(); + } + } + + return friends.getLast(); + } } From c3bbd4934817d741c4d9ce8f59c6dc95dd42b7e5 Mon Sep 17 00:00:00 2001 From: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> Date: Mon, 18 Feb 2019 07:14:21 -0800 Subject: [PATCH 055/102] Add Chat History config options --- .../chathistory/ChatHistoryConfig.java | 55 +++++++++++++++++++ .../chathistory/ChatHistoryPlugin.java | 18 +++++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java new file mode 100644 index 0000000000..e30629c742 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * 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.plugins.chathistory; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("chathistory") +public interface ChatHistoryConfig extends Config +{ + @ConfigItem( + keyName = "retainChatHistory", + name = "Retain Chat History", + description = "Retains chat history when logging in/out or world hopping", + position = 0 + ) + default boolean retainChatHistory() + { + return true; + } + + @ConfigItem( + keyName = "pmTargetCycling", + name = "PM Target Cycling", + description = "Pressing Tab while sending a PM will cycle the target username based on PM history", + position = 1 + ) + default boolean pmTargetCycling() + { + return true; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java index 77fcb70df0..43919214ea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java @@ -25,6 +25,7 @@ package net.runelite.client.plugins.chathistory; import com.google.common.collect.EvictingQueue; +import com.google.inject.Provides; import java.awt.event.KeyEvent; import java.util.ArrayDeque; import java.util.Deque; @@ -42,6 +43,7 @@ import net.runelite.api.vars.InputType; import net.runelite.client.callback.ClientThread; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.QueuedMessage; +import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyListener; import net.runelite.client.input.KeyManager; @@ -70,11 +72,20 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Inject private ClientThread clientThread; + @Inject + private ChatHistoryConfig config; + @Inject private KeyManager keyManager; @Inject private ChatMessageManager chatMessageManager; + + @Provides + ChatHistoryConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(ChatHistoryConfig.class); + } @Override protected void startUp() @@ -101,6 +112,11 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener // of information that chat history was reset if (chatMessage.getMessage().equals(WELCOME_MESSAGE)) { + if (!config.retainChatHistory()) + { + return; + } + QueuedMessage queuedMessage; while ((queuedMessage = messageQueue.poll()) != null) @@ -178,7 +194,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Override public void keyPressed(KeyEvent e) { - if (e.getKeyCode() != CYCLE_HOTKEY) + if (e.getKeyCode() != CYCLE_HOTKEY || !config.pmTargetCycling()) { return; } From aa5789b84357010d642a1e66bb605789ad93101f Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 18 Feb 2019 16:38:36 -0500 Subject: [PATCH 056/102] config service: split into service and controller --- .../http/service/config/ConfigController.java | 102 ++++++++++++++++++ .../http/service/config/ConfigService.java | 69 +++--------- 2 files changed, 117 insertions(+), 54 deletions(-) create mode 100644 http-service/src/main/java/net/runelite/http/service/config/ConfigController.java diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java new file mode 100644 index 0000000000..966d49cda2 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.config; + +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import net.runelite.http.api.config.Configuration; +import net.runelite.http.service.account.AuthFilter; +import net.runelite.http.service.account.beans.SessionEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import static org.springframework.web.bind.annotation.RequestMethod.DELETE; +import static org.springframework.web.bind.annotation.RequestMethod.PUT; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/config") +public class ConfigController +{ + private final ConfigService configService; + private final AuthFilter authFilter; + + @Autowired + public ConfigController(ConfigService configService, AuthFilter authFilter) + { + this.configService = configService; + this.authFilter = authFilter; + } + + @RequestMapping + public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return null; + } + + return configService.get(session.getUser()); + } + + @RequestMapping(path = "/{key:.+}", method = PUT) + public void setKey( + HttpServletRequest request, + HttpServletResponse response, + @PathVariable String key, + @RequestBody(required = false) String value + ) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return; + } + + configService.setKey(session.getUser(), key, value); + } + + @RequestMapping(path = "/{key:.+}", method = DELETE) + public void unsetKey( + HttpServletRequest request, + HttpServletResponse response, + @PathVariable String key + ) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return; + } + + configService.unsetKey(session.getUser(), key); + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java index 102e2f9c7a..ed96f36cf4 100644 --- a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java @@ -24,28 +24,18 @@ */ package net.runelite.http.service.config; -import java.io.IOException; import java.util.List; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import javax.annotation.Nullable; import net.runelite.http.api.config.ConfigEntry; import net.runelite.http.api.config.Configuration; -import net.runelite.http.service.account.AuthFilter; -import net.runelite.http.service.account.beans.SessionEntry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import static org.springframework.web.bind.annotation.RequestMethod.DELETE; -import static org.springframework.web.bind.annotation.RequestMethod.PUT; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.stereotype.Service; import org.sql2o.Connection; import org.sql2o.Sql2o; import org.sql2o.Sql2oException; -@RestController -@RequestMapping("/config") +@Service public class ConfigService { private static final String CREATE_CONFIG = "CREATE TABLE IF NOT EXISTS `config` (\n" @@ -59,16 +49,13 @@ public class ConfigService + " ADD CONSTRAINT `user_fk` FOREIGN KEY (`user`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;"; private final Sql2o sql2o; - private final AuthFilter auth; @Autowired public ConfigService( - @Qualifier("Runelite SQL2O") Sql2o sql2o, - AuthFilter auth + @Qualifier("Runelite SQL2O") Sql2o sql2o ) { this.sql2o = sql2o; - this.auth = auth; try (Connection con = sql2o.open()) { @@ -87,71 +74,45 @@ public class ConfigService } } - @RequestMapping - public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException + public Configuration get(int userId) { - SessionEntry session = auth.handle(request, response); - - if (session == null) - { - return null; - } - List config; try (Connection con = sql2o.open()) { config = con.createQuery("select `key`, value from config where user = :user") - .addParameter("user", session.getUser()) + .addParameter("user", userId) .executeAndFetch(ConfigEntry.class); } return new Configuration(config); } - @RequestMapping(path = "/{key:.+}", method = PUT) public void setKey( - HttpServletRequest request, - HttpServletResponse response, - @PathVariable String key, - @RequestBody(required = false) String value - ) throws IOException + int userId, + String key, + @Nullable String value + ) { - SessionEntry session = auth.handle(request, response); - - if (session == null) - { - return; - } - try (Connection con = sql2o.open()) { con.createQuery("insert into config (user, `key`, value) values (:user, :key, :value) on duplicate key update `key` = :key, value = :value") - .addParameter("user", session.getUser()) + .addParameter("user", userId) .addParameter("key", key) .addParameter("value", value != null ? value : "") .executeUpdate(); } } - @RequestMapping(path = "/{key:.+}", method = DELETE) public void unsetKey( - HttpServletRequest request, - HttpServletResponse response, - @PathVariable String key - ) throws IOException + int userId, + String key + ) { - SessionEntry session = auth.handle(request, response); - - if (session == null) - { - return; - } - try (Connection con = sql2o.open()) { con.createQuery("delete from config where user = :user and `key` = :key") - .addParameter("user", session.getUser()) + .addParameter("user", userId) .addParameter("key", key) .executeUpdate(); } From f62e7e3f143ffe85d607af79c523969bb358b457 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 18 Feb 2019 16:39:01 -0500 Subject: [PATCH 057/102] config controller: add test --- .../service/config/ConfigControllerTest.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java diff --git a/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java b/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java new file mode 100644 index 0000000000..5ba857ef0a --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/config/ConfigControllerTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.config; + +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import net.runelite.http.service.account.AuthFilter; +import net.runelite.http.service.account.beans.SessionEntry; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest(ConfigController.class) +@Slf4j +public class ConfigControllerTest +{ + @Autowired + private MockMvc mockMvc; + + @MockBean + private ConfigService configService; + + @MockBean + private AuthFilter authFilter; + + @Before + public void before() throws IOException + { + when(authFilter.handle(any(HttpServletRequest.class), any(HttpServletResponse.class))) + .thenReturn(mock(SessionEntry.class)); + } + + @Test + public void testSetKey() throws Exception + { + mockMvc.perform(put("/config/key") + .content("value") + .contentType(MediaType.TEXT_PLAIN)) + .andExpect(status().isOk()); + + verify(configService).setKey(anyInt(), eq("key"), eq("value")); + } +} \ No newline at end of file From 6186314dbc81abe94f0fdd24049b2e2c110154bd Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 18 Feb 2019 16:39:34 -0500 Subject: [PATCH 058/102] http service: fix overwriting all default message converters The previous change to try and force GSON for serialization broke default message converters such as text/plain. Change to use extendMessageConverters and remove the Jackson converter instead. --- .../net/runelite/http/service/SpringWebMvcConfigurer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java b/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java index f0fd4ed99c..704e4f9cb2 100644 --- a/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java +++ b/http-service/src/main/java/net/runelite/http/service/SpringWebMvcConfigurer.java @@ -30,6 +30,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.GsonHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @@ -52,8 +53,11 @@ public class SpringWebMvcConfigurer extends WebMvcConfigurerAdapter * @param converters */ @Override - public void configureMessageConverters(List> converters) + public void extendMessageConverters(List> converters) { + // Could not figure out a better way to force GSON + converters.removeIf(MappingJackson2HttpMessageConverter.class::isInstance); + GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter(); gsonHttpMessageConverter.setGson(RuneLiteAPI.GSON); converters.add(gsonHttpMessageConverter); From 2c76947527d93af090a18070c04dd1991339c308 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Mon, 18 Feb 2019 23:25:48 +0100 Subject: [PATCH 059/102] Support new Hydra slayer helmet in clue scroll plugin Signed-off-by: Tomas Slusny --- .../runelite/client/plugins/cluescrolls/clues/EmoteClue.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index 30a33d7e50..d3123ce2da 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -133,8 +133,8 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Panic by the pilot on White Wolf Mountain. Beware of double agents! Equip mithril platelegs, a ring of life and a rune axe.", GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN, new WorldPoint(2847, 3499, 0), PANIC, item(MITHRIL_PLATELEGS), item(RING_OF_LIFE), item(RUNE_AXE)), new EmoteClue("Panic by the big egg where no one dare goes and the ground is burnt. Beware of double agents! Equip a dragon med helm, a TokTz-Ket-Xil, a brine sabre, rune platebody and an uncharged amulet of glory.", SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE, new WorldPoint(3227, 3831, 0), PANIC, item(DRAGON_MED_HELM), item(TOKTZKETXIL), item(BRINE_SABRE), item(RUNE_PLATEBODY), item(AMULET_OF_GLORY)), new EmoteClue("Panic at the area flowers meet snow. Equip Blue D'hide vambs, a dragon spear and a rune plateskirt.", HALFWAY_DOWN_TROLLWEISS_MOUNTAIN, new WorldPoint(2776, 3781, 0), PANIC, item(BLUE_DHIDE_VAMB), item(DRAGON_SPEAR), item(RUNE_PLATESKIRT), item(SLED_4084)), - new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I))), - new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I))), + new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), + new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), new EmoteClue("Blow a raspberry at the monkey cage in Ardougne Zoo. Equip a studded leather body, bronze platelegs and a normal staff with no orb.", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)), new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)), new EmoteClue("Blow a raspberry in the Fishing Guild bank. Beware of double agents! Equip an elemental shield, blue dragonhide chaps and a rune warhammer.", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)), From e77b3ec76d83295e7feae2d75776f19751540fe8 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Mon, 18 Feb 2019 23:52:50 +0100 Subject: [PATCH 060/102] Add version information to Discord tooltip Signed-off-by: Tomas Slusny --- .../runelite/client/plugins/discord/DiscordState.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java index 625aed1f08..d4aef9572d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java @@ -34,6 +34,7 @@ import java.util.Optional; import java.util.UUID; import javax.inject.Inject; import lombok.Data; +import net.runelite.client.RuneLiteProperties; import net.runelite.client.discord.DiscordPresence; import net.runelite.client.discord.DiscordService; import net.runelite.client.ws.PartyService; @@ -57,14 +58,16 @@ class DiscordState private final DiscordService discordService; private final DiscordConfig config; private PartyService party; + private final RuneLiteProperties properties; private DiscordPresence lastPresence; @Inject - private DiscordState(final DiscordService discordService, final DiscordConfig config, final PartyService party) + private DiscordState(final DiscordService discordService, final DiscordConfig config, final PartyService party, final RuneLiteProperties properties) { this.discordService = discordService; this.config = config; this.party = party; + this.properties = properties; } /** @@ -90,6 +93,7 @@ class DiscordState final DiscordPresence.DiscordPresenceBuilder presenceBuilder = DiscordPresence.builder() .state(lastPresence.getState()) .details(lastPresence.getDetails()) + .largeImageText(lastPresence.getLargeImageText()) .startTimestamp(lastPresence.getStartTimestamp()) .smallImageKey(lastPresence.getSmallImageKey()) .partyMax(lastPresence.getPartyMax()) @@ -168,9 +172,13 @@ class DiscordState } } + // Replace snapshot with + to make tooltip shorter (so it will span only 1 line) + final String versionShortHand = properties.getVersion().replace("-SNAPSHOT", "+"); + final DiscordPresence.DiscordPresenceBuilder presenceBuilder = DiscordPresence.builder() .state(MoreObjects.firstNonNull(state, "")) .details(MoreObjects.firstNonNull(details, "")) + .largeImageText(properties.getTitle() + " v" + versionShortHand) .startTimestamp(event.getStart()) .smallImageKey(MoreObjects.firstNonNull(imageKey, "default")) .partyMax(PARTY_MAX) From ef1818b6dfbb926996a1a62bf5181c3b800a55d9 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 19 Feb 2019 00:44:09 +0100 Subject: [PATCH 061/102] Check for area update on Discord plugin startup Signed-off-by: Tomas Slusny --- .../java/net/runelite/client/plugins/discord/DiscordPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java index 06e0369535..9598b7eff5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java @@ -130,6 +130,7 @@ public class DiscordPlugin extends Plugin clientToolbar.addNavigation(discordButton); checkForGameStateUpdate(); + checkForAreaUpdate(); if (discordService.getCurrentUser() != null) { From 1089eba6bcfb8d55aac41ef7a506510cb2623bfc Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sun, 17 Feb 2019 11:15:25 -0700 Subject: [PATCH 062/102] mixins: rename gameDraw to renderWidgetLayer --- .../src/main/java/net/runelite/mixins/RSClientMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index b67eea80ab..122811ee37 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -1265,9 +1265,9 @@ public abstract class RSClientMixin implements RSClient callbacks.clientMainLoop(); } - @MethodHook("gameDraw") + @MethodHook("renderWidgetLayer") @Inject - public static void gameDraw(Widget[] widgets, int parentId, int var2, int var3, int var4, int var5, int x, int y, int var8) + public static void renderWidgetLayer(Widget[] widgets, int parentId, int var2, int var3, int var4, int var5, int x, int y, int var8) { for (Widget rlWidget : widgets) { From 2c822800c875c1774cc27fa700e7de2e9dac4726 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sun, 17 Feb 2019 19:35:57 -0700 Subject: [PATCH 063/102] runelite-api: Add missing widget types --- .../src/main/java/net/runelite/api/widgets/WidgetType.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetType.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetType.java index da76a7580f..9d140c3cd0 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetType.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetType.java @@ -27,9 +27,12 @@ package net.runelite.api.widgets; public final class WidgetType { public static final int LAYER = 0; + public static final int INVENTORY = 2; public static final int RECTANGLE = 3; public static final int TEXT = 4; public static final int GRAPHIC = 5; public static final int MODEL = 6; + public static final int TEXT_INVENTORY = 7; + public static final int IF1_TOOLTIP = 8; public static final int LINE = 9; } From ed461e14e53c0cc17a52463fb96881546f85ee1d Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 19 Feb 2019 08:54:33 +0100 Subject: [PATCH 064/102] Do not use default smallImageKey for Rich Presence Having big image with RuneLite logo and then small image with RuneLite logo in it's corner do not looks very good, so update the small icon only when it is showing something interesting. Signed-off-by: Tomas Slusny --- .../java/net/runelite/client/discord/DiscordService.java | 9 ++++++--- .../runelite/client/plugins/discord/DiscordState.java | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java index 0c2739b8a2..0988273ecc 100644 --- a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java +++ b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java @@ -150,9 +150,12 @@ public class DiscordService implements AutoCloseable ? "default" : discordPresence.getLargeImageKey(); discordRichPresence.largeImageText = discordPresence.getLargeImageText(); - discordRichPresence.smallImageKey = Strings.isNullOrEmpty(discordPresence.getSmallImageKey()) - ? "default" - : discordPresence.getSmallImageKey(); + + if (!Strings.isNullOrEmpty(discordPresence.getSmallImageKey())) + { + discordRichPresence.smallImageKey = discordPresence.getSmallImageKey(); + } + discordRichPresence.smallImageText = discordPresence.getSmallImageText(); discordRichPresence.partyId = discordPresence.getPartyId(); discordRichPresence.partySize = discordPresence.getPartySize(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java index d4aef9572d..0b57424f85 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java @@ -180,7 +180,7 @@ class DiscordState .details(MoreObjects.firstNonNull(details, "")) .largeImageText(properties.getTitle() + " v" + versionShortHand) .startTimestamp(event.getStart()) - .smallImageKey(MoreObjects.firstNonNull(imageKey, "default")) + .smallImageKey(imageKey) .partyMax(PARTY_MAX) .partySize(party.getMembers().size()); From be3903357427c367fb6cd1a64169152477cc99c8 Mon Sep 17 00:00:00 2001 From: Will Thomas Date: Thu, 14 Feb 2019 22:49:11 +0000 Subject: [PATCH 065/102] wiki plugin: Add skill guide lookup Signed-off-by: Will Thomas --- .../net/runelite/api/widgets/WidgetID.java | 1 + .../client/plugins/wiki/WikiPlugin.java | 61 +++++++++++++------ 2 files changed, 44 insertions(+), 18 deletions(-) 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 e919c0f992..be7e595dd7 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 @@ -126,6 +126,7 @@ public class WidgetID public static final int ENTERING_HOUSE_GROUP_ID = 71; public static final int FULLSCREEN_MAP_GROUP_ID = 165; public static final int QUESTLIST_GROUP_ID = 399; + public static final int SKILLS_GROUP_ID = 320; static class WorldMap { 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 e6b21437e0..44146c4cb5 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 @@ -27,6 +27,8 @@ package net.runelite.client.plugins.wiki; import com.google.common.primitives.Ints; import java.net.URLEncoder; import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.inject.Inject; import javax.inject.Provider; import lombok.extern.slf4j.Slf4j; @@ -79,6 +81,9 @@ public class WikiPlugin extends Plugin private static final String MENUOP_GUIDE = "Guide"; private static final String MENUOP_QUICKGUIDE = "Quick Guide"; + private static final String MENUOP_WIKI_SKILL = "Wiki"; + + private static final Pattern SKILL_REGEX = Pattern.compile("([A-Za-z]+) guide"); @Inject private SpriteManager spriteManager; @@ -246,6 +251,13 @@ public class WikiPlugin extends Plugin String quest = Text.removeTags(ev.getMenuTarget()); LinkBrowser.browse(WIKI_BASE + "/w/" + URLEncoder.encode(quest.replace(' ', '_')) + quickguide + "?" + UTM_PARAMS); break; + case MENUOP_WIKI_SKILL: + Matcher skillRegex = WikiPlugin.SKILL_REGEX.matcher(Text.removeTags(ev.getMenuTarget())); + + if (skillRegex.find()) + { + LinkBrowser.browse(WIKI_BASE + "/w/" + URLEncoder.encode(skillRegex.group(1)) + "?" + UTM_PARAMS); + } } } } @@ -261,29 +273,42 @@ public class WikiPlugin extends Plugin { int widgetIndex = event.getActionParam0(); int widgetID = event.getActionParam1(); + MenuEntry[] menuEntries = client.getMenuEntries(); - if (!Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) || !"Read Journal:".equals(event.getOption())) + if (Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) && "Read Journal:".equals(event.getOption())) { - return; + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 2); + + MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); + menuEntry.setTarget(event.getTarget()); + menuEntry.setOption(MENUOP_GUIDE); + menuEntry.setParam0(widgetIndex); + menuEntry.setParam1(widgetID); + menuEntry.setType(MenuAction.RUNELITE.getId()); + + menuEntry = menuEntries[menuEntries.length - 2] = new MenuEntry(); + menuEntry.setTarget(event.getTarget()); + menuEntry.setOption(MENUOP_QUICKGUIDE); + menuEntry.setParam0(widgetIndex); + menuEntry.setParam1(widgetID); + menuEntry.setType(MenuAction.RUNELITE.getId()); + + client.setMenuEntries(menuEntries); } - MenuEntry[] menuEntries = client.getMenuEntries(); - menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 2); + if ((WidgetInfo.TO_GROUP(widgetID) == WidgetID.SKILLS_GROUP_ID) && event.getOption().startsWith("View")) + { + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); - MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - menuEntry.setTarget(event.getTarget()); - menuEntry.setOption(MENUOP_GUIDE); - menuEntry.setParam0(widgetIndex); - menuEntry.setParam1(widgetID); - menuEntry.setType(MenuAction.RUNELITE.getId()); + MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); + menuEntry.setTarget(event.getOption().replace("View ", "")); + menuEntry.setOption(MENUOP_WIKI_SKILL); + menuEntry.setParam0(widgetIndex); + menuEntry.setParam1(widgetID); + menuEntry.setIdentifier(event.getIdentifier()); + menuEntry.setType(MenuAction.RUNELITE.getId()); - menuEntry = menuEntries[menuEntries.length - 2] = new MenuEntry(); - menuEntry.setTarget(event.getTarget()); - menuEntry.setOption(MENUOP_QUICKGUIDE); - menuEntry.setParam0(widgetIndex); - menuEntry.setParam1(widgetID); - menuEntry.setType(MenuAction.RUNELITE.getId()); - - client.setMenuEntries(menuEntries); + client.setMenuEntries(menuEntries); + } } } From 06d4adc5e432513177011e30a1c6c353e49e12b9 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 19 Feb 2019 09:44:59 -0500 Subject: [PATCH 066/102] client: change Counter infobox to store count as an integer --- .../client/plugins/cannon/CannonCounter.java | 6 ++--- .../kingdomofmiscellania/KingdomCounter.java | 2 +- .../mta/graveyard/GraveyardCounter.java | 11 ++------ .../nightmarezone/AbsorptionCounter.java | 10 +++----- .../client/plugins/prayer/PrayerCounter.java | 17 +++++++++---- .../client/plugins/slayer/SlayerPlugin.java | 2 +- .../client/plugins/slayer/TaskCounter.java | 2 +- .../specialcounter/SpecialCounter.java | 14 +++-------- .../client/ui/overlay/infobox/Counter.java | 25 ++++++++----------- .../ui/overlay/infobox/InfoBoxOverlay.java | 14 +++++++++-- 10 files changed, 50 insertions(+), 53 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java index 2db9d6f3e0..631410d8c2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java @@ -26,15 +26,15 @@ package net.runelite.client.plugins.cannon; import java.awt.Color; import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.infobox.Counter; +import net.runelite.client.ui.overlay.infobox.InfoBox; -public class CannonCounter extends Counter +public class CannonCounter extends InfoBox { private final CannonPlugin plugin; public CannonCounter(BufferedImage img, CannonPlugin plugin) { - super(img, plugin, String.valueOf(plugin.getCballsLeft())); + super(img, plugin); this.plugin = plugin; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java index 7dc6aabf35..24f8029184 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java @@ -34,7 +34,7 @@ public class KingdomCounter extends Counter public KingdomCounter(BufferedImage image, KingdomPlugin plugin) { - super(image, plugin, String.valueOf(plugin.getFavor())); + super(image, plugin, plugin.getFavor()); this.plugin = plugin; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java index 83e74cc6d6..907712ab28 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java @@ -31,22 +31,15 @@ import net.runelite.client.ui.overlay.infobox.Counter; public class GraveyardCounter extends Counter { - private int count; - public GraveyardCounter(BufferedImage image, Plugin plugin) { - super(image, plugin, "0"); - } - - public void setCount(int count) - { - this.count = count; - this.setText(String.valueOf(count)); + super(image, plugin, 0); } @Override public Color getTextColor() { + int count = getCount(); if (count >= GraveyardRoom.MIN_SCORE) { return Color.GREEN; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java index 05d1498312..4c6b496a29 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java @@ -33,8 +33,6 @@ import net.runelite.client.ui.overlay.infobox.Counter; public class AbsorptionCounter extends Counter { - private int absorption; - @Getter @Setter private int threshold; @@ -49,20 +47,19 @@ public class AbsorptionCounter extends Counter public AbsorptionCounter(BufferedImage image, Plugin plugin, int absorption, int threshold) { - super(image, plugin, ""); + super(image, plugin, absorption); this.threshold = threshold; - setAbsorption(absorption); } public void setAbsorption(int absorption) { - this.absorption = absorption; - setText(String.valueOf(absorption)); + setCount(absorption); } @Override public Color getTextColor() { + int absorption = getCount(); if (absorption >= threshold) { return aboveThresholdColor; @@ -76,6 +73,7 @@ public class AbsorptionCounter extends Counter @Override public String getTooltip() { + int absorption = getCount(); return "Absorption: " + absorption; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerCounter.java index 546c9f98a8..c510dab82e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerCounter.java @@ -24,25 +24,32 @@ */ package net.runelite.client.plugins.prayer; +import java.awt.Color; import lombok.Getter; import net.runelite.client.plugins.Plugin; -import net.runelite.client.ui.overlay.infobox.Counter; +import net.runelite.client.ui.overlay.infobox.InfoBox; -class PrayerCounter extends Counter +class PrayerCounter extends InfoBox { @Getter private final PrayerType prayerType; PrayerCounter(Plugin plugin, PrayerType prayerType) { - super(null, plugin, ""); + super(null, plugin); this.prayerType = prayerType; } @Override - public String toString() + public String getText() { - return "Counter{" + "prayer=" + prayerType.getName() + '}'; + return null; + } + + @Override + public Color getTextColor() + { + return null; } @Override diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java index ff8d6e39bb..875f1f009d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java @@ -580,7 +580,7 @@ public class SlayerPlugin extends Plugin // add and update counter, set timer addCounter(); - counter.setText(String.valueOf(amount)); + counter.setCount(amount); infoTimer = Instant.now(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java index f4ac0045b9..f73a5aae5b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java @@ -33,6 +33,6 @@ public class TaskCounter extends Counter { public TaskCounter(BufferedImage img, Plugin plugin, int amount) { - super(img, plugin, String.valueOf(amount)); + super(img, plugin, amount); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounter.java index 083ef5bba6..3c7b0f2135 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounter.java @@ -29,30 +29,24 @@ import net.runelite.client.ui.overlay.infobox.Counter; class SpecialCounter extends Counter { - private int hitValue; private SpecialWeapon weapon; SpecialCounter(BufferedImage image, SpecialCounterPlugin plugin, int hitValue, SpecialWeapon weapon) { - super(image, plugin, null); + super(image, plugin, hitValue); this.weapon = weapon; - this.hitValue = hitValue; } void addHits(double hit) { - this.hitValue += hit; - } - - @Override - public String getText() - { - return Integer.toString(hitValue); + int count = getCount(); + setCount(count + (int) hit); } @Override public String getTooltip() { + int hitValue = getCount(); if (!weapon.isDamage()) { if (hitValue == 1) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Counter.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Counter.java index 599a178838..49614e9b61 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Counter.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Counter.java @@ -26,33 +26,28 @@ package net.runelite.client.ui.overlay.infobox; import java.awt.Color; import java.awt.image.BufferedImage; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; import net.runelite.client.plugins.Plugin; +@ToString public class Counter extends InfoBox { - private String text; + @Getter + @Setter + private int count; - public Counter(BufferedImage image, Plugin plugin, String text) + public Counter(BufferedImage image, Plugin plugin, int count) { super(image, plugin); - this.text = text; - } - - @Override - public String toString() - { - return "Counter{" + "text=" + text + '}'; + this.count = count; } @Override public String getText() { - return text; - } - - public void setText(String text) - { - this.text = text; + return Integer.toString(count); } @Override diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java index fecd9f1090..e6a8d6f749 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java @@ -26,6 +26,7 @@ package net.runelite.client.ui.overlay.infobox; import com.google.common.base.Strings; +import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; @@ -94,10 +95,19 @@ public class InfoBoxOverlay extends Overlay continue; } + final String text = box.getText(); + final Color color = box.getTextColor(); + final InfoBoxComponent infoBoxComponent = new InfoBoxComponent(); - infoBoxComponent.setColor(box.getTextColor()); + if (!Strings.isNullOrEmpty(text)) + { + infoBoxComponent.setText(text); + } + if (color != null) + { + infoBoxComponent.setColor(color); + } infoBoxComponent.setImage(box.getScaledImage()); - infoBoxComponent.setText(box.getText()); infoBoxComponent.setTooltip(box.getTooltip()); panelComponent.getChildren().add(infoBoxComponent); } From ac8f728d47a4653fc363db95572970b28ce03529 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 17 Feb 2019 20:31:29 +0100 Subject: [PATCH 067/102] Remove dodgy charges variable from item charges plugin Just use config class directly, this variable makes no sense. Signed-off-by: Tomas Slusny --- .../plugins/itemcharges/ItemChargeOverlay.java | 2 +- .../plugins/itemcharges/ItemChargePlugin.java | 17 +++++------------ .../itemcharges/ItemChargePluginTest.java | 16 +++++++++++----- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java index 7730d46ffd..c8a07716bf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java @@ -83,7 +83,7 @@ class ItemChargeOverlay extends Overlay continue; } - charges = itemChargePlugin.getDodgyCharges(); + charges = config.dodgyNecklace(); } else { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java index c545e9a5bb..f232b64bfd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java @@ -28,8 +28,6 @@ import com.google.inject.Provides; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; import net.runelite.api.ChatMessageType; import net.runelite.api.events.ChatMessage; import net.runelite.client.Notifier; @@ -68,9 +66,6 @@ public class ItemChargePlugin extends Plugin @Inject private ItemChargeConfig config; - @Getter(AccessLevel.PACKAGE) - private int dodgyCharges; - @Provides ItemChargeConfig getConfig(ConfigManager configManager) { @@ -81,7 +76,6 @@ public class ItemChargePlugin extends Plugin protected void startUp() { overlayManager.add(overlay); - dodgyCharges = config.dodgyNecklace(); } @Override @@ -110,22 +104,21 @@ public class ItemChargePlugin extends Plugin notifier.notify("Your dodgy necklace has crumbled to dust."); } - setDodgyCharges(MAX_DODGY_CHARGES); + updateDodgyNecklaceCharges(MAX_DODGY_CHARGES); } else if (dodgyCheckMatcher.find()) { - setDodgyCharges(Integer.parseInt(dodgyCheckMatcher.group(1))); + updateDodgyNecklaceCharges(Integer.parseInt(dodgyCheckMatcher.group(1))); } else if (dodgyProtectMatcher.find()) { - setDodgyCharges(Integer.parseInt(dodgyProtectMatcher.group(1))); + updateDodgyNecklaceCharges(Integer.parseInt(dodgyProtectMatcher.group(1))); } } } - private void setDodgyCharges(int dodgyCharges) + private void updateDodgyNecklaceCharges(final int value) { - this.dodgyCharges = dodgyCharges; - config.dodgyNecklace(dodgyCharges); + config.dodgyNecklace(value); } } \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java index b8fc81a16a..ea6438031a 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java @@ -33,11 +33,13 @@ import net.runelite.api.Client; import net.runelite.api.events.ChatMessage; import net.runelite.client.Notifier; import net.runelite.client.ui.overlay.OverlayManager; -import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import static org.mockito.Matchers.eq; import org.mockito.Mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) @@ -78,18 +80,22 @@ public class ItemChargePluginTest { ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SERVER, "", CHECK, "", 0); itemChargePlugin.onChatMessage(chatMessage); - assertEquals(10, itemChargePlugin.getDodgyCharges()); + verify(config).dodgyNecklace(eq(10)); + reset(config); chatMessage = new ChatMessage(null, ChatMessageType.SERVER, "", PROTECT, "", 0); itemChargePlugin.onChatMessage(chatMessage); - assertEquals(9, itemChargePlugin.getDodgyCharges()); + verify(config).dodgyNecklace(eq(9)); + reset(config); chatMessage = new ChatMessage(null, ChatMessageType.SERVER, "", PROTECT_1, "", 0); itemChargePlugin.onChatMessage(chatMessage); - assertEquals(1, itemChargePlugin.getDodgyCharges()); + verify(config).dodgyNecklace(eq(1)); + reset(config); chatMessage = new ChatMessage(null, ChatMessageType.SERVER, "", BREAK, "", 0); itemChargePlugin.onChatMessage(chatMessage); - assertEquals(10, itemChargePlugin.getDodgyCharges()); + verify(config).dodgyNecklace(eq(10)); + reset(config); } } \ No newline at end of file From 1a3815865189853b9b2dcc1dcf2ed522e7da14ec Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Tue, 18 Dec 2018 11:24:10 +0000 Subject: [PATCH 068/102] Add infoboxes to item charges plugin Closes #1318 Co-authored-by: Tomas Slusny Signed-off-by: Tomas Slusny --- .../plugins/itemcharges/ItemChargeConfig.java | 11 ++ .../itemcharges/ItemChargeInfobox.java | 60 ++++++ .../itemcharges/ItemChargeOverlay.java | 17 +- .../plugins/itemcharges/ItemChargePlugin.java | 173 ++++++++++++++++++ .../plugins/itemcharges/ItemChargeType.java | 3 +- .../plugins/itemcharges/ItemWithSlot.java | 47 +++++ .../itemcharges/ItemChargePluginTest.java | 10 + 7 files changed, 304 insertions(+), 17 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeInfobox.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java index 40488c5137..28c503b20a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java @@ -203,4 +203,15 @@ public interface ItemChargeConfig extends Config { return false; } + + @ConfigItem( + keyName = "showInfoboxes", + name = "Show Infoboxes", + description = "Configures whether to show an infobox equipped charge items", + position = 15 + ) + default boolean showInfoboxes() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeInfobox.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeInfobox.java new file mode 100644 index 0000000000..7ee70d44b5 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeInfobox.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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.plugins.itemcharges; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import lombok.Getter; +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.client.ui.overlay.infobox.Counter; + +@Getter +class ItemChargeInfobox extends Counter +{ + private final ItemChargePlugin plugin; + private final ItemWithSlot item; + private final EquipmentInventorySlot slot; + + ItemChargeInfobox( + ItemChargePlugin plugin, + BufferedImage image, + String name, + int charges, + ItemWithSlot item, + EquipmentInventorySlot slot) + { + super(image, plugin, charges); + setTooltip(name); + this.plugin = plugin; + this.item = item; + this.slot = slot; + } + + @Override + public Color getTextColor() + { + return getPlugin().getColor(getCount()); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java index c8a07716bf..27bb35b21d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.itemcharges; -import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; @@ -112,7 +111,7 @@ class ItemChargeOverlay extends Overlay final TextComponent textComponent = new TextComponent(); textComponent.setPosition(new Point(bounds.x, bounds.y + 16)); textComponent.setText(charges < 0 ? "?" : String.valueOf(charges)); - textComponent.setColor(getColor(charges)); + textComponent.setColor(itemChargePlugin.getColor(charges)); textComponent.render(graphics); } return null; @@ -137,20 +136,6 @@ class ItemChargeOverlay extends Overlay return jewellery; } - private Color getColor(int charges) - { - Color color = Color.WHITE; - if (charges <= config.veryLowWarning()) - { - color = config.veryLowWarningColor(); - } - else if (charges <= config.lowWarning()) - { - color = config.lowWarningolor(); - } - return color; - } - private boolean displayOverlay() { return config.showTeleportCharges() || config.showDodgyCount() || config.showFungicideCharges() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java index f232b64bfd..e295efd9e5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, Seth + * Copyright (c) 2018, Hydrox6 * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,17 +26,29 @@ package net.runelite.client.plugins.itemcharges; import com.google.inject.Provides; +import java.awt.Color; +import java.awt.image.BufferedImage; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.ItemContainerChanged; import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; @PluginDescriptor( name = "Item Charges", @@ -54,12 +67,21 @@ public class ItemChargePlugin extends Plugin private static final int MAX_DODGY_CHARGES = 10; + @Inject + private Client client; + @Inject private OverlayManager overlayManager; @Inject private ItemChargeOverlay overlay; + @Inject + private ItemManager itemManager; + + @Inject + private InfoBoxManager infoBoxManager; + @Inject private Notifier notifier; @@ -82,6 +104,37 @@ public class ItemChargePlugin extends Plugin protected void shutDown() throws Exception { overlayManager.remove(overlay); + infoBoxManager.removeIf(ItemChargeInfobox.class::isInstance); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!event.getGroup().equals("itemCharge")) + { + return; + } + + if (!config.showInfoboxes()) + { + infoBoxManager.removeIf(ItemChargeInfobox.class::isInstance); + return; + } + + if (!config.showTeleportCharges()) + { + removeInfobox(ItemWithSlot.TELEPORT); + } + + if (!config.showAbyssalBraceletCharges()) + { + removeInfobox(ItemWithSlot.ABYSSAL_BRACELET); + } + + if (!config.showDodgyCount()) + { + removeInfobox(ItemWithSlot.DODGY_NECKLACE); + } } @Subscribe @@ -117,8 +170,128 @@ public class ItemChargePlugin extends Plugin } } + @Subscribe + public void onItemContainerChanged(ItemContainerChanged event) + { + if (event.getItemContainer() != client.getItemContainer(InventoryID.EQUIPMENT) || !config.showInfoboxes()) + { + return; + } + + final Item[] items = event.getItemContainer().getItems(); + + if (config.showTeleportCharges()) + { + updateJewelleryInfobox(ItemWithSlot.TELEPORT, items); + } + + if (config.showDodgyCount()) + { + updateJewelleryInfobox(ItemWithSlot.DODGY_NECKLACE, items); + } + + if (config.showAbyssalBraceletCharges()) + { + updateJewelleryInfobox(ItemWithSlot.ABYSSAL_BRACELET, items); + } + } + private void updateDodgyNecklaceCharges(final int value) { config.dodgyNecklace(value); + + if (config.showInfoboxes() && config.showDodgyCount()) + { + final ItemContainer itemContainer = client.getItemContainer(InventoryID.EQUIPMENT); + + if (itemContainer == null) + { + return; + } + + updateJewelleryInfobox(ItemWithSlot.DODGY_NECKLACE, itemContainer.getItems()); + } + } + + private void updateJewelleryInfobox(ItemWithSlot item, Item[] items) + { + for (final EquipmentInventorySlot equipmentInventorySlot : item.getSlots()) + { + updateJewelleryInfobox(item, items, equipmentInventorySlot); + } + } + + private void updateJewelleryInfobox(ItemWithSlot type, Item[] items, EquipmentInventorySlot slot) + { + removeInfobox(type, slot); + + if (slot.getSlotIdx() >= items.length) + { + return; + } + + final int id = items[slot.getSlotIdx()].getId(); + if (id < 0) + { + return; + } + + final ItemWithCharge itemWithCharge = ItemWithCharge.findItem(id); + int charges = -1; + + if (itemWithCharge == null) + { + if (id == ItemID.DODGY_NECKLACE && type == ItemWithSlot.DODGY_NECKLACE) + { + charges = config.dodgyNecklace(); + } + } + else if (itemWithCharge.getType() == type.getType()) + { + charges = itemWithCharge.getCharges(); + } + + if (charges <= 0) + { + return; + } + + final String name = itemManager.getItemComposition(id).getName(); + final BufferedImage image = itemManager.getImage(id); + final ItemChargeInfobox infobox = new ItemChargeInfobox(this, image, name, charges, type, slot); + infoBoxManager.addInfoBox(infobox); + } + + private void removeInfobox(final ItemWithSlot item) + { + infoBoxManager.removeIf(t -> t instanceof ItemChargeInfobox && ((ItemChargeInfobox) t).getItem() == item); + } + + private void removeInfobox(final ItemWithSlot item, final EquipmentInventorySlot slot) + { + infoBoxManager.removeIf(t -> + { + if (!(t instanceof ItemChargeInfobox)) + { + return false; + } + + final ItemChargeInfobox i = (ItemChargeInfobox)t; + return i.getItem() == item && i.getSlot() == slot; + }); + } + + Color getColor(int charges) + { + Color color = Color.WHITE; + if (charges <= config.veryLowWarning()) + { + color = config.veryLowWarningColor(); + } + else if (charges <= config.lowWarning()) + { + color = config.lowWarningolor(); + } + return color; } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java index 2f25c12164..cbe5d20ff3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java @@ -32,5 +32,6 @@ enum ItemChargeType IMPBOX, TELEPORT, WATERCAN, - WATERSKIN + WATERSKIN, + DODGY_NECKLACE } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java new file mode 100644 index 0000000000..3fbd2bac66 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019, Tomas Slusny + * 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.plugins.itemcharges; + +import com.google.common.collect.Sets; +import java.util.Set; +import lombok.Getter; +import net.runelite.api.EquipmentInventorySlot; + +@Getter +enum ItemWithSlot +{ + ABYSSAL_BRACELET(ItemChargeType.ABYSSAL_BRACELET, EquipmentInventorySlot.GLOVES), + DODGY_NECKLACE(ItemChargeType.DODGY_NECKLACE, EquipmentInventorySlot.AMULET), + TELEPORT(ItemChargeType.TELEPORT, EquipmentInventorySlot.WEAPON, EquipmentInventorySlot.AMULET, EquipmentInventorySlot.GLOVES, EquipmentInventorySlot.RING); + + private final ItemChargeType type; + private final Set slots; + + ItemWithSlot(final ItemChargeType type, final EquipmentInventorySlot... slots) + { + this.type = type; + this.slots = Sets.newHashSet(slots); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java index ea6438031a..165c7d50a7 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/itemcharges/ItemChargePluginTest.java @@ -28,10 +28,12 @@ import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.concurrent.ScheduledExecutorService; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.events.ChatMessage; import net.runelite.client.Notifier; +import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.ui.overlay.OverlayManager; import org.junit.Before; import org.junit.Test; @@ -54,6 +56,14 @@ public class ItemChargePluginTest @Bind private Client client; + @Mock + @Bind + private ScheduledExecutorService scheduledExecutorService; + + @Mock + @Bind + private RuneLiteConfig runeLiteConfig; + @Mock @Bind private OverlayManager overlayManager; From 4c1a5307ecd9719b2584995227faab7f1db18146 Mon Sep 17 00:00:00 2001 From: Harry Semple Date: Tue, 19 Feb 2019 20:53:57 -0500 Subject: [PATCH 069/102] agility plugin: color shortcuts you don't have the level to use differently This creates a new agility shortcut enum in the client, extracted from the world map plugin, to keep track of shortcut location and level requirement. The old shortcuts in the agility plugin were merged into this too. Co-authored-by: Adam --- .../runelite/client/game/AgilityShortcut.java | 242 ++++++++++++++++++ .../plugins/agility/AgilityOverlay.java | 11 +- .../client/plugins/agility/AgilityPlugin.java | 54 +++- .../client/plugins/agility/Obstacle.java | 41 +++ .../client/plugins/agility/Obstacles.java | 170 +++--------- .../worldmap/AgilityShortcutLocation.java | 142 ---------- .../worldmap/AgilityShortcutPoint.java | 5 +- .../plugins/worldmap/WorldMapPlugin.java | 6 +- 8 files changed, 379 insertions(+), 292 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacle.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java diff --git a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java new file mode 100644 index 0000000000..c376bd34f1 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2018, SomeoneWithAnInternetConnection + * Copyright (c) 2019, MrGroggle + * 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.game; + +import lombok.Getter; +import static net.runelite.api.NullObjectID.*; +import static net.runelite.api.ObjectID.*; +import net.runelite.api.coords.WorldPoint; + +@Getter +public enum AgilityShortcut +{ + GENERIC_SHORTCUT(1, "Shortcut", null, + // Trollheim + ROCKS_3790, ROCKS_3791, + // Fremennik Slayer Cave + STEPS_29993, + // Fossil Island + LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, RUBBER_CAP_MUSHROOM, + // Brimhaven dungeon + CREVICE_30198, + // Lumbridge + STILE_12982, + // Gu'Tanoth Bridge + GAP, GAP_2831, + // Lumbridge Swamp Caves + STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673, + // Morytania Pirate Ship + ROCK_16115, + // Lumber Yard + BROKEN_FENCE_2618, + // McGrubor's Wood + LOOSE_RAILING, + // Underwater Area Fossil Island + TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, + // Tree Gnome Village + LOOSE_RAILING_2186, + // Burgh de Rott + LOW_FENCE, + // Taverley + STILE, + // Asgarnian Ice Dungeon + STEPS, + // Fossil Island Wyvern Cave + STAIRS_31485), + BRIMHAVEN_DUNGEON_MEDIUM_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2698, 9491, 0), PIPE_21727), + BRIMHAVEN_DUNGEON_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2655, 9573, 0), PIPE_21728), + BRIMHAVEN_DUNGEON_STEPPING_STONES_RETURN(1, "Pipe Squeeze", null, STEPPING_STONE_21739), + BRIMHAVEN_DUNGEON_LOG_BALANCE_RETURN(1, "Log Balance", null, LOG_BALANCE_20884), + AGILITY_PYRAMID_ROCKS_WEST(1, "Rocks", null, CLIMBING_ROCKS_11948), + CAIRN_ISLE_CLIMBING_ROCKS(1, "Rocks", null, CLIMBING_ROCKS), + KARAMJA_GLIDER_LOG(1, "Log Balance", new WorldPoint(2906, 3050, 0), A_WOODEN_LOG ), + FALADOR_CRUMBLING_WALL(5, "Crumbling Wall", new WorldPoint(2936, 3357, 0), CRUMBLING_WALL_24222 ), + RIVER_LUM_GRAPPLE_WEST(8, "Grapple Broken Raft", new WorldPoint(3245, 3179, 0), BROKEN_RAFT), + RIVER_LUM_GRAPPLE_EAST(8, "Grapple Broken Raft", new WorldPoint(3258, 3179, 0), BROKEN_RAFT), + CORSAIR_COVE_ROCKS(10, "Rocks", new WorldPoint(2545, 2871, 0), ROCKS_31757), + KARAMJA_MOSS_GIANT_SWING(10, "Rope", null, ROPESWING_23568, ROPESWING_23569), + FALADOR_GRAPPLE_WALL(11, "Grapple Wall", new WorldPoint(3031, 3391, 0), WALL_17049, WALL_17050), + BRIMHAVEN_DUNGEON_STEPPING_STONES(12, "Stepping Stones", null, STEPPING_STONE_21738), + VARROCK_SOUTH_FENCE(13, "Fence", new WorldPoint(3239, 3334, 0), FENCE_16518), + GOBLIN_VILLAGE_WALL(14, "Wall", new WorldPoint(2925, 3523, 0), TIGHTGAP), + CORSAIR_COVE_DUNGEON_PILLAR(15, "Pillar Jump", new WorldPoint(1980, 8996, 0), PILLAR_31809), + EDGEVILLE_DUNGEON_MONKEYBARS(15, "Monkey Bars", null, MONKEYBARS_23566), + TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15 + YANILLE_UNDERWALL_TUNNEL(16, "Underwall Tunnel", new WorldPoint(2574, 3109, 0), HOLE_16520, WALL_17047), + YANILLE_WATCHTOWER_TRELLIS(18, "Trellis", null, TRELLIS_20056), + COAL_TRUCKS_LOG_BALANCE(20, "Log Balance", new WorldPoint(2598, 3475, 0), LOG_BALANCE_23274), + GRAND_EXCHANGE_UNDERWALL_TUNNEL(21, "Underwall Tunnel", new WorldPoint(3139, 3515, 0), UNDERWALL_TUNNEL_16529, UNDERWALL_TUNNEL_16530), + BRIMHAVEN_DUNGEON_PIPE(22, "Pipe Squeeze", new WorldPoint(2654, 9569, 0), PIPE_21728), + OBSERVATORY_SCALE_CLIFF(23, "Grapple Rocks", new WorldPoint(2447, 3155, 0), NULL_31849), + EAGLES_PEAK_ROCK_CLIMB(25, "Rock Climb", new WorldPoint(2320, 3499, 0), ROCKS_19849), + FALADOR_UNDERWALL_TUNNEL(26, "Underwall Tunnel", new WorldPoint(2947, 3313, 0), UNDERWALL_TUNNEL, UNDERWALL_TUNNEL_16528), + MOUNT_KARUULM_LOWER(29, "Rocks", new WorldPoint(1324, 3782, 0), ROCKS_34397), + CORSAIR_COVE_RESOURCE_ROCKS(30, "Rocks", new WorldPoint(2486, 2898, 0), ROCKS_31758, ROCKS_31759), + SOUTHEAST_KARAJMA_STEPPING_STONES(30, "Stepping Stones", new WorldPoint(2924, 2946, 0), STEPPING_STONES, STEPPING_STONES_23646, STEPPING_STONES_23647), + BRIMHAVEN_DUNGEON_LOG_BALANCE(30, "Log Balance", null, LOG_BALANCE_20882), + AGILITY_PYRAMID_ROCKS_EAST(30, "Rocks", null, CLIMBING_ROCKS_11949), + DRAYNOR_MANOR_STEPPING_STONES(31, "Stepping Stones", new WorldPoint(3150, 3362, 0), STEPPING_STONE_16533), + CATHERBY_CLIFFSIDE_GRAPPLE(32, "Grapple Rock", new WorldPoint(2868, 3429, 0), ROCKS_17042), + CAIRN_ISLE_ROCKS(32, "Rocks", null, ROCKS_2231), + ARDOUGNE_LOG_BALANCE(33, "Log Balance", new WorldPoint(2602, 3336, 0), LOG_BALANCE_16546, LOG_BALANCE_16547, LOG_BALANCE_16548), + BRIMHAVEN_DUNGEON_MEDIUM_PIPE(34, "Pipe Squeeze", null, new WorldPoint(2698, 9501, 0), PIPE_21727), + CATHERBY_OBELISK_GRAPPLE(36, "Grapple Rock", new WorldPoint(2841, 3434, 0), CROSSBOW_TREE_17062), + GNOME_STRONGHOLD_ROCKS(37, "Rocks", new WorldPoint(2485, 3515, 0), ROCKS_16534, ROCKS_16535), + AL_KHARID_MINING_PITCLIFF_SCRAMBLE(38, "Rocks", new WorldPoint(3305, 3315, 0), ROCKS_16549, ROCKS_16550), + YANILLE_WALL_GRAPPLE(39, "Grapple Wall", new WorldPoint(2552, 3072, 0), CASTLE_WALL), + NEITIZNOT_BRIDGE_REPAIR(40, "Bridge Repair - Quest", new WorldPoint(2315, 3828, 0), ROPE_BRIDGE_21306, ROPE_BRIDGE_21307), + KOUREND_LAKE_JUMP_EAST(40, "Stepping Stones", new WorldPoint(1612, 3570, 0), STEPPING_STONE_29729, STEPPING_STONE_29730), + KOUREND_LAKE_JUMP_WEST(40, "Stepping Stones", new WorldPoint(1604, 3572, 0), STEPPING_STONE_29729, STEPPING_STONE_29730), + YANILLE_DUNGEON_BALANCE(40, "Balancing Ledge", null, BALANCING_LEDGE_23548), + TROLLHEIM_EASY_CLIFF_SCRAMBLE(41, "Rocks", new WorldPoint(2869, 3670, 0), ROCKS_16521), + DWARVEN_MINE_NARROW_CREVICE(42, "Narrow Crevice", new WorldPoint(3034, 9806, 0), CREVICE_16543), + DRAYNOR_UNDERWALL_TUNNEL(42, "Underwall Tunnel", new WorldPoint(3068, 3261, 0), UNDERWALL_TUNNEL_19032, UNDERWALL_TUNNEL_19036), + TROLLHEIM_MEDIUM_CLIFF_SCRAMBLE_NORTH(43, "Rocks", new WorldPoint(2886, 3684, 0), ROCKS_3803, ROCKS_3804, ROCKS_16522), + TROLLHEIM_MEDIUM_CLIFF_SCRAMBLE_SOUTH(43, "Rocks", new WorldPoint(2876, 3666, 0), ROCKS_3803, ROCKS_3804, ROCKS_16522), + TROLLHEIM_ADVANCED_CLIFF_SCRAMBLE(44, "Rocks", new WorldPoint(2907, 3686, 0), ROCKS_16523, ROCKS_3748), + KOUREND_RIVER_STEPPING_STONES(45, "Stepping Stones", new WorldPoint(1721, 3509, 0), STEPPING_STONE_29728), + TIRANNWN_LOG_BALANCE(45, "Log Balance", null, LOG_BALANCE_3933, LOG_BALANCE_3931, LOG_BALANCE_3930, LOG_BALANCE_3929, LOG_BALANCE_3932), + COSMIC_ALTAR_MEDIUM_WALKWAY(46, "Narrow Walkway", new WorldPoint(2399, 4403, 0), JUTTING_WALL_17002), + DEEP_WILDERNESS_DUNGEON_CREVICE_NORTH(46, "Narrow Crevice", new WorldPoint(3047, 10335, 0), CREVICE_19043), + DEEP_WILDERNESS_DUNGEON_CREVICE_SOUTH(46, "Narrow Crevice", new WorldPoint(3045, 10327, 0), CREVICE_19043), + TROLLHEIM_HARD_CLIFF_SCRAMBLE(47, "Rocks", new WorldPoint(2902, 3680, 0), ROCKS_16524), + FREMENNIK_LOG_BALANCE(48, "Log Balance", new WorldPoint(2721, 3591, 0), LOG_BALANCE_16540, LOG_BALANCE_16541, LOG_BALANCE_16542), + YANILLE_DUNGEON_PIPE_SQUEEZE(49, "Pipe Squeeze", null, OBSTACLE_PIPE_23140), + ARCEUUS_ESSENCE_MINE_BOULDER(49, "Boulder", new WorldPoint(1774, 3888, 0), BOULDER_27990), + MORYTANIA_STEPPING_STONE(50, "Stepping Stone", new WorldPoint(3418, 3326, 0), STEPPING_STONE_13504), + VARROCK_SEWERS_PIPE_SQUEEZE(51, "Pipe Squeeze", new WorldPoint(3152, 9905, 0), OBSTACLE_PIPE_16511), + ARCEUUS_ESSENCE_MINE_EAST_SCRAMBLE(52, "Rock Climb", new WorldPoint(1770, 3851, 0), ROCKS_27987, ROCKS_27988), + KARAMJA_VOLCANO_GRAPPLE_NORTH(53, "Grapple Rock", new WorldPoint(2873, 3143, 0), STRONG_TREE_17074), + KARAMJA_VOLCANO_GRAPPLE_SOUTH(53, "Grapple Rock", new WorldPoint(2874, 3128, 0), STRONG_TREE_17074), + MOTHERLODE_MINE_WALL_EAST(54, "Wall", new WorldPoint(3124, 9703, 0), DARK_TUNNEL_10047), + MOTHERLODE_MINE_WALL_WEST(54, "Wall", new WorldPoint(3118, 9702, 0), DARK_TUNNEL_10047), + MISCELLANIA_DOCK_STEPPING_STONE(55, "Stepping Stone", new WorldPoint(2572, 3862, 0), STEPPING_STONE_11768), + ISAFDAR_FOREST_OBSTACLES(56, "Trap", null, DENSE_FOREST_3938, DENSE_FOREST_3939, DENSE_FOREST_3998, DENSE_FOREST_3999, DENSE_FOREST, LEAVES, LEAVES_3924, LEAVES_3925, STICKS, TRIPWIRE), + RELEKKA_EAST_FENCE(57, "Fence", new WorldPoint(2688, 3697, 0), BROKEN_FENCE), + YANILLE_DUNGEON_MONKEY_BARS(57, "Monkey Bars", null, MONKEYBARS_23567), + PHASMATYS_ECTOPOOL_SHORTCUT(58, "Weathered Wall", null , WEATHERED_WALL, WEATHERED_WALL_16526), + ELVEN_OVERPASS_CLIFF_SCRAMBLE(59, "Rocks", new WorldPoint(2345, 3300, 0), ROCKS_16514, ROCKS_16515), + WILDERNESS_GWD_CLIMB_EAST(60, "Rocks", new WorldPoint(2943, 3770, 0), ROCKY_HANDHOLDS_26400, ROCKY_HANDHOLDS_26401, ROCKY_HANDHOLDS_26402, ROCKY_HANDHOLDS_26404, ROCKY_HANDHOLDS_26405, ROCKY_HANDHOLDS_26406), + WILDERNESS_GWD_CLIMB_WEST(60, "Rocks", new WorldPoint(2928, 3760, 0), ROCKY_HANDHOLDS_26400, ROCKY_HANDHOLDS_26401, ROCKY_HANDHOLDS_26402, ROCKY_HANDHOLDS_26404, ROCKY_HANDHOLDS_26405, ROCKY_HANDHOLDS_26406), + MOS_LEHARMLESS_STEPPING_STONE(60, "Stepping Stone", new WorldPoint(3710, 2970, 0), STEPPING_STONE_19042), + WINTERTODT_GAP(60, "Gap", new WorldPoint(1629, 4023, 0), GAP_29326), + UNGAEL_ICE(60, "Ice Chunks", null, NULL_25337, NULL_29868, NULL_29869, NULL_29870, ICE_CHUNKS_31822, NULL_31823, ICE_CHUNKS_31990), + SLAYER_TOWER_MEDIUM_CHAIN_FIRST(61, "Spiked Chain (Floor 1)", new WorldPoint(3421, 3550, 0), SPIKEY_CHAIN), + SLAYER_TOWER_MEDIUM_CHAIN_SECOND(61, "Spiked Chain (Floor 2)", new WorldPoint(3420, 3551, 0), SPIKEY_CHAIN_16538), + SLAYER_DUNGEON_CREVICE(62, "Narrow Crevice", new WorldPoint(2729, 10008, 0), CREVICE_16539), + MOUNT_KARUULM_UPPER(62, "Rocks", new WorldPoint(1322, 3791, 0), ROCKS_34396), + TAVERLEY_DUNGEON_RAILING(63, "Loose Railing", new WorldPoint(2935, 9811, 0), LOOSE_RAILING_28849), + TROLLHEIM_WILDERNESS_ROCKS_EAST(64, "Rocks", new WorldPoint(2945, 3678, 0), ROCKS_16545), + TROLLHEIM_WILDERNESS_ROCKS_WEST(64, "Rocks", new WorldPoint(2917, 3672, 0), ROCKS_16545), + FOSSIL_ISLAND_VOLCANO(64, "Rope", new WorldPoint(3780, 3822, 0), ROPE_ANCHOR, ROPE_ANCHOR_30917), + MORYTANIA_TEMPLE(65, "Loose Railing", new WorldPoint(3422, 3476, 0), ROCKS_16998, ROCKS_16999, ORNATE_RAILING, ORNATE_RAILING_17000), + REVENANT_CAVES_GREEN_DRAGONS(65, "Jump", new WorldPoint(3220, 10086, 0), PILLAR_31561), + COSMIC_ALTAR_ADVANCED_WALKWAY(66, "Narrow Walkway", new WorldPoint(2408, 4401, 0), JUTTING_WALL_17002), + LUMBRIDGE_DESERT_STEPPING_STONE(66, "Stepping Stone", new WorldPoint(3210, 3135, 0), STEPPING_STONE_16513), + HEROES_GUILD_TUNNEL_EAST(67, "Crevice", new WorldPoint(2898, 9901, 0), CREVICE_9739, CREVICE_9740), + HEROES_GUILD_TUNNEL_WEST(67, "Crevice", new WorldPoint(2913, 9895, 0), CREVICE_9739, CREVICE_9740), + YANILLE_DUNGEON_RUBBLE_CLIMB(67, "Pile of Rubble", null, PILE_OF_RUBBLE_23563, PILE_OF_RUBBLE_23564), + ELVEN_OVERPASS_MEDIUM_CLIFF(68, "Rocks", new WorldPoint(2337, 3288, 0), ROCKS_16514, ROCKS_16515), + WEISS_OBSTACLES(68, "Shortcut", null, LITTLE_BOULDER, ROCKSLIDE_33184, ROCKSLIDE_33185, NULL_33327, NULL_33328, LEDGE_33190, ROCKSLIDE_33191, FALLEN_TREE_33192), + ARCEUUS_ESSENSE_NORTH(69, "Rock Climb", new WorldPoint(1759, 3873, 0), ROCKS_27984, ROCKS_27985), + TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON(70, "Pipe Squeeze", new WorldPoint(2886, 9798, 0), OBSTACLE_PIPE_16509), + TAVERLEY_DUNGEON_ROCKS_NORTH(70, "Rocks", new WorldPoint(2887, 9823, 0), ROCKS, ROCKS_14106), + TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106), + FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole" , new WorldPoint(3713, 3827, 0), HOLE_31481, HOLE_31482), + FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole" , new WorldPoint(3715, 3817, 0), HOLE_31481, HOLE_31482), + AL_KHARID_WINDOW(70, "Window", new WorldPoint(3293, 3158, 0), BROKEN_WALL_33344, BIG_WINDOW), + GWD_SARADOMIN_ROPE_NORTH(70, "Rope Descent", new WorldPoint(2912, 5300, 0), NULL_26371), + GWD_SARADOMIN_ROPE_SOUTH(70, "Rope Descent", new WorldPoint(2951, 5267, 0), NULL_26375), + SLAYER_TOWER_ADVANCED_CHAIN_FIRST(71, "Spiked Chain (Floor 2)", new WorldPoint(3447, 3578, 0), SPIKEY_CHAIN ), + SLAYER_TOWER_ADVANCED_CHAIN_SECOND(71, "Spiked Chain (Floor 3)", new WorldPoint(3446, 3576, 0), SPIKEY_CHAIN_16538), + STRONGHOLD_SLAYER_CAVE_TUNNEL(72, "Tunnel", new WorldPoint(2431, 9806, 0), TUNNEL_30174, TUNNEL_30175), + TROLL_STRONGHOLD_WALL_CLIMB(73, "Rocks", new WorldPoint(2841, 3694, 0), ROCKS_16464), + ARCEUUS_ESSENSE_MINE_WEST(73, "Rock Climb", new WorldPoint(1742, 3853, 0), ROCKS_27984, ROCKS_27985 ), + LAVA_DRAGON_ISLE_JUMP(74, "Stepping Stone", new WorldPoint(3200, 3807, 0), STEPPING_STONE_14918), + REVENANT_CAVES_DEMONS_JUMP(75, "Jump", new WorldPoint(3199, 10135, 0), PILLAR_31561), + REVENANT_CAVES_ANKOU_EAST(75, "Jump", new WorldPoint(3201, 10195, 0), PILLAR_31561), + REVENANT_CAVES_ANKOU_NORTH(75, "Jump", new WorldPoint(3180, 10209, 0), PILLAR_31561), + ZUL_ANDRA_ISLAND_CROSSING(76, "Stepping Stone", new WorldPoint(2156, 3073, 0), STEPPING_STONE_10663), + SHILO_VILLAGE_STEPPING_STONES( 77, "Stepping Stones", new WorldPoint(2863, 2974, 0), STEPPING_STONE_16466), + KHARAZI_JUNGLE_VINE_CLIMB(79, "Vine", new WorldPoint(2897, 2939, 0), NULL_26884, NULL_26886), + TAVERLEY_DUNGEON_SPIKED_BLADES(80, "Strange Floor", new WorldPoint(2877, 9813, 0), STRANGE_FLOOR), + SLAYER_DUNGEON_CHASM_JUMP(81, "Spiked Blades", new WorldPoint(2770, 10003, 0), STRANGE_FLOOR_16544), + LAVA_MAZE_NORTH_JUMP(82, "Stepping Stone", new WorldPoint(3092, 3880, 0), STEPPING_STONE_14917), + BRIMHAVEN_DUNGEON_EAST_STEPPING_STONES_NORTH(83, "Stepping Stones", new WorldPoint(2685, 9547, 0), STEPPING_STONE_19040), + BRIMHAVEN_DUNGEON_EAST_STEPPING_STONES_SOUTH(83, "Stepping Stones", new WorldPoint(2693, 9529, 0), STEPPING_STONE_19040), + ELVEN_ADVANCED_CLIFF_SCRAMBLE(85, "Rocks", new WorldPoint(2337, 3253, 0), ROCKS_16514, ROCKS_16514), + KALPHITE_WALL(86, "Crevice", new WorldPoint(3214, 9508, 0), CREVICE_16465), + BRIMHAVEN_DUNGEON_VINE_EAST(87, "Vine", new WorldPoint(2672, 9582, 0), VINE_26880, VINE_26882), + BRIMHAVEN_DUNGEON_VINE_WEST(87, "Vine", new WorldPoint(2606, 9584, 0), VINE_26880, VINE_26882), + REVENANT_CAVES_CHAMBER_JUMP(89, "Jump", new WorldPoint(3240, 10144, 0), PILLAR_31561); + + /** + * The agility level required to pass the shortcut + */ + @Getter + private final int level; + /** + * Brief description of the shortcut (e.g. 'Rocks', 'Stepping Stones', 'Jump') + */ + @Getter + private final String description; + /** + * The location of the Shortcut icon on the world map (null if there is no icon) + */ + @Getter + private final WorldPoint worldMapLocation; + /** + * An optional location in case the location of the shortcut icon is either + * null or isn't close enough to the obstacle + */ + @Getter + private final WorldPoint worldLocation; + /** + * Array of obstacles, null objects, decorations etc. that this shortcut uses. + * Typically an ObjectID/NullObjectID + */ + @Getter + private final int[] obstacleIds; + + AgilityShortcut(int level, String description, WorldPoint mapLocation, WorldPoint worldLocation, int... obstacleIds) + { + this.level = level; + this.description = description; + this.worldMapLocation = mapLocation; + this.worldLocation = worldLocation; + this.obstacleIds = obstacleIds; + } + + AgilityShortcut(int level, String description, WorldPoint location, int... obstacleIds) + { + this(level, description, location, location, obstacleIds); + } + + public String getTooltip() + { + return description + " - Level " + level; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java index bc6e953f6d..e9c205f64f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java @@ -36,6 +36,7 @@ import net.runelite.api.Client; import net.runelite.api.Point; import net.runelite.api.Tile; import net.runelite.api.coords.LocalPoint; +import net.runelite.client.game.AgilityShortcut; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @@ -44,6 +45,7 @@ import net.runelite.client.ui.overlay.OverlayUtil; class AgilityOverlay extends Overlay { private static final int MAX_DISTANCE = 2350; + private static final Color SHORTCUT_HIGH_LEVEL_COLOR = Color.ORANGE; private final Client client; private final AgilityPlugin plugin; @@ -66,14 +68,15 @@ class AgilityOverlay extends Overlay LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation(); Point mousePosition = client.getMouseCanvasPosition(); final List marksOfGrace = plugin.getMarksOfGrace(); - plugin.getObstacles().forEach((object, tile) -> + plugin.getObstacles().forEach((object, obstacle) -> { - if (Obstacles.SHORTCUT_OBSTACLE_IDS.contains(object.getId()) && !config.highlightShortcuts() || + if (Obstacles.SHORTCUT_OBSTACLE_IDS.containsKey(object.getId()) && !config.highlightShortcuts() || Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId()) && !config.showTrapOverlay()) { return; } + Tile tile = obstacle.getTile(); if (tile.getPlane() == client.getPlane() && object.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) { @@ -87,11 +90,11 @@ class AgilityOverlay extends Overlay } return; } - Area objectClickbox = object.getClickbox(); if (objectClickbox != null) { - Color configColor = config.getOverlayColor(); + AgilityShortcut agilityShortcut = obstacle.getShortcut(); + Color configColor = agilityShortcut == null || agilityShortcut.getLevel() <= plugin.getAgilityLevel() ? config.getOverlayColor() : SHORTCUT_HIGH_LEVEL_COLOR; if (config.highlightMarks() && !marksOfGrace.isEmpty()) { configColor = config.getMarkColor(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java index cd60c6b940..c895a07980 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java @@ -38,10 +38,12 @@ import net.runelite.api.Item; import net.runelite.api.ItemID; import static net.runelite.api.ItemID.AGILITY_ARENA_TICKET; import net.runelite.api.Player; +import net.runelite.api.Skill; import static net.runelite.api.Skill.AGILITY; import net.runelite.api.Tile; import net.runelite.api.TileObject; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.BoostedLevelChanged; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.DecorativeObjectChanged; import net.runelite.api.events.DecorativeObjectDespawned; @@ -63,6 +65,7 @@ import net.runelite.api.events.WallObjectSpawned; import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.AgilityShortcut; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -80,7 +83,7 @@ public class AgilityPlugin extends Plugin private static final int AGILITY_ARENA_REGION_ID = 11157; @Getter - private final Map obstacles = new HashMap<>(); + private final Map obstacles = new HashMap<>(); @Getter private final List marksOfGrace = new ArrayList<>(); @@ -115,6 +118,9 @@ public class AgilityPlugin extends Plugin private int lastAgilityXp; private WorldPoint lastArenaTicketPosition; + @Getter + private int agilityLevel; + @Provides AgilityConfig getConfig(ConfigManager configManager) { @@ -126,6 +132,7 @@ public class AgilityPlugin extends Plugin { overlayManager.add(agilityOverlay); overlayManager.add(lapCounterOverlay); + agilityLevel = client.getBoostedSkillLevel(Skill.AGILITY); } @Override @@ -136,6 +143,7 @@ public class AgilityPlugin extends Plugin marksOfGrace.clear(); obstacles.clear(); session = null; + agilityLevel = 0; } @Subscribe @@ -208,6 +216,17 @@ public class AgilityPlugin extends Plugin } } + + @Subscribe + public void onBoostedLevelChanged(BoostedLevelChanged boostedLevelChanged) + { + Skill skill = boostedLevelChanged.getSkill(); + if (skill == AGILITY) + { + agilityLevel = client.getBoostedSkillLevel(skill); + } + } + @Subscribe public void onItemSpawned(ItemSpawned itemSpawned) { @@ -366,11 +385,40 @@ public class AgilityPlugin extends Plugin } if (Obstacles.COURSE_OBSTACLE_IDS.contains(newObject.getId()) || - Obstacles.SHORTCUT_OBSTACLE_IDS.contains(newObject.getId()) || (Obstacles.TRAP_OBSTACLE_IDS.contains(newObject.getId()) && Obstacles.TRAP_OBSTACLE_REGIONS.contains(newObject.getWorldLocation().getRegionID()))) { - obstacles.put(newObject, tile); + obstacles.put(newObject, new Obstacle(tile, null)); + } + + if (Obstacles.SHORTCUT_OBSTACLE_IDS.containsKey(newObject.getId())) + { + AgilityShortcut closestShortcut = null; + int distance = -1; + + // Find the closest shortcut to this object + for (AgilityShortcut shortcut : Obstacles.SHORTCUT_OBSTACLE_IDS.get(newObject.getId())) + { + if (shortcut.getWorldLocation() == null) + { + closestShortcut = shortcut; + break; + } + else + { + int newDistance = shortcut.getWorldLocation().distanceTo2D(newObject.getWorldLocation()); + if (closestShortcut == null || newDistance < distance) + { + closestShortcut = shortcut; + distance = newDistance; + } + } + } + + if (closestShortcut != null) + { + obstacles.put(newObject, new Obstacle(tile, closestShortcut)); + } } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacle.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacle.java new file mode 100644 index 0000000000..6038de468b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacle.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, MrGroggle + * 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 HOLDER 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.plugins.agility; + +import javax.annotation.Nullable; +import lombok.AllArgsConstructor; +import lombok.Value; +import net.runelite.api.Tile; +import net.runelite.client.game.AgilityShortcut; + +@Value +@AllArgsConstructor +class Obstacle +{ + private final Tile tile; + @Nullable + private final AgilityShortcut shortcut; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java index 43a96bd151..4506891e99 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java @@ -25,11 +25,27 @@ package net.runelite.client.plugins.agility; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; import java.util.List; import java.util.Set; -import static net.runelite.api.NullObjectID.*; +import static net.runelite.api.NullObjectID.NULL_10872; +import static net.runelite.api.NullObjectID.NULL_10873; +import static net.runelite.api.NullObjectID.NULL_12945; +import static net.runelite.api.NullObjectID.NULL_18083; +import static net.runelite.api.NullObjectID.NULL_18116; +import static net.runelite.api.NullObjectID.NULL_18122; +import static net.runelite.api.NullObjectID.NULL_18124; +import static net.runelite.api.NullObjectID.NULL_18129; +import static net.runelite.api.NullObjectID.NULL_18130; +import static net.runelite.api.NullObjectID.NULL_18132; +import static net.runelite.api.NullObjectID.NULL_18133; +import static net.runelite.api.NullObjectID.NULL_18135; +import static net.runelite.api.NullObjectID.NULL_18136; +import static net.runelite.api.NullObjectID.NULL_3550; import static net.runelite.api.ObjectID.*; +import net.runelite.client.game.AgilityShortcut; class Obstacles { @@ -91,144 +107,7 @@ class Obstacles ZIP_LINE_11645, ZIP_LINE_11646 ); - static final Set SHORTCUT_OBSTACLE_IDS = ImmutableSet.of( - // Grand Exchange - UNDERWALL_TUNNEL_16529, UNDERWALL_TUNNEL_16530, - // South Varrock - STEPPING_STONE_16533, FENCE_16518, ROCKS_16549, ROCKS_16550, - // Falador - WALL_17049, WALL_17050, CRUMBLING_WALL_24222, UNDERWALL_TUNNEL, UNDERWALL_TUNNEL_16528, CREVICE_16543, - // Draynor - UNDERWALL_TUNNEL_19032, UNDERWALL_TUNNEL_19036, - // South Lumbridge - BROKEN_RAFT, STEPPING_STONE_16513, - // Trollheim - ROCKS_3790, ROCKS_3791, ROCKS_3803, ROCKS_3804, ROCKS_16523, ROCKS_16524, ROCKS_3748, ROCKS_16545, ROCKS_16521, - ROCKS_16522, ROCKS_16464, - // North Camelot - LOG_BALANCE_16540, LOG_BALANCE_16541, LOG_BALANCE_16542, - // Rellekka - BROKEN_FENCE, - // Ardougne - LOG_BALANCE_16546, LOG_BALANCE_16547, LOG_BALANCE_16548, - // Yanille - CASTLE_WALL, HOLE_16520, WALL_17047, - // Observatory - NULL_31849, - // Gnome Stronghold - ROCKS_16534, ROCKS_16535, - // Karamja Volcano - STRONG_TREE_17074, - // Shilo Village - STEPPING_STONE_16466, - // Vine east of Shilo Village - NULL_26884, NULL_26886, - // Stepping stones east of Shilo Village - STEPPING_STONES, STEPPING_STONES_23646, STEPPING_STONES_23647, - // Middle of Karamja - A_WOODEN_LOG, - // Slayer Tower - SPIKEY_CHAIN, SPIKEY_CHAIN_16538, - // Fremennik Slayer Cave - STRANGE_FLOOR_16544, CREVICE_16539, STEPS_29993, - // Wilderness - STEPPING_STONE_14918, STEPPING_STONE_14917, ROCKY_HANDHOLDS_26404, ROCKY_HANDHOLDS_26405, ROCKY_HANDHOLDS_26406, - // Godwars - ROCKY_HANDHOLDS_26400, ROCKY_HANDHOLDS_26401, ROCKY_HANDHOLDS_26402, - // Seers' Village Coal Mine - LOG_BALANCE_23274, - // Arceuus Essence Mine - ROCKS_27984, ROCKS_27985, BOULDER_27990, ROCKS_27987, ROCKS_27988, - // Wintertodt - GAP_29326, - // Gnome Stronghold Slayer Underground - TUNNEL_30174, TUNNEL_30175, - // Taverley Underground - OBSTACLE_PIPE_16509, STRANGE_FLOOR, ROCKS, ROCKS_14106, LOOSE_RAILING_28849, - // Heroes Guild - CREVICE_9739, CREVICE_9740, - // Fossil Island - HOLE_31481, HOLE_31482, LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, ROPE_ANCHOR, ROPE_ANCHOR_30917, - RUBBER_CAP_MUSHROOM, - ROCKS_31757, ROCKS_31758, ROCKS_31759, PILLAR_31809, - // West Brimhaven - ROPESWING_23568, ROPESWING_23569, - // Brimhaven Dungeon - VINE_26880, VINE_26882, PIPE_21728, STEPPING_STONE_19040, PIPE_21727, LOG_BALANCE_20882, LOG_BALANCE_20884, - STEPPING_STONE_21738, STEPPING_STONE_21739, TIGHTGAP, - // Lumbridge - STILE_12982, - // Edgeville Dungeon - MONKEYBARS_23566, OBSTACLE_PIPE_16511, - // Miscellania - STEPPING_STONE_11768, - // Kalphite - CREVICE_16465, - // Eagles' Peak - ROCKS_19849, - // Catherby - CROSSBOW_TREE_17062, ROCKS_17042, - // McGrubor's Woods - LOOSE_RAILING, - // Cairn Isle - ROCKS_2231, - // South Kourend - STEPPING_STONE_29728, STEPPING_STONE_29729, STEPPING_STONE_29730, - // Cosmic Temple - JUTTING_WALL_17002, - // Arandar - ROCKS_16514, ROCKS_16515, LOG_BALANCE_3933, - // South River Salve - STEPPING_STONE_13504, - DARK_TUNNEL_10047, - // Ectofuntus - WEATHERED_WALL, WEATHERED_WALL_16526, - // Mos Le'Harmless - STEPPING_STONE_19042, - // North River Salve - ROCKS_16998, ROCKS_16999, ORNATE_RAILING, ORNATE_RAILING_17000, - // West Zul-Andra - STEPPING_STONE_10663, - // Yanille Agility Dungeon - BALANCING_LEDGE_23548, OBSTACLE_PIPE_23140, MONKEYBARS_23567, PILE_OF_RUBBLE_23563, PILE_OF_RUBBLE_23564, - // High Level Wilderness Dungeon - CREVICE_19043, - // Revenant Caves - PILLAR_31561, - // Elf Camp Isafdar Tirranwn - LOG_BALANCE_3931, LOG_BALANCE_3930, LOG_BALANCE_3929, LOG_BALANCE_3932, DENSE_FOREST_3938, DENSE_FOREST_3939, - DENSE_FOREST_3998, DENSE_FOREST_3999, DENSE_FOREST, LEAVES, LEAVES_3924, LEAVES_3925, STICKS, TRIPWIRE, - // Gu'Tanoth bridge - GAP, GAP_2831, - // Lumbridge Swamp Caves - STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673, - // Morytania Pirate Ship - ROCK_16115, - // Agility Pyramid Entrance - CLIMBING_ROCKS_11948, CLIMBING_ROCKS_11949, - // Lumber Yard - BROKEN_FENCE_2618, - // Ungael and Vorkath crater - NULL_25337, NULL_29868, NULL_29869, NULL_29870, ICE_CHUNKS_31822, NULL_31823, ICE_CHUNKS_31990, - // Underwater Area Fossil Island - TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, - // Tree Gnome Village - LOOSE_RAILING_2186, - // Weiss - LITTLE_BOULDER, ROCKSLIDE_33184, ROCKSLIDE_33185, NULL_33327, NULL_33328, LEDGE_33190, ROCKSLIDE_33191, FALLEN_TREE_33192, - // Al-Kharid - BROKEN_WALL_33344, BIG_WINDOW, - // Burgh de Rott - LOW_FENCE, - // Taverley - STILE, - // Asgarnian Ice Dungeon - STEPS, - // Fossil Island Wyvern Cave - STAIRS_31485, - // Mount Karuulm - ROCKS_34397, ROCKS_34396 - ); + static final Multimap SHORTCUT_OBSTACLE_IDS; static final Set TRAP_OBSTACLE_IDS = ImmutableSet.of( // Agility pyramid @@ -236,4 +115,17 @@ class Obstacles ); static final List TRAP_OBSTACLE_REGIONS = ImmutableList.of(12105, 13356); + + static + { + final ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + for (final AgilityShortcut item : AgilityShortcut.values()) + { + for (int obstacle : item.getObstacleIds()) + { + builder.put(obstacle, item); + } + } + SHORTCUT_OBSTACLE_IDS = builder.build(); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java deleted file mode 100644 index c0b95cfa32..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutLocation.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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 HOLDER 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.plugins.worldmap; - -import lombok.Getter; -import net.runelite.api.coords.WorldPoint; - -@Getter -enum AgilityShortcutLocation -{ - KARAMJA_GLIDER_LOG("Log Balance", 1, new WorldPoint(2906, 3050, 0)), - FALADOR_CRUMBLING_WALL("Crumbling Wall", 5, new WorldPoint(2936, 3357, 0)), - RIVER_LUM_GRAPPLE_WEST("Grapple Broken Raft", 8, new WorldPoint(3245, 3179, 0)), - RIVER_LUM_GRAPPLE_EAST("Grapple Broken Raft", 8, new WorldPoint(3258, 3179, 0)), - CORSAIR_COVE_ROCKS("Rocks", 10, new WorldPoint(2545, 2871, 0)), - FALADOR_GRAPPLE_WALL("Grapple Wall", 11, new WorldPoint(3031, 3391, 0)), - VARROCK_SOUTH_FENCE("Fence", 13, new WorldPoint(3239, 3334, 0)), - GOBLIN_VILLAGE_WALL("Wall", 14, new WorldPoint(2925, 3523, 0)), - CORSAIR_COVE_DUNGEON_PILLAR("Pillar Jump", 15, new WorldPoint(1980, 8996, 0)), - YANILLE_UNDERWALL_TUNNEL("Underwall Tunnel", 16, new WorldPoint(2574, 3109, 0)), - COAL_TRUCKS_LOG_BALANCE("Log Balance", 20, new WorldPoint(2598, 3475, 0)), - GRAND_EXCHANGE_UNDERWALL_TUNNEL("Underwall Tunnel", 21, new WorldPoint(3139, 3515, 0)), - BRIMHAVEN_DUNGEON_PIPE("Pipe Squeeze", 22, new WorldPoint(2654, 9569, 0)), - OBSERVATORY_SCALE_CLIFF("Grapple Rocks", 23, new WorldPoint(2447, 3155, 0)), - EAGLES_PEAK_ROCK_CLIMB("Rock Climb", 25, new WorldPoint(2320, 3499, 0)), - FALADOR_UNDERWALL_TUNNEL("Underwall Tunnel", 26, new WorldPoint(2947, 3313, 0)), - MOUNT_KARUULM_LOWER("Rocks", 29, new WorldPoint(1324, 3782, 0)), - CORSAIR_COVE_RESOURCE_ROCKS("Rocks", 30, new WorldPoint(2545, 2871, 0)), - SOUTHEAST_KARAJMA_STEPPING_STONES("Stepping Stones", 30, new WorldPoint(2924, 2946, 0)), - DRAYNOR_MANOR_STEPPING_STONES("Stepping Stones", 31, new WorldPoint(3150, 3362, 0)), - CATHERBY_CLIFFSIDE_GRAPPLE("Grapple Rock", 32, new WorldPoint(2868, 3429, 0)), - ARDOUGNE_LOG_BALANCE("Log Balance", 33, new WorldPoint(2602, 3336, 0)), - GNOME_STRONGHOLD_ROCKS("Rocks", 37, new WorldPoint(2485, 3515, 0)), - AL_KHARID_MINING_PITCLIFF_SCRAMBLE("Rocks", 38, new WorldPoint(3305, 3315, 0)), - YANILLE_WALL_GRAPPLE("Grapple Wall", 39, new WorldPoint(2552, 3072, 0)), - NEITIZNOT_BRIDGE_REPAIR("Bridge Repair - Quest", 40, new WorldPoint(2315, 3828, 0)), - KOUREND_LAKE_JUMP_WEST("Stepping Stones", 40, new WorldPoint(1604, 3572, 0)), - KOUREND_LAKE_JUMP_EAST("Stepping Stones", 40, new WorldPoint(1612, 3570, 0)), - TROLLHEIM_EASY_CLIFF_SCRAMBLE("Rocks", 41, new WorldPoint(2869, 3670, 0)), - DWARVEN_MINE_NARROW_CREVICE("Narrow Crevice", 42, new WorldPoint(3034, 9806, 0)), - DRAYNOR_UNDERWALL_TUNNEL("Underwall Tunnel", 42, new WorldPoint(3068, 3261, 0)), - TROLLHEIM_MEDIUM_CLIFF_SCRAMBLE_NORTH("Rocks", 43, new WorldPoint(2886, 3684, 0)), - TROLLHEIM_MEDIUM_CLIFF_SCRAMBLE_SOUTH("Rocks", 43, new WorldPoint(2876, 3666, 0)), - TROLLHEIM_ADVANCED_CLIFF_SCRAMBLE("Rocks", 44, new WorldPoint(2907, 3686, 0)), - KOUREND_RIVER_STEPPING_STONES("Stepping Stones", 45, new WorldPoint(1721, 3509, 0)), - COSMIC_ALTAR_MEDIUM_WALKWAY("Narrow Walkway", 46, new WorldPoint(2399, 4403, 0)), - DEEP_WILDERNESS_DUNGEON_CREVICE_NORTH("Narrow Crevice", 46, new WorldPoint(3047, 10335, 0)), - DEEP_WILDERNESS_DUNGEON_CREVICE_SOUTH("Narrow Crevice", 46, new WorldPoint(3045, 10327, 0)), - TROLLHEIM_HARD_CLIFF_SCRAMBLE("Rocks", 47, new WorldPoint(2902, 3680, 0)), - FREMENNIK_LOG_BALANCE("Log Balance", 48, new WorldPoint(2721, 3591, 0)), - ARCEUUS_ESSENCE_MINE_BOULDER("Boulder", 49, new WorldPoint(1774, 3888, 0)), - MORYTANIA_STEPPING_STONE("Stepping Stone", 50, new WorldPoint(3418, 3326, 0)), - VARROCK_SEWERS_PIPE_SQUEEZE("Pipe Squeeze", 51, new WorldPoint(3152, 9905, 0)), - ARCEUUS_ESSENCE_MINE_EAST_SCRAMBLE("Rock Climb", 52, new WorldPoint(1770, 3851, 0)), - KARAMJA_VOLCANO_GRAPPLE_NORTH("Grapple Rock", 53, new WorldPoint(2873, 3143, 0)), - KARAMJA_VOLCANO_GRAPPLE_SOUTH("Grapple Rock", 53, new WorldPoint(2874, 3128, 0)), - MOTHERLODE_MINE_WALL_WEST("Wall", 54, new WorldPoint(3118, 9702, 0)), - MOTHERLODE_MINE_WALL_EAST("Wall", 54, new WorldPoint(3124, 9703, 0)), - MISCELLANIA_DOCK_STEPPING_STONE("Stepping Stone", 55, new WorldPoint(2572, 3862, 0)), - RELEKKA_EAST_FENCE("Fence", 57, new WorldPoint(2688, 3697, 0)), - ELVEN_OVERPASS_CLIFF_SCRAMBLE("Rocks", 59, new WorldPoint(2345, 3300, 0)), - WILDERNESS_GWD_CLIMB_WEST("Rocks", 60, new WorldPoint(2928, 3760, 0)), - WILDERNESS_GWD_CLIMB_EAST("Rocks", 60, new WorldPoint(2943, 3770, 0)), - MOS_LEHARMLESS_STEPPING_STONE("Stepping Stone", 60, new WorldPoint(3710, 2970, 0)), - WINTERTODT_GAP("Gap", 60, new WorldPoint(1629, 4023, 0)), - SLAYER_TOWER_MEDIUM_CHAIN_FIRST("Spiked Chain (Floor 1)", 61, new WorldPoint(3421, 3550, 0)), - SLAYER_TOWER_MEDIUM_CHAIN_SECOND("Spiked Chain (Floor 2)", 61, new WorldPoint(3420, 3551, 0)), - SLAYER_DUNGEON_CREVICE("Narrow Crevice", 62, new WorldPoint(2729, 10008, 0)), - MOUNT_KARUULM_UPPER("Rocks", 62, new WorldPoint(1322, 3791, 0)), - TAVERLEY_DUNGEON_RAILING("Loose Railing", 63, new WorldPoint(2935, 9811, 0)), - TROLLHEIM_WILDERNESS_ROCKS("Rocks", 64, new WorldPoint(2945, 3678, 0)), - FOSSIL_ISLAND_VOLCANO("Rope", 64, new WorldPoint(3780, 3822, 0)), - MORYTANIA_TEMPLE("Loose Railing", 65, new WorldPoint(3422, 3476, 0)), - REVENANT_CAVES_GREEN_DRAGONS("Jump", 65, new WorldPoint(3220, 10086, 0)), - COSMIC_ALTAR_ADVANCED_WALKWAY("Narrow Walkway", 66, new WorldPoint(2408, 4401, 0)), - LUMBRIDGE_DESERT_STEPPING_STONE("Stepping Stone", 66, new WorldPoint(3210, 3135, 0)), - HEROS_GUILD_TUNNEL_WEST("Crevice", 67, new WorldPoint(2898, 9901, 0)), - HEROS_GUILD_TUNNEL_EAST("Crevice", 67, new WorldPoint(2913, 9895, 0)), - ELVEN_OVERPASS_MEDIUM_CLIFF("Rocks", 68, new WorldPoint(2337, 3288, 0)), - ARCEUUS_ESSENSE_NORTH("Rock Climb", 69, new WorldPoint(1759, 3873, 0)), - TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON("Pipe Squeeze", 70, new WorldPoint(2886, 9798, 0)), - FOSSIL_ISLAND_HARDWOOD("Hole", 70, new WorldPoint(3663, 3810, 0)), - GWD_SARADOMIN_ROPE_FIRST("Rope Descent", 70, new WorldPoint(2912, 5300, 0)), - GWD_SARADOMIN_ROPE_SECOND("Rope Descent", 70, new WorldPoint(2951, 5267, 0)), - SLAYER_TOWER_ADVANCED_CHAIN_FIRST("Spiked Chain (Floor 2)", 71, new WorldPoint(3447, 3578, 0)), - SLAYER_TOWER_ADVANCED_CHAIN_SECOND("Spiked Chain (Floor 3)", 71, new WorldPoint(3446, 3576, 0)), - SLAYER_CAVE_WALL_CLIMB("Tunnel", 72, new WorldPoint(2431, 9806, 0)), - TROLL_STRONGHOLD_WALL_CLIMB("Rocks", 73, new WorldPoint(2841, 3694, 0)), - ARCEUUS_ESSENSE_MINE_WEST("Rock Climb", 73, new WorldPoint(1742, 3853, 0)), - LAVA_DRAGON_ISLE_JUMP("Stepping Stone", 74, new WorldPoint(3200, 3807, 0)), - REVENANT_CAVES_DEMONS_JUMP("Jump", 75, new WorldPoint(3199, 10135, 0)), - REVENANT_CAVES_ANKOU_EAST("Jump", 75, new WorldPoint(3201, 10195, 0)), - REVENANT_CAVES_ANKOU_NORTH("Jump", 75, new WorldPoint(3180, 10209, 0)), - ZUL_ANDRA_ISLAND_CROSSING("Stepping Stone", 76, new WorldPoint(2156, 3073, 0)), - SHILO_VILLAGE_STEPPING_STONES("Stepping Stones", 77, new WorldPoint(2863, 2974, 0)), - KHARAZI_JUNGLE_VINE_CLIMB("Vine", 79, new WorldPoint(2897, 2939, 0)), - TAVERLEY_DUNGEON_SPIKED_BLADES("Strange Floor", 80, new WorldPoint(2877, 9813, 0)), - TAVERLEY_DUNGEON_ROCKS("Rocks", 70, new WorldPoint(2887, 9823, 0)), - SLAYER_DUNGEON_CHASM_JUMP("Spiked Blades", 81, new WorldPoint(2770, 10003, 0)), - LAVA_MAZE_NORTH_JUMP("Stepping Stone", 82, new WorldPoint(3092, 3880, 0)), - BRIMHAVEN_DUNGEON_EAST_STEPPING_NORTH("Stepping Stones", 83, new WorldPoint(2685, 9547, 0)), - BRIMHAVEN_DUNGEON_EAST_STEPPING_SOUTH("Stepping Stones", 83, new WorldPoint(2693, 9529, 0)), - ELVEN_ADVANCED_CLIFF_SCRAMBLE("Rocks", 85, new WorldPoint(2337, 3253, 0)), - KALPHITE_WALL("Crevice", 86, new WorldPoint(3214, 9508, 0)), - BRIMHAVEN_DUNGEON_VINE_EAST("Vine", 87, new WorldPoint(2672, 9582, 0)), - BRIMHAVEN_DUNGEON_VINE_WEST("Vine", 87, new WorldPoint(2606, 9584, 0)), - RENEVANT_CAVES("Jump", 89, new WorldPoint(3240, 10144, 0)); - - private final String tooltip; - private final WorldPoint location; - private final int levelReq; - - AgilityShortcutLocation(String description, int level, WorldPoint location) - { - this.tooltip = description + " - Level " + level; - this.location = location; - this.levelReq = level; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java index 74f4673c85..c99979f103 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java @@ -27,12 +27,13 @@ package net.runelite.client.plugins.worldmap; import java.awt.image.BufferedImage; import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; +import net.runelite.client.game.AgilityShortcut; class AgilityShortcutPoint extends WorldMapPoint { - AgilityShortcutPoint(AgilityShortcutLocation data, BufferedImage icon, boolean showTooltip) + AgilityShortcutPoint(AgilityShortcut data, BufferedImage icon, boolean showTooltip) { - super(data.getLocation(), icon); + super(data.getWorldMapLocation(), icon); if (showTooltip) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java index fea186927b..276e2083e4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java @@ -36,6 +36,7 @@ import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ExperienceChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.AgilityShortcut; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; @@ -167,9 +168,10 @@ public class WorldMapPlugin extends Plugin if (config.agilityShortcutLevelIcon() || config.agilityShortcutTooltips()) { - Arrays.stream(AgilityShortcutLocation.values()) + Arrays.stream(AgilityShortcut.values()) + .filter(value -> value.getWorldMapLocation() != null) .map(value -> new AgilityShortcutPoint(value, - agilityLevel > 0 && config.agilityShortcutLevelIcon() && value.getLevelReq() > agilityLevel ? NOPE_ICON : BLANK_ICON, + agilityLevel > 0 && config.agilityShortcutLevelIcon() && value.getLevel() > agilityLevel ? NOPE_ICON : BLANK_ICON, config.agilityShortcutTooltips())) .forEach(worldMapPointManager::add); } From 9d7dbe2aeaefd8778794f11799057e293b59d3ac Mon Sep 17 00:00:00 2001 From: theGeekPirate Date: Wed, 20 Feb 2019 00:38:59 -0800 Subject: [PATCH 070/102] Correct Falador teleport XP in Skill Calc (#7943) --- .../runelite/client/plugins/skillcalculator/skill_magic.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json index 38719b3d00..15905e0a0c 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json @@ -238,7 +238,7 @@ "level": 37, "sprite": 33, "name": "Falador Teleport", - "xp": 47 + "xp": 48 }, { "level": 39, From 3cf17cb6e547235a424724cf8220076255ff1dff Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 19 Feb 2019 09:20:42 -0500 Subject: [PATCH 071/102] item prices: add high alch profit to overlay Co-authored-by: Medes --- .../plugins/itemprices/ItemPricesConfig.java | 12 +++++++ .../plugins/itemprices/ItemPricesOverlay.java | 36 +++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java index ed69408341..a7b62e52b3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java @@ -74,4 +74,16 @@ public interface ItemPricesConfig extends Config { return true; } + + @ConfigItem( + keyName = "showAlchProfit", + name = "Show High Alchemy Profit", + description = "Show the profit from casting high alchemy on items", + position = 5 + ) + default boolean showAlchProfit() + { + return false; + } + } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java index 7e170db214..3d9553ca62 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java @@ -196,6 +196,7 @@ class ItemPricesOverlay extends Overlay int gePrice = 0; int haPrice = 0; + int haProfit = 0; if (config.showGEPrice()) { @@ -205,16 +206,20 @@ class ItemPricesOverlay extends Overlay { haPrice = Math.round(itemDef.getPrice() * HIGH_ALCHEMY_CONSTANT); } + if (gePrice > 0 && haPrice > 0 && config.showAlchProfit()) + { + haProfit = calculateHAProfit(haPrice, gePrice); + } if (gePrice > 0 || haPrice > 0) { - return stackValueText(qty, gePrice, haPrice); + return stackValueText(qty, gePrice, haPrice, haProfit); } return null; } - private String stackValueText(int qty, int gePrice, int haValue) + private String stackValueText(int qty, int gePrice, int haValue, int haProfit) { if (gePrice > 0) { @@ -246,9 +251,36 @@ class ItemPricesOverlay extends Overlay } } + if (haProfit > 0) + { + Color haColor = haProfitColor(haProfit); + + itemStringBuilder.append("
"); + itemStringBuilder.append("HA Profit: ") + .append(ColorUtil.wrapWithColorTag(String.valueOf(haProfit * qty), haColor)) + .append(" gp"); + if (config.showEA() && qty > 1) + { + itemStringBuilder.append(" (") + .append(ColorUtil.wrapWithColorTag(String.valueOf(haProfit), haColor)) + .append(" ea)"); + } + } + // Build string and reset builder final String text = itemStringBuilder.toString(); itemStringBuilder.setLength(0); return text; } + + private int calculateHAProfit(int haPrice, int gePrice) + { + int natureRunePrice = itemManager.getItemPrice(ItemID.NATURE_RUNE); + return haPrice - gePrice - natureRunePrice; + } + + private static Color haProfitColor(int haProfit) + { + return haProfit >= 0 ? Color.GREEN : Color.RED; + } } From 8923dae45e3efb4a466e3947a55ec2a91b5b7c23 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 20 Feb 2019 19:29:13 -0500 Subject: [PATCH 072/102] client: only enable developer mode if launcher version isn't set --- .../src/main/java/net/runelite/client/RuneLite.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index b7fae34e2c..ecdda28103 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -183,9 +183,9 @@ public class RuneLite System.exit(0); } - final boolean developerMode = options.has("developer-mode"); + final boolean developerMode = options.has("developer-mode") && RuneLiteProperties.getLauncherVersion() == null; - if (developerMode && RuneLiteProperties.getLauncherVersion() == null) + if (developerMode) { boolean assertions = false; assert assertions = true; From ccaa955572615038c5c53d85276eb4a79a8ef194 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 21 Feb 2019 12:11:50 +0000 Subject: [PATCH 073/102] [maven-release-plugin] prepare release runelite-parent-1.5.13 --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- protocol-api/pom.xml | 2 +- protocol/pom.xml | 2 +- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-mixins/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- runescape-api/pom.xml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 21e66169bc..05429ae427 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 0ea164ee8d..507a7f30a5 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 17a7524427..e947d4e56e 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 0829178ece..594e9e240d 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 32dc046a4c..60819f5391 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 Web Service diff --git a/pom.xml b/pom.xml index 44828e6d8e..931e6e13b2 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 pom RuneLite @@ -59,7 +59,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - HEAD + runelite-parent-1.5.13 diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index 46d1cd9593..ee7f34b67a 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index 91084dfbe6..3e55dead1e 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 34afe917d0..0cd8522d97 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 3cb78ed8f2..3964781464 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 client diff --git a/runelite-mixins/pom.xml b/runelite-mixins/pom.xml index bd4ddb5801..927a805860 100644 --- a/runelite-mixins/pom.xml +++ b/runelite-mixins/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 mixins diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 9b274b38f5..b42d7e2b81 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 script-assembler-plugin diff --git a/runescape-api/pom.xml b/runescape-api/pom.xml index 03417c67e0..5b06826b55 100644 --- a/runescape-api/pom.xml +++ b/runescape-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13-SNAPSHOT + 1.5.13 net.runelite.rs From 18167a77827f2958082a81c0c4aa11cc3c2272c9 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 21 Feb 2019 12:11:57 +0000 Subject: [PATCH 074/102] [maven-release-plugin] prepare for next development iteration --- cache-client/pom.xml | 2 +- cache-updater/pom.xml | 2 +- cache/pom.xml | 2 +- http-api/pom.xml | 2 +- http-service/pom.xml | 2 +- pom.xml | 4 ++-- protocol-api/pom.xml | 2 +- protocol/pom.xml | 2 +- runelite-api/pom.xml | 2 +- runelite-client/pom.xml | 2 +- runelite-mixins/pom.xml | 2 +- runelite-script-assembler-plugin/pom.xml | 2 +- runescape-api/pom.xml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 05429ae427..9ad16f216c 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 507a7f30a5..f6d5cc5ffa 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index e947d4e56e..072a7e4767 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 594e9e240d..910cacdbd6 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 60819f5391..d1217f0ced 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index 931e6e13b2..a5187a029c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT pom RuneLite @@ -59,7 +59,7 @@ https://github.com/runelite/runelite scm:git:git://github.com/runelite/runelite scm:git:git@github.com:runelite/runelite - runelite-parent-1.5.13 + HEAD diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index ee7f34b67a..df42e1e53a 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index 3e55dead1e..490f2eb372 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 0cd8522d97..f9b875d6fa 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 3964781464..e026f85423 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT client diff --git a/runelite-mixins/pom.xml b/runelite-mixins/pom.xml index 927a805860..8b90c2bec0 100644 --- a/runelite-mixins/pom.xml +++ b/runelite-mixins/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT mixins diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index b42d7e2b81..57ce1ecb31 100644 --- a/runelite-script-assembler-plugin/pom.xml +++ b/runelite-script-assembler-plugin/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT script-assembler-plugin diff --git a/runescape-api/pom.xml b/runescape-api/pom.xml index 5b06826b55..4986a1d5fa 100644 --- a/runescape-api/pom.xml +++ b/runescape-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.13 + 1.5.14-SNAPSHOT net.runelite.rs From 3c1da4bb1e6f39fafb1a4b948e8f57148c0dcd1f Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 21 Feb 2019 08:51:39 -0500 Subject: [PATCH 075/102] http service: disable spring jmx Multiple api deployments is causing Spring to try to register the datasources multiple times and is erroring --- http-service/src/main/resources/application.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/http-service/src/main/resources/application.yaml b/http-service/src/main/resources/application.yaml index 7b6785a325..9aa02c58ac 100644 --- a/http-service/src/main/resources/application.yaml +++ b/http-service/src/main/resources/application.yaml @@ -4,4 +4,9 @@ datasource: runelite-cache: jndiName: java:comp/env/jdbc/runelite-cache2 runelite-tracker: - jndiName: java:comp/env/jdbc/runelite-tracker \ No newline at end of file + jndiName: java:comp/env/jdbc/runelite-tracker +# By default Spring tries to register the datasource as an MXBean, +# so if multiple apis are delpoyed on one web container with +# shared datasource it tries to register it multiples times and +# fails when starting the 2nd api +spring.jmx.enabled: false \ No newline at end of file From 7df862de4d32262699f1ee76e63825ec14d726b2 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Thu, 21 Feb 2019 16:05:10 +0100 Subject: [PATCH 076/102] Do not try to draw infobox caption if text is null or empty Closes #7964 Signed-off-by: Tomas Slusny --- .../ui/overlay/components/InfoBoxComponent.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java index be055179bb..d8f7841099 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java @@ -24,6 +24,7 @@ */ package net.runelite.client.ui.overlay.components; +import com.google.common.base.Strings; import java.awt.Color; import java.awt.Dimension; import java.awt.FontMetrics; @@ -86,11 +87,14 @@ public class InfoBoxComponent implements LayoutableRenderableEntity null); // Render caption - final TextComponent textComponent = new TextComponent(); - textComponent.setColor(color); - textComponent.setText(text); - textComponent.setPosition(new Point(baseX + ((size - metrics.stringWidth(text)) / 2), baseY + size - SEPARATOR)); - textComponent.render(graphics); + if (!Strings.isNullOrEmpty(text)) + { + final TextComponent textComponent = new TextComponent(); + textComponent.setColor(color); + textComponent.setText(text); + textComponent.setPosition(new Point(baseX + ((size - metrics.stringWidth(text)) / 2), baseY + size - SEPARATOR)); + textComponent.render(graphics); + } this.bounds.setBounds(bounds); return bounds.getSize(); From dad7b05e6a39118ffa040fd9e84466d6e0c841bb Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Thu, 21 Feb 2019 16:41:53 +0100 Subject: [PATCH 077/102] Remove emptyOrNull text check from InfoboxOverlay This is unnecessary as it should be checked when drawing the text. Signed-off-by: Tomas Slusny --- .../runelite/client/ui/overlay/infobox/InfoBoxOverlay.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java index e6a8d6f749..58f20aae63 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java @@ -99,10 +99,7 @@ public class InfoBoxOverlay extends Overlay final Color color = box.getTextColor(); final InfoBoxComponent infoBoxComponent = new InfoBoxComponent(); - if (!Strings.isNullOrEmpty(text)) - { - infoBoxComponent.setText(text); - } + infoBoxComponent.setText(text); if (color != null) { infoBoxComponent.setColor(color); From 66997ac71baa88aeca443b65e56f582a6bb7160e Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 21 Feb 2019 10:43:47 -0500 Subject: [PATCH 078/102] item prices: show negative high alch profits too --- .../runelite/client/plugins/itemprices/ItemPricesOverlay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java index 3d9553ca62..7c748a7702 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java @@ -251,7 +251,7 @@ class ItemPricesOverlay extends Overlay } } - if (haProfit > 0) + if (haProfit != 0) { Color haColor = haProfitColor(haProfit); From 654ee9051222ceefff271cec8c1cd88238bcd2fa Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Thu, 17 Jan 2019 20:51:38 +0100 Subject: [PATCH 079/102] Add button to sync local config with remote Add button to info panel that will show when you are logged in to sync local configuration with remote. Signed-off-by: Tomas Slusny --- .../runelite/client/config/ConfigManager.java | 58 +++++++++++++++++- .../client/plugins/info/InfoPanel.java | 41 +++++++++++-- .../client/plugins/info/import_icon.png | Bin 0 -> 8483 bytes 3 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/info/import_icon.png 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 2cde4900ad..bb04cbec5f 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 @@ -111,12 +111,17 @@ public class ConfigManager load(); // load profile specific config } + private File getLocalPropertiesFile() + { + return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME); + } + private File getPropertiesFile() { // Sessions that aren't logged in have no username if (session == null || session.getUsername() == null) { - return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME); + return getLocalPropertiesFile(); } else { @@ -184,6 +189,57 @@ public class ConfigManager } } + private synchronized void syncPropertiesFromFile(File propertiesFile) + { + final Properties properties = new Properties(); + try (FileInputStream in = new FileInputStream(propertiesFile)) + { + properties.load(new InputStreamReader(in, Charset.forName("UTF-8"))); + } + catch (Exception e) + { + log.debug("Malformed properties, skipping update"); + return; + } + + final Map copy = (Map) ImmutableMap.copyOf(this.properties); + copy.forEach((groupAndKey, value) -> + { + if (!properties.containsKey(groupAndKey)) + { + final String[] split = groupAndKey.split("\\.", 2); + if (split.length != 2) + { + return; + } + + final String groupName = split[0]; + final String key = split[1]; + unsetConfiguration(groupName, key); + } + }); + + properties.forEach((objGroupAndKey, objValue) -> + { + final String groupAndKey = String.valueOf(objGroupAndKey); + final String[] split = groupAndKey.split("\\.", 2); + if (split.length != 2) + { + return; + } + + final String groupName = split[0]; + final String key = split[1]; + final String value = String.valueOf(objValue); + setConfiguration(groupName, key, value); + }); + } + + public void importLocal() + { + syncPropertiesFromFile(getLocalPropertiesFile()); + } + private synchronized void loadFromFile() { properties.clear(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java index 2edb250135..203b688b4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java @@ -40,6 +40,7 @@ import javax.inject.Singleton; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import javax.swing.event.HyperlinkEvent; @@ -48,6 +49,7 @@ import net.runelite.api.events.SessionClose; import net.runelite.api.events.SessionOpen; import net.runelite.client.RuneLiteProperties; import net.runelite.client.account.SessionManager; +import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.ColorScheme; @@ -66,9 +68,12 @@ public class InfoPanel extends PluginPanel private static final ImageIcon DISCORD_ICON; private static final ImageIcon PATREON_ICON; private static final ImageIcon WIKI_ICON; + private static final ImageIcon IMPORT_ICON; private final JLabel loggedLabel = new JLabel(); private final JRichTextPane emailLabel = new JRichTextPane(); + private JPanel syncPanel; + private JPanel actionsContainer; @Inject @Nullable @@ -86,6 +91,9 @@ public class InfoPanel extends PluginPanel @Inject private ScheduledExecutorService executor; + @Inject + private ConfigManager configManager; + static { ARROW_RIGHT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/util/arrow_right.png")); @@ -93,6 +101,7 @@ public class InfoPanel extends PluginPanel DISCORD_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "discord_icon.png")); PATREON_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "patreon_icon.png")); WIKI_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "wiki_icon.png")); + IMPORT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "import_icon.png")); } void init() @@ -150,11 +159,22 @@ public class InfoPanel extends PluginPanel versionPanel.add(loggedLabel); versionPanel.add(emailLabel); - updateLoggedIn(); - - JPanel actionsContainer = new JPanel(); + actionsContainer = new JPanel(); actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0)); - actionsContainer.setLayout(new GridLayout(4, 1, 0, 10)); + actionsContainer.setLayout(new GridLayout(0, 1, 0, 10)); + + syncPanel = buildLinkPanel(IMPORT_ICON, "Import local settings", "to remote RuneLite account", () -> + { + final int result = JOptionPane.showOptionDialog(syncPanel, + "This will replace your current RuneLite account settings with settings from your local profile.", + "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, new String[]{"Yes", "No"}, "No"); + + if (result == JOptionPane.YES_OPTION) + { + configManager.importLocal(); + } + }); actionsContainer.add(buildLinkPanel(GITHUB_ICON, "Report an issue or", "make a suggestion", runeLiteProperties.getGithubLink())); actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", runeLiteProperties.getDiscordInvite())); @@ -164,6 +184,7 @@ public class InfoPanel extends PluginPanel add(versionPanel, BorderLayout.NORTH); add(actionsContainer, BorderLayout.CENTER); + updateLoggedIn(); eventBus.register(this); } @@ -171,6 +192,14 @@ public class InfoPanel extends PluginPanel * Builds a link panel with a given icon, text and url to redirect to. */ private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url) + { + return buildLinkPanel(icon, topText, bottomText, () -> LinkBrowser.browse(url)); + } + + /** + * Builds a link panel with a given icon, text and callable to call. + */ + private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, Runnable callback) { JPanel container = new JPanel(); container.setBackground(ColorScheme.DARKER_GRAY_COLOR); @@ -193,7 +222,6 @@ public class InfoPanel extends PluginPanel @Override public void mousePressed(MouseEvent mouseEvent) { - LinkBrowser.browse(url); container.setBackground(pressedColor); textContainer.setBackground(pressedColor); } @@ -201,6 +229,7 @@ public class InfoPanel extends PluginPanel @Override public void mouseReleased(MouseEvent e) { + callback.run(); container.setBackground(hoverColor); textContainer.setBackground(hoverColor); } @@ -252,12 +281,14 @@ public class InfoPanel extends PluginPanel emailLabel.setContentType("text/plain"); emailLabel.setText(name); loggedLabel.setText("Logged in as"); + actionsContainer.add(syncPanel, 0); } else { emailLabel.setContentType("text/html"); emailLabel.setText("Login to sync settings to the cloud."); loggedLabel.setText("Not logged in"); + actionsContainer.remove(syncPanel); } } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/info/import_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/info/import_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..32263bf15962b926d8c5862f0becbb3780753967 GIT binary patch literal 8483 zcmV+;A>7`HP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3>zb{snnWdCy&vxMX~xg0V{o-;d`<*nJZj+Z>&{rP8lUbl_cD$>|?RnjQJqmNB=MCxG89lGt`19HA6Z&Gc&ntiVg-_01@Bh7> z-CCopHP79(kT|Jio|}5z%KnKrc8=2Tk0rh`e}8}<38rX4YsSFC3>`-qlfANY*;>xA zV4ud$oe!>K0UM(m)+}t}ahmLk)3y0bw)?#36`Vxb42!v7 zv3QmRaA+r+UB!mrWI5UFs)DQNu$qlB&ako=77Ww6xa^1RJ}vi0yO|jNBfGiZSm7yUUgk_ zl{+uai9g&bAktGFHP3s^u;yx^ER*J3-se2-Wa~XgoPAdQ(%Tnlv*Yx6jjIp6Qhm+B%v2Yv#B;<|m-ZQYJt*@5?UcD6!W-Ng~AwYc7z!@9fHV2A+{^}O-B zXjjEENiz1{%aKUxJeO#e9dqHE{rdg8Fzny$Xk7o%lIC;G|87b1(>DLjlIG8M{`X6o zKiqk~X9Xr&6L_2;dpSWIBV=$6PnpBu1sPr#ptu(o$uap=2c+|6?=g?OH~-DW9|vdO+4Z}~ zsZHiIZr>*toww!BH9UXkmAGcebu4big)w@*`{)bIfh-D}a?|z78eGtV**Y~H++Tgq zoy)qkN&uIDD0ocIv4MrA=G-c|_Kul|=Uh^U4z&ue0`7dTw#@7%k>6m|fG6~7m7J#q z*a2XlfIn{1#CvdzBNH04Dc(6tvUOQX?&U7Fgme+tcHOhfH>M4h!@%&(vOGL1%@ZPJ zM!>ajY8Jd+g}6)=92nY1ukEU7T2g3jvyNDchc!gmzQLahM6Zw3n+f0;*0{ZWVHhVr zB6QQXEYit8y1(Zd3!#G7^!okCbKvw0>~h(ZZx*eY-EeyR*vKtcY+?AjbB1a1EtLCi zHZX(9ni-yN(+1A;VF10=HoUk#6Fd%rtXT?<4ovpWz3$+!a}3zeSP;3C zeHT`=$oc{mBC(k`3FNDdkwmQmsrPs zPD@mD3;@gEE+L^TWFvu|*#a&>o=Qu=f_XMa0t~xf7w{yKjt^rW%Ogs4Mh*jeNnS!fZE!7EGNN5EX49IZsxI z#1rom8Yrjl5Wx$GG;|)Gq3Vlrk78q4?UQ%{GOGZHD6a$uOdUtNkBx~(05#pjkeRoa zgW-TX-4N+wp=C7~Il(#a#GeZMT5LB4m#B3mQfGp+lZh;FCNDNib|xBbQd{bR?>G_v zsSr!h1qp#F#ct#62D^)mcyD(k>p0T$Bp7j=I?cen$e!T=*sEJe@J@Nt!37ogY!Nnz zB*-^0(ihwAS1;O8=DdUvN|66S!nQkKC0U=6$v5s&? z|K>~{Eg2o1L`^(FF$<80gTh8n7A!e#@9v!F8m^c!1-s#DJDjgyzsrrTux=^#67Y9t zlWz|#){%IQJXcef5(+Z1cDx>$x^gE{rMT`DFc&N;@e$ z|KJ}v0kYWezXN}DTfnyse-E1Ce+0Q9e3iU5rj(MDdSr8n&N@=*+0O*4WK(y7p^Gpk z{49HT*1`bx+Wu*c!qMtiN#_6`gItMm&*N_WUZCWXd|kV;G%Eg;cpLYDKY@)q!8U^s zK!x<;9&d60WQx6o<4t2jdH36!Hk1=Hk5MQ2`yg%Tx5*VaeIaezgd4{BAngqvp=J-# zCT^w|A+2Q5P`KQ((oTTa4iPcnL$|okbhrrljpXP_5t|pfC|-B~wjbgX9|3XJlY%@; zg51w~XSLs~C62i^$NajISs&~CcRMp5xB6f1%&c#R_HTD)z8~7Z-I;kmw1FZ<$r2M= zO?*U5Mh3hGOdL=c6l{t(8ZMH34aNiOPU-|cK(rPd+-`4=@@1&o@%G>$$TRX!`8qNu z9j2W?PgEwFmQ}zi=w()lg}4+83+{#8DSIhcUc8!etZ^EGlm2S40ij zV8K(p?us-i76fVNu%PI!N3Y$LY%Qr{w_ZcL-%!_kXDZ+vfV>Q#qYOmKN3(3|{lFmF z{yLzvg|gd+4ip{$Y}=;U0Rn7}WN9YocuSuqFiJ_kdyiOaaiDnPCZ@edj1|%Rej21WCv$jM+d7Q&loOXc_%n8OvJbW`j7K9eSN`A?^?-Q=cST3vT1M5s2m}HhC6n zDhB?1)rQ33+Ny4y9M?rPl8X?a8V8P11x}WEOf($l)Tp+-MTo|>?5gHLJ6p?j|A?VdcgxR8(wou!MO&bnK0Vh zvdtp}P`N4rNeMS`jDY6BHUGi+$_NqtU))6a!n^9N23n|uVs=BL=VeF%s! zO1erzaBcy?j`Ca9X>VC)*|12;+@WZmK&*%@vPMy`1WQ0AzKo+f7KzB580 zI6DRptF-k%`01p_smDOD05`4tV_3dN<*KaZCBiVmz+VtGr$)o4yl89NsYI}Zfa?OK z4M|v(R5gjJ&1q1QPc6;bta1TC`zofLdcjjn%e!9i6w`LSK*h8ey?B+!TLEN|9}68S zwN=$dSU%dO(ip%FASbwwC92A;s4pv%fq{K4k&3ihIR%%>`J|rYE{W*L!_+P@L!Rn) z>;nIp$!bd5=o__uxbMRVN>p=d*L9+pE*pO8I-FD4(T^sW7Uc(cJI>H)?WaOag2%<6 z-fkzLR7wkXuhn^XC2LCs3xL+PgxT+AB|K1OV(J%il+4-44e=%dQMcCsLIVt&FhPU? zEhS!{i>#BLXw;9*I-oAp)ZR4_lX91Aw#M044 z3Z~PX0&wChnC3dcWZq+RN7J98^!gH~uQ1&~YRfi z;1j7I^x-2?RonyXrS|w_5)Vz#u5%LZnGRQ2=AOwdM~$y0F+&q0Wws8zUoU@!1a!W)v1z?L43VLpPjm5c+Y!4CUtPWT|+){9z+-4#>@MNHUqcrnoNw z@QeR{z`KjbZOjQH`Ayk=Q@0!UwYhiB=X!VO4|nToXIqUgT#<8wXDauTP|aBp8pLMh zHEGvH%P$-UScPmJ&dbUQd#xJ}X9(TAmcGI%Sg<%WPXsHr(+yBPrnpl<`F#YK69W4{ zz9hWw`EHZ7b$HCV;9-3+1>I~k#64F(NOM@<*?hdtErb0EUcPiIr(doCCEP3yl{&&v z2i)_u&R~9ZRK{gSmdDIX6m!9ldWN0n3A3~E2-(83Y1jbjBJGOh2nZ&pPF9EF zAu$5F)?5Xhm`HD%J{Oj zKQ0JPAE_7B6S{)g`eh|mw|8kN5jeZbep6x* zREynnqbQ+10r7k0)G!;V2LDEnnbY2eu{V$LRNIX^W?Lvld<)O03D>n`0fHgHERndk z7y`F@=#4;%Eb@r_4?ZoCKQ0lM^^xtJ{gUk)%WXd3x*F+jdp1XU?5GCQep_ntGYLWm zbQ9Z~4s!4lSDmm*^h|BLcmfDUm`lB_nTVqTdI(BaZUBl}^qksuQah$v$8I+qK|AqE zrLU-DkHVK% z>c^-jO^aEXovBZr4l1nY=b-ITjB4S8p@SX>Vs7PDiBI!2KC#1cYsv;{QwQ{mV;tn2nKfr%rkaXfa|+Ym@VaXc`jD&Uy$}@Kj+>FYft8USTvh+kS0uQ@*Z^gC z(%qKpUozfDp-t`L7c4!DK*014OPd*}2o|alVR&nA25eYmWL3e~Ss>baiy^R!=T`DZ z5sb76g-BUNFr)G$s61>3$*rc~oyzzeJhn~FkD_2ds0N=Q$s6} z+!qNEbqCrRTe-{W4tS4@4qo5($31n&^XZO&DRZe~z z`Zx*o%h(68_L}>cqrZ)PsA~h;fsDLbcj{B@7Rxg*Foi{9k00$&H;Q$RE=P_IECI@p zFhTS(UwAE4uXUSnv0i+yAOS|tUA*o_BqBHnV)0p{P49@g#+`KUb!fK1H?oKBT@bXp z&(LCWTUYlPL*%@3y;p@>(*%fPrQxgWN*$a=PnZzc68)NXaTqg@7Y7p3BHaQh{8k-a zIqdeLze9~YfGwV36AWHXD{4nVWo5OZ!YO4c5~8*clr z_GQk-{`-BIUxx1f<-W}OfqmcCyd~6Lfsa;WZL*WXzGPL3l_N=@A;;THqU-x)PdGJc=F^MD{W_7!LTX0eIDOu|X!4Po&>G=*MlN;}`qX94(8X>;_k2b! zP8)gv%jQg7e6*qMnH%NZrx6|Xv_V!Mo3Qqg1vKZkD<)(iH5mBaxNkh$%BOwQz{STb z-c;8YUmS;dlfd!R$ zZ}|c-8jvv%gucg<)}xl~Kf`*v#r5-qkvTf&LkXcvzbK)i z8h{$O&yb;L{Kqs@?LZY!m|Az{ty7F}IMYz`3=luP;@6PjYmjEo7@l$Iv0*vGW2f2k z(rwS&wKFfhXYR^tUV7JC&fNcYv9GgtX}xCe_OwsLS|7uA>23J#p}BYYDKBZ-tgqKN zqS3GhY3Zk|v`atZh~%QF+@#*(MXKL>O6s)QJ(jg*G6<%D_TsZQQH&cZPh2bBsx)W- zK_ZDD=w|}cYZPCT_~{wJ?9U{=@vxKR+I>dxgN8bvQT%-Ub&-tk=HcKfZ{fM;6wc7y z=PA6++@;T%I|%P<<_?8s_VDd^vFqBu_Nu|Hr&s;3>-bBnnwWSVh0z4gi?9$uWiD^C(=ulBS z={B!o*bl9-zGVdp06Mjmq#b&`P;+5NNCHpXE7CJ1IAn|!ij;{C?)!q7evTPFf%V>v zjtZ=2csKTq!)JKcv~p&bSis^RODs5xVEvAD;P{XxtD^6oaR%rEkvOHY&s=1I z#0SSs?kS_Wr;N^!kp|#5t4W{HYQcO{2e2W$!bc z-p&w^@0w0G7a&?}C(&s<9U%>IRJYFWfuvJWYy|tIF2JcLrv1oHed>vPWUf|>3W}Tt zMt^!1hd!X?PQu3u4}DmhK4`c`6C8VD!tKI|7aEu|*jv&F@<$?PvAYzYrM9#H)Yn@(s|CR{6k;=H(P?SIisPnvneT|ubWbrFF&oq^gQ39 zjj49p^UH3amWOB8GdhgjtkOUNRja?dyE4u-AOhhk_x9&L(*64hMDq+sW|a_OE!(ch z7TMM1SIubG5^%$rg3PM1fr`M%lHj1lm5V23myjy?tt&qH9+OPWYMk1-v&gs<(# znA{$PkDDJ^l%}cg{HU%cFs_`RQo91fDoReFy*|&f?Lxb&WWww;o80zukQ!qY9KOZ| zr)Kld<0C+4u$s$%9v^Yh4YzT(5N zU+DSvm{mECSuJ-S$kfbdfgl{XzT*(EsR(AFCTa$eoAlhb)8NW}%#W`?t_>TKP|S08 z7lP)e$Ov#ql!m&QQxABL;D*zj)L^?Is=1P)y5VYO3XU{K_1O;(n&T#;&hy-8!)?ML z5x26;Qr%=14ua}oXEbQ6*Mp~MjOW4AQ*4G*0iY+qW!3q{tq2o+orFu9OTWHEPdLqzq>*6+E2tw5C}tQ z3ZT?92(GHJux8;G=n=3CB^+w%-rcQPNPZ3TA|+(a00NImL_t(Y$L*HEYg0iG#=mVETVvWoBML?k5u}Qcs~1UoX^s{2 zVEYFMUcKl=u!0yo6hsf!dh{UJgGCT5XtALsf(oLxRUssof}-F>p=$kknFs6ZOZu8b z5OiVT&CbqzGxKI=M*7#5i+d5+FX^bHAxQ@%WsLPn(xRjpNq3!dZ`)!SkO$^~8c+m= zfZaeBkOumJg7GSLH{S|iH*g)O0wX{ohD^flR!z2hv!H#z0&oxLZNlgtlU)G%;tHjJ zGH?axXdz-9rlSm`;s{Ivw*l9N{BWjgGEO4ZfSz_e8w-22VZs3=U^L=9*h%0d@DTV2 zdEAMfm^m$fm{^u7*MQZlz>~n zci@;8fgp*_82F6_UKfF}D8?h85Mk*#&#Q}`A>FnE`ZDkn*i#3%0L(@)R)DNWcUt(? zfIGl>AZ@%PFk?FiZ^j}r1?-K`p9NN;fLDPokG^1D9uI{!01cK8{>nQa2Rc1{TY%L# zz%PNvAyC=>oc93cfwLZeo6-0=(+D^m>aW1K|C~JDP7ioTgmD7y1C@HA_DkZjq(dIP zWbLonRq Date: Fri, 22 Feb 2019 00:25:59 +0100 Subject: [PATCH 080/102] Backup RuneLite account settings before overwriting them Signed-off-by: Tomas Slusny --- .../runelite/client/config/ConfigManager.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) 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 bb04cbec5f..78b84776a1 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 @@ -43,8 +43,11 @@ import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.nio.channels.FileLock; import java.nio.charset.Charset; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.time.Instant; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -70,6 +73,7 @@ import net.runelite.http.api.config.Configuration; public class ConfigManager { private static final String SETTINGS_FILE_NAME = "settings.properties"; + private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); @Inject EventBus eventBus; @@ -179,7 +183,7 @@ public class ConfigManager try { - saveToFile(); + saveToFile(propertiesFile); log.debug("Updated configuration on disk with the latest version"); } @@ -237,6 +241,24 @@ public class ConfigManager public void importLocal() { + if (session == null) + { + // No session, no import + return; + } + + final File file = new File(propertiesFile.getParent(), propertiesFile.getName() + "." + TIME_FORMAT.format(new Date())); + + try + { + saveToFile(file); + } + catch (IOException e) + { + log.warn("Backup failed, skipping import", e); + return; + } + syncPropertiesFromFile(getLocalPropertiesFile()); } @@ -287,7 +309,7 @@ public class ConfigManager } } - private synchronized void saveToFile() throws IOException + private synchronized void saveToFile(final File propertiesFile) throws IOException { propertiesFile.getParentFile().mkdirs(); @@ -368,7 +390,7 @@ public class ConfigManager { try { - saveToFile(); + saveToFile(propertiesFile); } catch (IOException ex) { @@ -411,7 +433,7 @@ public class ConfigManager { try { - saveToFile(); + saveToFile(propertiesFile); } catch (IOException ex) { From 4e1e132985b7d7bf6d76d4231732e34461f15256 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 22 Feb 2019 00:39:17 +0100 Subject: [PATCH 081/102] Log config property changes only if they really change This prevents spam from previous property loading addition Signed-off-by: Tomas Slusny --- .../java/net/runelite/client/config/ConfigManager.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 78b84776a1..9ef92ed01c 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 @@ -372,8 +372,6 @@ public class ConfigManager public void setConfiguration(String groupName, String key, String value) { - log.debug("Setting configuration value for {}.{} to {}", groupName, key, value); - String oldValue = (String) properties.setProperty(groupName + "." + key, value); if (Objects.equals(oldValue, value)) @@ -381,6 +379,8 @@ public class ConfigManager return; } + log.debug("Setting configuration value for {}.{} to {}", groupName, key, value); + synchronized (pendingChanges) { pendingChanges.put(groupName + "." + key, value); @@ -415,8 +415,6 @@ public class ConfigManager public void unsetConfiguration(String groupName, String key) { - log.debug("Unsetting configuration value for {}.{}", groupName, key); - String oldValue = (String) properties.remove(groupName + "." + key); if (oldValue == null) @@ -424,6 +422,8 @@ public class ConfigManager return; } + log.debug("Unsetting configuration value for {}.{}", groupName, key); + synchronized (pendingChanges) { pendingChanges.put(groupName + "." + key, null); From 114422e3919d2ef50e955e84d4d4cca04c65a8b7 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 22 Feb 2019 00:54:48 +0100 Subject: [PATCH 082/102] Properly split config properties loaded from config client Some keys contain multiple dots (account-based, farming) and so this was setting incorrect value before. Signed-off-by: Tomas Slusny --- .../java/net/runelite/client/config/ConfigManager.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 9ef92ed01c..b24c9ccb96 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 @@ -167,7 +167,13 @@ public class ConfigManager for (ConfigEntry entry : configuration.getConfig()) { log.debug("Loading configuration value from client {}: {}", entry.getKey(), entry.getValue()); - final String[] split = entry.getKey().split("\\."); + final String[] split = entry.getKey().split("\\.", 2); + + if (split.length != 2) + { + continue; + } + final String groupName = split[0]; final String key = split[1]; final String value = entry.getValue(); From 4787fe71e447e52ab45c75d2bd706a8860f6e131 Mon Sep 17 00:00:00 2001 From: Royce Mathews Date: Fri, 22 Feb 2019 01:31:27 -0600 Subject: [PATCH 083/102] Add enchanting jewelry to the idle notification plugin. (#7977) Closes #7975 --- runelite-api/src/main/java/net/runelite/api/AnimationID.java | 1 + .../runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java | 1 + 2 files changed, 2 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index ee1a50d7ed..1f96e9c898 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -123,6 +123,7 @@ public final class AnimationID public static final int HERBLORE_POTIONMAKING = 363; //used for both herb and secondary public static final int MAGIC_CHARGING_ORBS = 726; public static final int MAGIC_MAKE_TABLET = 4068; + public static final int MAGIC_ENCHANTING_JEWELRY = 931; public static final int BURYING_BONES = 827; public static final int USING_GILDED_ALTAR = 3705; public static final int LOOKING_INTO = 832; 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 9a47e57de0..8a23af905f 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 @@ -202,6 +202,7 @@ public class IdleNotifierPlugin extends Plugin case MAGIC_CHARGING_ORBS: case MAGIC_LUNAR_STRING_JEWELRY: case MAGIC_MAKE_TABLET: + case MAGIC_ENCHANTING_JEWELRY: /* Prayer */ case USING_GILDED_ALTAR: /* Farming */ From de0d3bc787e209f664323b627c8404401c88688f Mon Sep 17 00:00:00 2001 From: RyBo Date: Fri, 22 Feb 2019 00:37:05 -0700 Subject: [PATCH 084/102] Highlight more efficient ledge in the Falador Agility course (#7938) --- .../java/net/runelite/client/plugins/agility/Obstacles.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java index 4506891e99..92df605a36 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/Obstacles.java @@ -78,7 +78,7 @@ class Obstacles STEPPING_STONE_15412, TROPICAL_TREE_15414, MONKEYBARS_15417, SKULL_SLOPE_15483, ROPE_15487, TROPICAL_TREE_16062, // Falador ROUGH_WALL_10833, TIGHTROPE_10834, HAND_HOLDS_10836, GAP_11161, GAP_11360, TIGHTROPE_11361, - TIGHTROPE_11364, GAP_11365, LEDGE_11366, LEDGE_11367, LEDGE_11368, LEDGE_11370, EDGE_11371, + TIGHTROPE_11364, GAP_11365, LEDGE_11366, LEDGE_11367, LEDGE_11369, LEDGE_11370, EDGE_11371, // Wilderness OBSTACLE_PIPE_23137, ROPESWING_23132, STEPPING_STONE_23556, LOG_BALANCE_23542, ROCKS_23640, // Seers From 7f066a5bc558d89f05050253903f3a3e05820eef Mon Sep 17 00:00:00 2001 From: Koekkruimels <47660479+Koekkruimels@users.noreply.github.com> Date: Fri, 22 Feb 2019 09:53:21 +0100 Subject: [PATCH 085/102] Add color to the library customer based on player inventory (#7951) --- .../plugins/kourendlibrary/KourendLibraryOverlay.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java index 3c6863af3a..b581b10bd8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java @@ -31,6 +31,7 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.geom.Rectangle2D; +import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; @@ -38,6 +39,8 @@ import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.Setter; import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.ItemContainer; import net.runelite.api.Perspective; import static net.runelite.api.Perspective.getCanvasTilePoly; import net.runelite.api.Player; @@ -216,9 +219,13 @@ class KourendLibraryOverlay extends Overlay .forEach(n -> { Book b = library.getCustomerBook(); + ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY); + boolean hasBookInInventory = itemContainer != null + && b != null + && Arrays.stream(itemContainer.getItems()).anyMatch(item -> item.getId() == b.getItem()); LocalPoint local = n.getLocalLocation(); Polygon poly = getCanvasTilePoly(client, local); - OverlayUtil.renderPolygon(g, poly, Color.WHITE); + OverlayUtil.renderPolygon(g, poly, hasBookInInventory ? Color.GREEN : Color.WHITE); Point screen = Perspective.localToCanvas(client, local, client.getPlane(), n.getLogicalHeight()); if (screen != null) { From 8bfca20223a3ffb422cb12f229e8a296ba9d0217 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 22 Feb 2019 13:22:29 +0000 Subject: [PATCH 086/102] Catch JVM incompatible library JNA error when initializing Discord Signed-off-by: Tomas Slusny --- .../main/java/net/runelite/client/discord/DiscordService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java index 0988273ecc..091c479ac6 100644 --- a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java +++ b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java @@ -78,7 +78,7 @@ public class DiscordService implements AutoCloseable discordRPC = DiscordRPC.INSTANCE; discordEventHandlers = new DiscordEventHandlers(); } - catch (UnsatisfiedLinkError e) + catch (Error e) { log.warn("Failed to load Discord library, Discord support will be disabled."); } From 6e707a1f5223b108a9990946e4ad78b39adf2601 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sat, 23 Feb 2019 16:54:33 +0100 Subject: [PATCH 087/102] Move slayer weakness overlay 1 layer up above In order to not draw the weakness overlay under NPC HP bars and prayers move overlay 1 layer up to UNDER_WIDGETS. Signed-off-by: Tomas Slusny --- .../runelite/client/plugins/slayer/TargetWeaknessOverlay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java index 5521380e57..ada3f3a727 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetWeaknessOverlay.java @@ -59,7 +59,7 @@ class TargetWeaknessOverlay extends Overlay this.itemManager = itemManager; this.npcManager = npcManager; setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); + setLayer(OverlayLayer.UNDER_WIDGETS); } @Override From 813be24ad1284fae545fe70a754fe591e9a3241c Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 24 Feb 2019 00:05:05 +0100 Subject: [PATCH 088/102] Limit access levels for InfoBox fields Signed-off-by: Tomas Slusny --- .../net/runelite/client/ui/overlay/infobox/InfoBox.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java index fc498d3635..8c2889e8e6 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java @@ -26,24 +26,25 @@ package net.runelite.client.ui.overlay.infobox; import java.awt.Color; import java.awt.Image; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import net.runelite.client.plugins.Plugin; public abstract class InfoBox { - @Getter + @Getter(AccessLevel.PACKAGE) private final Plugin plugin; @Getter @Setter private Image image; - @Getter - @Setter + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) private Image scaledImage; - @Getter + @Getter(AccessLevel.PACKAGE) @Setter private InfoBoxPriority priority; From 78f16f28f0e4befc52da19c3f2338bee90388d72 Mon Sep 17 00:00:00 2001 From: Koekkruimels Date: Wed, 20 Feb 2019 13:26:51 +0100 Subject: [PATCH 089/102] kourend library plugin: add config option to hide duplicate books --- .../kourendlibrary/KourendLibraryConfig.java | 10 +++++ .../kourendlibrary/KourendLibraryOverlay.java | 19 +++++++-- .../kourendlibrary/KourendLibraryPlugin.java | 42 +++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java index b61a24c139..6ec40a00fd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java @@ -42,4 +42,14 @@ public interface KourendLibraryConfig extends Config { return true; } + + @ConfigItem( + keyName = "hideDuplicateBook", + name = "Hide duplicate book", + description = "Don't show the duplicate book locations in the library" + ) + default boolean hideDuplicateBook() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java index b581b10bd8..f1f0162d59 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import javax.annotation.Nullable; import lombok.AccessLevel; import lombok.Setter; import net.runelite.api.Client; @@ -57,15 +58,19 @@ class KourendLibraryOverlay extends Overlay private final static int MAXIMUM_DISTANCE = 24; private final Library library; private final Client client; + private final KourendLibraryConfig config; + private final KourendLibraryPlugin plugin; @Setter(AccessLevel.PACKAGE) private boolean hidden; @Inject - private KourendLibraryOverlay(Library library, Client client) + private KourendLibraryOverlay(Library library, Client client, KourendLibraryConfig config, KourendLibraryPlugin plugin) { this.library = library; this.client = client; + this.config = config; + this.plugin = plugin; setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ABOVE_SCENE); @@ -136,7 +141,7 @@ class KourendLibraryOverlay extends Overlay Color color = bookIsKnown ? Color.ORANGE : Color.WHITE; // Render the poly on the floor - if (!(bookIsKnown && book == null) && (library.getState() == SolvedState.NO_DATA || book != null || !possible.isEmpty())) + if (!(bookIsKnown && book == null) && (library.getState() == SolvedState.NO_DATA || book != null || !possible.isEmpty()) && !shouldHideOverlayIfDuplicateBook(book)) { Polygon poly = getCanvasTilePoly(client, localBookcase); if (poly != null) @@ -149,7 +154,7 @@ class KourendLibraryOverlay extends Overlay // If the book is singled out, render the text and the book's icon if (bookIsKnown) { - if (book != null) + if (book != null && !shouldHideOverlayIfDuplicateBook(book)) { FontMetrics fm = g.getFontMetrics(); Rectangle2D bounds = fm.getStringBounds(book.getShortName(), g); @@ -236,4 +241,12 @@ class KourendLibraryOverlay extends Overlay return null; } + + private boolean shouldHideOverlayIfDuplicateBook(@Nullable Book book) + { + return config.hideDuplicateBook() + && book != null + && !book.isDarkManuscript() + && plugin.doesPlayerContainBook(book); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java index 73602299f4..649189fc47 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java @@ -26,6 +26,7 @@ package net.runelite.client.plugins.kourendlibrary; import com.google.inject.Provides; import java.awt.image.BufferedImage; +import java.util.EnumSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; @@ -34,6 +35,9 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.AnimationID; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; import net.runelite.api.MenuAction; import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; @@ -41,6 +45,7 @@ import net.runelite.api.events.AnimationChanged; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameTick; +import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -94,6 +99,7 @@ public class KourendLibraryPlugin extends Plugin private boolean buttonAttached = false; private WorldPoint lastBookcaseClick = null; private WorldPoint lastBookcaseAnimatedOn = null; + private EnumSet playerBooks = null; @Provides KourendLibraryConfig provideConfig(ConfigManager configManager) @@ -120,6 +126,8 @@ public class KourendLibraryPlugin extends Plugin overlayManager.add(overlay); + updatePlayerBooks(); + if (!config.hideButton()) { clientToolbar.addNavigation(navButton); @@ -135,6 +143,7 @@ public class KourendLibraryPlugin extends Plugin buttonAttached = false; lastBookcaseClick = null; lastBookcaseAnimatedOn = null; + playerBooks = null; } @Subscribe @@ -271,4 +280,37 @@ public class KourendLibraryPlugin extends Plugin } } } + + @Subscribe + public void onItemContainerChanged(ItemContainerChanged itemContainerChangedEvent) + { + updatePlayerBooks(); + } + + boolean doesPlayerContainBook(Book book) + { + return playerBooks.contains(book); + } + + private void updatePlayerBooks() + { + ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY); + + if (itemContainer != null) + { + EnumSet books = EnumSet.noneOf(Book.class); + + for (Item item : itemContainer.getItems()) + { + Book book = Book.byId(item.getId()); + + if (book != null) + { + books.add(book); + } + } + + playerBooks = books; + } + } } \ No newline at end of file From fbd9bce202f9609e2917cfa9772e2f3e8ec7359c Mon Sep 17 00:00:00 2001 From: Koekkruimels Date: Sun, 24 Feb 2019 10:37:03 +0100 Subject: [PATCH 090/102] Refactor changes of #7951 to use doesPlayerContainBook --- .../plugins/kourendlibrary/KourendLibraryOverlay.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java index f1f0162d59..5cf7910ee6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryOverlay.java @@ -31,7 +31,6 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.geom.Rectangle2D; -import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; @@ -40,8 +39,6 @@ import javax.annotation.Nullable; import lombok.AccessLevel; import lombok.Setter; import net.runelite.api.Client; -import net.runelite.api.InventoryID; -import net.runelite.api.ItemContainer; import net.runelite.api.Perspective; import static net.runelite.api.Perspective.getCanvasTilePoly; import net.runelite.api.Player; @@ -224,13 +221,10 @@ class KourendLibraryOverlay extends Overlay .forEach(n -> { Book b = library.getCustomerBook(); - ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY); - boolean hasBookInInventory = itemContainer != null - && b != null - && Arrays.stream(itemContainer.getItems()).anyMatch(item -> item.getId() == b.getItem()); + boolean doesPlayerContainBook = b != null && plugin.doesPlayerContainBook(b); LocalPoint local = n.getLocalLocation(); Polygon poly = getCanvasTilePoly(client, local); - OverlayUtil.renderPolygon(g, poly, hasBookInInventory ? Color.GREEN : Color.WHITE); + OverlayUtil.renderPolygon(g, poly, doesPlayerContainBook ? Color.GREEN : Color.WHITE); Point screen = Perspective.localToCanvas(client, local, client.getPlane(), n.getLogicalHeight()); if (screen != null) { From 8d34c4960f5f96c8c21778217b731df464aff8a4 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 24 Feb 2019 11:55:11 +0100 Subject: [PATCH 091/102] Fix infobox impl access levels and remove unused values Signed-off-by: Tomas Slusny --- .../client/plugins/cannon/CannonCounter.java | 2 +- .../kingdomofmiscellania/KingdomCounter.java | 2 +- .../plugins/mta/graveyard/GraveyardCounter.java | 2 +- .../nightmarezone/AbsorptionCounter.java | 17 ++--------------- .../nightmarezone/NightmareZoneOverlay.java | 2 +- .../client/plugins/slayer/TaskCounter.java | 4 ++-- .../client/ui/overlay/infobox/Timer.java | 8 ++------ 7 files changed, 10 insertions(+), 27 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java index 631410d8c2..bd13e194be 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonCounter.java @@ -32,7 +32,7 @@ public class CannonCounter extends InfoBox { private final CannonPlugin plugin; - public CannonCounter(BufferedImage img, CannonPlugin plugin) + CannonCounter(BufferedImage img, CannonPlugin plugin) { super(img, plugin); this.plugin = plugin; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java index 24f8029184..8a2871125f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kingdomofmiscellania/KingdomCounter.java @@ -32,7 +32,7 @@ public class KingdomCounter extends Counter { private final KingdomPlugin plugin; - public KingdomCounter(BufferedImage image, KingdomPlugin plugin) + KingdomCounter(BufferedImage image, KingdomPlugin plugin) { super(image, plugin, plugin.getFavor()); this.plugin = plugin; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java index 907712ab28..ecfbafd544 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardCounter.java @@ -31,7 +31,7 @@ import net.runelite.client.ui.overlay.infobox.Counter; public class GraveyardCounter extends Counter { - public GraveyardCounter(BufferedImage image, Plugin plugin) + GraveyardCounter(BufferedImage image, Plugin plugin) { super(image, plugin, 0); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java index 4c6b496a29..4671edde12 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java @@ -26,36 +26,23 @@ package net.runelite.client.plugins.nightmarezone; import java.awt.Color; import java.awt.image.BufferedImage; -import lombok.Getter; import lombok.Setter; import net.runelite.client.plugins.Plugin; import net.runelite.client.ui.overlay.infobox.Counter; +@Setter public class AbsorptionCounter extends Counter { - @Getter - @Setter private int threshold; - - @Getter - @Setter private Color aboveThresholdColor = Color.GREEN; - - @Getter - @Setter private Color belowThresholdColor = Color.RED; - public AbsorptionCounter(BufferedImage image, Plugin plugin, int absorption, int threshold) + AbsorptionCounter(BufferedImage image, Plugin plugin, int absorption, int threshold) { super(image, plugin, absorption); this.threshold = threshold; } - public void setAbsorption(int absorption) - { - setCount(absorption); - } - @Override public Color getTextColor() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java index e2a123b1af..71ae196d3e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java @@ -129,7 +129,7 @@ class NightmareZoneOverlay extends Overlay } else { - absorptionCounter.setAbsorption(absorptionPoints); + absorptionCounter.setCount(absorptionPoints); } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java index f73a5aae5b..0d4274c063 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskCounter.java @@ -29,9 +29,9 @@ import net.runelite.client.ui.overlay.infobox.Counter; import java.awt.image.BufferedImage; -public class TaskCounter extends Counter +class TaskCounter extends Counter { - public TaskCounter(BufferedImage img, Plugin plugin, int amount) + TaskCounter(BufferedImage img, Plugin plugin, int amount) { super(img, plugin, amount); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Timer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Timer.java index 3219b487b2..4d6c2b7be4 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Timer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/Timer.java @@ -31,9 +31,11 @@ import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import lombok.Getter; +import lombok.ToString; import net.runelite.client.plugins.Plugin; @Getter +@ToString public class Timer extends InfoBox { private final Instant startTime; @@ -51,12 +53,6 @@ public class Timer extends InfoBox endTime = startTime.plus(duration); } - @Override - public String toString() - { - return "Timer{" + "startTime=" + startTime + ", endTime=" + endTime + ", duration=" + duration + '}'; - } - @Override public String getText() { From e4250c5d3b874274cf65620285bc2fce27d5e69b Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 24 Feb 2019 10:15:30 -0500 Subject: [PATCH 092/102] xptracker service: only update last_updated after hiscores are saved --- .../runelite/http/service/xp/XpTrackerService.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java b/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java index 9f4e639964..9e8e0a5e06 100644 --- a/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java +++ b/http-service/src/main/java/net/runelite/http/service/xp/XpTrackerService.java @@ -96,17 +96,11 @@ public class XpTrackerService log.warn("Username update queue is full ({})", QUEUE_LIMIT); return; } + + usernameUpdateQueue.add(username); } - - con.createQuery("update player set last_updated = CURRENT_TIMESTAMP where id = :id") - .addParameter("id", playerEntity.getId()) - .executeUpdate(); } - synchronized (usernameUpdateQueue) - { - usernameUpdateQueue.add(username); - } usernameFilter.put(username); } @@ -190,7 +184,7 @@ public class XpTrackerService .addParameter("overall_rank", hiscoreResult.getOverall().getRank()) .executeUpdate(); - con.createQuery("update player set rank = :rank where id = :id") + con.createQuery("update player set rank = :rank, last_updated = CURRENT_TIMESTAMP where id = :id") .addParameter("id", playerEntity.getId()) .addParameter("rank", hiscoreResult.getOverall().getRank()) .executeUpdate(); From 368a080ad0b476d66a3ac3cc87c0e544efe4eb0d Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 24 Feb 2019 13:44:49 -0500 Subject: [PATCH 093/102] xptracker: up xp threshold to 10k --- .../net/runelite/client/plugins/xptracker/XpTrackerPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java index 54dff5a299..bb43ffdd7a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerPlugin.java @@ -73,7 +73,7 @@ public class XpTrackerPlugin extends Plugin /** * Amount of EXP that must be gained for an update to be submitted. */ - private static final int XP_THRESHOLD = 1000; + private static final int XP_THRESHOLD = 10_000; static final List COMBAT = ImmutableList.of( Skill.ATTACK, From c8e85d07f7d8b31b0257e90c44e3aa7bbb0d7b40 Mon Sep 17 00:00:00 2001 From: Magic fTail Date: Sun, 24 Feb 2019 23:55:34 +0100 Subject: [PATCH 094/102] Split synchronizing and uploading loot data into separate configs --- .../plugins/loottracker/LootTrackerConfig.java | 16 ++++++++++++++-- .../plugins/loottracker/LootTrackerPanel.java | 8 +++++--- .../plugins/loottracker/LootTrackerPlugin.java | 5 ++--- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java index 98b7053117..bba5994d89 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java @@ -51,11 +51,23 @@ public interface LootTrackerConfig extends Config @ConfigItem( keyName = "saveLoot", - name = "Save loot", - description = "Save loot between client sessions (requires being logged in)" + name = "Submit loot tracker data", + description = "Submit loot tracker data (requires being logged in)" ) default boolean saveLoot() { return true; } + + @ConfigItem( + keyName = "syncPanel", + name = "Synchronize panel contents", + description = "Synchronize you local loot tracker with your online (requires being logged in). This means" + + " that panel is filled with portion of your remote data on startup and deleting data in panel deletes them" + + " also on server." + ) + default boolean syncPanel() + { + return true; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java index 4aaa7e0c7a..ed850cdcbb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java @@ -99,6 +99,7 @@ class LootTrackerPanel extends PluginPanel private final ItemManager itemManager; private final LootTrackerPlugin plugin; + private final LootTrackerConfig config; private boolean groupLoot; private boolean hideIgnoredItems; @@ -130,10 +131,11 @@ class LootTrackerPanel extends PluginPanel INVISIBLE_ICON_HOVER = new ImageIcon(ImageUtil.alphaOffset(invisibleImg, -220)); } - LootTrackerPanel(final LootTrackerPlugin plugin, final ItemManager itemManager) + LootTrackerPanel(final LootTrackerPlugin plugin, final ItemManager itemManager, final LootTrackerConfig config) { this.itemManager = itemManager; this.plugin = plugin; + this.config = config; this.hideIgnoredItems = true; setBorder(new EmptyBorder(6, 6, 6, 6)); @@ -297,7 +299,7 @@ class LootTrackerPanel extends PluginPanel // Delete all loot, or loot matching the current view LootTrackerClient client = plugin.getLootTrackerClient(); - if (client != null) + if (client != null && config.syncPanel()) { client.delete(currentView); } @@ -472,7 +474,7 @@ class LootTrackerPanel extends PluginPanel LootTrackerClient client = plugin.getLootTrackerClient(); // Without loot being grouped we have no way to identify single kills to be deleted - if (client != null && groupLoot) + if (client != null && groupLoot && config.syncPanel()) { client.delete(box.getId()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index 30d4a25ba5..055c2cc3f4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -195,7 +195,7 @@ public class LootTrackerPlugin extends Plugin protected void startUp() throws Exception { ignoredItems = Text.fromCSV(config.getIgnoredItems()); - panel = new LootTrackerPanel(this, itemManager); + panel = new LootTrackerPanel(this, itemManager, config); spriteManager.getSpriteAsync(SpriteID.TAB_INVENTORY, 0, panel::loadHeaderIcon); final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "panel_icon.png"); @@ -227,9 +227,8 @@ public class LootTrackerPlugin extends Plugin { Collection lootRecords; - if (!config.saveLoot()) + if (!config.syncPanel()) { - // don't load loot if we're not saving loot return; } From ffb60d5b2a64ae49597e5b8669c8b182734798fd Mon Sep 17 00:00:00 2001 From: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> Date: Mon, 25 Feb 2019 10:43:47 -0800 Subject: [PATCH 095/102] Add dynamic hitpoints orb icon to poison plugin (#6517) To improve visibility of poison/venom/disease on low HP, also recolor heart icon when poisoned/venomed/diseased. --- .../main/java/net/runelite/api/VarPlayer.java | 4 + .../client/plugins/poison/PoisonConfig.java | 10 ++ .../client/plugins/poison/PoisonPlugin.java | 160 ++++++++++++++---- .../client/plugins/poison/1067-DISEASE.png | Bin 0 -> 2991 bytes .../client/plugins/poison/1067-POISON.png | Bin 0 -> 2992 bytes .../client/plugins/poison/1067-VENOM.png | Bin 0 -> 2986 bytes 6 files changed, 141 insertions(+), 33 deletions(-) create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/poison/1067-DISEASE.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/poison/1067-POISON.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/poison/1067-VENOM.png diff --git a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java index 37b71aaf66..c3183074b0 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java +++ b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java @@ -37,6 +37,10 @@ public enum VarPlayer ATTACK_STYLE(43), QUEST_POINTS(101), IS_POISONED(102), + /** + * Seems to start at 50(10 splash) and goes down by 1 every 30 seconds + */ + DISEASE_VALUE(456), BANK_TAB(115), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonConfig.java index 2595009205..6c723d4f71 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonConfig.java @@ -42,4 +42,14 @@ public interface PoisonConfig extends Config { return false; } + + @ConfigItem( + keyName = "changeHealthIcon", + name = "Change HP Orb Icon", + description = "Configures whether the hp orb icon should change color to match poison/disease" + ) + default boolean changeHealthIcon() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java index 68b9889a2a..84a4c5e3d6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poison/PoisonPlugin.java @@ -35,12 +35,13 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import javax.inject.Inject; import lombok.Getter; -import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.GameState; import net.runelite.api.SpriteID; import net.runelite.api.VarPlayer; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.VarbitChanged; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.SpriteManager; @@ -50,22 +51,36 @@ import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.ImageUtil; @PluginDescriptor( name = "Poison", description = "Tracks current damage values for Poison and Venom", - tags = {"combat", "poison", "venom"} + tags = {"combat", "poison", "venom", "heart", "hp"} ) -@Slf4j public class PoisonPlugin extends Plugin { static final int POISON_TICK_MILLIS = 18200; private static final int VENOM_THRESHOLD = 1000000; private static final int VENOM_MAXIUMUM_DAMAGE = 20; + private static final BufferedImage HEART_DISEASE; + private static final BufferedImage HEART_POISON; + private static final BufferedImage HEART_VENOM; + + static + { + HEART_DISEASE = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-DISEASE.png"), 26, 26); + HEART_POISON = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-POISON.png"), 26, 26); + HEART_VENOM = ImageUtil.resizeCanvas(ImageUtil.getResourceStreamFromClass(PoisonPlugin.class, "1067-VENOM.png"), 26, 26); + } + @Inject private Client client; + @Inject + private ClientThread clientThread; + @Inject private PoisonOverlay poisonOverlay; @@ -88,6 +103,8 @@ public class PoisonPlugin extends Plugin private Instant poisonNaturalCure; private Instant nextPoisonTick; private int lastValue = -1; + private int lastDiseaseValue = -1; + private BufferedImage heart; @Provides PoisonConfig getConfig(ConfigManager configManager) @@ -99,6 +116,11 @@ public class PoisonPlugin extends Plugin protected void startUp() throws Exception { overlayManager.add(poisonOverlay); + + if (client.getGameState() == GameState.LOGGED_IN) + { + clientThread.invoke(this::checkHealthIcon); + } } @Override @@ -117,64 +139,87 @@ public class PoisonPlugin extends Plugin poisonNaturalCure = null; nextPoisonTick = null; lastValue = -1; + lastDiseaseValue = -1; + clientThread.invoke(this::resetHealthIcon); } @Subscribe public void onVarbitChanged(VarbitChanged event) { final int poisonValue = client.getVar(VarPlayer.POISON); - if (poisonValue == lastValue) + if (poisonValue != lastValue) { - return; - } + lastValue = poisonValue; + nextPoisonTick = Instant.now().plus(Duration.of(POISON_TICK_MILLIS, ChronoUnit.MILLIS)); - lastValue = poisonValue; - nextPoisonTick = Instant.now().plus(Duration.of(POISON_TICK_MILLIS, ChronoUnit.MILLIS)); + final int damage = nextDamage(poisonValue); + this.lastDamage = damage; - final int damage = nextDamage(poisonValue); - this.lastDamage = damage; + envenomed = poisonValue >= VENOM_THRESHOLD; - envenomed = poisonValue >= VENOM_THRESHOLD; - - if (poisonValue < VENOM_THRESHOLD) - { - poisonNaturalCure = Instant.now().plus(Duration.of(POISON_TICK_MILLIS * poisonValue, ChronoUnit.MILLIS)); - } - else - { - poisonNaturalCure = null; - } - - if (config.showInfoboxes()) - { - if (infobox != null) + if (poisonValue < VENOM_THRESHOLD) { - infoBoxManager.removeInfoBox(infobox); - infobox = null; + poisonNaturalCure = Instant.now().plus(Duration.of(POISON_TICK_MILLIS * poisonValue, ChronoUnit.MILLIS)); + } + else + { + poisonNaturalCure = null; } - if (damage > 0) + if (config.showInfoboxes()) { - final BufferedImage image = getSplat(envenomed ? SpriteID.HITSPLAT_DARK_GREEN_VENOM : SpriteID.HITSPLAT_GREEN_POISON, damage); - - if (image != null) + if (infobox != null) { - infobox = new PoisonInfobox(image, this); - infoBoxManager.addInfoBox(infobox); + infoBoxManager.removeInfoBox(infobox); + infobox = null; + } + + if (damage > 0) + { + final BufferedImage image = getSplat(envenomed ? SpriteID.HITSPLAT_DARK_GREEN_VENOM : SpriteID.HITSPLAT_GREEN_POISON, damage); + + if (image != null) + { + infobox = new PoisonInfobox(image, this); + infoBoxManager.addInfoBox(infobox); + } } } + + checkHealthIcon(); + } + + final int diseaseValue = client.getVar(VarPlayer.DISEASE_VALUE); + if (diseaseValue != lastDiseaseValue) + { + lastDiseaseValue = diseaseValue; + checkHealthIcon(); } } @Subscribe public void onConfigChanged(ConfigChanged event) { - if (event.getGroup().equals(PoisonConfig.GROUP) && !config.showInfoboxes() && infobox != null) + if (!event.getGroup().equals(PoisonConfig.GROUP)) + { + return; + } + + if (!config.showInfoboxes() && infobox != null) { infoBoxManager.removeInfoBox(infobox); infobox = null; } + + if (config.changeHealthIcon()) + { + clientThread.invoke(this::checkHealthIcon); + } + else + { + clientThread.invoke(this::resetHealthIcon); + } } private static int nextDamage(int poisonValue) @@ -250,4 +295,53 @@ public class PoisonPlugin extends Plugin return line1 + line2; } + + private void checkHealthIcon() + { + if (!config.changeHealthIcon()) + { + return; + } + + final BufferedImage newHeart; + final int poison = client.getVar(VarPlayer.IS_POISONED); + + if (poison >= VENOM_THRESHOLD) + { + newHeart = HEART_VENOM; + } + else if (poison > 0) + { + newHeart = HEART_POISON; + } + else if (client.getVar(VarPlayer.DISEASE_VALUE) > 0) + { + newHeart = HEART_DISEASE; + } + else + { + resetHealthIcon(); + return; + } + + // Only update sprites when the heart icon actually changes + if (newHeart != heart) + { + heart = newHeart; + client.getWidgetSpriteCache().reset(); + client.getSpriteOverrides().put(SpriteID.MINIMAP_ORB_HITPOINTS_ICON, ImageUtil.getImageSpritePixels(heart, client)); + } + } + + private void resetHealthIcon() + { + if (heart == null) + { + return; + } + + client.getWidgetSpriteCache().reset(); + client.getSpriteOverrides().remove(SpriteID.MINIMAP_ORB_HITPOINTS_ICON); + heart = null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/poison/1067-DISEASE.png b/runelite-client/src/main/resources/net/runelite/client/plugins/poison/1067-DISEASE.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ff5ac911aafdd5efdebda94d62098d226a1eb2 GIT binary patch literal 2991 zcmV;g3sCflP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0002mNklIq7* zIMl_&wkB482)yv}y`Q|72ws{^`Xv>GG8b(*S0#6wF@+!CMF-Mb$(A>;UfeZ!zI1?o z8OmG;1rFv*0J75&CzGVNnpp#eYtqF5DEvStRXiFBy=-y;yy!rd#1wu&FNyh8t_qw? z;zg2w-OQS+^h5aHX`*%YICp^Fo7SiselbM!m7a3 lf9Smlw8G8LU;+W20|4(PYp5iOkT(DT002ovPDHLkV1fjkjR^n% literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/poison/1067-POISON.png b/runelite-client/src/main/resources/net/runelite/client/plugins/poison/1067-POISON.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b05c1ca1c413f92f9e3f421500aafcfdc15016 GIT binary patch literal 2992 zcmV;h3s3ZkP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0002nNkl-L=rrxSK(vZZ69}!OjcWOsxsZD=9!LtLl<%;5{VEF```MCnct^>F# zi*g|~I2$hjNDm>&D25lHuD*W-Tx9`xc2F6*?u|rsOp*ZGaz%Ow@$7)~5`sl5NnIpX zOj5?JL1=NcI4Ywj^t6YY;wN~YG@SNbvM3kw-?Wcpo$h>DPd)Vw{??!g{D7Mpn7~F@ mH@LqdjGz&&e}*Oy;5Go2@ME3bOWqIw0000KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0002hNkl+)kPyLB(JD5)s3~eO=1FTV_G?m^an>iyttC3*fOb1|U~st;5u2u{g|y&i zz5}3AIc1{WfWGuHBqBBeKq@n5*jXeKw}vDE&iX{9a#ER5bvX!rlC(o96s1-_g8;$U z0ds2yJz;OVJIqGG;Bp5bylR@F7V_V=k7nEc?RomGZ}7JOANT?L0){{@Yy Date: Sun, 24 Feb 2019 14:21:42 -0500 Subject: [PATCH 096/102] api: add RS Enum API --- .../main/java/net/runelite/api/Client.java | 2 + .../net/runelite/api/EnumComposition.java | 36 +++++++++ .../net/runelite/mixins/RSClientMixin.java | 26 +++++++ .../java/net/runelite/mixins/RSEnumMixin.java | 75 +++++++++++++++++++ .../java/net/runelite/rs/api/RSClient.java | 3 + .../main/java/net/runelite/rs/api/RSEnum.java | 48 ++++++++++++ 6 files changed, 190 insertions(+) create mode 100644 runelite-api/src/main/java/net/runelite/api/EnumComposition.java create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/RSEnumMixin.java create mode 100644 runescape-api/src/main/java/net/runelite/rs/api/RSEnum.java diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index a410eb96a6..3fb789cf26 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1579,4 +1579,6 @@ public interface Client extends GameEngine * Returns client item composition cache */ NodeCache getItemCompositionCache(); + + EnumComposition getEnum(int id); } diff --git a/runelite-api/src/main/java/net/runelite/api/EnumComposition.java b/runelite-api/src/main/java/net/runelite/api/EnumComposition.java new file mode 100644 index 0000000000..7bbfaa1693 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/EnumComposition.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019, Adam + * 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.api; + +public interface EnumComposition +{ + int[] getIntVals(); + + String[] getStringVals(); + + int getIntValue(int key); + + String getStringValue(int key); +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 122811ee37..d162081476 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -24,6 +24,8 @@ */ package net.runelite.mixins; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; @@ -32,6 +34,7 @@ import javax.annotation.Nullable; import javax.inject.Named; import net.runelite.api.ChatMessageType; import net.runelite.api.ClanMember; +import net.runelite.api.EnumComposition; import net.runelite.api.Friend; import net.runelite.api.GameState; import net.runelite.api.GrandExchangeOffer; @@ -106,6 +109,7 @@ import net.runelite.rs.api.RSChatLineBuffer; import net.runelite.rs.api.RSClanMemberManager; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSDeque; +import net.runelite.rs.api.RSEnum; import net.runelite.rs.api.RSFriendContainer; import net.runelite.rs.api.RSFriendManager; import net.runelite.rs.api.RSHashTable; @@ -176,6 +180,11 @@ public abstract class RSClientMixin implements RSClient @Inject static int skyboxColor; + @Inject + private final Cache enumCache = CacheBuilder.newBuilder() + .maximumSize(64) + .build(); + @Inject @Override public Callbacks getCallbacks() @@ -1442,4 +1451,21 @@ public abstract class RSClientMixin implements RSClient return false; } + + @Inject + @Override + public EnumComposition getEnum(int id) + { + assert isClientThread() : "getEnum must be called on client thread"; + + RSEnum rsEnum = enumCache.getIfPresent(id); + if (rsEnum != null) + { + return rsEnum; + } + + rsEnum = getRsEnum(id); + enumCache.put(id, rsEnum); + return rsEnum; + } } \ No newline at end of file diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSEnumMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSEnumMixin.java new file mode 100644 index 0000000000..06dd3ab2e8 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSEnumMixin.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019, Adam + * 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.mixins; + +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.rs.api.RSEnum; + +@Mixin(RSEnum.class) +public abstract class RSEnumMixin implements RSEnum +{ + @Inject + @Override + public int getIntValue(int key) + { + final int[] keys = getKeys(); + if (keys == null) + { + return getDefaultInt(); + } + + for (int i = 0; i < keys.length; ++i) + { + if (keys[i] == key) + { + final int[] values = getIntVals(); + return values[i]; + } + } + return getDefaultInt(); + } + + @Inject + @Override + public String getStringValue(int key) + { + final int[] keys = getKeys(); + if (keys == null) + { + return getDefaultString(); + } + + for (int i = 0; i < keys.length; ++i) + { + if (keys[i] == key) + { + final String[] values = getStringVals(); + return values[i]; + } + } + return getDefaultString(); + } +} diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index 587eceb6e1..654e0048ea 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -929,4 +929,7 @@ public interface RSClient extends RSGameEngine, Client @Import("spellSelected") @Override void setSpellSelected(boolean selected); + + @Import("getEnum") + RSEnum getRsEnum(int id); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSEnum.java b/runescape-api/src/main/java/net/runelite/rs/api/RSEnum.java new file mode 100644 index 0000000000..d1a5273e5b --- /dev/null +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSEnum.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, Adam + * 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.rs.api; + +import net.runelite.api.EnumComposition; +import net.runelite.mapping.Import; + +public interface RSEnum extends EnumComposition, RSCacheableNode +{ + @Import("keys") + int[] getKeys(); + + @Import("intVals") + @Override + int[] getIntVals(); + + @Import("stringVals") + @Override + String[] getStringVals(); + + @Import("defaultInt") + int getDefaultInt(); + + @Import("defaultString") + String getDefaultString(); +} From 5cdb642815c322888434b2c4b857ee55c55140a3 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 25 Feb 2019 16:52:36 -0500 Subject: [PATCH 097/102] client: fix indenting of getItemCompositionCache javadoc --- runelite-api/src/main/java/net/runelite/api/Client.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 3fb789cf26..4c44c7e3ef 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1576,7 +1576,7 @@ public interface Client extends GameEngine void setSpellSelected(boolean selected); /** - * Returns client item composition cache + * Returns client item composition cache */ NodeCache getItemCompositionCache(); From 01bfb8af197f01beee14ecb1093747f211fc492f Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 24 Feb 2019 20:13:11 -0500 Subject: [PATCH 098/102] Revert "Clear stored npcs in fishing/pc/rc plugins" This reverts commit 7eeb484c648c95f84505b039fd33ad18bf9c55d6. --- .../client/plugins/fishing/FishingPlugin.java | 11 ----------- .../plugins/pestcontrol/PestControlPlugin.java | 13 +------------ .../client/plugins/runecraft/RunecraftPlugin.java | 1 - 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java index 07977334e4..592f706455 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java @@ -50,7 +50,6 @@ import net.runelite.api.NPC; import net.runelite.api.Varbits; import net.runelite.api.coords.LocalPoint; import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.InteractingChanged; import net.runelite.api.events.ItemContainerChanged; @@ -144,16 +143,6 @@ public class FishingPlugin extends Plugin currentSpot = null; } - @Subscribe - public void onGameStateChanged(GameStateChanged gameStateChanged) - { - if (gameStateChanged.getGameState() == GameState.LOADING) - { - fishingSpots.clear(); - minnowSpots.clear(); - } - } - @Subscribe public void onItemContainerChanged(ItemContainerChanged event) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java index 360e56f40d..7407c5f301 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java @@ -35,14 +35,12 @@ import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; -import net.runelite.api.GameState; import net.runelite.api.NPC; import net.runelite.api.NpcID; import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.GameStateChanged; +import net.runelite.client.eventbus.Subscribe; import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; -import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; @@ -89,15 +87,6 @@ public class PestControlPlugin extends Plugin spinners.clear(); } - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOADING) - { - spinners.clear(); - } - } - @Subscribe public void onChatMessage(ChatMessage chatMessage) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java index 14b53f9995..7f0cef2d94 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java @@ -232,7 +232,6 @@ public class RunecraftPlugin extends Plugin if (event.getGameState() == GameState.LOADING) { abyssObjects.clear(); - darkMage = null; } } From 0821cf216d43265188f4408be29e64f83bc6c286 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 24 Feb 2019 20:18:31 -0500 Subject: [PATCH 099/102] Clear stored npcs in fishing/pc/rc plugins Fixes #5970 This was originally attempted in 7eeb484c648c95f84505b039fd33ad18bf9c55d6 but NPCs are not automatically despawned from a scene change, which causes eg. the fishing plugin to lose fishing spots that are in view during a scene change. --- .../client/plugins/fishing/FishingPlugin.java | 12 ++++++++++++ .../plugins/pestcontrol/PestControlPlugin.java | 14 +++++++++++++- .../client/plugins/runecraft/RunecraftPlugin.java | 12 ++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java index 592f706455..8da48d7cdc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java @@ -50,6 +50,7 @@ import net.runelite.api.NPC; import net.runelite.api.Varbits; import net.runelite.api.coords.LocalPoint; import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.InteractingChanged; import net.runelite.api.events.ItemContainerChanged; @@ -143,6 +144,17 @@ public class FishingPlugin extends Plugin currentSpot = null; } + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + GameState gameState = gameStateChanged.getGameState(); + if (gameState == GameState.CONNECTION_LOST || gameState == GameState.LOGIN_SCREEN || gameState == GameState.HOPPING) + { + fishingSpots.clear(); + minnowSpots.clear(); + } + } + @Subscribe public void onItemContainerChanged(ItemContainerChanged event) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java index 7407c5f301..7e711e66a0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/PestControlPlugin.java @@ -35,12 +35,14 @@ import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; +import net.runelite.api.GameState; import net.runelite.api.NPC; import net.runelite.api.NpcID; import net.runelite.api.events.ChatMessage; -import net.runelite.client.eventbus.Subscribe; +import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; +import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; @@ -87,6 +89,16 @@ public class PestControlPlugin extends Plugin spinners.clear(); } + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + GameState gameState = event.getGameState(); + if (gameState == GameState.CONNECTION_LOST || gameState == GameState.LOGIN_SCREEN || gameState == GameState.HOPPING) + { + spinners.clear(); + } + } + @Subscribe public void onChatMessage(ChatMessage chatMessage) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java index 7f0cef2d94..4662b95d5a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java @@ -229,9 +229,17 @@ public class RunecraftPlugin extends Plugin @Subscribe public void onGameStateChanged(GameStateChanged event) { - if (event.getGameState() == GameState.LOADING) + GameState gameState = event.getGameState(); + switch (gameState) { - abyssObjects.clear(); + case LOADING: + abyssObjects.clear(); + break; + case CONNECTION_LOST: + case HOPPING: + case LOGIN_SCREEN: + darkMage = null; + break; } } From 81b98c18960c8afcfb20fe3469da5ced66ef4528 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 25 Feb 2019 09:33:17 -0500 Subject: [PATCH 100/102] Revert "Clear Cerberus ghost on LOADING game state" This reverts commit b99c8d748083ebfbf8eecc7e399ce9a0d29d5aaf. --- .../net/runelite/client/plugins/cerberus/CerberusPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java index 322e8c38cd..2087e31844 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java @@ -75,7 +75,7 @@ public class CerberusPlugin extends Plugin @Subscribe public void onGameStateChanged(GameStateChanged event) { - if (event.getGameState() == GameState.LOADING) + if (event.getGameState() == GameState.LOGIN_SCREEN || event.getGameState() == GameState.HOPPING) { ghosts.clear(); } From 1dee0120becb956b9b101949b3cf288ee339533e Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 25 Feb 2019 09:44:39 -0500 Subject: [PATCH 101/102] cerb plugin: clear ghosts on connection lost too --- .../net/runelite/client/plugins/cerberus/CerberusPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java index 2087e31844..47f1adbec4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cerberus/CerberusPlugin.java @@ -75,7 +75,8 @@ public class CerberusPlugin extends Plugin @Subscribe public void onGameStateChanged(GameStateChanged event) { - if (event.getGameState() == GameState.LOGIN_SCREEN || event.getGameState() == GameState.HOPPING) + GameState gameState = event.getGameState(); + if (gameState == GameState.LOGIN_SCREEN || gameState == GameState.HOPPING || gameState == GameState.CONNECTION_LOST) { ghosts.clear(); } From b86061dc80e2e122b87206d9072cf8421ffce056 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 25 Feb 2019 17:38:01 -0500 Subject: [PATCH 102/102] http service: remove ws service This has been unused now for a few releases --- .../http/service/account/AccountService.java | 14 --- .../http/service/ws/SessionManager.java | 67 ------------ .../runelite/http/service/ws/WSService.java | 100 ------------------ 3 files changed, 181 deletions(-) delete mode 100644 http-service/src/main/java/net/runelite/http/service/ws/SessionManager.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/ws/WSService.java diff --git a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java b/http-service/src/main/java/net/runelite/http/service/account/AccountService.java index 3ef3a98659..c78a25b9ff 100644 --- a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java +++ b/http-service/src/main/java/net/runelite/http/service/account/AccountService.java @@ -45,8 +45,6 @@ import net.runelite.http.api.ws.messages.LoginResponse; import net.runelite.http.service.account.beans.SessionEntry; import net.runelite.http.service.account.beans.UserEntry; import net.runelite.http.service.util.redis.RedisPool; -import net.runelite.http.service.ws.SessionManager; -import net.runelite.http.service.ws.WSService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -241,12 +239,6 @@ public class AccountService LoginResponse response = new LoginResponse(); response.setUsername(username); - WSService service = SessionManager.findSession(uuid); - if (service != null) - { - service.send(response); - } - try (Jedis jedis = jedisPool.getResource()) { jedis.publish("session." + uuid, websocketGson.toJson(response, WebsocketMessage.class)); @@ -276,10 +268,4 @@ public class AccountService { auth.handle(request, response); } - - @RequestMapping("/wscount") - public int wscount() - { - return SessionManager.getCount(); - } } diff --git a/http-service/src/main/java/net/runelite/http/service/ws/SessionManager.java b/http-service/src/main/java/net/runelite/http/service/ws/SessionManager.java deleted file mode 100644 index 815ab911e8..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ws/SessionManager.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * 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.http.service.ws; - -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public class SessionManager -{ - private static final ConcurrentMap sessions = new ConcurrentHashMap<>(); - - public static void changeSessionUID(WSService service, UUID uuid) - { - synchronized (service) - { - remove(service); - service.setUuid(uuid); - sessions.put(uuid, service); - } - } - - static void remove(WSService service) - { - synchronized (service) - { - UUID current = service.getUuid(); - if (current != null) - { - sessions.remove(current); - service.setUuid(null); - } - } - } - - public static WSService findSession(UUID uuid) - { - return sessions.get(uuid); - } - - public static int getCount() - { - return sessions.size(); - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/ws/WSService.java b/http-service/src/main/java/net/runelite/http/service/ws/WSService.java deleted file mode 100644 index 05489f2b87..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/ws/WSService.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * 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.http.service.ws; - -import com.google.gson.Gson; -import java.util.UUID; -import javax.websocket.CloseReason; -import javax.websocket.EndpointConfig; -import javax.websocket.OnClose; -import javax.websocket.OnError; -import javax.websocket.OnMessage; -import javax.websocket.OnOpen; -import javax.websocket.Session; -import javax.websocket.server.ServerEndpoint; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import net.runelite.http.api.ws.WebsocketGsonFactory; -import net.runelite.http.api.ws.WebsocketMessage; -import net.runelite.http.api.ws.messages.Handshake; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ServerEndpoint("/ws") -public class WSService -{ - private static final Logger logger = LoggerFactory.getLogger(WSService.class); - - private static final Gson gson = WebsocketGsonFactory.build(); - - private Session session; - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private UUID uuid; - - public void send(WebsocketMessage message) - { - String json = gson.toJson(message, WebsocketMessage.class); - - logger.debug("Sending {}", json); - - session.getAsyncRemote().sendText(json); - } - - @OnOpen - public void onOpen(Session session, EndpointConfig config) - { - this.session = session; - logger.debug("New session {}", session); - } - - @OnClose - public void onClose(Session session, CloseReason resaon) - { - SessionManager.remove(this); - logger.debug("Close session {}", session); - } - - @OnError - public void onError(Session session, Throwable ex) - { - SessionManager.remove(this); - logger.debug("Error in session {}", session, ex); - } - - @OnMessage - public void onMessage(Session session, String text) - { - WebsocketMessage message = gson.fromJson(text, WebsocketMessage.class); - logger.debug("Got message: {}", message); - - if (message instanceof Handshake) - { - Handshake hs = (Handshake) message; - SessionManager.changeSessionUID(this, hs.getSession()); - } - } -}