diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java index 6003c5a1e9..64eb37734b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java @@ -137,6 +137,18 @@ public interface MenuEntrySwapperConfig extends Config return true; } + @ConfigItem( + position = -2, + keyName = "objectLeftClickCustomization", + name = "Customizable left-click", + description = "Allows customization of left-clicks on objects", + section = objectSection + ) + default boolean objectLeftClickCustomization() + { + return true; + } + @ConfigItem( keyName = "swapAdmire", name = "Admire", @@ -837,23 +849,4 @@ public interface MenuEntrySwapperConfig extends Config { return false; } - - enum UnchargedCellsMode - { - TAKE, - TAKE_1, - TAKE_5, - TAKE_10 - } - - @ConfigItem( - keyName = "swapUnchargedCells", - name = "Uncharged Cells", - description = "Swap the take option for Uncharged Cells in Guardians of the Rift.", - section = objectSection - ) - default UnchargedCellsMode swapUnchargedCells() - { - return UnchargedCellsMode.TAKE; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index f9b539cf0f..4ea328b280 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -29,7 +29,9 @@ package net.runelite.client.plugins.menuentryswapper; import com.google.common.annotations.VisibleForTesting; import static com.google.common.base.Predicates.alwaysTrue; import static com.google.common.base.Predicates.equalTo; +import com.google.common.base.Strings; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; @@ -43,6 +45,8 @@ import java.util.Set; import java.util.function.Predicate; import java.util.function.Supplier; import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.ItemComposition; @@ -50,6 +54,7 @@ import net.runelite.api.KeyCode; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; import net.runelite.api.NPC; +import net.runelite.api.ObjectComposition; import net.runelite.api.events.ClientTick; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOpened; @@ -57,6 +62,9 @@ import net.runelite.api.events.PostItemComposition; import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.callback.ClientThread; +import net.runelite.client.chat.ChatMessageBuilder; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.chat.QueuedMessage; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ConfigChanged; @@ -71,7 +79,6 @@ import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfi import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.KaramjaGlovesMode; import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.MorytaniaLegsMode; import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.RadasBlessingMode; -import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.UnchargedCellsMode; import net.runelite.client.util.Text; @PluginDescriptor( @@ -80,6 +87,7 @@ import net.runelite.client.util.Text; tags = {"npcs", "inventory", "items", "objects"}, enabledByDefault = false ) +@Slf4j public class MenuEntrySwapperPlugin extends Plugin { private static final String CONFIGURE = "Configure"; @@ -90,6 +98,7 @@ public class MenuEntrySwapperPlugin extends Plugin private static final String SHIFTCLICK_CONFIG_GROUP = "shiftclick"; private static final String ITEM_KEY_PREFIX = "item_"; + private static final String OBJECT_KEY_PREFIX = "object_"; // Shift click private static final WidgetMenuOption FIXED_INVENTORY_TAB_CONFIGURE_SC = new WidgetMenuOption(CONFIGURE, @@ -140,6 +149,14 @@ public class MenuEntrySwapperPlugin extends Plugin MenuAction.NPC_FIFTH_OPTION, MenuAction.EXAMINE_NPC); + private static final List OBJECT_MENU_TYPES = ImmutableList.of( + MenuAction.GAME_OBJECT_FIRST_OPTION, + MenuAction.GAME_OBJECT_SECOND_OPTION, + MenuAction.GAME_OBJECT_THIRD_OPTION, + MenuAction.GAME_OBJECT_FOURTH_OPTION + // GAME_OBJECT_FIFTH_OPTION gets sorted underneath Walk here after we swap, so it doesn't work + ); + private static final Set ESSENCE_MINE_NPCS = ImmutableSet.of( "aubury", "sedridor", @@ -173,6 +190,9 @@ public class MenuEntrySwapperPlugin extends Plugin @Inject private ItemManager itemManager; + @Inject + private ChatMessageManager chatMessageManager; + private boolean configuringShiftClick = false; private boolean configuringLeftClick = false; @@ -422,10 +442,6 @@ public class MenuEntrySwapperPlugin extends Plugin swap("climb", "climb-down", () -> (shiftModifier() ? config.swapStairsShiftClick() : config.swapStairsLeftClick()) == MenuEntrySwapperConfig.StairsMode.CLIMB_DOWN); swap("deposit", "deposit-runes", config::swapDepositPool); - - swap("take", "uncharged cells", "take-1", () -> config.swapUnchargedCells() == UnchargedCellsMode.TAKE_1); - swap("take", "uncharged cells", "take-5", () -> config.swapUnchargedCells() == UnchargedCellsMode.TAKE_5); - swap("take", "uncharged cells", "take-10", () -> config.swapUnchargedCells() == UnchargedCellsMode.TAKE_10); } public Swap swap(String option, String swappedOption, Supplier enabled) @@ -482,7 +498,7 @@ public class MenuEntrySwapperPlugin extends Plugin client.getItemCompositionCache().reset(); } - private Integer getSwapConfig(boolean shift, int itemId) + private Integer getItemSwapConfig(boolean shift, int itemId) { itemId = ItemVariationMapping.map(itemId); String config = configManager.getConfiguration(shift ? SHIFTCLICK_CONFIG_GROUP : MenuEntrySwapperConfig.GROUP, ITEM_KEY_PREFIX + itemId); @@ -494,13 +510,13 @@ public class MenuEntrySwapperPlugin extends Plugin return Integer.parseInt(config); } - private void setSwapConfig(boolean shift, int itemId, int index) + private void setItemSwapConfig(boolean shift, int itemId, int index) { itemId = ItemVariationMapping.map(itemId); configManager.setConfiguration(shift ? SHIFTCLICK_CONFIG_GROUP : MenuEntrySwapperConfig.GROUP, ITEM_KEY_PREFIX + itemId, index); } - private void unsetSwapConfig(boolean shift, int itemId) + private void unsetItemSwapConfig(boolean shift, int itemId) { itemId = ItemVariationMapping.map(itemId); configManager.unsetConfiguration(shift ? SHIFTCLICK_CONFIG_GROUP : MenuEntrySwapperConfig.GROUP, ITEM_KEY_PREFIX + itemId); @@ -526,6 +542,7 @@ public class MenuEntrySwapperPlugin extends Plugin { if (!configuringShiftClick && !configuringLeftClick) { + configureObjectClick(event); return; } @@ -563,7 +580,7 @@ public class MenuEntrySwapperPlugin extends Plugin else { // Otherwise it is possible that we have Use swap configured - Integer config = getSwapConfig(true, itemId); + Integer config = getItemSwapConfig(true, itemId); if (config != null && config == -1) { activeAction = MenuAction.ITEM_USE; @@ -573,7 +590,7 @@ public class MenuEntrySwapperPlugin extends Plugin else { // Apply left click action from configuration - Integer config = getSwapConfig(false, itemId); + Integer config = getItemSwapConfig(false, itemId); if (config != null) { activeAction = config >= 0 @@ -596,7 +613,7 @@ public class MenuEntrySwapperPlugin extends Plugin int index = menuAction == MenuAction.ITEM_USE ? -1 : menuAction.getId() - MenuAction.ITEM_FIRST_OPTION.getId(); - setSwapConfig(configuringShiftClick, itemId, index); + setItemSwapConfig(configuringShiftClick, itemId, index); }); if (activeAction == menuAction) @@ -610,7 +627,81 @@ public class MenuEntrySwapperPlugin extends Plugin .setOption(RESET) .setTarget(configuringShiftClick ? SHIFT_CLICK_MENU_TARGET : LEFT_CLICK_MENU_TARGET) .setType(MenuAction.RUNELITE) - .onClick(e -> unsetSwapConfig(configuringShiftClick, itemId)); + .onClick(e -> unsetItemSwapConfig(configuringShiftClick, itemId)); + } + + private void configureObjectClick(MenuOpened event) + { + if (!shiftModifier() || !config.objectLeftClickCustomization()) + { + return; + } + + MenuEntry[] entries = event.getMenuEntries(); + for (int idx = entries.length - 1; idx >= 0; --idx) + { + MenuEntry entry = entries[idx]; + if (entry.getType() == MenuAction.EXAMINE_OBJECT) + { + final ObjectComposition composition = client.getObjectDefinition(entry.getIdentifier()); + final String[] actions = composition.getActions(); + + final MenuAction currentAction; + Integer swapConfig = getObjectSwapConfig(composition.getId()); + if (swapConfig != null) + { + currentAction = OBJECT_MENU_TYPES.get(swapConfig); + } + else + { + currentAction = defaultAction(composition); + } + + for (int actionIdx = 0; actionIdx < OBJECT_MENU_TYPES.size(); ++actionIdx) + { + if (Strings.isNullOrEmpty(actions[actionIdx])) + { + continue; + } + + final int menuIdx = actionIdx; + final MenuAction menuAction = OBJECT_MENU_TYPES.get(actionIdx); + if (currentAction == menuAction) + { + continue; + } + + client.createMenuEntry(idx) + .setOption("Swap " + actions[actionIdx]) + .setTarget(entry.getTarget()) + .setType(MenuAction.RUNELITE) + .onClick(e -> + { + final String message = new ChatMessageBuilder() + .append("The default left click option for '").append(composition.getName()).append("' ") + .append("has been set to '").append(actions[menuIdx]).append("'.") + .build(); + + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.CONSOLE) + .runeLiteFormattedMessage(message) + .build()); + + log.debug("Set object swap for {} to {}", composition.getId(), menuAction); + + final MenuAction defaultAction = defaultAction(composition); + if (defaultAction != menuAction) + { + setObjectSwapConfig(composition.getId(), menuIdx); + } + else + { + unsetObjectSwapConfig(composition.getId()); + } + }); + } + } + } } @Subscribe @@ -715,7 +806,7 @@ public class MenuEntrySwapperPlugin extends Plugin // the client unable to perform the swap itself. if (config.shiftClickCustomization() && !option.equals("use")) { - Integer customOption = getSwapConfig(true, eventId); + Integer customOption = getItemSwapConfig(true, eventId); if (customOption != null && customOption == -1) { @@ -731,7 +822,7 @@ public class MenuEntrySwapperPlugin extends Plugin // Custom left-click item swap if (itemOp) { - Integer swapIndex = getSwapConfig(false, eventId); + Integer swapIndex = getItemSwapConfig(false, eventId); if (swapIndex != null) { MenuAction swapAction = swapIndex >= 0 @@ -746,6 +837,29 @@ public class MenuEntrySwapperPlugin extends Plugin } } + if (OBJECT_MENU_TYPES.contains(menuAction)) + { + // Get multiloc id + int objectId = eventId; + ObjectComposition objectComposition = client.getObjectDefinition(objectId); + if (objectComposition.getImpostorIds() != null) + { + objectComposition = objectComposition.getImpostor(); + objectId = objectComposition.getId(); + } + + Integer customOption = getObjectSwapConfig(objectId); + if (customOption != null) + { + MenuAction swapAction = OBJECT_MENU_TYPES.get(customOption); + if (swapAction == menuAction) + { + swap(optionIndexes, menuEntries, index, menuEntries.length - 1); + return; + } + } + } + // Built-in swaps Collection swaps = this.swaps.get(option); for (Swap swap : swaps) @@ -800,7 +914,7 @@ public class MenuEntrySwapperPlugin extends Plugin } ItemComposition itemComposition = event.getItemComposition(); - Integer option = getSwapConfig(true, itemComposition.getId()); + Integer option = getItemSwapConfig(true, itemComposition.getId()); if (option != null && option < itemComposition.getInventoryActions().length) { @@ -964,4 +1078,38 @@ public class MenuEntrySwapperPlugin extends Plugin configuringLeftClick = target.equals(LEFT_CLICK_MENU_TARGET); rebuildCustomizationMenus(); } + + private Integer getObjectSwapConfig(int objectId) + { + String config = configManager.getConfiguration(MenuEntrySwapperConfig.GROUP, OBJECT_KEY_PREFIX + objectId); + if (config == null || config.isEmpty()) + { + return null; + } + + return Integer.parseInt(config); + } + + private void setObjectSwapConfig(int objectId, int index) + { + configManager.setConfiguration(MenuEntrySwapperConfig.GROUP, OBJECT_KEY_PREFIX + objectId, index); + } + + private void unsetObjectSwapConfig(int objectId) + { + configManager.unsetConfiguration(MenuEntrySwapperConfig.GROUP, OBJECT_KEY_PREFIX + objectId); + } + + private static MenuAction defaultAction(ObjectComposition objectComposition) + { + String[] actions = objectComposition.getActions(); + for (int i = 0; i < OBJECT_MENU_TYPES.size(); ++i) + { + if (!Strings.isNullOrEmpty(actions[i])) + { + return OBJECT_MENU_TYPES.get(i); + } + } + return null; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java index 1f7bdcf57c..55339b884a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java @@ -69,7 +69,8 @@ public class RunecraftPlugin extends Plugin private static final List DEGRADED_POUCHES = ImmutableList.of( ItemID.MEDIUM_POUCH_5511, ItemID.LARGE_POUCH_5513, - ItemID.GIANT_POUCH_5515 + ItemID.GIANT_POUCH_5515, + ItemID.COLOSSAL_POUCH_26786 ); @Getter(AccessLevel.PACKAGE) diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPluginTest.java index 4fa03023a1..f051cfaa2d 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPluginTest.java @@ -34,8 +34,10 @@ import net.runelite.api.GameState; import net.runelite.api.KeyCode; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; +import net.runelite.api.ObjectComposition; import net.runelite.api.events.ClientTick; import net.runelite.api.events.MenuEntryAdded; +import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; import net.runelite.client.menus.TestMenuEntry; @@ -45,10 +47,12 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import org.mockito.Mock; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -70,6 +74,10 @@ public class MenuEntrySwapperPluginTest @Bind ItemManager itemManager; + @Mock + @Bind + ChatMessageManager chatMessageManager; + @Mock @Bind MenuEntrySwapperConfig config; @@ -85,6 +93,7 @@ public class MenuEntrySwapperPluginTest Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + when(client.getObjectDefinition(anyInt())).thenReturn(mock(ObjectComposition.class)); when(client.getMenuEntries()).thenAnswer((Answer) invocationOnMock -> {