From 34c685a82d73a906d18347c756db94a4cbb7e17a Mon Sep 17 00:00:00 2001 From: Max Weber Date: Tue, 27 Aug 2019 13:32:46 -0600 Subject: [PATCH 01/45] runelite-api: Add setAllWidgetsAreOpTargetable --- .../src/main/java/net/runelite/api/Client.java | 11 +++++++++++ .../src/main/java/net/runelite/api/MenuAction.java | 5 +++++ 2 files changed, 16 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 56e2995e32..31e7c8afe1 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -38,6 +38,7 @@ import net.runelite.api.hooks.Callbacks; import net.runelite.api.hooks.DrawCallbacks; import net.runelite.api.vars.AccountType; import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetConfig; import net.runelite.api.widgets.WidgetInfo; import org.slf4j.Logger; @@ -1635,6 +1636,11 @@ public interface Client extends GameEngine */ int getIf1DraggedItemIndex(); + /** + * Is a widget is in target mode? + */ + boolean getSpellSelected(); + /** * Sets if a widget is in target mode */ @@ -1660,4 +1666,9 @@ public interface Client extends GameEngine * Returns the max item index + 1 from cache */ int getItemCount(); + + /** + * Makes all widgets behave as if they are {@link WidgetConfig#WIDGET_USE_TARGET} + */ + void setAllWidgetsAreOpTargetable(boolean value); } diff --git a/runelite-api/src/main/java/net/runelite/api/MenuAction.java b/runelite-api/src/main/java/net/runelite/api/MenuAction.java index cafbbe7706..688b18f141 100644 --- a/runelite-api/src/main/java/net/runelite/api/MenuAction.java +++ b/runelite-api/src/main/java/net/runelite/api/MenuAction.java @@ -230,6 +230,11 @@ public enum MenuAction */ WIDGET_DEFAULT(57), + /** + * Casting a spell / op target on a widget + */ + SPELL_CAST_ON_WIDGET(58), + /** * Menu action triggered by examining an object. */ From c6632af7bf2c21cac0e9e02a5c12d4bff85f589f Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 26 Aug 2019 18:46:28 -0600 Subject: [PATCH 02/45] runelite-client: Don't add our menu options in spell casting/target mode --- .../src/main/java/net/runelite/client/menus/MenuManager.java | 5 +++++ .../java/net/runelite/client/ui/overlay/OverlayRenderer.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java index 955c3ef0e5..863e58ea10 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java @@ -117,6 +117,11 @@ public class MenuManager @Subscribe public void onMenuEntryAdded(MenuEntryAdded event) { + if (client.getSpellSelected()) + { + return; + } + int widgetId = event.getActionParam1(); Collection options = managedMenuOptions.get(widgetId); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index e0810cef00..81b405fe83 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -304,7 +304,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener graphics.setColor(previous); } - if (menuEntries == null && !client.isMenuOpen() && bounds.contains(mouse)) + if (menuEntries == null && !client.isMenuOpen() && !client.getSpellSelected() && bounds.contains(mouse)) { menuEntries = createRightClickMenuEntries(overlay); } From 33d233d9a59bf1f6be0760e770708860e5e1ae99 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Tue, 27 Aug 2019 19:46:52 -0600 Subject: [PATCH 03/45] WidgetInspector: Add widget picker --- .../main/java/net/runelite/api/SpriteID.java | 1 + .../plugins/devtools/DevToolsOverlay.java | 78 ----- .../plugins/devtools/WidgetInspector.java | 323 ++++++++++++++++-- .../devtools/WidgetInspectorOverlay.java | 132 +++++++ 4 files changed, 431 insertions(+), 103 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspectorOverlay.java 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 35419da483..962089c146 100644 --- a/runelite-api/src/main/java/net/runelite/api/SpriteID.java +++ b/runelite-api/src/main/java/net/runelite/api/SpriteID.java @@ -1564,6 +1564,7 @@ public final class SpriteID public static final int MOBILE_FUNCTION_MODE_DISABLED = 1624; public static final int MOBILE_YELLOW_TOUCH_ANIMATION_1 = 1625; public static final int MOBILE_YELLOW_TOUCH_ANIMATION_2 = 1626; + public static final int MOBILE_FINGER_ON_INTERFACE = 1653; /* Unmapped: 1627~1701 */ public static final int BUTTON_FRIENDS = 1702; public static final int BUTTON_IGNORES = 1703; 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 9bb7292dc3..457a86b766 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 @@ -36,8 +36,6 @@ import java.awt.geom.Rectangle2D; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; -import lombok.Getter; -import lombok.Setter; import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.DecorativeObject; @@ -72,9 +70,6 @@ import net.runelite.client.ui.overlay.tooltip.TooltipManager; @Singleton class DevToolsOverlay extends Overlay { - private static final int ITEM_EMPTY = 6512; - private static final int ITEM_FILLED = 20594; - private static final Font FONT = FontManager.getRunescapeFont().deriveFont(Font.BOLD, 16); private static final Color RED = new Color(221, 44, 0); private static final Color GREEN = new Color(0, 200, 83); @@ -92,13 +87,6 @@ class DevToolsOverlay extends Overlay private final DevToolsPlugin plugin; private final TooltipManager toolTipManager; - @Setter - @Getter - private Widget widget; - - @Setter - private int itemIndex = -1; - @Inject private DevToolsOverlay(Client client, DevToolsPlugin plugin, TooltipManager toolTipManager) { @@ -145,8 +133,6 @@ class DevToolsOverlay extends Overlay renderGraphicsObjects(graphics); } - renderWidgets(graphics); - return null; } @@ -430,70 +416,6 @@ class DevToolsOverlay extends Overlay } } - private void renderWidgets(Graphics2D graphics) - { - if (widget == null || widget.isHidden()) - { - return; - } - - Rectangle childBounds = widget.getBounds(); - graphics.setColor(CYAN); - graphics.draw(childBounds); - - if (itemIndex == -1) - { - return; - } - - if (widget.getItemId() != ITEM_EMPTY - && widget.getItemId() != ITEM_FILLED) - { - Rectangle componentBounds = widget.getBounds(); - - graphics.setColor(ORANGE); - graphics.draw(componentBounds); - - renderWidgetText(graphics, componentBounds, widget.getItemId(), YELLOW); - } - - WidgetItem widgetItem = widget.getWidgetItem(itemIndex); - if (widgetItem == null - || widgetItem.getId() < 0 - || widgetItem.getId() == ITEM_EMPTY - || widgetItem.getId() == ITEM_FILLED) - { - return; - } - - Rectangle itemBounds = widgetItem.getCanvasBounds(); - - graphics.setColor(ORANGE); - graphics.draw(itemBounds); - - renderWidgetText(graphics, itemBounds, widgetItem.getId(), YELLOW); - } - - private void renderWidgetText(Graphics2D graphics, Rectangle bounds, int itemId, Color color) - { - if (itemId == -1) - { - return; - } - - String text = itemId + ""; - FontMetrics fm = graphics.getFontMetrics(); - Rectangle2D textBounds = fm.getStringBounds(text, graphics); - - int textX = (int) (bounds.getX() + (bounds.getWidth() / 2) - (textBounds.getWidth() / 2)); - int textY = (int) (bounds.getY() + (bounds.getHeight() / 2) + (textBounds.getHeight() / 2)); - - graphics.setColor(Color.BLACK); - graphics.drawString(text, textX + 1, textY + 1); - graphics.setColor(color); - graphics.drawString(text, textX, textY); - } - private void renderPlayerWireframe(Graphics2D graphics, Player player, Color color) { Polygon[] polys = player.getPolygons(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java index cea9a2b9c1..44839a52de 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java @@ -27,13 +27,20 @@ package net.runelite.client.plugins.devtools; import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Dimension; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Collection; +import java.util.Comparator; +import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import java.util.Stack; +import java.util.stream.Stream; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; @@ -45,31 +52,68 @@ import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.SpriteID; import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.MenuOptionClicked; +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.WidgetItem; +import net.runelite.api.widgets.WidgetType; import net.runelite.client.callback.ClientThread; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.ClientUI; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.ColorUtil; @Slf4j +@Singleton class WidgetInspector extends JFrame { + private static final Map widgetIdMap = new HashMap<>(); + + static final Color SELECTED_WIDGET_COLOR = Color.CYAN; + private static final float SELECTED_WIDGET_HUE; + + static + { + float[] hsb = new float[3]; + Color.RGBtoHSB(SELECTED_WIDGET_COLOR.getRed(), SELECTED_WIDGET_COLOR.getGreen(), SELECTED_WIDGET_COLOR.getBlue(), hsb); + SELECTED_WIDGET_HUE = hsb[0]; + } + private final Client client; private final ClientThread clientThread; private final DevToolsConfig config; - private final DevToolsOverlay overlay; - private final DevToolsPlugin plugin; + private final Provider overlay; + private final OverlayManager overlayManager; private final JTree widgetTree; private final WidgetInfoTableModel infoTableModel; private final JCheckBox alwaysOnTop; + private final JCheckBox hideHidden; - private static final Map widgetIdMap = new HashMap<>(); + private DefaultMutableTreeNode root; + + @Getter + private Widget selectedWidget; + + @Getter + private int selectedItem; + + private Widget picker = null; + + @Getter + private boolean pickerSelected = false; @Inject private WidgetInspector( @@ -77,16 +121,17 @@ class WidgetInspector extends JFrame ClientThread clientThread, WidgetInfoTableModel infoTableModel, DevToolsConfig config, + DevToolsPlugin plugin, EventBus eventBus, - DevToolsOverlay overlay, - DevToolsPlugin plugin) + Provider overlay, + OverlayManager overlayManager) { this.client = client; this.clientThread = clientThread; this.infoTableModel = infoTableModel; this.config = config; this.overlay = overlay; - this.plugin = plugin; + this.overlayManager = overlayManager; eventBus.register(this); @@ -116,16 +161,12 @@ class WidgetInspector extends JFrame { WidgetTreeNode node = (WidgetTreeNode) selected; Widget widget = node.getWidget(); - overlay.setWidget(widget); - overlay.setItemIndex(widget.getItemId()); - refreshInfo(); - log.debug("Set widget to {} and item index to {}", widget, widget.getItemId()); + setSelectedWidget(widget, -1, false); } else if (selected instanceof WidgetItemNode) { WidgetItemNode node = (WidgetItemNode) selected; - overlay.setItemIndex(node.getWidgetItem().getIndex()); - log.debug("Set item index to {}", node.getWidgetItem().getIndex()); + setSelectedWidget(node.getWidgetItem().getWidget(), node.getWidgetItem().getIndex(), false); } }); @@ -151,15 +192,20 @@ class WidgetInspector extends JFrame onConfigChanged(null); bottomPanel.add(alwaysOnTop); + hideHidden = new JCheckBox("Hide hidden"); + hideHidden.setSelected(true); + hideHidden.addItemListener(ev -> refreshWidgets()); + bottomPanel.add(hideHidden); + final JButton revalidateWidget = new JButton("Revalidate"); revalidateWidget.addActionListener(ev -> clientThread.invokeLater(() -> { - if (overlay.getWidget() == null) + if (selectedWidget == null) { return; } - overlay.getWidget().revalidate(); + selectedWidget.revalidate(); })); bottomPanel.add(revalidateWidget); @@ -182,10 +228,13 @@ class WidgetInspector extends JFrame clientThread.invokeLater(() -> { Widget[] rootWidgets = client.getWidgetRoots(); - DefaultMutableTreeNode root = new DefaultMutableTreeNode(); + root = new DefaultMutableTreeNode(); - overlay.setWidget(null); - overlay.setItemIndex(-1); + Widget wasSelectedWidget = selectedWidget; + int wasSelectedItem = selectedItem; + + selectedWidget = null; + selectedItem = -1; for (Widget widget : rootWidgets) { @@ -198,17 +247,15 @@ class WidgetInspector extends JFrame SwingUtilities.invokeLater(() -> { - overlay.setWidget(null); - overlay.setItemIndex(-1); - refreshInfo(); widgetTree.setModel(new DefaultTreeModel(root)); + setSelectedWidget(wasSelectedWidget, wasSelectedItem, true); }); }); } private DefaultMutableTreeNode addWidget(String type, Widget widget) { - if (widget == null || widget.isHidden()) + if (widget == null || (hideHidden.isSelected() && widget.isHidden())) { return null; } @@ -271,9 +318,70 @@ class WidgetInspector extends JFrame return node; } - private void refreshInfo() + private void setSelectedWidget(Widget widget, int item, boolean updateTree) { - infoTableModel.setWidget(overlay.getWidget()); + infoTableModel.setWidget(widget); + + if (this.selectedWidget == widget && this.selectedItem == item) + { + return; + } + + this.selectedWidget = widget; + this.selectedItem = item; + + if (root == null || !updateTree) + { + return; + } + + clientThread.invoke(() -> + { + Stack treePath = new Stack<>(); + for (Widget w = widget; w != null; w = w.getParent()) + { + treePath.push(w); + } + + DefaultMutableTreeNode node = root; + deeper: + for (; !treePath.empty(); ) + { + Widget w = treePath.pop(); + for (Enumeration it = node.children(); it.hasMoreElements(); ) + { + WidgetTreeNode inner = (WidgetTreeNode) it.nextElement(); + if (inner.getWidget().getId() == w.getId() && inner.getWidget().getIndex() == w.getIndex()) + { + node = inner; + continue deeper; + } + } + } + if (selectedItem != -1) + { + for (Enumeration it = node.children(); it.hasMoreElements(); ) + { + Object wiw = it.nextElement(); + if (wiw instanceof WidgetItemNode) + { + WidgetItemNode inner = (WidgetItemNode) wiw; + if (inner.getWidgetItem().getIndex() == selectedItem) + { + node = inner; + break; + } + } + } + } + + final DefaultMutableTreeNode fnode = node; + SwingUtilities.invokeLater(() -> + { + widgetTree.getSelectionModel().clearSelection(); + widgetTree.getSelectionModel().addSelectionPath(new TreePath(fnode.getPath())); + }); + }); } static WidgetInfo getWidgetInfo(int packedId) @@ -297,12 +405,177 @@ class WidgetInspector extends JFrame setVisible(true); toFront(); repaint(); + overlayManager.add(this.overlay.get()); + clientThread.invokeLater(this::addPickerWidget); } public void close() { - overlay.setWidget(null); - overlay.setItemIndex(-1); + overlayManager.remove(this.overlay.get()); + clientThread.invokeLater(this::removePickerWidget); + setSelectedWidget(null, -1, false); setVisible(false); } + + private void removePickerWidget() + { + if (picker == null) + { + return; + } + + Widget parent = picker.getParent(); + if (parent == null) + { + return; + } + + Widget[] children = parent.getChildren(); + if (children == null || children.length <= picker.getIndex() || children[picker.getIndex()] != picker) + { + return; + } + + children[picker.getIndex()] = null; + } + + private void addPickerWidget() + { + removePickerWidget(); + + int x = 10, y = 2; + Widget parent = client.getWidget(WidgetInfo.MINIMAP_ORBS); + if (parent == null) + { + Widget[] roots = client.getWidgetRoots(); + + parent = Stream.of(roots) + .filter(w -> w.getType() == WidgetType.LAYER && w.getContentType() == 0 && !w.isSelfHidden()) + .sorted(Comparator.comparing((Widget w) -> w.getRelativeX() + w.getRelativeY()) + .reversed() + .thenComparing(Widget::getId) + .reversed()) + .findFirst().get(); + x = 4; + y = 4; + } + + picker = parent.createChild(-1, WidgetType.GRAPHIC); + + log.info("Picker is {}.{} [{}]", WidgetInfo.TO_GROUP(picker.getId()), WidgetInfo.TO_CHILD(picker.getId()), picker.getIndex()); + + picker.setSpriteId(SpriteID.MOBILE_FINGER_ON_INTERFACE); + picker.setOriginalWidth(15); + picker.setOriginalHeight(17); + picker.setOriginalX(x); + picker.setOriginalY(y); + picker.revalidate(); + picker.setTargetVerb("Select"); + picker.setName("Pick"); + picker.setClickMask(WidgetConfig.USE_WIDGET | WidgetConfig.USE_ITEM); + picker.setNoClickThrough(true); + picker.setOnTargetEnterListener((JavaScriptCallback) ev -> + { + pickerSelected = true; + picker.setOpacity(30); + client.setAllWidgetsAreOpTargetable(true); + }); + picker.setOnTargetLeaveListener((JavaScriptCallback) ev -> onPickerDeselect()); + } + + private void onPickerDeselect() + { + client.setAllWidgetsAreOpTargetable(false); + picker.setOpacity(0); + pickerSelected = false; + } + + @Subscribe + private void onMenuOptionClicked(MenuOptionClicked ev) + { + if (!pickerSelected) + { + return; + } + + onPickerDeselect(); + client.setSpellSelected(false); + ev.consume(); + + Object target = getWidgetOrWidgetItemForMenuOption(ev.getMenuAction().getId(), ev.getActionParam(), ev.getWidgetId()); + if (target == null) + { + return; + } + if (target instanceof WidgetItem) + { + WidgetItem iw = (WidgetItem) target; + setSelectedWidget(iw.getWidget(), iw.getIndex(), true); + } + else + { + setSelectedWidget((Widget) target, -1, true); + } + } + + @Subscribe + private void onMenuEntryAdded(MenuEntryAdded event) + { + if (!pickerSelected) + { + return; + } + + MenuEntry[] menuEntries = client.getMenuEntries(); + + for (int i = 0; i < menuEntries.length; i++) + { + MenuEntry entry = menuEntries[i]; + if (entry.getType() != MenuAction.ITEM_USE_ON_WIDGET.getId() + && entry.getType() != MenuAction.SPELL_CAST_ON_WIDGET.getId()) + { + continue; + } + String name = WidgetInfo.TO_GROUP(entry.getParam1()) + "." + WidgetInfo.TO_CHILD(entry.getParam1()); + + if (entry.getParam0() != -1) + { + name += " [" + entry.getParam0() + "]"; + } + + Color color = colorForWidget(i, menuEntries.length); + + entry.setTarget(ColorUtil.wrapWithColorTag(name, color)); + } + + client.setMenuEntries(menuEntries); + } + + Color colorForWidget(int index, int length) + { + float h = SELECTED_WIDGET_HUE + .1f + (.8f / length) * index; + + return Color.getHSBColor(h, 1, 1); + } + + Object getWidgetOrWidgetItemForMenuOption(int type, int param0, int param1) + { + if (type == MenuAction.SPELL_CAST_ON_WIDGET.getId()) + { + Widget w = client.getWidget(WidgetInfo.TO_GROUP(param1), WidgetInfo.TO_CHILD(param1)); + if (param0 != -1) + { + w = w.getChild(param0); + } + + return w; + } + else if (type == MenuAction.ITEM_USE_ON_WIDGET.getId()) + { + Widget w = client.getWidget(WidgetInfo.TO_GROUP(param1), WidgetInfo.TO_CHILD(param1)); + return w.getWidgetItem(param0); + } + + return null; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspectorOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspectorOverlay.java new file mode 100644 index 0000000000..c0ceab94a8 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspectorOverlay.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018 Abex + * Copyright (c) 2017, Kronos + * 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.client.plugins.devtools; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import javax.inject.Inject; +import javax.inject.Singleton; +import net.runelite.api.Client; +import net.runelite.api.MenuEntry; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +@Singleton +public class WidgetInspectorOverlay extends Overlay +{ + private final Client client; + private final WidgetInspector inspector; + + @Inject + public WidgetInspectorOverlay( + Client client, + WidgetInspector inspector + ) + { + this.client = client; + this.inspector = inspector; + + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + setPriority(OverlayPriority.HIGHEST); + } + + @Override + public Dimension render(Graphics2D g) + { + Widget w = inspector.getSelectedWidget(); + if (w != null) + { + Object wiw = w; + if (inspector.getSelectedItem() != -1) + { + wiw = w.getWidgetItem(inspector.getSelectedItem()); + } + + renderWiw(g, wiw, WidgetInspector.SELECTED_WIDGET_COLOR); + } + + if (inspector.isPickerSelected()) + { + boolean menuOpen = client.isMenuOpen(); + + MenuEntry[] entries = client.getMenuEntries(); + for (int i = menuOpen ? 0 : entries.length - 1; i < entries.length; i++) + { + MenuEntry e = entries[i]; + + Object wiw = inspector.getWidgetOrWidgetItemForMenuOption(e.getType(), e.getParam0(), e.getParam1()); + if (wiw == null) + { + continue; + } + + Color color = inspector.colorForWidget(i, entries.length); + renderWiw(g, wiw, color); + } + } + + return null; + } + + private void renderWiw(Graphics2D g, Object wiw, Color color) + { + g.setColor(color); + + if (wiw instanceof WidgetItem) + { + WidgetItem wi = (WidgetItem) wiw; + Rectangle bounds = wi.getCanvasBounds(); + g.draw(bounds); + + String text = wi.getId() + ""; + FontMetrics fm = g.getFontMetrics(); + Rectangle2D textBounds = fm.getStringBounds(text, g); + + int textX = (int) (bounds.getX() + (bounds.getWidth() / 2) - (textBounds.getWidth() / 2)); + int textY = (int) (bounds.getY() + (bounds.getHeight() / 2) + (textBounds.getHeight() / 2)); + + g.setColor(Color.BLACK); + g.drawString(text, textX + 1, textY + 1); + g.setColor(Color.ORANGE); + g.drawString(text, textX, textY); + } + else + { + Widget w = (Widget) wiw; + g.draw(w.getBounds()); + } + } +} From b78bd73e9199bb36c5a6ba1e15f0004cf68b3d0c Mon Sep 17 00:00:00 2001 From: beaumitch Date: Wed, 18 Sep 2019 11:02:05 -0400 Subject: [PATCH 04/45] agility plugin: add laps to goal to overlay Add configuration option for laps til level --- .../client/plugins/agility/AgilityConfig.java | 38 +++++++++++++++---- .../plugins/agility/AgilitySession.java | 5 +++ .../plugins/agility/LapCounterOverlay.java | 10 ++++- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java index 655d0245a8..85608f9dbf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java @@ -54,11 +54,33 @@ public interface AgilityConfig extends Config return 5; } + @ConfigItem( + keyName = "lapsToLevel", + name = "Show Laps Until Level", + description = "Show number of laps remaining until next level is reached.", + position = 3 + ) + default boolean lapsToLevel() + { + return true; + } + + @ConfigItem( + keyName = "lapsToGoal", + name = "Show Laps Until Goal", + description = "Show number of laps remaining until experience tracker goal is reached", + position = 4 + ) + default boolean lapsToGoal() + { + return false; + } + @ConfigItem( keyName = "overlayColor", name = "Overlay Color", description = "Color of Agility overlay", - position = 3 + position = 5 ) default Color getOverlayColor() { @@ -69,7 +91,7 @@ public interface AgilityConfig extends Config keyName = "highlightMarks", name = "Highlight Marks of Grace", description = "Enable/disable the highlighting of retrievable Marks of Grace", - position = 4 + position = 6 ) default boolean highlightMarks() { @@ -80,7 +102,7 @@ public interface AgilityConfig extends Config keyName = "markHighlight", name = "Mark Highlight Color", description = "Color of highlighted Marks of Grace", - position = 5 + position = 7 ) default Color getMarkColor() { @@ -91,7 +113,7 @@ public interface AgilityConfig extends Config keyName = "highlightShortcuts", name = "Highlight Agility Shortcuts", description = "Enable/disable the highlighting of Agility shortcuts", - position = 6 + position = 8 ) default boolean highlightShortcuts() { @@ -102,7 +124,7 @@ public interface AgilityConfig extends Config keyName = "trapOverlay", name = "Show Trap Overlay", description = "Enable/disable the highlighting of traps on Agility courses", - position = 7 + position = 9 ) default boolean showTrapOverlay() { @@ -113,7 +135,7 @@ public interface AgilityConfig extends Config keyName = "trapHighlight", name = "Trap Overlay Color", description = "Color of Agility trap overlay", - position = 8 + position = 10 ) default Color getTrapColor() { @@ -124,7 +146,7 @@ public interface AgilityConfig extends Config keyName = "agilityArenaNotifier", name = "Agility Arena notifier", description = "Notify on ticket location change in Agility Arena", - position = 9 + position = 11 ) default boolean notifyAgilityArena() { @@ -135,7 +157,7 @@ public interface AgilityConfig extends Config keyName = "agilityArenaTimer", name = "Agility Arena timer", description = "Configures whether Agility Arena timer is displayed", - position = 10 + position = 12 ) default boolean showAgilityArenaTimer() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilitySession.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilitySession.java index a8ba2937ca..72e9a0dd07 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilitySession.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilitySession.java @@ -30,6 +30,7 @@ import lombok.Setter; import net.runelite.api.Client; import net.runelite.api.Experience; import net.runelite.api.Skill; +import net.runelite.api.VarPlayer; @Getter @Setter @@ -39,6 +40,7 @@ class AgilitySession private Instant lastLapCompleted; private int totalLaps; private int lapsTillLevel; + private int lapsTillGoal; AgilitySession(Courses course) { @@ -61,11 +63,14 @@ class AgilitySession } while (remainingXp < 0); lapsTillLevel = remainingXp > 0 ? (int) Math.ceil(remainingXp / course.getTotalXp()) : 0; + int goalRemainingXp = client.getVar(VarPlayer.AGILITY_GOAL_END) - currentExp; + lapsTillGoal = goalRemainingXp > 0 ? (int) Math.ceil(goalRemainingXp / course.getTotalXp()) : 0; } void resetLapCount() { totalLaps = 0; lapsTillLevel = 0; + lapsTillGoal = 0; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/LapCounterOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/LapCounterOverlay.java index b6da44d76a..a53f6bac4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/LapCounterOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/LapCounterOverlay.java @@ -85,7 +85,7 @@ class LapCounterOverlay extends Overlay .right(Integer.toString(session.getTotalLaps())) .build()); - if (session.getLapsTillLevel() > 0) + if (config.lapsToLevel() && session.getLapsTillLevel() > 0) { panelComponent.getChildren().add(LineComponent.builder() .left("Laps until level:") @@ -93,6 +93,14 @@ class LapCounterOverlay extends Overlay .build()); } + if (config.lapsToGoal() && session.getLapsTillGoal() > 0) + { + panelComponent.getChildren().add(LineComponent.builder() + .left("Laps until goal:") + .right(Integer.toString(session.getLapsTillGoal())) + .build()); + } + return panelComponent.render(graphics); } } From 10b55604fced843782489cfb2d5b2b7e35657d1f Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 17 Sep 2019 15:02:10 -0400 Subject: [PATCH 05/45] opponent info: add show opponents in menu --- .../opponentinfo/OpponentInfoConfig.java | 11 +++++++ .../opponentinfo/OpponentInfoPlugin.java | 29 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java index 07a84629c8..9f08e128af 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java @@ -63,4 +63,15 @@ public interface OpponentInfoConfig extends Config { return true; } + + @ConfigItem( + keyName = "showOpponentsInMenu", + name = "Show opponents in menu", + description = "Marks opponents names in the menu which you are attacking or are attacking you (NPC only)", + position = 3 + ) + default boolean showOpponentsInMenu() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java index 6e36665a8b..e038e81ab2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java @@ -35,10 +35,14 @@ import lombok.Getter; import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.GameState; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.NPC; import net.runelite.api.WorldType; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.InteractingChanged; +import net.runelite.api.events.MenuEntryAdded; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; @@ -159,4 +163,29 @@ public class OpponentInfoPlugin extends Plugin } } } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) + { + if (menuEntryAdded.getType() != MenuAction.NPC_SECOND_OPTION.getId() + || !menuEntryAdded.getOption().equals("Attack") + || !config.showOpponentsInMenu()) + { + return; + } + + int npcIndex = menuEntryAdded.getIdentifier(); + NPC npc = client.getCachedNPCs()[npcIndex]; + if (npc == null) + { + return; + } + + if (npc.getInteracting() == client.getLocalPlayer() || lastOpponent == npc) + { + MenuEntry[] menuEntries = client.getMenuEntries(); + menuEntries[menuEntries.length - 1].setTarget("*" + menuEntryAdded.getTarget()); + client.setMenuEntries(menuEntries); + } + } } From e842c5c90e9ee35e6a5c4a49e2815f5ef2b50a24 Mon Sep 17 00:00:00 2001 From: Hudson Shykowski Date: Thu, 19 Sep 2019 21:49:42 -0600 Subject: [PATCH 06/45] Add Forthos Dungeon monsters to the NPC health list --- runelite-client/src/main/resources/npc_health.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/resources/npc_health.json b/runelite-client/src/main/resources/npc_health.json index 4944167e6f..6f39e21f79 100644 --- a/runelite-client/src/main/resources/npc_health.json +++ b/runelite-client/src/main/resources/npc_health.json @@ -1157,5 +1157,8 @@ "Wyrm_99": 130, "Drake_192": 250, "Hydra_194": 300, - "Alchemical Hydra_426": 1100 + "Alchemical Hydra_426": 1100, + "Undead Druid_105": 140, + "Temple Spider_75": 70, + "Sarachnis_318": 400 } From e0af554c698ea2029f8aa5aa6bff64ed55328890 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 18 Sep 2019 08:30:17 -0400 Subject: [PATCH 07/45] hooks: ignore npc update immediately after login The npc update after login isn't a game tick and happens prior to most state syncing --- .../java/net/runelite/client/RuneLite.java | 5 +++ .../net/runelite/client/callback/Hooks.java | 35 ++++++++++++++++--- 2 files changed, 35 insertions(+), 5 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 0decdb3c48..61e155b3e6 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -46,6 +46,7 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.client.account.SessionManager; +import net.runelite.client.callback.Hooks; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.CommandManager; import net.runelite.client.config.ConfigManager; @@ -151,6 +152,9 @@ public class RuneLite @Inject private Provider chatboxPanelManager; + @Inject + private Provider hooks; + @Inject @Nullable private Client client; @@ -322,6 +326,7 @@ public class RuneLite eventBus.register(commandManager.get()); eventBus.register(lootManager.get()); eventBus.register(chatboxPanelManager.get()); + eventBus.register(hooks.get()); // Add core overlays WidgetOverlay.createOverlays(client).forEach(overlayManager::add); diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index 4365d045f6..ca2053e446 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -50,6 +50,7 @@ import net.runelite.api.Renderable; import net.runelite.api.WorldMapManager; import net.runelite.api.events.BeforeMenuRender; import net.runelite.api.events.BeforeRender; +import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.hooks.Callbacks; import net.runelite.api.hooks.DrawCallbacks; @@ -60,6 +61,7 @@ import net.runelite.client.Notifier; import net.runelite.client.RuneLite; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyManager; import net.runelite.client.input.MouseManager; import net.runelite.client.task.Scheduler; @@ -128,6 +130,7 @@ public class Hooks implements Callbacks private Graphics2D stretchedGraphics; private long lastCheck; + private boolean ignoreNextNpcUpdate; private boolean shouldProcessGameTick; private static MainBufferProvider lastMainBufferProvider; @@ -463,15 +466,37 @@ public class Hooks implements Callbacks overlayManager.getItemWidgets().clear(); } + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + switch (gameStateChanged.getGameState()) + { + case LOGGING_IN: + case HOPPING: + ignoreNextNpcUpdate = true; + } + } + @Override public void updateNpcs() { - // The NPC update event seem to run every server tick, - // but having the game tick event after all packets - // have been processed is typically more useful. - shouldProcessGameTick = true; + if (ignoreNextNpcUpdate) + { + // After logging in an NPC update happens outside of the normal game tick, which + // is sent prior to skills and vars being bursted, so ignore it. + ignoreNextNpcUpdate = false; + log.debug("Skipping login updateNpc"); + } + else + { + // The NPC update event seem to run every server tick, + // but having the game tick event after all packets + // have been processed is typically more useful. + shouldProcessGameTick = true; + } + // Replay deferred events, otherwise if two npc - // update packets get processed in one frame, a + // update packets get processed in one client tick, a // despawn event could be published prior to the // spawn event, which is deferred deferredEventBus.replay(); From 1705fa642c0bd859927f92f8af78c984a538e226 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 21 Sep 2019 12:40:20 -0400 Subject: [PATCH 08/45] api: add sound volume accessors and vars --- .../main/java/net/runelite/api/Client.java | 36 +++++++++++++++++++ .../main/java/net/runelite/api/VarPlayer.java | 6 +++- 2 files changed, 41 insertions(+), 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 56e2995e32..cef172aa96 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -944,6 +944,42 @@ public interface Client extends GameEngine */ List getGraphicsObjects(); + /** + * Gets the music volume + * @return volume 0-255 inclusive + */ + int getMusicVolume(); + + /** + * Sets the music volume + * @param volume 0-255 inclusive + */ + void setMusicVolume(int volume); + + /** + * Gets the sound effect volume + * @return volume 0-127 inclusive + */ + int getSoundEffectVolume(); + + /** + * Sets the sound effect volume + * @param volume 0-127 inclusive + */ + void setSoundEffectVolume(int volume); + + /** + * Gets the area sound effect volume + * @return volume 0-127 inclusive + */ + int getAreaSoundEffectVolume(); + + /** + * Sets the area sound effect volume + * @param volume 0-127 inclusive + */ + void setAreaSoundEffectVolume(int volume); + /** * Play a sound effect at the player's current location. This is how UI, * and player-generated (e.g. mining, woodcutting) sound effects are 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 62489df3f0..9ae457c29e 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java +++ b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java @@ -162,7 +162,11 @@ public enum VarPlayer MUSIC_TRACKS_UNLOCKED_16(1009), MUSIC_TRACKS_UNLOCKED_17(1338), MUSIC_TRACKS_UNLOCKED_18(1681), - MUSIC_TRACKS_UNLOCKED_19(2065); + MUSIC_TRACKS_UNLOCKED_19(2065), + + MUSIC_VOLUME(168), + SOUND_EFFECT_VOLUME(169), + AREA_EFFECT_VOLUME(872); private final int id; } From 276a278461edc13296f632b4bb9df51e31f41c0a Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 23 Sep 2019 10:54:26 -0400 Subject: [PATCH 09/45] api: add volume changed event --- .../runelite/api/events/VolumeChanged.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java diff --git a/runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java b/runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java new file mode 100644 index 0000000000..8af4ee481b --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java @@ -0,0 +1,41 @@ +/* + * 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.events; + +import lombok.Value; + +@Value +public class VolumeChanged +{ + public enum Type + { + MUSIC, + EFFECTS, + AREA + } + + private final Type type; +} From 6fc270dfc2c2cdeb024242541391c1652d2f3064 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 21 Sep 2019 11:25:23 -0400 Subject: [PATCH 10/45] music list plugin: rename to music plugin --- .../MusicListPlugin.java => music/MusicPlugin.java} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename runelite-client/src/main/java/net/runelite/client/plugins/{musiclist/MusicListPlugin.java => music/MusicPlugin.java} (98%) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/musiclist/MusicListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java similarity index 98% rename from runelite-client/src/main/java/net/runelite/client/plugins/musiclist/MusicListPlugin.java rename to runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java index ab38b515f9..17284fe85f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/musiclist/MusicListPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java @@ -22,7 +22,7 @@ * (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.musiclist; +package net.runelite.client.plugins.music; import java.util.Arrays; import java.util.Collection; @@ -54,10 +54,10 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( - name = "Music List", + name = "Music", description = "Adds search and filter for the music list" ) -public class MusicListPlugin extends Plugin +public class MusicPlugin extends Plugin { @Inject private Client client; From 0145582b4134bf16f36455ead0d440d971f4ac80 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 21 Sep 2019 12:57:56 -0400 Subject: [PATCH 11/45] music plugin: add sound volume overrides --- .../client/plugins/music/MusicConfig.java | 79 +++++++++++++++++++ .../client/plugins/music/MusicPlugin.java | 63 ++++++++++++++- 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java new file mode 100644 index 0000000000..20b50545d0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java @@ -0,0 +1,79 @@ +/* + * 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.music; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; + +@ConfigGroup("music") +public interface MusicConfig extends Config +{ + @ConfigItem( + keyName = "musicVolume", + name = "Music Volume", + description = "Overrides music volume in game with more granular control", + position = 1 + ) + @Range( + min = 0, + max = 255 + ) + default int getMusicVolume() + { + return 0; + } + + @ConfigItem( + keyName = "soundEffectVolume", + name = "Sound Effect Volume", + description = "Overrides the sound effect volume in game with more granular control", + position = 2 + ) + @Range( + min = 0, + max = 127 + ) + default int getSoundEffectVolume() + { + return 0; + } + + @ConfigItem( + keyName = "areaSoundEffectVolume", + name = "Area Sound Effect Volume", + description = "Overrides the area sound effect volume in game with more granular control", + position = 3 + ) + @Range( + min = 0, + max = 127 + ) + default int getAreaSoundEffectVolume() + { + return 0; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java index 17284fe85f..80ef0c22e3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2019, Anthony Chen + * Copyright (c) 2019, Adam * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,6 +25,7 @@ */ package net.runelite.client.plugins.music; +import com.google.inject.Provides; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; @@ -37,8 +39,10 @@ import net.runelite.api.ScriptID; import net.runelite.api.SoundEffectID; import net.runelite.api.SpriteID; import net.runelite.api.VarClientInt; +import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.VarClientIntChanged; +import net.runelite.api.events.VolumeChanged; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.JavaScriptCallback; import net.runelite.api.widgets.Widget; @@ -47,6 +51,7 @@ import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetPositionMode; import net.runelite.api.widgets.WidgetType; import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.game.chatbox.ChatboxTextInput; @@ -55,7 +60,7 @@ import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( name = "Music", - description = "Adds search and filter for the music list" + description = "Adds search and filter for the music list, and additional volume control" ) public class MusicPlugin extends Plugin { @@ -65,6 +70,9 @@ public class MusicPlugin extends Plugin @Inject private ClientThread clientThread; + @Inject + private MusicConfig musicConfig; + @Inject private ChatboxPanelManager chatboxPanelManager; @@ -77,10 +85,17 @@ public class MusicPlugin extends Plugin private MusicState currentMusicFilter = MusicState.ALL; + private int lastMusicVolume; + private int lastEffectVolume; + private int lastAreaEffectVolume; + @Override protected void startUp() { + lastMusicVolume = lastEffectVolume = lastAreaEffectVolume = -1; + clientThread.invoke(this::addMusicButtons); + clientThread.invoke(this::applyMusicVolumeConfig); } @Override @@ -95,6 +110,12 @@ public class MusicPlugin extends Plugin tracks = null; } + @Provides + MusicConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(MusicConfig.class); + } + @Subscribe public void onGameStateChanged(GameStateChanged gameStateChanged) { @@ -167,6 +188,46 @@ public class MusicPlugin extends Plugin } } + @Subscribe + public void onVolumeChanged(VolumeChanged volumeChanged) + { + applyMusicVolumeConfig(); + } + + @Subscribe + public void onConfigChanged(ConfigChanged configChanged) + { + if (configChanged.getGroup().equals("music")) + { + clientThread.invokeLater(this::applyMusicVolumeConfig); + } + } + + private void applyMusicVolumeConfig() + { + int musicVolume = musicConfig.getMusicVolume(); + // Set the volume if it is >0, or if it was >0 and is now going back to 0 + if (musicVolume > 0 || lastMusicVolume > 0) + { + client.setMusicVolume(musicVolume); + lastMusicVolume = musicVolume; + } + + int soundEffectVolume = musicConfig.getSoundEffectVolume(); + if (soundEffectVolume > 0 || lastEffectVolume > 0) + { + client.setSoundEffectVolume(soundEffectVolume); + lastEffectVolume = soundEffectVolume; + } + + int areaSoundEffectVolume = musicConfig.getAreaSoundEffectVolume(); + if (areaSoundEffectVolume > 0 || lastAreaEffectVolume > 0) + { + client.setAreaSoundEffectVolume(areaSoundEffectVolume); + lastAreaEffectVolume = areaSoundEffectVolume; + } + } + private boolean isOnMusicTab() { return client.getVar(VarClientInt.INVENTORY_TAB) == 13; From 28472435255cc18c78c662206e108c296dfba364 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 26 Sep 2019 10:36:03 +0000 Subject: [PATCH 12/45] Update 184 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3ac957076d..00f448daab 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ true true - 183 + 184 From c1d48488301eb1b4c38c5f8324391c2a744e623c Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 26 Sep 2019 10:58:35 +0000 Subject: [PATCH 13/45] [maven-release-plugin] prepare release runelite-parent-1.5.34 --- 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-script-assembler-plugin/pom.xml | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 0975d9574e..c641f65788 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index ac9f061f94..0856abb59c 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 51686ecba3..09a306eb41 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 cache diff --git a/http-api/pom.xml b/http-api/pom.xml index fe6dbf04b5..7a29dc623b 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 394944917a..3051f96392 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 Web Service diff --git a/pom.xml b/pom.xml index 00f448daab..b3cc9716f3 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 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.34 diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index 753d6cd5a5..fc07db823b 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index d3e17b01d9..bedba8efee 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index f09c046a63..7034d56275 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 11fa7d6638..7ba2afc3dc 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34-SNAPSHOT + 1.5.34 client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 9193373951..26a8058b44 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.34-SNAPSHOT + 1.5.34 script-assembler-plugin From 6547478c07ae5d0574b8f3fa6017611cf02bf666 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Thu, 26 Sep 2019 10:58:41 +0000 Subject: [PATCH 14/45] [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-script-assembler-plugin/pom.xml | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index c641f65788..88d32c2985 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 0856abb59c..7d42489f5b 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 09a306eb41..77756e056c 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 7a29dc623b..00ce6f4808 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 3051f96392..3d129ddac7 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index b3cc9716f3..b41e6948c1 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-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.34 + HEAD diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index fc07db823b..f54c525380 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index bedba8efee..84c404c3f5 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 7034d56275..bc24d72ca6 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 7ba2afc3dc..70adbefb09 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.34 + 1.5.35-SNAPSHOT client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 26a8058b44..6a73a3a31b 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.34 + 1.5.35-SNAPSHOT script-assembler-plugin From 721bc9421667cb0dff4108186d89ebf72f15a609 Mon Sep 17 00:00:00 2001 From: Derek Johns Date: Fri, 27 Sep 2019 07:19:59 -0500 Subject: [PATCH 15/45] clues: add "may require 20gp" to Gu'Tanoth coord clue help text --- .../client/plugins/cluescrolls/clues/CoordinateClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 55735a3767..4aa3888d13 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -94,7 +94,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(3544, 3256, 0), "North-east of Burgh de Rott.") .put(new WorldPoint(2841, 3267, 0), "Crandor island.") .put(new WorldPoint(3168, 3041, 0), "Bedabin Camp.") - .put(new WorldPoint(2542, 3031, 0), "Gu'Tanoth.") + .put(new WorldPoint(2542, 3031, 0), "Gu'Tanoth, may require 20gp.") .put(new WorldPoint(2581, 3030, 0), "Gu'Tanoth island, enter cave north-west of Feldip Hills (AKS).") .put(new WorldPoint(2961, 3024, 0), "Ship yard (DKP).") .put(new WorldPoint(2339, 3311, 0), "East of Prifddinas on Arandar mountain pass.") From 35a68354810bb89853eaf74917f8f7ac82b828e7 Mon Sep 17 00:00:00 2001 From: Daniel Bolink Date: Fri, 27 Sep 2019 09:44:42 -0700 Subject: [PATCH 16/45] clues: add crystal pickaxe to soul altar emote clue --- .../runelite/client/plugins/cluescrolls/clues/EmoteClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7231020f74..cb27e08052 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 @@ -152,7 +152,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Slap your head in the centre of the Kourend catacombs. Beware of double agents! Equip the arclight and the amulet of the damned.", "Kourend catacombs", CENTRE_OF_THE_CATACOMBS_OF_KOUREND, new WorldPoint(1663, 10045, 0), SLAP_HEAD, item(ARCLIGHT), any("Amulet of the damned", item(AMULET_OF_THE_DAMNED), item(AMULET_OF_THE_DAMNED_FULL))), new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", "Rimmington", ROAD_JUNCTION_NORTH_OF_RIMMINGTON, new WorldPoint(2981, 3276, 0), SPIN, item(GREEN_HAT), item(CREAM_ROBE_TOP), item(LEATHER_CHAPS)), new EmoteClue("Spin in Draynor Manor by the fountain. Equip an iron platebody, studded leather chaps and a bronze full helmet.", "Draynor Manor", DRAYNOR_MANOR_BY_THE_FOUNTAIN, new WorldPoint(3088, 3336, 0), SPIN, item(IRON_PLATEBODY), item(STUDDED_CHAPS), item(BRONZE_FULL_HELM)), - new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", "Soul altar", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED), item(DRAGON_PICKAXEOR)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), + new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", "Soul altar", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon or Crystal pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED), item(DRAGON_PICKAXEOR), item(CRYSTAL_PICKAXE), item(CRYSTAL_PICKAXE_INACTIVE)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), new EmoteClue("Spin in the Varrock Castle courtyard. Equip a black axe, a coif and a ruby ring.", "Varrock Castle", OUTSIDE_VARROCK_PALACE_COURTYARD, new WorldPoint(3213, 3463, 0), SPIN, item(BLACK_AXE), item(COIF), item(RUBY_RING)), new EmoteClue("Spin in West Ardougne Church. Equip a dragon spear and red dragonhide chaps.", "Ardougne", CHAPEL_IN_WEST_ARDOUGNE, new WorldPoint(2530, 3290, 0), SPIN, item(DRAGON_SPEAR), item(RED_DHIDE_CHAPS)), new EmoteClue("Spin on the bridge by the Barbarian Village. Salute before you talk to me. Equip purple gloves, a steel kiteshield and a mithril full helmet.", "Barbarian Village", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)), From 5d4f7d2fcee3cdcddc19130d0d5a2866ff96d7c7 Mon Sep 17 00:00:00 2001 From: Jordan Date: Fri, 27 Sep 2019 10:10:19 -0700 Subject: [PATCH 17/45] clues: fix swordfish skill challenge --- .../client/plugins/cluescrolls/clues/SkillChallengeClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java index df10aa06cc..2c75d1a49e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java @@ -140,7 +140,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll new SkillChallengeClue("Chop a yew tree.", ANY_AXE), new SkillChallengeClue("Fix a magical lamp in Dorgesh-Kaan.", item(ItemID.LIGHT_ORB)), new SkillChallengeClue("Burn a yew log.", item(ItemID.YEW_LOGS), item(ItemID.TINDERBOX)), - new SkillChallengeClue("Catch and cook a swordfish.", "cook a swordfish.", ANY_HARPOON), + new SkillChallengeClue("Cook a swordfish", "cook a swordfish", item(ItemID.RAW_SWORDFISH)), new SkillChallengeClue("Craft multiple cosmic runes from a single essence.", item(ItemID.PURE_ESSENCE)), new SkillChallengeClue("Plant a watermelon seed.", item(ItemID.RAKE), item(ItemID.SEED_DIBBER), xOfItem(ItemID.WATERMELON_SEED, 3)), new SkillChallengeClue("Activate the Chivalry prayer."), From 05243c6c95dde345abb9788bcb9c6ee940f72c14 Mon Sep 17 00:00:00 2001 From: Jordan Date: Fri, 27 Sep 2019 10:27:54 -0700 Subject: [PATCH 18/45] clues: fix Warriors' Guild master clue text --- .../runelite/client/plugins/cluescrolls/clues/EmoteClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 cb27e08052..b66c17e0da 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 @@ -138,7 +138,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu 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.", "Lava dragon isle", 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.", "Trollweiss mountain", 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", 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 slayer helm of any kind and a dragon defender or avernic defender.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), any("Dragon defender or Avernic defender", item(DRAGON_DEFENDER), item(AVERNIC_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 in the bank of the Warriors' Guild. Beware of double agents! Equip a dragon battleaxe, a slayer helm of any kind and a dragon defender or avernic defender.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), any("Dragon defender or Avernic defender", item(DRAGON_DEFENDER), item(AVERNIC_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.", "Ardougne Zoo", 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.", "Keep Le Faye", 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", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)), From b5de66636861dd4dcd9e9234ee7188092d92cca4 Mon Sep 17 00:00:00 2001 From: maddie <34499002+post-async@users.noreply.github.com> Date: Fri, 27 Sep 2019 10:35:02 -0700 Subject: [PATCH 19/45] clues: clarify bandit camp location in coordinate hint --- .../client/plugins/cluescrolls/clues/CoordinateClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 4aa3888d13..039e70770c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -100,7 +100,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(2339, 3311, 0), "East of Prifddinas on Arandar mountain pass.") .put(new WorldPoint(3440, 3341, 0), "Nature Spirit's grotto.") .put(new WorldPoint(2763, 2974, 0), "Cairn Isle, west of Shilo Village.") - .put(new WorldPoint(3138, 2969, 0), "West of Bandit Camp.") + .put(new WorldPoint(3138, 2969, 0), "West of Bandit Camp in Kharidian Desert.") .put(new WorldPoint(2924, 2963, 0), "On the southern part of eastern Karamja.") .put(new WorldPoint(2838, 2914, 0), "Kharazi Jungle, near water pool.") .put(new WorldPoint(3441, 3419, 0), "Mort Myre Swamp.") From 3231abf89c26076b37e15c6ffc8bc8c4762177fd Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Mon, 30 Sep 2019 07:20:31 +0200 Subject: [PATCH 20/45] i --- runescape-client/.DS_Store | Bin 6148 -> 0 bytes runescape-client/src/main/java/Actor.java | 5 +- runescape-client/src/main/java/Client.java | 8 +- .../java/{class319.java => ClientType.java} | 7 +- runescape-client/src/main/java/HealthBar.java | 8 +- .../src/main/java/InterfaceParent.java | 4 +- runescape-client/src/main/java/NPC.java | 4 +- runescape-client/src/main/java/Scene.java | 125 ++++---- runescape-client/src/main/java/Sprite.java | 294 +++++++++--------- runescape-client/src/main/java/class191.java | 4 +- runescape-client/src/main/java/class32.java | 2 +- runescape-client/src/main/java/class325.java | 12 +- runescape-client/src/main/java/class4.java | 4 +- 13 files changed, 242 insertions(+), 235 deletions(-) delete mode 100644 runescape-client/.DS_Store rename runescape-client/src/main/java/{class319.java => ClientType.java} (59%) diff --git a/runescape-client/.DS_Store b/runescape-client/.DS_Store deleted file mode 100644 index 8f7026824783bb4152ab96dd1a1ed6fbf1b0dd22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKI|>3Z5S{S@f{mqRuHX%V=n1@l$btx>AZWdn=kjR2`83P2ofgU)n7m{%FCnkk z*%1+4-}>w&gLxhmpaMUyfPEhd+^{CLf&S^h;4J`fg0LIr-b(Cld`t<9%r?-!1r*=dBM#vcM1kC$3QQ~SXen;dQ#*Sn`6Hw Uwt-GZ-0496445u7D)4Ou-khQox&QzG diff --git a/runescape-client/src/main/java/Actor.java b/runescape-client/src/main/java/Actor.java index bd3ae411e4..12ee43e023 100644 --- a/runescape-client/src/main/java/Actor.java +++ b/runescape-client/src/main/java/Actor.java @@ -29,7 +29,8 @@ public abstract class Actor extends Entity { @Export("isWalking") boolean isWalking; @ObfuscatedName("ax") - int field932; + @Export("size") + int size; @ObfuscatedName("as") @ObfuscatedGetter( intValue = -334562759 @@ -315,7 +316,7 @@ public abstract class Actor extends Entity { Actor() { this.isWalking = false; - this.field932 = 772175475; + this.size = 772175475; this.readySequence = -1; this.turnLeftSequence = -1; this.turnRightSequence = -1; diff --git a/runescape-client/src/main/java/Client.java b/runescape-client/src/main/java/Client.java index b257375fb5..24b99a25e1 100644 --- a/runescape-client/src/main/java/Client.java +++ b/runescape-client/src/main/java/Client.java @@ -2110,7 +2110,7 @@ public final class Client extends GameShell implements Usernamed { } ViewportMouse.client = this; - class319.field3843 = clientType; + ClientType.clientType = clientType; this.startThread(765, 503, 184); } } catch (RuntimeException var22) { @@ -5267,9 +5267,9 @@ public final class Client extends GameShell implements Usernamed { garbageValue = "1638335073" ) @Export("openMenu") - final void openMenu(int var1, int var2) { - UserComparator6.calculateMenuBounds(var1, var2); - PacketWriter.scene.menuOpen(WorldMapRectangle.plane, var1, var2, false); + final void openMenu(int screenX, int screenY) { + UserComparator6.calculateMenuBounds(screenX, screenY); + PacketWriter.scene.menuOpen(WorldMapRectangle.plane, screenX, screenY, false); isMenuOpen = true; } diff --git a/runescape-client/src/main/java/class319.java b/runescape-client/src/main/java/ClientType.java similarity index 59% rename from runescape-client/src/main/java/class319.java rename to runescape-client/src/main/java/ClientType.java index 0912083a75..21c6f8e919 100644 --- a/runescape-client/src/main/java/class319.java +++ b/runescape-client/src/main/java/ClientType.java @@ -1,11 +1,14 @@ +import net.runelite.mapping.Implements; import net.runelite.mapping.ObfuscatedGetter; import net.runelite.mapping.ObfuscatedName; @ObfuscatedName("ln") -public class class319 { +@Implements("ClientType") +public class ClientType +{ @ObfuscatedName("u") @ObfuscatedGetter( intValue = 2052078695 ) - public static int field3843; + public static int clientType; } diff --git a/runescape-client/src/main/java/HealthBar.java b/runescape-client/src/main/java/HealthBar.java index 38bee8e26c..011d9edae6 100644 --- a/runescape-client/src/main/java/HealthBar.java +++ b/runescape-client/src/main/java/HealthBar.java @@ -169,10 +169,10 @@ public class HealthBar extends Node { if (var0.field976 == Client.cycle || var0.sequence == -1 || var0.sequenceDelay != 0 || var0.sequenceFrameCycle + 1 > GrandExchangeOfferUnitPriceComparator.SequenceDefinition_get(var0.sequence).frameLengths[var0.sequenceFrame]) { int var1 = var0.field976 - var0.field948; int var2 = Client.cycle - var0.field948; - int var3 = var0.field932 * -527978816 + var0.field971 * 128; - int var4 = var0.field932 * -527978816 + var0.field973 * 128; - int var5 = var0.field972 * 128 + var0.field932 * -527978816; - int var6 = var0.field932 * -527978816 + var0.field974 * 128; + int var3 = var0.size * -527978816 + var0.field971 * 128; + int var4 = var0.size * -527978816 + var0.field973 * 128; + int var5 = var0.field972 * 128 + var0.size * -527978816; + int var6 = var0.size * -527978816 + var0.field974 * 128; var0.x = (var2 * var5 + var3 * (var1 - var2)) / var1; var0.y = (var6 * var2 + var4 * (var1 - var2)) / var1; } diff --git a/runescape-client/src/main/java/InterfaceParent.java b/runescape-client/src/main/java/InterfaceParent.java index 0235d4f201..5db3af8647 100644 --- a/runescape-client/src/main/java/InterfaceParent.java +++ b/runescape-client/src/main/java/InterfaceParent.java @@ -212,7 +212,7 @@ public class InterfaceParent extends Node { var9 = var1.readBits(1); var4.definition = PacketBufferNode.getNpcDefinition(var1.readBits(14)); - var4.field932 = var4.definition.size * 772175475; + var4.size = var4.definition.size * 772175475; var4.field982 = var4.definition.rotation; if (var4.field982 == 0) { var4.rotation = 0; @@ -317,7 +317,7 @@ public class InterfaceParent extends Node { if ((var5 & 32) != 0) { var4.definition = PacketBufferNode.getNpcDefinition(var1.method5647()); - var4.field932 = var4.definition.size * 772175475; + var4.size = var4.definition.size * 772175475; var4.field982 = var4.definition.rotation; var4.walkSequence = var4.definition.walkSequence; var4.walkBackSequence = var4.definition.walkBackSequence; diff --git a/runescape-client/src/main/java/NPC.java b/runescape-client/src/main/java/NPC.java index 2105a08667..30b27fc115 100644 --- a/runescape-client/src/main/java/NPC.java +++ b/runescape-client/src/main/java/NPC.java @@ -122,8 +122,8 @@ public final class NPC extends Actor { super.field949 = 0; super.pathX[0] = var1; super.pathY[0] = var2; - super.x = super.pathX[0] * 128 + super.field932 * -527978816; - super.y = super.pathY[0] * 128 + super.field932 * -527978816; + super.x = super.pathX[0] * 128 + super.size * -527978816; + super.y = super.pathY[0] * 128 + super.size * -527978816; } @ObfuscatedName("y") diff --git a/runescape-client/src/main/java/Scene.java b/runescape-client/src/main/java/Scene.java index 6432a085c2..cde552f69b 100644 --- a/runescape-client/src/main/java/Scene.java +++ b/runescape-client/src/main/java/Scene.java @@ -317,39 +317,42 @@ public class Scene { @ObfuscatedName("p") @Export("addTile") - public void addTile(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8, int var9, int var10, int var11, int var12, int var13, int var14, int var15, int var16, int var17, int var18, int var19, int var20) { + public void addTile(int z, int x, int y, int shape, int rotation, int texture, int heightSw, int heightNw, + int heightNe, int heightSe, int underlaySwColor, int underlayNwColor, int underlayNeColor, + int underlaySeColor, int overlaySwColor, int overlayNwColor, int overlayNeColor, + int overlaySeColor, int underlayRgb, int overlayRgb) { TilePaint var21; int var22; - if (var4 == 0) { - var21 = new TilePaint(var11, var12, var13, var14, -1, var19, false); + if (shape == 0) { + var21 = new TilePaint(underlaySwColor, underlayNwColor, underlayNeColor, underlaySeColor, -1, underlayRgb, false); - for (var22 = var1; var22 >= 0; --var22) { - if (this.tiles[var22][var2][var3] == null) { - this.tiles[var22][var2][var3] = new Tile(var22, var2, var3); + for (var22 = z; var22 >= 0; --var22) { + if (this.tiles[var22][x][y] == null) { + this.tiles[var22][x][y] = new Tile(var22, x, y); } } - this.tiles[var1][var2][var3].paint = var21; - } else if (var4 != 1) { - TileModel var23 = new TileModel(var4, var5, var6, var2, var3, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20); + this.tiles[z][x][y].paint = var21; + } else if (shape != 1) { + TileModel var23 = new TileModel(shape, rotation, texture, x, y, heightSw, heightNw, heightNe, heightSe, underlaySwColor, underlayNwColor, underlayNeColor, underlaySeColor, overlaySwColor, overlayNwColor, overlayNeColor, overlaySeColor, underlayRgb, overlayRgb); - for (var22 = var1; var22 >= 0; --var22) { - if (this.tiles[var22][var2][var3] == null) { - this.tiles[var22][var2][var3] = new Tile(var22, var2, var3); + for (var22 = z; var22 >= 0; --var22) { + if (this.tiles[var22][x][y] == null) { + this.tiles[var22][x][y] = new Tile(var22, x, y); } } - this.tiles[var1][var2][var3].model = var23; + this.tiles[z][x][y].model = var23; } else { - var21 = new TilePaint(var15, var16, var17, var18, var6, var20, var8 == var7 && var7 == var9 && var10 == var7); + var21 = new TilePaint(overlaySwColor, overlayNwColor, overlayNeColor, overlaySeColor, texture, overlayRgb, heightNw == heightSw && heightSw == heightNe && heightSe == heightSw); - for (var22 = var1; var22 >= 0; --var22) { - if (this.tiles[var22][var2][var3] == null) { - this.tiles[var22][var2][var3] = new Tile(var22, var2, var3); + for (var22 = z; var22 >= 0; --var22) { + if (this.tiles[var22][x][y] == null) { + this.tiles[var22][x][y] = new Tile(var22, x, y); } } - this.tiles[var1][var2][var3].paint = var21; + this.tiles[z][x][y].paint = var21; } } @@ -970,61 +973,61 @@ public class Scene { @ObfuscatedName("ai") @Export("drawTileMinimap") - public void drawTileMinimap(int[] var1, int var2, int var3, int var4, int var5, int var6) { - Tile var7 = this.tiles[var4][var5][var6]; - if (var7 != null) { - TilePaint var8 = var7.paint; - int var10; - if (var8 != null) { - int var9 = var8.rgb; - if (var9 != 0) { - for (var10 = 0; var10 < 4; ++var10) { - var1[var2] = var9; - var1[var2 + 1] = var9; - var1[var2 + 2] = var9; - var1[var2 + 3] = var9; - var2 += var3; + public void drawTileMinimap(int[] pixels, int index, int width, int plane, int x, int y) { + Tile tile = this.tiles[plane][x][y]; + if (tile != null) { + TilePaint tilePaint = tile.paint; + int shape; + if (tilePaint != null) { + int rgb = tilePaint.rgb; + if (rgb != 0) { + for (shape = 0; shape < 4; ++shape) { + pixels[index] = rgb; + pixels[index + 1] = rgb; + pixels[index + 2] = rgb; + pixels[index + 3] = rgb; + index += width; } } } else { - TileModel var18 = var7.model; - if (var18 != null) { - var10 = var18.shape; - int var11 = var18.rotation; - int var12 = var18.underlayRgb; - int var13 = var18.overlayRgb; - int[] var14 = this.tileShape2D[var10]; - int[] var15 = this.tileRotation2D[var11]; + TileModel tileModel = tile.model; + if (tileModel != null) { + shape = tileModel.shape; + int rotation = tileModel.rotation; + int underlayRgb = tileModel.underlayRgb; + int overlayRgb = tileModel.overlayRgb; + int[] shapes = this.tileShape2D[shape]; + int[] rotations = this.tileRotation2D[rotation]; int var16 = 0; int var17; - if (var12 != 0) { + if (underlayRgb != 0) { for (var17 = 0; var17 < 4; ++var17) { - var1[var2] = var14[var15[var16++]] == 0 ? var12 : var13; - var1[var2 + 1] = var14[var15[var16++]] == 0 ? var12 : var13; - var1[var2 + 2] = var14[var15[var16++]] == 0 ? var12 : var13; - var1[var2 + 3] = var14[var15[var16++]] == 0 ? var12 : var13; - var2 += var3; + pixels[index] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + pixels[index + 1] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + pixels[index + 2] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + pixels[index + 3] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + index += width; } } else { for (var17 = 0; var17 < 4; ++var17) { - if (var14[var15[var16++]] != 0) { - var1[var2] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index] = overlayRgb; } - if (var14[var15[var16++]] != 0) { - var1[var2 + 1] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index + 1] = overlayRgb; } - if (var14[var15[var16++]] != 0) { - var1[var2 + 2] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index + 2] = overlayRgb; } - if (var14[var15[var16++]] != 0) { - var1[var2 + 3] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index + 3] = overlayRgb; } - var2 += var3; + index += width; } } @@ -1035,13 +1038,13 @@ public class Scene { @ObfuscatedName("am") @Export("menuOpen") - public void menuOpen(int var1, int var2, int var3, boolean var4) { - if (!method3085() || var4) { + public void menuOpen(int plane, int screenX, int screenY, boolean walking) { + if (!method3085() || walking) { checkClick = true; - viewportWalking = var4; - Scene_selectedPlane = var1; - Scene_selectedScreenX = var2; - Scene_selectedScreenY = var3; + viewportWalking = walking; + Scene_selectedPlane = plane; + Scene_selectedScreenX = screenX; + Scene_selectedScreenY = screenY; Scene_selectedX = -1; Scene_selectedY = -1; } diff --git a/runescape-client/src/main/java/Sprite.java b/runescape-client/src/main/java/Sprite.java index e55638f17f..1b8816f5e1 100644 --- a/runescape-client/src/main/java/Sprite.java +++ b/runescape-client/src/main/java/Sprite.java @@ -109,25 +109,25 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("r") @Export("pad") - public void pad(int var1) { + public void pad(int amount) { if (this.subWidth != this.width || this.subHeight != this.height) { - int var2 = var1; - if (var1 > this.xOffset) { + int var2 = amount; + if (amount > this.xOffset) { var2 = this.xOffset; } - int var3 = var1; - if (var1 + this.xOffset + this.subWidth > this.width) { + int var3 = amount; + if (amount + this.xOffset + this.subWidth > this.width) { var3 = this.width - this.xOffset - this.subWidth; } - int var4 = var1; - if (var1 > this.yOffset) { + int var4 = amount; + if (amount > this.yOffset) { var4 = this.yOffset; } - int var5 = var1; - if (var1 + this.yOffset + this.subHeight > this.height) { + int var5 = amount; + if (amount + this.yOffset + this.subHeight > this.height) { var5 = this.height - this.yOffset - this.subHeight; } @@ -183,7 +183,7 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("m") @Export("outline") - public void outline(int var1) { + public void outline(int color) { int[] var2 = new int[this.subWidth * this.subHeight]; int var3 = 0; @@ -192,13 +192,13 @@ public final class Sprite extends Rasterizer2D { int var6 = this.pixels[var3]; if (var6 == 0) { if (var5 > 0 && this.pixels[var3 - 1] != 0) { - var6 = var1; + var6 = color; } else if (var4 > 0 && this.pixels[var3 - this.subWidth] != 0) { - var6 = var1; + var6 = color; } else if (var5 < this.subWidth - 1 && this.pixels[var3 + 1] != 0) { - var6 = var1; + var6 = color; } else if (var4 < this.subHeight - 1 && this.pixels[var3 + this.subWidth] != 0) { - var6 = var1; + var6 = color; } } @@ -226,40 +226,40 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("i") @Export("drawAt") - public void drawAt(int var1, int var2) { - var1 += this.xOffset; - var2 += this.yOffset; - int var3 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void drawAt(int x, int y) { + x += this.xOffset; + y += this.yOffset; + int var3 = x + y * Rasterizer2D.Rasterizer2D_width; int var4 = 0; int var5 = this.subHeight; int var6 = this.subWidth; int var7 = Rasterizer2D.Rasterizer2D_width - var6; int var8 = 0; int var9; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var9 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var9 = Rasterizer2D.Rasterizer2D_yClipStart - y; var5 -= var9; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var4 += var9 * var6; var3 += var9 * Rasterizer2D.Rasterizer2D_width; } - if (var5 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var5 -= var5 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var5 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var5 -= var5 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var9 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var9 = Rasterizer2D.Rasterizer2D_xClipStart - x; var6 -= var9; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var4 += var9; var3 += var9; var8 += var9; var7 += var9; } - if (var6 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var9 = var6 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var6 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var9 = var6 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var6 -= var9; var8 += var9; var7 += var9; @@ -272,40 +272,40 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("b") @Export("drawTransBgAt") - public void drawTransBgAt(int var1, int var2) { - var1 += this.xOffset; - var2 += this.yOffset; - int var3 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void drawTransBgAt(int x, int y) { + x += this.xOffset; + y += this.yOffset; + int var3 = x + y * Rasterizer2D.Rasterizer2D_width; int var4 = 0; int var5 = this.subHeight; int var6 = this.subWidth; int var7 = Rasterizer2D.Rasterizer2D_width - var6; int var8 = 0; int var9; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var9 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var9 = Rasterizer2D.Rasterizer2D_yClipStart - y; var5 -= var9; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var4 += var9 * var6; var3 += var9 * Rasterizer2D.Rasterizer2D_width; } - if (var5 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var5 -= var5 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var5 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var5 -= var5 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var9 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var9 = Rasterizer2D.Rasterizer2D_xClipStart - x; var6 -= var9; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var4 += var9; var3 += var9; var8 += var9; var7 += var9; } - if (var6 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var9 = var6 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var6 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var9 = var6 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var6 -= var9; var8 += var9; var7 += var9; @@ -318,275 +318,275 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("a") @Export("drawScaledAt") - public void drawScaledAt(int var1, int var2, int var3, int var4) { - if (var3 > 0 && var4 > 0) { + public void drawScaledAt(int x, int y, int width, int height) { + if (width > 0 && height > 0) { int var5 = this.subWidth; int var6 = this.subHeight; int var7 = 0; int var8 = 0; int var9 = this.width; int var10 = this.height; - int var11 = (var9 << 16) / var3; - int var12 = (var10 << 16) / var4; + int var11 = (var9 << 16) / width; + int var12 = (var10 << 16) / height; int var13; if (this.xOffset > 0) { var13 = (var11 + (this.xOffset << 16) - 1) / var11; - var1 += var13; + x += var13; var7 += var13 * var11 - (this.xOffset << 16); } if (this.yOffset > 0) { var13 = (var12 + (this.yOffset << 16) - 1) / var12; - var2 += var13; + y += var13; var8 += var13 * var12 - (this.yOffset << 16); } if (var5 < var9) { - var3 = (var11 + ((var5 << 16) - var7) - 1) / var11; + width = (var11 + ((var5 << 16) - var7) - 1) / var11; } if (var6 < var10) { - var4 = (var12 + ((var6 << 16) - var8) - 1) / var12; + height = (var12 + ((var6 << 16) - var8) - 1) / var12; } - var13 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; - int var14 = Rasterizer2D.Rasterizer2D_width - var3; - if (var2 + var4 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var4 -= var2 + var4 - Rasterizer2D.Rasterizer2D_yClipEnd; + var13 = x + y * Rasterizer2D.Rasterizer2D_width; + int var14 = Rasterizer2D.Rasterizer2D_width - width; + if (y + height > Rasterizer2D.Rasterizer2D_yClipEnd) { + height -= y + height - Rasterizer2D.Rasterizer2D_yClipEnd; } int var15; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var15 = Rasterizer2D.Rasterizer2D_yClipStart - var2; - var4 -= var15; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var15 = Rasterizer2D.Rasterizer2D_yClipStart - y; + height -= var15; var13 += var15 * Rasterizer2D.Rasterizer2D_width; var8 += var12 * var15; } - if (var3 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var15 = var3 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; - var3 -= var15; + if (width + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var15 = width + x - Rasterizer2D.Rasterizer2D_xClipEnd; + width -= var15; var14 += var15; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var15 = Rasterizer2D.Rasterizer2D_xClipStart - var1; - var3 -= var15; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var15 = Rasterizer2D.Rasterizer2D_xClipStart - x; + width -= var15; var13 += var15; var7 += var11 * var15; var14 += var15; } - Sprite_drawScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var7, var8, var13, var14, var3, var4, var11, var12, var5); + Sprite_drawScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var7, var8, var13, var14, width, height, var11, var12, var5); } } @ObfuscatedName("x") @Export("drawTransOverlayAt") - public void drawTransOverlayAt(int var1, int var2, int var3, int var4) { - if (var3 == 256) { - this.drawTransBgAt(var1, var2); + public void drawTransOverlayAt(int x, int y, int overlayOpacity, int overlayColor) { + if (overlayOpacity == 256) { + this.drawTransBgAt(x, y); } else { - var1 += this.xOffset; - var2 += this.yOffset; - int var5 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + x += this.xOffset; + y += this.yOffset; + int var5 = x + y * Rasterizer2D.Rasterizer2D_width; int var6 = 0; int var7 = this.subHeight; int var8 = this.subWidth; int var9 = Rasterizer2D.Rasterizer2D_width - var8; int var10 = 0; int var11; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var11 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var11 = Rasterizer2D.Rasterizer2D_yClipStart - y; var7 -= var11; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var6 += var11 * var8; var5 += var11 * Rasterizer2D.Rasterizer2D_width; } - if (var7 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var7 -= var7 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var7 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var7 -= var7 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var11 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var11 = Rasterizer2D.Rasterizer2D_xClipStart - x; var8 -= var11; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var6 += var11; var5 += var11; var10 += var11; var9 += var11; } - if (var8 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var11 = var8 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var8 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var11 = var8 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var8 -= var11; var10 += var11; var9 += var11; } if (var8 > 0 && var7 > 0) { - Sprite_drawTransOverlay(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var6, var5, var8, var7, var9, var10, var3, var4); + Sprite_drawTransOverlay(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var6, var5, var8, var7, var9, var10, overlayOpacity, overlayColor); } } } @ObfuscatedName("s") @Export("drawTransAt") - public void drawTransAt(int var1, int var2, int var3) { - var1 += this.xOffset; - var2 += this.yOffset; - int var4 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void drawTransAt(int x, int y, int opacity) { + x += this.xOffset; + y += this.yOffset; + int var4 = x + y * Rasterizer2D.Rasterizer2D_width; int var5 = 0; int var6 = this.subHeight; int var7 = this.subWidth; int var8 = Rasterizer2D.Rasterizer2D_width - var7; int var9 = 0; int var10; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var10 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var10 = Rasterizer2D.Rasterizer2D_yClipStart - y; var6 -= var10; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var5 += var10 * var7; var4 += var10 * Rasterizer2D.Rasterizer2D_width; } - if (var6 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var6 -= var6 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var6 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var6 -= var6 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var10 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var10 = Rasterizer2D.Rasterizer2D_xClipStart - x; var7 -= var10; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var5 += var10; var4 += var10; var9 += var10; var8 += var10; } - if (var7 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var10 = var7 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var7 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var10 = var7 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var7 -= var10; var9 += var10; var8 += var10; } if (var7 > 0 && var6 > 0) { - Sprite_drawTransparent(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var5, var4, var7, var6, var8, var9, var3); + Sprite_drawTransparent(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var5, var4, var7, var6, var8, var9, opacity); } } @ObfuscatedName("j") @Export("drawTransScaledAt") - public void drawTransScaledAt(int var1, int var2, int var3, int var4, int var5) { - if (var3 > 0 && var4 > 0) { + public void drawTransScaledAt(int x, int y, int width, int height, int opacity) { + if (width > 0 && height > 0) { int var6 = this.subWidth; int var7 = this.subHeight; int var8 = 0; int var9 = 0; int var10 = this.width; int var11 = this.height; - int var12 = (var10 << 16) / var3; - int var13 = (var11 << 16) / var4; + int var12 = (var10 << 16) / width; + int var13 = (var11 << 16) / height; int var14; if (this.xOffset > 0) { var14 = (var12 + (this.xOffset << 16) - 1) / var12; - var1 += var14; + x += var14; var8 += var14 * var12 - (this.xOffset << 16); } if (this.yOffset > 0) { var14 = (var13 + (this.yOffset << 16) - 1) / var13; - var2 += var14; + y += var14; var9 += var14 * var13 - (this.yOffset << 16); } if (var6 < var10) { - var3 = (var12 + ((var6 << 16) - var8) - 1) / var12; + width = (var12 + ((var6 << 16) - var8) - 1) / var12; } if (var7 < var11) { - var4 = (var13 + ((var7 << 16) - var9) - 1) / var13; + height = (var13 + ((var7 << 16) - var9) - 1) / var13; } - var14 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; - int var15 = Rasterizer2D.Rasterizer2D_width - var3; - if (var2 + var4 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var4 -= var2 + var4 - Rasterizer2D.Rasterizer2D_yClipEnd; + var14 = x + y * Rasterizer2D.Rasterizer2D_width; + int var15 = Rasterizer2D.Rasterizer2D_width - width; + if (y + height > Rasterizer2D.Rasterizer2D_yClipEnd) { + height -= y + height - Rasterizer2D.Rasterizer2D_yClipEnd; } int var16; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var16 = Rasterizer2D.Rasterizer2D_yClipStart - var2; - var4 -= var16; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var16 = Rasterizer2D.Rasterizer2D_yClipStart - y; + height -= var16; var14 += var16 * Rasterizer2D.Rasterizer2D_width; var9 += var13 * var16; } - if (var3 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var16 = var3 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; - var3 -= var16; + if (width + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var16 = width + x - Rasterizer2D.Rasterizer2D_xClipEnd; + width -= var16; var15 += var16; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var16 = Rasterizer2D.Rasterizer2D_xClipStart - var1; - var3 -= var16; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var16 = Rasterizer2D.Rasterizer2D_xClipStart - x; + width -= var16; var14 += var16; var8 += var12 * var16; var15 += var16; } - Sprite_drawTransScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var8, var9, var14, var15, var3, var4, var12, var13, var6, var5); + Sprite_drawTransScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var8, var9, var14, var15, width, height, var12, var13, var6, opacity); } } @ObfuscatedName("l") - public void method6082(int var1, int var2, int var3) { - var1 += this.xOffset; - var2 += this.yOffset; - int var4 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void method6082(int x, int y, int opacity) { + x += this.xOffset; + y += this.yOffset; + int var4 = x + y * Rasterizer2D.Rasterizer2D_width; int var5 = 0; int var6 = this.subHeight; int var7 = this.subWidth; int var8 = Rasterizer2D.Rasterizer2D_width - var7; int var9 = 0; int var10; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var10 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var10 = Rasterizer2D.Rasterizer2D_yClipStart - y; var6 -= var10; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var5 += var10 * var7; var4 += var10 * Rasterizer2D.Rasterizer2D_width; } - if (var6 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var6 -= var6 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var6 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var6 -= var6 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var10 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var10 = Rasterizer2D.Rasterizer2D_xClipStart - x; var7 -= var10; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var5 += var10; var4 += var10; var9 += var10; var8 += var10; } - if (var7 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var10 = var7 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var7 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var10 = var7 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var7 -= var10; var9 += var10; var8 += var10; } if (var7 > 0 && var6 > 0) { - if (var3 == 256) { + if (opacity == 256) { method6071(0, 0, 0, Rasterizer2D.Rasterizer2D_pixels, this.pixels, var5, 0, var4, 0, var7, var6, var8, var9); } else { - method6084(0, 0, 0, Rasterizer2D.Rasterizer2D_pixels, this.pixels, var5, 0, var4, 0, var7, var6, var8, var9, var3); + method6084(0, 0, 0, Rasterizer2D.Rasterizer2D_pixels, this.pixels, var5, 0, var4, 0, var7, var6, var8, var9, opacity); } } @@ -711,25 +711,25 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("ax") @Export("drawRotatedMaskedCenteredAround") - public void drawRotatedMaskedCenteredAround(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8, int[] var9, int[] var10) { + public void drawRotatedMaskedCenteredAround(int x, int y, int width, int height, int xOffset, int yOffset, int rotation, int zoom, int[] xOffsets, int[] yOffsets) { try { - int var11 = -var3 / 2; - int var12 = -var4 / 2; - int var13 = (int)(Math.sin((double)var7 / 326.11D) * 65536.0D); - int var14 = (int)(Math.cos((double)var7 / 326.11D) * 65536.0D); - var13 = var13 * var8 >> 8; - var14 = var14 * var8 >> 8; - int var15 = var12 * var13 + var11 * var14 + (var5 << 16); - int var16 = var12 * var14 - var11 * var13 + (var6 << 16); - int var17 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + int var11 = -width / 2; + int var12 = -height / 2; + int var13 = (int)(Math.sin((double)rotation / 326.11D) * 65536.0D); + int var14 = (int)(Math.cos((double)rotation / 326.11D) * 65536.0D); + var13 = var13 * zoom >> 8; + var14 = var14 * zoom >> 8; + int var15 = var12 * var13 + var11 * var14 + (xOffset << 16); + int var16 = var12 * var14 - var11 * var13 + (yOffset << 16); + int var17 = x + y * Rasterizer2D.Rasterizer2D_width; - for (var2 = 0; var2 < var4; ++var2) { - int var18 = var9[var2]; + for (y = 0; y < height; ++y) { + int var18 = xOffsets[y]; int var19 = var17 + var18; int var20 = var15 + var14 * var18; int var21 = var16 - var13 * var18; - for (var1 = -var10[var2]; var1 < 0; ++var1) { + for (x = -yOffsets[y]; x < 0; ++x) { Rasterizer2D.Rasterizer2D_pixels[var19++] = this.pixels[this.subWidth * (var21 >> 16) + (var20 >> 16)]; var20 += var14; var21 -= var13; diff --git a/runescape-client/src/main/java/class191.java b/runescape-client/src/main/java/class191.java index cf1181948e..4a991ac441 100644 --- a/runescape-client/src/main/java/class191.java +++ b/runescape-client/src/main/java/class191.java @@ -49,8 +49,8 @@ public class class191 { ) static final void method3639(Actor var0) { int var1 = var0.field948 - Client.cycle; - int var2 = var0.field932 * -527978816 + var0.field971 * 128; - int var3 = var0.field932 * -527978816 + var0.field973 * 128; + int var2 = var0.size * -527978816 + var0.field971 * 128; + int var3 = var0.size * -527978816 + var0.field973 * 128; var0.x += (var2 - var0.x) / var1; var0.y += (var3 - var0.y) / var1; var0.field949 = 0; diff --git a/runescape-client/src/main/java/class32.java b/runescape-client/src/main/java/class32.java index 285f0c56a2..290e8c7952 100644 --- a/runescape-client/src/main/java/class32.java +++ b/runescape-client/src/main/java/class32.java @@ -46,7 +46,7 @@ public class class32 { return; } - URL var3 = new URL(RunException.RunException_applet.getCodeBase(), "clienterror.ws?c=" + RunException.RunException_revision + "&u=" + RunException.localPlayerName + "&v1=" + TaskHandler.javaVendor + "&v2=" + TaskHandler.javaVersion + "&ct=" + class319.field3843 + "&e=" + var2); + URL var3 = new URL(RunException.RunException_applet.getCodeBase(), "clienterror.ws?c=" + RunException.RunException_revision + "&u=" + RunException.localPlayerName + "&v1=" + TaskHandler.javaVendor + "&v2=" + TaskHandler.javaVersion + "&ct=" + ClientType.clientType + "&e=" + var2); DataInputStream var4 = new DataInputStream(var3.openStream()); var4.read(); var4.close(); diff --git a/runescape-client/src/main/java/class325.java b/runescape-client/src/main/java/class325.java index 0c4d47df79..226d7e4e1c 100644 --- a/runescape-client/src/main/java/class325.java +++ b/runescape-client/src/main/java/class325.java @@ -63,8 +63,8 @@ public class class325 { var11 = var0.x; var12 = var0.y; - var4 = var0.pathX[var0.pathLength - 1] * 128 + var0.field932 * -527978816; - int var5 = var0.field932 * -527978816 + var0.pathY[var0.pathLength - 1] * 128; + var4 = var0.pathX[var0.pathLength - 1] * 128 + var0.size * -527978816; + int var5 = var0.size * -527978816 + var0.pathY[var0.pathLength - 1] * 128; if (var11 < var4) { if (var12 < var5) { var0.orientation = 1280; @@ -203,8 +203,8 @@ public class class325 { var0.spotAnimation = -1; var0.field948 = 0; var0.field976 = 0; - var0.x = var0.pathX[0] * 128 + var0.field932 * -527978816; - var0.y = var0.field932 * -527978816 + var0.pathY[0] * 128; + var0.x = var0.pathX[0] * 128 + var0.size * -527978816; + var0.y = var0.size * -527978816 + var0.pathY[0] * 128; var0.method1765(); } @@ -213,8 +213,8 @@ public class class325 { var0.spotAnimation = -1; var0.field948 = 0; var0.field976 = 0; - var0.x = var0.field932 * -527978816 + var0.pathX[0] * 128; - var0.y = var0.field932 * -527978816 + var0.pathY[0] * 128; + var0.x = var0.size * -527978816 + var0.pathX[0] * 128; + var0.y = var0.size * -527978816 + var0.pathY[0] * 128; var0.method1765(); } diff --git a/runescape-client/src/main/java/class4.java b/runescape-client/src/main/java/class4.java index f26b1b5cad..dc7e3353df 100644 --- a/runescape-client/src/main/java/class4.java +++ b/runescape-client/src/main/java/class4.java @@ -152,7 +152,7 @@ final class class4 implements class0 { int var3 = var2.x >> 7; int var4 = var2.y >> 7; if (var3 >= 0 && var3 < 104 && var4 >= 0 && var4 < 104) { - if (var2.field932 * 1669471931 == 1 && (var2.x & 127) == 64 && (var2.y & 127) == 64) { + if (var2.size * 1669471931 == 1 && (var2.x & 127) == 64 && (var2.y & 127) == 64) { if (Client.tileLastDrawnActor[var3][var4] == Client.viewportDrawCount) { continue; } @@ -162,7 +162,7 @@ final class class4 implements class0 { long var5 = class267.calculateTag(0, 0, 1, !var2.definition.isInteractable, Client.npcIndices[var1]); var2.playerCycle = Client.cycle; - PacketWriter.scene.drawEntity(WorldMapRectangle.plane, var2.x, var2.y, MusicPatchPcmStream.getTileHeight(var2.field932 * -527978816 - 64 + var2.x, var2.field932 * -527978816 - 64 + var2.y, WorldMapRectangle.plane), var2.field932 * -527978816 - 64 + 60, var2, var2.rotation, var5, var2.isWalking); + PacketWriter.scene.drawEntity(WorldMapRectangle.plane, var2.x, var2.y, MusicPatchPcmStream.getTileHeight(var2.size * -527978816 - 64 + var2.x, var2.size * -527978816 - 64 + var2.y, WorldMapRectangle.plane), var2.size * -527978816 - 64 + 60, var2, var2.rotation, var5, var2.isWalking); } } } From 6234f209e9cab5b7880b76d69fdefc73d24e1bef Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 30 Sep 2019 09:01:25 -0600 Subject: [PATCH 21/45] runelite-client: Remove Demonic Gorilla Plugin as per Jagex's wishes --- .../demonicgorilla/DemonicGorilla.java | 140 ---- .../demonicgorilla/DemonicGorillaOverlay.java | 154 ---- .../demonicgorilla/DemonicGorillaPlugin.java | 716 ------------------ .../demonicgorilla/MemorizedPlayer.java | 52 -- .../demonicgorilla/PendingGorillaAttack.java | 52 -- 5 files changed, 1114 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorilla.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/MemorizedPlayer.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/PendingGorillaAttack.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorilla.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorilla.java deleted file mode 100644 index 0a96a49635..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorilla.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.demonicgorilla; - -import java.util.Arrays; -import java.util.List; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.Actor; -import net.runelite.api.HeadIcon; -import net.runelite.api.NPC; -import net.runelite.api.NPCComposition; -import net.runelite.api.coords.WorldArea; - -public class DemonicGorilla -{ - static final int MAX_ATTACK_RANGE = 10; // Needs <= 10 tiles to reach target - static final int ATTACK_RATE = 5; // 5 ticks between each attack - static final int ATTACKS_PER_SWITCH = 3; // 3 unsuccessful attacks per style switch - - static final int PROJECTILE_MAGIC_SPEED = 8; // Travels 8 tiles per tick - static final int PROJECTILE_RANGED_SPEED = 6; // Travels 6 tiles per tick - static final int PROJECTILE_MAGIC_DELAY = 12; // Requires an extra 12 tiles - static final int PROJECTILE_RANGED_DELAY = 9; // Requires an extra 9 tiles - - public static final AttackStyle[] ALL_REGULAR_ATTACK_STYLES = - { - AttackStyle.MELEE, - AttackStyle.RANGED, - AttackStyle.MAGIC - }; - - enum AttackStyle - { - MAGIC, - RANGED, - MELEE, - BOULDER - } - - @Getter - private NPC npc; - - @Getter - @Setter - private List nextPosibleAttackStyles; - - @Getter - @Setter - private int attacksUntilSwitch; - - @Getter - @Setter - private int nextAttackTick; - - @Getter - @Setter - private int lastTickAnimation; - - @Getter - @Setter - private WorldArea lastWorldArea; - - @Getter - @Setter - private boolean initiatedCombat; - - @Getter - @Setter - private Actor lastTickInteracting; - - @Getter - @Setter - private boolean takenDamageRecently; - - @Getter - @Setter - private int recentProjectileId; - - @Getter - @Setter - private boolean changedPrayerThisTick; - - @Getter - @Setter - private boolean changedAttackStyleThisTick; - - @Getter - @Setter - private boolean changedAttackStyleLastTick; - - @Getter - @Setter - private HeadIcon lastTickOverheadIcon; - - @Getter - @Setter - private int disabledMeleeMovementForTicks; - - public DemonicGorilla(NPC npc) - { - this.npc = npc; - this.nextPosibleAttackStyles = Arrays.asList(ALL_REGULAR_ATTACK_STYLES); - this.nextAttackTick = -100; - this.attacksUntilSwitch = ATTACKS_PER_SWITCH; - this.recentProjectileId = -1; - } - - public HeadIcon getOverheadIcon() - { - NPCComposition composition = this.npc.getComposition(); - if (composition != null) - { - return composition.getOverheadIcon(); - } - return null; - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java deleted file mode 100644 index 2fa191d5ba..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaOverlay.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.demonicgorilla; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.geom.Arc2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.Skill; -import net.runelite.api.coords.LocalPoint; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -public class DemonicGorillaOverlay extends Overlay -{ - private static final Color COLOR_ICON_BACKGROUND = new Color(0, 0, 0, 128); - private static final Color COLOR_ICON_BORDER = new Color(0, 0, 0, 255); - private static final Color COLOR_ICON_BORDER_FILL = new Color(219, 175, 0, 255); - private static final int OVERLAY_ICON_DISTANCE = 50; - private static final int OVERLAY_ICON_MARGIN = 8; - - private Client client; - private DemonicGorillaPlugin plugin; - - @Inject - private SkillIconManager iconManager; - - @Inject - public DemonicGorillaOverlay(Client client, DemonicGorillaPlugin plugin) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - this.client = client; - this.plugin = plugin; - } - - private BufferedImage getIcon(DemonicGorilla.AttackStyle attackStyle) - { - switch (attackStyle) - { - case MELEE: return iconManager.getSkillImage(Skill.ATTACK); - case RANGED: return iconManager.getSkillImage(Skill.RANGED); - case MAGIC: return iconManager.getSkillImage(Skill.MAGIC); - } - return null; - } - - @Override - public Dimension render(Graphics2D graphics) - { - for (DemonicGorilla gorilla : plugin.getGorillas().values()) - { - if (gorilla.getNpc().getInteracting() == null) - { - continue; - } - - LocalPoint lp = gorilla.getNpc().getLocalLocation(); - if (lp != null) - { - Point point = Perspective.localToCanvas(client, lp, client.getPlane(), - gorilla.getNpc().getLogicalHeight() + 16); - if (point != null) - { - point = new Point(point.getX(), point.getY()); - - List attackStyles = gorilla.getNextPosibleAttackStyles(); - List icons = new ArrayList<>(); - int totalWidth = (attackStyles.size() - 1) * OVERLAY_ICON_MARGIN; - for (DemonicGorilla.AttackStyle attackStyle : attackStyles) - { - BufferedImage icon = getIcon(attackStyle); - icons.add(icon); - totalWidth += icon.getWidth(); - } - - int bgPadding = 4; - int currentPosX = 0; - for (BufferedImage icon : icons) - { - graphics.setStroke(new BasicStroke(2)); - graphics.setColor(COLOR_ICON_BACKGROUND); - graphics.fillOval( - point.getX() - totalWidth / 2 + currentPosX - bgPadding, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, - icon.getWidth() + bgPadding * 2, - icon.getHeight() + bgPadding * 2); - - graphics.setColor(COLOR_ICON_BORDER); - graphics.drawOval( - point.getX() - totalWidth / 2 + currentPosX - bgPadding, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, - icon.getWidth() + bgPadding * 2, - icon.getHeight() + bgPadding * 2); - - graphics.drawImage( - icon, - point.getX() - totalWidth / 2 + currentPosX, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE, - null); - - graphics.setColor(COLOR_ICON_BORDER_FILL); - Arc2D.Double arc = new Arc2D.Double( - point.getX() - totalWidth / 2 + currentPosX - bgPadding, - point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, - icon.getWidth() + bgPadding * 2, - icon.getHeight() + bgPadding * 2, - 90.0, - -360.0 * (DemonicGorilla.ATTACKS_PER_SWITCH - - gorilla.getAttacksUntilSwitch()) / DemonicGorilla.ATTACKS_PER_SWITCH, - Arc2D.OPEN); - graphics.draw(arc); - - currentPosX += icon.getWidth() + OVERLAY_ICON_MARGIN; - } - } - } - } - - return null; - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java deleted file mode 100644 index 0e9660b918..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java +++ /dev/null @@ -1,716 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.demonicgorilla; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.AnimationID; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.HeadIcon; -import net.runelite.api.Hitsplat; -import net.runelite.api.NPC; -import net.runelite.api.NpcID; -import net.runelite.api.Player; -import net.runelite.api.Projectile; -import net.runelite.api.ProjectileID; -import net.runelite.api.coords.WorldArea; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.HitsplatApplied; -import net.runelite.api.events.NpcDespawned; -import net.runelite.api.events.NpcSpawned; -import net.runelite.api.events.PlayerDespawned; -import net.runelite.api.events.PlayerSpawned; -import net.runelite.api.events.ProjectileMoved; -import net.runelite.client.callback.ClientThread; -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; - -@PluginDescriptor( - name = "Demonic Gorillas", - description = "Count demonic gorilla attacks and display their next possible attack styles", - tags = {"combat", "overlay", "pve", "pvm"} -) -public class DemonicGorillaPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private OverlayManager overlayManager; - - @Inject - private DemonicGorillaOverlay overlay; - - @Inject - private ClientThread clientThread; - - @Getter - private Map gorillas; - - private List recentBoulders; - - private List pendingAttacks; - - private Map memorizedPlayers; - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - gorillas = new HashMap<>(); - recentBoulders = new ArrayList<>(); - pendingAttacks = new ArrayList<>(); - memorizedPlayers = new HashMap<>(); - clientThread.invoke(this::reset); // Updates the list of gorillas and players - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - gorillas = null; - recentBoulders = null; - pendingAttacks = null; - memorizedPlayers = null; - } - - private void clear() - { - recentBoulders.clear(); - pendingAttacks.clear(); - memorizedPlayers.clear(); - gorillas.clear(); - } - - private void reset() - { - recentBoulders.clear(); - pendingAttacks.clear(); - resetGorillas(); - resetPlayers(); - } - - private void resetGorillas() - { - gorillas.clear(); - for (NPC npc : client.getNpcs()) - { - if (isNpcGorilla(npc.getId())) - { - gorillas.put(npc, new DemonicGorilla(npc)); - } - } - } - - private void resetPlayers() - { - memorizedPlayers.clear(); - for (Player player : client.getPlayers()) - { - memorizedPlayers.put(player, new MemorizedPlayer(player)); - } - } - - public static boolean isNpcGorilla(int npcId) - { - return npcId == NpcID.DEMONIC_GORILLA || - npcId == NpcID.DEMONIC_GORILLA_7145 || - npcId == NpcID.DEMONIC_GORILLA_7146 || - npcId == NpcID.DEMONIC_GORILLA_7147 || - npcId == NpcID.DEMONIC_GORILLA_7148 || - npcId == NpcID.DEMONIC_GORILLA_7149; - } - - private void checkGorillaAttackStyleSwitch(DemonicGorilla gorilla, - final DemonicGorilla.AttackStyle... protectedStyles) - { - if (gorilla.getAttacksUntilSwitch() <= 0 || - gorilla.getNextPosibleAttackStyles().isEmpty()) - { - gorilla.setNextPosibleAttackStyles(Arrays - .stream(DemonicGorilla.ALL_REGULAR_ATTACK_STYLES) - .filter(x -> Arrays.stream(protectedStyles).noneMatch(y -> x == y)) - .collect(Collectors.toList())); - gorilla.setAttacksUntilSwitch(DemonicGorilla.ATTACKS_PER_SWITCH); - gorilla.setChangedAttackStyleThisTick(true); - } - } - - private DemonicGorilla.AttackStyle getProtectedStyle(Player player) - { - HeadIcon headIcon = player.getOverheadIcon(); - if (headIcon == null) - { - return null; - } - switch (headIcon) - { - case MELEE: - return DemonicGorilla.AttackStyle.MELEE; - case RANGED: - return DemonicGorilla.AttackStyle.RANGED; - case MAGIC: - return DemonicGorilla.AttackStyle.MAGIC; - default: - return null; - } - } - - private void onGorillaAttack(DemonicGorilla gorilla, final DemonicGorilla.AttackStyle attackStyle) - { - gorilla.setInitiatedCombat(true); - - Player target = (Player)gorilla.getNpc().getInteracting(); - - DemonicGorilla.AttackStyle protectedStyle = null; - if (target != null) - { - protectedStyle = getProtectedStyle(target); - } - boolean correctPrayer = - target == null || // If player is out of memory, assume prayer was correct - attackStyle == protectedStyle; - - if (attackStyle == DemonicGorilla.AttackStyle.BOULDER) - { - // The gorilla can't throw boulders when it's meleeing - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - else - { - if (correctPrayer) - { - gorilla.setAttacksUntilSwitch(gorilla.getAttacksUntilSwitch() - 1); - } - else - { - // We're not sure if the attack will hit a 0 or not, - // so we don't know if we should decrease the counter or not, - // so we keep track of the attack here until the damage splat - // has appeared on the player. - - int damagesOnTick = client.getTickCount(); - if (attackStyle == DemonicGorilla.AttackStyle.MAGIC) - { - MemorizedPlayer mp = memorizedPlayers.get(target); - WorldArea lastPlayerArea = mp.getLastWorldArea(); - if (lastPlayerArea != null) - { - int dist = gorilla.getNpc().getWorldArea().distanceTo(lastPlayerArea); - damagesOnTick += (dist + DemonicGorilla.PROJECTILE_MAGIC_DELAY) / - DemonicGorilla.PROJECTILE_MAGIC_SPEED; - } - } - else if (attackStyle == DemonicGorilla.AttackStyle.RANGED) - { - MemorizedPlayer mp = memorizedPlayers.get(target); - WorldArea lastPlayerArea = mp.getLastWorldArea(); - if (lastPlayerArea != null) - { - int dist = gorilla.getNpc().getWorldArea().distanceTo(lastPlayerArea); - damagesOnTick += (dist + DemonicGorilla.PROJECTILE_RANGED_DELAY) / - DemonicGorilla.PROJECTILE_RANGED_SPEED; - } - } - pendingAttacks.add(new PendingGorillaAttack(gorilla, attackStyle, target, damagesOnTick)); - } - - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x == attackStyle) - .collect(Collectors.toList())); - - if (gorilla.getNextPosibleAttackStyles().isEmpty()) - { - // Sometimes the gorilla can switch attack style before it's supposed to - // if someone was fighting it earlier and then left, so we just - // reset the counter in that case. - - gorilla.setNextPosibleAttackStyles(Arrays - .stream(DemonicGorilla.ALL_REGULAR_ATTACK_STYLES) - .filter(x -> x == attackStyle) - .collect(Collectors.toList())); - gorilla.setAttacksUntilSwitch(DemonicGorilla.ATTACKS_PER_SWITCH - - (correctPrayer ? 1 : 0)); - } - } - - checkGorillaAttackStyleSwitch(gorilla, protectedStyle); - - int tickCounter = client.getTickCount(); - gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE); - } - - private void checkGorillaAttacks() - { - int tickCounter = client.getTickCount(); - for (DemonicGorilla gorilla : gorillas.values()) - { - Player interacting = (Player)gorilla.getNpc().getInteracting(); - MemorizedPlayer mp = memorizedPlayers.get(interacting); - - if (gorilla.getLastTickInteracting() != null && interacting == null) - { - gorilla.setInitiatedCombat(false); - } - else if (mp != null && mp.getLastWorldArea() != null && - !gorilla.isInitiatedCombat() && - tickCounter < gorilla.getNextAttackTick() && - gorilla.getNpc().getWorldArea().isInMeleeDistance(mp.getLastWorldArea())) - { - gorilla.setInitiatedCombat(true); - gorilla.setNextAttackTick(tickCounter + 1); - } - - int animationId = gorilla.getNpc().getAnimation(); - - if (gorilla.isTakenDamageRecently() && - tickCounter >= gorilla.getNextAttackTick() + 4) - { - // The gorilla was flinched, so its next attack gets delayed - gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE / 2); - gorilla.setInitiatedCombat(true); - - if (mp != null && mp.getLastWorldArea() != null && - !gorilla.getNpc().getWorldArea().isInMeleeDistance(mp.getLastWorldArea()) && - !gorilla.getNpc().getWorldArea().intersectsWith(mp.getLastWorldArea())) - { - // Gorillas stop meleeing when they get flinched - // and the target isn't in melee distance - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - checkGorillaAttackStyleSwitch(gorilla, DemonicGorilla.AttackStyle.MELEE, - getProtectedStyle(interacting)); - } - } - else if (animationId != gorilla.getLastTickAnimation()) - { - if (animationId == AnimationID.DEMONIC_GORILLA_MELEE_ATTACK) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MELEE); - } - else if (animationId == AnimationID.DEMONIC_GORILLA_MAGIC_ATTACK) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MAGIC); - } - else if (animationId == AnimationID.DEMONIC_GORILLA_RANGED_ATTACK) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.RANGED); - } - else if (animationId == AnimationID.DEMONIC_GORILLA_AOE_ATTACK && interacting != null) - { - // Note that AoE animation is the same as prayer switch animation - // so we need to check if the prayer was switched or not. - // It also does this animation when it spawns, so - // we need the interacting != null check. - - if (gorilla.getOverheadIcon() == gorilla.getLastTickOverheadIcon()) - { - // Confirmed, the gorilla used the AoE attack - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.BOULDER); - } - else - { - if (tickCounter >= gorilla.getNextAttackTick()) - { - gorilla.setChangedPrayerThisTick(true); - - // This part is more complicated because the gorilla may have - // used an attack, but the prayer switch animation takes - // priority over normal attack animations. - - int projectileId = gorilla.getRecentProjectileId(); - if (projectileId == ProjectileID.DEMONIC_GORILLA_MAGIC) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MAGIC); - } - else if (projectileId == ProjectileID.DEMONIC_GORILLA_RANGED) - { - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.RANGED); - } - else if (mp != null) - { - WorldArea lastPlayerArea = mp.getLastWorldArea(); - if (lastPlayerArea != null && - interacting != null && recentBoulders.stream() - .anyMatch(x -> x.distanceTo(lastPlayerArea) == 0)) - { - // A boulder started falling on the gorillas target, - // so we assume it was the gorilla who shot it - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.BOULDER); - } - else if (!mp.getRecentHitsplats().isEmpty()) - { - // It wasn't any of the three other attacks, - // but the player took damage, so we assume - // it's a melee attack - onGorillaAttack(gorilla, DemonicGorilla.AttackStyle.MELEE); - } - } - } - - // The next attack tick is always delayed if the - // gorilla switched prayer - gorilla.setNextAttackTick(tickCounter + DemonicGorilla.ATTACK_RATE); - gorilla.setChangedPrayerThisTick(true); - } - } - } - - if (gorilla.getDisabledMeleeMovementForTicks() > 0) - { - gorilla.setDisabledMeleeMovementForTicks(gorilla.getDisabledMeleeMovementForTicks() - 1); - } - else if (gorilla.isInitiatedCombat() && - gorilla.getNpc().getInteracting() != null && - !gorilla.isChangedAttackStyleThisTick() && - gorilla.getNextPosibleAttackStyles().size() >= 2 && - gorilla.getNextPosibleAttackStyles().stream() - .anyMatch(x -> x == DemonicGorilla.AttackStyle.MELEE)) - { - // If melee is a possibility, we can check if the gorilla - // is or isn't moving toward the player to determine if - // it is actually attempting to melee or not. - // We only run this check if the gorilla is in combat - // because otherwise it attempts to travel to melee - // distance before attacking its target. - - if (mp != null && mp.getLastWorldArea() != null && gorilla.getLastWorldArea() != null) - { - WorldArea predictedNewArea = gorilla.getLastWorldArea().calculateNextTravellingPoint( - client, mp.getLastWorldArea(), true, x -> - { - // Gorillas can't normally walk through other gorillas - // or other players - final WorldArea area1 = new WorldArea(x, 1, 1); - return area1 != null && - gorillas.values().stream().noneMatch(y -> - { - if (y == gorilla) - { - return false; - } - final WorldArea area2 = - y.getNpc().getIndex() < gorilla.getNpc().getIndex() ? - y.getNpc().getWorldArea() : y.getLastWorldArea(); - return area2 != null && area1.intersectsWith(area2); - }) && - memorizedPlayers.values().stream().noneMatch(y -> - { - final WorldArea area2 = y.getLastWorldArea(); - return area2 != null && area1.intersectsWith(area2); - }); - - // There is a special case where if a player walked through - // a gorilla, or a player walked through another player, - // the tiles that were walked through becomes - // walkable, but I didn't feel like it's necessary to handle - // that special case as it should rarely happen. - }); - if (predictedNewArea != null) - { - int distance = gorilla.getNpc().getWorldArea().distanceTo(mp.getLastWorldArea()); - WorldPoint predictedMovement = predictedNewArea.toWorldPoint(); - if (distance <= DemonicGorilla.MAX_ATTACK_RANGE && - mp != null && - mp.getLastWorldArea().hasLineOfSightTo(client, gorilla.getLastWorldArea())) - { - if (predictedMovement.distanceTo(gorilla.getLastWorldArea().toWorldPoint()) != 0) - { - if (predictedMovement.distanceTo(gorilla.getNpc().getWorldLocation()) == 0) - { - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x == DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - else - { - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x != DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - } - else if (tickCounter >= gorilla.getNextAttackTick() && - gorilla.getRecentProjectileId() == -1 && - recentBoulders.stream().noneMatch(x -> x.distanceTo(mp.getLastWorldArea()) == 0)) - { - gorilla.setNextPosibleAttackStyles(gorilla - .getNextPosibleAttackStyles() - .stream() - .filter(x -> x == DemonicGorilla.AttackStyle.MELEE) - .collect(Collectors.toList())); - } - } - } - } - } - - if (gorilla.isTakenDamageRecently()) - { - gorilla.setInitiatedCombat(true); - } - - if (gorilla.getOverheadIcon() != gorilla.getLastTickOverheadIcon()) - { - if (gorilla.isChangedAttackStyleLastTick() || - gorilla.isChangedAttackStyleThisTick()) - { - // Apparently if it changes attack style and changes - // prayer on the same tick or 1 tick apart, it won't - // be able to move for the next 2 ticks if it attempts - // to melee - gorilla.setDisabledMeleeMovementForTicks(2); - } - else - { - // If it didn't change attack style lately, - // it's only for the next 1 tick - gorilla.setDisabledMeleeMovementForTicks(1); - } - } - gorilla.setLastTickAnimation(gorilla.getNpc().getAnimation()); - gorilla.setLastWorldArea(gorilla.getNpc().getWorldArea()); - gorilla.setLastTickInteracting(gorilla.getNpc().getInteracting()); - gorilla.setTakenDamageRecently(false); - gorilla.setChangedPrayerThisTick(false); - gorilla.setChangedAttackStyleLastTick(gorilla.isChangedAttackStyleThisTick()); - gorilla.setChangedAttackStyleThisTick(false); - gorilla.setLastTickOverheadIcon(gorilla.getOverheadIcon()); - gorilla.setRecentProjectileId(-1); - } - } - - @Subscribe - public void onProjectileMoved(ProjectileMoved event) - { - Projectile projectile = event.getProjectile(); - int projectileId = projectile.getId(); - if (projectileId != ProjectileID.DEMONIC_GORILLA_RANGED && - projectileId != ProjectileID.DEMONIC_GORILLA_MAGIC && - projectileId != ProjectileID.DEMONIC_GORILLA_BOULDER) - { - return; - } - - // The event fires once before the projectile starts moving, - // and we only want to check each projectile once - if (client.getGameCycle() >= projectile.getStartMovementCycle()) - { - return; - } - - if (projectileId == ProjectileID.DEMONIC_GORILLA_BOULDER) - { - recentBoulders.add(WorldPoint.fromLocal(client, event.getPosition())); - } - else if (projectileId == ProjectileID.DEMONIC_GORILLA_MAGIC || - projectileId == ProjectileID.DEMONIC_GORILLA_RANGED) - { - WorldPoint projectileSourcePosition = WorldPoint.fromLocal( - client, projectile.getX1(), projectile.getY1(), client.getPlane()); - for (DemonicGorilla gorilla : gorillas.values()) - { - if (gorilla.getNpc().getWorldLocation().distanceTo(projectileSourcePosition) == 0) - { - gorilla.setRecentProjectileId(projectile.getId()); - } - } - } - } - - private void checkPendingAttacks() - { - Iterator it = pendingAttacks.iterator(); - int tickCounter = client.getTickCount(); - while (it.hasNext()) - { - PendingGorillaAttack attack = it.next(); - if (tickCounter >= attack.getFinishesOnTick()) - { - boolean shouldDecreaseCounter = false; - DemonicGorilla gorilla = attack.getAttacker(); - MemorizedPlayer target = memorizedPlayers.get(attack.getTarget()); - if (target == null) - { - // Player went out of memory, so assume the hit was a 0 - shouldDecreaseCounter = true; - } - else if (target.getRecentHitsplats().isEmpty()) - { - // No hitsplats was applied. This may happen in some cases - // where the player was out of memory while the - // projectile was travelling. So we assume the hit was a 0. - shouldDecreaseCounter = true; - } - else if (target.getRecentHitsplats().stream() - .anyMatch(x -> x.getHitsplatType() == Hitsplat.HitsplatType.BLOCK)) - { - // A blue hitsplat appeared, so we assume the gorilla hit a 0 - shouldDecreaseCounter = true; - } - - if (shouldDecreaseCounter) - { - gorilla.setAttacksUntilSwitch(gorilla.getAttacksUntilSwitch() - 1); - checkGorillaAttackStyleSwitch(gorilla); - } - - it.remove(); - } - } - } - - private void updatePlayers() - { - for (MemorizedPlayer mp : memorizedPlayers.values()) - { - mp.setLastWorldArea(mp.getPlayer().getWorldArea()); - mp.getRecentHitsplats().clear(); - } - } - - @Subscribe - public void onHitsplatApplied(HitsplatApplied event) - { - if (gorillas.isEmpty()) - { - return; - } - - if (event.getActor() instanceof Player) - { - Player player = (Player)event.getActor(); - MemorizedPlayer mp = memorizedPlayers.get(player); - if (mp != null) - { - mp.getRecentHitsplats().add(event.getHitsplat()); - } - } - else if (event.getActor() instanceof NPC) - { - DemonicGorilla gorilla = gorillas.get(event.getActor()); - Hitsplat.HitsplatType hitsplatType = event.getHitsplat().getHitsplatType(); - if (gorilla != null && (hitsplatType == Hitsplat.HitsplatType.BLOCK || - hitsplatType == Hitsplat.HitsplatType.DAMAGE)) - { - gorilla.setTakenDamageRecently(true); - } - } - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - GameState gs = event.getGameState(); - if (gs == GameState.LOGGING_IN || - gs == GameState.CONNECTION_LOST || - gs == GameState.HOPPING) - { - reset(); - } - } - - @Subscribe - public void onPlayerSpawned(PlayerSpawned event) - { - if (gorillas.isEmpty()) - { - return; - } - - Player player = event.getPlayer(); - memorizedPlayers.put(player, new MemorizedPlayer(player)); - } - - @Subscribe - public void onPlayerDespawned(PlayerDespawned event) - { - if (gorillas.isEmpty()) - { - return; - } - - memorizedPlayers.remove(event.getPlayer()); - } - - @Subscribe - public void onNpcSpawned(NpcSpawned event) - { - NPC npc = event.getNpc(); - if (isNpcGorilla(npc.getId())) - { - if (gorillas.isEmpty()) - { - // Players are not kept track of when there are no gorillas in - // memory, so we need to add the players that were already in memory. - resetPlayers(); - } - - gorillas.put(npc, new DemonicGorilla(npc)); - } - } - - @Subscribe - public void onNpcDespawned(NpcDespawned event) - { - if (gorillas.remove(event.getNpc()) != null && gorillas.isEmpty()) - { - clear(); - } - } - - @Subscribe - public void onGameTick(GameTick event) - { - checkGorillaAttacks(); - checkPendingAttacks(); - updatePlayers(); - recentBoulders.clear(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/MemorizedPlayer.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/MemorizedPlayer.java deleted file mode 100644 index 7dd0058cd6..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/MemorizedPlayer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.demonicgorilla; - -import java.util.ArrayList; -import java.util.List; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.Hitsplat; -import net.runelite.api.Player; -import net.runelite.api.coords.WorldArea; - -public class MemorizedPlayer -{ - @Getter - private Player player; - - @Getter - @Setter - private WorldArea lastWorldArea; - - @Getter - private List recentHitsplats; - - public MemorizedPlayer(Player player) - { - this.player = player; - this.recentHitsplats = new ArrayList<>(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/PendingGorillaAttack.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/PendingGorillaAttack.java deleted file mode 100644 index 6f3faff8d2..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/PendingGorillaAttack.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.demonicgorilla; - -import lombok.Getter; -import net.runelite.api.Player; - -public class PendingGorillaAttack -{ - @Getter - private DemonicGorilla attacker; - - @Getter - private DemonicGorilla.AttackStyle attackStyle; - - @Getter - private Player target; - - @Getter - private int finishesOnTick; - - public PendingGorillaAttack(DemonicGorilla attacker, DemonicGorilla.AttackStyle attackStyle, - Player target, int finishesOnTick) - { - this.attacker = attacker; - this.attackStyle = attackStyle; - this.target = target; - this.finishesOnTick = finishesOnTick; - } -} \ No newline at end of file From 3819994572a21fbaf2e796323915b0b30b88b046 Mon Sep 17 00:00:00 2001 From: dekvall Date: Tue, 1 Oct 2019 14:05:51 +0200 Subject: [PATCH 22/45] runelite-api: add convexhull to wallobject --- .../src/main/java/net/runelite/api/WallObject.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/WallObject.java b/runelite-api/src/main/java/net/runelite/api/WallObject.java index ddc4a734cd..c9016b4289 100644 --- a/runelite-api/src/main/java/net/runelite/api/WallObject.java +++ b/runelite-api/src/main/java/net/runelite/api/WallObject.java @@ -24,6 +24,8 @@ */ package net.runelite.api; +import java.awt.Polygon; + /** * Represents one or two walls on a tile */ @@ -55,6 +57,15 @@ public interface WallObject extends TileObject */ int getConfig(); + /** + * Gets the convex hull of the objects model. + * + * @return the convex hull + * @see net.runelite.api.model.Jarvis + */ + Polygon getConvexHull(); + Polygon getConvexHull2(); + Renderable getRenderable1(); Renderable getRenderable2(); } From 047861d8cd3ae3c44015db47201123d42d192e2a Mon Sep 17 00:00:00 2001 From: dekvall Date: Tue, 1 Oct 2019 14:28:39 +0200 Subject: [PATCH 23/45] object indicators: add ability to mark wall objects --- .../ObjectIndicatorsOverlay.java | 6 ++++ .../ObjectIndicatorsPlugin.java | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+) 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 f111a6f94f..509b3f5bde 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 @@ -32,6 +32,7 @@ import net.runelite.api.Client; import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; import net.runelite.api.TileObject; +import net.runelite.api.WallObject; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @@ -72,6 +73,11 @@ class ObjectIndicatorsOverlay extends Overlay { polygon = ((GameObject) object).getConvexHull(); } + else if (object instanceof WallObject) + { + polygon = ((WallObject) object).getConvexHull(); + polygon2 = ((WallObject) object).getConvexHull2(); + } else if (object instanceof DecorativeObject) { polygon = ((DecorativeObject) object).getConvexHull(); 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 e305c76ff3..c41e81c6c6 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 @@ -51,6 +51,7 @@ import net.runelite.api.ObjectComposition; import net.runelite.api.Scene; import net.runelite.api.Tile; import net.runelite.api.TileObject; +import net.runelite.api.WallObject; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.GameObjectDespawned; @@ -60,6 +61,9 @@ 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.api.events.WallObjectChanged; +import net.runelite.api.events.WallObjectDespawned; +import net.runelite.api.events.WallObjectSpawned; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyListener; @@ -157,6 +161,28 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener } } + @Subscribe + public void onWallObjectSpawned(WallObjectSpawned event) + { + checkObjectPoints(event.getWallObject()); + } + + @Subscribe + public void onWallObjectChanged(WallObjectChanged event) + { + WallObject previous = event.getPrevious(); + WallObject wallObject = event.getWallObject(); + + objects.remove(previous); + checkObjectPoints(wallObject); + } + + @Subscribe + public void onWallObjectDespawned(WallObjectDespawned event) + { + objects.remove(event.getWallObject()); + } + @Subscribe public void onGameObjectSpawned(GameObjectSpawned event) { @@ -296,6 +322,12 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener final GameObject[] tileGameObjects = tile.getGameObjects(); final DecorativeObject tileDecorativeObject = tile.getDecorativeObject(); + final WallObject tileWallObject = tile.getWallObject(); + + if (tileWallObject != null && tileWallObject.getId() == id) + { + return tileWallObject; + } if (tileDecorativeObject != null && tileDecorativeObject.getId() == id) { From a4cfbc3b423516d488ab4d9cf3a21eb4172bdb98 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 9 Sep 2019 08:19:28 -0600 Subject: [PATCH 24/45] runelite-api: Use more general Shape for clickboxes and convex hulls --- .../src/main/java/net/runelite/api/Actor.java | 3 ++- .../main/java/net/runelite/api/DecorativeObject.java | 6 +++--- .../src/main/java/net/runelite/api/GameObject.java | 6 +++--- .../src/main/java/net/runelite/api/TileObject.java | 4 ++-- .../src/main/java/net/runelite/api/WallObject.java | 6 +++--- .../client/plugins/agility/AgilityOverlay.java | 4 ++-- .../blastfurnace/BlastFurnaceClickBoxOverlay.java | 4 ++-- .../client/plugins/devtools/DevToolsOverlay.java | 11 ++++++----- .../client/plugins/herbiboars/HerbiboarOverlay.java | 6 +++--- .../client/plugins/npchighlight/NpcSceneOverlay.java | 5 +++-- .../objectindicators/ObjectIndicatorsOverlay.java | 6 +++--- .../client/plugins/roguesden/RoguesDenOverlay.java | 7 ++++--- .../client/plugins/runecraft/AbyssOverlay.java | 4 ++-- .../client/plugins/slayer/TargetClickboxOverlay.java | 4 ++-- .../net/runelite/client/ui/overlay/OverlayUtil.java | 10 +++++----- 15 files changed, 45 insertions(+), 41 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Actor.java b/runelite-api/src/main/java/net/runelite/api/Actor.java index 2b35102832..a523555648 100644 --- a/runelite-api/src/main/java/net/runelite/api/Actor.java +++ b/runelite-api/src/main/java/net/runelite/api/Actor.java @@ -26,6 +26,7 @@ package net.runelite.api; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.awt.image.BufferedImage; import javax.annotation.Nullable; import net.runelite.api.annotations.VisibleForDevtools; @@ -218,7 +219,7 @@ public interface Actor extends Renderable * @return the convex hull * @see net.runelite.api.model.Jarvis */ - Polygon getConvexHull(); + Shape getConvexHull(); /** * Gets the world area that the actor occupies. 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 145531fa5d..7dba1a3e65 100644 --- a/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java +++ b/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java @@ -24,7 +24,7 @@ */ package net.runelite.api; -import java.awt.Polygon; +import java.awt.Shape; /** * Represents a decorative object, such as an object on a wall. @@ -37,8 +37,8 @@ public interface DecorativeObject extends TileObject * @return the convex hull * @see net.runelite.api.model.Jarvis */ - Polygon getConvexHull(); - Polygon getConvexHull2(); + Shape getConvexHull(); + Shape getConvexHull2(); Renderable getRenderable(); Renderable getRenderable2(); diff --git a/runelite-api/src/main/java/net/runelite/api/GameObject.java b/runelite-api/src/main/java/net/runelite/api/GameObject.java index c721f35067..2dbf259795 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameObject.java +++ b/runelite-api/src/main/java/net/runelite/api/GameObject.java @@ -24,7 +24,7 @@ */ package net.runelite.api; -import java.awt.Polygon; +import java.awt.Shape; import net.runelite.api.coords.Angle; /** @@ -54,12 +54,12 @@ public interface GameObject extends TileObject Point getSceneMaxLocation(); /** - * Gets the convex hull of the actors model. + * Gets the convex hull of the object's model. * * @return the convex hull * @see net.runelite.api.model.Jarvis */ - Polygon getConvexHull(); + Shape getConvexHull(); /** * Gets the orientation of the object. diff --git a/runelite-api/src/main/java/net/runelite/api/TileObject.java b/runelite-api/src/main/java/net/runelite/api/TileObject.java index e9012d29e4..7c6c606756 100644 --- a/runelite-api/src/main/java/net/runelite/api/TileObject.java +++ b/runelite-api/src/main/java/net/runelite/api/TileObject.java @@ -26,7 +26,7 @@ package net.runelite.api; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import javax.annotation.Nullable; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; @@ -132,5 +132,5 @@ public interface TileObject * @return the clickable area */ @Nullable - Area getClickbox(); + Shape getClickbox(); } diff --git a/runelite-api/src/main/java/net/runelite/api/WallObject.java b/runelite-api/src/main/java/net/runelite/api/WallObject.java index c9016b4289..99e8236942 100644 --- a/runelite-api/src/main/java/net/runelite/api/WallObject.java +++ b/runelite-api/src/main/java/net/runelite/api/WallObject.java @@ -24,7 +24,7 @@ */ package net.runelite.api; -import java.awt.Polygon; +import java.awt.Shape; /** * Represents one or two walls on a tile @@ -63,8 +63,8 @@ public interface WallObject extends TileObject * @return the convex hull * @see net.runelite.api.model.Jarvis */ - Polygon getConvexHull(); - Polygon getConvexHull2(); + Shape getConvexHull(); + Shape getConvexHull2(); Renderable getRenderable1(); Renderable getRenderable2(); 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 e9c205f64f..c012b945dc 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 @@ -29,7 +29,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import java.util.List; import javax.inject.Inject; import net.runelite.api.Client; @@ -90,7 +90,7 @@ class AgilityOverlay extends Overlay } return; } - Area objectClickbox = object.getClickbox(); + Shape objectClickbox = object.getClickbox(); if (objectClickbox != null) { AgilityShortcut agilityShortcut = obstacle.getShortcut(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java index 9dba17df30..ea09b36e63 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java @@ -27,7 +27,7 @@ package net.runelite.client.plugins.blastfurnace; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.geom.Area; +import java.awt.Shape; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.EquipmentInventorySlot; @@ -110,7 +110,7 @@ class BlastFurnaceClickBoxOverlay extends Overlay if (localLocation.distanceTo(location) <= MAX_DISTANCE) { - Area objectClickbox = object.getClickbox(); + Shape objectClickbox = object.getClickbox(); if (objectClickbox != null) { if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) 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 457a86b766..aa2f55bd27 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 @@ -32,6 +32,7 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.geom.Rectangle2D; import java.util.List; import javax.inject.Inject; @@ -286,10 +287,10 @@ class DevToolsOverlay extends Overlay // Draw a polygon around the convex hull // of the model vertices - Polygon p = gameObject.getConvexHull(); + Shape p = gameObject.getConvexHull(); if (p != null) { - graphics.drawPolygon(p); + graphics.draw(p); } } } @@ -330,16 +331,16 @@ class DevToolsOverlay extends Overlay OverlayUtil.renderTileOverlay(graphics, decorObject, "ID: " + decorObject.getId(), DEEP_PURPLE); } - Polygon p = decorObject.getConvexHull(); + Shape p = decorObject.getConvexHull(); if (p != null) { - graphics.drawPolygon(p); + graphics.draw(p); } p = decorObject.getConvexHull2(); if (p != null) { - graphics.drawPolygon(p); + graphics.draw(p); } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java index 653228cdb3..a97f5d9d49 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/herbiboars/HerbiboarOverlay.java @@ -28,7 +28,7 @@ import com.google.inject.Inject; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.geom.Area; +import java.awt.Shape; import java.util.Set; import net.runelite.api.TileObject; import net.runelite.api.coords.WorldPoint; @@ -103,7 +103,7 @@ class HerbiboarOverlay extends Overlay { if (config.showClickBoxes()) { - Area clickbox = object.getClickbox(); + Shape clickbox = object.getClickbox(); if (clickbox != null) { graphics.setColor(config.getObjectColor()); @@ -129,7 +129,7 @@ class HerbiboarOverlay extends Overlay { if (config.showClickBoxes()) { - Area clickbox = object.getClickbox(); + Shape clickbox = object.getClickbox(); if (clickbox != null) { Color col = config.getObjectColor(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index ae252aef93..fef1b03c8a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -30,6 +30,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.text.DecimalFormat; import java.text.NumberFormat; import java.time.Instant; @@ -167,7 +168,7 @@ public class NpcSceneOverlay extends Overlay break; case HULL: - Polygon objectClickbox = actor.getConvexHull(); + Shape objectClickbox = actor.getConvexHull(); renderPoly(graphics, color, objectClickbox); break; @@ -185,7 +186,7 @@ public class NpcSceneOverlay extends Overlay } } - private void renderPoly(Graphics2D graphics, Color color, Polygon polygon) + private void renderPoly(Graphics2D graphics, Color color, Shape polygon) { if (polygon != null) { 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 509b3f5bde..a61aa526dc 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 @@ -26,7 +26,7 @@ package net.runelite.client.plugins.objectindicators; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.Polygon; +import java.awt.Shape; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.DecorativeObject; @@ -66,8 +66,8 @@ class ObjectIndicatorsOverlay extends Overlay continue; } - final Polygon polygon; - Polygon polygon2 = null; + final Shape polygon; + Shape polygon2 = null; if (object instanceof GameObject) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java index 4b5cc234e1..1dc0aa0bc6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java @@ -28,6 +28,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.coords.LocalPoint; @@ -65,11 +66,11 @@ public class RoguesDenOverlay extends Overlay { if (tile.getPlane() == client.getPlane() && obstacle.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) { - Polygon p = tile.getGameObjects()[0].getConvexHull(); + Shape p = tile.getGameObjects()[0].getConvexHull(); if (p != null) { graphics.setColor(Color.CYAN); - graphics.drawPolygon(p); + graphics.draw(p); } } }); @@ -82,7 +83,7 @@ public class RoguesDenOverlay extends Overlay if (p != null) { graphics.setColor(Color.CYAN); - graphics.drawPolygon(p); + graphics.draw(p); } } }); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java index b4d3df3e18..0981628dc9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java @@ -26,7 +26,7 @@ package net.runelite.client.plugins.runecraft; import java.awt.Color; import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import com.google.inject.Inject; import java.awt.Dimension; import java.awt.Graphics2D; @@ -105,7 +105,7 @@ class AbyssOverlay extends Overlay } Point mousePosition = client.getMouseCanvasPosition(); - Area objectClickbox = object.getClickbox(); + Shape objectClickbox = object.getClickbox(); if (objectClickbox != null) { if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java index cc52cf9ac1..52b5b31865 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java @@ -30,7 +30,7 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.Polygon; +import java.awt.Shape; import java.util.List; import javax.inject.Inject; import net.runelite.api.NPC; @@ -71,7 +71,7 @@ public class TargetClickboxOverlay extends Overlay private void renderTargetOverlay(Graphics2D graphics, NPC actor, Color color) { - Polygon objectClickbox = actor.getConvexHull(); + Shape objectClickbox = actor.getConvexHull(); if (objectClickbox != null) { graphics.setColor(color); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index f15bc0124e..912abab8f4 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -31,8 +31,8 @@ import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.RenderingHints; +import java.awt.Shape; import java.awt.Stroke; -import java.awt.geom.Area; import java.awt.image.BufferedImage; import net.runelite.api.Actor; import net.runelite.api.Client; @@ -50,14 +50,14 @@ public class OverlayUtil private static final int MINIMAP_DOT_RADIUS = 4; private static final double UNIT = Math.PI / 1024.0d; - public static void renderPolygon(Graphics2D graphics, Polygon poly, Color color) + public static void renderPolygon(Graphics2D graphics, Shape poly, Color color) { graphics.setColor(color); final Stroke originalStroke = graphics.getStroke(); graphics.setStroke(new BasicStroke(2)); - graphics.drawPolygon(poly); + graphics.draw(poly); graphics.setColor(new Color(0, 0, 0, 50)); - graphics.fillPolygon(poly); + graphics.fill(poly); graphics.setStroke(originalStroke); } @@ -175,7 +175,7 @@ public class OverlayUtil renderImageLocation(client, graphics, localLocation, image, 0); } - public static void renderHoverableArea(Graphics2D graphics, Area area, net.runelite.api.Point mousePosition, Color fillColor, Color borderColor, Color borderHoverColor) + public static void renderHoverableArea(Graphics2D graphics, Shape area, net.runelite.api.Point mousePosition, Color fillColor, Color borderColor, Color borderHoverColor) { if (area != null) { From 293b9cdf7ca8725a46ec770e79390ca8d19dd8dc Mon Sep 17 00:00:00 2001 From: Max Weber Date: Wed, 11 Sep 2019 22:20:28 -0600 Subject: [PATCH 25/45] runelite-api: Add simple Shape implementations --- .../net/runelite/api/geometry/Shapes.java | 212 ++++++++ .../runelite/api/geometry/SimplePolygon.java | 496 ++++++++++++++++++ 2 files changed, 708 insertions(+) create mode 100644 runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java create mode 100644 runelite-api/src/main/java/net/runelite/api/geometry/SimplePolygon.java diff --git a/runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java b/runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java new file mode 100644 index 0000000000..2e02a1cf62 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2019 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.api.geometry; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class Shapes implements Shape +{ + public Shapes(T ...shape) + { + this(Arrays.asList(shape)); + } + + @Getter + private final List shapes; + + @Override + public Rectangle getBounds() + { + int + minX = Integer.MAX_VALUE, + minY = Integer.MAX_VALUE, + maxX = Integer.MIN_VALUE, + maxY = Integer.MIN_VALUE; + + for (Shape shape : shapes) + { + Rectangle bounds = shape.getBounds(); + minX = Math.min(bounds.x, minX); + minY = Math.min(bounds.y, minY); + maxX = Math.max(bounds.x + bounds.width, maxX); + maxY = Math.max(bounds.y + bounds.height, maxY); + } + + return new Rectangle(minX, minY, maxX - minX, maxY - minY); + } + + @Override + public Rectangle2D getBounds2D() + { + double + minX = Double.MAX_VALUE, + minY = Double.MAX_VALUE, + maxX = Double.MIN_VALUE, + maxY = Double.MIN_VALUE; + + for (Shape shape : shapes) + { + Rectangle2D bounds = shape.getBounds2D(); + minX = Math.min(bounds.getX(), minX); + minY = Math.min(bounds.getY(), minY); + maxX = Math.max(bounds.getMaxX(), maxX); + maxY = Math.max(bounds.getMaxY(), maxY); + } + + return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY); + } + + @Override + public boolean contains(double x, double y) + { + return shapes.stream().anyMatch(s -> s.contains(x, y)); + } + + @Override + public boolean contains(Point2D p) + { + return shapes.stream().anyMatch(s -> s.contains(p)); + } + + @Override + public boolean intersects(double x, double y, double w, double h) + { + return shapes.stream().anyMatch(s -> s.intersects(x, y, w, h)); + } + + @Override + public boolean intersects(Rectangle2D r) + { + return shapes.stream().anyMatch(s -> s.intersects(r)); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + return shapes.stream().anyMatch(s -> s.contains(x, y, w, h)); + } + + @Override + public boolean contains(Rectangle2D r) + { + return shapes.stream().anyMatch(s -> s.contains(r)); + } + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + return new ShapeIterator(shapes.stream() + .map(s -> s.getPathIterator(at)) + .iterator()); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return new ShapeIterator(shapes.stream() + .map(s -> s.getPathIterator(at, flatness)) + .iterator()); + } + + private static class ShapeIterator implements PathIterator + { + private final Iterator iter; + private PathIterator current = null; + private final int windingRule; + + ShapeIterator(Iterator iter) + { + this.iter = iter; + if (iter.hasNext()) + { + current = iter.next(); + windingRule = current.getWindingRule(); + checkDone(); + } + else + { + windingRule = 0; + } + } + + @Override + public int getWindingRule() + { + return windingRule; + } + + @Override + public boolean isDone() + { + return current == null; + } + + @Override + public void next() + { + current.next(); + checkDone(); + } + + private void checkDone() + { + for (; current != null && current.isDone(); ) + { + if (iter.hasNext()) + { + current = iter.next(); + assert windingRule == current.getWindingRule(); + } + else + { + current = null; + } + } + } + + @Override + public int currentSegment(float[] coords) + { + return current.currentSegment(coords); + } + + @Override + public int currentSegment(double[] coords) + { + return current.currentSegment(coords); + } + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/geometry/SimplePolygon.java b/runelite-api/src/main/java/net/runelite/api/geometry/SimplePolygon.java new file mode 100644 index 0000000000..bfd136d948 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/geometry/SimplePolygon.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2019 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.api.geometry; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Point; + +/** + * A simple list of vertices that can be append or prepended to + */ +@AllArgsConstructor +@Getter +@Setter +public class SimplePolygon implements Shape +{ + private static final int GROW = 16; + + protected int[] x, y; + protected int left, right; + + public SimplePolygon() + { + this(new int[32], new int[32], 16, 15); + } + + public SimplePolygon(int[] x, int[] y, int length) + { + this(x, y, 0, length - 1); + } + + public void pushLeft(int xCoord, int yCoord) + { + left--; + if (left < 0) + { + expandLeft(GROW); + } + x[left] = xCoord; + y[left] = yCoord; + } + + public void popLeft() + { + left++; + } + + protected void expandLeft(int grow) + { + int[] nx = new int[x.length + grow]; + System.arraycopy(x, 0, nx, grow, x.length); + x = nx; + int[] ny = new int[nx.length]; + System.arraycopy(y, 0, ny, grow, y.length); + y = ny; + left += grow; + right += grow; + } + + public void pushRight(int xCoord, int yCoord) + { + right++; + if (right >= x.length) + { + expandRight(GROW); + } + x[right] = xCoord; + y[right] = yCoord; + } + + public void popRight() + { + right--; + } + + protected void expandRight(int grow) + { + int[] nx = new int[x.length + grow]; + System.arraycopy(x, 0, nx, 0, x.length); + x = nx; + int[] ny = new int[nx.length]; + System.arraycopy(y, 0, ny, 0, y.length); + y = ny; + } + + public int getX(int index) + { + return x[left + index]; + } + + public int getY(int index) + { + return y[left + index]; + } + + public int size() + { + return right - left + 1; + } + + public List toRuneLitePointList() + { + List out = new ArrayList<>(size()); + for (int i = left; i <= right; i++) + { + out.add(new Point(x[i], y[i])); + } + return out; + } + + public void copyTo(int[] xDest, int[] yDest, int offset) + { + System.arraycopy(x, left, xDest, offset, size()); + System.arraycopy(y, left, yDest, offset, size()); + } + + public void appendTo(SimplePolygon other) + { + int size = size(); + if (size <= 0) + { + return; + } + other.expandRight(size); + copyTo(other.x, other.y, other.right + 1); + other.right += size; + } + + public void reverse() + { + int half = size() / 2; + for (int i = 0; i < half; i++) + { + int li = left + i; + int ri = right - i; + int tx = x[li]; + int ty = y[li]; + x[li] = x[ri]; + y[li] = y[ri]; + x[ri] = tx; + y[ri] = ty; + } + } + + /** + * Clips the polygon with the passed convex polygon + */ + public void intersectWithConvex(SimplePolygon convex) + { + // Sutherland-Hodgman + int[] tx = new int[size()]; + int[] ty = new int[tx.length]; + + int cx1 = convex.x[convex.right]; + int cy1 = convex.y[convex.right]; + for (int ci = convex.left; ci <= convex.right; ci++) + { + if (size() < 3) + { + return; + } + + int tRight = this.right; + int tLeft = this.left; + + int[] tmpX = x; + int[] tmpY = y; + + this.x = tx; + this.y = ty; + this.left = 0; + this.right = -1; + tx = tmpX; + ty = tmpY; + + int cx2 = convex.x[ci]; + int cy2 = convex.y[ci]; + + int tx1 = tx[tRight]; + int ty1 = ty[tRight]; + + for (int ti = tLeft; ti <= tRight; ti++) + { + int tx2 = tx[ti]; + int ty2 = ty[ti]; + + int p1 = (cx2 - cx1) * (ty1 - cy1) - (cy2 - cy1) * (tx1 - cx1); + int p2 = (cx2 - cx1) * (ty2 - cy1) - (cy2 - cy1) * (tx2 - cx1); + + if (p1 < 0 && p2 < 0) + { + pushRight(tx2, ty2); + } + else if (p1 >= 0 != p2 >= 0) + { + long nota = cx1 * cy2 - cy1 * cx2; + long clue = tx1 * ty2 - ty1 * tx2; + long div = ((cx1 - cx2) * (ty1 - ty2) - (cy1 - cy2) * (tx1 - tx2)); + pushRight((int) ((nota * (tx1 - tx2) - (cx1 - cx2) * clue) / div), + (int) ((nota * (ty1 - ty2) - (cy1 - cy2) * clue) / div)); + + if (p1 >= 0) + { + pushRight(tx2, ty2); + } + } + + tx1 = tx2; + ty1 = ty2; + } + + cx1 = cx2; + cy1 = cy2; + } + } + + @Override + public Rectangle getBounds() + { + int + minX = Integer.MAX_VALUE, + minY = Integer.MAX_VALUE, + maxX = Integer.MIN_VALUE, + maxY = Integer.MIN_VALUE; + + for (int i = left; i <= right; i++) + { + final int xs = x[i]; + final int ys = y[i]; + + if (xs < minX) + { + minX = xs; + } + if (xs > maxX) + { + maxX = xs; + } + if (ys < minY) + { + minY = ys; + } + if (ys > maxY) + { + maxY = ys; + } + } + + return new Rectangle(minX, minY, maxX - minX, maxY - minY); + } + + @Override + public Rectangle2D getBounds2D() + { + Rectangle b = getBounds(); + return new Rectangle2D.Float(b.x, b.y, b.width, b.height); + } + + @Override + public boolean contains(double cx, double cy) + { + if (size() < 3) + { + return false; + } + + return (crossings(cx, cy, false) & 1) != 0; + } + + private int crossings(double cx, double cy, boolean swap) + { + int collisions = 0; + + int[] x = this.x; + int[] y = this.y; + if (swap) + { + y = this.x; + x = this.y; + } + + for (int x0 = x[right], y0 = y[right], x1, y1, i = left; i <= right; i++, x0 = x1, y0 = y1) + { + x1 = x[i]; + y1 = y[i]; + + if (y0 == y1) + { + continue; + } + + double dy0 = y0, dy1 = y1; + + if (cy <= dy0 == cy <= dy1) + { + continue; + } + + double dx0 = x0, dx1 = x1; + + boolean left = cx < dx0; + if (left == cx < dx1) + { + if (!left) + { + collisions++; + } + continue; + } + + if ((dx1 - dx0) * (cy - dy0) - (cx - dx0) * (dy1 - dy0) > 0 == dy0 > dy1) + { + collisions++; + } + } + return collisions; + } + + @Override + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + @Override + public boolean intersects(double x0, double y0, double w, double h) + { + // this is horribly inefficient, but I don't think it will be called anywhere + + double x1 = x0 + w; + double y1 = y0 + h; + + return crossings(x0, y0, false) != crossings(x1, y0, false) // top + || crossings(x0, y1, false) != crossings(x1, y1, false) // bottom + || crossings(x0, y0, true) != crossings(x0, y1, true) // left + || crossings(x1, y0, true) != crossings(x1, y1, true); // right + + } + + @Override + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + if (!getBounds().contains(x, y, w, h)) + { + return false; + } + + return !intersects(x, y, w, h); + } + + @Override + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + if (at == null) + { + return new SimpleIterator(); + } + return new TransformIterator(at); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return getPathIterator(at); + } + + private class SimpleIterator implements PathIterator + { + private int i = -1; + + @Override + public int getWindingRule() + { + return WIND_EVEN_ODD; + } + + @Override + public boolean isDone() + { + return size() == 0 || i > right; + } + + @Override + public void next() + { + if (i == -1) + { + i = left; + } + else + { + i++; + } + } + + @Override + public int currentSegment(float[] coords) + { + if (i == -1) + { + coords[0] = x[right]; + coords[1] = y[right]; + return SEG_MOVETO; + } + + coords[0] = x[i]; + coords[1] = y[i]; + return SEG_LINETO; + } + + @Override + public int currentSegment(double[] coords) + { + if (i == -1) + { + coords[0] = x[right]; + coords[1] = y[right]; + return SEG_MOVETO; + } + + coords[0] = x[i]; + coords[1] = y[i]; + return SEG_LINETO; + } + } + + private class TransformIterator extends SimpleIterator + { + private final AffineTransform transform; + + TransformIterator(AffineTransform transform) + { + this.transform = transform; + } + + @Override + public int currentSegment(float[] coords) + { + int v = super.currentSegment(coords); + transform.transform(coords, 0, coords, 0, 2); + return v; + } + + @Override + public int currentSegment(double[] coords) + { + int v = super.currentSegment(coords); + transform.transform(coords, 0, coords, 0, 2); + return v; + } + } +} From b77461a3e0e363355f2c1013c97ef62b8ce687de Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 9 Sep 2019 10:33:49 -0600 Subject: [PATCH 26/45] Perspective: Add modelToCanvas This has significantly less overhead than repeatedly calling localToCanvas, and may be vectorized in the future by a smarter jit --- .../java/net/runelite/api/Perspective.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/Perspective.java b/runelite-api/src/main/java/net/runelite/api/Perspective.java index 45469cc00c..e414e89c0d 100644 --- a/runelite-api/src/main/java/net/runelite/api/Perspective.java +++ b/runelite-api/src/main/java/net/runelite/api/Perspective.java @@ -148,7 +148,74 @@ public class Perspective } return null; + } + /** + * Translates a model's vertices into 2d space + */ + public static void modelToCanvas(Client client, int end, int x3dCenter, int y3dCenter, int z3dCenter, int rotate, int[] x3d, int[] y3d, int[] z3d, int[] x2d, int[] y2d) + { + final int + cameraPitch = client.getCameraPitch(), + cameraYaw = client.getCameraYaw(), + + pitchSin = SINE[cameraPitch], + pitchCos = COSINE[cameraPitch], + yawSin = SINE[cameraYaw], + yawCos = COSINE[cameraYaw], + rotateSin = SINE[rotate], + rotateCos = COSINE[rotate], + + cx = x3dCenter - client.getCameraX(), + cy = y3dCenter - client.getCameraY(), + cz = z3dCenter - client.getCameraZ(), + + viewportXMiddle = client.getViewportWidth() / 2, + viewportYMiddle = client.getViewportHeight() / 2, + viewportXOffset = client.getViewportXOffset(), + viewportYOffset = client.getViewportYOffset(), + + zoom3d = client.getScale(); + + for (int i = 0; i < end; i++) + { + int x = x3d[i]; + int y = y3d[i]; + int z = z3d[i]; + + if (rotate != 0) + { + int x0 = x; + x = x0 * rotateCos + y * rotateSin >> 16; + y = y * rotateCos - x0 * rotateSin >> 16; + } + + x += cx; + y += cy; + z += cz; + + final int + x1 = x * yawCos + y * yawSin >> 16, + y1 = y * yawCos - x * yawSin >> 16, + y2 = z * pitchCos - y1 * pitchSin >> 16, + z1 = y1 * pitchCos + z * pitchSin >> 16; + + int viewX, viewY; + + if (z1 < 50) + { + viewX = Integer.MIN_VALUE; + viewY = Integer.MIN_VALUE; + } + else + { + viewX = (viewportXMiddle + x1 * zoom3d / z1) + viewportXOffset; + viewY = (viewportYMiddle + y2 * zoom3d / z1) + viewportYOffset; + } + + x2d[i] = viewX; + y2d[i] = viewY; + } } /** From 80709f1bfa692dfcb0038a80f7fc5c65861290fd Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 9 Sep 2019 10:38:27 -0600 Subject: [PATCH 27/45] Jarvis: use primitive arrays This creates much less garbage and allows use with modelToCanvas --- .../java/net/runelite/api/model/Jarvis.java | 137 ++++++++++++------ 1 file changed, 96 insertions(+), 41 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java b/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java index ba29c86b6d..0c60b84462 100644 --- a/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java +++ b/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java @@ -24,9 +24,9 @@ */ package net.runelite.api.model; -import java.util.ArrayList; import java.util.List; import net.runelite.api.Point; +import net.runelite.api.geometry.SimplePolygon; /** * Provides utility methods for computing the convex hull of a list of @@ -41,92 +41,147 @@ public class Jarvis /** * Computes and returns the convex hull of the passed points. *

- * The size of the list must be at least 4, otherwise this method will + * The size of the list must be at least 3, otherwise this method will * return null. * * @param points list of points * @return list containing the points part of the convex hull */ + @Deprecated public static List convexHull(List points) { - if (points.size() < 3) + int[] xs = new int[points.size()]; + int[] ys = new int[xs.length]; + for (int i = 0; i < xs.length; i++) + { + Point p = points.get(i); + xs[i] = p.getX(); + ys[i] = p.getY(); + } + + SimplePolygon poly = convexHull(xs, ys); + if (poly == null) { return null; } - List ch = new ArrayList<>(); + return poly.toRuneLitePointList(); + } + + /** + * Computes and returns the convex hull of the passed points. + *

+ * The size of the list must be at least 3, otherwise this method will + * return null. + * + * @return a shape the points part of the convex hull + */ + public static SimplePolygon convexHull(int[] xs, int[] ys) + { + int length = xs.length; + + // remove any invalid entries + { + int i = 0, offset = 0; + for (; i < length; i++) + { + if (xs[i] == Integer.MIN_VALUE) + { + offset++; + i++; + break; + } + } + for (; i < length; i++) + { + if (xs[i] == Integer.MIN_VALUE) + { + offset++; + continue; + } + xs[i - offset] = xs[i]; + ys[i - offset] = ys[i]; + } + length -= offset; + } + + if (length < 3) + { + return null; + } // find the left most point - Point left = findLeftMost(points); + int left = findLeftMost(xs, ys, length); // current point we are on - Point current = left; + int current = left; + + SimplePolygon out = new SimplePolygon(new int[16], new int[16], 0); do { - ch.add(current); - assert ch.size() <= points.size() : "hull has more points than graph"; - if (ch.size() > points.size()) + int cx = xs[current]; + int cy = ys[current]; + out.pushRight(cx, cy); + + if (out.size() > length) { - // Just to make sure we never somehow get stuck in this loop return null; } // the next point - all points are to the right of the // line between current and next - Point next = null; + int next = 0; + int nx = xs[next]; + int ny = ys[next]; - for (Point p : points) + for (int i = 1; i < length; i++) { - if (next == null) + long cp = crossProduct(cx, cy, xs[i], ys[i], nx, ny); + if (cp > 0 || (cp == 0 && square(cx - xs[i]) + square(cy - ys[i]) > square(cx - nx) + square(cy - ny))) { - next = p; - continue; + next = i; + nx = xs[next]; + ny = ys[next]; } - - long cp = crossProduct(current, p, next); - if (cp > 0 || (cp == 0 && current.distanceTo(p) > current.distanceTo(next))) - { - next = p; - } - } - - // Points can be null if they are behind or very close to the camera. - if (next == null) - { - return null; } current = next; } while (current != left); - return ch; + return out; } - private static Point findLeftMost(List points) + private static int square(int x) { - Point left = null; + return x * x; + } - for (Point p : points) + private static int findLeftMost(int[] xs, int[] ys, int length) + { + int idx = 0; + int x = xs[idx]; + int y = ys[idx]; + + for (int i = 1; i < length; i++) { - if (left == null || p.getX() < left.getX()) + int ix = xs[i]; + if (ix < x || ix == x && ys[i] < y) { - left = p; - } - else if (p.getX() == left.getX() && p.getY() < left.getY()) - { - left = p; + idx = i; + x = xs[idx]; + y = ys[idx]; } } - return left; + return idx; } - private static long crossProduct(Point p, Point q, Point r) + private static long crossProduct(int px, int py, int qx, int qy, int rx, int ry) { - long val = (long)(q.getY() - p.getY()) * (r.getX() - q.getX()) - - (long)(q.getX() - p.getX()) * (r.getY() - q.getY()); + long val = (long) (qy - py) * (rx - qx) + - (long) (qx - px) * (ry - qy); return val; } } From f16cd53d0920f88d6edeb08c2b9c7f005e910f15 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 9 Sep 2019 10:46:42 -0600 Subject: [PATCH 28/45] runelite-api: Optimize getClickbox - Use the pre-calculated center/extreme xyz fields for the aabb - use modelToCanvas and reduce indirection - Use a specialized union that only does axis-aligned rectangles instead of the Area class - Use a specialized intersection that only does convex polygons, again to avoid Area --- runelite-api/pom.xml | 6 + .../src/main/java/net/runelite/api/Model.java | 1 + .../java/net/runelite/api/Perspective.java | 369 +++++++--------- .../runelite/api/geometry/RectangleUnion.java | 415 ++++++++++++++++++ .../api/geometry/RectangleUnionTest.java | 115 +++++ 5 files changed, 688 insertions(+), 218 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/geometry/RectangleUnion.java create mode 100644 runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index bc24d72ca6..8f2c250c66 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -57,5 +57,11 @@ 4.12 test + + org.slf4j + slf4j-simple + 1.7.12 + test + diff --git a/runelite-api/src/main/java/net/runelite/api/Model.java b/runelite-api/src/main/java/net/runelite/api/Model.java index c287b2afd1..d229a073f7 100644 --- a/runelite-api/src/main/java/net/runelite/api/Model.java +++ b/runelite-api/src/main/java/net/runelite/api/Model.java @@ -103,4 +103,5 @@ public interface Model extends Renderable int getExtremeZ(); int getXYZMag(); + boolean isClickable(); } diff --git a/runelite-api/src/main/java/net/runelite/api/Perspective.java b/runelite-api/src/main/java/net/runelite/api/Perspective.java index e414e89c0d..a248f9e0bb 100644 --- a/runelite-api/src/main/java/net/runelite/api/Perspective.java +++ b/runelite-api/src/main/java/net/runelite/api/Perspective.java @@ -27,20 +27,19 @@ package net.runelite.api; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.geom.Area; +import java.awt.Shape; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; import static net.runelite.api.Constants.TILE_FLAG_BRIDGE; import net.runelite.api.coords.LocalPoint; +import net.runelite.api.geometry.RectangleUnion; +import net.runelite.api.geometry.Shapes; +import net.runelite.api.geometry.SimplePolygon; import net.runelite.api.model.Jarvis; -import net.runelite.api.model.Triangle; -import net.runelite.api.model.Vertex; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -562,244 +561,178 @@ public class Perspective * Get the on-screen clickable area of {@code model} as though it's for the * object on the tile at ({@code localX}, {@code localY}) and rotated to * angle {@code orientation}. - * - * @param client the game client - * @param model the model to calculate a clickbox for + * @param client the game client + * @param model the model to calculate a clickbox for * @param orientation the orientation of the model (0-2048, where 0 is north) - * @param point the coordinate of the tile + * @param point the coordinate of the tile * @return the clickable area of the model */ - public static @Nullable Area getClickbox(@Nonnull Client client, Model model, int orientation, @Nonnull LocalPoint point) + @Nullable + public static Shape getClickbox(@Nonnull Client client, Model model, int orientation, LocalPoint point) { if (model == null) { return null; } - List triangles = model.getTriangles().stream() - .map(triangle -> triangle.rotate(orientation)) - .collect(Collectors.toList()); + int x = point.getX(); + int y = point.getY(); + int z = getTileHeight(client, point, client.getPlane()); - List vertices = model.getVertices().stream() - .map(v -> v.rotate(orientation)) - .collect(Collectors.toList()); + SimplePolygon bounds = calculateAABB(client, model, orientation, x, y, z); - Area clickBox = get2DGeometry(client, triangles, point); - Area visibleAABB = getAABB(client, vertices, point); - - if (visibleAABB == null) + if (bounds == null) { return null; } - clickBox.intersect(visibleAABB); - return clickBox; - } - - /** - * Determine if a given point is off-screen. - * - * @param client - * @param point - * @return - */ - private static boolean isOffscreen(@Nonnull Client client, @Nonnull Point point) - { - return (point.getX() < 0 || point.getX() >= client.getViewportWidth()) - && (point.getY() < 0 || point.getY() >= client.getViewportHeight()); - } - - private static @Nonnull Area get2DGeometry( - @Nonnull Client client, - @Nonnull List triangles, - @Nonnull LocalPoint point - ) - { - int radius = 5; - Area geometry = new Area(); - - final int tileHeight = getTileHeight(client, point, client.getPlane()); - - for (Triangle triangle : triangles) + if (model.isClickable()) { - Vertex _a = triangle.getA(); - Point a = localToCanvas(client, - point.getX() - _a.getX(), - point.getY() - _a.getZ(), - tileHeight + _a.getY()); - if (a == null) - { - continue; - } - - Vertex _b = triangle.getB(); - Point b = localToCanvas(client, - point.getX() - _b.getX(), - point.getY() - _b.getZ(), - tileHeight + _b.getY()); - if (b == null) - { - continue; - } - - Vertex _c = triangle.getC(); - Point c = localToCanvas(client, - point.getX() - _c.getX(), - point.getY() - _c.getZ(), - tileHeight + _c.getY()); - if (c == null) - { - continue; - } - - if (isOffscreen(client, a) && isOffscreen(client, b) && isOffscreen(client, c)) - { - continue; - } - - int minX = Math.min(Math.min(a.getX(), b.getX()), c.getX()); - int minY = Math.min(Math.min(a.getY(), b.getY()), c.getY()); - - // For some reason, this calculation is always 4 pixels short of the actual in-client one - int maxX = Math.max(Math.max(a.getX(), b.getX()), c.getX()) + 4; - int maxY = Math.max(Math.max(a.getY(), b.getY()), c.getY()) + 4; - - Rectangle clickableRect = new Rectangle( - minX - radius, minY - radius, - maxX - minX + radius, maxY - minY + radius - ); - - if (geometry.contains(clickableRect)) - { - continue; - } - - geometry.add(new Area(clickableRect)); + return bounds; } - return geometry; - } - - private static Area getAABB( - @Nonnull Client client, - @Nonnull List vertices, - @Nonnull LocalPoint point - ) - { - int maxX = 0; - int minX = 0; - int maxY = 0; - int minY = 0; - int maxZ = 0; - int minZ = 0; - - for (Vertex vertex : vertices) - { - int x = vertex.getX(); - int y = vertex.getY(); - int z = vertex.getZ(); - - if (x > maxX) - { - maxX = x; - } - if (x < minX) - { - minX = x; - } - - if (y > maxY) - { - maxY = y; - } - if (y < minY) - { - minY = y; - } - - if (z > maxZ) - { - maxZ = z; - } - if (z < minZ) - { - minZ = z; - } - } - - int centerX = (minX + maxX) / 2; - int centerY = (minY + maxY) / 2; - int centerZ = (minZ + maxZ) / 2; - - int extremeX = (maxX - minX + 1) / 2; - int extremeY = (maxY - minY + 1) / 2; - int extremeZ = (maxZ - minZ + 1) / 2; - - if (extremeX < 32) - { - extremeX = 32; - } - - if (extremeZ < 32) - { - extremeZ = 32; - } - - int x1 = point.getX() - (centerX - extremeX); - int y1 = centerY - extremeY; - int z1 = point.getY() - (centerZ - extremeZ); - - int x2 = point.getX() - (centerX + extremeX); - int y2 = centerY + extremeY; - int z2 = point.getY() - (centerZ + extremeZ); - - final int tileHeight = getTileHeight(client, point, client.getPlane()); - - Point p1 = localToCanvas(client, x1, z1, tileHeight + y1); - Point p2 = localToCanvas(client, x1, z2, tileHeight + y1); - Point p3 = localToCanvas(client, x2, z2, tileHeight + y1); - - Point p4 = localToCanvas(client, x2, z1, tileHeight + y1); - Point p5 = localToCanvas(client, x1, z1, tileHeight + y2); - Point p6 = localToCanvas(client, x1, z2, tileHeight + y2); - Point p7 = localToCanvas(client, x2, z2, tileHeight + y2); - Point p8 = localToCanvas(client, x2, z1, tileHeight + y2); - - List points = new ArrayList<>(8); - points.add(p1); - points.add(p2); - points.add(p3); - points.add(p4); - points.add(p5); - points.add(p6); - points.add(p7); - points.add(p8); - - try - { - points = Jarvis.convexHull(points); - } - catch (NullPointerException e) - { - // No non-null screen points for this AABB e.g. for an way off-screen model - return null; - } - - if (points == null) + Shapes bounds2d = calculate2DBounds(client, model, orientation, x, y, z); + if (bounds2d == null) { return null; } - Polygon hull = new Polygon(); - for (Point p : points) + for (SimplePolygon poly : bounds2d.getShapes()) { - if (p != null) - { - hull.addPoint(p.getX(), p.getY()); - } + poly.intersectWithConvex(bounds); } - return new Area(hull); + return bounds2d; + } + + private static SimplePolygon calculateAABB(Client client, Model m, int jauOrient, int x, int y, int z) + { + int ex = m.getExtremeX(); + if (ex == -1) + { + // dynamic models don't get stored when they render where this normally happens + m.calculateBoundsCylinder(); + m.calculateExtreme(0); + ex = m.getExtremeX(); + } + + int x1 = m.getCenterX(); + int y1 = m.getCenterZ(); + int z1 = m.getCenterY(); + + int ey = m.getExtremeZ(); + int ez = m.getExtremeY(); + + int x2 = x1 + ex; + int y2 = y1 + ey; + int z2 = z1 + ez; + + x1 -= ex; + y1 -= ey; + z1 -= ez; + + int[] xa = new int[]{ + x1, x2, x1, x2, + x1, x2, x1, x2 + }; + int[] ya = new int[]{ + y1, y1, y2, y2, + y1, y1, y2, y2 + }; + int[] za = new int[]{ + z1, z1, z1, z1, + z2, z2, z2, z2 + }; + + int[] x2d = new int[8]; + int[] y2d = new int[8]; + + modelToCanvas(client, 8, x, y, z, jauOrient, xa, ya, za, x2d, y2d); + + return Jarvis.convexHull(x2d, y2d); + } + + private static Shapes calculate2DBounds(Client client, Model m, int jauOrient, int x, int y, int z) + { + int[] x2d = new int[m.getVerticesCount()]; + int[] y2d = new int[m.getVerticesCount()]; + + Perspective.modelToCanvas(client, + m.getVerticesCount(), + x, y, z, + jauOrient, + m.getVerticesX(), m.getVerticesZ(), m.getVerticesY(), + x2d, y2d); + + final int radius = 5; + + int[][] tris = new int[][]{ + m.getTrianglesX(), + m.getTrianglesY(), + m.getTrianglesZ() + }; + + int vpX1 = client.getViewportXOffset(); + int vpY1 = client.getViewportXOffset(); + int vpX2 = vpX1 + client.getViewportWidth(); + int vpY2 = vpY1 + client.getViewportHeight(); + + List rects = new ArrayList<>(m.getTrianglesCount()); + + nextTri: + for (int tri = 0; tri < m.getTrianglesCount(); tri++) + { + int + minX = Integer.MAX_VALUE, + minY = Integer.MAX_VALUE, + maxX = Integer.MIN_VALUE, + maxY = Integer.MIN_VALUE; + + for (int[] vertex : tris) + { + final int idx = vertex[tri]; + final int xs = x2d[idx]; + final int ys = y2d[idx]; + + if (xs == Integer.MIN_VALUE || ys == Integer.MIN_VALUE) + { + continue nextTri; + } + + if (xs < minX) + { + minX = xs; + } + if (xs > maxX) + { + maxX = xs; + } + if (ys < minY) + { + minY = ys; + } + if (ys > maxY) + { + maxY = ys; + } + } + + minX -= radius; + minY -= radius; + maxX += radius; + maxY += radius; + + if (vpX1 > maxX || vpX2 < minX || vpY1 > maxY || vpY2 < minY) + { + continue; + } + + RectangleUnion.Rectangle r = new RectangleUnion.Rectangle(minX, minY, maxX, maxY); + + rects.add(r); + } + + return RectangleUnion.union(rects); } /** diff --git a/runelite-api/src/main/java/net/runelite/api/geometry/RectangleUnion.java b/runelite-api/src/main/java/net/runelite/api/geometry/RectangleUnion.java new file mode 100644 index 0000000000..e71f80c6b1 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/geometry/RectangleUnion.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2019 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.api.geometry; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class RectangleUnion +{ + private RectangleUnion() + { + } + + @RequiredArgsConstructor + @Getter + @ToString + public static class Rectangle + { + private final int x1, y1, x2, y2; + } + + /** + * Returns a polygon representing the union of all of the passed rectangles. + * the passed List will be modified + */ + @Nullable + public static Shapes union(List lefts) + { + // https://stackoverflow.com/a/35362615/2977136 + if (lefts.size() == 0) + { + return null; + } + + boolean trace = log.isTraceEnabled(); + + // Sort all of the rectangles so they are ordered by their left edge + lefts.sort(Comparator.comparing(Rectangle::getX1)); + + // Again, but for the right edge + // this should be relatively fast if the rectangles are similar sizes because timsort deals with partially + // presorted data well + List rights = new ArrayList<>(lefts); + rights.sort(Comparator.comparing(Rectangle::getX2)); + + // ranges of our scan line with how many rectangles it is occluding + Segments segments = new Segments(); + Shapes out = new Shapes<>(new ArrayList<>()); + ChangingState cs = new ChangingState(out); + + // Walk a beam left to right, colliding with any vertical edges of rectangles + for (int l = 0, r = 0; ; ) + { + Rectangle lr = null, rr = null; + if (l < lefts.size()) + { + lr = lefts.get(l); + } + if (r < rights.size()) + { + rr = rights.get(r); + } + if (lr == null && rr == null) + { + break; + } + + // get the next edge, preferring + edges + Rectangle rect; + boolean remove = lr == null || (rr != null && rr.x2 < lr.x1); + if (remove) + { + cs.delta = -1; + cs.x = rr.x2; + r++; + rect = rr; + } + else + { + cs.delta = 1; + cs.x = lr.x1; + l++; + rect = lr; + } + if (trace) + { + log.trace("{}{}", remove ? "-" : "+", rect); + } + + int y1 = rect.y1; + int y2 = rect.y2; + + // Find or create the y1 edge + Segment n = segments.findLE(y1); + if (n == null) + { + n = segments.insertAfter(null, y1); + } + if (n.y != y1) + { + n = segments.insertAfter(n, y1); + n.value = n.previous.value; + } + + for (; ; ) + { + // create the y2 edge if the next edge is past + if (n.next == null || n.next.y > y2) + { + segments.insertAfter(n, y2); + } + cs.touch(n); + n = n.next; + if (n.y == y2) + { + cs.finish(n); + + if (trace) + { + for (Segment s = segments.first; s != null; s = s.next) + { + String chunk = ""; + if (s.chunk != null) + { + chunk = (s.left ? ">" : "[") + System.identityHashCode(s.chunk) + (s.left ? "]" : "<"); + } + log.trace("{} = {} {}", s.y, s.value, chunk); + } + log.trace(""); + } + break; + } + } + } + + assert segments.allZero(); + + return out; + } + + @RequiredArgsConstructor + private static class ChangingState + { + final Shapes out; + + int x; + int delta; + + Segment first; + + void touch(Segment s) + { + int oldValue = s.value; + s.value += delta; + if (oldValue <= 0 ^ s.value <= 0) + { + if (first == null) + { + first = s; + } + } + else + { + finish(s); + } + } + + void finish(Segment s) + { + if (first == null) + { + return; + } + + if (first.chunk != null && s.chunk != null) + { + push(first); + push(s); + + if (first.chunk == s.chunk) + { + Chunk c = first.chunk; + first.chunk = null; + s.chunk = null; + c.left = null; + c.right = null; + out.getShapes().add(c); + } + else + { + Chunk leftChunk, rightChunk; + if (!s.left) + { + leftChunk = s.chunk; + rightChunk = first.chunk; + } + else + { + leftChunk = first.chunk; + rightChunk = s.chunk; + } + + log.trace("Joining {} onto {}", System.identityHashCode(rightChunk), System.identityHashCode(leftChunk)); + if (first.left == s.left) + { + log.trace("reverse"); + if (first.left) + { + leftChunk.reverse(); + } + else + { + rightChunk.reverse(); + } + } + log.trace("{} {}", first.y, s.y); + rightChunk.appendTo(leftChunk); + + first.chunk = null; + s.chunk = null; + leftChunk.right.chunk = null; + rightChunk.left.chunk = null; + leftChunk.right = rightChunk.right; + leftChunk.left.chunk = leftChunk; + leftChunk.right.chunk = leftChunk; + } + } + else if (first.chunk == null && s.chunk == null) + { + first.chunk = new Chunk(); + first.chunk.right = first; + first.left = false; + s.chunk = first.chunk; + first.chunk.left = s; + s.left = true; + + push(first); + push(s); + } + else if (first.chunk == null) + { + push(s); + move(first, s); + push(first); + } + else + { + push(first); + move(s, first); + push(s); + } + + first = null; + } + + private void move(Segment dst, Segment src) + { + dst.chunk = src.chunk; + dst.left = src.left; + src.chunk = null; + if (dst.left) + { + assert dst.chunk.left == src; + dst.chunk.left = dst; + } + else + { + assert dst.chunk.right == src; + dst.chunk.right = dst; + } + } + + private void push(Segment s) + { + if (s.left) + { + s.chunk.pushLeft(x, s.y); + assert s.chunk.left == s; + } + else + { + s.chunk.pushRight(x, s.y); + assert s.chunk.right == s; + } + } + } + + @NoArgsConstructor + private static class Segment + { + Segment next, previous; + + Chunk chunk; + boolean left; + int y; + int value; + } + + @NoArgsConstructor + private static class Segments + { + Segment first; + + Segment findLE(int y) + { + Segment s = first; + if (s == null || s.y > y) + { + return null; + } + for (; ; ) + { + if (s.y == y) + { + return s; + } + + Segment n = s.next; + if (n == null || n.y > y) + { + return s; + } + + s = n; + } + } + + Segment insertAfter(Segment before, int y) + { + Segment n = new Segment(); + n.y = y; + if (before != null) + { + if (before.next != null) + { + n.next = before.next; + n.next.previous = n; + } + n.value = before.value; + before.next = n; + n.previous = before; + } + else + { + if (first != null) + { + n.next = first; + first.previous = n; + } + first = n; + } + return n; + } + + boolean allZero() + { + for (Segment s = first; s != null; s = s.next) + { + if (s.value != 0 || s.chunk != null) + { + return false; + } + } + return true; + } + } + + private static class Chunk extends SimplePolygon + { + Segment left, right; + + @Override + public void reverse() + { + super.reverse(); + assert right.left == false; + assert left.left == true; + Segment tr = left; + left = right; + right = tr; + right.left = false; + left.left = true; + } + } +} diff --git a/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java b/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java new file mode 100644 index 0000000000..f8d714180b --- /dev/null +++ b/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2019 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.api.geometry; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import javax.imageio.ImageIO; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; + +@Slf4j +public class RectangleUnionTest +{ + private static final int ITERATIONS = 100; + private static final int WIDTH = 1000; + private static final int MAX_RECTS = 50; + + // @Test + public void test() throws IOException + { + for (int count = 1; count < MAX_RECTS; count++) + { + for (int r = 0; r < ITERATIONS; r++) + { + Random rand = new Random(count << 16 | r); + String id = count + "rects_iteration" + r; + log.info(id); + BufferedImage wanted = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_BYTE_BINARY); + BufferedImage got = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_BYTE_BINARY); + + Graphics2D wg = wanted.createGraphics(); + wg.setColor(Color.WHITE); + Graphics2D gg = got.createGraphics(); + gg.setColor(Color.WHITE); + + List rects = new ArrayList<>(count); + + for (int i = 0; i < count; i++) + { + int x1, y1, x2, y2; + + do + { + x1 = rand.nextInt(WIDTH); + x2 = rand.nextInt(WIDTH); + } + while (x1 >= x2); + + do + { + y1 = rand.nextInt(WIDTH); + y2 = rand.nextInt(WIDTH); + } + while (y1 >= y2); + + RectangleUnion.Rectangle rect = new RectangleUnion.Rectangle(x1, y1, x2, y2); + log.trace("{}", rect); + rects.add(rect); + + wg.fillRect(x1, y1, x2 - x1, y2 - y1); + } + + Shape union = RectangleUnion.union(rects); + + gg.fill(union); + + loop: + for (int x = 0; x < WIDTH; x++) + { + for (int y = 0; y < WIDTH; y++) + { + if (wanted.getRGB(x, y) != got.getRGB(x, y)) + { + File tmp = new File(System.getProperty("java.io.tmpdir")); + ImageIO.write(wanted, "png", new File(tmp, id + "_wanted.png")); + ImageIO.write(got, "png", new File(tmp, id + "_got.png")); + + Assert.fail(id); + break loop; + } + } + } + } + } + } +} \ No newline at end of file From 9e696ac3f2e6099460df51bee4079e636c0830a1 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 9 Sep 2019 19:31:57 -0600 Subject: [PATCH 29/45] runelite-api: Remove Triangle and Vertex classes --- .../src/main/java/net/runelite/api/Model.java | 18 ----- .../java/net/runelite/api/model/Triangle.java | 54 --------------- .../java/net/runelite/api/model/Vertex.java | 65 ------------------- 3 files changed, 137 deletions(-) delete mode 100644 runelite-api/src/main/java/net/runelite/api/model/Triangle.java delete mode 100644 runelite-api/src/main/java/net/runelite/api/model/Vertex.java diff --git a/runelite-api/src/main/java/net/runelite/api/Model.java b/runelite-api/src/main/java/net/runelite/api/Model.java index d229a073f7..4e5332e2f2 100644 --- a/runelite-api/src/main/java/net/runelite/api/Model.java +++ b/runelite-api/src/main/java/net/runelite/api/Model.java @@ -24,29 +24,11 @@ */ package net.runelite.api; -import java.util.List; -import net.runelite.api.model.Triangle; -import net.runelite.api.model.Vertex; - /** * Represents the model of an object. */ public interface Model extends Renderable { - /** - * Gets a list of all vertices of the model. - * - * @return the vertices - */ - List getVertices(); - - /** - * Gets a list of all triangles of the model. - * - * @return the triangle - */ - List getTriangles(); - int getVerticesCount(); int[] getVerticesX(); diff --git a/runelite-api/src/main/java/net/runelite/api/model/Triangle.java b/runelite-api/src/main/java/net/runelite/api/model/Triangle.java deleted file mode 100644 index daf59c2489..0000000000 --- a/runelite-api/src/main/java/net/runelite/api/model/Triangle.java +++ /dev/null @@ -1,54 +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.api.model; - -import lombok.Value; - -/** - * Represents 3 vertices as a three-dimensional Triangle. - */ -@Value -public class Triangle -{ - private final Vertex a; - private final Vertex b; - private final Vertex c; - - /** - * Rotates the triangle by the given orientation. - * - * @param orientation passed orientation - * @return new instance - */ - public Triangle rotate(int orientation) - { - return new Triangle( - a.rotate(orientation), - b.rotate(orientation), - c.rotate(orientation) - ); - } - -} diff --git a/runelite-api/src/main/java/net/runelite/api/model/Vertex.java b/runelite-api/src/main/java/net/runelite/api/model/Vertex.java deleted file mode 100644 index b59a7d7891..0000000000 --- a/runelite-api/src/main/java/net/runelite/api/model/Vertex.java +++ /dev/null @@ -1,65 +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.api.model; - -import lombok.Value; -import net.runelite.api.Perspective; - -/** - * Represents a point in a three-dimensional space. - */ -@Value -public class Vertex -{ - private final int x; - private final int y; - private final int z; - - /** - * Rotates the triangle by the given orientation. - * - * @param orientation passed orientation - * @return new instance - */ - public Vertex rotate(int orientation) - { - // models are orientated north (1024) and there are 2048 angles total - orientation = (orientation + 1024) % 2048; - - if (orientation == 0) - { - return this; - } - - int sin = Perspective.SINE[orientation]; - int cos = Perspective.COSINE[orientation]; - - return new Vertex( - x * cos + z * sin >> 16, - y, - z * cos - x * sin >> 16 - ); - } -} From b15bf1c22118d6f8d9c9efbd47ce686a0f862d40 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 1 Oct 2019 21:53:48 -0400 Subject: [PATCH 30/45] world hopper: add ping to tags --- .../runelite/client/plugins/worldhopper/WorldHopperPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index a02401e795..96aad43f11 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -93,7 +93,8 @@ import org.apache.commons.lang3.ArrayUtils; @PluginDescriptor( name = "World Hopper", - description = "Allows you to quickly hop worlds" + description = "Allows you to quickly hop worlds", + tags = {"ping"} ) @Slf4j public class WorldHopperPlugin extends Plugin From 1549bc63d79aa07a1c0e86d528524f7098921cf2 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Wed, 2 Oct 2019 12:51:41 +0000 Subject: [PATCH 31/45] [maven-release-plugin] prepare release runelite-parent-1.5.35 --- 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-script-assembler-plugin/pom.xml | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index 88d32c2985..a55293f657 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 7d42489f5b..4ed7f2d2e9 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 77756e056c..0e1ecb0f26 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 cache diff --git a/http-api/pom.xml b/http-api/pom.xml index 00ce6f4808..c7207f80c4 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 3d129ddac7..47d16414fb 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 Web Service diff --git a/pom.xml b/pom.xml index b41e6948c1..bfc2c9310b 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 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.35 diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index f54c525380..234a7841a7 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index 84c404c3f5..d20bc19839 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index bc24d72ca6..8fa47f73ea 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 70adbefb09..29111ace0e 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35-SNAPSHOT + 1.5.35 client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index 6a73a3a31b..e051b7a81b 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.35-SNAPSHOT + 1.5.35 script-assembler-plugin From 03c4422628b94160ef3970bfa11317369f1c8698 Mon Sep 17 00:00:00 2001 From: Runelite auto updater Date: Wed, 2 Oct 2019 12:51:48 +0000 Subject: [PATCH 32/45] [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-script-assembler-plugin/pom.xml | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cache-client/pom.xml b/cache-client/pom.xml index a55293f657..9e2da34d4c 100644 --- a/cache-client/pom.xml +++ b/cache-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT cache-client diff --git a/cache-updater/pom.xml b/cache-updater/pom.xml index 4ed7f2d2e9..c8c34e2059 100644 --- a/cache-updater/pom.xml +++ b/cache-updater/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT Cache Updater diff --git a/cache/pom.xml b/cache/pom.xml index 0e1ecb0f26..e82ec87614 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT cache diff --git a/http-api/pom.xml b/http-api/pom.xml index c7207f80c4..b9c5bd1aab 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT Web API diff --git a/http-service/pom.xml b/http-service/pom.xml index 47d16414fb..05b3b911f7 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT Web Service diff --git a/pom.xml b/pom.xml index bfc2c9310b..90b3bd9b60 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-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.35 + HEAD diff --git a/protocol-api/pom.xml b/protocol-api/pom.xml index 234a7841a7..469eeffed9 100644 --- a/protocol-api/pom.xml +++ b/protocol-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT protocol-api diff --git a/protocol/pom.xml b/protocol/pom.xml index d20bc19839..d548031afa 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT protocol diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml index 8fa47f73ea..fe99f48577 100644 --- a/runelite-api/pom.xml +++ b/runelite-api/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT runelite-api diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 29111ace0e..a87e7f816b 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -29,7 +29,7 @@ net.runelite runelite-parent - 1.5.35 + 1.5.36-SNAPSHOT client diff --git a/runelite-script-assembler-plugin/pom.xml b/runelite-script-assembler-plugin/pom.xml index e051b7a81b..da0cc3fc3e 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.35 + 1.5.36-SNAPSHOT script-assembler-plugin From 1e58a77683de2598d1907b0cac57d4e2a156ef80 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 27 Sep 2019 22:15:46 -0400 Subject: [PATCH 33/45] item controller: add etag to bulk prices --- .../http/service/item/ItemController.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java b/http-service/src/main/java/net/runelite/http/service/item/ItemController.java index 9d1ed5710e..8db56ef2ff 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java +++ b/http-service/src/main/java/net/runelite/http/service/item/ItemController.java @@ -28,6 +28,9 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; import java.time.Instant; import java.util.Arrays; import java.util.List; @@ -53,20 +56,39 @@ public class ItemController private static final String RUNELITE_CACHE = "RuneLite-Cache"; private static final int MAX_BATCH_LOOKUP = 1024; + private static class MemoizedPrices + { + final ItemPrice[] prices; + final String hash; + + MemoizedPrices(ItemPrice[] prices) + { + this.prices = prices; + + Hasher hasher = Hashing.sha256().newHasher(); + for (ItemPrice itemPrice : prices) + { + hasher.putInt(itemPrice.getId()).putInt(itemPrice.getPrice()); + } + HashCode code = hasher.hash(); + hash = code.toString(); + } + } + private final Cache cachedEmpty = CacheBuilder.newBuilder() .maximumSize(1024L) .build(); private final ItemService itemService; - private final Supplier memorizedPrices; + private final Supplier memoizedPrices; @Autowired public ItemController(ItemService itemService) { this.itemService = itemService; - memorizedPrices = Suppliers.memoizeWithExpiration(() -> itemService.fetchPrices().stream() + memoizedPrices = Suppliers.memoizeWithExpiration(() -> new MemoizedPrices(itemService.fetchPrices().stream() .map(priceEntry -> { ItemPrice itemPrice = new ItemPrice(); @@ -76,7 +98,7 @@ public class ItemController itemPrice.setTime(priceEntry.getTime()); return itemPrice; }) - .toArray(ItemPrice[]::new), 30, TimeUnit.MINUTES); + .toArray(ItemPrice[]::new)), 30, TimeUnit.MINUTES); } @GetMapping("/{itemId}") @@ -220,8 +242,10 @@ public class ItemController @GetMapping("/prices") public ResponseEntity prices() { + MemoizedPrices memorizedPrices = this.memoizedPrices.get(); return ResponseEntity.ok() + .eTag(memorizedPrices.hash) .cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic()) - .body(memorizedPrices.get()); + .body(memorizedPrices.prices); } } From cade74c18cf965ec79dd13fe0cf4de0e09a314b8 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 27 Sep 2019 22:16:02 -0400 Subject: [PATCH 34/45] feed controller: add etag --- .../http/service/feed/FeedController.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 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 c679cd319f..480478c9d0 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 @@ -24,6 +24,9 @@ */ package net.runelite.http.service.feed; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -51,7 +54,26 @@ public class FeedController private final TwitterService twitterService; private final OSRSNewsService osrsNewsService; - private FeedResult feedResult; + private static class MemoizedFeed + { + final FeedResult feedResult; + final String hash; + + MemoizedFeed(FeedResult feedResult) + { + this.feedResult = feedResult; + + Hasher hasher = Hashing.sha256().newHasher(); + for (FeedItem itemPrice : feedResult.getItems()) + { + hasher.putBytes(itemPrice.getTitle().getBytes()).putBytes(itemPrice.getContent().getBytes()); + } + HashCode code = hasher.hash(); + hash = code.toString(); + } + } + + private MemoizedFeed memoizedFeed; @Autowired public FeedController(BlogService blogService, TwitterService twitterService, OSRSNewsService osrsNewsService) @@ -93,20 +115,21 @@ public class FeedController log.warn(e.getMessage()); } - feedResult = new FeedResult(items); + memoizedFeed = new MemoizedFeed(new FeedResult(items)); } @GetMapping public ResponseEntity getFeed() { - if (feedResult == null) + if (memoizedFeed == null) { return ResponseEntity.notFound() .build(); } return ResponseEntity.ok() + .eTag(memoizedFeed.hash) .cacheControl(CacheControl.maxAge(10, TimeUnit.MINUTES).cachePublic()) - .body(feedResult); + .body(memoizedFeed.feedResult); } } From d6041bdc55d9290f645e93115200b750eb5fa9b3 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 27 Sep 2019 22:18:45 -0400 Subject: [PATCH 35/45] client: use own okhttp client with cache --- .../src/main/java/net/runelite/client/RuneLiteModule.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java index 525a0f23b6..5d9bbf1531 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java @@ -28,6 +28,7 @@ import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.name.Names; import java.applet.Applet; +import java.io.File; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Supplier; @@ -49,12 +50,15 @@ import net.runelite.client.task.Scheduler; import net.runelite.client.util.DeferredEventBus; import net.runelite.client.util.ExecutorServiceExceptionLogger; import net.runelite.http.api.RuneLiteAPI; +import okhttp3.Cache; import okhttp3.OkHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RuneLiteModule extends AbstractModule { + private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb + private final Supplier clientLoader; private final boolean developerMode; @@ -69,7 +73,9 @@ public class RuneLiteModule extends AbstractModule { bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode); bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor())); - bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT); + bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT.newBuilder() + .cache(new Cache(new File(RuneLite.RUNELITE_DIR, "cache" + File.separator + "okhttp"), MAX_OKHTTP_CACHE_SIZE)) + .build()); bind(MenuManager.class); bind(ChatMessageManager.class); bind(ItemManager.class); From 1fa840926583b37d1d6cccafd07afe31ba9f1ebc Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 28 Sep 2019 10:11:34 -0400 Subject: [PATCH 36/45] http-api: add javax.inject dependency --- http-api/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/http-api/pom.xml b/http-api/pom.xml index b9c5bd1aab..a0b31501c9 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -63,6 +63,11 @@ commons-csv 1.4 + + javax.inject + javax.inject + 1 + junit From 2af98eacfc84c61f3ed2dc7b8298f63c7e1e41f4 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 27 Sep 2019 22:19:46 -0400 Subject: [PATCH 37/45] feed: use caching okhttp client --- .../java/net/runelite/http/api/feed/FeedClient.java | 12 +++++++++++- .../net/runelite/client/plugins/feed/FeedPlugin.java | 4 +++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java b/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java index 6b05ad20ba..bf4698315c 100644 --- a/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java +++ b/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java @@ -28,8 +28,10 @@ import com.google.gson.JsonParseException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import javax.inject.Inject; import net.runelite.http.api.RuneLiteAPI; import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; @@ -39,6 +41,14 @@ public class FeedClient { private static final Logger logger = LoggerFactory.getLogger(FeedClient.class); + private final OkHttpClient client; + + @Inject + public FeedClient(OkHttpClient client) + { + this.client = client; + } + public FeedResult lookupFeed() throws IOException { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() @@ -51,7 +61,7 @@ public class FeedClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java index 8a34a73cf1..89c7ef3c5a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java @@ -64,10 +64,12 @@ public class FeedPlugin extends Plugin @Inject private ScheduledExecutorService executorService; + @Inject + private FeedClient feedClient; + private FeedPanel feedPanel; private NavigationButton navButton; - private FeedClient feedClient = new FeedClient(); private Supplier feedSupplier = Suppliers.memoizeWithExpiration(() -> { try From 9c5b36cec7db880394d8b4b7375ff0b12c1d22d8 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 27 Sep 2019 22:21:42 -0400 Subject: [PATCH 38/45] item manager: use caching okhttp client --- .../runelite/http/api/item/ItemClient.java | 22 ++++++++++++++----- .../net/runelite/client/game/ItemManager.java | 6 +++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java b/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java index 17784dd67b..d1262e32c6 100644 --- a/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java +++ b/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java @@ -34,8 +34,10 @@ import java.lang.reflect.Type; import java.util.Arrays; import java.util.Map; import javax.imageio.ImageIO; +import javax.inject.Inject; import net.runelite.http.api.RuneLiteAPI; import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; @@ -45,6 +47,14 @@ public class ItemClient { private static final Logger logger = LoggerFactory.getLogger(ItemClient.class); + private final OkHttpClient client; + + @Inject + public ItemClient(OkHttpClient client) + { + this.client = client; + } + public ItemPrice lookupItemPrice(int itemId) throws IOException { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() @@ -59,7 +69,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -95,7 +105,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -126,7 +136,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -156,7 +166,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -187,7 +197,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -219,7 +229,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { 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 e758d66969..88cb65b466 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 @@ -84,7 +84,7 @@ public class ItemManager private final ScheduledExecutorService scheduledExecutorService; private final ClientThread clientThread; - private final ItemClient itemClient = new ItemClient(); + private final ItemClient itemClient; private Map itemPrices = Collections.emptyMap(); private Map itemStats = Collections.emptyMap(); private final LoadingCache itemImages; @@ -155,11 +155,13 @@ public class ItemManager build(); @Inject - public ItemManager(Client client, ScheduledExecutorService executor, ClientThread clientThread) + public ItemManager(Client client, ScheduledExecutorService executor, ClientThread clientThread, + ItemClient itemClient) { this.client = client; this.scheduledExecutorService = executor; this.clientThread = clientThread; + this.itemClient = itemClient; scheduledExecutorService.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES); scheduledExecutorService.submit(this::loadStats); From f49670cd5b494daf6b59e916b9ae0f3aa52394b5 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 27 Sep 2019 23:40:56 -0400 Subject: [PATCH 39/45] Use caching okhttp client for worldclient --- .../runelite/http/api/worlds/WorldClient.java | 19 ++++++++++++++----- .../defaultworld/DefaultWorldPlugin.java | 6 ++++-- .../worldhopper/WorldHopperPlugin.java | 5 ++++- .../net/runelite/client/rs/HostSupplier.java | 6 ++++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java b/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java index 668e088404..8e08d0c9b1 100644 --- a/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java +++ b/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java @@ -26,21 +26,30 @@ package net.runelite.http.api.worlds; import com.google.gson.JsonParseException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import javax.inject.Inject; import net.runelite.http.api.RuneLiteAPI; import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - public class WorldClient { private static final Logger logger = LoggerFactory.getLogger(WorldClient.class); + private final OkHttpClient client; + + @Inject + public WorldClient(OkHttpClient client) + { + this.client = client; + } + public WorldResult lookupWorlds() throws IOException { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() @@ -53,7 +62,7 @@ public class WorldClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java index d68791d289..ef987c2cc7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java @@ -31,9 +31,9 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.events.GameStateChanged; -import net.runelite.client.events.SessionOpen; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionOpen; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.util.WorldUtil; @@ -55,7 +55,9 @@ public class DefaultWorldPlugin extends Plugin @Inject private DefaultWorldConfig config; - private final WorldClient worldClient = new WorldClient(); + @Inject + private WorldClient worldClient; + private int worldCache; private boolean worldChangeRequired; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index 96aad43f11..09fa7b747b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -140,6 +140,9 @@ public class WorldHopperPlugin extends Plugin @Inject private WorldHopperPingOverlay worldHopperOverlay; + @Inject + private WorldClient worldClient; + private ScheduledExecutorService hopperExecutorService; private NavigationButton navButton; @@ -508,7 +511,7 @@ public class WorldHopperPlugin extends Plugin try { - WorldResult worldResult = new WorldClient().lookupWorlds(); + WorldResult worldResult = worldClient.lookupWorlds(); if (worldResult != null) { diff --git a/runelite-client/src/main/java/net/runelite/client/rs/HostSupplier.java b/runelite-client/src/main/java/net/runelite/client/rs/HostSupplier.java index b92f9bb074..cd75157ac1 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/HostSupplier.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/HostSupplier.java @@ -33,6 +33,8 @@ import java.util.Random; import java.util.function.Supplier; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; +import net.runelite.http.api.RuneLiteAPI; +import net.runelite.http.api.worlds.World; import net.runelite.http.api.worlds.WorldClient; @Slf4j @@ -51,11 +53,11 @@ class HostSupplier implements Supplier try { - List newHosts = new WorldClient() + List newHosts = new WorldClient(RuneLiteAPI.CLIENT) .lookupWorlds() .getWorlds() .stream() - .map(i -> i.getAddress()) + .map(World::getAddress) .collect(Collectors.toList()); Collections.shuffle(newHosts, random); From d6772a3be4f228a6e686ac1e3f5036cdba69d2e6 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 2 Oct 2019 18:59:05 -0400 Subject: [PATCH 40/45] tile indicators: fix storing names for multilocs This was storing "null" for multilocs whose base name is "null", which caused a lot of unintentional matches against objects on the tile with no names. --- .../ObjectIndicatorsPlugin.java | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) 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 c41e81c6c6..7b91196592 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 @@ -37,9 +37,11 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import javax.inject.Inject; import lombok.AccessLevel; 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; @@ -78,6 +80,7 @@ import net.runelite.client.ui.overlay.OverlayManager; tags = {"overlay", "objects", "mark", "marker"}, enabledByDefault = false ) +@Slf4j public class ObjectIndicatorsPlugin extends Plugin implements KeyListener { private static final String CONFIG_GROUP = "objectindicators"; @@ -279,9 +282,13 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener return; } - ObjectComposition objectDefinition = client.getObjectDefinition(object.getId()); + // object.getId() is always the base object id, getObjectComposition transforms it to + // the correct object we see + ObjectComposition objectDefinition = getObjectComposition(object.getId()); String name = objectDefinition.getName(); - if (Strings.isNullOrEmpty(name)) + // Name is probably never "null" - however prevent adding it if it is, as it will + // become ambiguous as objects with no name are assigned name "null" + if (Strings.isNullOrEmpty(name) || name.equals("null")) { return; } @@ -304,8 +311,10 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener if ((worldPoint.getX() & (REGION_SIZE - 1)) == objectPoint.getRegionX() && (worldPoint.getY() & (REGION_SIZE - 1)) == objectPoint.getRegionY()) { - if (objectPoint.getName().equals(client.getObjectDefinition(object.getId()).getName())) + // Transform object to get the name which matches against what we've stored + if (objectPoint.getName().equals(getObjectComposition(object.getId()).getName())) { + log.debug("Marking object {} due to matching {}", object, objectPoint); objects.add(object); break; } @@ -346,7 +355,8 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener return object; } - // Check impostors + // Menu action EXAMINE_OBJECT sends the transformed object id, not the base id, unlike + // all of the GAME_OBJECT_OPTION actions, so check the id against the impostor ids final ObjectComposition comp = client.getObjectDefinition(object.getId()); if (comp.getImpostorIds() != null) @@ -386,11 +396,13 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener { objectPoints.remove(point); objects.remove(object); + log.debug("Unmarking object: {}", point); } else { objectPoints.add(point); objects.add(object); + log.debug("Marking object: {}", point); } savePoints(regionId, objectPoints); @@ -418,8 +430,20 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener return null; } - return GSON.fromJson(json, new TypeToken>() + Set points = GSON.fromJson(json, new TypeToken>() { }.getType()); + // Prior to multiloc support the plugin would mark objects named "null", which breaks + // in most cases due to the specific object being identified being ambiguous, so remove + // them + return points.stream() + .filter(point -> !point.getName().equals("null")) + .collect(Collectors.toSet()); + } + + private ObjectComposition getObjectComposition(int id) + { + ObjectComposition objectComposition = client.getObjectDefinition(id); + return objectComposition.getImpostorIds() == null ? objectComposition : objectComposition.getImpostor(); } } \ No newline at end of file From b22fc6b30176bcb176d63d6c61a602f83a4ed938 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 2 Oct 2019 19:31:27 -0400 Subject: [PATCH 41/45] object indicators: support non-gameobject multilocs --- .../ObjectIndicatorsPlugin.java | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) 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 7b91196592..c3739650f5 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 @@ -333,47 +333,57 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener final DecorativeObject tileDecorativeObject = tile.getDecorativeObject(); final WallObject tileWallObject = tile.getWallObject(); - if (tileWallObject != null && tileWallObject.getId() == id) + if (objectIdEquals(tileWallObject, id)) { return tileWallObject; } - if (tileDecorativeObject != null && tileDecorativeObject.getId() == id) + if (objectIdEquals(tileDecorativeObject, id)) { return tileDecorativeObject; } for (GameObject object : tileGameObjects) { - if (object == null) - { - continue; - } - - if (object.getId() == id) + if (objectIdEquals(object, id)) { return object; } - - // Menu action EXAMINE_OBJECT sends the transformed object id, not the base id, unlike - // all of the GAME_OBJECT_OPTION actions, so check the id against the impostor ids - final ObjectComposition comp = client.getObjectDefinition(object.getId()); - - if (comp.getImpostorIds() != null) - { - for (int impostorId : comp.getImpostorIds()) - { - if (impostorId == id) - { - return object; - } - } - } } return null; } + private boolean objectIdEquals(TileObject tileObject, int id) + { + if (tileObject == null) + { + return false; + } + + if (tileObject.getId() == id) + { + return true; + } + + // Menu action EXAMINE_OBJECT sends the transformed object id, not the base id, unlike + // all of the GAME_OBJECT_OPTION actions, so check the id against the impostor ids + final ObjectComposition comp = client.getObjectDefinition(tileObject.getId()); + + if (comp.getImpostorIds() != null) + { + for (int impostorId : comp.getImpostorIds()) + { + if (impostorId == id) + { + return true; + } + } + } + + return false; + } + private void markObject(String name, final TileObject object) { if (object == null) From 5f745be26de01207cffa357cac24c91acee9c67b Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 2 Oct 2019 20:55:47 -0400 Subject: [PATCH 42/45] api: add getConvexHull to GroundObject --- .../src/main/java/net/runelite/api/GroundObject.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/GroundObject.java b/runelite-api/src/main/java/net/runelite/api/GroundObject.java index 8a974cd752..8971aa88bf 100644 --- a/runelite-api/src/main/java/net/runelite/api/GroundObject.java +++ b/runelite-api/src/main/java/net/runelite/api/GroundObject.java @@ -24,10 +24,20 @@ */ package net.runelite.api; +import java.awt.Shape; + /** * Represents an object on the ground of a tile. */ public interface GroundObject extends TileObject { Renderable getRenderable(); + + /** + * Gets the convex hull of the objects model. + * + * @return the convex hull + * @see net.runelite.api.model.Jarvis + */ + Shape getConvexHull(); } From ad5514acdefe657b31326c2f6776c66884daf060 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 2 Oct 2019 21:10:57 -0400 Subject: [PATCH 43/45] object indicator: add support for ground objects --- .../ObjectIndicatorsOverlay.java | 5 ++++ .../ObjectIndicatorsPlugin.java | 27 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 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 a61aa526dc..21d0a4692d 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 @@ -31,6 +31,7 @@ import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; +import net.runelite.api.GroundObject; import net.runelite.api.TileObject; import net.runelite.api.WallObject; import net.runelite.client.ui.overlay.Overlay; @@ -83,6 +84,10 @@ class ObjectIndicatorsOverlay extends Overlay polygon = ((DecorativeObject) object).getConvexHull(); polygon2 = ((DecorativeObject) object).getConvexHull2(); } + else if (object instanceof GroundObject) + { + polygon = ((GroundObject) object).getConvexHull(); + } else { polygon = object.getCanvasTilePoly(); 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 c3739650f5..34386b52c4 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 @@ -47,6 +47,7 @@ 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.GroundObject; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; import net.runelite.api.ObjectComposition; @@ -55,14 +56,16 @@ import net.runelite.api.Tile; import net.runelite.api.TileObject; import net.runelite.api.WallObject; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.DecorativeObjectDespawned; +import net.runelite.api.events.DecorativeObjectSpawned; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.GameObjectDespawned; import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GroundObjectDespawned; +import net.runelite.api.events.GroundObjectSpawned; 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.api.events.WallObjectChanged; import net.runelite.api.events.WallObjectDespawned; import net.runelite.api.events.WallObjectSpawned; @@ -212,6 +215,20 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener objects.remove(event.getDecorativeObject()); } + @Subscribe + public void onGroundObjectSpawned(GroundObjectSpawned groundObjectSpawned) + { + final GroundObject groundObject = groundObjectSpawned.getGroundObject(); + checkObjectPoints(groundObject); + } + + @Subscribe + public void onGroundObjectDespawned(GroundObjectDespawned groundObjectDespawned) + { + GroundObject groundObject = groundObjectDespawned.getGroundObject(); + objects.remove(groundObject); + } + @Subscribe public void onGameStateChanged(GameStateChanged gameStateChanged) { @@ -332,6 +349,7 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener final GameObject[] tileGameObjects = tile.getGameObjects(); final DecorativeObject tileDecorativeObject = tile.getDecorativeObject(); final WallObject tileWallObject = tile.getWallObject(); + final GroundObject groundObject = tile.getGroundObject(); if (objectIdEquals(tileWallObject, id)) { @@ -343,6 +361,11 @@ public class ObjectIndicatorsPlugin extends Plugin implements KeyListener return tileDecorativeObject; } + if (objectIdEquals(groundObject, id)) + { + return groundObject; + } + for (GameObject object : tileGameObjects) { if (objectIdEquals(object, id)) From 722bb126435be506494a22486f3b3270f5462a9b Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Thu, 3 Oct 2019 21:16:10 +0200 Subject: [PATCH 44/45] deob: Fix test --- runescape-client/src/main/java/ClientType.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runescape-client/src/main/java/ClientType.java b/runescape-client/src/main/java/ClientType.java index 21c6f8e919..be8cae3aba 100644 --- a/runescape-client/src/main/java/ClientType.java +++ b/runescape-client/src/main/java/ClientType.java @@ -1,3 +1,4 @@ +import net.runelite.mapping.Export; import net.runelite.mapping.Implements; import net.runelite.mapping.ObfuscatedGetter; import net.runelite.mapping.ObfuscatedName; @@ -10,5 +11,6 @@ public class ClientType @ObfuscatedGetter( intValue = 2052078695 ) + @Export("clientType") public static int clientType; } From 946ba0f500472315a8000fe355174eb8edc30a5c Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Thu, 3 Oct 2019 21:59:30 +0200 Subject: [PATCH 45/45] api: Fix RectangleUnionTest --- .../net/runelite/api/geometry/RectangleUnionTest.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java b/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java index f8d714180b..df678b350a 100644 --- a/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java +++ b/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java @@ -34,17 +34,16 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.imageio.ImageIO; -import lombok.extern.slf4j.Slf4j; import org.junit.Assert; +import org.junit.Test; -@Slf4j public class RectangleUnionTest { private static final int ITERATIONS = 100; private static final int WIDTH = 1000; private static final int MAX_RECTS = 50; - // @Test + @Test public void test() throws IOException { for (int count = 1; count < MAX_RECTS; count++) @@ -53,7 +52,7 @@ public class RectangleUnionTest { Random rand = new Random(count << 16 | r); String id = count + "rects_iteration" + r; - log.info(id); + BufferedImage wanted = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_BYTE_BINARY); BufferedImage got = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_BYTE_BINARY); @@ -83,7 +82,6 @@ public class RectangleUnionTest while (y1 >= y2); RectangleUnion.Rectangle rect = new RectangleUnion.Rectangle(x1, y1, x2, y2); - log.trace("{}", rect); rects.add(rect); wg.fillRect(x1, y1, x2 - x1, y2 - y1);