From a94637d3be596b50cbe06a577f6f6b90b2486350 Mon Sep 17 00:00:00 2001 From: Abex Date: Tue, 22 Oct 2019 12:49:01 -0600 Subject: [PATCH] wiki: support wiki-casting on non-inventory items --- .../net/runelite/api/widgets/WidgetID.java | 12 +- .../net/runelite/api/widgets/WidgetInfo.java | 6 +- .../client/plugins/wiki/WikiPlugin.java | 138 ++++++++++++++---- 3 files changed, 123 insertions(+), 33 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index 33d0f462ac..8dc2e13152 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -52,7 +52,7 @@ public class WidgetID public static final int EQUIPMENT_INVENTORY_GROUP_ID = 85; public static final int EMOTES_GROUP_ID = 216; public static final int RUNE_POUCH_GROUP_ID = 190; - public static final int DIARY_GROUP_ID = 259; + public static final int ACHIEVEMENT_DIARY_GROUP_ID = 259; public static final int PEST_CONTROL_BOAT_GROUP_ID = 407; public static final int PEST_CONTROL_GROUP_ID = 408; public static final int CLAN_CHAT_GROUP_ID = 7; @@ -843,4 +843,14 @@ public class WidgetID static final int SOUND_EFFECT_SLIDER = 50; static final int AREA_SOUND_SLIDER = 56; } + + static class AchievementDiary + { + static final int CONTAINER = 2; + } + + static class Skills + { + static final int CONTAINER = 0; + } } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 32281cd2c8..c7e3efb585 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -502,7 +502,11 @@ public enum WidgetInfo OPTIONS_MUSIC_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.MUSIC_SLIDER), OPTIONS_SOUND_EFFECT_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.SOUND_EFFECT_SLIDER), - OPTIONS_AREA_SOUND_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.AREA_SOUND_SLIDER); + OPTIONS_AREA_SOUND_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.AREA_SOUND_SLIDER), + + ACHIEVEMENT_DIARY_CONTAINER(WidgetID.ACHIEVEMENT_DIARY_GROUP_ID, WidgetID.AchievementDiary.CONTAINER), + + SKILLS_CONTAINER(WidgetID.SKILLS_GROUP_ID, WidgetID.Skills.CONTAINER); private final int groupId; private final int childId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java index afbc30b766..3c14556492 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java @@ -26,8 +26,7 @@ package net.runelite.client.plugins.wiki; import com.google.common.primitives.Ints; import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.stream.Stream; import javax.inject.Inject; import javax.inject.Provider; import lombok.extern.slf4j.Slf4j; @@ -82,9 +81,6 @@ public class WikiPlugin extends Plugin private static final String MENUOP_QUICKGUIDE = "Quick Guide"; private static final String MENUOP_WIKI = "Wiki"; - private static final Pattern SKILL_REGEX = Pattern.compile("([A-Za-z]+) guide"); - private static final Pattern DIARY_REGEX = Pattern.compile("([A-Za-z &]+) Journal"); - @Inject private SpriteManager spriteManager; @@ -164,12 +160,14 @@ public class WikiPlugin extends Plugin icon.setOriginalHeight(16); icon.setTargetVerb("Lookup"); icon.setName("Wiki"); - icon.setClickMask(WidgetConfig.USE_GROUND_ITEM | WidgetConfig.USE_ITEM | WidgetConfig.USE_NPC | WidgetConfig.USE_OBJECT); + icon.setClickMask(WidgetConfig.USE_GROUND_ITEM | WidgetConfig.USE_ITEM | WidgetConfig.USE_NPC + | WidgetConfig.USE_OBJECT | WidgetConfig.USE_WIDGET); icon.setNoClickThrough(true); icon.setOnTargetEnterListener((JavaScriptCallback) ev -> { wikiSelected = true; icon.setSpriteId(WikiSprite.WIKI_SELECTED_ICON.getSpriteId()); + client.setAllWidgetsAreOpTargetable(true); }); icon.setAction(5, "Search"); // Start at option 5 so the target op is ontop icon.setOnOpListener((JavaScriptCallback) ev -> @@ -188,6 +186,8 @@ public class WikiPlugin extends Plugin private void onDeselect() { + client.setAllWidgetsAreOpTargetable(false); + wikiSelected = false; if (icon != null) { @@ -198,6 +198,7 @@ public class WikiPlugin extends Plugin @Subscribe private void onMenuOptionClicked(MenuOptionClicked ev) { + optarget: if (wikiSelected) { onDeselect(); @@ -211,6 +212,9 @@ public class WikiPlugin extends Plugin switch (ev.getMenuAction()) { + case RUNELITE: + // This is a quest widget op + break optarget; case CANCEL: return; case ITEM_USE_ON_WIDGET: @@ -245,6 +249,18 @@ public class WikiPlugin extends Plugin location = WorldPoint.fromScene(client, ev.getActionParam(), ev.getWidgetId(), client.getPlane()); break; } + case SPELL_CAST_ON_WIDGET: + Widget w = getWidget(ev.getWidgetId(), ev.getActionParam()); + + if (w.getType() == WidgetType.GRAPHIC && w.getItemId() != -1) + { + type = "item"; + id = itemManager.canonicalize(w.getItemId()); + name = itemManager.getItemComposition(id).getName(); + location = null; + break; + } + // fallthrough default: log.info("Unknown menu option: {} {} {}", ev, ev.getMenuAction(), ev.getMenuAction() == MenuAction.CANCEL); return; @@ -293,25 +309,12 @@ public class WikiPlugin extends Plugin LinkBrowser.browse(ub.build().toString()); break; case MENUOP_WIKI: - Matcher skillRegex = WikiPlugin.SKILL_REGEX.matcher(Text.removeTags(ev.getMenuTarget())); - Matcher diaryRegex = WikiPlugin.DIARY_REGEX.matcher(Text.removeTags(ev.getMenuTarget())); + LinkBrowser.browse(WIKI_BASE.newBuilder() + .addPathSegment("w") + .addPathSegment(Text.removeTags(ev.getMenuTarget())) + .addQueryParameter(UTM_SORUCE_KEY, UTM_SORUCE_VALUE) + .build().toString()); - if (skillRegex.find()) - { - LinkBrowser.browse(WIKI_BASE.newBuilder() - .addPathSegment("w") - .addPathSegment(skillRegex.group(1)) - .addQueryParameter(UTM_SORUCE_KEY, UTM_SORUCE_VALUE) - .build().toString()); - } - else if (diaryRegex.find()) - { - LinkBrowser.browse(WIKI_BASE.newBuilder() - .addPathSegment("w") - .addPathSegment(diaryRegex.group(1) + " Diary") - .addQueryParameter(UTM_SORUCE_KEY, UTM_SORUCE_VALUE) - .build().toString()); - } } } } @@ -322,6 +325,16 @@ public class WikiPlugin extends Plugin .build(); } + private Widget getWidget(int wid, int index) + { + Widget w = client.getWidget(WidgetInfo.TO_GROUP(wid), WidgetInfo.TO_CHILD(wid)); + if (index != -1) + { + w = w.getChild(index); + } + return w; + } + @Subscribe public void onMenuEntryAdded(MenuEntryAdded event) { @@ -329,19 +342,42 @@ public class WikiPlugin extends Plugin int widgetID = event.getActionParam1(); MenuEntry[] menuEntries = client.getMenuEntries(); - if (Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) && "Read Journal:".equals(event.getOption())) + if (wikiSelected && event.getType() == MenuAction.SPELL_CAST_ON_WIDGET.getId()) { + Widget w = getWidget(widgetID, widgetIndex); + if (!(w.getType() == WidgetType.GRAPHIC && w.getItemId() != -1)) + { + // we don't support this widget + // remove the last SPELL_CAST_ON_WIDGET; we can't blindly remove the top action because some other + // plugin might have added something on this same event, and we probably shouldn't remove that instead + MenuEntry[] oldEntries = menuEntries; + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length - 1); + for (int ourEntry = oldEntries.length - 1; + ourEntry >= 2 && oldEntries[oldEntries.length - 1].getType() != MenuAction.SPELL_CAST_ON_WIDGET.getId(); + ourEntry--) + { + menuEntries[ourEntry - 1] = oldEntries[ourEntry]; + } + client.setMenuEntries(menuEntries); + } + } + + if (Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) + && ((wikiSelected && widgetIndex != -1) || "Read Journal:".equals(event.getOption()))) + { + Widget w = getWidget(widgetID, widgetIndex); + String target = w.getName(); menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 2); MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - menuEntry.setTarget(event.getTarget()); + menuEntry.setTarget(target); menuEntry.setOption(MENUOP_GUIDE); menuEntry.setParam0(widgetIndex); menuEntry.setParam1(widgetID); menuEntry.setType(MenuAction.RUNELITE.getId()); menuEntry = menuEntries[menuEntries.length - 2] = new MenuEntry(); - menuEntry.setTarget(event.getTarget()); + menuEntry.setTarget(target); menuEntry.setOption(MENUOP_QUICKGUIDE); menuEntry.setParam0(widgetIndex); menuEntry.setParam1(widgetID); @@ -350,17 +386,57 @@ public class WikiPlugin extends Plugin client.setMenuEntries(menuEntries); } - if ((WidgetInfo.TO_GROUP(widgetID) == WidgetID.SKILLS_GROUP_ID && event.getOption().startsWith("View")) - || (WidgetInfo.TO_GROUP(widgetID) == WidgetID.DIARY_GROUP_ID && event.getOption().startsWith("Open"))) + if (widgetID == WidgetInfo.ACHIEVEMENT_DIARY_CONTAINER.getId()) { + Widget w = getWidget(widgetID, widgetIndex); + if (w.getActions() == null) + { + return; + } + + String action = Stream.of(w.getActions()) + .filter(s -> s != null && !s.isEmpty()) + .findFirst().orElse(null); + if (action == null) + { + return; + } + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); - menuEntry.setTarget(event.getOption().replace("View ", "").replace("Open ", "")); + menuEntry.setTarget(action.replace("Open ", "").replace("Journal", "Diary")); + menuEntry.setOption(MENUOP_WIKI); + menuEntry.setParam0(widgetIndex); + menuEntry.setParam1(widgetID); + menuEntry.setType(MenuAction.RUNELITE.getId()); + + client.setMenuEntries(menuEntries); + } + + if (WidgetInfo.TO_GROUP(widgetID) == WidgetInfo.SKILLS_CONTAINER.getGroupId()) + { + Widget w = getWidget(widgetID, widgetIndex); + if (w.getParentId() != WidgetInfo.SKILLS_CONTAINER.getId()) + { + return; + } + + String action = Stream.of(w.getActions()) + .filter(s -> s != null && !s.isEmpty()) + .findFirst().orElse(null); + if (action == null) + { + return; + } + + menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1); + + MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry(); + menuEntry.setTarget(action.replace("View ", "").replace(" guide", "")); menuEntry.setOption(MENUOP_WIKI); menuEntry.setParam0(widgetIndex); menuEntry.setParam1(widgetID); - menuEntry.setIdentifier(event.getIdentifier()); menuEntry.setType(MenuAction.RUNELITE.getId()); client.setMenuEntries(menuEntries);