From 7c2e71cc5593fe92221099af3606b1d8f5046355 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Thu, 25 Apr 2019 21:26:21 +0100 Subject: [PATCH 1/6] location to cc plugin --- .../LocationChatterConfig.java | 16 ++ .../LocationChatterPlugin.java | 140 +++++++++++ .../WildernessLocationsPlugin.java | 224 +++++++++--------- 3 files changed, 270 insertions(+), 110 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterConfig.java new file mode 100644 index 0000000000..745e0fa64e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterConfig.java @@ -0,0 +1,16 @@ +package net.runelite.client.plugins.locationchatter; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Keybind; + +@ConfigGroup("locationchatter") +public interface LocationChatterConfig extends Config +{ + @ConfigItem(keyName = "keybind", name = "Send to CC", description = "Configure button to send current location to CC") + default Keybind keybind() + { + return Keybind.NOT_SET; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterPlugin.java new file mode 100644 index 0000000000..e464bb14cf --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/locationchatter/LocationChatterPlugin.java @@ -0,0 +1,140 @@ +package net.runelite.client.plugins.locationchatter; + +import com.google.inject.Provides; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.ScriptID; +import net.runelite.api.VarClientStr; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.VarClientStrChanged; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginManager; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.plugins.wildernesslocations.WildernessLocationsPlugin; +import net.runelite.client.util.HotkeyListener; + +import javax.inject.Inject; + +@Slf4j +@PluginDescriptor( + name = "Location Chatter", + tags = {"location", "exilent", "pklite", "spammer"}, + type = PluginType.UTILITY + ) +public class LocationChatterPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + LocationChatterConfig config; + + @Inject + private KeyManager keyManager; + + @Inject + private PluginManager pluginManager; + + private WildernessLocationsPlugin wildyLocsPlugin; + + private String oldChat = ""; + private int currentCooldown = 0; + private final int COOLDOWN_TICKS = 30; + + private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.keybind()) + { + @Override + public void hotkeyPressed() + { + sendLocToCC(); + } + }; + + @Override + public void startUp() + { + for (Plugin pl : pluginManager.getPlugins()) + { + if (pl instanceof WildernessLocationsPlugin) + { + wildyLocsPlugin = (WildernessLocationsPlugin) pl; + } + } + keyManager.registerKeyListener(hotkeyListener); + } + + @Override + public void shutDown() + { + keyManager.unregisterKeyListener(hotkeyListener); + } + + @Provides + LocationChatterConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(LocationChatterConfig.class); + } + + @Subscribe + public void onGameTick(GameTick tickEvent) + { + if (currentCooldown != 0) + { + currentCooldown--; + } + } + + @Subscribe + public void onVarClientStrChanged(VarClientStrChanged varClient) + { + String newChat = client.getVar(VarClientStr.CHATBOX_TYPED_TEXT); + if (varClient.getIndex() == VarClientStr.CHATBOX_TYPED_TEXT.getIndex() && !newChat.equals(oldChat)) + { + oldChat = newChat; + } + } + + private boolean inClanChat() + { + return client.getWidget(WidgetInfo.CLAN_CHAT_TITLE) != null; + } + + private void sendMessage(String text) + { + int mode = 0; + if (inClanChat() && text.startsWith("/")) + { + mode = 2; + } + int finalMode = mode; + Runnable r = () -> + { + String cached = oldChat; + client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, text); + client.runScript(ScriptID.CHATBOX_INPUT, finalMode, text); + oldChat = cached; + client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, oldChat); + }; + clientThread.invoke(r); + } + + private void sendLocToCC() + { + String location = wildyLocsPlugin.getLocationString(); + if (location.equals("")) + { + return; + } + sendMessage("/World: " + client.getWorld() + " Location: " + location); + currentCooldown = COOLDOWN_TICKS; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java index 30cc474a2b..d0c5bab2f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java @@ -1,16 +1,14 @@ - package net.runelite.client.plugins.wildernesslocations; + import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; -import java.util.function.Consumer; import javax.inject.Inject; + +import lombok.Getter; import net.runelite.api.Client; -import net.runelite.api.Player; import net.runelite.api.Varbits; import net.runelite.api.coords.WorldArea; import net.runelite.api.coords.WorldPoint; @@ -18,113 +16,119 @@ import net.runelite.api.events.GameTick; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.wildernesslocations.WildernessLocationsOverlay; -import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.WildernessLocation; -@PluginDescriptor(name="PvP Wild Locations", - description="Indicates the players current location in the wild", - tags={"Wildy,", "Wilderness Location", "location", "loc", "pvp", "pklite"}, - type = PluginType.PVP +@PluginDescriptor( + name = "Wild Locations", + description = "Indicates the players current location in the wild", + tags = {"Wildy", "Wilderness Location", "location", "loc", "pvp", "pklite"} ) - -public class WildernessLocationsPlugin extends Plugin { - @Inject - private Client client; - @Inject - OverlayManager overlayManager; - @Inject - private WildernessLocationsOverlay overlay; - private final HashMap wildLocs; - private boolean renderLocation; - private String locationString; - private WorldPoint worldPoint; - private static int UPDATE_INTERVAL = 3; - - public WildernessLocationsPlugin() { - overlay = new WildernessLocationsOverlay(client, this); - wildLocs = WildernessLocationsPlugin.getLocationMap(); - locationString = ""; - worldPoint = null; - } - - @Override - protected void startUp() throws Exception { - overlayManager.add(overlay); - } - - @Override - protected void shutDown() throws Exception { - overlayManager.add(overlay); - } - - @Subscribe - public void onGameTick(GameTick event) { - if (UPDATE_INTERVAL > 0) { - --UPDATE_INTERVAL; - return; - } - boolean bl = renderLocation = client.getVar(Varbits.IN_WILDERNESS) == 1; - if (renderLocation) { - if (client.getLocalPlayer().getWorldLocation() != worldPoint) { - locationString = location(); - worldPoint = client.getLocalPlayer().getWorldLocation(); - } - } else { - worldPoint = null; - locationString = ""; - } - UPDATE_INTERVAL = 3; - } - - private String location() { - int dist = 10000; - String s = ""; - WorldArea closestArea = null; - for (Map.Entry entry : wildLocs.entrySet()) { - WorldArea worldArea = entry.getKey(); - if (worldArea.toWorldPointList().contains(client.getLocalPlayer().getWorldLocation())) { - s = entry.getValue(); - return s; - } - int distTo = worldArea.distanceTo(client.getLocalPlayer().getWorldLocation()); - if (distTo >= dist) continue; - dist = distTo; - closestArea = worldArea; - } - if (client.getLocalPlayer().getWorldLocation().getY() > ((WorldArea)Objects.requireNonNull(closestArea)).toWorldPoint().getY() + closestArea.getHeight()) { - s = s + "N"; - } - if (client.getLocalPlayer().getWorldLocation().getY() < closestArea.toWorldPoint().getY()) { - s = s + "S"; - } - if (client.getLocalPlayer().getWorldLocation().getX() < closestArea.toWorldPoint().getX()) { - s = s + "W"; - } - if (client.getLocalPlayer().getWorldLocation().getX() > closestArea.toWorldPoint().getX() + closestArea.getWidth()) { - s = s + "E"; - } - s = s + " of "; - if ((s = s + wildLocs.get(closestArea)).startsWith(" of ")) { - s = s.substring(3); - } - return s; - } - - private static HashMap getLocationMap() { - HashMap hashMap = new HashMap(); - Arrays.stream(WildernessLocation.values()).forEach(wildernessLocation -> hashMap.put(wildernessLocation.getWorldArea(), wildernessLocation.getName())); - return hashMap; - } - - public boolean isRenderLocation() { - return renderLocation; - } - - public String getLocationString() { - return locationString; - } +public class WildernessLocationsPlugin extends Plugin +{ + + @Inject + private Client client; + + @Inject + OverlayManager overlayManager; + + @Inject + private WildernessLocationsOverlay overlay = new WildernessLocationsOverlay(this.client, this); + + private final HashMap wildLocs = getLocationMap(); + @Getter + private boolean renderLocation; + @Getter + private String locationString = ""; + private WorldPoint worldPoint = null; + + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + } + + @Subscribe + public void onGameTick(GameTick event) + { + renderLocation = client.getVar(Varbits.IN_WILDERNESS) == 1; + if (renderLocation) + { + if (client.getLocalPlayer().getWorldLocation() != worldPoint) + { + locationString = location(); + worldPoint = client.getLocalPlayer().getWorldLocation(); + } + } + else + { + worldPoint = null; + locationString = ""; + } + } + + + private String location() + { + int dist = 10000; + String s = ""; + WorldArea closestArea = null; + for (Map.Entry entry : wildLocs.entrySet()) + { + WorldArea worldArea = entry.getKey(); + + if (worldArea.toWorldPointList().contains(client.getLocalPlayer().getWorldLocation())) + { + s = entry.getValue(); + return s; + } + int distTo = worldArea.distanceTo(client.getLocalPlayer().getWorldLocation()); + if (distTo < dist) + { + dist = distTo; + closestArea = worldArea; + } + } + if (client.getLocalPlayer().getWorldLocation().getY() > + (Objects.requireNonNull(closestArea).toWorldPoint().getY() + closestArea.getHeight())) + { + s = s + "N"; + } + if (client.getLocalPlayer().getWorldLocation().getY() < closestArea.toWorldPoint().getY()) + { + s = s + "S"; + } + if (client.getLocalPlayer().getWorldLocation().getX() < closestArea.toWorldPoint().getX()) + { + s = s + "W"; + } + if (client.getLocalPlayer().getWorldLocation().getX() > + (closestArea.toWorldPoint().getX() + closestArea.getWidth())) + { + s = s + "E"; + } + s = s + " of "; + s = s + wildLocs.get(closestArea); + if (s.startsWith(" of ")) + { + s = s.substring(3); + } + return s; + } + + private static HashMap getLocationMap() + { + HashMap hashMap = new HashMap<>(); + Arrays.stream(WildernessLocation.values()).forEach(wildernessLocation -> + hashMap.put(wildernessLocation.getWorldArea(), wildernessLocation.getName())); + return hashMap; + } } - From 72407dd5a3bae0db991f94df350b1e1c4daea050 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Thu, 25 Apr 2019 21:36:30 +0100 Subject: [PATCH 2/6] Update WildernessLocationsPlugin.java --- .../plugins/wildernesslocations/WildernessLocationsPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java index d0c5bab2f0..27b0bc5f82 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java @@ -23,6 +23,7 @@ import net.runelite.client.util.WildernessLocation; name = "Wild Locations", description = "Indicates the players current location in the wild", tags = {"Wildy", "Wilderness Location", "location", "loc", "pvp", "pklite"} + type = PluginType.PVP ) public class WildernessLocationsPlugin extends Plugin { From 071ccdbe24ed24d861b80067961b25214b1fe5e3 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Thu, 25 Apr 2019 21:49:45 +0100 Subject: [PATCH 3/6] Add help text to profilepanel.java Add help text to account profiles to explain how to use them with encryption keys --- .../plugins/profiles/ProfilesPanel.java | 1132 +++++++++-------- 1 file changed, 577 insertions(+), 555 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java index 0366c4bda7..b0d03b20ba 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/profiles/ProfilesPanel.java @@ -1,555 +1,577 @@ -/* - * Copyright (c) 2019, Spedwards - * 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.profiles; - -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.util.Arrays; -import java.util.Base64; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.SecretKeySpec; -import javax.inject.Inject; -import javax.swing.*; -import javax.swing.border.EmptyBorder; - -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.PluginPanel; - -@Slf4j -class ProfilesPanel extends PluginPanel -{ - private static final int iterations = 100000; - private static final String UNLOCK_PASSWORD = "Encryption Password"; - private static final String LOAD_ACCOUNTS = "Load Accounts"; - private static final String ACCOUNT_USERNAME = "Account Username"; - private static final String ACCOUNT_LABEL = "Account Label"; - private static final String PASSWORD_LABEL = "Account Password"; - private static final Dimension PREFERRED_SIZE = new Dimension(PluginPanel.PANEL_WIDTH - 20, 30); - private static final Dimension MINIMUM_SIZE = new Dimension(0, 30); - - private final Client client; - private static ProfilesConfig profilesConfig; - - private final JPasswordField txtDecryptPassword = new JPasswordField(UNLOCK_PASSWORD); - private final JButton btnLoadAccounts = new JButton(LOAD_ACCOUNTS); - private final JTextField txtAccountLabel = new JTextField(ACCOUNT_LABEL); - private final JPasswordField txtAccountLogin = new JPasswordField(ACCOUNT_USERNAME); - private final JPasswordField txtPasswordLogin = new JPasswordField(PASSWORD_LABEL); - private final JPanel profilesPanel = new JPanel(); - private GridBagConstraints c; - - @Inject - public ProfilesPanel(Client client, ProfilesConfig config) - { - super(); - this.client = client; - profilesConfig = config; - - setBorder(new EmptyBorder(18, 10, 0, 10)); - setBackground(ColorScheme.DARK_GRAY_COLOR); - setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.gridx = 0; - c.gridy = 0; - c.weightx = 1; - c.weighty = 0; - c.insets = new Insets(0, 0, 4, 0); - - txtDecryptPassword.setEchoChar((char) 0); - txtDecryptPassword.setPreferredSize(PREFERRED_SIZE); - txtDecryptPassword.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - txtDecryptPassword.setBackground(ColorScheme.DARKER_GRAY_COLOR); - txtDecryptPassword.setMinimumSize(MINIMUM_SIZE); - txtDecryptPassword.setToolTipText(UNLOCK_PASSWORD); - txtDecryptPassword.addFocusListener(new FocusListener() - { - @Override - public void focusGained(FocusEvent e) - { - txtDecryptPassword.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - if (String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD)) - { - txtDecryptPassword.setText(""); - txtDecryptPassword.setEchoChar('*'); - } - } - - @Override - public void focusLost(FocusEvent e) - { - txtDecryptPassword.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - if (txtDecryptPassword.getPassword().length == 0) - { - txtDecryptPassword.setText(UNLOCK_PASSWORD); - txtDecryptPassword.setEchoChar((char) 0); - } - } - }); - - add(txtDecryptPassword, c); - c.gridy++; - - btnLoadAccounts.setPreferredSize(PREFERRED_SIZE); - btnLoadAccounts.setBackground(ColorScheme.DARKER_GRAY_COLOR); - btnLoadAccounts.setMinimumSize(MINIMUM_SIZE); - btnLoadAccounts.setToolTipText(LOAD_ACCOUNTS); - btnLoadAccounts.addMouseListener(new MouseListener() - { - @Override - public void mouseClicked(MouseEvent e) - { - - } - - @Override - public void mousePressed(MouseEvent e) - { - - } - - @Override - public void mouseReleased(MouseEvent e) - { - try - { - redrawProfiles(); - } - catch (InvalidKeySpecException | NoSuchAlgorithmException ex) - { - showErrorMessage("Unable to load data", "Incorrect password!"); - } - } - - @Override - public void mouseEntered(MouseEvent e) - { - - } - - @Override - public void mouseExited(MouseEvent e) - { - - } - }); - - add(btnLoadAccounts, c); - c.gridy++; - - txtAccountLabel.setPreferredSize(PREFERRED_SIZE); - txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - txtAccountLabel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - txtAccountLabel.setMinimumSize(MINIMUM_SIZE); - txtAccountLabel.addFocusListener(new FocusListener() - { - @Override - public void focusGained(FocusEvent e) - { - if (txtAccountLabel.getText().equals(ACCOUNT_LABEL)) - { - txtAccountLabel.setText(""); - txtAccountLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - } - } - - @Override - public void focusLost(FocusEvent e) - { - if (txtAccountLabel.getText().isEmpty()) - { - txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - txtAccountLabel.setText(ACCOUNT_LABEL); - } - } - }); - - add(txtAccountLabel, c); - c.gridy++; - - // Do not hide username characters until they focus or if in streamer mode - txtAccountLogin.setEchoChar((char) 0); - txtAccountLogin.setPreferredSize(PREFERRED_SIZE); - txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - txtAccountLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR); - txtAccountLogin.setMinimumSize(MINIMUM_SIZE); - txtAccountLogin.addFocusListener(new FocusListener() - { - @Override - public void focusGained(FocusEvent e) - { - if (ACCOUNT_USERNAME.equals(String.valueOf(txtAccountLogin.getPassword()))) - { - txtAccountLogin.setText(""); - if (config.isStreamerMode()) - { - txtAccountLogin.setEchoChar('*'); - } - txtAccountLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - } - } - - @Override - public void focusLost(FocusEvent e) - { - if (txtAccountLogin.getPassword().length == 0) - { - txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - txtAccountLogin.setText(ACCOUNT_USERNAME); - txtAccountLogin.setEchoChar((char) 0); - } - } - }); - - add(txtAccountLogin, c); - c.gridy++; - - txtPasswordLogin.setEchoChar((char) 0); - txtPasswordLogin.setPreferredSize(PREFERRED_SIZE); - txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - txtPasswordLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR); - txtPasswordLogin.setToolTipText(PASSWORD_LABEL); - txtPasswordLogin.setMinimumSize(MINIMUM_SIZE); - txtPasswordLogin.addFocusListener(new FocusListener() - { - @Override - public void focusGained(FocusEvent e) - { - if (PASSWORD_LABEL.equals(String.valueOf(txtPasswordLogin.getPassword()))) - { - txtPasswordLogin.setText(""); - txtPasswordLogin.setEchoChar('*'); - txtPasswordLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - } - } - - @Override - public void focusLost(FocusEvent e) - { - if (txtPasswordLogin.getPassword().length == 0) - { - txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - txtPasswordLogin.setText(PASSWORD_LABEL); - txtPasswordLogin.setEchoChar((char) 0); - } - } - }); - - - if (config.rememberPassword()) - { - add(txtPasswordLogin, c); - c.gridy++; - } - c.insets = new Insets(0, 0, 15, 0); - - JButton btnAddAccount = new JButton("Add Account"); - btnAddAccount.setPreferredSize(PREFERRED_SIZE); - btnAddAccount.setBackground(ColorScheme.DARKER_GRAY_COLOR); - btnAddAccount.setMinimumSize(MINIMUM_SIZE); - btnAddAccount.addActionListener(e -> - { - String labelText = String.valueOf(txtAccountLabel.getText()); - String loginText = String.valueOf(txtAccountLogin.getPassword()); - String passwordText = String.valueOf(txtPasswordLogin.getPassword()); - - if (labelText.equals(ACCOUNT_LABEL) || loginText.equals(ACCOUNT_USERNAME)) - { - return; - } - String data; - if (config.rememberPassword() && txtPasswordLogin.getPassword() != null) - { - data = labelText + ":" + loginText + ":" + passwordText; - } - else - { - data = labelText + ":" + loginText; - } - - try - { - if(!addProfile(data)) - { - return; - } - } - catch (InvalidKeySpecException | NoSuchAlgorithmException ex) - { - ex.printStackTrace(); - } - - this.addAccount(data); - - txtAccountLabel.setText(ACCOUNT_LABEL); - txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - - txtAccountLogin.setText(ACCOUNT_USERNAME); - txtAccountLogin.setEchoChar((char) 0); - txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - - txtPasswordLogin.setText(PASSWORD_LABEL); - txtPasswordLogin.setEchoChar((char) 0); - txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); - }); - - txtAccountLogin.addKeyListener(new KeyAdapter() - { - @Override - public void keyPressed(KeyEvent e) - { - if (e.getKeyCode() == KeyEvent.VK_ENTER) - { - btnAddAccount.doClick(); - btnAddAccount.requestFocus(); - } - } - }); - txtAccountLogin.addMouseListener(new MouseListener() - { - @Override - public void mouseClicked(MouseEvent e) - { - - - } - - @Override - public void mousePressed(MouseEvent e) - { - - } - - @Override - public void mouseReleased(MouseEvent e) - { - - } - - @Override - public void mouseEntered(MouseEvent e) - { - } - - @Override - public void mouseExited(MouseEvent e) - { - - } - }); - - add(btnAddAccount, c); - c.gridy++; - - profilesPanel.setLayout(new GridBagLayout()); - add(profilesPanel, c); - c.gridy = 0; - c.insets = new Insets(0, 0, 5, 0); - - //addAccounts(config.profilesData()); - } - - void redrawProfiles() throws InvalidKeySpecException, NoSuchAlgorithmException - { - profilesPanel.removeAll(); - c.gridy = 0; - addAccounts(getProfileData()); - - revalidate(); - repaint(); - } - - private void addAccount(String data) - { - ProfilePanel profile = new ProfilePanel(client, data, profilesConfig, this); - c.gridy++; - profilesPanel.add(profile, c); - - revalidate(); - repaint(); - } - - void addAccounts(String data) - { - //log.info("Data: " + data); - data = data.trim(); - if (!data.contains(":")) - { - return; - } - Arrays.stream(data.split("\\n")).forEach(this::addAccount); - } - - boolean addProfile(String data) throws InvalidKeySpecException, NoSuchAlgorithmException - { - return setProfileData( - getProfileData() + data + "\n"); - } - - void removeProfile(String data) throws InvalidKeySpecException, NoSuchAlgorithmException - { - setProfileData( - getProfileData().replaceAll(data + "\\n", "")); - redrawProfiles(); - } - - void setSalt(byte[] bytes) - { - profilesConfig.salt(base64Encode(bytes)); - } - - byte[] getSalt() - { - if(profilesConfig.salt().length() == 0) - { - return new byte[0]; - } - return base64Decode(profilesConfig.salt()); - } - - SecretKey getAesKey() throws NoSuchAlgorithmException, InvalidKeySpecException - { - if(getSalt().length == 0) - { - byte[] b = new byte[16]; - SecureRandom.getInstanceStrong().nextBytes(b); - setSalt(b); - } - SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); - KeySpec spec = new PBEKeySpec(txtDecryptPassword.getPassword(), getSalt(), iterations, 128); - SecretKey key = factory.generateSecret(spec); - return key; - } - - String getProfileData() throws InvalidKeySpecException, NoSuchAlgorithmException - { - String tmp = profilesConfig.profilesData(); - if(tmp.startsWith("¬")) - { - if(txtDecryptPassword.getPassword().length == 0 || String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD)) - { - showErrorMessage("Unable to load data", "Please enter a password!"); - return tmp; - } - tmp = tmp.substring(1); - return decryptText(base64Decode(tmp), getAesKey()); - } - return tmp; - } - - boolean setProfileData(String data) throws InvalidKeySpecException, NoSuchAlgorithmException - { - if(txtDecryptPassword.getPassword().length == 0 || String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD)) - { - showErrorMessage("Unable to save data", "Please enter a password!"); - return false; - } - byte[] enc = encryptText(data, getAesKey()); - if(enc.length == 0) - return false; - String s = "¬"+base64Encode(enc); - profilesConfig.profilesData(s); - return true; - } - - public byte[] base64Decode(String data) - { - return Base64.getDecoder().decode(data); - } - - public String base64Encode(byte[] data) - { - return Base64.getEncoder().encodeToString(data); - } - - /** - * Encrypts login info - * - * @param text text to encrypt - * @return encrypted string - */ - public static byte[] encryptText(String text, SecretKey aesKey) - { - try - { - Cipher cipher = Cipher.getInstance("AES"); - SecretKeySpec newKey = new SecretKeySpec(aesKey.getEncoded(), "AES"); - cipher.init(Cipher.ENCRYPT_MODE, newKey); - return cipher.doFinal(text.getBytes()); - } - catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException e) - { - e.printStackTrace(); - } - return new byte[0]; - } - - public static String decryptText(byte[] enc, SecretKey aesKey) - { - try - { - Cipher cipher = Cipher.getInstance("AES"); - SecretKeySpec newKey = new SecretKeySpec(aesKey.getEncoded(), "AES"); - cipher.init(Cipher.DECRYPT_MODE, newKey); - return new String(cipher.doFinal(enc)); - } - catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException e) - { - e.printStackTrace(); - } - return ""; - } - - public static void showErrorMessage(String title, String text) - { - SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null, - text, - title, - JOptionPane.ERROR_MESSAGE)); - } - -} +/* + * Copyright (c) 2019, Spedwards + * 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.profiles; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Arrays; +import java.util.Base64; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import javax.inject.Inject; +import javax.swing.*; +import javax.swing.border.EmptyBorder; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.PluginPanel; + +@Slf4j +class ProfilesPanel extends PluginPanel +{ + private static final int iterations = 100000; + private static final String UNLOCK_PASSWORD = "Encryption Password"; + private static final String LOAD_ACCOUNTS = "Load Accounts"; + private static final String ACCOUNT_USERNAME = "Account Username"; + private static final String ACCOUNT_LABEL = "Account Label"; + private static final String PASSWORD_LABEL = "Account Password"; + private static final String HELP = "To add and load accounts, first enter a password into the Encryption Password " + + "field then press Load Accounts. You can now add as many accounts as you would like. The next time you restart" + + " PKLite, enter your encryption password and click load accounts to see the accounts you entered"; + private static final Dimension PREFERRED_SIZE = new Dimension(PluginPanel.PANEL_WIDTH - 20, 30); + private static final Dimension HELP_PREFERRED_SIZE = new Dimension(PluginPanel.PANEL_WIDTH - 20, 130); + + private static final Dimension MINIMUM_SIZE = new Dimension(0, 30); + + private final Client client; + private static ProfilesConfig profilesConfig; + + private final JPasswordField txtDecryptPassword = new JPasswordField(UNLOCK_PASSWORD); + private final JButton btnLoadAccounts = new JButton(LOAD_ACCOUNTS); + private final JTextField txtAccountLabel = new JTextField(ACCOUNT_LABEL); + private final JPasswordField txtAccountLogin = new JPasswordField(ACCOUNT_USERNAME); + private final JPasswordField txtPasswordLogin = new JPasswordField(PASSWORD_LABEL); + private final JPanel profilesPanel = new JPanel(); + private final JPanel helpPanel = new JPanel(new BorderLayout()); + private GridBagConstraints c; + + @Inject + public ProfilesPanel(Client client, ProfilesConfig config) + { + super(); + this.client = client; + profilesConfig = config; + + setBorder(new EmptyBorder(18, 10, 0, 10)); + setBackground(ColorScheme.DARK_GRAY_COLOR); + setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 0; + c.gridy = 0; + c.weightx = 1; + c.weighty = 0; + c.insets = new Insets(0, 0, 4, 0); + + helpPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + JLabel helpLabel = new JLabel("

" + HELP + "

"); + helpLabel.setFont(FontManager.getRunescapeSmallFont()); + helpPanel.setPreferredSize(HELP_PREFERRED_SIZE); + //helpPanel.setSize(MINIMUM_SIZE); + helpPanel.add(helpLabel, BorderLayout.NORTH); + + add(helpPanel); + c.gridy = c.gridy + 3; + c.gridy++; + + + txtDecryptPassword.setEchoChar((char) 0); + txtDecryptPassword.setPreferredSize(PREFERRED_SIZE); + txtDecryptPassword.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + txtDecryptPassword.setBackground(ColorScheme.DARKER_GRAY_COLOR); + txtDecryptPassword.setMinimumSize(MINIMUM_SIZE); + txtDecryptPassword.setToolTipText(UNLOCK_PASSWORD); + txtDecryptPassword.addFocusListener(new FocusListener() + { + @Override + public void focusGained(FocusEvent e) + { + txtDecryptPassword.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + if (String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD)) + { + txtDecryptPassword.setText(""); + txtDecryptPassword.setEchoChar('*'); + } + } + + @Override + public void focusLost(FocusEvent e) + { + txtDecryptPassword.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + if (txtDecryptPassword.getPassword().length == 0) + { + txtDecryptPassword.setText(UNLOCK_PASSWORD); + txtDecryptPassword.setEchoChar((char) 0); + } + } + }); + + add(txtDecryptPassword, c); + c.gridy++; + + btnLoadAccounts.setPreferredSize(PREFERRED_SIZE); + btnLoadAccounts.setBackground(ColorScheme.DARKER_GRAY_COLOR); + btnLoadAccounts.setMinimumSize(MINIMUM_SIZE); + btnLoadAccounts.setToolTipText(LOAD_ACCOUNTS); + btnLoadAccounts.addMouseListener(new MouseListener() + { + @Override + public void mouseClicked(MouseEvent e) + { + + } + + @Override + public void mousePressed(MouseEvent e) + { + + } + + @Override + public void mouseReleased(MouseEvent e) + { + try + { + redrawProfiles(); + } + catch (InvalidKeySpecException | NoSuchAlgorithmException ex) + { + showErrorMessage("Unable to load data", "Incorrect password!"); + } + } + + @Override + public void mouseEntered(MouseEvent e) + { + + } + + @Override + public void mouseExited(MouseEvent e) + { + + } + }); + + add(btnLoadAccounts, c); + c.gridy++; + + txtAccountLabel.setPreferredSize(PREFERRED_SIZE); + txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + txtAccountLabel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + txtAccountLabel.setMinimumSize(MINIMUM_SIZE); + txtAccountLabel.addFocusListener(new FocusListener() + { + @Override + public void focusGained(FocusEvent e) + { + if (txtAccountLabel.getText().equals(ACCOUNT_LABEL)) + { + txtAccountLabel.setText(""); + txtAccountLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + } + } + + @Override + public void focusLost(FocusEvent e) + { + if (txtAccountLabel.getText().isEmpty()) + { + txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + txtAccountLabel.setText(ACCOUNT_LABEL); + } + } + }); + + add(txtAccountLabel, c); + c.gridy++; + + // Do not hide username characters until they focus or if in streamer mode + txtAccountLogin.setEchoChar((char) 0); + txtAccountLogin.setPreferredSize(PREFERRED_SIZE); + txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + txtAccountLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR); + txtAccountLogin.setMinimumSize(MINIMUM_SIZE); + txtAccountLogin.addFocusListener(new FocusListener() + { + @Override + public void focusGained(FocusEvent e) + { + if (ACCOUNT_USERNAME.equals(String.valueOf(txtAccountLogin.getPassword()))) + { + txtAccountLogin.setText(""); + if (config.isStreamerMode()) + { + txtAccountLogin.setEchoChar('*'); + } + txtAccountLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + } + } + + @Override + public void focusLost(FocusEvent e) + { + if (txtAccountLogin.getPassword().length == 0) + { + txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + txtAccountLogin.setText(ACCOUNT_USERNAME); + txtAccountLogin.setEchoChar((char) 0); + } + } + }); + + add(txtAccountLogin, c); + c.gridy++; + + txtPasswordLogin.setEchoChar((char) 0); + txtPasswordLogin.setPreferredSize(PREFERRED_SIZE); + txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + txtPasswordLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR); + txtPasswordLogin.setToolTipText(PASSWORD_LABEL); + txtPasswordLogin.setMinimumSize(MINIMUM_SIZE); + txtPasswordLogin.addFocusListener(new FocusListener() + { + @Override + public void focusGained(FocusEvent e) + { + if (PASSWORD_LABEL.equals(String.valueOf(txtPasswordLogin.getPassword()))) + { + txtPasswordLogin.setText(""); + txtPasswordLogin.setEchoChar('*'); + txtPasswordLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + } + } + + @Override + public void focusLost(FocusEvent e) + { + if (txtPasswordLogin.getPassword().length == 0) + { + txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + txtPasswordLogin.setText(PASSWORD_LABEL); + txtPasswordLogin.setEchoChar((char) 0); + } + } + }); + + + if (config.rememberPassword()) + { + add(txtPasswordLogin, c); + c.gridy++; + } + c.insets = new Insets(0, 0, 15, 0); + + JButton btnAddAccount = new JButton("Add Account"); + btnAddAccount.setPreferredSize(PREFERRED_SIZE); + btnAddAccount.setBackground(ColorScheme.DARKER_GRAY_COLOR); + btnAddAccount.setMinimumSize(MINIMUM_SIZE); + btnAddAccount.addActionListener(e -> + { + String labelText = String.valueOf(txtAccountLabel.getText()); + String loginText = String.valueOf(txtAccountLogin.getPassword()); + String passwordText = String.valueOf(txtPasswordLogin.getPassword()); + + if (labelText.equals(ACCOUNT_LABEL) || loginText.equals(ACCOUNT_USERNAME)) + { + return; + } + String data; + if (config.rememberPassword() && txtPasswordLogin.getPassword() != null) + { + data = labelText + ":" + loginText + ":" + passwordText; + } + else + { + data = labelText + ":" + loginText; + } + + try + { + if(!addProfile(data)) + { + return; + } + } + catch (InvalidKeySpecException | NoSuchAlgorithmException ex) + { + ex.printStackTrace(); + } + + this.addAccount(data); + + txtAccountLabel.setText(ACCOUNT_LABEL); + txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + + txtAccountLogin.setText(ACCOUNT_USERNAME); + txtAccountLogin.setEchoChar((char) 0); + txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + + txtPasswordLogin.setText(PASSWORD_LABEL); + txtPasswordLogin.setEchoChar((char) 0); + txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR); + }); + + txtAccountLogin.addKeyListener(new KeyAdapter() + { + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + { + btnAddAccount.doClick(); + btnAddAccount.requestFocus(); + } + } + }); + txtAccountLogin.addMouseListener(new MouseListener() + { + @Override + public void mouseClicked(MouseEvent e) + { + + + } + + @Override + public void mousePressed(MouseEvent e) + { + + } + + @Override + public void mouseReleased(MouseEvent e) + { + + } + + @Override + public void mouseEntered(MouseEvent e) + { + } + + @Override + public void mouseExited(MouseEvent e) + { + + } + }); + + add(btnAddAccount, c); + c.gridy++; + + profilesPanel.setLayout(new GridBagLayout()); + add(profilesPanel, c); + c.gridy = 0; + c.insets = new Insets(0, 0, 5, 0); + + //addAccounts(config.profilesData()); + } + + void redrawProfiles() throws InvalidKeySpecException, NoSuchAlgorithmException + { + profilesPanel.removeAll(); + c.gridy = 0; + addAccounts(getProfileData()); + + revalidate(); + repaint(); + } + + private void addAccount(String data) + { + ProfilePanel profile = new ProfilePanel(client, data, profilesConfig, this); + c.gridy++; + profilesPanel.add(profile, c); + + revalidate(); + repaint(); + } + + void addAccounts(String data) + { + //log.info("Data: " + data); + data = data.trim(); + if (!data.contains(":")) + { + return; + } + Arrays.stream(data.split("\\n")).forEach(this::addAccount); + } + + boolean addProfile(String data) throws InvalidKeySpecException, NoSuchAlgorithmException + { + return setProfileData( + getProfileData() + data + "\n"); + } + + void removeProfile(String data) throws InvalidKeySpecException, NoSuchAlgorithmException + { + setProfileData( + getProfileData().replaceAll(data + "\\n", "")); + revalidate(); + repaint(); + + } + + void setSalt(byte[] bytes) + { + profilesConfig.salt(base64Encode(bytes)); + } + + byte[] getSalt() + { + if(profilesConfig.salt().length() == 0) + { + return new byte[0]; + } + return base64Decode(profilesConfig.salt()); + } + + SecretKey getAesKey() throws NoSuchAlgorithmException, InvalidKeySpecException + { + if(getSalt().length == 0) + { + byte[] b = new byte[16]; + SecureRandom.getInstanceStrong().nextBytes(b); + setSalt(b); + } + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + KeySpec spec = new PBEKeySpec(txtDecryptPassword.getPassword(), getSalt(), iterations, 128); + SecretKey key = factory.generateSecret(spec); + return key; + } + + String getProfileData() throws InvalidKeySpecException, NoSuchAlgorithmException + { + String tmp = profilesConfig.profilesData(); + if(tmp.startsWith("¬")) + { + if(txtDecryptPassword.getPassword().length == 0 || String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD)) + { + showErrorMessage("Unable to load data", "Please enter a password!"); + return tmp; + } + tmp = tmp.substring(1); + return decryptText(base64Decode(tmp), getAesKey()); + } + return tmp; + } + + boolean setProfileData(String data) throws InvalidKeySpecException, NoSuchAlgorithmException + { + if(txtDecryptPassword.getPassword().length == 0 || String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD)) + { + showErrorMessage("Unable to save data", "Please enter a password!"); + return false; + } + byte[] enc = encryptText(data, getAesKey()); + if(enc.length == 0) + return false; + String s = "¬"+base64Encode(enc); + profilesConfig.profilesData(s); + return true; + } + + public byte[] base64Decode(String data) + { + return Base64.getDecoder().decode(data); + } + + public String base64Encode(byte[] data) + { + return Base64.getEncoder().encodeToString(data); + } + + /** + * Encrypts login info + * + * @param text text to encrypt + * @return encrypted string + */ + public static byte[] encryptText(String text, SecretKey aesKey) + { + try + { + Cipher cipher = Cipher.getInstance("AES"); + SecretKeySpec newKey = new SecretKeySpec(aesKey.getEncoded(), "AES"); + cipher.init(Cipher.ENCRYPT_MODE, newKey); + return cipher.doFinal(text.getBytes()); + } + catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException e) + { + e.printStackTrace(); + } + return new byte[0]; + } + + public static String decryptText(byte[] enc, SecretKey aesKey) + { + try + { + Cipher cipher = Cipher.getInstance("AES"); + SecretKeySpec newKey = new SecretKeySpec(aesKey.getEncoded(), "AES"); + cipher.init(Cipher.DECRYPT_MODE, newKey); + return new String(cipher.doFinal(enc)); + } + catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException e) + { + e.printStackTrace(); + } + return ""; + } + + public static void showErrorMessage(String title, String text) + { + SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null, + text, + title, + JOptionPane.ERROR_MESSAGE)); + } + +} \ No newline at end of file From 7671e61cf3bc58ea3ae421569b3146969df6b076 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Thu, 25 Apr 2019 21:50:59 +0100 Subject: [PATCH 4/6] Removes the hotkey & attack option hiding Removes the hotkey and makes attack option hiding much more certain --- .../plugins/pvptools/PvpToolsConfig.java | 282 ++-- .../plugins/pvptools/PvpToolsPlugin.java | 1361 ++++++++--------- 2 files changed, 803 insertions(+), 840 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsConfig.java index a6a1392763..e8e53d6b6a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsConfig.java @@ -1,147 +1,135 @@ -/* - * Copyright (c) 2019. PKLite - All Rights Reserved - * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. - * Proprietary and confidential. Refer to PKLite License file for more information on - * full terms of this copyright and to determine what constitutes authorized use. - * Written by PKLite(ST0NEWALL, others) , 2019 - * - */ - -package net.runelite.client.plugins.pvptools; - -import java.awt.Color; -import java.security.Key; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.Keybind; - -@ConfigGroup("pvptools") -public interface PvpToolsConfig extends Config -{ - @ConfigItem( - keyName = "countPlayers", - name = "Count Players", - description = "When in PvP zones, counts the attackable players in and not in player's CC", - position = 3 - ) - default boolean countPlayers() - { - return true; - } - - @ConfigItem( - keyName = "countOverHeads", - name = "Count Enemy Overheads", - description = "Counts the number of each protection prayer attackable targets not in your CC are currently" + - " using", - position = 4 - ) - default boolean countOverHeads() - { - return true; - } - - @ConfigItem( - keyName = "fallInHelper", - name = "Fall In Helper", - description = "Hides all non-friendly player entities other than the one that is attacking you.", - position = 5 - ) - default boolean fallInHelper() - { - return true; - } - - @ConfigItem( - keyName = "hotkey", - name = "Fall In Hotkey", - description = "Turns the fall in helper on or off when you press this hotkey", - position = 6 - ) - default Keybind hotkey() - { - return Keybind.NOT_SET; - } - - @ConfigItem( - keyName = "attackOptionsClan", - name = "Move CC Attack Option", - description = "Moves the attack option for people in the same CC", - position = 7, - group = "Right-Click Attack Options" - ) - default boolean attackOptionsClan() - { - return false; - } - - @ConfigItem( - keyName = "attackOptionsFriend", - name = "Move Friend Attack Options", - description = "Moves the attack option for people on your friends list", - position = 8, - group = "Right-Click Attack Options" - ) - default boolean attackOptionsFriend() - { - return false; - } - - @ConfigItem( - keyName = "attackOptionsHotkey", - name = "Attack Option Hotkey", - description = "Enables a hotkey for attack options to disable or enable hiding quickly", - position = 10, - group = "Right-Click Attack Options" - ) - default Keybind attackOptionsHotkey() - { - return Keybind.CTRL; - } - - @ConfigItem( - keyName = "levelRangeAttackOptions", - name = "Moves Other Attack Options", - description = "Moves the attack option for people that are outside your level range", - position = 9, - group = "Right-Click Attack Options" - ) - default boolean levelRangeAttackOptions() - { - return false; - } - - @ConfigItem( - keyName = "riskCalculator", - name = "Risk Calculator", - description = "Enables a panel in the PvP Tools Panel that shows the players current risk", - position = 13 - ) - default boolean riskCalculatorEnabled() - { - return true; - } - - @ConfigItem( - keyName = "missingPlayers", - name = "Missing CC Players", - description = "Adds a button to the PvP Tools panel that opens a window showing which CC members are not at" + - " the current players location", - position = 14 - ) - default boolean missingPlayersEnabled() { return true; } - - @ConfigItem( - keyName = "currentPlayers", - name = "Current CC Players", - description = "Adds a button to the PvP Tools panel that opens a window showing which CC members currently at" + - " the players location", - position = 15 - ) - default boolean currentPlayersEnabled() - { - return true; - } - -} +/* + * Copyright (c) 2019. PKLite - All Rights Reserved + * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. + * Proprietary and confidential. Refer to PKLite License file for more information on + * full terms of this copyright and to determine what constitutes authorized use. + * Written by PKLite(ST0NEWALL, others) , 2019 + * + */ + +package net.runelite.client.plugins.pvptools; + +import java.awt.Color; +import java.security.Key; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Keybind; + +@ConfigGroup("pvptools") +public interface PvpToolsConfig extends Config +{ + @ConfigItem( + keyName = "countPlayers", + name = "Count Players", + description = "When in PvP zones, counts the attackable players in and not in player's CC", + position = 3 + ) + default boolean countPlayers() + { + return true; + } + + @ConfigItem( + keyName = "countOverHeads", + name = "Count Enemy Overheads", + description = "Counts the number of each protection prayer attackable targets not in your CC are currently" + + " using", + position = 4 + ) + default boolean countOverHeads() + { + return true; + } + + @ConfigItem( + keyName = "fallInHelper", + name = "Fall In Helper", + description = "Hides all non-friendly player entities other than the one that is attacking you.", + position = 5 + ) + default boolean fallInHelper() + { + return true; + } + + @ConfigItem( + keyName = "hotkey", + name = "Fall In Hotkey", + description = "Turns the fall in helper on or off when you press this hotkey", + position = 6 + ) + default Keybind hotkey() + { + return Keybind.NOT_SET; + } + + @ConfigItem( + keyName = "attackOptionsClan", + name = "Move CC Attack Option", + description = "Moves the attack option for people in the same CC", + position = 7, + group = "Right-Click Attack Options" + ) + default boolean attackOptionsClan() + { + return false; + } + + @ConfigItem( + keyName = "attackOptionsFriend", + name = "Move Friend Attack Options", + description = "Moves the attack option for people on your friends list", + position = 8, + group = "Right-Click Attack Options" + ) + default boolean attackOptionsFriend() + { + return false; + } + + @ConfigItem( + keyName = "levelRangeAttackOptions", + name = "Moves Other Attack Options", + description = "Moves the attack option for people that are outside your level range", + position = 9, + group = "Right-Click Attack Options" + ) + default boolean levelRangeAttackOptions() + { + return false; + } + + @ConfigItem( + keyName = "riskCalculator", + name = "Risk Calculator", + description = "Enables a panel in the PvP Tools Panel that shows the players current risk", + position = 13 + ) + default boolean riskCalculatorEnabled() + { + return true; + } + + @ConfigItem( + keyName = "missingPlayers", + name = "Missing CC Players", + description = "Adds a button to the PvP Tools panel that opens a window showing which CC members are not at" + + " the current players location", + position = 14 + ) + default boolean missingPlayersEnabled() { return true; } + + @ConfigItem( + keyName = "currentPlayers", + name = "Current CC Players", + description = "Adds a button to the PvP Tools panel that opens a window showing which CC members currently at" + + " the players location", + position = 15 + ) + default boolean currentPlayersEnabled() + { + return true; + } + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPlugin.java index 42f8e4395f..838ba3c25a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPlugin.java @@ -1,693 +1,668 @@ -/* - * Copyright (c) 2019. PKLite - All Rights Reserved - * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. - * Proprietary and confidential. Refer to PKLite License file for more information on - * full terms of this copyright and to determine what constitutes authorized use. - * Written by PKLite(ST0NEWALL, others) , 2019 - * - */ - -package net.runelite.client.plugins.pvptools; - -import com.google.inject.Provides; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.image.BufferedImage; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.NavigableMap; -import java.util.Objects; -import java.util.TreeMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ScheduledExecutorService; -import java.util.stream.Collectors; -import javax.inject.Inject; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.ClanMember; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemComposition; -import net.runelite.api.MenuEntry; -import net.runelite.api.Player; -import net.runelite.api.SkullIcon; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.FocusChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.ItemContainerChanged; -import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.events.PlayerDespawned; -import net.runelite.api.events.PlayerSpawned; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.AsyncBufferedImage; -import net.runelite.client.game.ClanManager; -import net.runelite.client.game.ItemManager; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginManager; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.clanchat.ClanChatPlugin; -import static net.runelite.client.plugins.pvptools.PvpToolsPanel.htmlLabel; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.HotkeyListener; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.PvPUtil; -import static net.runelite.client.util.StackFormatter.quantityToRSDecimalStack; -import net.runelite.client.util.Text; -import org.apache.commons.lang3.ArrayUtils; - -@PluginDescriptor( - name = "PvP Tools", - description = "Enable the PvP Tools panel", - tags = {"panel", "pvp", "pk", "pklite"}, - type = PluginType.PVP -) -public class PvpToolsPlugin extends Plugin -{ - @Inject - PvpToolsOverlay pvpToolsOverlay; - boolean fallinHelperEnabled = false; - private PvpToolsPanel panel; - private MissingPlayersJFrame missingPlayersJFrame; - private CurrentPlayersJFrame currentPlayersJFrame; - private NavigationButton navButton; - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private boolean attackHotKeyPressed; - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) - private boolean hideAll; - @Inject - private ScheduledExecutorService executorService; - @Inject - private OverlayManager overlayManager; - @Inject - private Client client; - @Inject - private ItemManager itemManager; - private PvpToolsPlugin uhPvpToolsPlugin = this; - - /** - * ActionListener for the missing cc members and refresh buttons - */ - final ActionListener playersButtonActionListener = new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - if (missingPlayersJFrame != null) - { - missingPlayersJFrame.dispose(); - missingPlayersJFrame = null; - missingPlayersJFrame = new MissingPlayersJFrame(client, uhPvpToolsPlugin, getMissingMembers()); - } - else - { - missingPlayersJFrame = new MissingPlayersJFrame(client, uhPvpToolsPlugin, getMissingMembers()); - } - } - }; - - final ActionListener currentPlayersActionListener = new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - if (currentPlayersJFrame != null) - { - currentPlayersJFrame.dispose(); - currentPlayersJFrame = null; - currentPlayersJFrame = new CurrentPlayersJFrame(client, uhPvpToolsPlugin, getCurrentMembers()); - } - else - { - currentPlayersJFrame = new CurrentPlayersJFrame(client, uhPvpToolsPlugin, getCurrentMembers()); - } - } - }; - - - @Inject - private ClientToolbar clientToolbar; - - @Inject - private KeyManager keyManager; - - @Inject - private PvpToolsConfig config; - - @Inject - private PluginManager pluginManager; - - @Inject - private ClanManager clanManager; - - - private ClanChatPlugin clanChatPlugin; - /** - * The HotKeyListener for the hot key assigned in the config that triggers the Fall In Helper feature - */ - private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.hotkey()) - { - public void hotkeyPressed() - { - toggleFallinHelper(); - } - }; - - - private final HotkeyListener attackOptionsHotKeyListener = new HotkeyListener(() -> config.attackOptionsHotkey()) - { - long lastPress = 0; - - @Override - public void keyPressed(KeyEvent e) - { - attackHotKeyPressed = true; - } - - @Override - public void keyReleased(KeyEvent e) - { - attackHotKeyPressed = (System.currentTimeMillis() - lastPress) < 800; - lastPress = System.currentTimeMillis(); - } - }; - - private int[] overheadCount = new int[]{0, 0, 0}; - - private Comparator itemPriceComparator = new Comparator() - { - @Override - public int compare(Item o1, Item o2) - { - return (itemManager.getItemPrice(itemManager.getItemComposition(o1.getId()).getPrice()) - - itemManager.getItemPrice(itemManager.getItemComposition(o2.getId()).getPrice())); - } - }; - private String mtarget; - - public List getMissingMembers() - { - CopyOnWriteArrayList ccMembers = ClanChatPlugin.getClanMembers(); - ArrayList missingMembers = new ArrayList(); - for (ClanMember clanMember:client.getClanMembers()) - { - if (!Objects.isNull(clanMember)) - { - List arrayList = ccMembers.stream().map(player -> Text.removeTags(Text.standardize(player.getName()))).collect(Collectors.toList()); - if (!arrayList.contains(Text.removeTags(Text.standardize(clanMember.getUsername())))) - { - if (!missingMembers.contains(clanMember.getUsername())) - { - missingMembers.add("[W" + clanMember.getWorld() + "] - " + clanMember.getUsername()); - } - } - } - } - - return missingMembers; - - //Arrays.stream(Arrays.stream(client.getClanMembers()).filter(Objects::nonNull).map(ClanMember::getUsername) - //.toArray()).collect(Collectors.toList()); - } - - public List getCurrentMembers() - { - CopyOnWriteArrayList ccMembers = ClanChatPlugin.getClanMembers(); - ArrayList currentMembers = new ArrayList(); - for (ClanMember clanMember:client.getClanMembers()) - { - if (!Objects.isNull(clanMember)) - { - List arrayList = ccMembers.stream().map(player -> Text.removeTags(Text.standardize(player.getName()))).collect(Collectors.toList()); - if (arrayList.contains(Text.removeTags(Text.standardize(clanMember.getUsername())))) - { - if (!currentMembers.contains(clanMember.getUsername())) - { - currentMembers.add(clanMember.getUsername()); - } - } - } - } - - return currentMembers; - - //Arrays.stream(Arrays.stream(client.getClanMembers()).filter(Objects::nonNull).map(ClanMember::getUsername) - //.toArray()).collect(Collectors.toList()); - } - - - - @Provides - PvpToolsConfig config(ConfigManager configManager) - { - return configManager.getConfig(PvpToolsConfig.class); - } - - @Override - protected void startUp() throws Exception - { - - overlayManager.add(pvpToolsOverlay); - - keyManager.registerKeyListener(hotkeyListener); - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "skull.png"); - - panel = new PvpToolsPanel(); - panel.init(); - - navButton = NavigationButton.builder() - .tooltip("PvP Tools") - .icon(icon) - .priority(5) - .panel(panel) - .build(); - - panel.missingPlayers.addActionListener(playersButtonActionListener); - panel.currentPlayers.addActionListener(currentPlayersActionListener); - clientToolbar.addNavigation(navButton); - - - keyManager.registerKeyListener(attackOptionsHotKeyListener); - - if (config.missingPlayersEnabled()) - { - panel.missingPlayers.setVisible(true); - } - - if (config.currentPlayersEnabled()) - { - panel.currentPlayers.setVisible(true); - } - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(pvpToolsOverlay); - keyManager.unregisterKeyListener(hotkeyListener); - keyManager.unregisterKeyListener(attackOptionsHotKeyListener); - clientToolbar.removeNavigation(navButton); - } - - @Subscribe - public void onConfigChanged(ConfigChanged configChanged) - { - if (configChanged.getGroup().equals("pvptools")) - { - switch (configChanged.getKey()) - { - case "countPlayers": - if (config.countPlayers()) - { - updatePlayers(); - } - if (!config.countPlayers()) - { - panel.disablePlayerCount(); - } - break; - case "countOverHeads": - if (config.countOverHeads()) - { - countOverHeads(); - } - if (!config.countOverHeads()) - { - panel.disablePrayerCount(); - } - break; - case "riskCalculator": - if (config.riskCalculatorEnabled()) - { - getCarriedWealth(); - } - if (!config.riskCalculatorEnabled()) - { - panel.disableRiskCalculator(); - } - break; - case "missingPlayers": - if (config.missingPlayersEnabled()) - { - panel.missingPlayers.setVisible(true); - } - break; - case "currentPlayers": - if (config.currentPlayersEnabled()) - { - panel.currentPlayers.setVisible(true); - } - break; - default: - break; - } - } - } - - @Subscribe - public void onItemContainerChanged(ItemContainerChanged event) - { - if (event.getItemContainer().equals(client.getItemContainer(InventoryID.INVENTORY)) && - config.riskCalculatorEnabled()) - { - getCarriedWealth(); - } - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState().equals(GameState.LOGGED_IN) && config.riskCalculatorEnabled()) - { - getCarriedWealth(); - } - if (event.getGameState().equals(GameState.LOGGED_IN)) - { - if (config.countPlayers()) - { - updatePlayers(); - } - } - } - - @Subscribe - public void onPlayerSpawned(PlayerSpawned event) - { - if (config.countPlayers() && PvPUtil.isAttackable(client, event.getPlayer())) - { - updatePlayers(); - } - if (config.countOverHeads()) - { - countOverHeads(); - } - } - - @Subscribe - public void onPlayerDespawned(PlayerDespawned event) - { - if (config.countPlayers() && PvPUtil.isAttackable(client, event.getPlayer())) - { - updatePlayers(); - } - if (config.countOverHeads()) - { - countOverHeads(); - } - } - - @Subscribe - public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) - { - if (!attackHotKeyPressed) - { - if (config.attackOptionsFriend() || config.attackOptionsClan() || config.levelRangeAttackOptions()) - { - if (client.getGameState() != GameState.LOGGED_IN) - { - return; - } - Player[] players = client.getCachedPlayers(); - Player player = null; - int identifier = menuEntryAdded.getIdentifier(); - if (identifier >= 0 && identifier < players.length) - { - player = players[identifier]; - } - if (player == null) - { - return; - } - final String option = Text.removeTags(menuEntryAdded.getOption()).toLowerCase(); - final String mtarget = Text.removeTags(menuEntryAdded.getTarget()).toLowerCase(); - if (attackHotKeyPressed && config.attackOptionsClan() || config.attackOptionsFriend() || - config.levelRangeAttackOptions()) - { - if (config.attackOptionsFriend() && player.isFriend()) - { - moveEntry(mtarget); - } - if (config.attackOptionsClan() && player.isClanMember()) - { - moveEntry(mtarget); - } - if (config.levelRangeAttackOptions() && !PvPUtil.isAttackable(client, player)) - { - moveEntry(mtarget); - } - } - } - } - } - - - private void moveEntry(String mtarget) - { - this.mtarget = mtarget; - MenuEntry[] menuEntries = client.getMenuEntries(); - MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; - - // strip out existing '); - if (idx != -1) - { - target = target.substring(idx + 1); - } - /*System.out.println("Contents : " + lastEntry.getTarget()); - System.out.println("Contents : " + lastEntry.getIdentifier()); - System.out.println("Contents : " + lastEntry.getOption()); - System.out.println("length : " + menuEntries.length);*/ - if (menuEntries[menuEntries.length - 1] != null) - { - //System.out.println(menuEntries.length + ": " + menuEntries[menuEntries.length-1]); - } - if (lastEntry.getOption().contains("attack".toLowerCase())) - { - ArrayUtils.shift(menuEntries, 1); - //ArrayUtils.add(menuEntries, menuEntries.length - 2); - //menuEntries = ArrayUtils.remove(menuEntries, menuEntries.length - 1); - //menuEntrySwapperPlugin.swap("attack", option, mtarget, false); - } - if (lastEntry.getOption().equals("Attack")) - { - ArrayUtils.shift(menuEntries, 1); - - //menuEntries = ArrayUtils.sremove(menuEntries, menuEntries.length - 1); - //menuEntrySwapperPlugin.swap("attack", option, mtarget, false); - } - client.setMenuEntries(menuEntries); - - } - - @Subscribe - public void onFocusChanged(FocusChanged focusChanged) - { - if (!focusChanged.isFocused()) - { - setAttackHotKeyPressed(false); - } - } - - /** - * Enables or disables the fall in helper feature - */ - private void toggleFallinHelper() - { - if (!fallinHelperEnabled) - { - client.setIsHidingEntities(true); - client.setPlayersHidden(true); - fallinHelperEnabled = true; - } - else - { - client.setIsHidingEntities(false); - client.setPlayersHidden(false); - fallinHelperEnabled = false; - } - - } - - /** - * Updates the PvP Tools panel with the numbers for enemy protection prayers - */ - private void updatePrayerNumbers() - { - panel.numMageJLabel.setText(htmlLabel("Enemies Praying Mage: ", String.valueOf(overheadCount[0]))); - panel.numRangeJLabel.setText(htmlLabel("Enemies Praying Range: ", String.valueOf(overheadCount[1]))); - panel.numMeleeJLabel.setText(htmlLabel("Enemies Praying Melee: ", String.valueOf(overheadCount[2]))); - panel.numMageJLabel.repaint(); - panel.numRangeJLabel.repaint(); - panel.numMeleeJLabel.repaint(); - } - - /** - * - */ - private void updatePlayers() - { - if (config.countPlayers()) - { - int cc = 0; - int other = 0; - for (Player p : client.getPlayers()) - { - if (Objects.nonNull(p)) - { - if (PvPUtil.isAttackable(client, p)) - { - if (p.isClanMember()) - { - cc++; - } - else - { - other++; - } - } - } - } - - panel.numOther.setText(htmlLabel("Other Player Count: ", String.valueOf(other))); - panel.numCC.setText(htmlLabel("Friendly Player Count: ", String.valueOf(cc))); - panel.numCC.repaint(); - panel.numOther.repaint(); - } - } - - private void countOverHeads() - { - overheadCount = new int[]{0, 0, 0}; - for (Player p : client.getPlayers()) - { - if (Objects.nonNull(p)) - { - if (PvPUtil.isAttackable(client, p)) - { - if (!p.isClanMember() && !(p.getOverheadIcon() == null)) - { - switch (p.getOverheadIcon()) - { - case MAGIC: - overheadCount[0]++; - break; - case RANGED: - overheadCount[1]++; - break; - case MELEE: - overheadCount[2]++; - break; - } - } - } - } - } - updatePrayerNumbers(); - } - - /** - * Calculates the player's risk based on Item Price of all items in their inventory and equipment - */ - private void getCarriedWealth() - { - if (!config.riskCalculatorEnabled()) - { - return; - } - if (client.getItemContainer(InventoryID.EQUIPMENT) == null) - { - return; - } - if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null) - { - return; - } - Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(), - Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems()); - TreeMap priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue)); - int wealth = 0; - for (Item i : items) - { - int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity()); - - final ItemComposition itemComposition = itemManager.getItemComposition(i.getId()); - if (!itemComposition.isTradeable() && value == 0) - { - value = itemComposition.getPrice() * i.getQuantity(); - priceMap.put(value, i); - } - else - { - value = itemManager.getItemPrice(i.getId()) * i.getQuantity(); - if (i.getId() > 0 && value > 0) - { - priceMap.put(value, i); - } - } - wealth += value; - } - panel.totalRiskLabel.setText(htmlLabel("Total risk: ", quantityToRSDecimalStack(wealth))); - panel.totalRiskLabel.repaint(); - - int itemLimit = 0; - if (client.getLocalPlayer().getSkullIcon() != null) - { - if (client.getLocalPlayer().getSkullIcon() == SkullIcon.SKULL) - { - itemLimit = 1; - } - } - if (client.getLocalPlayer().getSkullIcon() == null) - { - itemLimit = 4; - } - - AsyncBufferedImage itemImage = null; - - NavigableMap descendingMap = priceMap.descendingMap(); - - for (int i = 0; i < itemLimit; i++) - { - if (i == 0) - { - if (!descendingMap.isEmpty()) - { - itemImage = itemManager.getImage(descendingMap.pollFirstEntry().getValue().getId()); - } - } - else - { - if (!descendingMap.isEmpty()) - { - itemManager.getItemComposition(priceMap.descendingMap().pollFirstEntry().getValue().getId()) - .getName(); - } - } - } - panel.riskProtectingItem.setText(htmlLabel("Risk Protecting Item: ", - quantityToRSDecimalStack(descendingMap.keySet().stream().mapToInt(Integer::intValue).sum()))); - panel.riskProtectingItem.repaint(); - - panel.biggestItemLabel.setText("Most Valuable Item: "); - if (itemImage != null) - { - itemImage.addTo(panel.biggestItemLabel); - } - panel.biggestItemLabel.repaint(); - } - -} +/* + * Copyright (c) 2019. PKLite - All Rights Reserved + * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. + * Proprietary and confidential. Refer to PKLite License file for more information on + * full terms of this copyright and to determine what constitutes authorized use. + * Written by PKLite(ST0NEWALL, others) , 2019 + * + */ + +package net.runelite.client.plugins.pvptools; + +import com.google.inject.Provides; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.NavigableMap; +import java.util.Objects; +import java.util.TreeMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledExecutorService; +import java.util.stream.Collectors; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.ClanMember; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemComposition; +import net.runelite.api.MenuEntry; +import net.runelite.api.Player; +import net.runelite.api.SkullIcon; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.ItemContainerChanged; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.PlayerDespawned; +import net.runelite.api.events.PlayerSpawned; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.AsyncBufferedImage; +import net.runelite.client.game.ClanManager; +import net.runelite.client.game.ItemManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginManager; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.plugins.clanchat.ClanChatPlugin; +import static net.runelite.client.plugins.pvptools.PvpToolsPanel.htmlLabel; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.HotkeyListener; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.PvPUtil; +import static net.runelite.client.util.StackFormatter.quantityToRSDecimalStack; +import net.runelite.client.util.Text; +import org.apache.commons.lang3.ArrayUtils; + +@PluginDescriptor( + name = "PvP Tools", + description = "Enable the PvP Tools panel", + tags = {"panel", "pvp", "pk", "pklite"}, + type = PluginType.PVP +) +public class PvpToolsPlugin extends Plugin +{ + @Inject + PvpToolsOverlay pvpToolsOverlay; + boolean fallinHelperEnabled = false; + private PvpToolsPanel panel; + private MissingPlayersJFrame missingPlayersJFrame; + private CurrentPlayersJFrame currentPlayersJFrame; + private NavigationButton navButton; + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean attackHotKeyPressed; + @Getter(AccessLevel.PACKAGE) + @Setter(AccessLevel.PACKAGE) + private boolean hideAll; + @Inject + private ScheduledExecutorService executorService; + @Inject + private OverlayManager overlayManager; + @Inject + private Client client; + @Inject + private ItemManager itemManager; + private PvpToolsPlugin uhPvpToolsPlugin = this; + + /** + * ActionListener for the missing cc members and refresh buttons + */ + final ActionListener playersButtonActionListener = new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + if (missingPlayersJFrame != null) + { + missingPlayersJFrame.dispose(); + missingPlayersJFrame = null; + missingPlayersJFrame = new MissingPlayersJFrame(client, uhPvpToolsPlugin, getMissingMembers()); + } + else + { + missingPlayersJFrame = new MissingPlayersJFrame(client, uhPvpToolsPlugin, getMissingMembers()); + } + } + }; + + final ActionListener currentPlayersActionListener = new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + if (currentPlayersJFrame != null) + { + currentPlayersJFrame.dispose(); + currentPlayersJFrame = null; + currentPlayersJFrame = new CurrentPlayersJFrame(client, uhPvpToolsPlugin, getCurrentMembers()); + } + else + { + currentPlayersJFrame = new CurrentPlayersJFrame(client, uhPvpToolsPlugin, getCurrentMembers()); + } + } + }; + + + @Inject + private ClientToolbar clientToolbar; + + @Inject + private KeyManager keyManager; + + @Inject + private PvpToolsConfig config; + + @Inject + private PluginManager pluginManager; + + @Inject + private ClanManager clanManager; + + + private ClanChatPlugin clanChatPlugin; + /** + * The HotKeyListener for the hot key assigned in the config that triggers the Fall In Helper feature + */ + private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.hotkey()) + { + public void hotkeyPressed() + { + toggleFallinHelper(); + } + }; + + private int[] overheadCount = new int[]{0, 0, 0}; + + private Comparator itemPriceComparator = new Comparator() + { + @Override + public int compare(Item o1, Item o2) + { + return (itemManager.getItemPrice(itemManager.getItemComposition(o1.getId()).getPrice()) + - itemManager.getItemPrice(itemManager.getItemComposition(o2.getId()).getPrice())); + } + }; + + private String mtarget; + + public List getMissingMembers() + { + CopyOnWriteArrayList ccMembers = ClanChatPlugin.getClanMembers(); + ArrayList missingMembers = new ArrayList(); + for (ClanMember clanMember:client.getClanMembers()) + { + if (!Objects.isNull(clanMember)) + { + List arrayList = ccMembers.stream().map(player -> Text.removeTags(Text.standardize(player.getName()))).collect(Collectors.toList()); + if (!arrayList.contains(Text.removeTags(Text.standardize(clanMember.getUsername())))) + { + if (!missingMembers.contains(clanMember.getUsername())) + { + missingMembers.add("[W" + clanMember.getWorld() + "] - " + clanMember.getUsername()); + } + } + } + } + + return missingMembers; + + //Arrays.stream(Arrays.stream(client.getClanMembers()).filter(Objects::nonNull).map(ClanMember::getUsername) + //.toArray()).collect(Collectors.toList()); + } + + public List getCurrentMembers() + { + CopyOnWriteArrayList ccMembers = ClanChatPlugin.getClanMembers(); + ArrayList currentMembers = new ArrayList(); + for (ClanMember clanMember:client.getClanMembers()) + { + if (!Objects.isNull(clanMember)) + { + List arrayList = ccMembers.stream().map(player -> Text.removeTags(Text.standardize(player.getName()))).collect(Collectors.toList()); + if (arrayList.contains(Text.removeTags(Text.standardize(clanMember.getUsername())))) + { + if (!currentMembers.contains(clanMember.getUsername())) + { + currentMembers.add(clanMember.getUsername()); + } + } + } + } + + return currentMembers; + + //Arrays.stream(Arrays.stream(client.getClanMembers()).filter(Objects::nonNull).map(ClanMember::getUsername) + //.toArray()).collect(Collectors.toList()); + } + + + + @Provides + PvpToolsConfig config(ConfigManager configManager) + { + return configManager.getConfig(PvpToolsConfig.class); + } + + @Override + protected void startUp() throws Exception + { + + overlayManager.add(pvpToolsOverlay); + + keyManager.registerKeyListener(hotkeyListener); + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "skull.png"); + + panel = new PvpToolsPanel(); + panel.init(); + + navButton = NavigationButton.builder() + .tooltip("PvP Tools") + .icon(icon) + .priority(5) + .panel(panel) + .build(); + + panel.missingPlayers.addActionListener(playersButtonActionListener); + panel.currentPlayers.addActionListener(currentPlayersActionListener); + clientToolbar.addNavigation(navButton); + + + if (config.missingPlayersEnabled()) + { + panel.missingPlayers.setVisible(true); + } + + if (config.currentPlayersEnabled()) + { + panel.currentPlayers.setVisible(true); + } + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(pvpToolsOverlay); + keyManager.unregisterKeyListener(hotkeyListener); + clientToolbar.removeNavigation(navButton); + } + + @Subscribe + public void onConfigChanged(ConfigChanged configChanged) + { + if (configChanged.getGroup().equals("pvptools")) + { + switch (configChanged.getKey()) + { + case "countPlayers": + if (config.countPlayers()) + { + updatePlayers(); + } + if (!config.countPlayers()) + { + panel.disablePlayerCount(); + } + break; + case "countOverHeads": + if (config.countOverHeads()) + { + countOverHeads(); + } + if (!config.countOverHeads()) + { + panel.disablePrayerCount(); + } + break; + case "riskCalculator": + if (config.riskCalculatorEnabled()) + { + getCarriedWealth(); + } + if (!config.riskCalculatorEnabled()) + { + panel.disableRiskCalculator(); + } + break; + case "missingPlayers": + if (config.missingPlayersEnabled()) + { + panel.missingPlayers.setVisible(true); + } + break; + case "currentPlayers": + if (config.currentPlayersEnabled()) + { + panel.currentPlayers.setVisible(true); + } + break; + default: + break; + } + } + } + + @Subscribe + public void onItemContainerChanged(ItemContainerChanged event) + { + if (event.getItemContainer().equals(client.getItemContainer(InventoryID.INVENTORY)) && + config.riskCalculatorEnabled()) + { + getCarriedWealth(); + } + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState().equals(GameState.LOGGED_IN) && config.riskCalculatorEnabled()) + { + getCarriedWealth(); + } + if (event.getGameState().equals(GameState.LOGGED_IN)) + { + if (config.countPlayers()) + { + updatePlayers(); + } + } + } + + @Subscribe + public void onPlayerSpawned(PlayerSpawned event) + { + if (config.countPlayers() && PvPUtil.isAttackable(client, event.getPlayer())) + { + updatePlayers(); + } + if (config.countOverHeads()) + { + countOverHeads(); + } + } + + @Subscribe + public void onPlayerDespawned(PlayerDespawned event) + { + if (config.countPlayers() && PvPUtil.isAttackable(client, event.getPlayer())) + { + updatePlayers(); + } + if (config.countOverHeads()) + { + countOverHeads(); + } + } + + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) + { + if (config.attackOptionsFriend() || config.attackOptionsClan() || config.levelRangeAttackOptions()) + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + Player[] players = client.getCachedPlayers(); + Player player = null; + int identifier = menuEntryAdded.getIdentifier(); + if (identifier >= 0 && identifier < players.length) + { + player = players[identifier]; + } + if (player == null) + { + return; + } + final String option = Text.removeTags(menuEntryAdded.getOption()).toLowerCase(); + final String mtarget = Text.removeTags(menuEntryAdded.getTarget()).toLowerCase(); + if (attackHotKeyPressed && config.attackOptionsClan() || config.attackOptionsFriend() || + config.levelRangeAttackOptions()) + { + if (config.attackOptionsFriend() && player.isFriend()) + { + moveEntry(mtarget); + } + if (config.attackOptionsClan() && player.isClanMember()) + { + moveEntry(mtarget); + } + if (config.levelRangeAttackOptions() && !PvPUtil.isAttackable(client, player)) + { + moveEntry(mtarget); + } + } + } + } + + private void moveEntry(String mtarget) + { + this.mtarget = mtarget; + MenuEntry[] menuEntries = client.getMenuEntries(); + MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; + + // strip out existing '); + if (idx != -1) + { + target = target.substring(idx + 1); + } + /*System.out.println("Contents : " + lastEntry.getTarget()); + System.out.println("Contents : " + lastEntry.getIdentifier()); + System.out.println("Contents : " + lastEntry.getOption()); + System.out.println("length : " + menuEntries.length);*/ + if (menuEntries[menuEntries.length - 1] != null) + { + //System.out.println(menuEntries.length + ": " + menuEntries[menuEntries.length-1]); + } + if (lastEntry.getOption().contains("attack".toLowerCase())) + { + ArrayUtils.shift(menuEntries, 1); + //ArrayUtils.add(menuEntries, menuEntries.length - 2); + //menuEntries = ArrayUtils.remove(menuEntries, menuEntries.length - 1); + //menuEntrySwapperPlugin.swap("attack", option, mtarget, false); + } + if (lastEntry.getOption().equals("Attack")) + { + ArrayUtils.shift(menuEntries, 1); + + //menuEntries = ArrayUtils.sremove(menuEntries, menuEntries.length - 1); + //menuEntrySwapperPlugin.swap("attack", option, mtarget, false); + } + client.setMenuEntries(menuEntries); + + } + + @Subscribe + public void onFocusChanged(FocusChanged focusChanged) + { + if (!focusChanged.isFocused()) + { + setAttackHotKeyPressed(false); + } + } + + /** + * Enables or disables the fall in helper feature + */ + private void toggleFallinHelper() + { + if (!fallinHelperEnabled) + { + client.setIsHidingEntities(true); + client.setPlayersHidden(true); + fallinHelperEnabled = true; + } + else + { + client.setIsHidingEntities(false); + client.setPlayersHidden(false); + fallinHelperEnabled = false; + } + + } + + /** + * Updates the PvP Tools panel with the numbers for enemy protection prayers + */ + private void updatePrayerNumbers() + { + panel.numMageJLabel.setText(htmlLabel("Enemies Praying Mage: ", String.valueOf(overheadCount[0]))); + panel.numRangeJLabel.setText(htmlLabel("Enemies Praying Range: ", String.valueOf(overheadCount[1]))); + panel.numMeleeJLabel.setText(htmlLabel("Enemies Praying Melee: ", String.valueOf(overheadCount[2]))); + panel.numMageJLabel.repaint(); + panel.numRangeJLabel.repaint(); + panel.numMeleeJLabel.repaint(); + } + + /** + * + */ + private void updatePlayers() + { + if (config.countPlayers()) + { + int cc = 0; + int other = 0; + for (Player p : client.getPlayers()) + { + if (Objects.nonNull(p)) + { + if (PvPUtil.isAttackable(client, p)) + { + if (p.isClanMember()) + { + cc++; + } + else + { + other++; + } + } + } + } + + panel.numOther.setText(htmlLabel("Other Player Count: ", String.valueOf(other))); + panel.numCC.setText(htmlLabel("Friendly Player Count: ", String.valueOf(cc))); + panel.numCC.repaint(); + panel.numOther.repaint(); + } + } + + private void countOverHeads() + { + overheadCount = new int[]{0, 0, 0}; + for (Player p : client.getPlayers()) + { + if (Objects.nonNull(p)) + { + if (PvPUtil.isAttackable(client, p)) + { + if (!p.isClanMember() && !(p.getOverheadIcon() == null)) + { + switch (p.getOverheadIcon()) + { + case MAGIC: + overheadCount[0]++; + break; + case RANGED: + overheadCount[1]++; + break; + case MELEE: + overheadCount[2]++; + break; + } + } + } + } + } + updatePrayerNumbers(); + } + + /** + * Calculates the player's risk based on Item Price of all items in their inventory and equipment + */ + private void getCarriedWealth() + { + if (!config.riskCalculatorEnabled()) + { + return; + } + if (client.getItemContainer(InventoryID.EQUIPMENT) == null) + { + return; + } + if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null) + { + return; + } + Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(), + Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems()); + TreeMap priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue)); + int wealth = 0; + for (Item i : items) + { + int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity()); + + final ItemComposition itemComposition = itemManager.getItemComposition(i.getId()); + if (!itemComposition.isTradeable() && value == 0) + { + value = itemComposition.getPrice() * i.getQuantity(); + priceMap.put(value, i); + } + else + { + value = itemManager.getItemPrice(i.getId()) * i.getQuantity(); + if (i.getId() > 0 && value > 0) + { + priceMap.put(value, i); + } + } + wealth += value; + } + panel.totalRiskLabel.setText(htmlLabel("Total risk: ", quantityToRSDecimalStack(wealth))); + panel.totalRiskLabel.repaint(); + + int itemLimit = 0; + if (client.getLocalPlayer().getSkullIcon() != null) + { + if (client.getLocalPlayer().getSkullIcon() == SkullIcon.SKULL) + { + itemLimit = 1; + } + } + if (client.getLocalPlayer().getSkullIcon() == null) + { + itemLimit = 4; + } + + AsyncBufferedImage itemImage = null; + + NavigableMap descendingMap = priceMap.descendingMap(); + + for (int i = 0; i < itemLimit; i++) + { + if (i == 0) + { + if (!descendingMap.isEmpty()) + { + itemImage = itemManager.getImage(descendingMap.pollFirstEntry().getValue().getId()); + } + } + else + { + if (!descendingMap.isEmpty()) + { + itemManager.getItemComposition(priceMap.descendingMap().pollFirstEntry().getValue().getId()) + .getName(); + } + } + } + panel.riskProtectingItem.setText(htmlLabel("Risk Protecting Item: ", + quantityToRSDecimalStack(descendingMap.keySet().stream().mapToInt(Integer::intValue).sum()))); + panel.riskProtectingItem.repaint(); + + panel.biggestItemLabel.setText("Most Valuable Item: "); + if (itemImage != null) + { + itemImage.addTo(panel.biggestItemLabel); + } + panel.biggestItemLabel.repaint(); + } + +} \ No newline at end of file From 01ab3e1c222d1bdc71a2f1a494f5587aa99db713 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Thu, 25 Apr 2019 21:56:37 +0100 Subject: [PATCH 5/6] Update WildernessLocationsPlugin.java --- .../plugins/wildernesslocations/WildernessLocationsPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java index 27b0bc5f82..f6c1a9b46c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java @@ -22,7 +22,7 @@ import net.runelite.client.util.WildernessLocation; @PluginDescriptor( name = "Wild Locations", description = "Indicates the players current location in the wild", - tags = {"Wildy", "Wilderness Location", "location", "loc", "pvp", "pklite"} + tags = {"Wildy", "Wilderness Location", "location", "loc", "pvp", "pklite"}, type = PluginType.PVP ) public class WildernessLocationsPlugin extends Plugin From f55e1aa7a743dfe106ac9eb1ba98e74ec81045c0 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Thu, 25 Apr 2019 22:19:29 +0100 Subject: [PATCH 6/6] Update WildernessLocationsPlugin.java --- .../plugins/wildernesslocations/WildernessLocationsPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java index f6c1a9b46c..544a8aad02 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wildernesslocations/WildernessLocationsPlugin.java @@ -15,6 +15,7 @@ import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.GameTick; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.WildernessLocation;