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 12fe00ed39..22bd9731d4 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 @@ -41,6 +41,7 @@ public class WidgetID public static final int LOGOUT_PANEL_ID = 182; public static final int BANK_GROUP_ID = 12; public static final int BANK_INVENTORY_GROUP_ID = 15; + public static final int BANK_PIN_GROUP_ID = 213; public static final int GRAND_EXCHANGE_INVENTORY_GROUP_ID = 467; public static final int GRAND_EXCHANGE_GROUP_ID = 465; public static final int DEPOSIT_BOX_GROUP_ID = 192; @@ -353,6 +354,7 @@ public class WidgetID static final int MINIMAP = 3; static final int MINIMAP_DRAW_AREA = 8; static final int MULTICOMBAT_INDICATOR = 20; + static final int BANK_PIN = 21; static final int CLAN_CHAT_TAB = 31; static final int FRIENDS_TAB = 33; static final int IGNORES_TAB = 32; @@ -390,6 +392,7 @@ public class WidgetID static class ResizableViewport { static final int ITEMS_KEPT_ON_DEATH = 13; + static final int BANK_PIN = 13; static final int MULTICOMBAT_INDICATOR = 16; static final int CLAN_CHAT_TAB = 35; static final int FRIENDS_TAB = 37; @@ -425,6 +428,7 @@ public class WidgetID static class ResizableViewportBottomLine { + static final int BANK_PIN = 13; static final int LOGOUT_BUTTON_OVERLAY = 29; static final int CMB_TAB = 50; static final int CMB_ICON = 57; @@ -1062,4 +1066,18 @@ public class WidgetID public static final int TOTAL_TAX = 39; public static final int WINNINGS = 40; } + + public static class BankPin + { + public static final int BUTTON_1 = 16; + public static final int BUTTON_2 = 18; + public static final int BUTTON_3 = 20; + public static final int BUTTON_4 = 22; + public static final int BUTTON_5 = 24; + public static final int BUTTON_6 = 26; + public static final int BUTTON_7 = 28; + public static final int BUTTON_8 = 30; + public static final int BUTTON_9 = 32; + public static final int BUTTON_0 = 34; + } } 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 a059fd9d49..9f6f929952 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 @@ -705,7 +705,21 @@ public enum WidgetInfo ITEMS_KEPT_SAFE_ZONE_CONTAINER(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.SAFE_ZONE_CONTAINER), ITEMS_KEPT_CUSTOM_TEXT_CONTAINER(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.CUSTOM_TEXT_CONTAINER), ITEMS_LOST_VALUE(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.LOST_ITEMS_VALUE), - ITEMS_KEPT_MAX(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.MAX_ITEMS_KEPT_ON_DEATH); + ITEMS_KEPT_MAX(WidgetID.KEPT_ON_DEATH_GROUP_ID, WidgetID.KeptOnDeath.MAX_ITEMS_KEPT_ON_DEATH), + + FIXED_BANK_PIN(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.FixedViewport.BANK_PIN), + RESIZABLE_BANK_PIN(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.ResizableViewport.BANK_PIN), + RESIZABLE_BOTTOM_LINE_BANK_PIN(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.BANK_PIN), + BANK_PIN_1(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_1), + BANK_PIN_2(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_2), + BANK_PIN_3(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_3), + BANK_PIN_4(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_4), + BANK_PIN_5(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_5), + BANK_PIN_6(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_6), + BANK_PIN_7(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_7), + BANK_PIN_8(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_8), + BANK_PIN_9(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_9), + BANK_PIN_0(WidgetID.BANK_PIN_GROUP_ID, WidgetID.BankPin.BUTTON_0); private final int groupId; private final int childId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java index 7e666c19b2..8db739148c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusConfig.java @@ -71,4 +71,14 @@ public interface RuneLitePlusConfig extends Config return 100; } + @ConfigItem( + keyName = "keyboardPin", + name = "Keyboard bank pin", + description = "Enables you to type your bank pin", + position = 3 + ) + default boolean keyboardPin() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java index 72c638588c..5be13a27c2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java @@ -27,18 +27,32 @@ package net.runelite.client.plugins.runeliteplus; +import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.util.Map; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.MenuAction; import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.RuneLiteProperties; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.discord.DiscordService; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; import net.runelite.client.ui.ClientUI; +import org.apache.commons.lang3.ArrayUtils; @PluginDescriptor( loadWhenOutdated = true, // prevent users from disabling @@ -51,9 +65,63 @@ import net.runelite.client.ui.ClientUI; @Slf4j public class RuneLitePlusPlugin extends Plugin { + private class RuneLitePlusKeyListener implements KeyListener + { + private int lastKeyCycle; + + @Override + public void keyTyped(KeyEvent keyEvent) + { + if (!isNumber(keyEvent)) + { + return; + } + + if (client.getGameCycle() - lastKeyCycle <= 5) + { + keyEvent.consume(); + return; + } + + lastKeyCycle = client.getGameCycle(); + + clientThread.invoke(() -> handleKey(keyEvent.getKeyChar())); + keyEvent.consume(); + } + + @Override + public void keyPressed(KeyEvent keyEvent) + { + } + + @Override + public void keyReleased(KeyEvent keyEvent) + { + } + + private boolean isNumber(KeyEvent keyEvent) + { + char character = keyEvent.getKeyChar(); + return ArrayUtils.contains(numbers, character); + } + } + + private static final ImmutableSet buttons = ImmutableSet.of( + WidgetInfo.BANK_PIN_1, + WidgetInfo.BANK_PIN_2, + WidgetInfo.BANK_PIN_3, + WidgetInfo.BANK_PIN_4, + WidgetInfo.BANK_PIN_5, + WidgetInfo.BANK_PIN_6, + WidgetInfo.BANK_PIN_7, + WidgetInfo.BANK_PIN_8, + WidgetInfo.BANK_PIN_9, + WidgetInfo.BANK_PIN_0 + ); public static boolean customPresenceEnabled = false; public static final String rlPlusDiscordApp = "560644885250572289"; public static final String rlDiscordApp = "409416265891971072"; + private static final char[] numbers = "0123456789".toCharArray(); @Inject public RuneLitePlusConfig config; @@ -64,6 +132,14 @@ public class RuneLitePlusPlugin extends Plugin @Inject public DiscordService discordService; + @Inject + private KeyManager keyManager; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; @Provides RuneLitePlusConfig getConfig(ConfigManager configManager) @@ -71,6 +147,8 @@ public class RuneLitePlusPlugin extends Plugin return configManager.getConfig(RuneLitePlusConfig.class); } + private RuneLitePlusKeyListener keyListener; + @Override protected void startUp() throws Exception { @@ -122,13 +200,106 @@ public class RuneLitePlusPlugin extends Plugin discordService.close(); discordService.init(); } + + if (!config.keyboardPin()) + { + keyManager.unregisterKeyListener(keyListener); + } } } @Override protected void shutDown() throws Exception { - + keyManager.unregisterKeyListener(keyListener); } + @Subscribe + public void onWidgetLoaded(WidgetLoaded event) + { + if (!config.keyboardPin()) + { + return; + } + + if (event.getGroupId() == WidgetID.BANK_GROUP_ID) + { + // log.debug("Bank opened, removing key listener"); + keyManager.unregisterKeyListener(keyListener); + return; + } + else if (event.getGroupId() != WidgetID.BANK_PIN_GROUP_ID) + { + return; + } + + // log.debug("Registering key listener"); + keyListener = new RuneLitePlusKeyListener(); + keyManager.registerKeyListener(keyListener); + } + + private void handleKey(char c) + { + if (client.getWidget(WidgetID.BANK_PIN_GROUP_ID, 0) == null) + { + // log.debug("Key was pressed, but widget wasn't open"); + keyManager.unregisterKeyListener(keyListener); + return; + } + + Map buttonMap = new HashMap<>(); + Widget unknown = null; + + for (WidgetInfo w : buttons) + { + Widget widget = client.getWidget(w); + + if (widget == null) + { + // log.debug(w.toString() + " is null, returning early"); + continue; + } + else if (widget.getChild(1) == null || widget.getChild(1).isHidden()) + { + // log.debug(widget.getId() + " wasn't null, but either the text was missing or child was null"); + unknown = widget; + } + else + { + try + { + char number = widget.getChild(1).getText().charAt(0); + buttonMap.put(number, widget); + // log.debug(number + " is widget " + widget.getId()); + } + catch (IndexOutOfBoundsException e) + { + // log.debug("There was no text in widget " + widget.getId()); + unknown = widget; + } + } + } + + if (unknown != null && buttonMap.size() == 9) + { + for (char num : numbers) + { + if (!buttonMap.containsKey(num)) + { + // log.debug(num + " must be the unknown char for widget " + unknown.getId()); + buttonMap.put(num, unknown); + } + } + } + + if (buttonMap.size() != 10) + { + // log.debug("We didn't have 10 numbers, rip"); + return; + } + + Widget w = buttonMap.get(c); + + client.invokeMenuAction(0, w.getId(), MenuAction.WIDGET_DEFAULT.getId(), 1, "Select", "", w.getCanvasLocation().getX() + 32, w.getCanvasLocation().getY() + 32); + } }