Merge pull request #1125 from Kamielvf/shift-click-customization
Shift click customization
This commit is contained in:
@@ -81,4 +81,22 @@ public interface ItemComposition
|
||||
* @return true if stackable, false otherwise
|
||||
*/
|
||||
boolean isStackable();
|
||||
|
||||
/**
|
||||
* Returns the menu actions the item has in a players' inventory
|
||||
*
|
||||
* @return the inventory menu actions
|
||||
*/
|
||||
String[] getInventoryActions();
|
||||
|
||||
/**
|
||||
* Returns the menu action index of the shift-click action
|
||||
*
|
||||
* @return menu index of the shift-click action
|
||||
*/
|
||||
int getShiftClickActionIndex();
|
||||
|
||||
void setShiftClickActionIndex(int shiftclickActionIndex);
|
||||
|
||||
void resetShiftClickActionIndex();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* 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.ItemComposition;
|
||||
|
||||
@Data
|
||||
public class PostItemComposition
|
||||
{
|
||||
private ItemComposition itemComposition;
|
||||
}
|
||||
@@ -207,16 +207,19 @@ public class WidgetID
|
||||
|
||||
static class FixedViewport
|
||||
{
|
||||
static final int INVENTORY_TAB = 51;
|
||||
static final int PRAYER_TAB = 53;
|
||||
}
|
||||
|
||||
static class ResizableViewport
|
||||
{
|
||||
static final int INVENTORY_TAB = 54;
|
||||
static final int PRAYER_TAB = 56;
|
||||
}
|
||||
|
||||
static class ResizableViewportBottomLine
|
||||
{
|
||||
static final int INVENTORY_TAB = 51;
|
||||
static final int PRAYER_TAB = 53;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,11 +114,14 @@ public enum WidgetInfo
|
||||
LOGIN_CLICK_TO_PLAY_SCREEN(WidgetID.LOGIN_CLICK_TO_PLAY_GROUP_ID, 0),
|
||||
|
||||
FIXED_VIEWPORT(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.Viewport.FIXED_VIEWPORT),
|
||||
FIXED_VIEWPORT_INVENTORY_TAB(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.FixedViewport.INVENTORY_TAB),
|
||||
FIXED_VIEWPORT_PRAYER_TAB(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.FixedViewport.PRAYER_TAB),
|
||||
MINIMAP_WIDGET(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.Viewport.MINIMAP_WIDGET),
|
||||
RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.Viewport.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX),
|
||||
RESIZABLE_VIEWPORT_INVENTORY_TAB(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.ResizableViewport.INVENTORY_TAB),
|
||||
RESIZABLE_VIEWPORT_PRAYER_TAB(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.ResizableViewport.PRAYER_TAB),
|
||||
RESIZABLE_VIEWPORT_BOTTOM_LINE(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.Viewport.RESIZABLE_VIEWPORT_BOTTOM_LINE),
|
||||
RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.INVENTORY_TAB),
|
||||
RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.PRAYER_TAB),
|
||||
|
||||
PRAYER_THICK_SKIN(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.THICK_SKIN),
|
||||
|
||||
@@ -38,6 +38,7 @@ import java.awt.image.BufferedImage;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.KeyFocusListener;
|
||||
import net.runelite.api.MainBufferProvider;
|
||||
import net.runelite.api.MenuAction;
|
||||
@@ -54,6 +55,7 @@ import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.PostItemComposition;
|
||||
import net.runelite.api.events.ProjectileMoved;
|
||||
import net.runelite.api.events.SetMessage;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
@@ -413,4 +415,11 @@ public class Hooks
|
||||
eventBus.post(death);
|
||||
}
|
||||
}
|
||||
|
||||
public static void postItemComposition(ItemComposition itemComposition)
|
||||
{
|
||||
PostItemComposition event = new PostItemComposition();
|
||||
event.setItemComposition(itemComposition);
|
||||
eventBus.post(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,17 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "shiftClickCustomization",
|
||||
name = "Customizable shift-click",
|
||||
description = "Allows customization of shift-clicks on items"
|
||||
)
|
||||
default boolean shiftClickCustomization()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "swapPickpocket",
|
||||
name = "Pickpocket",
|
||||
description = "Swap Talk-to with Pickpocket on NPC<br>Example: Man, Woman"
|
||||
@@ -47,7 +58,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
position = 2,
|
||||
keyName = "swapBanker",
|
||||
name = "Bank",
|
||||
description = "Swap Talk-to with Bank on Bank NPC<br>Example: Banker"
|
||||
@@ -58,7 +69,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
position = 3,
|
||||
keyName = "swapExchange",
|
||||
name = "Exchange",
|
||||
description = "Swap Talk-to with Exchange on NPC<br>Example: Grand Exchange Clerk, Tool Leprechaun, Void Knight"
|
||||
@@ -69,7 +80,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
position = 4,
|
||||
keyName = "swapHarpoon",
|
||||
name = "Harpoon",
|
||||
description = "Swap Cage, Big Net with Harpoon on Fishing spot"
|
||||
@@ -80,7 +91,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
position = 5,
|
||||
keyName = "swapTrade",
|
||||
name = "Trade",
|
||||
description = "Swap Talk-to with Trade on NPC<br>Example: Shop keeper, Shop assistant"
|
||||
@@ -91,7 +102,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 5,
|
||||
position = 6,
|
||||
keyName = "swapTravel",
|
||||
name = "Travel",
|
||||
description = "Swap Talk-to with Travel, Take-boat, Pay-fare, Charter on NPC<br>Example: Squire, Monk of Entrana, Customs officer, Trader Crewmember"
|
||||
@@ -102,7 +113,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
position = 7,
|
||||
keyName = "swapPay",
|
||||
name = "Pay",
|
||||
description = "Swap Talk-to with Pay on NPC<br>Example: Elstan, Heskel, Fayeth"
|
||||
@@ -113,7 +124,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
position = 8,
|
||||
keyName = "swapHome",
|
||||
name = "Home",
|
||||
description = "Swap Enter with Home on Portal"
|
||||
@@ -124,7 +135,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
position = 9,
|
||||
keyName = "swapLastDestination",
|
||||
name = "Last-destination (XXX)",
|
||||
description = "Swap Zanaris with Last-destination on Fairy ring"
|
||||
@@ -135,7 +146,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 9,
|
||||
position = 10,
|
||||
keyName = "swapBoxTrap",
|
||||
name = "Reset",
|
||||
description = "Swap Check with Reset on box trap"
|
||||
@@ -146,7 +157,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 10,
|
||||
position = 11,
|
||||
keyName = "swapCatacombEntrance",
|
||||
name = "Catacomb entrance",
|
||||
description = "Swap Read with Investigate on Catacombs of Kourend entrance"
|
||||
@@ -157,7 +168,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 11,
|
||||
position = 12,
|
||||
keyName = "swapTeleportItem",
|
||||
name = "Teleport item",
|
||||
description = "Swap Wear, Wield with Rub, Teleport on teleport item<br>Example: Amulet of glory, Ardougne cloak, Chronicle"
|
||||
@@ -168,7 +179,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 12,
|
||||
position = 13,
|
||||
keyName = "swapSilverSickle",
|
||||
name = "Silver sickle(b)",
|
||||
description = "Swap Wield with Cast Bloom on Silver sickle(b)"
|
||||
@@ -179,7 +190,7 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 13,
|
||||
position = 14,
|
||||
keyName = "swapBones",
|
||||
name = "Bury",
|
||||
description = "Swap Bury with Use on Bones"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Kamiel
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,14 +27,32 @@ package net.runelite.client.plugins.menuentryswapper;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.PostItemComposition;
|
||||
import net.runelite.api.events.WidgetMenuOptionClicked;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.input.MouseManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.menus.WidgetMenuOption;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Menu Entry Swapper",
|
||||
@@ -41,18 +60,163 @@ import net.runelite.client.plugins.PluginDescriptor;
|
||||
)
|
||||
public class MenuEntrySwapperPlugin extends Plugin
|
||||
{
|
||||
private static final String CONFIGURE = "Configure";
|
||||
private static final String SAVE = "Save";
|
||||
private static final String MENU_TARGET = "Shift-click";
|
||||
|
||||
private static final String CONFIG_GROUP = "shiftclick";
|
||||
private static final String ITEM_KEY_PREFIX = "item_";
|
||||
|
||||
private static final WidgetMenuOption FIXED_INVENTORY_TAB_CONFIGURE = new WidgetMenuOption(CONFIGURE,
|
||||
MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB);
|
||||
|
||||
private static final WidgetMenuOption FIXED_INVENTORY_TAB_SAVE = new WidgetMenuOption(SAVE,
|
||||
MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB);
|
||||
|
||||
private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_CONFIGURE = new WidgetMenuOption(CONFIGURE,
|
||||
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB);
|
||||
|
||||
private static final WidgetMenuOption RESIZABLE_INVENTORY_TAB_SAVE = new WidgetMenuOption(SAVE,
|
||||
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB);
|
||||
|
||||
private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE = new WidgetMenuOption(CONFIGURE,
|
||||
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB);
|
||||
|
||||
private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE = new WidgetMenuOption(SAVE,
|
||||
MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB);
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private MenuEntrySwapperConfig config;
|
||||
|
||||
@Inject
|
||||
private ShiftClickConfigurationOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private ShiftClickInputListener inputListener;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
private MouseManager mouseManager;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
@Inject
|
||||
private MenuManager menuManager;
|
||||
|
||||
@Getter
|
||||
private boolean configuringShiftClick = false;
|
||||
|
||||
@Setter
|
||||
private boolean shiftModifier = false;
|
||||
|
||||
@Provides
|
||||
MenuEntrySwapperConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(MenuEntrySwapperConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Overlay getOverlay()
|
||||
{
|
||||
return overlay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
if (config.shiftClickCustomization())
|
||||
{
|
||||
enableCustomization();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
disableCustomization();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getKey().equals("shiftClickCustomization"))
|
||||
{
|
||||
if (config.shiftClickCustomization())
|
||||
{
|
||||
enableCustomization();
|
||||
}
|
||||
else
|
||||
{
|
||||
disableCustomization();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Integer getSwapConfig(int itemId)
|
||||
{
|
||||
String config = configManager.getConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
||||
if (config == null || config.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Integer.parseInt(config);
|
||||
}
|
||||
|
||||
private void setSwapConfig(int itemId, int index)
|
||||
{
|
||||
configManager.setConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId, index);
|
||||
}
|
||||
|
||||
private void unsetSwapConfig(int itemId)
|
||||
{
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
||||
}
|
||||
|
||||
private void enableCustomization()
|
||||
{
|
||||
keyManager.registerKeyListener(inputListener);
|
||||
refreshShiftClickCustomizationMenus();
|
||||
}
|
||||
|
||||
private void disableCustomization()
|
||||
{
|
||||
keyManager.unregisterKeyListener(inputListener);
|
||||
mouseManager.unregisterMouseListener(inputListener);
|
||||
removeShiftClickCustomizationMenus();
|
||||
configuringShiftClick = false;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetMenuOptionClicked(WidgetMenuOptionClicked event)
|
||||
{
|
||||
if (event.getWidget() == WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB
|
||||
|| event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_TAB
|
||||
|| event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_TAB)
|
||||
{
|
||||
configuringShiftClick = event.getMenuOption().equals(CONFIGURE);
|
||||
refreshShiftClickCustomizationMenus();
|
||||
|
||||
if (configuringShiftClick)
|
||||
{
|
||||
mouseManager.registerMouseListener(inputListener);
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseManager.unregisterMouseListener(inputListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
@@ -61,8 +225,9 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
String option = event.getOption().toLowerCase();
|
||||
String target = event.getTarget();
|
||||
int itemId = event.getIdentifier();
|
||||
String option = Text.removeTags(event.getOption()).toLowerCase();
|
||||
String target = Text.removeTags(event.getTarget()).toLowerCase();
|
||||
|
||||
if (option.equals("talk-to"))
|
||||
{
|
||||
@@ -144,6 +309,31 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
{
|
||||
swap("use", option, target, true);
|
||||
}
|
||||
else if (config.shiftClickCustomization() && shiftModifier && !option.equals("use"))
|
||||
{
|
||||
Integer customOption = getSwapConfig(itemId);
|
||||
|
||||
if (customOption != null && customOption == -1)
|
||||
{
|
||||
swap("use", option, target, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPostItemComposition(PostItemComposition event)
|
||||
{
|
||||
ItemComposition itemComposition = event.getItemComposition();
|
||||
Integer option = getSwapConfig(itemComposition.getId());
|
||||
|
||||
if (option != null)
|
||||
{
|
||||
itemComposition.setShiftClickActionIndex(option);
|
||||
|
||||
// Update our cached item composition too
|
||||
ItemComposition ourItemComposition = itemManager.getItemComposition(itemComposition.getId());
|
||||
ourItemComposition.setShiftClickActionIndex(option);
|
||||
}
|
||||
}
|
||||
|
||||
private int searchIndex(MenuEntry[] entries, String option, String target, boolean strict)
|
||||
@@ -151,21 +341,25 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
for (int i = entries.length - 1; i >= 0; i--)
|
||||
{
|
||||
MenuEntry entry = entries[i];
|
||||
String entryOption = Text.removeTags(entry.getOption()).toLowerCase();
|
||||
String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase();
|
||||
|
||||
if (strict)
|
||||
{
|
||||
if (entry.getOption().toLowerCase().equals(option) && entry.getTarget().equals(target))
|
||||
if (entryOption.equals(option) && entryTarget.equals(target))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry.getOption().toLowerCase().contains(option) && entry.getTarget().equals(target))
|
||||
if (entryOption.contains(option.toLowerCase()) && entryTarget.equals(target))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -185,4 +379,81 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
client.setMenuEntries(entries);
|
||||
}
|
||||
}
|
||||
|
||||
public void cycleItemShiftClickAction(WidgetItem item, int mouseClick)
|
||||
{
|
||||
ItemComposition itemComposition = client.getItemDefinition(item.getId());
|
||||
|
||||
if (mouseClick == MouseEvent.BUTTON1)
|
||||
{
|
||||
String[] actions = itemComposition.getInventoryActions();
|
||||
int shiftClickActionIndex = itemComposition.getShiftClickActionIndex();
|
||||
int nextActionIndex = getNextActionIndex(actions, shiftClickActionIndex);
|
||||
setSwapConfig(item.getId(), nextActionIndex);
|
||||
itemComposition.setShiftClickActionIndex(nextActionIndex);
|
||||
}
|
||||
else if (mouseClick == MouseEvent.BUTTON3)
|
||||
{
|
||||
unsetSwapConfig(item.getId());
|
||||
itemComposition.resetShiftClickActionIndex();
|
||||
}
|
||||
}
|
||||
|
||||
private int getNextActionIndex(String[] actions, int currentIndex)
|
||||
{
|
||||
int size = actions.length;
|
||||
int index = currentIndex + 1;
|
||||
|
||||
for (int i = index; i < index + size; i++)
|
||||
{
|
||||
if (i == size)
|
||||
{
|
||||
// -1 is used for "Use" which is not in actions
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = i % size;
|
||||
|
||||
if (actions[index] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private void removeShiftClickCustomizationMenus()
|
||||
{
|
||||
menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE);
|
||||
menuManager.removeManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE);
|
||||
menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE);
|
||||
menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE);
|
||||
menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE);
|
||||
menuManager.removeManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE);
|
||||
}
|
||||
|
||||
private void refreshShiftClickCustomizationMenus()
|
||||
{
|
||||
removeShiftClickCustomizationMenus();
|
||||
if (configuringShiftClick)
|
||||
{
|
||||
menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_SAVE);
|
||||
menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_SAVE);
|
||||
menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_SAVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
menuManager.addManagedCustomMenu(FIXED_INVENTORY_TAB_CONFIGURE);
|
||||
menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_INVENTORY_TAB_CONFIGURE);
|
||||
menuManager.addManagedCustomMenu(RESIZABLE_INVENTORY_TAB_CONFIGURE);
|
||||
}
|
||||
}
|
||||
|
||||
Collection<WidgetItem> getInventoryItems()
|
||||
{
|
||||
return Collections.unmodifiableCollection(client.getWidget(WidgetInfo.INVENTORY).getWidgetItems());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Kamiel
|
||||
* 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.menuentryswapper;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
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.components.TextComponent;
|
||||
|
||||
public class ShiftClickConfigurationOverlay extends Overlay
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private MenuEntrySwapperPlugin plugin;
|
||||
|
||||
@Inject
|
||||
public ShiftClickConfigurationOverlay()
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isConfiguringShiftClick() || client.isMenuOpen() || client.getWidget(WidgetInfo.INVENTORY).isHidden())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Font font = FontManager.getRunescapeSmallFont();
|
||||
graphics.setFont(font);
|
||||
|
||||
net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition();
|
||||
Point mousePoint = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY());
|
||||
|
||||
for (WidgetItem item : plugin.getInventoryItems())
|
||||
{
|
||||
final Rectangle bounds = item.getCanvasBounds();
|
||||
|
||||
if (!bounds.contains(mousePoint))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemComposition itemComposition = client.getItemDefinition(item.getId());
|
||||
String[] actions = itemComposition.getInventoryActions();
|
||||
int index = itemComposition.getShiftClickActionIndex();
|
||||
|
||||
if (index >= 0 && actions[index] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
String action = index == -1 ? "Use" : actions[index];
|
||||
int textWidth = graphics.getFontMetrics().stringWidth(action);
|
||||
int textLocationX = (int) (bounds.x + bounds.getWidth() / 2 - textWidth / 2);
|
||||
int textLocationY = bounds.y + 28;
|
||||
final TextComponent textComponent = new TextComponent();
|
||||
textComponent.setPosition(new Point(textLocationX, textLocationY));
|
||||
textComponent.setText(action);
|
||||
textComponent.render(graphics);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Kamiel
|
||||
* 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.menuentryswapper;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.MouseListener;
|
||||
|
||||
public class ShiftClickInputListener extends MouseListener implements KeyListener
|
||||
{
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private MenuEntrySwapperPlugin plugin;
|
||||
|
||||
@Inject
|
||||
private MenuEntrySwapperConfig config;
|
||||
|
||||
private WidgetItem getClickedItem(Point point)
|
||||
{
|
||||
for (WidgetItem item : plugin.getInventoryItems())
|
||||
{
|
||||
if (item.getCanvasBounds().contains(point))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseClicked(MouseEvent event)
|
||||
{
|
||||
if (!config.shiftClickCustomization() || !isValidInventoryClick(event.getPoint()))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
final WidgetItem item = getClickedItem(event.getPoint());
|
||||
final int button = event.getButton();
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
clientThread.invokeLater(() -> plugin.cycleItemShiftClickAction(item, button));
|
||||
event.consume();
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mousePressed(MouseEvent event)
|
||||
{
|
||||
if (!config.shiftClickCustomization() || !isValidInventoryClick(event.getPoint()))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
event.consume();
|
||||
return event;
|
||||
}
|
||||
|
||||
private boolean isValidInventoryClick(Point point)
|
||||
{
|
||||
Widget widget = client.getWidget(WidgetInfo.INVENTORY).getParent();
|
||||
return !widget.isHidden() && !client.isMenuOpen() && widget.getBounds().contains(point);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent event)
|
||||
{
|
||||
if (event.getKeyCode() == KeyEvent.VK_SHIFT)
|
||||
{
|
||||
plugin.setShiftModifier(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent event)
|
||||
{
|
||||
if (event.getKeyCode() == KeyEvent.VK_SHIFT)
|
||||
{
|
||||
plugin.setShiftModifier(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,17 +25,52 @@
|
||||
|
||||
package net.runelite.mixins;
|
||||
|
||||
import net.runelite.api.mixins.Copy;
|
||||
import net.runelite.api.mixins.Inject;
|
||||
import net.runelite.api.mixins.Mixin;
|
||||
import net.runelite.api.mixins.Replace;
|
||||
import net.runelite.rs.api.RSItemComposition;
|
||||
|
||||
@Mixin(RSItemComposition.class)
|
||||
public abstract class RSItemCompositionMixin implements RSItemComposition
|
||||
{
|
||||
private static final int DEFAULT_CUSTOM_SHIFT_CLICK_INDEX = -2;
|
||||
|
||||
@Inject
|
||||
private int shiftClickActionIndex = DEFAULT_CUSTOM_SHIFT_CLICK_INDEX;
|
||||
|
||||
@Inject
|
||||
RSItemCompositionMixin()
|
||||
{
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Override
|
||||
public boolean isStackable()
|
||||
{
|
||||
return getIsStackable() != 0;
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Override
|
||||
public void setShiftClickActionIndex(int shiftClickActionIndex)
|
||||
{
|
||||
this.shiftClickActionIndex = shiftClickActionIndex;
|
||||
}
|
||||
|
||||
@Copy("getShiftClickActionIndex")
|
||||
abstract int rs$getShiftClickActionIndex();
|
||||
|
||||
@Replace("getShiftClickActionIndex")
|
||||
public int getShiftClickActionIndex()
|
||||
{
|
||||
return shiftClickActionIndex == DEFAULT_CUSTOM_SHIFT_CLICK_INDEX ? rs$getShiftClickActionIndex() : shiftClickActionIndex;
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Override
|
||||
public void resetShiftClickActionIndex()
|
||||
{
|
||||
shiftClickActionIndex = DEFAULT_CUSTOM_SHIFT_CLICK_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,4 +69,12 @@ public interface RSItemComposition extends ItemComposition
|
||||
|
||||
@Import("maleModel")
|
||||
int getMaleModel();
|
||||
|
||||
@Import("inventoryActions")
|
||||
@Override
|
||||
String[] getInventoryActions();
|
||||
|
||||
@Import("getShiftClickActionIndex")
|
||||
@Override
|
||||
int getShiftClickActionIndex();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user