From 257822aea0c9c5b92cc3d0608ba32a6e217dbffb Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Mar 2018 17:45:49 -0400 Subject: [PATCH] Add npc menu options to MenuManager --- .../runelite/api/events/NpcActionChanged.java | 35 ++++++++ .../runelite/client/menus/MenuManager.java | 82 +++++++++++++++++++ .../mixins/RSNpcCompositionMixin.java | 46 +++++++++++ 3 files changed, 163 insertions(+) create mode 100644 runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/RSNpcCompositionMixin.java diff --git a/runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java b/runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java new file mode 100644 index 0000000000..5d105547ff --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, 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.Data; +import net.runelite.api.NPCComposition; + +@Data +public class NpcActionChanged +{ + private NPCComposition npcComposition; + private int idx; +} 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 7502a7b883..6abceb6264 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 @@ -32,7 +32,9 @@ import com.google.common.eventbus.Subscribe; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; @@ -40,8 +42,11 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.NpcActionChanged; import net.runelite.api.events.PlayerMenuOptionClicked; import net.runelite.api.events.PlayerMenuOptionsChanged; import net.runelite.api.events.WidgetMenuOptionClicked; @@ -64,6 +69,7 @@ public class MenuManager private final Map playerMenuIndexMap = new HashMap<>(); //Used to manage custom non-player menu options private final Multimap managedMenuOptions = HashMultimap.create(); + private final Set npcMenuOptions = new HashSet<>(); @Inject public MenuManager(Provider clientProvider, EventBus eventBus) @@ -72,6 +78,32 @@ public class MenuManager this.eventBus = eventBus; } + public void addNpcMenuOption(String option) + { + npcMenuOptions.add(option); + + // add to surrounding npcs + Client client = clientProvider.get(); + for (NPC npc : client.getNpcs()) + { + NPCComposition composition = npc.getComposition(); + addNpcOption(composition, option); + } + } + + public void removeNpcMenuOption(String option) + { + npcMenuOptions.remove(npcMenuOptions); + + // remove this option from all npc compositions + Client client = clientProvider.get(); + for (NPC npc : client.getNpcs()) + { + NPCComposition composition = npc.getComposition(); + removeNpcOption(composition, option); + } + } + /** * Adds a CustomMenuOption to the list of managed menu options. * @@ -186,6 +218,56 @@ public class MenuManager addPlayerMenuItem(newIdx, menuText); } + @Subscribe + public void onNpcActionChanged(NpcActionChanged event) + { + NPCComposition composition = event.getNpcComposition(); + for (String npcOption : npcMenuOptions) + { + addNpcOption(composition, npcOption); + } + } + + private void addNpcOption(NPCComposition composition, String npcOption) + { + String[] actions = composition.getActions(); + int unused = -1; + for (int i = 0; i < actions.length; ++i) + { + if (actions[i] == null && unused == -1) + { + unused = i; + } + else if (actions[i] != null && actions[i].equals(npcOption)) + { + return; + } + } + if (unused == -1) + { + return; + } + actions[unused] = npcOption; + } + + private void removeNpcOption(NPCComposition composition, String npcOption) + { + String[] actions = composition.getActions(); + + if (composition.getActions() == null) + { + return; + } + + for (int i = 0; i < actions.length; ++i) + { + if (actions[i] != null && actions[i].equals(npcOption)) + { + actions[i] = null; + } + } + } + @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSNpcCompositionMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSNpcCompositionMixin.java new file mode 100644 index 0000000000..ce3decf2bc --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSNpcCompositionMixin.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.mixins; + +import net.runelite.api.events.NpcActionChanged; +import net.runelite.api.mixins.FieldHook; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import static net.runelite.client.callback.Hooks.eventBus; +import net.runelite.rs.api.RSNPCComposition; + +@Mixin(RSNPCComposition.class) +public abstract class RSNpcCompositionMixin implements RSNPCComposition +{ + @FieldHook("actions") + @Inject + public void actionsHook(int idx) + { + NpcActionChanged npcActionChanged = new NpcActionChanged(); + npcActionChanged.setNpcComposition(this); + npcActionChanged.setIdx(idx); + eventBus.post(npcActionChanged); + } +}