diff --git a/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java b/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java index faf369be56..c03f1683e4 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java +++ b/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java @@ -24,58 +24,77 @@ */ package net.runelite.api.events; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; /** * An event when a new entry is added to a right-click menu. */ +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@ToString(onlyExplicitlyIncluded = true) public class MenuEntryAdded { // Here for RuneLite compatibility (different parameter order) - public MenuEntryAdded(String option, String target, int type, int identifier, int actionParam0, int actionParam1) + public MenuEntryAdded(MenuEntry menuEntry) { - this(option, target, identifier, type, actionParam0, actionParam1, false); - } + this.menuEntry = menuEntry; - public MenuEntryAdded(String option, String target, int identifier, int type, int param0, int param1, boolean forceLeftClick) - { - this.option = option; - this.target = target; - this.identifier = identifier; - this.type = type; - this.actionParam0 = param0; - this.actionParam1 = param1; - this.forceLeftClick = forceLeftClick; + this.option = menuEntry.getOption(); + this.target = menuEntry.getTarget(); + this.identifier = menuEntry.getIdentifier(); + this.type = menuEntry.getType().getId(); + this.actionParam0 = menuEntry.getParam0(); + this.actionParam1 = menuEntry.getParam1(); + this.forceLeftClick = false; } + @Getter + private final MenuEntry menuEntry; + @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private String option; @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private String target; @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private int type; @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private int identifier; @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private int actionParam0; @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private int actionParam1; @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private boolean forceLeftClick; /** @@ -87,6 +106,8 @@ public class MenuEntryAdded */ @Getter @Setter + @EqualsAndHashCode.Include + @ToString.Include private boolean modified; public void setModified() @@ -134,4 +155,4 @@ public class MenuEntryAdded { return MenuAction.of(type); } -} +} \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java b/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java index 4396273a65..cab8c5ca4c 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java +++ b/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java @@ -24,9 +24,12 @@ */ package net.runelite.api.events; +import javax.annotation.Nullable; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; +import lombok.ToString; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; import net.runelite.api.widgets.Widget; @@ -43,12 +46,16 @@ import net.runelite.api.widgets.Widget; * it seems that this event still triggers with the "Cancel" action. */ @RequiredArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@ToString(onlyExplicitlyIncluded = true) public class MenuOptionClicked { /** * The clicked menu entry */ + @Getter private final MenuEntry menuEntry; + /** * Whether or not the event has been consumed by a subscriber. */ @@ -59,6 +66,8 @@ public class MenuOptionClicked /** * Action parameter 0. Its value depends on the menuAction. */ + @EqualsAndHashCode.Include + @ToString.Include public int getParam0() { return menuEntry.getParam0(); @@ -72,6 +81,8 @@ public class MenuOptionClicked /** * Action parameter 1. Its value depends on the menuAction. */ + @EqualsAndHashCode.Include + @ToString.Include public int getParam1() { return menuEntry.getParam1(); @@ -85,6 +96,8 @@ public class MenuOptionClicked /** * The option text added to the menu. */ + @EqualsAndHashCode.Include + @ToString.Include public String getMenuOption() { return menuEntry.getOption(); @@ -98,6 +111,8 @@ public class MenuOptionClicked /** * The target of the action. */ + @EqualsAndHashCode.Include + @ToString.Include public String getMenuTarget() { return menuEntry.getTarget(); @@ -111,6 +126,8 @@ public class MenuOptionClicked /** * The action performed. */ + @EqualsAndHashCode.Include + @ToString.Include public MenuAction getMenuAction() { return menuEntry.getType(); @@ -124,6 +141,8 @@ public class MenuOptionClicked /** * The ID of the object, actor, or item that the interaction targets. */ + @EqualsAndHashCode.Include + @ToString.Include public int getId() { return menuEntry.getIdentifier(); @@ -168,6 +187,7 @@ public class MenuOptionClicked * with an associated widget. Such as eg, CC_OP. * @return */ + @Nullable public Widget getWidget() { return menuEntry.getWidget(); diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index a3cace1176..10fba4954d 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -191,6 +191,9 @@ public interface Widget */ void setForcedPosition(int x, int y); + void setForcedX(); + void setForcedY(); + /** * Gets the text displayed on this widget. * diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index e5a64dffb2..1ea6cd2784 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -1089,13 +1089,6 @@ public abstract class RSClientMixin implements RSClient client.getMenuTargets()[tmpOptionsCount] = "null"; } - String menuOption = client.getMenuOptions()[tmpOptionsCount]; - String menuTarget = client.getMenuTargets()[tmpOptionsCount]; - int menuOpcode = client.getMenuOpcodes()[tmpOptionsCount]; - int menuIdentifier = client.getMenuIdentifiers()[tmpOptionsCount]; - int menuArgument1 = client.getMenuArguments1()[tmpOptionsCount]; - int menuArgument2 = client.getMenuArguments2()[tmpOptionsCount]; - if (rl$menuEntries[tmpOptionsCount] == null) { rl$menuEntries[tmpOptionsCount] = newRuneliteMenuEntry(tmpOptionsCount); @@ -1106,13 +1099,9 @@ public abstract class RSClientMixin implements RSClient } MenuEntryAdded menuEntryAdded = new MenuEntryAdded( - menuOption, - menuTarget, - menuOpcode, - menuIdentifier, - menuArgument1, - menuArgument2 + rl$menuEntries[tmpOptionsCount] ); + client.getCallbacks().post(menuEntryAdded); if (menuEntryAdded.isModified() && client.getMenuOptionCount() == optionCount) diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java index 908bacbff1..7df3b69b41 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java @@ -44,6 +44,7 @@ import net.runelite.api.widgets.Widget; import static net.runelite.api.widgets.WidgetInfo.TO_CHILD; import static net.runelite.api.widgets.WidgetInfo.TO_GROUP; import net.runelite.api.widgets.WidgetItem; +import net.runelite.api.widgets.WidgetPositionMode; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSModel; import net.runelite.rs.api.RSNode; @@ -66,6 +67,10 @@ public abstract class RSWidgetMixin implements RSWidget private int rl$x; @Inject private int rl$y; + @Inject + private short forcedX; + @Inject + private short forcedY; @Inject RSWidgetMixin() @@ -73,6 +78,8 @@ public abstract class RSWidgetMixin implements RSWidget rl$parentId = -1; rl$x = -1; rl$y = -1; + forcedX = -1; + forcedY = -1; } @Inject @@ -642,4 +649,99 @@ public abstract class RSWidgetMixin implements RSWidget return new Point(dragOffsetX, dragOffsetY); } + + @Inject + public void setForcedX() + { + if (this.forcedX > -1) + { + this.setRelativeX(this.forcedX); + } + } + + @Inject + public void setForcedY() + { + if (this.forcedY > -1) + { + this.setRelativeY(this.forcedY); + } + } + + @Inject + @Override + public void setForcedPosition(int x, int y) + { + this.forcedX = (short) x; + this.forcedY = (short) y; + this.setRelativeX(x); + this.setRelativeY(y); + } + + @Copy("alignWidgetPosition") + @Replace("alignWidgetPosition") + public static void alignWidgetPosition(Widget widget, int x, int y) + { + if (widget.getXPositionMode() == WidgetPositionMode.ABSOLUTE_LEFT) + { + widget.setRelativeX(widget.getOriginalX()); + widget.setForcedX(); + } + else if (widget.getXPositionMode() == WidgetPositionMode.ABSOLUTE_CENTER) + { + widget.setRelativeX(widget.getOriginalX() + (x - widget.getWidth()) / 2); + widget.setForcedX(); + } + else if (widget.getXPositionMode() == WidgetPositionMode.ABSOLUTE_RIGHT) + { + widget.setRelativeX(x - widget.getWidth() - widget.getOriginalX()); + widget.setForcedX(); + } + else if (widget.getXPositionMode() == WidgetPositionMode.LEFT_16384THS) + { + widget.setRelativeX(widget.getOriginalX() * x >> 14); + widget.setForcedX(); + } + else if (widget.getXPositionMode() == WidgetPositionMode.CENTER_16384THS) + { + widget.setRelativeX((widget.getOriginalX() * x >> 14) + (x - widget.getWidth()) / 2); + widget.setForcedX(); + } + else + { + widget.setRelativeX(x - widget.getWidth() - (widget.getOriginalX() * x >> 14)); + widget.setForcedX(); + } + + if (widget.getYPositionMode() == WidgetPositionMode.ABSOLUTE_TOP) + { + widget.setRelativeY(widget.getOriginalY()); + widget.setForcedY(); + } + else if (widget.getYPositionMode() == WidgetPositionMode.ABSOLUTE_CENTER) + { + widget.setRelativeY((y - widget.getHeight()) / 2 + widget.getOriginalY()); + widget.setForcedY(); + } + else if (widget.getYPositionMode() == WidgetPositionMode.ABSOLUTE_BOTTOM) + { + widget.setRelativeY(y - widget.getHeight() - widget.getOriginalY()); + widget.setForcedY(); + } + else if (widget.getYPositionMode() == WidgetPositionMode.TOP_16384THS) + { + widget.setRelativeY(y * widget.getOriginalY() >> 14); + widget.setForcedY(); + } + else if (widget.getYPositionMode() == WidgetPositionMode.CENTER_16384THS) + { + widget.setRelativeY((y - widget.getHeight()) / 2 + (y * widget.getOriginalY() >> 14)); + widget.setForcedY(); + } + else + { + widget.setRelativeY(y - widget.getHeight() - (y * widget.getOriginalY() >> 14)); + widget.setForcedY(); + } + } } diff --git a/runescape-client/src/main/java/RuneLiteMenuEntry.java b/runescape-client/src/main/java/RuneLiteMenuEntry.java index 0ac7adf6e8..c9fd1c388e 100644 --- a/runescape-client/src/main/java/RuneLiteMenuEntry.java +++ b/runescape-client/src/main/java/RuneLiteMenuEntry.java @@ -1,8 +1,13 @@ import java.util.function.Consumer; +import net.runelite.api.Actor; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import net.runelite.api.events.NpcSpawned; import net.runelite.api.widgets.Widget; import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSNPC; import sun.reflect.generics.reflectiveObjects.NotImplementedException; public class RuneLiteMenuEntry implements MenuEntry @@ -455,6 +460,82 @@ public class RuneLiteMenuEntry implements MenuEntry return widget; } + @Override + public NPC getNpc() + { + NPC[] npcs = client.getCachedNPCs(); + NPC npc = null; + + MenuAction menuAction = this.getType(); + + if (menuAction == MenuAction.NPC_FIRST_OPTION || + menuAction == MenuAction.NPC_SECOND_OPTION || + menuAction == MenuAction.NPC_THIRD_OPTION || + menuAction == MenuAction.NPC_FOURTH_OPTION || + menuAction == MenuAction.NPC_FIFTH_OPTION || + menuAction == MenuAction.WIDGET_TARGET_ON_NPC) + { + int identifier = this.getIdentifier(); + + if (identifier >= 0 && identifier < npcs.length) + { + npc = npcs[identifier]; + } + } + + return npc; + } + + @Override + public Player getPlayer() + { + Player[] players = client.getCachedPlayers(); + Player player = null; + + MenuAction menuAction = this.getType(); + + if (menuAction == MenuAction.PLAYER_FIRST_OPTION || + menuAction == MenuAction.PLAYER_SECOND_OPTION || + menuAction == MenuAction.PLAYER_THIRD_OPTION || + menuAction == MenuAction.PLAYER_FOURTH_OPTION || + menuAction == MenuAction.PLAYER_FIFTH_OPTION || + menuAction == MenuAction.PLAYER_SIXTH_OPTION || + menuAction == MenuAction.PLAYER_SEVENTH_OPTION || + menuAction == MenuAction.PLAYER_EIGTH_OPTION || + menuAction == MenuAction.WIDGET_TARGET_ON_PLAYER || + menuAction == MenuAction.RUNELITE_PLAYER) + { + int identifier = this.getIdentifier(); + + if (identifier >= 0 && identifier < players.length) + { + player = players[identifier]; + } + } + + return player; + } + + @Override + public Actor getActor() + { + NPC npc = getNpc(); + + if (npc != null) + { + return npc; + } + + Player player = getPlayer(); + + if (player != null) + { + return player; + } + + return null; + } + @Override public int hashCode() {