From 78906dfd683b603aecee0e5f0bf5252261ea4fd2 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 17:30:23 +0100 Subject: [PATCH 01/21] update --- .../plugins/antidrag/AntiDragConfig.java | 7 +- .../plugins/antidrag/AntiDragPlugin.java | 30 +- .../client/plugins/batools/BAToolsPlugin.java | 3 +- .../plugins/clanchat/ClanChatPlugin.java | 629 ++++++------------ .../EquipmentInspectorPlugin.java | 2 +- .../client/plugins/hydra/HydraPlugin.java | 3 +- .../pvptools/CurrentPlayersJFrame.java | 74 +++ .../pvptools/MissingPlayersJFrame.java | 74 +++ .../plugins/pvptools/PvpToolsConfig.java | 69 ++ .../plugins/pvptools/PvpToolsOverlay.java | 61 ++ .../plugins/pvptools/PvpToolsPanel.java | 138 ++++ .../plugins/pvptools/PvpToolsPlugin.java | 475 +++++++++++++ .../client/plugins/pvptools/skull.png | Bin 0 -> 448 bytes .../ShayzienInfirmaryPlugin.java | 3 +- .../spellbookfixer/SpellbookFixerPlugin.java | 3 +- .../plugins/templetrek/TempleTrekPlugin.java | 3 +- .../tobdamagecount/DamageCounterPlugin.java | 1 + .../whalewatchers}/WhaleWatchersConfig.java | 0 .../WhaleWatchersGloryOverlay.java | 0 .../whalewatchers}/WhaleWatchersOverlay.java | 0 .../whalewatchers}/WhaleWatchersPlugin.java | 8 +- .../WhaleWatchersProtOverlay.java | 0 .../WhaleWatchersSmiteableOverlay.java | 0 .../WildernessLocationsPlugin.java | 3 +- .../net/runelite/client/util/PvPUtil.java | 61 ++ .../client/plugins/pvptools/skull.png | Bin 0 -> 448 bytes 26 files changed, 1218 insertions(+), 429 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/pvptools/CurrentPlayersJFrame.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/pvptools/MissingPlayersJFrame.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/pvptools/skull.png rename {whalewatchers => runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers}/WhaleWatchersConfig.java (100%) rename {whalewatchers => runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers}/WhaleWatchersGloryOverlay.java (100%) rename {whalewatchers => runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers}/WhaleWatchersOverlay.java (100%) rename {whalewatchers => runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers}/WhaleWatchersPlugin.java (96%) rename {whalewatchers => runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers}/WhaleWatchersProtOverlay.java (100%) rename {whalewatchers => runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers}/WhaleWatchersSmiteableOverlay.java (100%) create mode 100644 runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/pvptools/skull.png diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java index 1bed02603e..764a988611 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java @@ -28,7 +28,12 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -@ConfigGroup("antiDrag") +/*@ConfigGroup( + keyName = "antiDrag", + name = "Anti Drag", + description = "Configuration for the anti drag plugin" +)*/ +@ConfigGroup("antidrag") public interface AntiDragConfig extends Config { @ConfigItem( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java index 26f926be4a..4dafc29b8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java @@ -24,23 +24,22 @@ */ package net.runelite.client.plugins.antidrag; +import com.google.common.eventbus.Subscribe; import com.google.inject.Provides; import java.awt.event.KeyEvent; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.events.FocusChanged; import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyListener; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( - name = "Shift Anti Drag", - description = "Prevent dragging an item for a specified delay", - tags = {"antidrag", "delay", "inventory", "items"} -) + name = "Anti Drag", + type = "utility", + enabledByDefault = false) public class AntiDragPlugin extends Plugin implements KeyListener { private static final int DEFAULT_DELAY = 5; @@ -63,6 +62,7 @@ public class AntiDragPlugin extends Plugin implements KeyListener @Override protected void startUp() throws Exception { + client.setInventoryDragDelay(config.dragDelay()); keyManager.registerKeyListener(this); } @@ -79,30 +79,40 @@ public class AntiDragPlugin extends Plugin implements KeyListener } + public boolean toggleDrag = true; + @Override public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) + /*if (e.getKeyCode() == KeyEvent.VK_SHIFT) { client.setInventoryDragDelay(config.dragDelay()); } + client.setInventoryDragDelay(config.dragDelay());*/ } @Override public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) - { + if (e.getKeyCode() == KeyEvent.VK_CONTROL && toggleDrag) { + + toggleDrag = false; client.setInventoryDragDelay(DEFAULT_DELAY); + + } else if (e.getKeyCode() == KeyEvent.VK_CONTROL && !toggleDrag) { + + toggleDrag = true; + client.setInventoryDragDelay(config.dragDelay()); + } } - @Subscribe + /*@Subscribe public void onFocusChanged(FocusChanged focusChanged) { if (!focusChanged.isFocused()) { client.setInventoryDragDelay(DEFAULT_DELAY); } - } + }*/ } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java index 7b9e195848..961e8760cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java @@ -78,7 +78,8 @@ import net.runelite.client.util.Text; @PluginDescriptor( name = "BA Tools", description = "Custom tools for Barbarian Assault", - tags = {"minigame", "overlay", "timer"} + tags = {"minigame", "overlay", "timer"}, + type = "utility" ) public class BAToolsPlugin extends Plugin implements KeyListener { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java index 506c9a58c0..f52ebd7260 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java @@ -1,89 +1,30 @@ -/* - * Copyright (c) 2017, Devin French - * Copyright (c) 2019, Adam - * Copyright (c) 2018, trimbe - * 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.clanchat; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import com.google.inject.Provides; -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import javax.inject.Inject; -import net.runelite.api.ChatLineBuffer; -import net.runelite.api.ChatMessageType; -import net.runelite.api.ClanMember; -import net.runelite.api.ClanMemberRank; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.MessageNode; -import net.runelite.api.Player; -import net.runelite.api.ScriptID; -import net.runelite.api.SpriteID; -import net.runelite.api.VarClientStr; -import net.runelite.api.Varbits; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ClanChanged; -import net.runelite.api.events.ClanMemberJoined; -import net.runelite.api.events.ClanMemberLeft; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; -import net.runelite.api.events.PlayerDespawned; -import net.runelite.api.events.PlayerSpawned; -import net.runelite.api.events.VarClientStrChanged; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.api.widgets.WidgetType; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.chat.ChatMessageBuilder; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.ClanManager; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import static net.runelite.client.ui.JagexColors.CHAT_CLAN_NAME_OPAQUE_BACKGROUND; -import static net.runelite.client.ui.JagexColors.CHAT_CLAN_NAME_TRANSPARENT_BACKGROUND; -import static net.runelite.client.ui.JagexColors.CHAT_CLAN_TEXT_OPAQUE_BACKGROUND; -import static net.runelite.client.ui.JagexColors.CHAT_CLAN_TEXT_TRANSPARENT_BACKGROUND; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; -import net.runelite.client.util.Text; +import net.runelite.client.plugins.*; +import net.runelite.client.game.*; +import net.runelite.client.callback.*; -@PluginDescriptor( - name = "Clan Chat", - description = "Add rank icons to users talking in clan chat", - tags = {"icons", "rank", "recent"} -) +import java.util.List; +import java.util.Objects; +import java.util.concurrent.*; +import net.runelite.client.config.*; +import com.google.inject.*; +import net.runelite.client.util.*; +import net.runelite.client.eventbus.*; +import com.google.common.base.*; +import net.runelite.api.widgets.*; +import net.runelite.client.ui.*; +import net.runelite.client.chat.*; +import java.awt.*; +import net.runelite.api.*; +import net.runelite.api.events.*; +import com.google.common.collect.*; +import java.util.*; +import java.util.function.*; +import net.runelite.client.ui.overlay.infobox.*; +import java.awt.image.*; + +@PluginDescriptor(name = "Clan Chat", description = "Add rank icons to users talking in clan chat", tags = { "icons", "rank", "recent" }) public class ClanChatPlugin extends Plugin { private static final int MAX_CHATS = 10; @@ -91,508 +32,376 @@ public class ClanChatPlugin extends Plugin private static final String RECENT_TITLE = "Recent Clan Chats"; private static final int JOIN_LEAVE_DURATION = 20; private static final int MESSAGE_DELAY = 10; - @Inject private Client client; - @Inject private ClanManager clanManager; - @Inject private ClanChatConfig config; - @Inject private InfoBoxManager infoBoxManager; - @Inject private SpriteManager spriteManager; - @Inject private ClientThread clientThread; - - private List chats = new ArrayList<>(); - private List clanMembers = new ArrayList<>(); + private List chats; + private static CopyOnWriteArrayList clanMembers; private ClanChatIndicator clanMemberCounter; - /** - * queue of temporary messages added to the client - */ - private final Deque clanJoinMessages = new ArrayDeque<>(); - private Map activityBuffer = new HashMap<>(); + private final Deque clanJoinMessages; + private Map activityBuffer; private int clanJoinedTick; + public ClanChatPlugin() { + this.chats = new ArrayList(); + this.clanJoinMessages = new ArrayDeque(); + this.activityBuffer = new HashMap(); + } + + public static CopyOnWriteArrayList getClanMembers() { + return (CopyOnWriteArrayList)ClanChatPlugin.clanMembers.clone(); + } + @Provides - ClanChatConfig getConfig(ConfigManager configManager) - { + ClanChatConfig getConfig(final ConfigManager configManager) { return configManager.getConfig(ClanChatConfig.class); } - @Override - public void startUp() - { - chats = new ArrayList<>(Text.fromCSV(config.chatsData())); + public void startUp() { + this.chats = new ArrayList(Text.fromCSV(this.config.chatsData())); } - @Override - public void shutDown() - { - clanMembers.clear(); - removeClanCounter(); - resetClanChats(); + public void shutDown() { + ClanChatPlugin.clanMembers.clear(); + this.removeClanCounter(); + this.resetClanChats(); } @Subscribe - public void onConfigChanged(ConfigChanged configChanged) - { - if (configChanged.getGroup().equals("clanchat")) - { - if (!config.recentChats()) - { - resetClanChats(); + public void onConfigChanged(final ConfigChanged configChanged) { + if (configChanged.getGroup().equals("clanchat")) { + if (!this.config.recentChats()) { + this.resetClanChats(); } - - if (config.showClanCounter()) - { - clientThread.invoke(this::addClanCounter); + if (this.config.showClanCounter()) { + this.clientThread.invoke(this::addClanCounter); } - else - { - removeClanCounter(); + else { + this.removeClanCounter(); } } } @Subscribe - public void onClanMemberJoined(ClanMemberJoined event) - { + public void onClanMemberJoined(final ClanMemberJoined event) { final ClanMember member = event.getMember(); - - if (member.getWorld() == client.getWorld()) - { + if (member.getWorld() == this.client.getWorld()) { final String memberName = Text.toJagexName(member.getUsername()); - - for (final Player player : client.getPlayers()) - { - if (player != null && memberName.equals(Text.toJagexName(player.getName()))) - { - clanMembers.add(player); - addClanCounter(); + for (final Player player : this.client.getPlayers()) { + if (player != null && memberName.equals(Text.toJagexName(player.getName()))) { + ClanChatPlugin.clanMembers.add(player); + this.addClanCounter(); break; } } } - - // clan members getting initialized isn't relevant - if (clanJoinedTick == client.getTickCount()) - { + if (this.clanJoinedTick == this.client.getTickCount()) { return; } - - if (!config.showJoinLeave() || - member.getRank().getValue() < config.joinLeaveRank().getValue()) - { + if (!this.config.showJoinLeave() || member.getRank().getValue() < this.config.joinLeaveRank().getValue()) { return; } - - // attempt to filter out world hopping joins - if (!activityBuffer.containsKey(member.getUsername())) - { - ClanMemberActivity joinActivity = new ClanMemberActivity(ClanActivityType.JOINED, - member, client.getTickCount()); - activityBuffer.put(member.getUsername(), joinActivity); + if (!this.activityBuffer.containsKey(member.getUsername())) { + final ClanMemberActivity joinActivity = new ClanMemberActivity(ClanActivityType.JOINED, member, this.client.getTickCount()); + this.activityBuffer.put(member.getUsername(), joinActivity); } - else - { - activityBuffer.remove(member.getUsername()); + else { + this.activityBuffer.remove(member.getUsername()); } } @Subscribe - public void onClanMemberLeft(ClanMemberLeft event) - { + public void onClanMemberLeft(final ClanMemberLeft event) { final ClanMember member = event.getMember(); - - if (member.getWorld() == client.getWorld()) - { + if (member.getWorld() == this.client.getWorld()) { final String memberName = Text.toJagexName(member.getUsername()); - final Iterator each = clanMembers.iterator(); - - while (each.hasNext()) - { - if (memberName.equals(Text.toJagexName(each.next().getName()))) - { + final Iterator each = ClanChatPlugin.clanMembers.iterator(); + while (each.hasNext()) { + if (memberName.equals(Text.toJagexName(each.next().getName()))) { each.remove(); - - if (clanMembers.isEmpty()) - { - removeClanCounter(); + if (ClanChatPlugin.clanMembers.isEmpty()) { + this.removeClanCounter(); + break; } - break; } } } - - if (!config.showJoinLeave() || - member.getRank().getValue() < config.joinLeaveRank().getValue()) - { + if (!this.config.showJoinLeave() || member.getRank().getValue() < this.config.joinLeaveRank().getValue()) { return; } - - if (!activityBuffer.containsKey(member.getUsername())) - { - ClanMemberActivity leaveActivity = new ClanMemberActivity(ClanActivityType.LEFT, - member, client.getTickCount()); - activityBuffer.put(member.getUsername(), leaveActivity); + if (!this.activityBuffer.containsKey(member.getUsername())) { + final ClanMemberActivity leaveActivity = new ClanMemberActivity(ClanActivityType.LEFT, member, this.client.getTickCount()); + this.activityBuffer.put(member.getUsername(), leaveActivity); } - else - { - activityBuffer.remove(member.getUsername()); + else { + this.activityBuffer.remove(member.getUsername()); } } @Subscribe - public void onGameTick(GameTick gameTick) - { - if (client.getGameState() != GameState.LOGGED_IN) - { + public void onGameTick(final GameTick gameTick) { + if (this.client.getGameState() != GameState.LOGGED_IN) { return; } - - Widget clanChatTitleWidget = client.getWidget(WidgetInfo.CLAN_CHAT_TITLE); - if (clanChatTitleWidget != null) - { - Widget clanChatList = client.getWidget(WidgetInfo.CLAN_CHAT_LIST); - Widget owner = client.getWidget(WidgetInfo.CLAN_CHAT_OWNER); - if (client.getClanChatCount() > 0) - { - clanChatTitleWidget.setText(CLAN_CHAT_TITLE + " (" + client.getClanChatCount() + "/100)"); + final Widget clanChatTitleWidget = this.client.getWidget(WidgetInfo.CLAN_CHAT_TITLE); + if (clanChatTitleWidget != null) { + final Widget clanChatList = this.client.getWidget(WidgetInfo.CLAN_CHAT_LIST); + final Widget owner = this.client.getWidget(WidgetInfo.CLAN_CHAT_OWNER); + if (this.client.getClanChatCount() > 0) { + clanChatTitleWidget.setText("Clan Chat (" + this.client.getClanChatCount() + "/100)"); } - else if (config.recentChats() && clanChatList.getChildren() == null && !Strings.isNullOrEmpty(owner.getText())) - { - clanChatTitleWidget.setText(RECENT_TITLE); - - loadClanChats(); + else if (this.config.recentChats() && clanChatList.getChildren() == null && !Strings.isNullOrEmpty(owner.getText())) { + clanChatTitleWidget.setText("Recent Clan Chats"); + this.loadClanChats(); } } - - if (!config.showJoinLeave()) - { + if (!this.config.showJoinLeave()) { return; } - - timeoutClanMessages(); - - addClanActivityMessages(); + this.timeoutClanMessages(); + this.addClanActivityMessages(); } - private void timeoutClanMessages() - { - if (clanJoinMessages.isEmpty()) - { + private void timeoutClanMessages() { + if (this.clanJoinMessages.isEmpty()) { return; } - boolean removed = false; - - for (Iterator it = clanJoinMessages.iterator(); it.hasNext(); ) - { - ClanJoinMessage clanJoinMessage = it.next(); - MessageNode messageNode = clanJoinMessage.getMessageNode(); + final Iterator it = this.clanJoinMessages.iterator(); + while (it.hasNext()) { + final ClanJoinMessage clanJoinMessage = it.next(); + final MessageNode messageNode = clanJoinMessage.getMessageNode(); final int createdTick = clanJoinMessage.getTick(); - - if (client.getTickCount() > createdTick + JOIN_LEAVE_DURATION) - { - it.remove(); - - // If this message has been reused since, it will get a different id - if (clanJoinMessage.getGetMessageId() == messageNode.getId()) - { - ChatLineBuffer ccInfoBuffer = client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType()); - if (ccInfoBuffer != null) - { - ccInfoBuffer.removeMessageNode(messageNode); - removed = true; - } - } - } - else - { - // Everything else in the deque is newer + if (this.client.getTickCount() <= createdTick + 20) { break; } + it.remove(); + if (clanJoinMessage.getGetMessageId() != messageNode.getId()) { + continue; + } + final ChatLineBuffer ccInfoBuffer = this.client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType()); + if (ccInfoBuffer == null) { + continue; + } + ccInfoBuffer.removeMessageNode(messageNode); + removed = true; } - - if (removed) - { - clientThread.invoke(() -> client.runScript(ScriptID.BUILD_CHATBOX)); + if (removed) { + this.clientThread.invoke(() -> this.client.runScript(216, new Object[0])); } } - private void addClanActivityMessages() - { - Iterator activityIt = activityBuffer.values().iterator(); - - while (activityIt.hasNext()) - { - ClanMemberActivity activity = activityIt.next(); - - if (activity.getTick() < client.getTickCount() - MESSAGE_DELAY) - { + private void addClanActivityMessages() { + final Iterator activityIt = this.activityBuffer.values().iterator(); + while (activityIt.hasNext()) { + final ClanMemberActivity activity = activityIt.next(); + if (activity.getTick() < this.client.getTickCount() - 10) { activityIt.remove(); - addActivityMessage(activity.getMember(), activity.getActivityType()); + this.addActivityMessage(activity.getMember(), activity.getActivityType()); } } } - private void addActivityMessage(ClanMember member, ClanActivityType activityType) - { - final String activityMessage = activityType == ClanActivityType.JOINED ? " has joined." : " has left."; + private void addActivityMessage(final ClanMember member, final ClanActivityType activityType) { + final String activityMessage = (activityType == ClanActivityType.JOINED) ? " has joined." : " has left."; final ClanMemberRank rank = member.getRank(); - Color textColor = CHAT_CLAN_TEXT_OPAQUE_BACKGROUND; - Color channelColor = CHAT_CLAN_NAME_OPAQUE_BACKGROUND; + Color textColor = JagexColors.CHAT_CLAN_TEXT_OPAQUE_BACKGROUND; + Color channelColor = JagexColors.CHAT_CLAN_NAME_OPAQUE_BACKGROUND; int rankIcon = -1; - - if (client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1) - { - textColor = CHAT_CLAN_TEXT_TRANSPARENT_BACKGROUND; - channelColor = CHAT_CLAN_NAME_TRANSPARENT_BACKGROUND; + if (this.client.isResized() && this.client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1) { + textColor = JagexColors.CHAT_CLAN_TEXT_TRANSPARENT_BACKGROUND; + channelColor = JagexColors.CHAT_CLAN_NAME_TRANSPARENT_BACKGROUND; } - - if (config.clanChatIcons() && rank != null && rank != ClanMemberRank.UNRANKED) - { - rankIcon = clanManager.getIconNumber(rank); + if (this.config.clanChatIcons() && rank != null && rank != ClanMemberRank.UNRANKED) { + rankIcon = this.clanManager.getIconNumber(rank); } - - ChatMessageBuilder message = new ChatMessageBuilder() - .append("[") - .append(channelColor, client.getClanChatName()); - if (rankIcon > -1) - { - message - .append(" ") - .img(rankIcon); + final ChatMessageBuilder message = new ChatMessageBuilder().append("[").append(channelColor, this.client.getClanChatName()); + if (rankIcon > -1) { + message.append(" ").img(rankIcon); } - message - .append("] ") - .append(textColor, member.getUsername() + activityMessage); - + message.append("] ").append(textColor, member.getUsername() + activityMessage); final String messageString = message.build(); - client.addChatMessage(ChatMessageType.FRIENDSCHATNOTIFICATION, "", messageString, ""); - - final ChatLineBuffer chatLineBuffer = client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType()); + this.client.addChatMessage(ChatMessageType.FRIENDSCHATNOTIFICATION, "", messageString, ""); + final ChatLineBuffer chatLineBuffer = this.client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType()); final MessageNode[] lines = chatLineBuffer.getLines(); final MessageNode line = lines[0]; - - ClanJoinMessage clanJoinMessage = new ClanJoinMessage(line, line.getId(), client.getTickCount()); - clanJoinMessages.addLast(clanJoinMessage); + final ClanJoinMessage clanJoinMessage = new ClanJoinMessage(line, line.getId(), this.client.getTickCount()); + this.clanJoinMessages.addLast(clanJoinMessage); } @Subscribe - public void onVarClientStrChanged(VarClientStrChanged strChanged) - { - if (strChanged.getIndex() == VarClientStr.RECENT_CLAN_CHAT.getIndex() && config.recentChats()) - { - updateRecentChat(client.getVar(VarClientStr.RECENT_CLAN_CHAT)); + public void onVarClientStrChanged(final VarClientStrChanged strChanged) { + if (strChanged.getIndex() == VarClientStr.RECENT_CLAN_CHAT.getIndex() && this.config.recentChats()) { + this.updateRecentChat(this.client.getVar(VarClientStr.RECENT_CLAN_CHAT)); } } @Subscribe - public void onChatMessage(ChatMessage chatMessage) - { - if (client.getGameState() != GameState.LOADING && client.getGameState() != GameState.LOGGED_IN) - { + public void onChatMessage(final ChatMessage chatMessage) { + if (this.client.getGameState() != GameState.LOADING && this.client.getGameState() != GameState.LOGGED_IN) { return; } - - if (client.getClanChatCount() <= 0) - { + if (this.client.getClanChatCount() <= 0) { return; } - - switch (chatMessage.getType()) - { + switch (chatMessage.getType()) { case PRIVATECHAT: - case MODPRIVATECHAT: - if (!config.privateMessageIcons()) - { + case MODPRIVATECHAT: { + if (!this.config.privateMessageIcons()) { return; } break; + } case PUBLICCHAT: - case MODCHAT: - if (!config.publicChatIcons()) - { + case MODCHAT: { + if (!this.config.publicChatIcons()) { return; } break; - case FRIENDSCHAT: - if (!config.clanChatIcons()) - { + } + case FRIENDSCHAT: { + if (!this.config.clanChatIcons()) { return; } break; - default: + } + default: { return; + } } - - insertClanRankIcon(chatMessage); + this.insertClanRankIcon(chatMessage); } @Subscribe - public void onGameStateChanged(GameStateChanged state) - { - GameState gameState = state.getGameState(); - - if (gameState == GameState.LOGIN_SCREEN || gameState == GameState.CONNECTION_LOST || gameState == GameState.HOPPING) - { - clanMembers.clear(); - removeClanCounter(); - - clanJoinMessages.clear(); + public void onGameStateChanged(final GameStateChanged state) { + final GameState gameState = state.getGameState(); + if (gameState == GameState.LOGIN_SCREEN || gameState == GameState.CONNECTION_LOST || gameState == GameState.HOPPING) { + ClanChatPlugin.clanMembers.clear(); + this.removeClanCounter(); + this.clanJoinMessages.clear(); } } @Subscribe - public void onPlayerSpawned(PlayerSpawned event) - { - if (event.getPlayer().isClanMember()) - { - clanMembers.add(event.getPlayer()); - addClanCounter(); + public void onPlayerSpawned(final PlayerSpawned event) { + if (event.getPlayer().isClanMember()) { + ClanChatPlugin.clanMembers.add(event.getPlayer()); + this.addClanCounter(); } } @Subscribe - public void onPlayerDespawned(PlayerDespawned event) - { - if (clanMembers.remove(event.getPlayer()) && clanMembers.isEmpty()) - { - removeClanCounter(); + public void onPlayerDespawned(final PlayerDespawned event) { + if (ClanChatPlugin.clanMembers.remove(event.getPlayer()) && ClanChatPlugin.clanMembers.isEmpty()) { + this.removeClanCounter(); } } @Subscribe - public void onClanChanged(ClanChanged event) - { - if (event.isJoined()) - { - clanJoinedTick = client.getTickCount(); + public void onClanChanged(final ClanChanged event) { + if (event.isJoined()) { + this.clanJoinedTick = this.client.getTickCount(); } - else - { - clanMembers.clear(); - removeClanCounter(); + else { + ClanChatPlugin.clanMembers.clear(); + this.removeClanCounter(); } - - activityBuffer.clear(); + this.activityBuffer.clear(); } - int getClanAmount() - { - return clanMembers.size(); + int getClanAmount() { + return ClanChatPlugin.clanMembers.size(); } - private void insertClanRankIcon(final ChatMessage message) - { - final ClanMemberRank rank = clanManager.getRank(message.getName()); - - if (rank != null && rank != ClanMemberRank.UNRANKED) - { - int iconNumber = clanManager.getIconNumber(rank); + private void insertClanRankIcon(final ChatMessage message) { + final ClanMemberRank rank = this.clanManager.getRank(message.getName()); + if (rank != null && rank != ClanMemberRank.UNRANKED) { + final int iconNumber = this.clanManager.getIconNumber(rank); final String img = ""; - if (message.getType() == ChatMessageType.FRIENDSCHAT) - { - message.getMessageNode() - .setSender(message.getMessageNode().getSender() + " " + img); + if (message.getType() == ChatMessageType.FRIENDSCHAT) { + message.getMessageNode().setSender(message.getMessageNode().getSender() + " " + img); } - else - { - message.getMessageNode() - .setName(img + message.getMessageNode().getName()); + else { + message.getMessageNode().setName(img + message.getMessageNode().getName()); } - client.refreshChat(); + this.client.refreshChat(); } } - private void resetClanChats() - { - Widget clanChatList = client.getWidget(WidgetInfo.CLAN_CHAT_LIST); - Widget clanChatTitleWidget = client.getWidget(WidgetInfo.CLAN_CHAT_TITLE); - - if (clanChatList == null) - { + private void resetClanChats() { + final Widget clanChatList = this.client.getWidget(WidgetInfo.CLAN_CHAT_LIST); + final Widget clanChatTitleWidget = this.client.getWidget(WidgetInfo.CLAN_CHAT_TITLE); + if (clanChatList == null) { return; } - - if (client.getClanChatCount() == 0) - { + if (this.client.getClanChatCount() == 0) { clanChatList.setChildren(null); } - - clanChatTitleWidget.setText(CLAN_CHAT_TITLE); + clanChatTitleWidget.setText("Clan Chat"); } - private void loadClanChats() - { - Widget clanChatList = client.getWidget(WidgetInfo.CLAN_CHAT_LIST); - if (clanChatList == null) - { + private void loadClanChats() { + final Widget clanChatList = this.client.getWidget(WidgetInfo.CLAN_CHAT_LIST); + if (clanChatList == null) { return; } - int y = 2; clanChatList.setChildren(null); - for (String chat : Lists.reverse(chats)) - { - Widget widget = clanChatList.createChild(-1, WidgetType.TEXT); + for (final String chat : Lists.reverse(this.chats)) { + final Widget widget = clanChatList.createChild(-1, 4); widget.setFontId(494); - widget.setTextColor(0xffffff); + widget.setTextColor(16777215); widget.setText(chat); widget.setOriginalHeight(14); widget.setOriginalWidth(142); widget.setOriginalY(y); widget.setOriginalX(20); widget.revalidate(); - y += 14; } } - private void updateRecentChat(String s) - { - if (Strings.isNullOrEmpty(s)) - { + private void updateRecentChat(String s) { + if (Strings.isNullOrEmpty(s)) { return; } - s = Text.toJagexName(s); - - chats.removeIf(s::equalsIgnoreCase); - chats.add(s); - - while (chats.size() > MAX_CHATS) - { - chats.remove(0); + final List chats = this.chats; + final String s2 = s; + Objects.requireNonNull(s2); + chats.removeIf(s2::equalsIgnoreCase); + this.chats.add(s); + while (this.chats.size() > 10) { + this.chats.remove(0); } - - config.chatsData(Text.toCSV(chats)); + this.config.chatsData(Text.toCSV(this.chats)); } - private void removeClanCounter() - { - infoBoxManager.removeInfoBox(clanMemberCounter); - clanMemberCounter = null; + private void removeClanCounter() { + this.infoBoxManager.removeInfoBox(this.clanMemberCounter); + this.clanMemberCounter = null; } - private void addClanCounter() - { - if (!config.showClanCounter() || clanMemberCounter != null || clanMembers.isEmpty()) - { + private void addClanCounter() { + if (!this.config.showClanCounter() || this.clanMemberCounter != null || ClanChatPlugin.clanMembers.isEmpty()) { return; } + final BufferedImage image = this.spriteManager.getSprite(904, 0); + this.clanMemberCounter = new ClanChatIndicator(image, this); + this.infoBoxManager.addInfoBox(this.clanMemberCounter); + } - final BufferedImage image = spriteManager.getSprite(SpriteID.TAB_CLAN_CHAT, 0); - clanMemberCounter = new ClanChatIndicator(image, this); - infoBoxManager.addInfoBox(clanMemberCounter); + static { + ClanChatPlugin.clanMembers = new CopyOnWriteArrayList(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorPlugin.java index 02ad6e0b35..5ea9ea76b6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/equipmentinspector/EquipmentInspectorPlugin.java @@ -35,7 +35,7 @@ import java.util.concurrent.ScheduledExecutorService; name = "Equipment Inspector", description = "Inspects enemy equipment", enabledByDefault = false, - type = "PVP" + type = "utility" ) @Slf4j diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java index ba8c0317a7..f976a9cd2b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hydra/HydraPlugin.java @@ -17,7 +17,8 @@ import java.util.Map; @PluginDescriptor( name = "Hydra", description = "Hydra Helper", - tags = {"Hydra", "Helper"} + tags = {"Hydra", "Helper"}, + type = "PVM" ) public class HydraPlugin extends Plugin { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/CurrentPlayersJFrame.java b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/CurrentPlayersJFrame.java new file mode 100644 index 0000000000..e61b94fc95 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/CurrentPlayersJFrame.java @@ -0,0 +1,74 @@ +/* + * Decompiled with CFR 0.139. + */ +package net.runelite.client.plugins.pvptools; + +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.function.Consumer; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import net.runelite.api.Client; +import net.runelite.client.plugins.pvptools.PvpToolsPlugin; +import net.runelite.client.ui.FontManager; + +public class CurrentPlayersJFrame +extends JFrame { + public JList currentPlayersJList; + + CurrentPlayersJFrame(Client client, PvpToolsPlugin pvpToolsPlugin, List list) { + int x = client.getCanvas().getLocationOnScreen().x + client.getCanvas().getWidth(); + int y = client.getCanvas().getLocationOnScreen().y; + JPanel scrollContainerCurrent = new JPanel(new BorderLayout()); + JScrollPane jScrollPane = new JScrollPane(scrollContainerCurrent); + JButton refreshJButton = new JButton("Refresh"); + refreshJButton.addActionListener(pvpToolsPlugin.currentPlayersActionListener); + JButton copyJButton = new JButton("Copy List"); + this.currentPlayersJList = new JList(list.toArray()); + ActionListener copyButtonActionListener = e -> { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + StringBuilder stringBuilder = new StringBuilder(); + list.forEach(s -> { + stringBuilder.append((String)s); + stringBuilder.append(System.getProperty("line.separator")); + }); + StringSelection stringSelection = new StringSelection(stringBuilder.toString()); + clipboard.setContents(stringSelection, stringSelection); + }; + copyJButton.addActionListener(copyButtonActionListener); + this.setTitle("Current CC Members"); + this.setDefaultCloseOperation(2); + JLabel titleLabel = new JLabel("Current CC Members"); + titleLabel.setFont(FontManager.getRunescapeFont().deriveFont(1, 18.0f)); + this.currentPlayersJList.setFont(new Font("Arial", 0, 14)); + scrollContainerCurrent.add((Component)refreshJButton, "North"); + scrollContainerCurrent.add((Component)titleLabel, "Center"); + JPanel footerPanel = new JPanel(new BorderLayout()); + footerPanel.add((Component)this.currentPlayersJList, "North"); + footerPanel.add((Component)copyJButton, "Center"); + scrollContainerCurrent.add((Component)footerPanel, "South"); + this.add(jScrollPane); + this.setLocation(x, y); + this.setMaximumSize(Toolkit.getDefaultToolkit().getScreenSize()); + this.pack(); + this.setVisible(true); + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/MissingPlayersJFrame.java b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/MissingPlayersJFrame.java new file mode 100644 index 0000000000..324db3869a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/MissingPlayersJFrame.java @@ -0,0 +1,74 @@ +/* + * Decompiled with CFR 0.139. + */ +package net.runelite.client.plugins.pvptools; + +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.function.Consumer; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import net.runelite.api.Client; +import net.runelite.client.plugins.pvptools.PvpToolsPlugin; +import net.runelite.client.ui.FontManager; + +public class MissingPlayersJFrame +extends JFrame { + public JList missingPlayersJList; + + MissingPlayersJFrame(Client client, PvpToolsPlugin pvpToolsPlugin, List list) { + int x = client.getCanvas().getLocationOnScreen().x + client.getCanvas().getWidth(); + int y = client.getCanvas().getLocationOnScreen().y; + JPanel scrollConatiner = new JPanel(new BorderLayout()); + JScrollPane jScrollPane = new JScrollPane(scrollConatiner); + JButton refreshJButton = new JButton("Refresh"); + refreshJButton.addActionListener(pvpToolsPlugin.playersButtonActionListener); + JButton copyJButton = new JButton("Copy List"); + this.missingPlayersJList = new JList(list.toArray()); + ActionListener copyButtonActionListener = e -> { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + StringBuilder stringBuilder = new StringBuilder(); + list.forEach(s -> { + stringBuilder.append((String)s); + stringBuilder.append(System.getProperty("line.separator")); + }); + StringSelection stringSelection = new StringSelection(stringBuilder.toString()); + clipboard.setContents(stringSelection, stringSelection); + }; + copyJButton.addActionListener(copyButtonActionListener); + this.setTitle("Missing CC Members"); + this.setDefaultCloseOperation(2); + JLabel titleLabel = new JLabel("Missing CC Members"); + titleLabel.setFont(FontManager.getRunescapeFont().deriveFont(1, 18.0f)); + this.missingPlayersJList.setFont(new Font("Arial", 0, 14)); + scrollConatiner.add((Component)refreshJButton, "North"); + scrollConatiner.add((Component)titleLabel, "Center"); + JPanel footerPanel = new JPanel(new BorderLayout()); + footerPanel.add((Component)this.missingPlayersJList, "North"); + footerPanel.add((Component)copyJButton, "Center"); + scrollConatiner.add((Component)footerPanel, "South"); + this.add(jScrollPane); + this.setLocation(x, y); + this.setMaximumSize(Toolkit.getDefaultToolkit().getScreenSize()); + this.pack(); + this.setVisible(true); + } +} + 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 new file mode 100644 index 0000000000..d88182db0e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsConfig.java @@ -0,0 +1,69 @@ +/* + * Decompiled with CFR 0.139. + */ +package net.runelite.client.plugins.pvptools; + +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(value="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 public 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 public 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 public 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 public Keybind hotkey() { + return Keybind.NOT_SET; + } + + @ConfigItem(keyName="attackOptionsClan", name="Hide CC Attack Option", description="Hides the attack option for people in the same CC", position=7) + default public boolean attackOptionsClan() { + return false; + } + + @ConfigItem(keyName="attackOptionsFriend", name="Hide Friend Attack Options", description="Hides the attack option for people on your friends list", position=8) + default public 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) + default public Keybind attackOptionsHotkey() { + return Keybind.CTRL; + } + + @ConfigItem(keyName="levelRangeAttackOptions", name="Hide Other Attack Options", description="Hides the attack option for people that are outside your level range", position=9) + default public 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 public 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 public 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 public boolean currentPlayersEnabled() { + return true; + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsOverlay.java new file mode 100644 index 0000000000..b24b66dab7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsOverlay.java @@ -0,0 +1,61 @@ +/* + * Decompiled with CFR 0.139. + */ +package net.runelite.client.plugins.pvptools; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.Shape; +import java.awt.Stroke; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.client.plugins.pvptools.PvpToolsConfig; +import net.runelite.client.plugins.pvptools.PvpToolsPlugin; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; + +public class PvpToolsOverlay +extends Overlay { + private PvpToolsPlugin pvpToolsPlugin; + private PvpToolsConfig pvpToolsConfig; + private Client client; + + @Inject + private PvpToolsOverlay(PvpToolsConfig pvpToolsConfig, PvpToolsPlugin pvpToolsPlugin, Client client) { + this.pvpToolsPlugin = pvpToolsPlugin; + this.pvpToolsConfig = pvpToolsConfig; + this.client = client; + this.setLayer(OverlayLayer.ABOVE_WIDGETS); + this.setPriority(OverlayPriority.HIGH); + this.setPosition(OverlayPosition.DYNAMIC); + } + + @Override + public Dimension render(Graphics2D graphics) { + if (this.pvpToolsConfig.fallInHelper() && this.pvpToolsPlugin.fallinHelperEnabled) { + graphics.setFont(FontManager.getRunescapeFont().deriveFont(28)); + OverlayUtil.renderTextLocation(graphics, new Point(200, 80), "FALL IN HELPER ENABLED", Color.YELLOW); + } + return null; + } + + private void renderPoly(Graphics2D graphics, Color color, Polygon polygon) { + if (polygon != null) { + graphics.setColor(color); + graphics.setStroke(new BasicStroke(2.0f)); + graphics.draw(polygon); + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 20)); + graphics.fill(polygon); + } + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java new file mode 100644 index 0000000000..8856c37b32 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPanel.java @@ -0,0 +1,138 @@ +/* + * Decompiled with CFR 0.139. + */ +package net.runelite.client.plugins.pvptools; + +import com.google.common.base.MoreObjects; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.LayoutManager; +import javax.inject.Inject; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.plugins.info.JRichTextPane; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.PluginPanel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PvpToolsPanel +extends PluginPanel { + private static final Logger log = LoggerFactory.getLogger(PvpToolsPanel.class); + private final JLabel loggedLabel = new JLabel(); + private final JRichTextPane emailLabel = new JRichTextPane(); + public JLabel numCC = new JLabel(); + public JLabel numOther = new JLabel(); + public JLabel numMageJLabel = new JLabel(" "); + public JLabel numRangeJLabel = new JLabel(" "); + public JLabel numMeleeJLabel = new JLabel(" "); + public JLabel totalRiskLabel = new JLabel(" "); + public JLabel riskProtectingItem = new JLabel(" "); + public JLabel biggestItemLabel = new JLabel("Protected Item: "); + public JButton missingPlayers = new JButton("Show missing CC members"); + public JButton currentPlayers = new JButton("Show current CC members"); + public JLabel numBrews = new JLabel(); + @Inject + private JPanel pvpToolsPanel = new JPanel(new GridLayout(11, 1)); + private JPanel missingPlayersPanel = new JPanel(); + private JPanel currentPlayersPanel = new JPanel(); + + public static String htmlLabel(String key, String value) { + return "" + key + "" + value + ""; + } + + void init() { + this.setLayout(new BorderLayout()); + this.setBackground(ColorScheme.DARK_GRAY_COLOR); + this.setBorder(new EmptyBorder(10, 10, 10, 10)); + JPanel versionPanel = new JPanel(); + versionPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + versionPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + versionPanel.setLayout(new GridLayout(0, 1)); + JPanel riskPanel = new JPanel(); + riskPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + riskPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + riskPanel.setLayout(new GridLayout(0, 1)); + Font smallFont = FontManager.getRunescapeSmallFont(); + this.numCC.setText(PvpToolsPanel.htmlLabel("Friendly Player Count: ", "0")); + this.numOther.setText(PvpToolsPanel.htmlLabel("Other Player Count: ", "0")); + this.numBrews.setText(PvpToolsPanel.htmlLabel("Player brew count: ", "0")); + this.numMageJLabel.setText(PvpToolsPanel.htmlLabel("Enemies Praying Mage: ", "0")); + this.numMageJLabel.setFont(FontManager.getRunescapeFont()); + this.numRangeJLabel.setText(PvpToolsPanel.htmlLabel("Enemies Praying Range: ", "0")); + this.numRangeJLabel.setFont(FontManager.getRunescapeFont()); + this.numMeleeJLabel.setText(PvpToolsPanel.htmlLabel("Enemies Praying Melee: ", "0")); + this.numMeleeJLabel.setFont(FontManager.getRunescapeFont()); + this.totalRiskLabel.setText(PvpToolsPanel.htmlLabel("Total risk: ", "0")); + this.totalRiskLabel.setFont(FontManager.getRunescapeFont()); + this.riskProtectingItem.setText(PvpToolsPanel.htmlLabel("Risk Protecting Item: ", "0")); + this.riskProtectingItem.setFont(FontManager.getRunescapeFont()); + this.biggestItemLabel.setText("Most Valuable Item: "); + JLabel revision = new JLabel(); + revision.setFont(smallFont); + revision.setText("Oldschool revision: "); + JLabel launcher = new JLabel(PvpToolsPanel.htmlLabel("Launcher version: ", MoreObjects.firstNonNull(RuneLiteProperties.getLauncherVersion(), "Unknown"))); + launcher.setFont(smallFont); + this.loggedLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + this.loggedLabel.setFont(smallFont); + this.emailLabel.setForeground(Color.WHITE); + this.emailLabel.setFont(smallFont); + versionPanel.add(this.numCC); + versionPanel.add(this.numOther); + versionPanel.add(this.numBrews); + versionPanel.add(this.numMageJLabel); + versionPanel.add(this.numRangeJLabel); + versionPanel.add(this.numMeleeJLabel); + versionPanel.add(Box.createGlue()); + versionPanel.add(this.loggedLabel); + versionPanel.add(this.emailLabel); + riskPanel.add(this.totalRiskLabel); + riskPanel.add(this.riskProtectingItem); + riskPanel.add(this.biggestItemLabel); + this.add((Component)versionPanel, "North"); + this.add((Component)riskPanel, "Center"); + this.currentPlayers.setVisible(false); + this.missingPlayers.setVisible(false); + this.missingPlayersPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + this.missingPlayersPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + this.missingPlayersPanel.setLayout(new GridLayout(0, 1)); + this.missingPlayersPanel.add((Component)this.missingPlayers, "Last"); + this.missingPlayersPanel.add((Component)this.currentPlayers, "Last"); + this.add((Component)this.missingPlayersPanel, "Last"); + } + + public void disablePlayerCount() { + this.numOther.setText("Disabled"); + this.numCC.setText("Disabled"); + this.numCC.repaint(); + this.numOther.repaint(); + } + + public void disablePrayerCount() { + this.numMageJLabel.setText("disabled"); + this.numRangeJLabel.setText("disabled"); + this.numMeleeJLabel.setText("disabled"); + this.numMageJLabel.repaint(); + this.numRangeJLabel.repaint(); + this.numMeleeJLabel.repaint(); + } + + public void disableRiskCalculator() { + this.totalRiskLabel.setText("disabled"); + this.riskProtectingItem.setText("disabled"); + this.biggestItemLabel.setText("disabled"); + this.totalRiskLabel.repaint(); + this.riskProtectingItem.repaint(); + this.biggestItemLabel.repaint(); + } +} + 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 new file mode 100644 index 0000000000..4bf40b3a9a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/PvpToolsPlugin.java @@ -0,0 +1,475 @@ +package net.runelite.client.plugins.pvptools; + +import javax.inject.*; + +import com.google.inject.Inject; +import net.runelite.client.plugins.*; +import net.runelite.client.plugins.clanchat.*; +import java.util.function.*; +import java.awt.event.*; +import java.util.stream.*; +import java.util.concurrent.*; +import net.runelite.client.config.*; +import com.google.inject.*; +import net.runelite.client.ui.overlay.*; +import net.runelite.client.input.*; +import net.runelite.client.ui.*; +import java.awt.image.*; +import net.runelite.client.eventbus.*; +import org.apache.commons.lang3.*; +import net.runelite.api.events.*; +import net.runelite.client.util.*; +import net.runelite.api.*; +import net.runelite.client.game.*; +import java.util.*; + +@PluginDescriptor( + name = "PvP Tools", + description = "Enable the PvP Tools panel", + tags = { "panel", "pvp", "pk", "pklite" }, + type="PVP" +) +public class PvpToolsPlugin extends Plugin +{ + @Inject + PvpToolsOverlay pvpToolsOverlay; + boolean fallinHelperEnabled; + private PvpToolsPanel panel; + private MissingPlayersJFrame missingPlayersJFrame; + private CurrentPlayersJFrame currentPlayersJFrame; + private NavigationButton navButton; + private boolean attackHotKeyPressed; + private boolean hideAll; + @Inject + private ScheduledExecutorService executorService; + @Inject + private OverlayManager overlayManager; + @Inject + private Client client; + @Inject + private ItemManager itemManager; + private PvpToolsPlugin uhPvpToolsPlugin; + final ActionListener playersButtonActionListener; + final ActionListener currentPlayersActionListener; + @Inject + private ClientToolbar clientToolbar; + @Inject + private KeyManager keyManager; + @Inject + private PvpToolsConfig config; + @Inject + private PluginManager pluginManager; + @Inject + private ClanManager clanManager; + private ClanChatPlugin clanChatPlugin; + private final HotkeyListener hotkeyListener; + private final HotkeyListener attackOptionsHotKeyListener; + private int[] overheadCount; + private Comparator itemPriceComparator; + private String mtarget; + + public PvpToolsPlugin() { + this.fallinHelperEnabled = false; + this.uhPvpToolsPlugin = this; + this.playersButtonActionListener = new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + if (PvpToolsPlugin.this.missingPlayersJFrame != null) { + PvpToolsPlugin.this.missingPlayersJFrame.dispose(); + PvpToolsPlugin.this.missingPlayersJFrame = null; + PvpToolsPlugin.this.missingPlayersJFrame = new MissingPlayersJFrame(PvpToolsPlugin.this.client, PvpToolsPlugin.this.uhPvpToolsPlugin, PvpToolsPlugin.this.getMissingMembers()); + } + else { + PvpToolsPlugin.this.missingPlayersJFrame = new MissingPlayersJFrame(PvpToolsPlugin.this.client, PvpToolsPlugin.this.uhPvpToolsPlugin, PvpToolsPlugin.this.getMissingMembers()); + } + } + }; + this.currentPlayersActionListener = new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + if (PvpToolsPlugin.this.currentPlayersJFrame != null) { + PvpToolsPlugin.this.currentPlayersJFrame.dispose(); + PvpToolsPlugin.this.currentPlayersJFrame = null; + PvpToolsPlugin.this.currentPlayersJFrame = new CurrentPlayersJFrame(PvpToolsPlugin.this.client, PvpToolsPlugin.this.uhPvpToolsPlugin, PvpToolsPlugin.this.getCurrentMembers()); + } + else { + PvpToolsPlugin.this.currentPlayersJFrame = new CurrentPlayersJFrame(PvpToolsPlugin.this.client, PvpToolsPlugin.this.uhPvpToolsPlugin, PvpToolsPlugin.this.getCurrentMembers()); + } + } + }; + this.hotkeyListener = new HotkeyListener(() -> this.config.hotkey()) { + @Override + public void hotkeyPressed() { + PvpToolsPlugin.this.toggleFallinHelper(); + } + }; + this.attackOptionsHotKeyListener = new HotkeyListener(() -> this.config.attackOptionsHotkey()) { + long lastPress = 0L; + + @Override + public void keyPressed(final KeyEvent e) { + PvpToolsPlugin.this.attackHotKeyPressed = true; + } + + @Override + public void keyReleased(final KeyEvent e) { + PvpToolsPlugin.this.attackHotKeyPressed = (System.currentTimeMillis() - this.lastPress < 800L); + this.lastPress = System.currentTimeMillis(); + } + }; + this.overheadCount = new int[] { 0, 0, 0 }; + this.itemPriceComparator = new Comparator() { + @Override + public int compare(final Item o1, final Item o2) { + return PvpToolsPlugin.this.itemManager.getItemPrice(PvpToolsPlugin.this.itemManager.getItemComposition(o1.getId()).getPrice()) - PvpToolsPlugin.this.itemManager.getItemPrice(PvpToolsPlugin.this.itemManager.getItemComposition(o2.getId()).getPrice()); + } + }; + } + + public List getMissingMembers() { + CopyOnWriteArrayList ccMembers = ClanChatPlugin.getClanMembers(); + ArrayList missingMembers = new ArrayList(); + for (ClanMember clanMember : this.client.getClanMembers()) { + List arrayList; + if (Objects.isNull(clanMember) || (arrayList = ccMembers.stream().map(player -> Text.removeTags(Text.standardize(player.getName()))).collect(Collectors.toList())).contains(Text.removeTags(Text.standardize(clanMember.getUsername()))) || missingMembers.contains(clanMember.getUsername())) continue; + missingMembers.add("[W" + clanMember.getWorld() + "] - " + clanMember.getUsername()); + } + return missingMembers; + } + + public List getCurrentMembers() { + CopyOnWriteArrayList ccMembers = ClanChatPlugin.getClanMembers(); + ArrayList currentMembers = new ArrayList(); + for (ClanMember clanMember : this.client.getClanMembers()) { + List arrayList; + if (Objects.isNull(clanMember) || !(arrayList = ccMembers.stream().map(player -> Text.removeTags(Text.standardize(player.getName()))).collect(Collectors.toList())).contains(Text.removeTags(Text.standardize(clanMember.getUsername()))) || currentMembers.contains(clanMember.getUsername())) continue; + currentMembers.add(clanMember.getUsername()); + } + return currentMembers; + } + + @Provides + PvpToolsConfig config(final ConfigManager configManager) { + return configManager.getConfig(PvpToolsConfig.class); + } + + @Override + protected void startUp() throws Exception { + this.overlayManager.add(this.pvpToolsOverlay); + this.keyManager.registerKeyListener(this.hotkeyListener); + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "skull.png"); + (this.panel = new PvpToolsPanel()).init(); + this.navButton = NavigationButton.builder().tooltip("PvP Tools").icon(icon).priority(5).panel(this.panel).build(); + this.panel.missingPlayers.addActionListener(this.playersButtonActionListener); + this.panel.currentPlayers.addActionListener(this.currentPlayersActionListener); + this.clientToolbar.addNavigation(this.navButton); + this.keyManager.registerKeyListener(this.attackOptionsHotKeyListener); + if (this.config.missingPlayersEnabled()) { + this.panel.missingPlayers.setVisible(true); + } + if (this.config.currentPlayersEnabled()) { + this.panel.currentPlayers.setVisible(true); + } + } + + @Override + protected void shutDown() throws Exception { + this.overlayManager.remove(this.pvpToolsOverlay); + this.keyManager.unregisterKeyListener(this.hotkeyListener); + this.keyManager.unregisterKeyListener(this.attackOptionsHotKeyListener); + this.clientToolbar.removeNavigation(this.navButton); + } + + @Subscribe + public void onConfigChanged(final ConfigChanged configChanged) { + if (configChanged.getGroup().equals("pvptools")) { + final String key = configChanged.getKey(); + switch (key) { + case "countPlayers": { + if (this.config.countPlayers()) { + this.updatePlayers(); + } + if (!this.config.countPlayers()) { + this.panel.disablePlayerCount(); + break; + } + break; + } + case "countOverHeads": { + if (this.config.countOverHeads()) { + this.countOverHeads(); + } + if (!this.config.countOverHeads()) { + this.panel.disablePrayerCount(); + break; + } + break; + } + case "riskCalculator": { + if (this.config.riskCalculatorEnabled()) { + this.getCarriedWealth(); + } + if (!this.config.riskCalculatorEnabled()) { + this.panel.disableRiskCalculator(); + break; + } + break; + } + case "missingPlayers": { + if (this.config.missingPlayersEnabled()) { + this.panel.missingPlayers.setVisible(true); + break; + } + break; + } + case "currentPlayers": { + if (this.config.currentPlayersEnabled()) { + this.panel.currentPlayers.setVisible(true); + break; + } + break; + } + } + } + } + + @Subscribe + public void onItemContainerChanged(final ItemContainerChanged event) { + if (event.getItemContainer().equals(this.client.getItemContainer(InventoryID.INVENTORY)) && this.config.riskCalculatorEnabled()) { + this.getCarriedWealth(); + } + } + + @Subscribe + public void onGameStateChanged(final GameStateChanged event) { + if (event.getGameState().equals(GameState.LOGGED_IN) && this.config.riskCalculatorEnabled()) { + this.getCarriedWealth(); + } + if (event.getGameState().equals(GameState.LOGGED_IN) && this.config.countPlayers()) { + this.updatePlayers(); + } + } + + @Subscribe + public void onPlayerSpawned(final PlayerSpawned event) { + if (this.config.countPlayers() && PvPUtil.isAttackable(this.client, event.getPlayer())) { + this.updatePlayers(); + } + if (this.config.countOverHeads()) { + this.countOverHeads(); + } + } + + @Subscribe + public void onPlayerDespawned(final PlayerDespawned event) { + if (this.config.countPlayers() && PvPUtil.isAttackable(this.client, event.getPlayer())) { + this.updatePlayers(); + } + if (this.config.countOverHeads()) { + this.countOverHeads(); + } + } + + @Subscribe + public void onMenuEntryAdded(final MenuEntryAdded menuEntryAdded) { + if (!this.attackHotKeyPressed && (this.config.attackOptionsFriend() || this.config.attackOptionsClan() || this.config.levelRangeAttackOptions())) { + if (this.client.getGameState() != GameState.LOGGED_IN) { + return; + } + final Player[] players = this.client.getCachedPlayers(); + Player player = null; + final 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 ((this.attackHotKeyPressed && this.config.attackOptionsClan()) || this.config.attackOptionsFriend() || this.config.levelRangeAttackOptions()) { + if (this.config.attackOptionsFriend() && player.isFriend()) { + this.moveEntry(mtarget); + } + if (this.config.attackOptionsClan() && player.isClanMember()) { + this.moveEntry(mtarget); + } + if (this.config.levelRangeAttackOptions() && !PvPUtil.isAttackable(this.client, player)) { + this.moveEntry(mtarget); + } + } + } + } + + private void moveEntry(final String mtarget) { + this.mtarget = mtarget; + MenuEntry[] menuEntries = this.client.getMenuEntries(); + final MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; + String target = lastEntry.getTarget(); + final int idx = target.indexOf(62); + if (idx != -1) { + target = target.substring(idx + 1); + } + if (menuEntries[menuEntries.length - 1] != null) {} + if (lastEntry.getOption().contains("attack".toLowerCase())) { + menuEntries = ArrayUtils.remove(menuEntries, menuEntries.length - 1); + } + if (lastEntry.getOption().equals("Attack")) { + menuEntries = ArrayUtils.remove(menuEntries, menuEntries.length - 1); + } + this.client.setMenuEntries(menuEntries); + } + + @Subscribe + public void onFocusChanged(final FocusChanged focusChanged) { + if (!focusChanged.isFocused()) { + this.setAttackHotKeyPressed(false); + } + } + + private void toggleFallinHelper() { + if (!this.fallinHelperEnabled) { + this.client.setIsHidingEntities(true); + this.client.setPlayersHidden(true); + this.fallinHelperEnabled = true; + } + else { + this.client.setIsHidingEntities(false); + this.client.setPlayersHidden(false); + this.fallinHelperEnabled = false; + } + } + + private void updatePrayerNumbers() { + this.panel.numMageJLabel.setText(PvpToolsPanel.htmlLabel("Enemies Praying Mage: ", String.valueOf(this.overheadCount[0]))); + this.panel.numRangeJLabel.setText(PvpToolsPanel.htmlLabel("Enemies Praying Range: ", String.valueOf(this.overheadCount[1]))); + this.panel.numMeleeJLabel.setText(PvpToolsPanel.htmlLabel("Enemies Praying Melee: ", String.valueOf(this.overheadCount[2]))); + this.panel.numMageJLabel.repaint(); + this.panel.numRangeJLabel.repaint(); + this.panel.numMeleeJLabel.repaint(); + } + + private void updatePlayers() { + if (this.config.countPlayers()) { + int cc = 0; + int other = 0; + for (final Player p : this.client.getPlayers()) { + if (Objects.nonNull(p) && PvPUtil.isAttackable(this.client, p)) { + if (p.isClanMember()) { + ++cc; + } + else { + ++other; + } + } + } + this.panel.numOther.setText(PvpToolsPanel.htmlLabel("Other Player Count: ", String.valueOf(other))); + this.panel.numCC.setText(PvpToolsPanel.htmlLabel("Friendly Player Count: ", String.valueOf(cc))); + this.panel.numCC.repaint(); + this.panel.numOther.repaint(); + } + } + + private void countOverHeads() { + this.overheadCount = new int[] { 0, 0, 0 }; + for (final Player p : this.client.getPlayers()) { + if (Objects.nonNull(p) && PvPUtil.isAttackable(this.client, p) && !p.isClanMember() && p.getOverheadIcon() != null) { + switch (p.getOverheadIcon()) { + case MAGIC: { + final int[] overheadCount = this.overheadCount; + final int n = 0; + ++overheadCount[n]; + continue; + } + case RANGED: { + final int[] overheadCount2 = this.overheadCount; + final int n2 = 1; + ++overheadCount2[n2]; + continue; + } + case MELEE: { + final int[] overheadCount3 = this.overheadCount; + final int n3 = 2; + ++overheadCount3[n3]; + continue; + } + } + } + } + this.updatePrayerNumbers(); + } + + private void getCarriedWealth() { + if (!this.config.riskCalculatorEnabled()) { + return; + } + if (this.client.getItemContainer(InventoryID.EQUIPMENT) == null) { + return; + } + if (this.client.getItemContainer(InventoryID.INVENTORY).getItems() == null) { + return; + } + final Item[] items = ArrayUtils.addAll(Objects.requireNonNull(this.client.getItemContainer(InventoryID.EQUIPMENT)).getItems(), Objects.requireNonNull(this.client.getItemContainer(InventoryID.INVENTORY)).getItems()); + final TreeMap priceMap = new TreeMap(Comparator.comparingInt(Integer::intValue)); + int wealth = 0; + for (final Item i : items) { + int value = this.itemManager.getItemPrice(i.getId()) * i.getQuantity(); + final ItemComposition itemComposition = this.itemManager.getItemComposition(i.getId()); + if (!itemComposition.isTradeable() && value == 0) { + value = itemComposition.getPrice() * i.getQuantity(); + priceMap.put(value, i); + } + else { + value = this.itemManager.getItemPrice(i.getId()) * i.getQuantity(); + if (i.getId() > 0 && value > 0) { + priceMap.put(value, i); + } + } + wealth += value; + } + this.panel.totalRiskLabel.setText(PvpToolsPanel.htmlLabel("Total risk: ", StackFormatter.quantityToRSDecimalStack(wealth))); + this.panel.totalRiskLabel.repaint(); + int itemLimit = 0; + if (this.client.getLocalPlayer().getSkullIcon() != null && this.client.getLocalPlayer().getSkullIcon() == SkullIcon.SKULL) { + itemLimit = 1; + } + if (this.client.getLocalPlayer().getSkullIcon() == null) { + itemLimit = 4; + } + AsyncBufferedImage itemImage = null; + final NavigableMap descendingMap = priceMap.descendingMap(); + for (int j = 0; j < itemLimit; ++j) { + if (j == 0) { + if (!descendingMap.isEmpty()) { + itemImage = this.itemManager.getImage(descendingMap.pollFirstEntry().getValue().getId()); + } + } + else if (!descendingMap.isEmpty()) { + this.itemManager.getItemComposition(priceMap.descendingMap().pollFirstEntry().getValue().getId()).getName(); + } + } + this.panel.riskProtectingItem.setText(PvpToolsPanel.htmlLabel("Risk Protecting Item: ", StackFormatter.quantityToRSDecimalStack(descendingMap.keySet().stream().mapToInt(Integer::intValue).sum()))); + this.panel.riskProtectingItem.repaint(); + this.panel.biggestItemLabel.setText("Most Valuable Item: "); + if (itemImage != null) { + itemImage.addTo(this.panel.biggestItemLabel); + } + this.panel.biggestItemLabel.repaint(); + } + + boolean isAttackHotKeyPressed() { + return this.attackHotKeyPressed; + } + + void setAttackHotKeyPressed(final boolean attackHotKeyPressed) { + this.attackHotKeyPressed = attackHotKeyPressed; + } + + boolean isHideAll() { + return this.hideAll; + } + + void setHideAll(final boolean hideAll) { + this.hideAll = hideAll; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/skull.png b/runelite-client/src/main/java/net/runelite/client/plugins/pvptools/skull.png new file mode 100644 index 0000000000000000000000000000000000000000..09869ea0e1c2e15208ccac2839127b0c42ae7d6f GIT binary patch literal 448 zcmV;x0YCnUP)TQr$`dK^Q$VO1C|N+GS}7rM-cVqS3WUk6_YWWGKBv zP=V5Qm_+^r-C6VwYwjxU>1Jn}*_j}y10VbCH{YB&bG`xo2_lgT05Xcy-gf2_02nnq zzkX~22m!342(_??Q>A>C!F$!N z)r!mIl0gvA_kH@l&magmylqn>k%}mtAR+)rDKNdi!r}3$vDj`kAca756&ibzlFEf# zD1?Yf29p^ElNkWusL_Iy0;PO*9T70OUnioDFbs_#$#NlQ5u|kjm5=*f06?))g%ICf zs=D4ke0di}QDM~Uuw2N+Uj@CEtQ$n5UWcPz$0Bnbp#D|OFuPW7TJmf4CdU0P#{F)* zuJ`CQ>oKVlI%g-YS;U(SZ+?RE!F4s)#0*8M;c@zAT|uE(smA%i?v|}AIW^bmx=LNC qWwx%s<%7yyLvi}zUj2Ljuki)1TS~g;MmS3V0000!Whale Watchers", description = "A Plugin to save help whales in the wild", tags = { "whale watchers", "whale", "protect item", "warning", "pklite" }, enabledByDefault = true, hidden = false, developerPlugin = false, loadWhenOutdated = false) +@PluginDescriptor( + name = "Whale Watchers", + description = "A Plugin to save help whales in the wild", + tags = { "whale watchers", "whale", "protect item", "warning", "pklite" }, + type = "PVP", + enabledByDefault = false +) public class WhaleWatchersPlugin extends Plugin { @Inject diff --git a/whalewatchers/WhaleWatchersProtOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersProtOverlay.java similarity index 100% rename from whalewatchers/WhaleWatchersProtOverlay.java rename to runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersProtOverlay.java diff --git a/whalewatchers/WhaleWatchersSmiteableOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersSmiteableOverlay.java similarity index 100% rename from whalewatchers/WhaleWatchersSmiteableOverlay.java rename to runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersSmiteableOverlay.java 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 0020f384f4..c698e5894a 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 @@ -25,7 +25,8 @@ 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"}) + tags={"Wildy,", "Wilderness Location", "location", "loc", "pvp", "pklite"}, + type = "PVP") public class WildernessLocationsPlugin extends Plugin { @Inject diff --git a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java new file mode 100644 index 0000000000..3a842c227f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java @@ -0,0 +1,61 @@ +package net.runelite.client.util; + +import net.runelite.api.ItemComposition; +import java.util.TreeMap; +import java.util.Comparator; +import org.apache.commons.lang3.ArrayUtils; +import java.util.Objects; +import net.runelite.api.ItemContainer; +import net.runelite.api.Item; +import net.runelite.api.InventoryID; +import net.runelite.client.game.ItemManager; +import net.runelite.api.Player; +import net.runelite.api.Client; +import net.runelite.api.coords.WorldPoint; + +public class PvPUtil +{ + public PvPUtil() { + super(); + } + + public static int getWildernessLevelFrom(final WorldPoint point) { + final int x = point.getX(); + final int y = point.getY(); + final int underLevel = (y - 9920) / 8 + 1; + final int upperLevel = (y - 3520) / 8 + 1; + return (y > 6400) ? underLevel : upperLevel; + } + + public static boolean isAttackable(final Client c, final Player p) { + return Math.abs(c.getLocalPlayer().getCombatLevel() - p.getCombatLevel()) < getWildernessLevelFrom(c.getLocalPlayer().getWorldLocation()); + } + + public static int calculateRisk(final Client client, final ItemManager itemManager) { + if (client.getItemContainer(InventoryID.EQUIPMENT) == null) { + return 0; + } + if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null) { + return 0; + } + final Item[] items = (Item[])ArrayUtils.addAll(((ItemContainer)Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT))).getItems(), ((ItemContainer)Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY))).getItems()); + final TreeMap priceMap = new TreeMap(Comparator.comparingInt(Integer::intValue)); + int wealth = 0; + for (final 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(Integer.valueOf(value), i); + } + else { + value = itemManager.getItemPrice(i.getId()) * i.getQuantity(); + if (i.getId() > 0 && value > 0) { + priceMap.put(Integer.valueOf(value), i); + } + } + wealth += value; + } + return Integer.parseInt(StackFormatter.quantityToRSDecimalStack(priceMap.keySet().stream().mapToInt(Integer::intValue).sum())); + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/pvptools/skull.png b/runelite-client/src/main/resources/net/runelite/client/plugins/pvptools/skull.png new file mode 100644 index 0000000000000000000000000000000000000000..09869ea0e1c2e15208ccac2839127b0c42ae7d6f GIT binary patch literal 448 zcmV;x0YCnUP)TQr$`dK^Q$VO1C|N+GS}7rM-cVqS3WUk6_YWWGKBv zP=V5Qm_+^r-C6VwYwjxU>1Jn}*_j}y10VbCH{YB&bG`xo2_lgT05Xcy-gf2_02nnq zzkX~22m!342(_??Q>A>C!F$!N z)r!mIl0gvA_kH@l&magmylqn>k%}mtAR+)rDKNdi!r}3$vDj`kAca756&ibzlFEf# zD1?Yf29p^ElNkWusL_Iy0;PO*9T70OUnioDFbs_#$#NlQ5u|kjm5=*f06?))g%ICf zs=D4ke0di}QDM~Uuw2N+Uj@CEtQ$n5UWcPz$0Bnbp#D|OFuPW7TJmf4CdU0P#{F)* zuJ`CQ>oKVlI%g-YS;U(SZ+?RE!F4s)#0*8M;c@zAT|uE(smA%i?v|}AIW^bmx=LNC qWwx%s<%7yyLvi}zUj2Ljuki)1TS~g;MmS3V0000 Date: Sat, 20 Apr 2019 17:50:45 +0100 Subject: [PATCH 02/21] fkeyremapping --- .../fkeyremapping/fKeyRemappingConfig.java | 58 +++++++++++ .../fkeyremapping/fKeyRemappingListener.java | 95 +++++++++++++++++++ .../fkeyremapping/fKeyRemappingPlugin.java | 83 ++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingListener.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingConfig.java new file mode 100644 index 0000000000..cb66dc3e54 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingConfig.java @@ -0,0 +1,58 @@ +package net.runelite.client.plugins.fkeyremapping; + +import net.runelite.client.config.Config; + +import java.awt.event.KeyEvent; + +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Keybind; + +@ConfigGroup("fkeyremapping") +public interface fKeyRemappingConfig extends Config { + @ConfigItem( + position = 1, + keyName = "F1", + name = "F1 Key", + description = "The key which will replace F1." + ) + default Keybind f1() + { + return new Keybind(KeyEvent.VK_Q, 0); + } + + @ConfigItem( + position = 2, + keyName = "F2", + name = "F2 key", + description = "The key which will replace F2." + ) + default Keybind f2() + { + return new Keybind(KeyEvent.VK_W, 0); + } + + @ConfigItem( + position = 3, + keyName = "F3", + name = "F3 key", + description = "The key which will replace F3." + ) + default Keybind f3() + { + return new Keybind(KeyEvent.VK_E, 0); + } + + @ConfigItem( + position = 4, + keyName = "F4", + name = "F4 Key key", + description = "The key which will replace F4." + ) + default Keybind f4() + { + return new Keybind(KeyEvent.VK_R, 0); + } + + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingListener.java new file mode 100644 index 0000000000..6b2ac82124 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingListener.java @@ -0,0 +1,95 @@ +package net.runelite.client.plugins.fkeyremapping; + +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.util.Map; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.MouseAdapter; + +class fKeyRemappingListener extends MouseAdapter implements KeyListener +{ + @Inject + private fKeyRemappingPlugin plugin; + + @Inject + private fKeyRemappingConfig config; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + private final Map modified = new HashMap<>(); + + @Override + public void keyTyped(KeyEvent e) + { + } + + @Override + public void keyPressed(KeyEvent e) + { + if (client.getGameState() != GameState.LOGGED_IN || !plugin.chatboxFocused()) + { + return; + } + + + if (config.f1().matches(e)) + { + modified.put(e.getKeyCode(), KeyEvent.VK_F1); + e.setKeyCode(KeyEvent.VK_F1); + } + else if (config.f2().matches(e)) + { + modified.put(e.getKeyCode(), KeyEvent.VK_F2); + e.setKeyCode(KeyEvent.VK_F2); + } + else if (config.f3().matches(e)) + { + modified.put(e.getKeyCode(), KeyEvent.VK_F3); + e.setKeyCode(KeyEvent.VK_F3); + } + else if (config.f4().matches(e)) + { + modified.put(e.getKeyCode(), KeyEvent.VK_F4); + e.setKeyCode(KeyEvent.VK_F4); + } + + + } + + @Override + public void keyReleased(KeyEvent e) + { + if (client.getGameState() != GameState.LOGGED_IN || !plugin.chatboxFocused()) + { + return; + } + + modified.remove(e.getKeyCode()); + + if (config.f1().matches(e)) + { + e.setKeyCode(KeyEvent.VK_F1); + } + else if (config.f2().matches(e)) + { + e.setKeyCode(KeyEvent.VK_F2); + } + else if (config.f3().matches(e)) + { + e.setKeyCode(KeyEvent.VK_F3); + } + else if (config.f4().matches(e)) + { + e.setKeyCode(KeyEvent.VK_F4); + } + + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java new file mode 100644 index 0000000000..78199bfcc5 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java @@ -0,0 +1,83 @@ +package net.runelite.client.plugins.fkeyremapping; + +import com.google.inject.Provides; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.VarClientInt; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +@PluginDescriptor( + name = "fKeyRemapping", + description = "Used for interface hotkeys", + tags = {"hotkey", "remapping"}, + enabledByDefault = true +) +public class fKeyRemappingPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private KeyManager keyManager; + + @Inject + private fKeyRemappingListener inputListener; + + + @Override + protected void startUp() throws Exception + { + keyManager.registerKeyListener(inputListener); + + + } + + @Override + protected void shutDown() throws Exception + { + + + keyManager.unregisterKeyListener(inputListener); + } + + @Provides + fKeyRemappingConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(fKeyRemappingConfig.class); + } + + boolean chatboxFocused() + { + Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT); + if (chatboxParent == null || chatboxParent.getOnKeyListener() == null) + { + return false; + } + + // the search box on the world map can be focused, and chat input goes there, even + // though the chatbox still has its key listener. + Widget worldMapSearch = client.getWidget(WidgetInfo.WORLD_MAP_SEARCH); + if (worldMapSearch != null && client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) == 1) + { + return false; + } + + return true; + } + + + + + + + +} From 22ca3f43e4e7fe7fa8a320d405eb12e7a6ea97e5 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 18:51:11 +0100 Subject: [PATCH 03/21] additonal plugins --- .../groupitemlist/GroupItemListPlugin.java | 69 + .../plugins/groupitemlist/GroupedItem.java | 61 + .../rememberclan/RememberClanConfig.java | 48 + .../rememberclan/RememberClanPlugin.java | 78 + .../plugins/stronghold/StrongholdAnswer.java | 93 + .../plugins/stronghold/StrongholdPlugin.java | 107 + .../warindicators/WarIndicatorConfig.java | 164 + .../WarIndicatorMiniMapOverlay.java | 87 + .../warindicators/WarIndicatorOverlay.java | 101 + .../warindicators/WarIndicatorPlugin.java | 170 + .../warindicators/WarIndicatorService.java | 106 + .../plugins/zoneIndicators/MapLocations.java | 3479 +++++++++++++++++ .../zoneIndicators/ZoneIndicatorsConfig.java | 111 + .../ZoneIndicatorsMinimapOverlay.java | 116 + .../zoneIndicators/ZoneIndicatorsOverlay.java | 113 + .../zoneIndicators/ZoneIndicatorsPlugin.java | 297 ++ .../zoneIndicators/ZoneVisibility.java | 43 + 17 files changed, 5243 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdAnswer.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorMiniMapOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorService.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java new file mode 100644 index 0000000000..a01716d388 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java @@ -0,0 +1,69 @@ +package net.runelite.client.plugins.groupitemlist; + +import net.runelite.api.Client; +import net.runelite.api.MenuEntry; +import net.runelite.api.events.MenuOpened; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.LinkedHashMap; + +@PluginDescriptor( + name = "!Group Item List", + description = "Group the right click menu of a pile of items.", + tags = {"ground", "compress", "pile", "group"}, + enabledByDefault = false +) + +/** + * Main class of plugin - Groups duplicate right click menu options to singular entries with a quantity. + * + */ +public class GroupItemListPlugin extends Plugin { + + @Inject + private Client client; + + /** + * Fired on a right click menu opening. Count all menu entries and build a new list of entries + * displaying item quantities. + * + * @param menu Right click menu opened + */ + @Subscribe + public void onMenuOpened(MenuOpened menu) { + + LinkedHashMap entryCount = new LinkedHashMap<>(); + ArrayList temp = new ArrayList<>(); + MenuEntry[] updatedMenuEntries; + + // Iterate over menu entries + for (MenuEntry e : menu.getMenuEntries()) { + + // Increment the count if entry has been seen before + if (entryCount.containsKey(e)) { + entryCount.get(e).incrementCount(); + } + + // Store in map if entry has not been seen before + else { + entryCount.put(e, new GroupedItem(e)); + } + } + + // Create a list of updated menu entries from the map of GroupedItem + for (MenuEntry e : entryCount.keySet()) { + MenuEntry entry = entryCount.get(e).getEntry(); + temp.add(entry); + } + + // Parse to an array and set the new menu entries + updatedMenuEntries = temp.toArray(new MenuEntry[0]); + client.setMenuEntries(updatedMenuEntries); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java new file mode 100644 index 0000000000..b4fbbda77f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java @@ -0,0 +1,61 @@ +package net.runelite.client.plugins.groupitemlist; + +import net.runelite.api.MenuEntry; + +/** + * Object used to store a MenuEntry and the quantity. Updates the entry target if necessary + * e.g Shark to Shark [4]. + */ +public class GroupedItem { + + private int count; + private MenuEntry entry; + + /** + * Constructor for GroupedItem. + * + * @param entry The menu entry to be tracked for duplicates + */ + public GroupedItem(MenuEntry entry) { + this.entry = entry; + this.count = 1; + } + + /** + * Getter for the count. + * + * @return count + */ + public int getCount() { + return count; + } + + /** + * Getter for the menu entry, updates the target to reflect the quantity if more than 1 + * was found. + * + * @return Updated MenuEntry containing quantity + */ + public MenuEntry getEntry() { + if (count > 1) { + updateTarget(); + } + return entry; + } + + /** + * Updates the target of the menu entry to contain the quantity found. + */ + private void updateTarget() { + String target = entry.getTarget(); + target = target + " [" + count + "]"; + entry.setTarget(target); + } + + /** + * Increment count when duplicate entries are found. + */ + public void incrementCount() { + count += 1; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java new file mode 100644 index 0000000000..20775b1d35 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018, Infinitay + * Copyright (c) 2018, Shaun Dreclin + * + * 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.rememberclan; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("rememberclan") +public interface RememberClanConfig extends Config +{ + @ConfigItem( + position = 1, + keyName = "clanname", + name = "Clan Name", + description = "Clanname to always remember" + ) + default String clanname() + { + return ""; + } + + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java new file mode 100644 index 0000000000..be4d85e9fe --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, Infinitay + * Copyright (c) 2018, Shaun Dreclin + * 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.rememberclan; + +import com.google.inject.Provides; +import javax.inject.Inject; + +import net.runelite.api.*; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.vars.AccountType; +import net.runelite.client.chat.ChatColorType; +import net.runelite.client.chat.ChatMessageBuilder; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.chat.QueuedMessage; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +@PluginDescriptor( + name = "!Remember Clan", + description = "Remember a specific clan!", + enabledByDefault = false +) +public class RememberClanPlugin extends Plugin +{ + + @Inject + private Client client; + + @Inject + private RememberClanConfig config; + + @Inject + private ChatMessageManager chatMessageManager; + + private boolean loggingIn; + + @Provides + RememberClanConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(RememberClanConfig.class); + } + + @Subscribe + public void onGameTick(GameTick event) + { + client.setVar(VarClientStr.RECENT_CLAN_CHAT,config.clanname()); + + } + + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdAnswer.java b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdAnswer.java new file mode 100644 index 0000000000..2146cd8708 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdAnswer.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019, FlaxOnEm + * 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.stronghold; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.runelite.api.widgets.Widget; + +import java.util.HashMap; +import java.util.Map; + +@Getter +@RequiredArgsConstructor +enum StrongholdAnswer { + PAIR_0("To pass you must answer me this: Hey adventurer!
You've been randomly selected for a prize of 1 year of
free membership! I'm just going to need some of your
account details so I can put it on your account!", "No way! I'm reporting you to Jagex!"), + PAIR_1("To pass you must answer me this: Can I leave my
account logged in while I'm out of the room?", "No."), + PAIR_2("To pass you must answer me this: How do I remove a
hijacker from my account?", "Use the Account Recovery System."), + PAIR_3("To pass you must answer me this: What do you do if
someone asks you for your password or bank PIN to
make you a player moderator?", "Don't give them the information and send an 'Abuse report'."), + PAIR_4("To pass you must answer me this: You're watching a
stream by someone claiming to be Jagex offering double
xp. What do you do?", "Report the stream as a scam. Real Jagex streams have a 'verified' mark."), + PAIR_5("To pass you must answer me this: My friend asks me
for my password so that he can do a difficult quest for
me. Do I give it to them?", "Don't give them my password."), + PAIR_6("To pass you must answer me this: Who can I give my
password to?", "Nobody."), + PAIR_7("To pass you must answer me this: How do I set up
two-factor authentication for my Old School RuneScape
account?", "Through account settings on oldschool.runescape.com."), + PAIR_8("To pass you must answer me this: What is an example
of a good bank PIN?", "The birthday of a famous person or event."), + PAIR_9("To pass you must answer me this: What should you do
if your real-life friend asks for your password so he
can check your stats?", "Don't give out your password to anyone. Not even close friends."), + PAIR_A("To pass you must answer me this: A player tells you to
search for a video online, click the link in the description
and comment on the forum post to win a cash prize.
What do you do?", "Report the player for phishing."), + PAIR_B("To pass you must answer me this: You have been
offered an opportunity to check out a free giveaway or
double XP signup via email or in game chat. What
should I do?", "Report the incident and do not click any links."), + PAIR_C("To pass you must answer me this: How do I set a
bank PIN?", "Talk to any banker."), + PAIR_D("To pass you must answer me this: What do I do if a
moderator asks me for my account details?", "Politely tell them no and then use the 'Report Abuse' button."), + PAIR_E("To pass you must answer me this: You are part way
through the Stronghold of Security when you have to
answer another question. After you answer the question,
you should...", "Read the text and follow the advice given."), + PAIR_F("To pass you must answer me this: Will Jagex prevent
me from saying my PIN in game?", "No."), + PAIR_G("that sound?", "No way! You'll just take my gold for your own! Reported!"), + PAIR_H("To pass you must answer me this: What should I do if
I receive an email asking me to verify my identity or
Account details due to suspicious activity?", "Don't click any links, forward the email to reportphishing@jagex.com."), + PAIR_I("To pass you must answer me this: A website claims that
they can make me a player moderator. What should I
do?", "Inform Jagex by emailing reportphishing@jagex.com."), + PAIR_J("react?", "Don't share your information and report the player."), + PAIR_K("To pass you must answer me this: What do you do if
someone asks you for your password or bank PIN to
make you a member for free?", "Don't tell them anything and click the 'Report Abuse' button."), + PAIR_L("To pass you must answer me this: Is it OK to buy an
Old School RuneScape account?", "No, you should never buy an account."), + PAIR_M("To pass you must answer me this: You have been
offered an opportunity to check out a free giveaway or
double XP signup via social media or stream. What
should I do?", "Report the incident and do not click any links."), + PAIR_N("To pass you must answer me this: Where is it safe to
use my Old School RuneScape password?", "Only on the Old School RuneScape website."), + PAIR_O("To pass you must answer me this: What is the best
way to secure your account?", "Authenticator and two-step login on my registered email."), + PAIR_P("To pass you must answer me this: Who is it ok to
share my account with?", "Nobody."), + PAIR_Q("To pass you must answer me this: What should you do
if another player messages you recommending a website
to purchase items and/or gold?", "Do not visit the website and report the player who messaged you."), + PAIR_R("To pass you must answer me this: Whose responsibility
is it to keep your account secure?", "Me."), + PAIR_S("To pass you must answer me this: Is it safe to pay
someone to level your account?", "No, you should never allow anyone to level your account."), + PAIR_T("To pass you must answer me this: What do I do if my
account is compromised?", "Secure my device and reset my password."), + PAIR_U("respond?", "Decline the offer and report that player."), + PAIR_V("To pass you must answer me this: A player says that
Jagex prevents you from saying your password
backwards in game. What do you do?", "Don't type in my password backwards and report the player."), + PAIR_W("To pass you must answer me this: What do I do if I
think I have a keylogger or virus?", "Virus scan my device then change my password."), + PAIR_X("To pass you must answer me this: What is the best
security step you can take to keep your registered
email secure?", "Set up 2 step authentication with my email provider."); + + static final Map MATCHES = new HashMap<>(); + + static { + for (StrongholdAnswer strongholdAnswer : StrongholdAnswer.values()) { + MATCHES.put(strongholdAnswer.question, strongholdAnswer.answer); + } + } + + private final String question; + private final String answer; + + static Widget findCorrect(final String question, final Widget[] widgets) { + final String s = MATCHES.get(question); + + for (Widget widget: widgets) { + if (widget != null && widget.getText().equals(s)) + return widget; + } + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java new file mode 100644 index 0000000000..d1de9d419b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019, FlaxOnEm + * 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.stronghold; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.events.ClientTick; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.ColorUtil; + +import javax.inject.Inject; +import java.awt.Color; + +@PluginDescriptor( + name = "!Stronghold", + description = "Highlights the correct answer to Stronghold of Security questions", + tags = {"stronghold", "security", "overlay", "answer", "highlight"} +) +@Slf4j +public class StrongholdPlugin extends Plugin { + private static final Color ANSWER_COLOR = new Color(230, 0, 230); + + @Inject + private Client client; + + private boolean queueNPCDialogue; + private boolean queueNPCOption; + private String questionCache; + + @Subscribe + public void onWidgetLoaded(WidgetLoaded widgetLoaded) { + switch (widgetLoaded.getGroupId()) { + case WidgetID.DIALOG_NPC_GROUP_ID: + queueNPCDialogue = true; + break; + case WidgetID.DIALOG_OPTION_GROUP_ID: + queueNPCOption = true; + break; + } + } + + @Subscribe + public void onClientTick(ClientTick t) { + if (queueNPCDialogue) { + queueNPCDialogue = false; + onNPCDialogue(); + } + if (queueNPCOption) { + queueNPCOption = false; + onNPCOption(); + } + } + + private void onNPCDialogue() { + final Widget debugWidget = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT); + final String npcText = debugWidget.getText(); + if (StrongholdAnswer.MATCHES.containsKey(npcText)) + questionCache = npcText; + } + + private void onNPCOption() { + if (questionCache == null) + return; + + final Widget optionsWidget = client.getWidget(WidgetInfo.DIALOG_OPTION); + if (optionsWidget == null) + return; + + final Widget[] widgets = optionsWidget.getParent().getChildren(); + + final Widget answerWidget = StrongholdAnswer.findCorrect(questionCache, widgets); + questionCache = null; + if (answerWidget == null) + return; + + final String answerText = answerWidget.getText(); + answerWidget.setText(ColorUtil.wrapWithColorTag(answerText, ANSWER_COLOR)); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorConfig.java new file mode 100644 index 0000000000..c665baaa70 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorConfig.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018, Andrew EP | ElPinche256 + * 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.warindicators; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("warIndicators") + +public interface WarIndicatorConfig extends Config +{ + @ConfigItem( + position = 0, + keyName = "highLightCallers", + name = "Highlight Callers", + description = "Highlight listed caller(s)" + ) + default boolean highLightCallers() + { + return true; + } + + @ConfigItem( + position = 1, + keyName = "callerColor", + name = "Caller(s) Color", + description = "Color to highlight caller's name" + ) + default Color getCallerColor() + { + return new Color(36, 255, 237); + } + + @ConfigItem( + position = 2, + keyName = "callerMinimap", + name = "Callers on Minimap", + description = "Show your caller(s) on the minimap" + ) + default boolean callerMinimap() + { + return false; + } + + + @ConfigItem( + position = 3, + keyName = "callerTile", + name = "Show Caller's Tile", + description = "Show the tile your target is standing on" + ) + default boolean callerTile() + { + return false; + } + + @ConfigItem( + position = 4, + keyName = "activeCallers", + name = "Callers", + description = "Adds a user to your caller list. Format: (caller), (caller)" + ) + default String getActiveCallers() + { + return ""; + } + + @ConfigItem( + position = 5, + keyName = "activeCallers", + name = "", + description = "" + ) + void setActiveCallers(String key); + + + @ConfigItem( + position = 6, + keyName = "highlightSnipes", + name = "Highlight Targets", + description = "Highlight listed target(s)" + ) + default boolean highlightSnipes() + { + return true; + } + + @ConfigItem( + position = 7, + keyName = "snipeColor", + name = "Target(s) Color", + description = "Color to highlight target name" + ) + default Color getSnipeColor() + { + return new Color(255, 0, 0); + } + + @ConfigItem( + position = 8, + keyName = "snipeMinimap", + name = "Targets on Minimap", + description = "Show your target on the minimap" + ) + default boolean snipeMinimap() + { + return false; + } + + @ConfigItem( + position = 9, + keyName = "snipeTile", + name = "Show Target's Tile", + description = "Show the tile your target is standing on" + ) + default boolean snipeTile() + { + return false; + } + + @ConfigItem( + position = 10, + keyName = "targetedSnipes", + name = "Targets", + description = "Adds a user to your snipe list. Format: (target), (target)" + ) + default String getTargetedSnipes() + { + return ""; + } + + @ConfigItem( + position = 11, + keyName = "targetedSnipes", + name = "", + description = "" + ) + + void setTargetedSnipe(String key); +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorMiniMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorMiniMapOverlay.java new file mode 100644 index 0000000000..d7fa0cc92a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorMiniMapOverlay.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, Andrew EP | ElPinche256 + * 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.warindicators; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import javax.inject.Singleton; +import net.runelite.api.Player; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; +import org.apache.commons.lang3.ArrayUtils; + +@Singleton +public class WarIndicatorMiniMapOverlay extends Overlay +{ + private final WarIndicatorService warIndicatorService; + private final WarIndicatorConfig config; + + @Inject + private WarIndicatorMiniMapOverlay(WarIndicatorConfig config, WarIndicatorService warIndicatorService) + { + this.config = config; + this.warIndicatorService = warIndicatorService; + setLayer(OverlayLayer.ABOVE_WIDGETS); + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGH); + } + + @Override + public Dimension render(Graphics2D graphics) + { + warIndicatorService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color)); + return null; + } + + private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color) + { + final String name = actor.getName().replace('\u00A0', ' '); + final net.runelite.api.Point minimapLocation = actor.getMinimapLocation(); + + String[] callers = config.getActiveCallers().split(", "); + String[] targets = config.getTargetedSnipes().split(", "); + + if (config.callerMinimap() && ArrayUtils.contains(callers, actor.getName())) + { + if (minimapLocation != null) + { + OverlayUtil.renderTextLocation(graphics, minimapLocation, name, color); + } + } + + if (config.snipeMinimap() && ArrayUtils.contains(targets, actor.getName())) + { + if (minimapLocation != null) + { + OverlayUtil.renderTextLocation(graphics, minimapLocation, name, color); + } + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorOverlay.java new file mode 100644 index 0000000000..7ca7cc20c0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorOverlay.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, Andrew EP | ElPinche256 + * 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.warindicators; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Polygon; +import javax.inject.Inject; +import javax.inject.Singleton; +import org.apache.commons.lang3.ArrayUtils; +import net.runelite.api.Player; +import net.runelite.api.Point; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; + +@Singleton +public class WarIndicatorOverlay extends Overlay +{ + private final WarIndicatorService warIndicatorService; + private final WarIndicatorConfig config; + + @Inject + private WarIndicatorOverlay(WarIndicatorConfig config, WarIndicatorService warIndicatorService) + { + this.config = config; + this.warIndicatorService = warIndicatorService; + setLayer(OverlayLayer.ABOVE_SCENE); + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGH); + } + + @Override + public Dimension render(Graphics2D graphics) + { + warIndicatorService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color)); + return null; + } + + private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color) + { + if (!config.highlightSnipes() && !config.highLightCallers()) + { + return; + } + + Polygon poly = actor.getCanvasTilePoly(); + String[] callers = config.getActiveCallers().split(", "); + String[] targets = config.getTargetedSnipes().split(", "); + + if (config.callerTile() && ArrayUtils.contains(callers, actor.getName())) + { + if (poly != null) + { + OverlayUtil.renderPolygon(graphics, poly, color); + } + } + + if (config.snipeTile() && ArrayUtils.contains(targets, actor.getName())) + { + if (poly != null) + { + OverlayUtil.renderPolygon(graphics, poly, color); + } + } + + String name = actor.getName().replace('\u00A0', ' '); + int offset = actor.getLogicalHeight() + 40; + Point textLocation = actor.getCanvasTextLocation(graphics, name, offset); + + if (textLocation != null) + { + OverlayUtil.renderTextLocation(graphics, textLocation, name, color); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java new file mode 100644 index 0000000000..af7cf94ab7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2018, Andrew EP | ElPinche256 + * 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.warindicators; + +import com.google.common.collect.Sets; +import com.google.common.eventbus.Subscribe; +import com.google.inject.Provides; +import java.awt.Color; +import java.util.Collection; +import javax.inject.Inject; +import org.apache.commons.lang3.ArrayUtils; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.FOLLOW; +import static net.runelite.api.MenuAction.ITEM_USE_ON_PLAYER; +import static net.runelite.api.MenuAction.PLAYER_EIGTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FIFTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FIRST_OPTION; +import static net.runelite.api.MenuAction.PLAYER_FOURTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SECOND_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SEVENTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_SIXTH_OPTION; +import static net.runelite.api.MenuAction.PLAYER_THIRD_OPTION; +import static net.runelite.api.MenuAction.SPELL_CAST_ON_PLAYER; +import static net.runelite.api.MenuAction.TRADE; +import net.runelite.api.MenuEntry; +import net.runelite.api.Player; +import net.runelite.api.events.MenuEntryAdded; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "!War", + description = "War War War.", + tags = {"skill", "total", "max", "PVP"}, + enabledByDefault = false +) +public class WarIndicatorPlugin extends Plugin +{ + @Inject + private OverlayManager overlayManager; + + @Inject + private WarIndicatorConfig config; + + @Inject + private WarIndicatorOverlay warIndicatorOverlay; + + @Inject + private WarIndicatorMiniMapOverlay warIndicatorMiniMapOverlay; + + @Inject + private Client client; + + @Provides + WarIndicatorConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(WarIndicatorConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(warIndicatorOverlay); + overlayManager.add(warIndicatorMiniMapOverlay); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(warIndicatorOverlay); + overlayManager.remove(warIndicatorMiniMapOverlay); + } + + @Subscribe + public void onMenuEntryAdd(MenuEntryAdded menuEntryAdded) + { + int type = menuEntryAdded.getType(); + + if (type >= 2000) + { + type -= 2000; + } + + int identifier = menuEntryAdded.getIdentifier(); + if (type == FOLLOW.getId() || type == TRADE.getId() + || type == SPELL_CAST_ON_PLAYER.getId() + || type == ITEM_USE_ON_PLAYER.getId() + || type == PLAYER_FIRST_OPTION.getId() + || type == PLAYER_SECOND_OPTION.getId() + || type == PLAYER_THIRD_OPTION.getId() + || type == PLAYER_FOURTH_OPTION.getId() + || type == PLAYER_FIFTH_OPTION.getId() + || type == PLAYER_SIXTH_OPTION.getId() + || type == PLAYER_SEVENTH_OPTION.getId() + || type == PLAYER_EIGTH_OPTION.getId()) + { + Player[] players = client.getCachedPlayers(); + Player player = null; + String player2 = null; + + String[] callers = config.getActiveCallers().split(", "); + String[] targets = config.getTargetedSnipes().split(", "); + + if (identifier >= 0 && identifier < players.length) + { + player = players[identifier]; + player2 = players[identifier].getName(); + } + + if (player == null) + { + return; + } + + Color color = null; + + if (config.highLightCallers() && ArrayUtils.contains(callers, player2)) + { + color = config.getCallerColor(); + } + + if (config.highlightSnipes() && ArrayUtils.contains(targets, player2)) + { + color = config.getSnipeColor(); + } + + if (color != null) + { + MenuEntry[] menuEntries = client.getMenuEntries(); + MenuEntry lastEntry = menuEntries[menuEntries.length - 1]; + String target = lastEntry.getTarget(); + + int idx = target.indexOf('>'); + if (idx != -1) + { + target = target.substring(idx + 1); + } + + lastEntry.setTarget("" + target); + client.setMenuEntries(menuEntries); + } + + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorService.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorService.java new file mode 100644 index 0000000000..cb6c8127b5 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorService.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018, Andrew EP | ElPinche256 + * 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.warindicators; + +import net.runelite.api.Client; +import net.runelite.api.Player; +import javax.inject.Inject; +import javax.inject.Singleton; +import java.awt.*; +import java.util.function.BiConsumer; + +@Singleton +public class WarIndicatorService +{ + private final Client client; + private final WarIndicatorConfig config; + + @Inject + private WarIndicatorService(Client client, WarIndicatorConfig config) + { + this.config = config; + this.client = client; + } + + public void forEachPlayer(final BiConsumer consumer) + { + if (!config.highlightSnipes() && !config.highLightCallers()) + { + return; + } + + if (config.highlightSnipes()) + { + for (Player player : client.getPlayers()) + { + if (player == null || player.getName() == null) + { + continue; + } + + String[] targets = config.getTargetedSnipes().split(", "); + + if (targets == null) + { + return; + } + + for (int i = 0; i < targets.length; i++) + { + if (player.getName().equalsIgnoreCase(targets[i])) + { + consumer.accept(player, config.getSnipeColor()); + } + } + } + } + + if (config.highLightCallers()) + { + for (Player player : client.getPlayers()) + { + if (player == null || player.getName() == null) + { + continue; + } + + String[] callers = config.getActiveCallers().split(", "); + + if (callers == null) + { + return; + } + + for (int i = 0; i < callers.length; i++) + { + if (player.getName().equalsIgnoreCase(callers[i])) + { + consumer.accept(player, config.getCallerColor()); + } + } + } + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java new file mode 100644 index 0000000000..81e8e0f527 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java @@ -0,0 +1,3479 @@ +/* + * Copyright (c) 2018, Woox + * 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.zoneIndicators; + +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Area; +import java.util.ArrayList; +import java.util.List; +import net.runelite.api.Constants; + +public class MapLocations +{ + private static final List[] MULTICOMBAT = new List[Constants.MAX_Z]; + private static final List[] NOT_MULTICOMBAT = new List[Constants.MAX_Z]; + private static final List[] ROUGH_WILDERNESS = new List[Constants.MAX_Z]; + private static final List[] DEADMAN_SAFE_ZONES = new List[Constants.MAX_Z]; + private static final List[] PVP_WORLD_SAFE_ZONES = new List[Constants.MAX_Z]; + + private static Area getArea(List shapes) + { + Area area = new Area(); + for (Shape shape : shapes) + { + area.add(new Area(shape)); + } + return area; + } + + private static Area getArea(List shapes, Rectangle view) + { + Area area = new Area(); + for (Shape shape : shapes) + { + if (shape.intersects(view)) + { + area.add(new Area(shape)); + } + } + return area; + } + + public static Area getMulticombat(int plane) + { + Area area = getArea(MULTICOMBAT[plane]); + area.subtract(getArea(NOT_MULTICOMBAT[plane])); + return area; + } + + public static Area getMulticombat(Rectangle view, int plane) + { + Area area = getArea(MULTICOMBAT[plane], view); + area.subtract(getArea(NOT_MULTICOMBAT[plane], view)); + return area; + } + + public static Area getRoughWilderness(int plane) + { + return getArea(ROUGH_WILDERNESS[plane]); + } + + public static Area getRoughWilderness(Rectangle view, int plane) + { + return getArea(ROUGH_WILDERNESS[plane], view); + } + + public static Area getDeadmanSafeZones(int plane) + { + return getArea(DEADMAN_SAFE_ZONES[plane]); + } + + public static Area getDeadmanSafeZones(Rectangle view, int plane) + { + return getArea(DEADMAN_SAFE_ZONES[plane], view); + } + + public static Area getPvpSafeZones(int plane) + { + return getArea(PVP_WORLD_SAFE_ZONES[plane]); + } + + public static Area getPvpSafeZones(Rectangle view, int plane) + { + return getArea(PVP_WORLD_SAFE_ZONES[plane], view); + } + + static + { + for (int i = 0; i < MULTICOMBAT.length; i++) + { + MULTICOMBAT[i] = new ArrayList<>(); + } + for (int i = 0; i < NOT_MULTICOMBAT.length; i++) + { + NOT_MULTICOMBAT[i] = new ArrayList<>(); + } + for (int i = 0; i < ROUGH_WILDERNESS.length; i++) + { + ROUGH_WILDERNESS[i] = new ArrayList<>(); + } + for (int i = 0; i < DEADMAN_SAFE_ZONES.length; i++) + { + DEADMAN_SAFE_ZONES[i] = new ArrayList<>(); + } + for (int i = 0; i < PVP_WORLD_SAFE_ZONES.length; i++) + { + PVP_WORLD_SAFE_ZONES[i] = new ArrayList<>(); + } + + defineMulticombatAreas(); + defineDeadmanSafeZones(); + definePvpSafeZones(); + defineWilderness(); + } + + private static void defineMulticombatAreas() + { + // Main Wilderness + addPolygonOnPlane(MULTICOMBAT, 0, + 3200, 3968, + 3392, 3968, + 3392, 3840, + 3328, 3840, + 3328, 3520, + 3136, 3520, + 3136, 3648, + 3192, 3648, + 3192, 3752, + 3152, 3752, + 3152, 3840, + 3136, 3840, + 3136, 3872, + 3112, 3872, + 3112, 3880, + 3072, 3880, + 3072, 3896, + 3048, 3896, + 3048, 3872, + 3056, 3872, + 3056, 3864, + 3048, 3864, + 3048, 3856, + 3008, 3856, + 3008, 3904, + 3200, 3904); + + // South of wildy agility training arena + addPolygonOnPlane(MULTICOMBAT, 0, + 2984, 3928, + 3008, 3928, + 3008, 3912, + 2984, 3912); + + // Wildy zamorak temple + addPolygonOnPlane(MULTICOMBAT, 0, + 2944, 3832, + 2960, 3832, + 2960, 3816, + 2944, 3816); + + // Wildy bandit camp + addPolygonOnPlane(MULTICOMBAT, 0, + 3008, 3712, + 3072, 3712, + 3072, 3600, + 3008, 3600); + + // Chaos temple north of Falador + addPolygonOnPlane(MULTICOMBAT, 0, + 2928, 3520, + 2944, 3520, + 2944, 3512, + 2928, 3512); + + // Burthorpe + addPolygonOnPlane(MULTICOMBAT, 0, + 2880, 3544, + 2904, 3544, + 2904, 3520, + 2880, 3520); + + // White Wolf Mountain + addPolygonOnPlane(MULTICOMBAT, 0, + 2880, 3520, + 2816, 3520, + 2816, 3456, + 2880, 3456); + + // Death Plateu + addPolygonOnPlane(MULTICOMBAT, 0, + 2848, 3608, + 2880, 3608, + 2880, 3600, + 2848, 3600); + + // Trollheim/Godwars + addPolygonOnPlane(MULTICOMBAT, 0, + 2880, 3776, + 2912, 3776, + 2912, 3696, + 2920, 3696, + 2920, 3688, + 2896, 3688, + 2896, 3696, + 2880, 3696, + 2880, 3728, + 2888, 3728, + 2888, 3744, + 2880, 3744); + + // Northen Rellekka + addPolygonOnPlane(MULTICOMBAT, 0, + 2656, 3736, + 2704, 3736, + 2704, 3728, + 2712, 3728, + 2712, 3736, + 2736, 3736, + 2736, 3712, + 2656, 3712); + + // Northen Fremennik Isles + addPolygonOnPlane(MULTICOMBAT, 0, + 2304, 3904, + 2432, 3904, + 2432, 3840, + 2368, 3840, + 2368, 3816, + 2352, 3816, + 2352, 3824, + 2304, 3824); + + // Pirates Cove + addPolygonOnPlane(MULTICOMBAT, 0, + 2176, 3840, + 2240, 3840, + 2240, 3776, + 2176, 3776); + + // Lunar Isle + addPolygonOnPlane(MULTICOMBAT, 0, + 2048, 3968, + 2176, 3968, + 2176, 3840, + 2048, 3840); + + // Piscatoris Fishing Colony + addPolygonOnPlane(MULTICOMBAT, 0, + 2304, 3712, + 2368, 3712, + 2368, 3648, + 2304, 3648); + + // Ranging Guild + addPolygonOnPlane(MULTICOMBAT, 0, + 2656, 3448, + 2680, 3448, + 2680, 3440, + 2688, 3440, + 2688, 3416, + 2680, 3416, + 2680, 3408, + 2656, 3408, + 2656, 3416, + 2648, 3416, + 2648, 3440, + 2656, 3440); + + // Necromancer house, southeast of Ardy + addPolygonOnPlane(MULTICOMBAT, 0, + 2656, 3256, + 2680, 3256, + 2680, 3216, + 2664, 3216, + 2664, 3232, + 2656, 3232); + + // Battlefield noth of Tree Gnome Village + addPolygonOnPlane(MULTICOMBAT, 0, + 2504, 3248, + 2544, 3248, + 2544, 3232, + 2552, 3232, + 2552, 3208, + 2504, 3208); + + // Castle Wars + addPolygonOnPlane(MULTICOMBAT, 0, + 2368, 3136, + 2432, 3136, + 2432, 3072, + 2368, 3072); + + // Jiggig + addPolygonOnPlane(MULTICOMBAT, 0, + 2456, 3056, + 2496, 3056, + 2496, 3032, + 2456, 3032); + + // East feldip hills, near rantz + addPolygonOnPlane(MULTICOMBAT, 0, + 2648, 2976, + 2656, 2976, + 2656, 2952, + 2648, 2952); + + // Ape Atoll + addPolygonOnPlane(MULTICOMBAT, 0, + 2688, 2816, + 2816, 2816, + 2816, 2688, + 2688, 2688); + + // Pest Control + addPolygonOnPlane(MULTICOMBAT, 0, + 2624, 2624, + 2688, 2624, + 2688, 2560, + 2624, 2560); + + // Desert Bandit Camp + addPolygonOnPlane(MULTICOMBAT, 0, + 3152, 3000, + 3192, 3000, + 3192, 2960, + 3152, 2960); + + // Al Kharid + addPolygonOnPlane(MULTICOMBAT, 0, + 3264, 3200, + 3328, 3200, + 3328, 3136, + 3264, 3136); + + // Wizards Tower + addPolygonOnPlane(MULTICOMBAT, 0, + 3094, 3176, + 3126, 3176, + 3126, 3144, + 3094, 3144); + + // Draynor Village + addPolygonOnPlane(MULTICOMBAT, 0, + 3112, 3264, + 3136, 3264, + 3136, 3232, + 3104, 3232, + 3104, 3256, + 3112, 3256); + + // Falador + addPolygonOnPlane(MULTICOMBAT, 0, + 2944, 3456, + 3008, 3456, + 3008, 3328, + 3016, 3328, + 3016, 3304, + 2944, 3304); + + // Southwest fally castle isn't multicombat downstairs + addPolygonOnPlane(NOT_MULTICOMBAT, 0, + 2968, 3336, + 2968, 3328, + 2960, 3328, + 2960, 3336); + + // Barbarian Village + addPolygonOnPlane(MULTICOMBAT, 0, + 3072, 3456, + 3136, 3456, + 3136, 3392, + 3048, 3392, + 3048, 3408, + 3056, 3408, + 3056, 3440, + 3064, 3440, + 3064, 3448, + 3072, 3448); + + // Ammoniate crabs at northwest fossil island + addPolygonOnPlane(MULTICOMBAT, 0, + 3648, 3885, + 3663, 3885, + 3663, 3882, + 3664, 3882, + 3664, 3872, + 3663, 3872, + 3663, 3868, + 3648, 3868); + + // Ammoniate crabs at north fossil island + addPolygonOnPlane(MULTICOMBAT, 0, + 3680, 3904, + 3744, 3904, + 3744, 3856, + 3756, 3856, + 3756, 3852, + 3755, 3852, + 3755, 3851, + 3754, 3851, + 3754, 3850, + 3751, 3850, + 3751, 3849, + 3750, 3849, + 3750, 3848, + 3749, 3848, + 3749, 3847, + 3748, 3847, + 3748, 3846, + 3747, 3846, + 3747, 3845, + 3746, 3845, + 3746, 3844, + 3742, 3844, + 3742, 3845, + 3740, 3845, + 3740, 3844, + 3732, 3844, + 3732, 3843, + 3730, 3843, + 3730, 3842, + 3724, 3842, + 3724, 3843, + 3717, 3843, + 3717, 3842, + 3712, 3842, + 3712, 3846, + 3710, 3846, + 3710, 3847, + 3709, 3847, + 3709, 3848, + 3708, 3848, + 3708, 3859, + 3709, 3859, + 3709, 3860, + 3710, 3860, + 3710, 3861, + 3712, 3861, + 3712, 3866, + 3713, 3866, + 3713, 3870, + 3714, 3870, + 3714, 3873, + 3713, 3873, + 3713, 3876, + 3712, 3876, + 3712, 3881, + 3710, 3881, + 3710, 3888, + 3712, 3888, + 3712, 3890, + 3714, 3890, + 3714, 3891, + 3716, 3891, + 3716, 3892, + 3717, 3892, + 3717, 3893, + 3716, 3893, + 3716, 3894, + 3714, 3894, + 3714, 3895, + 3713, 3895, + 3713, 3896, + 3712, 3896, + 3712, 3897, + 3705, 3897, + 3705, 3898, + 3704, 3898, + 3704, 3899, + 3692, 3899, + 3692, 3898, + 3688, 3898, + 3688, 3897, + 3686, 3897, + 3686, 3896, + 3680, 3896); + + // Zeah, southwest of Wintertodt, snowy area with ice giants and wolves + addPolygonOnPlane(MULTICOMBAT, 0, + 1540, 3898, + 1543, 3898, + 1543, 3901, + 1546, 3901, + 1546, 3903, + 1547, 3903, + 1547, 3904, + 1550, 3904, + 1550, 3903, + 1553, 3903, + 1553, 3904, + 1559, 3904, + 1559, 3902, + 1564, 3902, + 1564, 3903, + 1565, 3903, + 1565, 3904, + 1568, 3904, + 1568, 3903, + 1569, 3903, + 1569, 3902, + 1570, 3902, + 1570, 3901, + 1573, 3901, + 1573, 3898, + 1577, 3898, + 1577, 3899, + 1578, 3899, + 1578, 3902, + 1579, 3902, + 1579, 3903, + 1584, 3903, + 1584, 3902, + 1586, 3902, + 1586, 3901, + 1590, 3901, + 1590, 3891, + 1588, 3891, + 1588, 3887, + 1572, 3887, + 1572, 3872, + 1567, 3872, + 1567, 3868, + 1563, 3868, + 1563, 3867, + 1558, 3867, + 1558, 3868, + 1557, 3868, + 1557, 3870, + 1549, 3870, + 1549, 3874, + 1545, 3874, + 1545, 3876, + 1543, 3876, + 1543, 3877, + 1542, 3877, + 1542, 3879, + 1541, 3879, + 1541, 3882, + 1539, 3882, + 1539, 3887, + 1540, 3887, + 1540, 3888, + 1539, 3888, + 1539, 3894, + 1540, 3894); + + // Zeah arceuus area + addPolygonOnPlane(MULTICOMBAT, 0, + 1664, 3776, + 1664, 3785, + 1667, 3785, + 1667, 3805, + 1671, 3805, + 1671, 3811, + 1675, 3811, + 1675, 3819, + 1690, 3819, + 1690, 3814, + 1695, 3814, + 1695, 3806, + 1719, 3806, + 1719, 3787, + 1725, 3787, + 1725, 3778, + 1711, 3778, + 1711, 3776); + + // Arceuus teletab-making house + addPolygonOnPlane(MULTICOMBAT, 0, + 1667, 3772, + 1679, 3772, + 1679, 3775, + 1691, 3775, + 1691, 3761, + 1679, 3761, + 1679, 3764, + 1667, 3764); + // Next house east + addPolygonOnPlane(MULTICOMBAT, 0, + 1696, 3775, + 1708, 3775, + 1708, 3763, + 1696, 3763); + // Next house east + addPolygonOnPlane(MULTICOMBAT, 0, + 1713, 3775, + 1727, 3775, + 1727, 3763, + 1724, 3763, + 1724, 3752, + 1716, 3752, + 1716, 3763, + 1713, 3763); + // Arceuus rune shop house + addPolygonOnPlane(MULTICOMBAT, 0, + 1716, 3750, + 1728, 3750, + 1728, 3736, + 1716, 3736); + // Arceuus general store house + addPolygonOnPlane(MULTICOMBAT, 0, + 1717, 3732, + 1725, 3732, + 1725, 3715, + 1715, 3715, + 1715, 3725, + 1717, 3725); + // Arceuus pub + addPolygonOnPlane(MULTICOMBAT, 0, + 1683, 3732, + 1691, 3732, + 1691, 3725, + 1697, 3725, + 1697, 3730, + 1703, 3730, + 1703, 3712, + 1683, 3712); + // Arceuus staff store + addPolygonOnPlane(MULTICOMBAT, 0, + 1664, 3732, + 1676, 3732, + 1676, 3720, + 1664, 3720); + // Next house to the west + addPolygonOnPlane(MULTICOMBAT, 0, + 1647, 3738, + 1655, 3738, + 1655, 3726, + 1658, 3726, + 1658, 3714, + 1644, 3714, + 1644, 3726, + 1647, 3726); + // Next house to the north + addPolygonOnPlane(MULTICOMBAT, 0, + 1647, 3762, + 1657, 3762, + 1657, 3752, + 1655, 3752, + 1655, 3745, + 1647, 3745); + + // Arceuus house magic trees + addPolygonOnPlane(MULTICOMBAT, 0, + 1682, 3755, + 1692, 3755, + 1692, 3745, + 1690, 3745, + 1690, 3738, + 1682, 3738); + // West of that ^ + addPolygonOnPlane(MULTICOMBAT, 0, + 1667, 3756, + 1675, 3756, + 1675, 3740, + 1665, 3740, + 1665, 3746, + 1667, 3746); + + // This one goes through western piscarilius, northen hosidius + // and southwestern arceuus + addPolygonOnPlane(MULTICOMBAT, 0, + 1728, 3808, + 1792, 3808, + 1792, 3764, + 1856, 3764, + 1856, 3712, + 1792, 3712, + 1792, 3648, + 1664, 3648, + 1664, 3706, + 1665, 3706, + 1665, 3705, + 1668, 3705, + 1668, 3706, + 1671, 3706, + 1671, 3705, + 1675, 3705, + 1675, 3704, + 1683, 3704, + 1683, 3701, + 1684, 3701, + 1684, 3700, + 1686, 3700, + 1686, 3702, + 1687, 3702, + 1687, 3700, + 1688, 3700, + 1688, 3701, + 1690, 3701, + 1690, 3703, + 1689, 3703, + 1689, 3704, + 1690, 3704, + 1690, 3705, + 1704, 3705, + 1704, 3707, + 1706, 3707, + 1706, 3712, + 1711, 3712, + 1711, 3711, + 1710, 3711, + 1710, 3710, + 1712, 3710, + 1712, 3707, + 1728, 3707); + + // Kourend castle + addPolygonOnPlane(MULTICOMBAT, 0, + 1614, 3691, + 1619, 3691, + 1619, 3690, + 1620, 3690, + 1620, 3689, + 1653, 3689, + 1653, 3690, + 1654, 3690, + 1654, 3691, + 1657, 3691, + 1657, 3690, + 1658, 3690, + 1658, 3689, + 1659, 3689, + 1659, 3686, + 1658, 3686, + 1658, 3685, + 1657, 3685, + 1657, 3662, + 1658, 3662, + 1658, 3661, + 1659, 3661, + 1659, 3658, + 1658, 3658, + 1658, 3657, + 1657, 3657, + 1657, 3656, + 1654, 3656, + 1654, 3657, + 1653, 3657, + 1653, 3658, + 1620, 3658, + 1620, 3657, + 1619, 3657, + 1619, 3656, + 1614, 3656, + 1614, 3657, + 1613, 3657, + 1613, 3661, + 1612, 3661, + 1612, 3662, + 1611, 3662, + 1611, 3663, + 1600, 3663, + 1600, 3662, + 1599, 3662, + 1599, 3661, + 1594, 3661, + 1594, 3662, + 1593, 3662, + 1593, 3685, + 1594, 3685, + 1594, 3686, + 1599, 3686, + 1599, 3685, + 1600, 3685, + 1600, 3684, + 1611, 3684, + 1611, 3685, + 1612, 3685, + 1612, 3686, + 1613, 3686, + 1613, 3690, + 1614, 3690); + + // Western hosidius area, including woodcutting guild and western sand crabs + addPolygonOnPlane(MULTICOMBAT, 0, + 1650, 3648, + 1664, 3648, + 1664, 3520, + 1689, 3520, + 1689, 3496, + 1707, 3496, + 1707, 3485, + 1708, 3485, + 1708, 3484, + 1710, 3484, + 1710, 3483, + 1713, 3483, + 1713, 3482, + 1720, 3482, + 1720, 3481, + 1721, 3481, + 1721, 3480, + 1722, 3480, + 1722, 3479, + 1723, 3479, + 1723, 3478, + 1724, 3478, + 1724, 3477, + 1726, 3477, + 1726, 3476, + 1728, 3476, + 1728, 3472, + 1708, 3472, + 1708, 3456, + 1600, 3456, + 1600, 3584, + 1608, 3584, + 1608, 3616, + 1650, 3616); + + // Hosidius sand crabs + addPolygonOnPlane(MULTICOMBAT, 0, + 1740, 3478, + 1741, 3478, + 1741, 3479, + 1745, 3479, + 1745, 3480, + 1751, 3480, + 1751, 3479, + 1752, 3479, + 1752, 3478, + 1753, 3478, + 1753, 3477, + 1755, 3477, + 1755, 3476, + 1757, 3476, + 1757, 3475, + 1758, 3475, + 1758, 3474, + 1759, 3474, + 1759, 3473, + 1779, 3473, + 1779, 3474, + 1781, 3474, + 1781, 3475, + 1786, 3475, + 1786, 3476, + 1800, 3476, + 1800, 3475, + 1805, 3475, + 1805, 3474, + 1807, 3474, + 1807, 3473, + 1808, 3473, + 1808, 3472, + 1810, 3472, + 1810, 3471, + 1833, 3471, + 1833, 3470, + 1834, 3470, + 1834, 3469, + 1852, 3469, + 1852, 3449, + 1792, 3449, + 1792, 3424, + 1800, 3424, + 1800, 3449, + 1800, 3400, + 1728, 3400, + 1728, 3462, + 1729, 3462, + 1729, 3466, + 1730, 3466, + 1730, 3469, + 1731, 3469, + 1731, 3470, + 1732, 3470, + 1732, 3471, + 1733, 3471, + 1733, 3473, + 1734, 3473, + 1734, 3474, + 1736, 3474, + 1736, 3475, + 1737, 3475, + 1737, 3476, + 1738, 3476, + 1738, 3477, + 1740, 3477); + + // Apparently there is a 1x1 single zone on the sand crab island + addPolygonOnPlane(NOT_MULTICOMBAT, 0, + 1777, 3416, + 1777, 3417, + 1778, 3417, + 1778, 3416); + + // Eastern hosidius area + addPolygonOnPlane(MULTICOMBAT, 0, + 1834, 3584, + 1888, 3584, + 1888, 3528, + 1856, 3528, + 1856, 3520, + 1834, 3520, + 1834, 3522, + 1833, 3522, + 1833, 3535, + 1834, 3535, + 1834, 3538, + 1835, 3538, + 1835, 3539, + 1836, 3539, + 1836, 3540, + 1837, 3540, + 1837, 3541, + 1838, 3541, + 1838, 3542, + 1840, 3542, + 1840, 3543, + 1841, 3543, + 1841, 3545, + 1842, 3545, + 1842, 3546, + 1844, 3546, + 1844, 3547, + 1845, 3547, + 1845, 3548, + 1851, 3548, + 1851, 3551, + 1853, 3551, + 1853, 3563, + 1851, 3563, + 1851, 3566, + 1847, 3566, + 1847, 3567, + 1845, 3567, + 1845, 3568, + 1844, 3568, + 1844, 3569, + 1843, 3569, + 1843, 3571, + 1842, 3571, + 1842, 3573, + 1841, 3573, + 1841, 3574, + 1840, 3574, + 1840, 3575, + 1839, 3575, + 1839, 3576, + 1838, 3576, + 1838, 3577, + 1837, 3577, + 1837, 3578, + 1836, 3578, + 1836, 3579, + 1835, 3579, + 1835, 3581, + 1834, 3581); + + // Eastern hosidius area also has a 1x1 multi area + addPolygonOnPlane(MULTICOMBAT, 0, + 1849, 3563, + 1849, 3564, + 1850, 3564, + 1850, 3563); + + // Hosidius cows/chickens/pigs + addPolygonOnPlane(MULTICOMBAT, 0, + 1792, 3513, + 1802, 3513, + 1802, 3520, + 1810, 3520, + 1810, 3513, + 1816, 3513, + 1816, 3512, + 1836, 3512, + 1836, 3494, + 1796, 3494, + 1796, 3495, + 1792, 3495); + + // Hosidius southeast of tithe farm + addPolygonOnPlane(MULTICOMBAT, 0, + 1777, 3597, + 1794, 3597, + 1794, 3561, + 1777, 3561, + 1777, 3591, + 1779, 3591, + 1779, 3592, + 1777, 3592); + + // West of shayzien house + addPolygonOnPlane(MULTICOMBAT, 0, + 1408, 3584, + 1408, 3582, + 1486, 3582, + 1486, 3568, + 1528, 3568, + 1528, 3520, + 1408, 3520, + 1408, 3464, + 1380, 3464, + 1380, 3486, + 1377, 3486, + 1377, 3488, + 1373, 3488, + 1373, 3492, + 1364, 3492, + 1364, 3512, + 1358, 3512, + 1358, 3520, + 1356, 3520, + 1356, 3532, + 1358, 3532, + 1358, 3540, + 1359, 3540, + 1359, 3542, + 1360, 3542, + 1360, 3557, + 1356, 3557, + 1356, 3560, + 1351, 3560, + 1351, 3570, + 1354, 3570, + 1354, 3581, + 1346, 3581, + 1346, 3584); + + // South of chambers of xeric + addPolygonOnPlane(MULTICOMBAT, 0, + 1261, 3489, + 1259, 3489, + 1259, 3488, + 1255, 3488, + 1255, 3487, + 1243, 3487, + 1243, 3490, + 1234, 3490, + 1234, 3480, + 1192, 3480, + 1192, 3568, + 1209, 3568, + 1209, 3548, + 1215, 3548, + 1215, 3544, + 1217, 3544, + 1217, 3536, + 1235, 3536, + 1235, 3532, + 1249, 3532, + 1249, 3525, + 1248, 3525, + 1248, 3517, + 1254, 3517, + 1254, 3513, + 1274, 3513, + 1274, 3510, + 1296, 3510, + 1296, 3511, + 1300, 3511, + 1300, 3501, + 1287, 3501, + 1287, 3490, + 1280, 3490, + 1280, 3489, + 1264, 3489, + 1264, 3490, + 1261, 3490); + + // Lizardman shamans + addPolygonOnPlane(MULTICOMBAT, 0, + 1416, 3728, + 1456, 3728, + 1456, 3688, + 1416, 3688); + + // Other lizardman area at shayzien (west side) + addPolygonOnPlane(MULTICOMBAT, 0, + 1472, 3712, + 1510, 3712, + 1510, 3702, + 1509, 3702, + 1509, 3701, + 1506, 3701, + 1506, 3696, + 1500, 3696, + 1500, 3680, + 1472, 3680); + + // Other lizardman area at shayzien (east side) + addPolygonOnPlane(MULTICOMBAT, 0, + 1538, 3704, + 1560, 3704, + 1560, 3672, + 1538, 3672); + + // Lovakengj house + addPolygonOnPlane(MULTICOMBAT, 0, + 1600, 3712, + 1472, 3712, + 1472, 3840, + 1547, 3840, + 1547, 3816, + 1556, 3816, + 1556, 3809, + 1562, 3809, + 1562, 3800, + 1568, 3800, + 1568, 3793, + 1571, 3793, + 1571, 3816, + 1571, 3776, + 1600, 3776); + + // Shayzien house + addPolygonOnPlane(MULTICOMBAT, 0, + 1475, 3587, + 1475, 3641, + 1534, 3641, + 1534, 3587); + + // Shayzien house bank is non-multi + addPolygonOnPlane(NOT_MULTICOMBAT, 0, + 1495, 3622, + 1515, 3622, + 1515, 3612, + 1495, 3612); + + // Shayzien house general store + addPolygonOnPlane(MULTICOMBAT, 0, + 1539, 3640, + 1551, 3640, + 1551, 3621, + 1539, 3621); + + // Kourend woodland barbarian area + addPolygonOnPlane(MULTICOMBAT, 0, + 1572, 3442, + 1591, 3442, + 1591, 3424, + 1572, 3424); + + // Catacombs + addPolygonTo(MULTICOMBAT, + 1600, 9984, + 1600, 10067, + 1628, 10067, + 1628, 10070, + 1639, 10070, + 1639, 10112, + 1730, 10112, + 1730, 9984); + + // Zeah dungeon with sand crabs + addPolygonTo(MULTICOMBAT, + 1632, 9792, + 1632, 9856, + 1728, 9856, + 1728, 9792); + + // Waterbirth island near the doors where people use rune throwing axes + addPolygonTo(MULTICOMBAT, + 2536, 10136, + 2536, 10152, + 2552, 10152, + 2552, 10136); + + // Waterbirth island dungeon, on the path to dks + addPolygonTo(MULTICOMBAT, + 1792, 4352, + 1792, 4416, + 1984, 4416, + 1984, 4352); + + // Dagannoths in lighthouse + addPolygonTo(MULTICOMBAT, + 2496, 10048, + 2560, 10048, + 2560, 9984, + 2496, 9984); + + // Dagannoth kings (DKs) including slayer only dks + addPolygonTo(MULTICOMBAT, + 2944, 4352, + 2944, 4480, + 2880, 4480, + 2880, 4352); + + // White wolf mountain dungeon at ice queen + addPolygonTo(MULTICOMBAT, + 2856, 9928, + 2856, 9968, + 2880, 9968, + 2880, 9928); + + // Kharazi jungle dungeon (in dragon slayer 2 quest) + addPolygonTo(MULTICOMBAT, + 2816, 9296, + 2880, 9296, + 2880, 9216, + 2816, 9216); + + // Tzhaar, fight pits and inferno area + addPolygonTo(MULTICOMBAT, + 2368, 5184, + 2560, 5184, + 2560, 5056, + 2368, 5056); + + // Smoke devils + addPolygonTo(MULTICOMBAT, + 2432, 9408, + 2344, 9408, + 2344, 9472, + 2432, 9472); + + // Kraken + addPolygonTo(MULTICOMBAT, + 2270, 10045, + 2291, 10045, + 2291, 10022, + 2270, 10022); + + // Giant mole + addPolygonTo(MULTICOMBAT, + 1728, 5240, + 1792, 5240, + 1792, 5120, + 1728, 5120); + + // Godwars dungeon + addPolygonTo(MULTICOMBAT, + 2816, 5376, + 2944, 5376, + 2944, 5248, + 2816, 5248); + + // Desert treasure shadow diamond area + addPolygonTo(MULTICOMBAT, + 2752, 5064, + 2728, 5064, + 2728, 5088, + 2720, 5088, + 2720, 5096, + 2712, 5096, + 2712, 5112, + 2736, 5112, + 2736, 5120, + 2752, 5120); + + // Kalphite slayer area + addPolygonTo(MULTICOMBAT, + 3264, 9544, + 3344, 9544, + 3344, 9472, + 3264, 9472); + + // Normal kalphite area including kalphite queen + addPolygonTo(MULTICOMBAT, + 3456, 9536, + 3520, 9536, + 3520, 9472, + 3456, 9472); + + // Tarns lair + addPolygonTo(MULTICOMBAT, + 3136, 4664, + 3200, 4664, + 3200, 4544, + 3136, 4544); + + // Haunted mine boss area + addPolygonTo(MULTICOMBAT, + 2752, 4416, + 2752, 4480, + 2816, 4480, + 2816, 4416); + + // Entrance to dorgesh kaan + addPolygonTo(MULTICOMBAT, + 3328, 9600, + 3312, 9600, + 3312, 9640, + 3304, 9640, + 3304, 9664, + 3328, 9664); + + // Hammerspikes hangout in dwarven mines + addPolygonTo(MULTICOMBAT, + 2960, 9824, + 2976, 9824, + 2976, 9800, + 2960, 9800); + + // Fremennik isles dungeon + addPolygonTo(MULTICOMBAT, + 2432, 10304, + 2432, 10240, + 2368, 10240, + 2368, 10304); + + // Varrock sewers + addPolygonTo(MULTICOMBAT, + 3152, 9920, + 3288, 9920, + 3288, 9856, + 3152, 9856); + + // Stronghold of security 1st floor + addPolygonTo(MULTICOMBAT, + 1856, 5248, + 1920, 5248, + 1920, 5184, + 1856, 5184); + + // Corp cave + addPolygonTo(MULTICOMBAT, + 2960, 4400, + 3000, 4400, + 3000, 4368, + 2960, 4368); + + // ZMI altar area + addPolygonTo(MULTICOMBAT, + 3008, 5632, + 3072, 5632, + 3072, 5568, + 3008, 5568); + + // Dragon slayer 2 zeah underground puzzle + addPolygonTo(MULTICOMBAT, + 1472, 9984, + 1536, 9984, + 1536, 9920, + 1472, 9920); + + // Wildy revenant caves + addPolygonTo(MULTICOMBAT, + 3136, 10062, + 3136, 10240, + 3236, 10240, + 3236, 10229, + 3264, 10229, + 3264, 10048, + 3208, 10048, + 3208, 10062); + + // King black dragon (Kbd) + addPolygonTo(MULTICOMBAT, + 2240, 4672, + 2240, 4736, + 2304, 4736, + 2304, 4672); + + // Scorpia + addPolygonTo(MULTICOMBAT, + 3248, 10352, + 3248, 10328, + 3216, 10328, + 3216, 10352); + + // Inside mage bank + addPolygonTo(MULTICOMBAT, + 2496, 4672, + 2496, 4736, + 2560, 4736, + 2560, 4672); + + // Wildy godwars dungeon + addPolygonTo(MULTICOMBAT, + 3072, 10112, + 3008, 10112, + 3008, 10176, + 3048, 10176, + 3048, 10152, + 3056, 10152, + 3056, 10144, + 3064, 10144, + 3064, 10136, + 3072, 10136); + + // Enchanted valley + addPolygonTo(MULTICOMBAT, + 3008, 4480, + 3008, 4544, + 3072, 4544, + 3072, 4480); + + // Zulrah + addPolygonTo(MULTICOMBAT, + 2256, 3080, + 2280, 3080, + 2280, 3064, + 2256, 3064); + + // Abyssal sire and abyss + addPolygonTo(MULTICOMBAT, + 3008, 4736, + 2944, 4736, + 2944, 4864, + 3136, 4864, + 3136, 4736, + 3072, 4736, + 3072, 4800, + 3008, 4800); + } + + private static void defineDeadmanSafeZones() + { + // Varrock + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3182, 3382, + 3182, 3399, + 3174, 3399, + 3174, 3448, + 3198, 3448, + 3198, 3449, + 3197, 3449, + 3197, 3450, + 3196, 3450, + 3196, 3451, + 3195, 3451, + 3195, 3452, + 3194, 3452, + 3194, 3453, + 3193, 3453, + 3193, 3454, + 3192, 3454, + 3192, 3455, + 3191, 3455, + 3191, 3456, + 3190, 3456, + 3190, 3457, + 3185, 3457, + 3185, 3463, + 3186, 3463, + 3186, 3464, + 3187, 3464, + 3187, 3467, + 3167, 3467, + 3167, 3468, + 3163, 3468, + 3163, 3467, + 3142, 3467, + 3142, 3468, + 3141, 3468, + 3141, 3469, + 3140, 3469, + 3140, 3470, + 3139, 3470, + 3139, 3471, + 3138, 3471, + 3138, 3484, + 3139, 3484, + 3139, 3485, + 3140, 3485, + 3140, 3486, + 3141, 3486, + 3141, 3491, + 3140, 3491, + 3140, 3492, + 3139, 3492, + 3139, 3493, + 3138, 3493, + 3138, 3515, + 3139, 3515, + 3139, 3516, + 3140, 3516, + 3140, 3517, + 3141, 3517, + 3141, 3518, + 3160, 3518, + 3160, 3517, + 3161, 3517, + 3161, 3516, + 3162, 3516, + 3162, 3515, + 3167, 3515, + 3167, 3516, + 3168, 3516, + 3168, 3517, + 3169, 3517, + 3169, 3518, + 3191, 3518, + 3191, 3517, + 3192, 3517, + 3192, 3516, + 3193, 3516, + 3193, 3515, + 3194, 3515, + 3194, 3514, + 3195, 3514, + 3195, 3513, + 3196, 3513, + 3196, 3512, + 3197, 3512, + 3197, 3511, + 3198, 3511, + 3198, 3510, + 3199, 3510, + 3199, 3509, + 3200, 3509, + 3200, 3508, + 3230, 3508, + 3230, 3507, + 3231, 3507, + 3231, 3506, + 3232, 3506, + 3232, 3505, + 3233, 3505, + 3233, 3504, + 3234, 3504, + 3234, 3503, + 3235, 3503, + 3235, 3502, + 3252, 3502, + 3252, 3496, + 3253, 3496, + 3253, 3495, + 3254, 3495, + 3254, 3494, + 3255, 3494, + 3255, 3493, + 3263, 3493, + 3263, 3472, + 3264, 3472, + 3264, 3471, + 3265, 3471, + 3265, 3470, + 3266, 3470, + 3266, 3469, + 3267, 3469, + 3267, 3468, + 3268, 3468, + 3268, 3467, + 3269, 3467, + 3269, 3466, + 3270, 3466, + 3270, 3465, + 3271, 3465, + 3271, 3437, + 3274, 3437, + 3274, 3424, + 3277, 3424, + 3277, 3420, + 3274, 3420, + 3274, 3411, + 3275, 3411, + 3275, 3410, + 3276, 3410, + 3276, 3409, + 3277, 3409, + 3277, 3408, + 3288, 3408, + 3288, 3391, + 3289, 3391, + 3289, 3385, + 3290, 3385, + 3290, 3378, + 3289, 3378, + 3289, 3377, + 3288, 3377, + 3288, 3376, + 3265, 3376, + 3265, 3380, + 3253, 3380, + 3253, 3382, + 3245, 3382, + 3245, 3380, + 3242, 3380, + 3242, 3382, + 3239, 3382, + 3239, 3381, + 3209, 3381, + 3209, 3382, + 3282, 3382); + + // Lumbridge + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3201, 3257, + 3213, 3257, + 3213, 3264, + 3233, 3264, + 3233, 3257, + 3235, 3257, + 3235, 3241, + 3237, 3241, + 3237, 3237, + 3239, 3237, + 3239, 3231, + 3243, 3231, + 3243, 3220, + 3253, 3220, + 3253, 3217, + 3256, 3217, + 3256, 3212, + 3259, 3212, + 3259, 3190, + 3247, 3190, + 3247, 3191, + 3238, 3191, + 3238, 3195, + 3230, 3195, + 3230, 3201, + 3228, 3201, + 3228, 3202, + 3227, 3202, + 3227, 3205, + 3228, 3205, + 3228, 3207, + 3225, 3207, + 3225, 3206, + 3224, 3206, + 3224, 3205, + 3223, 3205, + 3223, 3204, + 3222, 3204, + 3222, 3203, + 3215, 3203, + 3215, 3202, + 3214, 3202, + 3214, 3201, + 3203, 3201, + 3203, 3202, + 3202, 3202, + 3202, 3203, + 3201, 3203, + 3201, 3217, + 3199, 3217, + 3199, 3220, + 3201, 3220); + + // Falador + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2986, 3395, + 2986, 3394, + 2987, 3394, + 2987, 3393, + 2996, 3393, + 2996, 3394, + 3002, 3394, + 3002, 3395, + 3009, 3395, + 3009, 3394, + 3010, 3394, + 3010, 3393, + 3011, 3393, + 3011, 3392, + 3021, 3392, + 3021, 3391, + 3022, 3391, + 3022, 3390, + 3041, 3390, + 3041, 3389, + 3047, 3389, + 3047, 3390, + 3062, 3390, + 3062, 3389, + 3063, 3389, + 3063, 3388, + 3064, 3388, + 3064, 3387, + 3065, 3387, + 3065, 3386, + 3066, 3386, + 3066, 3368, + 3065, 3368, + 3065, 3367, + 3064, 3367, + 3064, 3366, + 3063, 3366, + 3063, 3365, + 3062, 3365, + 3062, 3364, + 3061, 3364, + 3061, 3363, + 3060, 3363, + 3060, 3331, + 3061, 3331, + 3061, 3328, + 3058, 3328, + 3058, 3329, + 3025, 3329, + 3025, 3328, + 3024, 3328, + 3024, 3327, + 3016, 3327, + 3016, 3326, + 3015, 3326, + 3015, 3325, + 3014, 3325, + 3014, 3324, + 3013, 3324, + 3013, 3323, + 3008, 3323, + 3008, 3324, + 3006, 3324, + 3006, 3323, + 3002, 3323, + 3002, 3322, + 3001, 3322, + 3001, 3321, + 3000, 3321, + 3000, 3320, + 2999, 3320, + 2999, 3319, + 2998, 3319, + 2998, 3318, + 2997, 3318, + 2997, 3317, + 2996, 3317, + 2996, 3316, + 2992, 3316, + 2992, 3315, + 2991, 3315, + 2991, 3314, + 2990, 3314, + 2990, 3313, + 2989, 3313, + 2989, 3312, + 2988, 3312, + 2988, 3311, + 2987, 3311, + 2987, 3310, + 2986, 3310, + 2986, 3309, + 2966, 3309, + 2966, 3310, + 2956, 3310, + 2956, 3311, + 2941, 3311, + 2941, 3312, + 2940, 3312, + 2940, 3320, + 2936, 3320, + 2936, 3354, + 2937, 3354, + 2937, 3357, + 2936, 3357, + 2936, 3389, + 2937, 3389, + 2937, 3390, + 2938, 3390, + 2938, 3391, + 2939, 3391, + 2939, 3392, + 2940, 3392, + 2940, 3393, + 2943, 3393, + 2943, 3394, + 2944, 3394, + 2944, 3395, + 2950, 3395, + 2950, 3394, + 2956, 3394, + 2956, 3395); + + // Port phasmatys + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3650, 3456, + 3650, 3472, + 3651, 3472, + 3651, 3473, + 3652, 3473, + 3652, 3474, + 3653, 3474, + 3653, 3507, + 3654, 3507, + 3654, 3508, + 3668, 3508, + 3668, 3509, + 3669, 3509, + 3669, 3510, + 3670, 3510, + 3670, 3511, + 3671, 3511, + 3671, 3512, + 3672, 3512, + 3672, 3513, + 3673, 3513, + 3673, 3514, + 3674, 3514, + 3674, 3515, + 3675, 3515, + 3675, 3516, + 3676, 3516, + 3676, 3517, + 3687, 3517, + 3687, 3494, + 3690, 3494, + 3690, 3493, + 3696, 3493, + 3696, 3482, + 3699, 3482, + 3699, 3481, + 3712, 3481, + 3712, 3456); + + // Sophanem + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3274, 2752, + 3274, 2784, + 3277, 2784, + 3277, 2786, + 3274, 2786, + 3274, 2789, + 3272, 2789, + 3272, 2810, + 3322, 2810, + 3322, 2752); + + // Ardy + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2560, 3256, + 2560, 3264, + 2559, 3264, + 2559, 3328, + 2560, 3328, + 2560, 3339, + 2561, 3339, + 2561, 3340, + 2562, 3340, + 2562, 3341, + 2563, 3341, + 2563, 3342, + 2616, 3342, + 2616, 3341, + 2617, 3341, + 2617, 3340, + 2669, 3340, + 2669, 3339, + 2670, 3339, + 2670, 3338, + 2671, 3338, + 2671, 3337, + 2672, 3337, + 2672, 3336, + 2673, 3336, + 2673, 3335, + 2674, 3335, + 2674, 3334, + 2683, 3334, + 2683, 3333, + 2684, 3333, + 2684, 3332, + 2685, 3332, + 2685, 3331, + 2686, 3331, + 2686, 3330, + 2687, 3330, + 2687, 3329, + 2688, 3329, + 2688, 3264, + 2638, 3264, + 2638, 3263, + 2625, 3263, + 2625, 3264, + 2611, 3264, + 2611, 3257, + 2602, 3257, + 2602, 3264, + 2587, 3264, + 2587, 3263, + 2586, 3263, + 2586, 3262, + 2584, 3262, + 2584, 3261, + 2583, 3261, + 2583, 3260, + 2582, 3260, + 2582, 3259, + 2581, 3259, + 2581, 3258, + 2572, 3258, + 2572, 3260, + 2571, 3260, + 2571, 3261, + 2566, 3261, + 2566, 3260, + 2565, 3260, + 2565, 3259, + 2564, 3259, + 2564, 3256); + + // Yanille + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2613, 3103, + 2614, 3103, + 2614, 3102, + 2615, 3102, + 2615, 3101, + 2616, 3101, + 2616, 3100, + 2617, 3100, + 2617, 3099, + 2618, 3099, + 2618, 3098, + 2619, 3098, + 2619, 3097, + 2620, 3097, + 2620, 3075, + 2590, 3075, + 2590, 3074, + 2589, 3074, + 2589, 3073, + 2584, 3073, + 2584, 3074, + 2583, 3074, + 2583, 3075, + 2543, 3075, + 2543, 3076, + 2542, 3076, + 2542, 3077, + 2539, 3077, + 2539, 3107, + 2542, 3107, + 2542, 3108, + 2543, 3108, + 2543, 3109, + 2608, 3109, + 2608, 3108, + 2609, 3108, + 2609, 3107, + 2610, 3107, + 2610, 3106, + 2611, 3106, + 2611, 3105, + 2612, 3105, + 2612, 3104, + 2613, 3104); + + // Gnome stronghold + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2495, 3439, + 2494, 3439, + 2494, 3432, + 2495, 3432, + 2495, 3431, + 2496, 3431, + 2496, 3430, + 2497, 3430, + 2497, 3429, + 2498, 3429, + 2498, 3417, + 2497, 3417, + 2497, 3416, + 2496, 3416, + 2496, 3412, + 2495, 3412, + 2495, 3408, + 2494, 3408, + 2494, 3404, + 2495, 3404, + 2495, 3403, + 2496, 3403, + 2496, 3402, + 2497, 3402, + 2497, 3401, + 2498, 3401, + 2498, 3400, + 2499, 3400, + 2499, 3399, + 2500, 3399, + 2500, 3398, + 2501, 3398, + 2501, 3397, + 2502, 3397, + 2502, 3396, + 2506, 3396, + 2506, 3391, + 2502, 3391, + 2502, 3390, + 2492, 3390, + 2492, 3391, + 2489, 3391, + 2489, 3390, + 2488, 3390, + 2488, 3389, + 2485, 3389, + 2485, 3390, + 2482, 3390, + 2482, 3389, + 2476, 3389, + 2476, 3390, + 2471, 3390, + 2471, 3391, + 2468, 3391, + 2468, 3390, + 2467, 3390, + 2467, 3389, + 2466, 3389, + 2466, 3385, + 2465, 3385, + 2465, 3384, + 2458, 3384, + 2458, 3385, + 2457, 3385, + 2457, 3389, + 2456, 3389, + 2456, 3390, + 2455, 3390, + 2455, 3391, + 2450, 3391, + 2450, 3390, + 2446, 3390, + 2446, 3391, + 2443, 3391, + 2443, 3390, + 2442, 3390, + 2442, 3389, + 2440, 3389, + 2440, 3388, + 2434, 3388, + 2434, 3389, + 2433, 3389, + 2433, 3390, + 2432, 3390, + 2432, 3391, + 2428, 3391, + 2428, 3392, + 2427, 3392, + 2427, 3393, + 2420, 3393, + 2420, 3394, + 2419, 3394, + 2419, 3395, + 2418, 3395, + 2418, 3396, + 2417, 3396, + 2417, 3397, + 2416, 3397, + 2416, 3399, + 2415, 3399, + 2415, 3400, + 2414, 3400, + 2414, 3408, + 2413, 3408, + 2413, 3409, + 2412, 3409, + 2412, 3410, + 2411, 3410, + 2411, 3411, + 2410, 3411, + 2410, 3412, + 2387, 3412, + 2387, 3407, + 2383, 3407, + 2383, 3408, + 2380, 3408, + 2380, 3409, + 2379, 3409, + 2379, 3410, + 2377, 3410, + 2377, 3411, + 2376, 3411, + 2376, 3413, + 2375, 3413, + 2375, 3417, + 2374, 3417, + 2374, 3418, + 2373, 3418, + 2373, 3419, + 2372, 3419, + 2372, 3420, + 2371, 3420, + 2371, 3421, + 2370, 3421, + 2370, 3422, + 2369, 3422, + 2369, 3433, + 2370, 3433, + 2370, 3434, + 2371, 3434, + 2371, 3444, + 2372, 3444, + 2372, 3445, + 2373, 3445, + 2373, 3446, + 2374, 3446, + 2374, 3447, + 2375, 3447, + 2375, 3459, + 2376, 3459, + 2376, 3460, + 2377, 3460, + 2377, 3461, + 2378, 3461, + 2378, 3462, + 2379, 3462, + 2379, 3463, + 2380, 3463, + 2380, 3464, + 2381, 3464, + 2381, 3476, + 2379, 3476, + 2379, 3477, + 2378, 3477, + 2378, 3478, + 2377, 3478, + 2377, 3485, + 2376, 3485, + 2376, 3486, + 2375, 3486, + 2375, 3499, + 2376, 3499, + 2376, 3500, + 2377, 3500, + 2377, 3507, + 2378, 3507, + 2378, 3508, + 2379, 3508, + 2379, 3509, + 2380, 3509, + 2380, 3521, + 2382, 3521, + 2382, 3522, + 2384, 3522, + 2384, 3523, + 2393, 3523, + 2393, 3524, + 2399, 3524, + 2399, 3525, + 2404, 3525, + 2404, 3524, + 2405, 3524, + 2405, 3523, + 2407, 3523, + 2407, 3522, + 2415, 3522, + 2415, 3521, + 2425, 3521, + 2425, 3522, + 2427, 3522, + 2427, 3523, + 2430, 3523, + 2430, 3522, + 2431, 3522, + 2431, 3521, + 2432, 3521, + 2432, 3520, + 2448, 3520, + 2448, 3517, + 2454, 3517, + 2454, 3516, + 2455, 3516, + 2455, 3515, + 2456, 3515, + 2456, 3514, + 2457, 3514, + 2457, 3513, + 2460, 3513, + 2460, 3512, + 2461, 3512, + 2461, 3511, + 2465, 3511, + 2465, 3510, + 2468, 3510, + 2468, 3511, + 2472, 3511, + 2472, 3512, + 2473, 3512, + 2473, 3513, + 2475, 3513, + 2475, 3514, + 2476, 3514, + 2476, 3515, + 2477, 3515, + 2477, 3516, + 2478, 3516, + 2478, 3517, + 2483, 3517, + 2483, 3516, + 2487, 3516, + 2487, 3515, + 2488, 3515, + 2488, 3512, + 2487, 3512, + 2487, 3509, + 2488, 3509, + 2488, 3508, + 2489, 3508, + 2489, 3507, + 2491, 3507, + 2491, 3506, + 2492, 3506, + 2492, 3505, + 2493, 3505, + 2493, 3499, + 2492, 3499, + 2492, 3498, + 2491, 3498, + 2491, 3497, + 2490, 3497, + 2490, 3495, + 2491, 3495, + 2491, 3494, + 2492, 3494, + 2492, 3493, + 2493, 3493, + 2493, 3485, + 2490, 3485, + 2490, 3484, + 2489, 3484, + 2489, 3483, + 2488, 3483, + 2488, 3482, + 2487, 3482, + 2487, 3481, + 2486, 3481, + 2486, 3474, + 2488, 3474, + 2488, 3471, + 2489, 3471, + 2489, 3470, + 2490, 3470, + 2490, 3460, + 2491, 3460, + 2491, 3456, + 2496, 3456, + 2496, 3440, + 2495, 3440); + + // Rellekka + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2620, 3682, + 2624, 3682, + 2624, 3683, + 2625, 3683, + 2625, 3687, + 2629, 3687, + 2629, 3686, + 2630, 3686, + 2630, 3685, + 2632, 3685, + 2632, 3686, + 2636, 3686, + 2636, 3692, + 2645, 3692, + 2645, 3695, + 2647, 3695, + 2647, 3696, + 2649, 3696, + 2649, 3702, + 2650, 3702, + 2650, 3703, + 2651, 3703, + 2651, 3704, + 2652, 3704, + 2652, 3711, + 2653, 3711, + 2653, 3712, + 2691, 3712, + 2691, 3709, + 2692, 3709, + 2692, 3707, + 2693, 3707, + 2693, 3703, + 2692, 3703, + 2692, 3701, + 2691, 3701, + 2691, 3699, + 2690, 3699, + 2690, 3695, + 2691, 3695, + 2691, 3693, + 2692, 3693, + 2692, 3691, + 2693, 3691, + 2693, 3685, + 2692, 3685, + 2692, 3683, + 2691, 3683, + 2691, 3681, + 2690, 3681, + 2690, 3680, + 2689, 3680, + 2689, 3672, + 2690, 3672, + 2690, 3671, + 2691, 3671, + 2691, 3666, + 2690, 3666, + 2690, 3664, + 2689, 3664, + 2689, 3660, + 2690, 3660, + 2690, 3658, + 2691, 3658, + 2691, 3656, + 2692, 3656, + 2692, 3654, + 2693, 3654, + 2693, 3651, + 2692, 3651, + 2692, 3649, + 2690, 3649, + 2690, 3648, + 2688, 3648, + 2688, 3647, + 2686, 3647, + 2686, 3646, + 2673, 3646, + 2673, 3645, + 2636, 3645, + 2636, 3647, + 2627, 3647, + 2627, 3648, + 2625, 3648, + 2625, 3649, + 2624, 3649, + 2624, 3650, + 2622, 3650, + 2622, 3651, + 2620, 3651, + 2620, 3652, + 2618, 3652, + 2618, 3653, + 2616, 3653, + 2616, 3654, + 2609, 3654, + 2609, 3655, + 2607, 3655, + 2607, 3656, + 2603, 3656, + 2603, 3657, + 2602, 3657, + 2602, 3658, + 2601, 3658, + 2601, 3663, + 2602, 3663, + 2602, 3664, + 2603, 3664, + 2603, 3665, + 2604, 3665, + 2604, 3666, + 2605, 3666, + 2605, 3667, + 2606, 3667, + 2606, 3671, + 2609, 3671, + 2609, 3672, + 2610, 3672, + 2610, 3673, + 2611, 3673, + 2611, 3675, + 2612, 3675, + 2612, 3676, + 2614, 3676, + 2614, 3677, + 2616, 3677, + 2616, 3679, + 2618, 3679, + 2618, 3681, + 2620, 3681); + + // Jatizo + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2407, 3797, + 2407, 3793, + 2399, 3793, + 2399, 3792, + 2391, 3792, + 2391, 3791, + 2386, 3791, + 2386, 3796, + 2388, 3796, + 2388, 3802, + 2386, 3802, + 2386, 3807, + 2388, 3807, + 2388, 3809, + 2402, 3809, + 2402, 3819, + 2406, 3819, + 2406, 3824, + 2408, 3824, + 2408, 3826, + 2413, 3826, + 2413, 3824, + 2419, 3824, + 2419, 3826, + 2424, 3826, + 2424, 3821, + 2423, 3821, + 2423, 3798, + 2422, 3798, + 2422, 3797); + + // Neitiznot + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2329, 3812, + 2333, 3812, + 2333, 3813, + 2334, 3813, + 2334, 3814, + 2335, 3814, + 2335, 3815, + 2338, 3815, + 2338, 3816, + 2339, 3816, + 2339, 3817, + 2368, 3817, + 2368, 3776, + 2352, 3776, + 2352, 3796, + 2344, 3796, + 2344, 3795, + 2331, 3795, + 2331, 3797, + 2330, 3797, + 2330, 3798, + 2329, 3798); + + // Pest control + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2624, 2688, + 2688, 2688, + 2688, 2624, + 2624, 2624); + + // Tutorial island + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 3052, 3135, + 3156, 3135, + 3156, 3057, + 3052, 3057); + + // Camelot bank + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2724, 3487, + 2724, 3490, + 2721, 3490, + 2721, 3494, + 2719, 3494, + 2719, 3497, + 2721, 3497, + 2721, 3498, + 2731, 3498, + 2731, 3490, + 2728, 3490, + 2728, 3487); + + // Catherby bank + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 2806, 3438, + 2806, 3446, + 2813, 3446, + 2813, 3438); + + // Kourend castle + addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, + 1627, 3658, + 1620, 3658, + 1620, 3657, + 1619, 3657, + 1619, 3656, + 1614, 3656, + 1614, 3657, + 1613, 3657, + 1613, 3661, + 1612, 3661, + 1612, 3662, + 1611, 3662, + 1611, 3663, + 1600, 3663, + 1600, 3662, + 1599, 3662, + 1599, 3661, + 1594, 3661, + 1594, 3662, + 1593, 3662, + 1593, 3685, + 1594, 3685, + 1594, 3686, + 1599, 3686, + 1599, 3685, + 1600, 3685, + 1600, 3684, + 1611, 3684, + 1611, 3685, + 1612, 3685, + 1612, 3686, + 1613, 3686, + 1613, 3690, + 1614, 3690, + 1614, 3691, + 1619, 3691, + 1619, 3690, + 1620, 3690, + 1620, 3689, + 1630, 3689, + 1630, 3686, + 1620, 3686, + 1620, 3685, + 1619, 3685, + 1619, 3683, + 1620, 3683, + 1620, 3682, + 1621, 3682, + 1621, 3681, + 1622, 3681, + 1622, 3680, + 1623, 3680, + 1623, 3679, + 1624, 3679, + 1624, 3668, + 1623, 3668, + 1623, 3667, + 1622, 3667, + 1622, 3666, + 1621, 3666, + 1621, 3665, + 1620, 3665, + 1620, 3664, + 1619, 3664, + 1619, 3662, + 1620, 3662, + 1620, 3661, + 1627, 3661); + } + + private static void definePvpSafeZones() + { + // Grand exchange + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3159, 3473, + 3159, 3474, + 3157, 3474, + 3157, 3475, + 3155, 3475, + 3155, 3476, + 3153, 3476, + 3153, 3477, + 3152, 3477, + 3152, 3478, + 3151, 3478, + 3151, 3480, + 3150, 3480, + 3150, 3482, + 3149, 3482, + 3149, 3484, + 3148, 3484, + 3148, 3496, + 3149, 3496, + 3149, 3498, + 3150, 3498, + 3150, 3500, + 3151, 3500, + 3151, 3502, + 3152, 3502, + 3152, 3503, + 3153, 3503, + 3153, 3504, + 3155, 3504, + 3155, 3505, + 3157, 3505, + 3157, 3506, + 3159, 3506, + 3159, 3507, + 3171, 3507, + 3171, 3506, + 3173, 3506, + 3173, 3505, + 3175, 3505, + 3175, 3504, + 3177, 3504, + 3177, 3503, + 3178, 3503, + 3178, 3502, + 3179, 3502, + 3179, 3500, + 3180, 3500, + 3180, 3498, + 3181, 3498, + 3181, 3496, + 3182, 3496, + 3182, 3484, + 3181, 3484, + 3181, 3482, + 3180, 3482, + 3180, 3480, + 3179, 3480, + 3179, 3478, + 3178, 3478, + 3178, 3477, + 3177, 3477, + 3177, 3476, + 3175, 3476, + 3175, 3475, + 3173, 3475, + 3173, 3474, + 3171, 3474, + 3171, 3473); + + // Edgeville + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3091, 3488, + 3091, 3493, + 3090, 3493, + 3090, 3498, + 3091, 3498, + 3091, 3500, + 3099, 3500, + 3099, 3488); + + // Fally west bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2943, 3368, + 2943, 3374, + 2948, 3374, + 2948, 3370, + 2950, 3370, + 2950, 3366, + 2949, 3366, + 2949, 3359, + 2945, 3359, + 2945, 3362, + 2946, 3362, + 2946, 3366, + 2945, 3366, + 2945, 3368); + + // Fally east bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3009, 3353, + 3009, 3359, + 3019, 3359, + 3019, 3357, + 3022, 3357, + 3022, 3353); + + // Fally castle + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2964, 3354, + 2966, 3354, + 2966, 3352, + 2967, 3352, + 2967, 3349, + 2976, 3349, + 2976, 3348, + 2977, 3348, + 2977, 3347, + 2981, 3347, + 2981, 3343, + 2982, 3343, + 2982, 3339, + 2981, 3339, + 2981, 3337, + 2967, 3337, + 2967, 3330, + 2963, 3330, + 2963, 3331, + 2962, 3331, + 2962, 3332, + 2961, 3332, + 2961, 3334, + 2964, 3334, + 2964, 3335, + 2965, 3335, + 2965, 3343, + 2964, 3343, + 2964, 3344, + 2961, 3344, + 2961, 3350, + 2963, 3350, + 2963, 3352, + 2964, 3352); + + // Varrock east bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3250, 3425, + 3258, 3425, + 3258, 3416, + 3250, 3416); + + // Varrock west bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3180, 3433, + 3180, 3448, + 3191, 3448, + 3191, 3433); + + // Port phasmatys + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3686, 3472, + 3700, 3472, + 3700, 3461, + 3686, 3461); + + // Yanille bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2609, 3088, + 2609, 3098, + 2617, 3098, + 2617, 3088); + + // Ardy east bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2649, 3280, + 2649, 3288, + 2659, 3288, + 2659, 3280); + + // Ardy west bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2612, 3330, + 2612, 3336, + 2615, 3336, + 2615, 3335, + 2619, 3335, + 2619, 3336, + 2622, 3336, + 2622, 3330); + + // Fishing guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2593, 3413, + 2588, 3413, + 2588, 3418, + 2583, 3418, + 2583, 3423, + 2590, 3423, + 2590, 3420, + 2593, 3420); + + // Gnome stronghold bank near slayer cave (2nd floor) + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, + 2444, 3431, + 2444, 3435, + 2448, 3435, + 2448, 3431, + 2447, 3431, + 2447, 3428, + 2449, 3428, + 2449, 3422, + 2447, 3422, + 2447, 3419, + 2448, 3419, + 2448, 3415, + 2444, 3415, + 2444, 3419, + 2445, 3419, + 2445, 3422, + 2443, 3422, + 2443, 3428, + 2445, 3428, + 2445, 3431); + + // Gnome stronghold bank in grand tree + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, + 2456, 3488, + 2452, 3488, + 2452, 3486, + 2450, 3486, + 2450, 3483, + 2451, 3483, + 2451, 3478, + 2448, 3478, + 2448, 3483, + 2449, 3483, + 2449, 3486, + 2447, 3486, + 2447, 3488, + 2443, 3488, + 2443, 3487, + 2438, 3487, + 2438, 3490, + 2443, 3490, + 2443, 3489, + 2447, 3489, + 2447, 3491, + 2449, 3491, + 2449, 3494, + 2448, 3494, + 2448, 3496, + 2451, 3496, + 2451, 3494, + 2450, 3494, + 2450, 3491, + 2452, 3491, + 2452, 3489, + 2456, 3489); + + // Al kharid bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3265, 3161, + 3265, 3174, + 3273, 3174, + 3273, 3161); + + // Shantay pass bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3308, 3119, + 3308, 3125, + 3310, 3125, + 3310, 3119); + + // Nardah bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3431, 2891, + 3431, 2889, + 3427, 2889, + 3427, 2887, + 3424, 2887, + 3424, 2895, + 3431, 2895, + 3431, 2893, + 3432, 2893, + 3432, 2891); + + // Sophanem bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2807, 5158, + 2792, 5158, + 2792, 5175, + 2807, 5175); + + // Canifis bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3509, 3474, + 3509, 3478, + 3508, 3478, + 3508, 3483, + 3509, 3483, + 3509, 3484, + 3517, 3484, + 3517, 3477, + 3516, 3477, + 3516, 3476, + 3513, 3476, + 3513, 3474); + + // Lumbridge castle outside + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3216, 3209, + 3216, 3210, + 3217, 3210, + 3217, 3228, + 3216, 3228, + 3216, 3229, + 3227, 3229, + 3227, 3221, + 3230, 3221, + 3230, 3217, + 3227, 3217, + 3227, 3209); + + // Lumbridge bank upstairs + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, + 3211, 3223, + 3211, 3215, + 3207, 3215, + 3207, 3223); + + // Draynor bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3098, 3240, + 3088, 3240, + 3088, 3247, + 3098, 3247); + + // Pest control bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2665, 2656, + 2670, 2656, + 2670, 2651, + 2665, 2651); + + // Shilo village bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2843, 2957, + 2846, 2957, + 2846, 2956, + 2849, 2956, + 2849, 2957, + 2850, 2957, + 2850, 2958, + 2855, 2958, + 2855, 2957, + 2856, 2957, + 2856, 2956, + 2858, 2956, + 2858, 2957, + 2862, 2957, + 2862, 2952, + 2858, 2952, + 2858, 2953, + 2856, 2953, + 2856, 2952, + 2855, 2952, + 2855, 2951, + 2850, 2951, + 2850, 2952, + 2849, 2952, + 2849, 2953, + 2847, 2953, + 2847, 2952, + 2843, 2952); + + // Legends guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, + 2731, 3374, + 2731, 3383, + 2734, 3383, + 2734, 3374); + + // Legends guild middle floor + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, + 2724, 3374, + 2724, 3383, + 2734, 3383, + 2734, 3382, + 2736, 3382, + 2736, 3375, + 2734, 3375, + 2734, 3374); + + // Warriors guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2843, 3537, + 2843, 3540, + 2841, 3540, + 2841, 3546, + 2849, 3546, + 2849, 3537, + 2847, 3537, + 2847, 3536, + 2846, 3536, + 2846, 3537); + + // Camelot bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2724, 3487, + 2724, 3490, + 2721, 3490, + 2721, 3494, + 2719, 3494, + 2719, 3497, + 2721, 3497, + 2721, 3498, + 2731, 3498, + 2731, 3490, + 2728, 3490, + 2728, 3487); + + // Camelot respawn point + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2761, 3483, + 2761, 3476, + 2755, 3476, + 2755, 3483); + + // Catherby bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2806, 3438, + 2806, 3446, + 2813, 3446, + 2813, 3438); + + // Barbarian outpost bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2536, 3572, + 2536, 3575, + 2538, 3575, + 2538, 3572); + + // Piscatoris bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2327, 3686, + 2327, 3694, + 2333, 3694, + 2333, 3686); + + // Lletya bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2350, 3161, + 2350, 3165, + 2351, 3165, + 2351, 3167, + 2357, 3167, + 2357, 3165, + 2356, 3165, + 2356, 3164, + 2355, 3164, + 2355, 3161); + + // Castle wars bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2446, 3087, + 2445, 3087, + 2445, 3085, + 2447, 3085, + 2447, 3081, + 2443, 3081, + 2443, 3082, + 2439, 3082, + 2439, 3081, + 2435, 3081, + 2435, 3099, + 2439, 3099, + 2439, 3098, + 2443, 3098, + 2443, 3099, + 2447, 3099, + 2447, 3095, + 2445, 3095, + 2445, 3093, + 2446, 3093); + + // Duel arena bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3380, 3267, + 3380, 3273, + 3381, 3273, + 3381, 3274, + 3385, 3274, + 3385, 3267); + + // Clan wars bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3375, 3165, + 3361, 3165, + 3361, 3173, + 3375, 3173); + + // Lumbridge cellar bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 3218, 9622, + 3218, 9624, + 3220, 9624, + 3220, 9622); + + // Dorgesh kaan bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2709, 5348, + 2707, 5348, + 2707, 5345, + 2701, 5345, + 2701, 5347, + 2697, 5347, + 2697, 5353, + 2701, 5353, + 2701, 5355, + 2707, 5355, + 2707, 5350, + 2709, 5350); + + // Keldagrim bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2842, 10204, + 2834, 10204, + 2834, 10216, + 2842, 10216); + + // Tzhaar bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2438, 5176, + 2438, 5180, + 2441, 5180, + 2441, 5182, + 2449, 5182, + 2449, 5181, + 2450, 5181, + 2450, 5180, + 2452, 5180, + 2452, 5175, + 2441, 5175, + 2441, 5176); + + // Inferno bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2542, 5135, + 2542, 5139, + 2539, 5139, + 2539, 5140, + 2538, 5140, + 2538, 5141, + 2537, 5141, + 2537, 5144, + 2541, 5144, + 2541, 5145, + 2543, 5145, + 2543, 5144, + 2544, 5144, + 2544, 5142, + 2545, 5142, + 2545, 5135); + + // Port khazard bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2661, 3160, + 2661, 3163, + 2666, 3163, + 2666, 3160); + + // Corsair cove bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2569, 2863, + 2569, 2868, + 2572, 2868, + 2572, 2863); + + // Burgh de rott bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3495, 3210, + 3495, 3214, + 3501, 3214, + 3501, 3210); + + // Edgeville respawn point + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3092, 3468, + 3092, 3474, + 3098, 3474, + 3098, 3468); + + // Mage bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2529, 4711, + 2529, 4724, + 2548, 4724, + 2548, 4711); + + // Lunar bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2097, 3917, + 2097, 3922, + 2105, 3922, + 2105, 3917); + + // Jatizo bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2414, 3801, + 2414, 3804, + 2420, 3804, + 2420, 3801); + + // Neitiznot bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2334, 3805, + 2334, 3809, + 2340, 3809, + 2340, 3805); + + // Hosidius bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1671, 3558, + 1671, 3577, + 1682, 3577, + 1682, 3558); + + // Woodcutting guild bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1589, 3475, + 1589, 3481, + 1594, 3481, + 1594, 3475); + + // Lands end bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1508, 3415, + 1508, 3424, + 1514, 3424, + 1514, 3415); + + // Chambers of xeric bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1252, 3570, + 1252, 3574, + 1257, 3574, + 1257, 3570); + + // Arceuus bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1621, 3736, + 1621, 3754, + 1627, 3754, + 1627, 3751, + 1633, 3751, + 1633, 3754, + 1639, 3754, + 1639, 3736); + + // Piscarilius bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1794, 3784, + 1794, 3794, + 1812, 3794, + 1812, 3784); + + // Lovakengj bank southeast + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1518, 3735, + 1518, 3744, + 1535, 3744, + 1535, 3735); + + // Lovakenj bank west + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1433, 3820, + 1433, 3837, + 1442, 3837, + 1442, 3820); + + // Lovakenj sulphur mine bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1452, 3855, + 1452, 3860, + 1455, 3860, + 1455, 3855); + + // Blast mine bank southeast + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1500, 3856, + 1500, 3858, + 1503, 3858, + 1503, 3856); + + // Wintertodt bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1638, 3942, + 1638, 3947, + 1642, 3947, + 1642, 3942); + + // Shayzien bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1495, 3612, + 1495, 3622, + 1515, 3622, + 1515, 3612); + + // Hosidius grape farm bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1804, 3571, + 1804, 3572, + 1808, 3572, + 1808, 3571); + + // Hosidius cooking bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 1652, 3605, + 1652, 3615, + 1661, 3615, + 1661, 3605); + + // Ecteria bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 2618, 3893, + 2618, 3897, + 2622, 3897, + 2622, 3893); + + // Mining guild expanded area + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 3018, 9733, + 3021, 9733, + 3021, 9729, + 3022, 9729, + 3022, 9728, + 3023, 9728, + 3023, 9727, + 3025, 9727, + 3025, 9726, + 3026, 9726, + 3026, 9725, + 3030, 9725, + 3030, 9726, + 3032, 9726, + 3032, 9727, + 3035, 9727, + 3035, 9726, + 3038, 9726, + 3038, 9727, + 3041, 9727, + 3041, 9728, + 3042, 9728, + 3042, 9730, + 3045, 9730, + 3045, 9727, + 3047, 9727, + 3047, 9726, + 3048, 9726, + 3048, 9724, + 3052, 9724, + 3052, 9725, + 3053, 9725, + 3053, 9726, + 3055, 9726, + 3055, 9725, + 3056, 9725, + 3056, 9723, + 3057, 9723, + 3057, 9720, + 3056, 9720, + 3056, 9719, + 3054, 9719, + 3054, 9718, + 3052, 9718, + 3052, 9717, + 3050, 9717, + 3050, 9718, + 3045, 9718, + 3045, 9716, + 3044, 9716, + 3044, 9715, + 3041, 9715, + 3041, 9714, + 3039, 9714, + 3039, 9713, + 3037, 9713, + 3037, 9714, + 3036, 9714, + 3036, 9715, + 3034, 9715, + 3034, 9716, + 3029, 9716, + 3029, 9715, + 3028, 9715, + 3028, 9714, + 3026, 9714, + 3026, 9709, + 3027, 9709, + 3027, 9708, + 3028, 9708, + 3028, 9705, + 3029, 9705, + 3029, 9701, + 3028, 9701, + 3028, 9700, + 3027, 9700, + 3027, 9699, + 3023, 9699, + 3023, 9700, + 3019, 9700, + 3019, 9701, + 3018, 9701, + 3018, 9705, + 3019, 9705, + 3019, 9707, + 3020, 9707, + 3020, 9708, + 3021, 9708, + 3021, 9709, + 3022, 9709, + 3022, 9713, + 3021, 9713, + 3021, 9714, + 3019, 9714, + 3019, 9715, + 3018, 9715, + 3018, 9717, + 3015, 9717, + 3015, 9716, + 3013, 9716, + 3013, 9717, + 3012, 9717, + 3012, 9720, + 3013, 9720, + 3013, 9721, + 3015, 9721, + 3015, 9723, + 3016, 9723, + 3016, 9727, + 3017, 9727, + 3017, 9730, + 3018, 9730); + + // Motherlode mine bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 3760, 5671, + 3760, 5668, + 3761, 5668, + 3761, 5665, + 3760, 5665, + 3760, 5663, + 3758, 5663, + 3758, 5671); + + // Mos le harmles bank + addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, + 3679, 2980, + 3679, 2985, + 3681, 2985, + 3681, 2984, + 3682, 2984, + 3682, 2985, + 3684, 2985, + 3684, 2980, + 3682, 2980, + 3682, 2981, + 3681, 2981, + 3681, 2980); + + // Zanaris bank + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 2388, 4454, + 2380, 4454, + 2380, 4463, + 2388, 4463); + + // Wodcuting guild bank underground + addPolygonTo(PVP_WORLD_SAFE_ZONES, + 1550, 9872, + 1550, 9874, + 1553, 9874, + 1553, 9872); + } + + private static void defineWilderness() + { + // Above ground + addPolygonTo(ROUGH_WILDERNESS, + 2944, 3523, + 3392, 3523, + 3392, 3971, + 2944, 3971); + + // Underground + addPolygonTo(ROUGH_WILDERNESS, + 2944, 9918, + 2944, 10360, + 3264, 10360, + 3264, 9918); + } + + private static void addPolygonTo(List[] shapes, int... coords) + { + Polygon poly = new Polygon(); + for (int i = 0; i < coords.length; i += 2) + { + poly.addPoint(coords[i], coords[i + 1]); + } + for (int i = 0; i < shapes.length; i++) + { + shapes[i].add(poly); + } + } + + private static void addPolygonOnPlane(List[] shapes, int plane, int... coords) + { + Polygon poly = new Polygon(); + for (int i = 0; i < coords.length; i += 2) + { + poly.addPoint(coords[i], coords[i + 1]); + } + shapes[plane].add(poly); + } + + private static void addPolygonOnPlanes(List[] shapes, int minPlane, int maxPlane, int... coords) + { + Polygon poly = new Polygon(); + for (int i = 0; i < coords.length; i += 2) + { + poly.addPoint(coords[i], coords[i + 1]); + } + for (int i = minPlane; i <= maxPlane; i++) + { + shapes[i].add(poly); + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java new file mode 100644 index 0000000000..370533dac7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018, Woox + * 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.zoneIndicators; + +import java.awt.Color; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("zoneIndicators") +public interface ZoneIndicatorsConfig extends Config +{ + @ConfigItem( + keyName = "multicombatZoneVisibility", + name = "Multicombat zones", + description = "Determine where multicombat zones should be shown", + position = 1 + ) + default ZoneVisibility multicombatZoneVisibility() + { + return ZoneVisibility.SHOW_IN_PVP; + } + + @ConfigItem( + keyName = "pvpSafeZones", + name = "PvP safe zones", + description = "Show safe zones in PvP worlds", + position = 2 + ) + default boolean showPvpSafeZones() + { + return true; + } + + @ConfigItem( + keyName = "deadmanSafeZones", + name = "Deadman safe zones", + description = "Show safe zones in Deadman worlds", + position = 3 + ) + default boolean showDeadmanSafeZones() + { + return true; + } + + @ConfigItem( + keyName = "collisionDetection", + name = "Collision detection", + description = "Only show lines where they can be walked through", + position = 4 + ) + default boolean collisionDetection() + { + return false; + } + + @ConfigItem( + keyName = "showMinimapLines", + name = "Show on minimap", + description = "Show multicombat and safe zones on the minimap", + position = 5 + ) + default boolean showMinimapLines() + { + return true; + } + + @ConfigItem( + keyName = "multicombatColor", + name = "Multicombat zone color", + description = "Choose color to use for marking multicombat zones", + position = 6 + ) + default Color multicombatColor() + { + return Color.MAGENTA; + } + + @ConfigItem( + keyName = "safeZoneColor", + name = "Safe zone color", + description = "Choose color to use for marking safe zones in PvP/Deadman", + position = 7 + ) + default Color safeZoneColor() + { + return Color.GREEN; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java new file mode 100644 index 0000000000..699b0f0ddf --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018, Woox + * 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.zoneIndicators; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.geometry.Geometry; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +public class ZoneIndicatorsMinimapOverlay extends Overlay +{ + private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; + + @Inject + private Client client; + + @Inject + private ZoneIndicatorsPlugin plugin; + + @Inject + private ZoneIndicatorsConfig config; + + @Inject + public ZoneIndicatorsMinimapOverlay() + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ALWAYS_ON_TOP); + setPriority(OverlayPriority.LOW); + } + + private Color getTransparentColorVersion(Color c) + { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), 192); + } + + private void renderPath(Graphics2D graphics, GeneralPath path, Color color) + { + LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); + Rectangle viewArea = new Rectangle( + playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, + playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, + MAX_LOCAL_DRAW_LENGTH * 2, + MAX_LOCAL_DRAW_LENGTH * 2); + + graphics.setColor(color); + + path = Geometry.clipPath(path, viewArea); + path = Geometry.filterPath(path, (p1, p2) -> + Perspective.localToMinimap(client, new LocalPoint((int)p1[0], (int)p1[1])) != null && + Perspective.localToMinimap(client, new LocalPoint((int)p2[0], (int)p2[1])) != null); + path = Geometry.transformPath(path, coords -> + { + Point point = Perspective.localToMinimap(client, new LocalPoint((int)coords[0], (int)coords[1])); + coords[0] = point.getX(); + coords[1] = point.getY(); + }); + + graphics.draw(path); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!config.showMinimapLines()) + { + return null; + } + + GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; + GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; + + if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) + { + renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); + } + if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) + { + renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); + } + + return null; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java new file mode 100644 index 0000000000..0f52222e8b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018, Woox + * 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.zoneIndicators; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.geometry.Geometry; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +public class ZoneIndicatorsOverlay extends Overlay +{ + private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; + + @Inject + private Client client; + + @Inject + private ZoneIndicatorsPlugin plugin; + + @Inject + private ZoneIndicatorsConfig config; + + @Inject + public ZoneIndicatorsOverlay() + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + setPriority(OverlayPriority.LOW); + } + + private Color getTransparentColorVersion(Color c) + { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), 92); + } + + private void renderPath(Graphics2D graphics, GeneralPath path, Color color) + { + LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); + Rectangle viewArea = new Rectangle( + playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, + playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, + MAX_LOCAL_DRAW_LENGTH * 2, + MAX_LOCAL_DRAW_LENGTH * 2); + + graphics.setColor(color); + graphics.setStroke(new BasicStroke(2)); + + path = Geometry.clipPath(path, viewArea); + path = Geometry.filterPath(path, (p1, p2) -> + Perspective.localToCanvas(client, new LocalPoint((int)p1[0], (int)p1[1]), client.getPlane()) != null && + Perspective.localToCanvas(client, new LocalPoint((int)p2[0], (int)p2[1]), client.getPlane()) != null); + path = Geometry.transformPath(path, coords -> + { + Point point = Perspective.localToCanvas(client, new LocalPoint((int)coords[0], (int)coords[1]), client.getPlane()); + coords[0] = point.getX(); + coords[1] = point.getY(); + }); + + graphics.draw(path); + } + + @Override + public Dimension render(Graphics2D graphics) + { + GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; + GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; + + if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) + { + renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); + } + if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) + { + renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); + } + + return null; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java new file mode 100644 index 0000000000..5f3397e900 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2018, Woox + * 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.zoneIndicators; + +import net.runelite.client.eventbus.Subscribe; +import com.google.inject.Provides; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; +import java.util.Arrays; +import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Constants; +import net.runelite.api.GameState; +import net.runelite.api.ObjectComposition; +import net.runelite.api.Perspective; +import net.runelite.api.Tile; +import net.runelite.api.WallObject; +import net.runelite.api.WorldType; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldArea; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.geometry.Geometry; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +@PluginDescriptor( + name = "!MultiLines", + description = "Show borders of multicombat and PvP safezones", + tags = {"multicombat", "lines", "pvp", "deadman", "safezones", "bogla"}, + enabledByDefault = false +) +public class ZoneIndicatorsPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Inject + private ZoneIndicatorsConfig config; + + @Inject + private ZoneIndicatorsOverlay overlay; + + @Inject + private ZoneIndicatorsMinimapOverlay minimapOverlay; + + @Inject + private OverlayManager overlayManager; + + @Getter + private GeneralPath[] multicombatPathToDisplay; + + @Getter + private GeneralPath[] pvpPathToDisplay; + + @Getter + private boolean inPvp; + + @Getter + private boolean inDeadman; + + private int currentPlane; + + @Provides + ZoneIndicatorsConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(ZoneIndicatorsConfig.class); + } + + @Override + protected void startUp() throws Exception + { + overlayManager.add(overlay); + overlayManager.add(minimapOverlay); + + multicombatPathToDisplay = new GeneralPath[Constants.MAX_Z]; + pvpPathToDisplay = new GeneralPath[Constants.MAX_Z]; + + clientThread.invokeLater(() -> + { + if (client.getGameState() == GameState.LOGGED_IN) + { + findLinesInScene(); + } + }); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + overlayManager.remove(minimapOverlay); + + multicombatPathToDisplay = null; + pvpPathToDisplay = null; + } + + private void transformWorldToLocal(float[] coords) + { + LocalPoint lp = LocalPoint.fromWorld(client, (int)coords[0], (int)coords[1]); + coords[0] = lp.getX() - Perspective.LOCAL_TILE_SIZE / 2; + coords[1] = lp.getY() - Perspective.LOCAL_TILE_SIZE / 2; + } + + private boolean isOpenableAt(WorldPoint wp) + { + int sceneX = wp.getX() - client.getBaseX(); + int sceneY = wp.getY() - client.getBaseY(); + + Tile tile = client.getScene().getTiles()[wp.getPlane()][sceneX][sceneY]; + if (tile == null) + { + return false; + } + + WallObject wallObject = tile.getWallObject(); + if (wallObject == null) + { + return false; + } + + ObjectComposition objectComposition = client.getObjectDefinition(wallObject.getId()); + if (objectComposition == null) + { + return false; + } + + String[] actions = objectComposition.getActions(); + if (actions == null) + { + return false; + } + + return Arrays.stream(actions).anyMatch(x -> x != null && x.toLowerCase().equals("open")); + } + + private boolean collisionFilter(float[] p1, float[] p2) + { + int x1 = (int)p1[0]; + int y1 = (int)p1[1]; + int x2 = (int)p2[0]; + int y2 = (int)p2[1]; + + if (x1 > x2) + { + int temp = x1; + x1 = x2; + x2 = temp; + } + if (y1 > y2) + { + int temp = y1; + y1 = y2; + y2 = temp; + } + int dx = x2 - x1; + int dy = y2 - y1; + WorldArea wa1 = new WorldArea(new WorldPoint( + x1, y1, currentPlane), 1, 1); + WorldArea wa2 = new WorldArea(new WorldPoint( + x1 - dy, y1 - dx, currentPlane), 1, 1); + + if (isOpenableAt(wa1.toWorldPoint()) || isOpenableAt(wa2.toWorldPoint())) + { + // When there's something with the open option (e.g. a door) on the tile, + // we assume it can be opened and walked through afterwards. Without this + // check, the line for that tile wouldn't render with collision detection + // because the collision check isn't done if collision data changes. + return true; + } + + boolean b1 = wa1.canTravelInDirection(client, -dy, -dx); + boolean b2 = wa2.canTravelInDirection(client, dy, dx); + return b1 && b2; + } + + private void findLinesInScene() + { + inDeadman = client.getWorldType().stream().anyMatch(x -> + x == WorldType.DEADMAN || x == WorldType.SEASONAL_DEADMAN); + inPvp = client.getWorldType().stream().anyMatch(x -> + x == WorldType.PVP || x == WorldType.PVP_HIGH_RISK); + + Rectangle sceneRect = new Rectangle( + client.getBaseX() + 1, client.getBaseY() + 1, + Constants.SCENE_SIZE - 2, Constants.SCENE_SIZE - 2); + + // Generate lines for multicombat zones + if (config.multicombatZoneVisibility() == ZoneVisibility.HIDE) + { + for (int i = 0; i < multicombatPathToDisplay.length; i++) + { + multicombatPathToDisplay[i] = null; + } + } + else + { + for (int i = 0; i < multicombatPathToDisplay.length; i++) + { + currentPlane = i; + + GeneralPath lines = new GeneralPath(MapLocations.getMulticombat(sceneRect, i)); + lines = Geometry.clipPath(lines, sceneRect); + if (config.multicombatZoneVisibility() == ZoneVisibility.SHOW_IN_PVP && + !isInDeadman() && !isInPvp()) + { + lines = Geometry.clipPath(lines, MapLocations.getRoughWilderness(i)); + } + lines = Geometry.splitIntoSegments(lines, 1); + if (config.collisionDetection()) + { + lines = Geometry.filterPath(lines, this::collisionFilter); + } + lines = Geometry.transformPath(lines, this::transformWorldToLocal); + multicombatPathToDisplay[i] = lines; + } + } + + // Generate safezone lines for deadman/pvp worlds + for (int i = 0; i < pvpPathToDisplay.length; i++) + { + currentPlane = i; + + GeneralPath safeZonePath = null; + if (config.showDeadmanSafeZones() && isInDeadman()) + { + safeZonePath = new GeneralPath(MapLocations.getDeadmanSafeZones(sceneRect, i)); + } + else if (config.showPvpSafeZones() && isInPvp()) + { + safeZonePath = new GeneralPath(MapLocations.getPvpSafeZones(sceneRect, i)); + } + if (safeZonePath != null) + { + safeZonePath = Geometry.clipPath(safeZonePath, sceneRect); + safeZonePath = Geometry.splitIntoSegments(safeZonePath, 1); + if (config.collisionDetection()) + { + safeZonePath = Geometry.filterPath(safeZonePath, this::collisionFilter); + } + safeZonePath = Geometry.transformPath(safeZonePath, this::transformWorldToLocal); + } + pvpPathToDisplay[i] = safeZonePath; + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getKey().equals("collisionDetection") || + event.getKey().equals("multicombatZoneVisibility") || + event.getKey().equals("deadmanSafeZones") || + event.getKey().equals("pvpSafeZones")) + { + findLinesInScene(); + } + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState() == GameState.LOGGED_IN) + { + findLinesInScene(); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java new file mode 100644 index 0000000000..9a457d9e50 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, Woox + * 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.zoneIndicators; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum ZoneVisibility +{ + HIDE("Hide"), + SHOW_IN_PVP("Show in PvP"), + SHOW_EVERYWHERE("Show everywhere"); + + private final String visibility; + + @Override + public String toString() + { + return visibility; + } +} \ No newline at end of file From 447aaf6a2503e36a33f3439f419c90f9fe7d6e6f Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 18:59:13 +0100 Subject: [PATCH 04/21] additional plugins --- .../fkeyremapping/fKeyRemappingPlugin.java | 1 + .../groupitemlist/GroupItemListPlugin.java | 1 + .../inventorysetups/InventorySetup.java | 15 + .../InventorySetupBankOverlay.java | 113 +++++ .../inventorysetups/InventorySetupConfig.java | 84 ++++ .../inventorysetups/InventorySetupItem.java | 15 + .../inventorysetups/InventorySetupPlugin.java | 403 ++++++++++++++++++ .../ui/InventorySetupContainerPanel.java | 109 +++++ .../ui/InventorySetupEquipmentPanel.java | 91 ++++ .../ui/InventorySetupInventoryPanel.java | 78 ++++ .../ui/InventorySetupPluginPanel.java | 287 +++++++++++++ .../ui/InventorySetupSlot.java | 45 ++ .../LootingBagViewerOverlay.java | 123 ++++++ .../LootingBagViewerPlugin.java | 60 +++ .../raidsthieving/BatSolver/BatSolver.java | 193 +++++++++ .../BatSolver/ChestIdentifier.java | 261 ++++++++++++ .../raidsthieving/BatSolver/SolutionSet.java | 165 +++++++ .../BatSolver/ThievingRoomType.java | 61 +++ .../plugins/raidsthieving/ChestOverlay.java | 172 ++++++++ .../plugins/raidsthieving/InstancePoint.java | 98 +++++ .../raidsthieving/RaidsThievingConfig.java | 67 +++ .../raidsthieving/RaidsThievingConstants.java | 35 ++ .../raidsthieving/RaidsThievingPlugin.java | 270 ++++++++++++ .../plugins/raidsthieving/ThievingChest.java | 78 ++++ .../rememberclan/RememberClanPlugin.java | 1 + .../plugins/safespot/SafeSpotConfig.java | 25 ++ .../plugins/safespot/SafeSpotOverlay.java | 40 ++ .../plugins/safespot/SafeSpotPlugin.java | 135 ++++++ .../plugins/stronghold/StrongholdPlugin.java | 1 + .../warindicators/WarIndicatorPlugin.java | 1 + .../zoneIndicators/ZoneIndicatorsPlugin.java | 1 + 31 files changed, 3029 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConstants.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ThievingChest.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java index 78199bfcc5..050d452811 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fkeyremapping/fKeyRemappingPlugin.java @@ -16,6 +16,7 @@ import net.runelite.client.plugins.PluginDescriptor; name = "fKeyRemapping", description = "Used for interface hotkeys", tags = {"hotkey", "remapping"}, + type = "utility", enabledByDefault = true ) public class fKeyRemappingPlugin extends Plugin diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java index a01716d388..99d9b14831 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java @@ -17,6 +17,7 @@ import java.util.LinkedHashMap; name = "!Group Item List", description = "Group the right click menu of a pile of items.", tags = {"ground", "compress", "pile", "group"}, + type = "utility", enabledByDefault = false ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java new file mode 100644 index 0000000000..043d22a30c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java @@ -0,0 +1,15 @@ +package net.runelite.client.plugins.inventorysetups; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; + +@AllArgsConstructor +public class InventorySetup +{ + @Getter + private ArrayList inventory; + @Getter + private ArrayList equipment; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java new file mode 100644 index 0000000000..34ba341fc7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java @@ -0,0 +1,113 @@ +package net.runelite.client.plugins.inventorysetups; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.Query; +import net.runelite.api.SpritePixels; +import net.runelite.api.queries.BankItemQuery; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.util.QueryRunner; + +import javax.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.util.Arrays; +import java.util.Objects; + +@Slf4j +public class InventorySetupBankOverlay extends Overlay +{ + private final Client client; + private final QueryRunner queryRunner; + private final InventorySetupPlugin plugin; + private final InventorySetupConfig config; + + @Inject + public InventorySetupBankOverlay(Client client, QueryRunner queryRunner, InventorySetupPlugin plugin, InventorySetupConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.LOW); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.client = client; + this.queryRunner = queryRunner; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (config.getBankHighlight()) + { + int[] ids = plugin.getCurrentInventorySetupIds(); + if (ids == null) + { + return null; + } + ids = Arrays.stream(ids) + .filter(Objects::nonNull) + .filter(id -> id != -1) + .toArray(); + final Query query = new BankItemQuery().idEquals(ids); + final WidgetItem[] widgetItems = queryRunner.runQuery(query); + final Widget bankContainer = client.getWidget(WidgetInfo.BANK_CONTAINER); + for (final WidgetItem item : widgetItems) + { + Point canvasLocation = item.getCanvasLocation(); + Rectangle canvasBounds = item.getCanvasBounds(); + Point windowLocation = bankContainer.getCanvasLocation(); + + if (canvasLocation == null || windowLocation == null) + { + return null; + } + + if (!(canvasLocation.getY() + 60 >= windowLocation.getY() + bankContainer.getHeight()) && !(canvasLocation.getY() + canvasBounds.getHeight() <= windowLocation.getY() + 90)) + { + final Color color = config.getBankHighlightColor(); + + if (color != null) + { + final BufferedImage outline = loadItemOutline(item.getId(), item.getQuantity(), color); + graphics.drawImage(outline, item.getCanvasLocation().getX() + 1, item.getCanvasLocation().getY() + 1, null); + if (item.getQuantity() > 1) + { + drawQuantity(graphics, item, Color.YELLOW); + } + else if (item.getQuantity() == 0) + { + drawQuantity(graphics, item, Color.YELLOW.darker()); + } + } + } + } + } + return null; + } + + private void drawQuantity(Graphics2D graphics, WidgetItem item, Color darker) + { + graphics.setColor(Color.BLACK); + graphics.drawString(String.valueOf(item.getQuantity()), item.getCanvasLocation().getX() + 2, item.getCanvasLocation().getY() + 11); + graphics.setColor(darker); + graphics.setFont(FontManager.getRunescapeSmallFont()); + graphics.drawString(String.valueOf(item.getQuantity()), item.getCanvasLocation().getX() + 1, item.getCanvasLocation().getY() + 10); + } + + private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) + { + final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 2, 0, 0, true, 710); + return itemSprite.toBufferedOutline(outlineColor); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java new file mode 100644 index 0000000000..edcc47cd9c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java @@ -0,0 +1,84 @@ +package net.runelite.client.plugins.inventorysetups; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +import java.awt.Color; + +@ConfigGroup("inventorysetups") +public interface InventorySetupConfig extends Config +{ + @ConfigItem( + keyName = "highlightDifferences", + name = "Highlight Differences", + description = "Highlight slots that don't match the selected setup", + position = 0 + ) + + default boolean getHighlightDifferences() + { + return false; + } + + @ConfigItem( + keyName = "highlightDifferenceColor", + name = "Highlight Color", + description = "The color used to highlight differences between setups", + position = 1 + ) + + default Color getHighlightColor() + { + return Color.RED; + } + + @ConfigItem( + keyName = "stackDifference", + name = "Stack Difference", + description = "Differences between setups will be highlighted if the stack size is different", + position = 2 + ) + + default boolean getStackDifference() + { + return false; + } + + @ConfigItem( + keyName = "variationDifference", + name = "Variation Difference", + description = "Variations of items (E.g., charged jewellery) will be counted as different", + position = 2 + ) + + default boolean getVariationDifference() + { + return false; + } + + @ConfigItem( + keyName = "bankHighlight", + name = "Bank Highlight", + description = "Highlight setup items in bank", + position = 4 + ) + + default boolean getBankHighlight() + { + return false; + } + + @ConfigItem( + keyName = "bankHighlightColor", + name = "Bank Highlight Color", + description = "The color used to highlight setup items in bank", + position = 5 + ) + + default Color getBankHighlightColor() + { + return Color.RED; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java new file mode 100644 index 0000000000..c1af4e68fd --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java @@ -0,0 +1,15 @@ +package net.runelite.client.plugins.inventorysetups; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +public class InventorySetupItem +{ + @Getter + private final int id; + @Getter + private final String name; + @Getter + private final int quantity; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java new file mode 100644 index 0000000000..8b9c632498 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java @@ -0,0 +1,403 @@ +package net.runelite.client.plugins.inventorysetups; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.inject.Provides; +import lombok.extern.slf4j.Slf4j; +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.ItemContainer; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.ItemContainerChanged; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemVariationMapping; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.inventorysetups.ui.InventorySetupPluginPanel; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.ImageUtil; + +import javax.inject.Inject; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import java.awt.image.BufferedImage; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; + +@PluginDescriptor( + name = "Inventory Setups", + description = "Save inventory setups", + tags = { "items", "inventory", "setups"}, + type = "utility", + enabledByDefault = false +) + +@Slf4j +public class InventorySetupPlugin extends Plugin +{ + + private static final String CONFIG_GROUP = "inventorysetups"; + private static final String CONFIG_KEY = "setups"; + private static final int NUM_INVENTORY_ITEMS = 28; + private static final int NUM_EQUIPMENT_ITEMS = 14; + + @Inject + private Client client; + + @Inject + private ItemManager itemManager; + + @Inject + private InventorySetupBankOverlay overlay; + + @Inject + private ClientToolbar clientToolbar; + + @Inject + private InventorySetupConfig config; + + @Inject + private OverlayManager overlayManager; + + @Inject + private ClientThread clientThread; + + @Inject + private ConfigManager configManager; + + private InventorySetupPluginPanel panel; + + private HashMap inventorySetups; + + private NavigationButton navButton; + + private boolean highlightDifference; + + @Override + public void startUp() + { + overlayManager.add(overlay); + + panel = new InventorySetupPluginPanel(this, itemManager); + + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "inventorysetups_icon.png"); + + navButton = NavigationButton.builder() + .tooltip("Inventory Setups") + .icon(icon) + .priority(9) + .panel(panel) + .build(); + + clientToolbar.addNavigation(navButton); + + // load all the inventory setups from the config file + clientThread.invokeLater(() -> + { + if (client.getGameState() != GameState.LOGIN_SCREEN) + { + return false; + } + + loadConfig(); + panel.showNoSetupsPanel(); + return true; + }); + + } + + public void addInventorySetup() + { + final String name = JOptionPane.showInputDialog(panel, + "Enter the name of this setup.", + "Add New Setup", + JOptionPane.PLAIN_MESSAGE); + + // cancel button was clicked + if (name == null) + { + return; + } + + if (name.isEmpty()) + { + JOptionPane.showMessageDialog(panel, + "Invalid Setup Name", + "Names must not be empty.", + JOptionPane.PLAIN_MESSAGE); + return; + } + + if (inventorySetups.containsKey(name)) + { + String builder = "The setup " + name + " already exists. " + + "Would you like to replace it with the current setup?"; + int confirm = JOptionPane.showConfirmDialog(panel, + builder, + "Warning", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE); + + if (confirm == JOptionPane.CANCEL_OPTION) + { + return; + } + + // delete the old setup, no need to ask for confirmation + // because the user confirmed above + removeInventorySetup(name, false); + } + + clientThread.invoke(() -> + { + ArrayList inv = getNormalizedContainer(InventoryID.INVENTORY); + ArrayList eqp = getNormalizedContainer(InventoryID.EQUIPMENT); + + final InventorySetup invSetup = new InventorySetup(inv, eqp); + SwingUtilities.invokeLater(() -> + { + inventorySetups.put(name, invSetup); + panel.addInventorySetup(name); + panel.setCurrentInventorySetup(name); + + updateConfig(); + }); + }); + } + + public void removeInventorySetup(final String name, boolean askForConfirmation) + { + if (inventorySetups.containsKey(name)) + { + int confirm = JOptionPane.YES_OPTION; + + if (askForConfirmation) + { + confirm = JOptionPane.showConfirmDialog(panel, + "Are you sure you want to remove this setup?", + "Warning", + JOptionPane.YES_NO_OPTION, + JOptionPane.PLAIN_MESSAGE); + } + + if (confirm == JOptionPane.YES_OPTION) + { + inventorySetups.remove(name); + panel.removeInventorySetup(name); + } + + updateConfig(); + } + } + + public final InventorySetup getInventorySetup(final String name) + { + return inventorySetups.get(name); + } + + @Provides + InventorySetupConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(InventorySetupConfig.class); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals(CONFIG_GROUP)) + { + // only allow highlighting if the config is enabled and the player is logged in + highlightDifference = config.getHighlightDifferences() && client.getGameState() == GameState.LOGGED_IN; + final String setupName = panel.getSelectedInventorySetup(); + if (highlightDifference && !setupName.isEmpty()) + { + panel.setCurrentInventorySetup(setupName); + } + } + } + + private void updateConfig() + { + if (inventorySetups.isEmpty()) + { + configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_KEY); + return; + } + + final Gson gson = new Gson(); + final String json = gson.toJson(inventorySetups); + configManager.setConfiguration(CONFIG_GROUP, CONFIG_KEY, json); + } + + private void loadConfig() + { + // serialize the internal data structure from the json in the configuration + final String json = configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY); + if (json == null || json.isEmpty()) + { + inventorySetups = new HashMap<>(); + } + else + { + // TODO add last resort?, serialize exception just make empty map + final Gson gson = new Gson(); + Type type = new TypeToken>() + { + + }.getType(); + inventorySetups = gson.fromJson(json, type); + } + + for (final String key : inventorySetups.keySet()) + { + panel.addInventorySetup(key); + } + + highlightDifference = false; + } + + @Subscribe + public void onItemContainerChanged(ItemContainerChanged event) + { + + if (!highlightDifference || client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + // empty entry, no need to compare anything + final String selectedInventorySetup = panel.getSelectedInventorySetup(); + if (selectedInventorySetup.isEmpty()) + { + return; + } + + // check to see that the container is the equipment or inventory + ItemContainer container = event.getItemContainer(); + + if (container == client.getItemContainer(InventoryID.INVENTORY)) + { + ArrayList normContainer = getNormalizedContainer(InventoryID.INVENTORY); + final InventorySetup setup = inventorySetups.get(selectedInventorySetup); + panel.highlightDifferences(normContainer, setup, InventoryID.INVENTORY); + } + else if (container == client.getItemContainer(InventoryID.EQUIPMENT)) + { + ArrayList normContainer = getNormalizedContainer(InventoryID.EQUIPMENT); + final InventorySetup setup = inventorySetups.get(selectedInventorySetup); + panel.highlightDifferences(normContainer, setup, InventoryID.EQUIPMENT); + } + + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + switch (event.getGameState()) + { + // set the highlighting off if login screen shows up + case LOGIN_SCREEN: + highlightDifference = false; + final String setupName = panel.getSelectedInventorySetup(); + if (!setupName.isEmpty()) + { + panel.setCurrentInventorySetup(setupName); + } + break; + + // set highlighting + case LOGGED_IN: + highlightDifference = config.getHighlightDifferences(); + break; + } + } + + public ArrayList getNormalizedContainer(final InventoryID id) + { + assert id == InventoryID.INVENTORY || id == InventoryID.EQUIPMENT : "invalid inventory ID"; + + final ItemContainer container = client.getItemContainer(id); + + ArrayList newContainer = new ArrayList<>(); + + Item[] items = null; + if (container != null) + { + items = container.getItems(); + } + + int size = id == InventoryID.INVENTORY ? NUM_INVENTORY_ITEMS : NUM_EQUIPMENT_ITEMS; + + for (int i = 0; i < size; i++) + { + if (items == null || i >= items.length) + { + newContainer.add(new InventorySetupItem(-1, "", 0)); + } + else + { + final Item item = items[i]; + String itemName = ""; + if (client.isClientThread()) + { + itemName = itemManager.getItemComposition(item.getId()).getName(); + } + newContainer.add(new InventorySetupItem(item.getId(), itemName, item.getQuantity())); + } + } + + return newContainer; + } + + public final InventorySetupConfig getConfig() + { + return config; + } + + public boolean getHighlightDifference() + { + return highlightDifference; + } + + @Override + public void shutDown() + { + overlayManager.remove(overlay); + clientToolbar.removeNavigation(navButton); + } + + final int[] getCurrentInventorySetupIds() + { + InventorySetup setup = inventorySetups.get(panel.getSelectedInventorySetup()); + if (setup == null) + { + return null; + } + ArrayList items = new ArrayList<>(); + items.addAll(setup.getEquipment()); + items.addAll(setup.getInventory()); + ArrayList itemIds = new ArrayList<>(); + for (InventorySetupItem item : items) + { + int id = item.getId(); + ItemComposition itemComposition = itemManager.getItemComposition(id); + if (id > 0) + { + itemIds.add(ItemVariationMapping.map(id)); + itemIds.add(itemComposition.getPlaceholderId()); + } + + } + return itemIds.stream().mapToInt(i -> i).toArray(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java new file mode 100644 index 0000000000..d5eda3697f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java @@ -0,0 +1,109 @@ +package net.runelite.client.plugins.inventorysetups.ui; + +import net.runelite.client.game.AsyncBufferedImage; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemVariationMapping; +import net.runelite.client.plugins.inventorysetups.InventorySetupConfig; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.ColorScheme; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.util.ArrayList; + +public abstract class InventorySetupContainerPanel extends JPanel +{ + + protected ItemManager itemManager; + + private final InventorySetupPlugin plugin; + + InventorySetupContainerPanel(final ItemManager itemManager, final InventorySetupPlugin plugin, String captionText) + { + this.itemManager = itemManager; + this.plugin = plugin; + JPanel containerPanel = new JPanel(); + + final JPanel containerSlotsPanel = new JPanel(); + + setupContainerPanel(containerSlotsPanel); + + // caption + final JLabel caption = new JLabel(captionText); + caption.setHorizontalAlignment(JLabel.CENTER); + caption.setVerticalAlignment(JLabel.CENTER); + + // panel that holds the caption and any other graphics + final JPanel captionPanel = new JPanel(); + captionPanel.add(caption); + + containerPanel.setLayout(new BorderLayout()); + containerPanel.add(captionPanel, BorderLayout.NORTH); + containerPanel.add(containerSlotsPanel, BorderLayout.CENTER); + + add(containerPanel); + } + + void setContainerSlot(int index, + final InventorySetupSlot containerSlot, + final ArrayList items) + { + if (index >= items.size() || items.get(index).getId() == -1) + { + containerSlot.setImageLabel(null, null); + return; + } + + int itemId = items.get(index).getId(); + int quantity = items.get(index).getQuantity(); + final String itemName = items.get(index).getName(); + AsyncBufferedImage itemImg = itemManager.getImage(itemId, quantity, quantity > 1); + String toolTip = itemName; + if (quantity > 1) + { + toolTip += " (" + quantity + ")"; + } + containerSlot.setImageLabel(toolTip, itemImg); + } + + void highlightDifferentSlotColor(InventorySetupItem savedItem, + InventorySetupItem currItem, + final InventorySetupSlot containerSlot) + { + // important note: do not use item names for comparisons + // they are all empty to avoid clientThread usage when highlighting + + final InventorySetupConfig config = plugin.getConfig(); + final Color highlightColor = config.getHighlightColor(); + + if (config.getStackDifference() && currItem.getQuantity() != savedItem.getQuantity()) + { + containerSlot.setBackground(highlightColor); + return; + } + + int currId = currItem.getId(); + int checkId = savedItem.getId(); + + if (!config.getVariationDifference()) + { + currId = ItemVariationMapping.map(currId); + checkId = ItemVariationMapping.map(checkId); + } + + if (currId != checkId) + { + containerSlot.setBackground(highlightColor); + return; + } + + // set the color back to the original, because they match + containerSlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); + } + + abstract public void setupContainerPanel(final JPanel containerSlotsPanel); + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java new file mode 100644 index 0000000000..7e0fecfa2b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java @@ -0,0 +1,91 @@ +package net.runelite.client.plugins.inventorysetups.ui; + +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.inventorysetups.InventorySetup; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.ColorScheme; + +import javax.swing.JPanel; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.HashMap; + +public class InventorySetupEquipmentPanel extends InventorySetupContainerPanel +{ + private HashMap equipmentSlots; + + InventorySetupEquipmentPanel(final ItemManager itemManager, final InventorySetupPlugin plugin) + { + super(itemManager, plugin, "Equipment"); + } + + @Override + public void setupContainerPanel(final JPanel containerSlotsPanel) + { + this.equipmentSlots = new HashMap<>(); + for (EquipmentInventorySlot slot : EquipmentInventorySlot.values()) + { + equipmentSlots.put(slot, new InventorySetupSlot(ColorScheme.DARKER_GRAY_COLOR)); + } + + final GridLayout gridLayout = new GridLayout(5, 3, 1, 1); + containerSlotsPanel.setLayout(gridLayout); + + // add the grid layouts, including invisible ones + containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.HEAD)); + containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.CAPE)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.AMULET)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.AMMO)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.WEAPON)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.BODY)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.SHIELD)); + containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.LEGS)); + containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.GLOVES)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.BOOTS)); + containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.RING)); + + } + + void setEquipmentSetupSlots(final InventorySetup setup) + { + final ArrayList equipment = setup.getEquipment(); + + for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values()) + { + int i = slot.getSlotIdx(); + super.setContainerSlot(i, equipmentSlots.get(slot), equipment); + } + + validate(); + repaint(); + + } + + void highlightDifferences(final ArrayList currEquipment, final InventorySetup inventorySetup) + { + final ArrayList equipToCheck = inventorySetup.getEquipment(); + + assert currEquipment.size() == equipToCheck.size() : "size mismatch"; + + for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values()) + { + + int slotIdx = slot.getSlotIdx(); + super.highlightDifferentSlotColor(equipToCheck.get(slotIdx), currEquipment.get(slotIdx), equipmentSlots.get(slot)); + } + } + + void resetEquipmentSlotsColor() + { + for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values()) + { + equipmentSlots.get(slot).setBackground(ColorScheme.DARKER_GRAY_COLOR); + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java new file mode 100644 index 0000000000..136f4603ea --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java @@ -0,0 +1,78 @@ +package net.runelite.client.plugins.inventorysetups.ui; + +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.inventorysetups.InventorySetup; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.ColorScheme; + +import javax.swing.JPanel; +import java.awt.GridLayout; +import java.util.ArrayList; + +public class InventorySetupInventoryPanel extends InventorySetupContainerPanel +{ + + private static final int ITEMS_PER_ROW = 4; + private static final int NUM_INVENTORY_ITEMS = 28; + + private ArrayList inventorySlots; + + InventorySetupInventoryPanel(final ItemManager itemManager, final InventorySetupPlugin plugin) + { + super(itemManager, plugin, "Inventory"); + } + + + @Override + public void setupContainerPanel(final JPanel containerSlotsPanel) + { + this.inventorySlots = new ArrayList<>(); + for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) + { + inventorySlots.add(new InventorySetupSlot(ColorScheme.DARKER_GRAY_COLOR)); + } + + int numRows = (NUM_INVENTORY_ITEMS + ITEMS_PER_ROW - 1) / ITEMS_PER_ROW; + containerSlotsPanel.setLayout(new GridLayout(numRows, ITEMS_PER_ROW, 1, 1)); + for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) + { + containerSlotsPanel.add(inventorySlots.get(i)); + } + } + + void setInventorySetupSlots(final InventorySetup setup) + { + ArrayList inventory = setup.getInventory(); + + for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) + { + super.setContainerSlot(i, inventorySlots.get(i), inventory); + } + + validate(); + repaint(); + + } + + void highlightDifferentSlots(final ArrayList currInventory, final InventorySetup inventorySetup) + { + + final ArrayList inventoryToCheck = inventorySetup.getInventory(); + + assert currInventory.size() == inventoryToCheck.size() : "size mismatch"; + + for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) + { + super.highlightDifferentSlotColor(inventoryToCheck.get(i), currInventory.get(i), inventorySlots.get(i)); + } + } + + void resetInventorySlotsColor() + { + for (InventorySetupSlot inventorySlot : inventorySlots) + { + inventorySlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java new file mode 100644 index 0000000000..b1b88a02c7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java @@ -0,0 +1,287 @@ +package net.runelite.client.plugins.inventorysetups.ui; + +import net.runelite.api.InventoryID; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.inventorysetups.InventorySetup; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.PluginErrorPanel; +import net.runelite.client.util.ImageUtil; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.border.EmptyBorder; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ItemEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.util.ArrayList; + +public class InventorySetupPluginPanel extends PluginPanel +{ + + private static ImageIcon ADD_ICON; + private static ImageIcon ADD_HOVER_ICON; + private static ImageIcon REMOVE_ICON; + private static ImageIcon REMOVE_HOVER_ICON; + + private final JPanel noSetupsPanel; + private final JPanel invEqPanel; + + private final InventorySetupInventoryPanel invPanel; + private final InventorySetupEquipmentPanel eqpPanel; + + private final JComboBox setupComboBox; + + private final JLabel removeMarker; + + private final InventorySetupPlugin plugin; + + static + { + final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "add_icon.png"); + ADD_ICON = new ImageIcon(addIcon); + ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); + + final BufferedImage removeIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "remove_icon.png"); + REMOVE_ICON = new ImageIcon(removeIcon); + REMOVE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(removeIcon, 0.53f)); + } + + public InventorySetupPluginPanel(final InventorySetupPlugin plugin, final ItemManager itemManager) + { + super(false); + this.plugin = plugin; + this.removeMarker = new JLabel(REMOVE_ICON); + this.invPanel = new InventorySetupInventoryPanel(itemManager, plugin); + this.eqpPanel = new InventorySetupEquipmentPanel(itemManager, plugin); + this.noSetupsPanel = new JPanel(); + this.invEqPanel = new JPanel(); + this.setupComboBox = new JComboBox<>(); + + // setup the title + final JLabel addMarker = new JLabel(ADD_ICON); + final JLabel title = new JLabel(); + title.setText("Inventory Setups"); + title.setForeground(Color.WHITE); + + // setup the add marker (+ sign in the top right) + addMarker.setToolTipText("Add a new inventory setup"); + addMarker.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + plugin.addInventorySetup(); + } + + @Override + public void mouseEntered(MouseEvent e) + { + addMarker.setIcon(ADD_HOVER_ICON); + } + + @Override + public void mouseExited(MouseEvent e) + { + addMarker.setIcon(ADD_ICON); + } + }); + + // setup the remove marker (X sign in the top right) + removeMarker.setToolTipText("Remove the current inventory setup"); + removeMarker.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + final String name = (String)setupComboBox.getSelectedItem(); + plugin.removeInventorySetup(name, true); + } + + @Override + public void mouseEntered(MouseEvent e) + { + if (removeMarker.isEnabled()) + { + removeMarker.setIcon(REMOVE_HOVER_ICON); + } + } + + @Override + public void mouseExited(MouseEvent e) + { + removeMarker.setIcon(REMOVE_ICON); + } + }); + + // setup the combo box for selection switching + // add empty to indicate the empty position + setupComboBox.addItem(""); + setupComboBox.setSelectedIndex(0); + setupComboBox.addItemListener(e -> + { + if (e.getStateChange() == ItemEvent.SELECTED) + { + String selection = (String)e.getItem(); + setCurrentInventorySetup(selection); + } + }); + + // the panel on the top right that holds the add and delete buttons + final JPanel markersPanel = new JPanel(); + markersPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 0)); + markersPanel.add(removeMarker); + markersPanel.add(addMarker); + + // the top panel that has the title and the buttons + final JPanel titleAndMarkersPanel = new JPanel(); + titleAndMarkersPanel.setLayout(new BorderLayout()); + titleAndMarkersPanel.add(title, BorderLayout.WEST); + titleAndMarkersPanel.add(markersPanel, BorderLayout.EAST); + + // the panel that stays at the top and doesn't scroll + // contains the title, buttons, and the combo box + final JPanel northAnchoredPanel = new JPanel(); + northAnchoredPanel.setLayout(new BoxLayout(northAnchoredPanel, BoxLayout.Y_AXIS)); + northAnchoredPanel.setBorder(new EmptyBorder(0, 0, 10, 0)); + northAnchoredPanel.add(titleAndMarkersPanel); + northAnchoredPanel.add(Box.createRigidArea(new Dimension(0, 10))); + northAnchoredPanel.add(setupComboBox); + + // the panel that holds the inventory and equipment panels + final BoxLayout invEqLayout = new BoxLayout(invEqPanel, BoxLayout.Y_AXIS); + invEqPanel.setLayout(invEqLayout); + invEqPanel.add(invPanel); + invEqPanel.add(Box.createRigidArea(new Dimension(0, 10))); + invEqPanel.add(eqpPanel); + + // setup the error panel. It's wrapped around a normal panel + // so it doesn't stretch to fill the parent panel + final PluginErrorPanel errorPanel = new PluginErrorPanel(); + errorPanel.setContent("Inventory Setups", "Select or create an inventory setup."); + noSetupsPanel.add(errorPanel); + + // the panel that holds the inventory panels, and the error panel + final JPanel contentPanel = new JPanel(); + final BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS); + contentPanel.setLayout(contentLayout); + contentPanel.add(invEqPanel); + contentPanel.add(noSetupsPanel); + + // wrapper for the main content panel to keep it from stretching + final JPanel contentWrapper = new JPanel(new BorderLayout()); + contentWrapper.add(Box.createGlue(), BorderLayout.CENTER); + contentWrapper.add(contentPanel, BorderLayout.NORTH); + final JScrollPane contentWrapperPane = new JScrollPane(contentWrapper); + contentWrapperPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + setLayout(new BorderLayout()); + setBorder(new EmptyBorder(10, 10, 10, 10)); + add(northAnchoredPanel, BorderLayout.NORTH); + add(contentWrapperPane, BorderLayout.CENTER); + + // show the no setups panel on startup + showNoSetupsPanel(); + + } + + public void showNoSetupsPanel() + { + setupComboBox.setSelectedIndex(0); + removeMarker.setEnabled(false); + noSetupsPanel.setVisible(true); + invEqPanel.setVisible(false); + } + + private void showHasSetupPanel(final String name) + { + setupComboBox.setSelectedItem(name); + removeMarker.setEnabled(true); + noSetupsPanel.setVisible(false); + invEqPanel.setVisible(true); + } + + public void setCurrentInventorySetup(final String name) + { + if (name.isEmpty()) + { + showNoSetupsPanel(); + return; + } + + showHasSetupPanel(name); + + final InventorySetup inventorySetup = plugin.getInventorySetup(name); + + invPanel.setInventorySetupSlots(inventorySetup); + eqpPanel.setEquipmentSetupSlots(inventorySetup); + + if (plugin.getHighlightDifference()) + { + final ArrayList normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY); + final ArrayList normEqp = plugin.getNormalizedContainer(InventoryID.EQUIPMENT); + + highlightDifferences(normInv, inventorySetup, InventoryID.INVENTORY); + highlightDifferences(normEqp, inventorySetup, InventoryID.EQUIPMENT); + } + else + { + invPanel.resetInventorySlotsColor(); + eqpPanel.resetEquipmentSlotsColor(); + } + + validate(); + repaint(); + } + + public void addInventorySetup(final String name) + { + setupComboBox.addItem(name); + } + + public void removeInventorySetup(final String name) + { + setupComboBox.removeItem(name); + showNoSetupsPanel(); + + invPanel.resetInventorySlotsColor(); + eqpPanel.resetEquipmentSlotsColor(); + + validate(); + repaint(); + } + + public void highlightDifferences(final ArrayList container, + final InventorySetup setupToCheck, + final InventoryID type) + { + switch (type) + { + case INVENTORY: + invPanel.highlightDifferentSlots(container, setupToCheck); + break; + + case EQUIPMENT: + eqpPanel.highlightDifferences(container, setupToCheck); + break; + } + } + + public final String getSelectedInventorySetup() + { + return (String)setupComboBox.getSelectedItem(); + } + + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java new file mode 100644 index 0000000000..13bbbaef14 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java @@ -0,0 +1,45 @@ +package net.runelite.client.plugins.inventorysetups.ui; + +import net.runelite.client.game.AsyncBufferedImage; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.Color; +import java.awt.Dimension; + +public class InventorySetupSlot extends JPanel +{ + + private final JLabel imageLabel; + + public InventorySetupSlot(Color color) + { + imageLabel = new JLabel(); + imageLabel.setVerticalAlignment(SwingConstants.CENTER); + setPreferredSize(new Dimension(46, 42)); + setBackground(color); + add(imageLabel); + + } + + public void setImageLabel(String toolTip, AsyncBufferedImage itemImage) + { + if (itemImage == null || toolTip == null) + { + imageLabel.setToolTipText(""); + imageLabel.setIcon(null); + imageLabel.revalidate(); + return; + } + + imageLabel.setToolTipText(toolTip); + itemImage.addTo(imageLabel); + + validate(); + repaint(); + } + + + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java new file mode 100644 index 0000000000..85a07780de --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2018 AWPH-I + * 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.lootingbagviewer; + +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ImageComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +import javax.inject.Inject; +import java.awt.*; +import java.awt.image.BufferedImage; + +class LootingBagViewerOverlay extends Overlay +{ + private static final int INVENTORY_SIZE = 28; + private static final int PLACEHOLDER_WIDTH = 36; + private static final int PLACEHOLDER_HEIGHT = 32; + private static final ImageComponent PLACEHOLDER_IMAGE = new ImageComponent(new BufferedImage(PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR)); + + private final Client client; + private final ItemManager itemManager; + + private final PanelComponent panelComponent = new PanelComponent(); + + private ItemContainer itemContainer; + private Item[] items; + + @Inject + private LootingBagViewerOverlay(Client client, ItemManager itemManager) + { + setPosition(OverlayPosition.BOTTOM_RIGHT); + panelComponent.setWrapping(4); + panelComponent.setGap(new Point(6, 4)); + panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); + this.itemManager = itemManager; + this.client = client; + + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (itemContainer == null) + { + if(client.getItemContainer(InventoryID.LOOTING_BAG) != null) { + itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); + items = itemContainer.getItems(); + } + return null; + } + else if(itemContainer != null && client.getItemContainer(InventoryID.LOOTING_BAG) != null) + { + itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); + Item[] tempItems = itemContainer.getItems(); + + for(int i = 0; i < items.length; i++) + { + if(!items[i].equals(tempItems[i])) + { + items = tempItems; + } + } + } + + panelComponent.getChildren().clear(); + + for (int i = 0; i < INVENTORY_SIZE; i++) + { + if (i < items.length) + { + final Item item = items[i]; + if (item.getQuantity() > 0) + { + final BufferedImage image = getImage(item); + if (image != null) + { + panelComponent.getChildren().add(new ImageComponent(image)); + continue; + } + } + } + + // put a placeholder image so each item is aligned properly and the panel is not resized + panelComponent.getChildren().add(PLACEHOLDER_IMAGE); + } + + return panelComponent.render(graphics); + } + + private BufferedImage getImage(Item item) + { + return itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java new file mode 100644 index 0000000000..5729c69993 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 AWPH-I + * 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.lootingbagviewer; + +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +import javax.inject.Inject; + +@PluginDescriptor( + name = "PvP Looting Bag Viewer", + description = "Add an overlay showing the contents of your looting bag", + tags = {"alternate", "items", "overlay", "second"}, + type = "utility", + enabledByDefault = false +) +public class LootingBagViewerPlugin extends Plugin +{ + @Inject + private net.runelite.client.plugins.lootingbagviewer.LootingBagViewerOverlay overlay; + + @Inject + private OverlayManager overlayManager; + + @Override + public void startUp() + { + overlayManager.add(overlay); + } + + @Override + public void shutDown() + { + overlayManager.remove(overlay); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java new file mode 100644 index 0000000000..ebbad81a54 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/BatSolver.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +import java.util.Map; +import java.util.HashSet; +import java.util.HashMap; +import java.util.TreeSet; +import java.util.List; +import java.util.ArrayList; +import static net.runelite.client.plugins.raidsthieving.BatSolver.SolutionSet.SOLUTION_SETS; + +public class BatSolver +{ + private Map numberOfSolutionsWithPoison; + private final SolutionSet solution; + + private final HashSet grubsChests; + + public BatSolver(ThievingRoomType roomType) + { + solution = new SolutionSet(roomType); + grubsChests = new HashSet<>(); + } + + public void addEmptyChest(int chestId) + { + // When a new empty chest is found, add it to the current solution set + solution.addEmptyChest(chestId); + calculateChanceOfPoison(); + } + + public void addGrubsChest(int chestId) + { + // When a chest with grubs is found, keep track of it to invalidate solutions + grubsChests.add(chestId); + calculateChanceOfPoison(); + } + + public TreeSet matchSolutions() + { + TreeSet possibleEmptyChests = new TreeSet<>(); + for (SolutionSet knownSolution : SolutionSet.SOLUTION_SETS) + { + if (knownSolution.getType() == solution.getType() && matchSolution(knownSolution)) + { + possibleEmptyChests.addAll(knownSolution.getEmptyChests()); + } + } + + return possibleEmptyChests; + } + + private boolean matchSolution(SolutionSet testSolution) + { + for (Integer grubsChest : grubsChests) + { + if (testSolution.containsChest(grubsChest)) + { + // If one of the chests is known to have grubs, it cannot be a solution + return false; + } + } + + boolean matchesAll = true; + boolean everMatched = false; + for (int i : solution.getEmptyChests()) + { + if (!testSolution.containsChest(i)) + { + matchesAll = false; + } + else + { + everMatched = true; + } + } + return matchesAll && everMatched; + } + + public ThievingRoomType getType() + { + return solution.getType(); + } + + + public void calculateChanceOfPoison() + { + if (getType() == null) + { + numberOfSolutionsWithPoison = null; + return; + } + + numberOfSolutionsWithPoison = new HashMap<>(); + for (SolutionSet sol : getPosssibleSolutions()) + { + if (getType() == sol.getType() && (solution.getEmptyChests().size() == 0 || matchSolution(sol))) + { + for (Integer i : sol.getEmptyChests()) + { + if (numberOfSolutionsWithPoison.containsKey(i)) + { + numberOfSolutionsWithPoison.put(i, numberOfSolutionsWithPoison.get(i) + 1); + } + else + { + numberOfSolutionsWithPoison.put(i, 1); + } + } + } + } + } + + private List getPosssibleSolutions() + { + List possibleSolutions = new ArrayList<>(); + for (SolutionSet soln : SOLUTION_SETS) + { + // Check if we've found grubs in one of the chests, invalidating it as an solution + boolean foundMatch = false; + for (int i : grubsChests) + { + if (soln.containsChest(i)) + { + foundMatch = true; + } + } + if (!foundMatch) + { + possibleSolutions.add(soln); + } + } + return possibleSolutions; + } + + public double relativeLikelihoodPoison(int chestId) + { + // Returns a double between 0 and 1 of how likely the chest has poison based on the number of possible solutions + // Uses a Sigmoid like function to give good contrast in drawn opacity, + // perhaps could be changed to something more accurate quantitavely. + if (numberOfSolutionsWithPoison == null) + { + calculateChanceOfPoison(); + } + if (numberOfSolutionsWithPoison == null) + { + return 1.0; + } + int mostFrequentPoison = 0; + for (Map.Entry entry : numberOfSolutionsWithPoison.entrySet()) + { + if (entry.getValue() > mostFrequentPoison) + { + mostFrequentPoison = entry.getValue(); + } + } + int timesFound = 0; + if (numberOfSolutionsWithPoison.containsKey(chestId)) + { + timesFound = numberOfSolutionsWithPoison.get(chestId); + } + double chestChance = (double) (timesFound) / (double) (mostFrequentPoison); + return 1. / (1 + Math.exp(5 - 10 * chestChance)); + } + + public int getNumberOfEmptyChests() + { + return solution.getEmptyChests().size(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java new file mode 100644 index 0000000000..7346e4ecf6 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ChestIdentifier.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +import net.runelite.client.plugins.raidsthieving.InstancePoint; +import net.runelite.client.plugins.raidsthieving.ThievingChest; +import java.util.HashMap; +import java.util.Map; + +public class ChestIdentifier +{ + public ChestIdentifier(ThievingRoomType roomType) + { + chestIds = new HashMap<>(); + switch (roomType) + { + case LEFT_TURN: + chestIds.put(new InstancePoint(3283, 5379), 1); + chestIds.put(new InstancePoint(3285, 5380), 2); + chestIds.put(new InstancePoint(3279, 5381), 3); + chestIds.put(new InstancePoint(3287, 5382), 4); + chestIds.put(new InstancePoint(3281, 5382), 5); + chestIds.put(new InstancePoint(3284, 5383), 6); + chestIds.put(new InstancePoint(3283, 5384), 7); + chestIds.put(new InstancePoint(3286, 5384), 8); + chestIds.put(new InstancePoint(3288, 5384), 9); + chestIds.put(new InstancePoint(3277, 5385), 10); + chestIds.put(new InstancePoint(3280, 5385), 11); + chestIds.put(new InstancePoint(3285, 5386), 12); + chestIds.put(new InstancePoint(3290, 5386), 13); + chestIds.put(new InstancePoint(3275, 5387), 14); + chestIds.put(new InstancePoint(3287, 5387), 15); + chestIds.put(new InstancePoint(3288, 5387), 16); + chestIds.put(new InstancePoint(3281, 5388), 17); + chestIds.put(new InstancePoint(3291, 5388), 18); + chestIds.put(new InstancePoint(3280, 5389), 19); + chestIds.put(new InstancePoint(3285, 5389), 20); + chestIds.put(new InstancePoint(3289, 5389), 21); + chestIds.put(new InstancePoint(3283, 5390), 22); + chestIds.put(new InstancePoint(3285, 5390), 23); + chestIds.put(new InstancePoint(3288, 5390), 24); + chestIds.put(new InstancePoint(3290, 5390), 25); + chestIds.put(new InstancePoint(3282, 5391), 26); + chestIds.put(new InstancePoint(3289, 5391), 27); + chestIds.put(new InstancePoint(3292, 5391), 28); + chestIds.put(new InstancePoint(3279, 5392), 29); + chestIds.put(new InstancePoint(3276, 5393), 30); + chestIds.put(new InstancePoint(3279, 5393), 31); + chestIds.put(new InstancePoint(3284, 5393), 32); + chestIds.put(new InstancePoint(3285, 5393), 33); + chestIds.put(new InstancePoint(3291, 5393), 34); + chestIds.put(new InstancePoint(3275, 5394), 35); + chestIds.put(new InstancePoint(3277, 5394), 36); + chestIds.put(new InstancePoint(3288, 5394), 37); + chestIds.put(new InstancePoint(3276, 5395), 38); + chestIds.put(new InstancePoint(3281, 5395), 39); + chestIds.put(new InstancePoint(3285, 5395), 40); + chestIds.put(new InstancePoint(3287, 5395), 41); + chestIds.put(new InstancePoint(3289, 5395), 42); + chestIds.put(new InstancePoint(3274, 5396), 43); + chestIds.put(new InstancePoint(3283, 5396), 44); + chestIds.put(new InstancePoint(3285, 5396), 45); + chestIds.put(new InstancePoint(3288, 5396), 46); + chestIds.put(new InstancePoint(3272, 5397), 47); + chestIds.put(new InstancePoint(3280, 5397), 48); + chestIds.put(new InstancePoint(3277, 5398), 49); + chestIds.put(new InstancePoint(3281, 5398), 50); + chestIds.put(new InstancePoint(3284, 5398), 51); + chestIds.put(new InstancePoint(3276, 5399), 52); + chestIds.put(new InstancePoint(3278, 5399), 53); + chestIds.put(new InstancePoint(3283, 5399), 54); + chestIds.put(new InstancePoint(3285, 5399), 55); + chestIds.put(new InstancePoint(3277, 5400), 56); + chestIds.put(new InstancePoint(3284, 5400), 57); + chestIds.put(new InstancePoint(3288, 5400), 58); + chestIds.put(new InstancePoint(3281, 5401), 59); + chestIds.put(new InstancePoint(3286, 5401), 60); + chestIds.put(new InstancePoint(3279, 5402), 61); + chestIds.put(new InstancePoint(3285, 5402), 62); + chestIds.put(new InstancePoint(3280, 5403), 63); + chestIds.put(new InstancePoint(3283, 5403), 64); + break; + case RIGHT_TURN: + chestIds.put(new InstancePoint(3338, 5405), 1); + chestIds.put(new InstancePoint(3334, 5405), 2); + chestIds.put(new InstancePoint(3342, 5404), 3); + chestIds.put(new InstancePoint(3340, 5404), 4); + chestIds.put(new InstancePoint(3345, 5403), 5); + chestIds.put(new InstancePoint(3334, 5403), 6); + chestIds.put(new InstancePoint(3330, 5403), 7); + chestIds.put(new InstancePoint(3343, 5402), 8); + chestIds.put(new InstancePoint(3342, 5402), 9); + chestIds.put(new InstancePoint(3339, 5402), 10); + chestIds.put(new InstancePoint(3338, 5402), 11); + chestIds.put(new InstancePoint(3336, 5402), 12); + chestIds.put(new InstancePoint(3347, 5401), 13); + chestIds.put(new InstancePoint(3330, 5401), 14); + chestIds.put(new InstancePoint(3345, 5400), 15); + chestIds.put(new InstancePoint(3341, 5400), 16); + chestIds.put(new InstancePoint(3337, 5400), 17); + chestIds.put(new InstancePoint(3334, 5400), 18); + chestIds.put(new InstancePoint(3345, 5399), 19); + chestIds.put(new InstancePoint(3343, 5399), 20); + chestIds.put(new InstancePoint(3340, 5399), 21); + chestIds.put(new InstancePoint(3335, 5399), 22); + chestIds.put(new InstancePoint(3331, 5399), 23); + chestIds.put(new InstancePoint(3338, 5398), 24); + chestIds.put(new InstancePoint(3337, 5398), 25); + chestIds.put(new InstancePoint(3345, 5397), 26); + chestIds.put(new InstancePoint(3341, 5397), 27); + chestIds.put(new InstancePoint(3334, 5397), 28); + chestIds.put(new InstancePoint(3331, 5397), 29); + chestIds.put(new InstancePoint(3346, 5396), 30); + chestIds.put(new InstancePoint(3343, 5396), 31); + chestIds.put(new InstancePoint(3339, 5396), 32); + chestIds.put(new InstancePoint(3335, 5396), 33); + chestIds.put(new InstancePoint(3333, 5396), 34); + chestIds.put(new InstancePoint(3340, 5395), 35); + chestIds.put(new InstancePoint(3337, 5395), 36); + chestIds.put(new InstancePoint(3334, 5395), 37); + chestIds.put(new InstancePoint(3345, 5394), 38); + chestIds.put(new InstancePoint(3342, 5394), 39); + chestIds.put(new InstancePoint(3332, 5394), 40); + chestIds.put(new InstancePoint(3343, 5393), 41); + chestIds.put(new InstancePoint(3341, 5393), 42); + chestIds.put(new InstancePoint(3338, 5393), 43); + chestIds.put(new InstancePoint(3335, 5393), 44); + chestIds.put(new InstancePoint(3334, 5393), 45); + chestIds.put(new InstancePoint(3346, 5392), 46); + chestIds.put(new InstancePoint(3342, 5392), 47); + chestIds.put(new InstancePoint(3332, 5392), 48); + chestIds.put(new InstancePoint(3350, 5391), 49); + chestIds.put(new InstancePoint(3346, 5391), 50); + chestIds.put(new InstancePoint(3340, 5391), 51); + chestIds.put(new InstancePoint(3339, 5391), 52); + chestIds.put(new InstancePoint(3336, 5391), 53); + chestIds.put(new InstancePoint(3333, 5391), 54); + chestIds.put(new InstancePoint(3349, 5390), 55); + chestIds.put(new InstancePoint(3343, 5390), 56); + chestIds.put(new InstancePoint(3337, 5390), 57); + chestIds.put(new InstancePoint(3335, 5390), 58); + chestIds.put(new InstancePoint(3344, 5389), 59); + chestIds.put(new InstancePoint(3340, 5389), 60); + chestIds.put(new InstancePoint(3336, 5389), 61); + chestIds.put(new InstancePoint(3333, 5389), 62); + chestIds.put(new InstancePoint(3346, 5388), 63); + chestIds.put(new InstancePoint(3340, 5387), 64); + chestIds.put(new InstancePoint(3337, 5386), 65); + chestIds.put(new InstancePoint(3333, 5386), 66); + chestIds.put(new InstancePoint(3338, 5385), 67); + chestIds.put(new InstancePoint(3336, 5385), 68); + chestIds.put(new InstancePoint(3337, 5384), 69); + chestIds.put(new InstancePoint(3340, 5382), 70); + chestIds.put(new InstancePoint(3334, 5383), 71); + chestIds.put(new InstancePoint(3340, 5379), 72); + chestIds.put(new InstancePoint(3338, 5380), 73); + chestIds.put(new InstancePoint(3336, 5381), 74); + break; + case STRAIGHT: + chestIds.put(new InstancePoint(3308, 5378), 1); + chestIds.put(new InstancePoint(3305, 5379), 2); + chestIds.put(new InstancePoint(3307, 5379), 3); + chestIds.put(new InstancePoint(3304, 5381), 4); + chestIds.put(new InstancePoint(3310, 5381), 5); + chestIds.put(new InstancePoint(3302, 5382), 6); + chestIds.put(new InstancePoint(3307, 5382), 7); + chestIds.put(new InstancePoint(3312, 5382), 8); + chestIds.put(new InstancePoint(3317, 5382), 9); + chestIds.put(new InstancePoint(3319, 5382), 10); + chestIds.put(new InstancePoint(3304, 5383), 11); + chestIds.put(new InstancePoint(3305, 5383), 12); + chestIds.put(new InstancePoint(3307, 5383), 13); + chestIds.put(new InstancePoint(3310, 5383), 14); + chestIds.put(new InstancePoint(3315, 5383), 15); + chestIds.put(new InstancePoint(3320, 5383), 16); + chestIds.put(new InstancePoint(3300, 5384), 17); + chestIds.put(new InstancePoint(3309, 5384), 18); + chestIds.put(new InstancePoint(3311, 5384), 19); + chestIds.put(new InstancePoint(3313, 5384), 20); + chestIds.put(new InstancePoint(3317, 5384), 21); + chestIds.put(new InstancePoint(3318, 5384), 22); + chestIds.put(new InstancePoint(3302, 5385), 23); + chestIds.put(new InstancePoint(3306, 5385), 24); + chestIds.put(new InstancePoint(3310, 5385), 25); + chestIds.put(new InstancePoint(3313, 5385), 26); + chestIds.put(new InstancePoint(3320, 5385), 27); + chestIds.put(new InstancePoint(3302, 5386), 28); + chestIds.put(new InstancePoint(3305, 5386), 29); + chestIds.put(new InstancePoint(3316, 5386), 30); + chestIds.put(new InstancePoint(3321, 5386), 31); + chestIds.put(new InstancePoint(3300, 5387), 32); + chestIds.put(new InstancePoint(3308, 5387), 33); + chestIds.put(new InstancePoint(3314, 5387), 34); + chestIds.put(new InstancePoint(3317, 5387), 35); + chestIds.put(new InstancePoint(3301, 5388), 36); + chestIds.put(new InstancePoint(3306, 5388), 37); + chestIds.put(new InstancePoint(3312, 5388), 38); + chestIds.put(new InstancePoint(3322, 5388), 39); + chestIds.put(new InstancePoint(3309, 5389), 40); + chestIds.put(new InstancePoint(3311, 5389), 41); + chestIds.put(new InstancePoint(3313, 5389), 42); + chestIds.put(new InstancePoint(3316, 5389), 43); + chestIds.put(new InstancePoint(3320, 5389), 44); + chestIds.put(new InstancePoint(3300, 5390), 45); + chestIds.put(new InstancePoint(3303, 5390), 46); + chestIds.put(new InstancePoint(3304, 5390), 47); + chestIds.put(new InstancePoint(3312, 5390), 48); + chestIds.put(new InstancePoint(3320, 5390), 49); + chestIds.put(new InstancePoint(3307, 5391), 50); + chestIds.put(new InstancePoint(3310, 5391), 51); + chestIds.put(new InstancePoint(3317, 5391), 52); + chestIds.put(new InstancePoint(3318, 5391), 53); + chestIds.put(new InstancePoint(3323, 5391), 54); + chestIds.put(new InstancePoint(3301, 5392), 55); + chestIds.put(new InstancePoint(3303, 5392), 56); + chestIds.put(new InstancePoint(3309, 5392), 57); + chestIds.put(new InstancePoint(3314, 5392), 58); + chestIds.put(new InstancePoint(3322, 5392), 59); + chestIds.put(new InstancePoint(3305, 5393), 60); + chestIds.put(new InstancePoint(3307, 5393), 61); + chestIds.put(new InstancePoint(3316, 5393), 62); + chestIds.put(new InstancePoint(3309, 5394), 63); + chestIds.put(new InstancePoint(3312, 5394), 64); + chestIds.put(new InstancePoint(3322, 5394), 65); + chestIds.put(new InstancePoint(3310, 5379), 66); + break; + } + + } + + public int indentifyChest(ThievingChest chest) + { + int id = chestIds.get(chest.getInstancePoint()); + chest.setChestId(id); + return id; + } + + private Map chestIds; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java new file mode 100644 index 0000000000..dc1c3c3dc2 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/SolutionSet.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +import lombok.Getter; +import java.util.HashSet; +import java.util.Arrays; +import java.util.Set; + +// Each Thieving room has 4 empty chests +// User-reported data shows these 4 come in groups, +// +// e.g. if there is an empty chest in L room chest 1, the other empty chests could be 16, 17, 38, 54, 55 +// See https://dikkenoob.github.io/ for more information + +public class SolutionSet +{ + public static final SolutionSet[] SOLUTION_SETS = + { + new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 16, 17, 55), + new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 17, 38, 54), + new SolutionSet(ThievingRoomType.LEFT_TURN, 2, 7, 21, 37), + new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 5, 19, 30), + new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 11, 15, 40), + new SolutionSet(ThievingRoomType.LEFT_TURN, 4, 22, 27, 46), + new SolutionSet(ThievingRoomType.LEFT_TURN, 5, 9, 19, 45), + new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 24, 26, 41), + new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 26, 32, 52), + new SolutionSet(ThievingRoomType.LEFT_TURN, 7, 13, 44, 59), + new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 14, 41, 43), + new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 10, 28, 33), + new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 31, 47, 50), + new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 35, 54, 63), + new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 30, 32, 59), + new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 40, 53, 56), + new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 13, 42, 54), + new SolutionSet(ThievingRoomType.LEFT_TURN, 13, 22, 27, 46), + new SolutionSet(ThievingRoomType.LEFT_TURN, 14, 18, 23, 51), + new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 43, 44, 58), + new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 16, 42, 45), + new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 29, 45, 51), + new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 25, 32, 34), + new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 28, 51, 62), + new SolutionSet(ThievingRoomType.LEFT_TURN, 21, 39, 41, 58), + new SolutionSet(ThievingRoomType.LEFT_TURN, 22, 25, 54, 64), + new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 31, 47, 55), + new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 33, 37, 60), + new SolutionSet(ThievingRoomType.LEFT_TURN, 24, 34, 55), + new SolutionSet(ThievingRoomType.LEFT_TURN, 26, 50, 63, 27), + new SolutionSet(ThievingRoomType.LEFT_TURN, 29, 39, 41, 61), + new SolutionSet(ThievingRoomType.LEFT_TURN, 33, 46, 52, 57), + new SolutionSet(ThievingRoomType.LEFT_TURN, 34, 45, 49, 60), + new SolutionSet(ThievingRoomType.LEFT_TURN, 36, 40, 42, 62), + new SolutionSet(ThievingRoomType.LEFT_TURN, 37, 38, 51, 64), + new SolutionSet(ThievingRoomType.LEFT_TURN, 48, 53, 55, 56), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 6, 28, 41), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 42, 55, 60), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 10, 31, 44), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 33, 51, 68), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 31, 43, 46), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 5, 21, 48), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 20, 24, 33), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 38, 47), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 21, 48), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 17, 35, 63), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 17, 45, 47), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 37, 41, 52), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 13, 40, 42), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 20, 24, 30), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 15, 23, 35), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 13, 21, 50), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 18, 37, 39), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 12, 14, 27, 34), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 14, 45, 67, 71), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 22, 29, 32), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 18, 28, 31, 64), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 19, 21, 63, 69), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 20, 51, 68, 72), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 22, 29, 56, 61), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 23, 53, 66, 74), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 26, 35, 53, 59), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 27, 30, 55, 57), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 31, 58, 60, 73), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 34, 57, 58, 70), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 38, 56, 61, 70), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 40, 54, 65, 72), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 42, 46, 65), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 47, 49, 66, 67), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 48, 62, 69), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 19, 32, 41), + new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 26, 36, 39), + new SolutionSet(ThievingRoomType.STRAIGHT, 1, 39, 43, 51), + new SolutionSet(ThievingRoomType.STRAIGHT, 2, 15, 20, 53), + new SolutionSet(ThievingRoomType.STRAIGHT, 3, 10, 42, 44), + new SolutionSet(ThievingRoomType.STRAIGHT, 4, 14, 38, 52), + new SolutionSet(ThievingRoomType.STRAIGHT, 5, 6, 35, 41), + new SolutionSet(ThievingRoomType.STRAIGHT, 7, 16, 34, 49), + new SolutionSet(ThievingRoomType.STRAIGHT, 9, 12, 26, 27), + new SolutionSet(ThievingRoomType.STRAIGHT, 13, 25, 30, 31), + new SolutionSet(ThievingRoomType.STRAIGHT, 15, 20, 53), + new SolutionSet(ThievingRoomType.STRAIGHT, 17, 24, 34, 58), + new SolutionSet(ThievingRoomType.STRAIGHT, 18, 23, 35, 57), + new SolutionSet(ThievingRoomType.STRAIGHT, 19, 26, 47, 65), + new SolutionSet(ThievingRoomType.STRAIGHT, 21, 33, 36, 61), + new SolutionSet(ThievingRoomType.STRAIGHT, 21, 54, 66), + new SolutionSet(ThievingRoomType.STRAIGHT, 22, 25, 46, 55), + new SolutionSet(ThievingRoomType.STRAIGHT, 24, 34, 58), + new SolutionSet(ThievingRoomType.STRAIGHT, 28, 40, 52, 62), + new SolutionSet(ThievingRoomType.STRAIGHT, 29, 41, 42, 63), + new SolutionSet(ThievingRoomType.STRAIGHT, 30, 32, 37, 64), + new SolutionSet(ThievingRoomType.STRAIGHT, 39, 43, 51), + new SolutionSet(ThievingRoomType.STRAIGHT, 43, 45, 50, 60), + new SolutionSet(ThievingRoomType.STRAIGHT, 51, 53, 56, 59) + }; + + SolutionSet(ThievingRoomType type) + { + this.type = type; + emptyChests = new HashSet<>(); + } + + private SolutionSet(ThievingRoomType type, Integer... emptyChests) + { + this.type = type; + this.emptyChests = new HashSet<>(Arrays.asList(emptyChests)); + } + + public void addEmptyChest(int chestId) + { + emptyChests.add(chestId); + } + + public boolean containsChest(int chestId) + { + return emptyChests.contains(chestId); + } + + @Getter + private ThievingRoomType type; + + @Getter + private Set emptyChests; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java new file mode 100644 index 0000000000..f709b2d435 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving.BatSolver; + +// There are three distinct Thieving rooms, distinguished by the position of the entrance relative to the exit +// e.g. If you enter the room and must turn left to get to the exit and trough, this is a LEFT_TURN + +import net.runelite.client.plugins.raidsthieving.InstancePoint; + +public enum ThievingRoomType +{ + LEFT_TURN(3271, 5389), + RIGHT_TURN(3350, 5399), + STRAIGHT(3317, 5397); + + private final int x; + private final int y; + + ThievingRoomType(int x, int y) + { + this.x = x; + this.y = y; + } + + public static ThievingRoomType IdentifyByInstancePoint(InstancePoint point) + { + for (ThievingRoomType type : ThievingRoomType.values()) + { + if (Math.abs(type.x - point.getX()) <= 1 && + Math.abs(type.y - point.getY()) <= 1) + { + return type; + } + } + + return null; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java new file mode 100644 index 0000000000..5e09486f89 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ChestOverlay.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2018, Tim Lehner + * 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.raidsthieving; + +import net.runelite.api.Client; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ProgressPieComponent; +import javax.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.util.Map; +import java.util.TreeSet; + +/** + * Represents the overlay that shows timers on traps that are placed by the + * player. + */ +public class ChestOverlay extends Overlay +{ + + private final Client client; + private final RaidsThievingPlugin plugin; + private final RaidsThievingConfig config; + + @Inject + ChestOverlay(Client client, RaidsThievingPlugin plugin, RaidsThievingConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_SCENE); + this.plugin = plugin; + this.config = config; + this.client = client; + } + + @Override + public Dimension render(Graphics2D graphics) + { + drawChests(graphics); + return null; + } + + /** + * Updates the timer colors. + */ + public void updateConfig() + { + } + + /** + * Iterates over all the traps that were placed by the local player, and + * draws a circle or a timer on the trap, depending on the trap state. + * + * @param graphics + */ + private void drawChests(Graphics2D graphics) + { + + for (Map.Entry entry : plugin.getChests().entrySet()) + { + ThievingChest chest = entry.getValue(); + WorldPoint pos = entry.getKey(); + + + if (chest != null) + { + if (!plugin.isBatsFound() && !chest.isEverOpened()) + { + if (shouldDrawChest(pos)) + { + Color drawColor = new Color(config.getPotentialBatColor().getRed(), + config.getPotentialBatColor().getGreen(), + config.getPotentialBatColor().getBlue(), + getChestOpacity(pos)); + drawCircleOnTrap(graphics, chest, drawColor); + } + } + if (chest.isPoison()) + { + drawCircleOnTrap(graphics, chest, config.getPoisonTrapColor()); + } + } + } + } + + private boolean shouldDrawChest(WorldPoint chestPos) + { + if (plugin.numberOfEmptyChestsFound() == 0) + { + return true; + } + int chestId = plugin.getChestId(chestPos); + BatSolver solver = plugin.getSolver(); + if (solver != null && chestId != -1) + { + TreeSet matches = solver.matchSolutions(); + return matches.contains(chestId) || matches.size() == 0; + } + return true; + } + + /** + * Draws a timer on a given trap. + * + * @param graphics + * @param chest The chest on which the circle needs to be drawn + * @param fill The fill color of the timer + */ + private void drawCircleOnTrap(Graphics2D graphics, ThievingChest chest, Color fill) + { + if (chest.getLocalPoint().getPlane() != client.getPlane()) + { + return; + } + LocalPoint localLoc = LocalPoint.fromWorld(client, chest.getLocalPoint()); + if (localLoc == null) + { + return; + } + Point loc = Perspective.localToCanvas(client, localLoc, chest.getLocalPoint().getPlane()); + + ProgressPieComponent pie = new ProgressPieComponent(); + pie.setFill(fill); + pie.setBorderColor(Color.BLACK); + pie.setPosition(loc); + pie.setProgress(1); + if (graphics != null && loc != null) + { + pie.render(graphics); + } + } + + private int getChestOpacity(WorldPoint chestPos) + { + int chestId = plugin.getChestId(chestPos); + BatSolver solver = plugin.getSolver(); + if (solver != null && chestId != -1) + { + return (int) (255 * solver.relativeLikelihoodPoison(chestId)); + } + return 255; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java new file mode 100644 index 0000000000..0df80aeb65 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/InstancePoint.java @@ -0,0 +1,98 @@ +package net.runelite.client.plugins.raidsthieving; + +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.coords.WorldPoint; + +import java.util.Objects; + +/** + * Represents a point in the instance chunk, invariant of rotation. + */ +@Getter +public class InstancePoint +{ + private static final int CHUNK_SIZE = 8; + private static final double CHUNK_OFFSET = 3.5; + + public InstancePoint(int x, int y, int rot) + { + this.x = x; + this.y = y; + this.rot = rot; + } + + public InstancePoint(int x, int y) + { + this.x = x; + this.y = y; + this.rot = 0; + } + + public static InstancePoint buildFromPoint(WorldPoint worldPoint, Client client) + { + Point point = new Point(worldPoint.getX(), worldPoint.getY()); + Point base = new Point(client.getBaseX(), client.getBaseY()); + int plane = worldPoint.getPlane(); + + int deltaX = point.getX() - base.getX(); + int deltaY = point.getY() - base.getY(); + int chunkIndexX = deltaX / CHUNK_SIZE; + int chunkIndexY = deltaY / CHUNK_SIZE; + + int chunkData = client.getInstanceTemplateChunks()[plane][chunkIndexX][chunkIndexY]; + int rotation = chunkData >> 1 & 0x3; + int y = (chunkData >> 3 & 0x7FF) * 8; + int x = (chunkData >> 14 & 0x3FF) * 8; + + return buildFromTile(base, point, rotation, new Point(x, y)); + } + + public static InstancePoint buildFromTile(Point base, Point tile, int rot, Point chunkOrigin) + { + int deltaX = tile.getX() - base.getX(); + int deltaY = tile.getY() - base.getY(); + + double chunkOffsetX = (deltaX % CHUNK_SIZE) - CHUNK_OFFSET; + double chunkOffsetY = (deltaY % CHUNK_SIZE) - CHUNK_OFFSET; + + for (int i = 0; i < rot; i++) + { + double temp = chunkOffsetX; + chunkOffsetX = -chunkOffsetY; + chunkOffsetY = temp; + } + + chunkOffsetX += CHUNK_OFFSET; + chunkOffsetY += CHUNK_OFFSET; + + int invariantChunkOffsetX = (int) chunkOffsetX; + int invariantChunkOffsetY = (int) chunkOffsetY; + + return new InstancePoint( + chunkOrigin.getX() + invariantChunkOffsetX, + chunkOrigin.getY() + invariantChunkOffsetY, + rot); + } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InstancePoint that = (InstancePoint) o; + return x == that.x && + y == that.y; + } + + @Override + public int hashCode() + { + return Objects.hash(x, y); + } + + private int x; + private int y; + private int rot; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java new file mode 100644 index 0000000000..bb055edf4e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConfig.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, Tim Lehner + * 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.raidsthieving; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import java.awt.Color; + +@ConfigGroup("raidsthievingplugin") +public interface RaidsThievingConfig extends Config +{ + @ConfigItem( + position = 1, + keyName = "hexColorPotentialBat", + name = "Potential Bat", + description = "Color of marker for chests which could have bat" + ) + default Color getPotentialBatColor() + { + return Color.YELLOW; + } + + @ConfigItem( + position = 2, + keyName = "hexColorPoison", + name = "Poison trap", + description = "Color of chest with poison" + ) + default Color getPoisonTrapColor() + { + return Color.GREEN; + } + + @ConfigItem( + position = 5, + keyName = "batNotify", + name = "Notify when found", + description = "Send notification if you see bats being found." + ) + default boolean batFoundNotify() + { + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConstants.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConstants.java new file mode 100644 index 0000000000..965934a01b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingConstants.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017, Tim Lehner + * 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.raidsthieving; + +public class RaidsThievingConstants +{ + public static final int CLOSED_CHEST_ID = 29742; + public static final int OPEN_EMPTY_CHEST = 29743; + public static final int OPEN_FULL_CHEST_1 = 29744; + public static final int OPEN_FULL_CHEST_2 = 29745; + public static final int EMPTY_TROUGH = 29746; + public static final int[] STORAGE = {29769, 29770, 29771, 29772}; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java new file mode 100644 index 0000000000..d9f7de646c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2017, Tim Lehner + * 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.raidsthieving; + +import com.google.inject.Provides; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.GraphicsObject; +import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameObjectSpawned; +import net.runelite.api.events.GraphicsObjectCreated; +import net.runelite.api.events.VarbitChanged; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver; +import net.runelite.client.plugins.raidsthieving.BatSolver.ChestIdentifier; +import net.runelite.client.plugins.raidsthieving.BatSolver.ThievingRoomType; +import net.runelite.client.ui.overlay.OverlayManager; +import javax.inject.Inject; +import java.text.MessageFormat; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@PluginDescriptor( + name = "!Raids Bat Finder", + description = "Tracks which chests need to be searched for bats and which poison", + tags = {"overlay", "skilling", "raid"} +) +public class RaidsThievingPlugin extends Plugin +{ + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private ChestOverlay overlay; + + @Inject + private Notifier notifier; + + @Inject + private RaidsThievingConfig config; + + @Getter + private final Map chests = new HashMap<>(); + + @Getter + private Instant lastActionTime = Instant.ofEpochMilli(0); + + private boolean inRaidChambers; + + @Getter + private boolean batsFound; + + @Getter + private BatSolver solver; + + @Getter + private ChestIdentifier mapper; + + + @Provides + RaidsThievingConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(RaidsThievingConfig.class); + } + + @Override + protected void startUp() + { + overlayManager.add(overlay); + overlay.updateConfig(); + reset(); + } + + @Override + protected void shutDown() throws Exception + { + overlayManager.remove(overlay); + lastActionTime = Instant.ofEpochMilli(0); + chests.clear(); + } + + + @Subscribe + public void onGameObjectSpawned(GameObjectSpawned event) + { + GameObject obj = event.getGameObject(); + WorldPoint loc = obj.getWorldLocation(); + InstancePoint absLoc = InstancePoint.buildFromPoint(loc, client); + + if (obj.getId() == RaidsThievingConstants.EMPTY_TROUGH) + { + ThievingRoomType type = ThievingRoomType.IdentifyByInstancePoint(absLoc); + + if (type != null) + { + solver = new BatSolver(type); + mapper = new ChestIdentifier(type); + for (ThievingChest chest : chests.values()) + { + mapper.indentifyChest(chest); + } + } + else + { + log.error(MessageFormat.format("Unable to identify room type with: {0} {1} {2} {3} {4}.", + loc.getX(), loc.getY(), absLoc.getX(), absLoc.getY(), absLoc.getRot())); + log.error("Please report this @https://github.com/runelite/runelite/pull/4914!"); + } + } + if (obj.getId() == RaidsThievingConstants.CLOSED_CHEST_ID) + { + if (!chests.containsKey(loc)) + { + ThievingChest chest = new ThievingChest(obj, absLoc); + + if (mapper != null) + { + mapper.indentifyChest(chest); + } + + chests.put(loc, chest); + } + else + { + checkForBats(); + } + } + + if (obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_1 || + obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_2) + { + ThievingChest chest = chests.get(obj.getWorldLocation()); + // We found a chest that has grubs + log.info(MessageFormat.format("Found grubs at {0}, {1} chestId: {2}", loc.getX(), loc.getY(), chest.getChestId())); + if (solver != null && chest.getChestId() != -1) + { + chest.setEverOpened(true); + solver.addGrubsChest(chest.getChestId()); + } + checkForBats(); + } + + if (obj.getId() == RaidsThievingConstants.OPEN_EMPTY_CHEST) + { + ThievingChest chest = chests.get(obj.getWorldLocation()); + // We found a chest that could have poison + if (solver != null && chest.getChestId() != -1) + { + chest.setEmpty(true); + chest.setEverOpened(true); + solver.addEmptyChest(chest.getChestId()); + } + } + } + + + @Subscribe + public void onGraphicsObjectCreated(GraphicsObjectCreated event) + { + GraphicsObject obj = event.getGraphicsObject(); + if (obj.getId() == 184) + { + log.debug("Found poison splat"); + WorldPoint loc = WorldPoint.fromLocal(client, obj.getLocation()); + chests.get(loc).setPoison(true); + } + } + + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + boolean setting = client.getVar(Varbits.IN_RAID) == 1; + + if (inRaidChambers != setting) + { + inRaidChambers = setting; + reset(); + } + + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("raidsthievingplugin")) + { + overlay.updateConfig(); + } + } + + private void reset() + { + chests.clear(); + batsFound = false; + solver = null; + mapper = null; + } + + public int numberOfEmptyChestsFound() + { + int total = 0; + for (ThievingChest chest : chests.values()) + { + if (chest.isEmpty()) + { + total++; + } + } + return total; + } + + + private boolean checkForBats() + { + for (ThievingChest chest : chests.values()) + { + if (chest.isEmpty() && !chest.isPoison()) + { + batsFound = true; + if (config.batFoundNotify()) + { + notifier.notify("Bats have been found!"); + } + return true; + } + } + return false; + } + + public int getChestId(WorldPoint worldPoint) + { + return chests.get(worldPoint).getChestId(); + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ThievingChest.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ThievingChest.java new file mode 100644 index 0000000000..05a58d554e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/ThievingChest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019, Tim Lehner + * 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.raidsthieving; + +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.GameObject; +import net.runelite.api.coords.WorldPoint; + +/** + * Wrapper class for a GameObject that represents a chest in the thieving room of Chambers of Xeric. + */ +@Getter +public class ThievingChest +{ + /** + * If the chest has never been opened, it could have bats. + */ + @Setter + private boolean everOpened; + + /** + * If the chest is empty, it could have bats. + */ + @Setter + private boolean empty; + + /** + * If the chest contains a poison trap instead. + */ + @Setter + private boolean poison; + + + @Setter + private int chestId; + + private final WorldPoint localPoint; + private final InstancePoint instancePoint; + + /** + * Constructor for a ThievingChest object + * + * @param gameObject The gameobject thats corresponds with this trap. + */ + ThievingChest(GameObject gameObject, InstancePoint instancePoint) + { + this.everOpened = false; + this.poison = false; + this.empty = false; + localPoint = gameObject.getWorldLocation(); + this.instancePoint = instancePoint; + this.chestId = -1; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java index be4d85e9fe..33f702e072 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java @@ -45,6 +45,7 @@ import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( name = "!Remember Clan", description = "Remember a specific clan!", + type = "utility", enabledByDefault = false ) public class RememberClanPlugin extends Plugin diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java new file mode 100644 index 0000000000..ec2e3cc105 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java @@ -0,0 +1,25 @@ +package net.runelite.client.plugins.safespot; + +import java.awt.Color; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.Config; + +@ConfigGroup("safespot") +public interface SafeSpotConfig extends Config +{ + @ConfigItem(position = 1, keyName = "playerSafeSpots", name = "Render for Players", description = "Renders 1 way safe spots vs other players") + default boolean playerSafeSpots() { + return true; + } + + @ConfigItem(position = 2, keyName = "npcSafeSpots", name = "Render for NPCs", description = "Renders 1 way safe spots vs NPCs") + default boolean npcSafeSpots() { + return false; + } + + @ConfigItem(position = 3, keyName = "tileColor", name = "Tile Color", description = "Color of safe spot tile") + default Color tileColor() { + return Color.MAGENTA; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java new file mode 100644 index 0000000000..7259957f15 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java @@ -0,0 +1,40 @@ +package net.runelite.client.plugins.safespot; + +import javax.inject.*; +import net.runelite.client.ui.overlay.*; +import java.awt.*; +import net.runelite.api.*; + +public class SafeSpotOverlay extends Overlay +{ + private final Client client; + private final SafeSpotPlugin safeSpotPlugin; + private final SafeSpotConfig config; + + @Inject + public SafeSpotOverlay( Client client, SafeSpotPlugin safeSpotPlugin, SafeSpotConfig config) { + this.client = client; + this.safeSpotPlugin = safeSpotPlugin; + this.config = config; + this.setPosition(OverlayPosition.DYNAMIC); + this.setPriority(OverlayPriority.LOW); + this.setLayer(OverlayLayer.ABOVE_SCENE); + } + + @Override + public Dimension render(Graphics2D graphics) { + if (safeSpotPlugin.isSafeSpotsRenderable() && safeSpotPlugin.getSafeSpotList() != null && safeSpotPlugin.getSafeSpotList().size() > 0) { + safeSpotPlugin.getSafeSpotList().forEach(tile -> { + Polygon poly; + if (tile != null && tile.getLocalLocation() != null) { + poly = Perspective.getCanvasTilePoly(client, tile.getLocalLocation()); + if (poly != null) { + OverlayUtil.renderPolygon(graphics, poly, config.tileColor()); + } + } + return; + }); + } + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java new file mode 100644 index 0000000000..9955332d11 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java @@ -0,0 +1,135 @@ +package net.runelite.client.plugins.safespot; + + +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import java.util.List; +import net.runelite.api.Actor; +import net.runelite.api.coords.WorldArea; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import net.runelite.api.events.GameTick; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.api.events.InteractingChanged; +import com.google.inject.Provides; +import net.runelite.client.config.ConfigManager; +import net.runelite.api.Tile; +import java.util.ArrayList; +import net.runelite.client.ui.overlay.OverlayManager; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.Plugin; + +@PluginDescriptor( + name = "1 Way Safe Spots", + description = "Renders tile overlays for one way safe spots", + tags = { "safe spot", "pvp", "safespots", "pklite" }, + type = "PVP", + enabledByDefault = false +) + +// TODO : filter tiles you cant stand on + +public class SafeSpotPlugin extends Plugin +{ + @Inject + private Client client; + @Inject + OverlayManager overlayManager; + @Inject + private SafeSpotConfig config; + private ArrayList safeSpotList; + private boolean safeSpotsRenderable; + private SafeSpotOverlay safeSpotOverlay; + private int tickCount; + + public SafeSpotPlugin() { + this.safeSpotsRenderable = false; + this.tickCount = 0; + } + + @Provides + SafeSpotConfig config(ConfigManager configManager) { + return configManager.getConfig(SafeSpotConfig.class); + } + + @Override + protected void startUp() throws Exception { + this.safeSpotOverlay = new SafeSpotOverlay(this.client, this, this.config); + this.overlayManager.add(safeSpotOverlay); + } + + @Override + protected void shutDown() throws Exception { + this.overlayManager.remove(safeSpotOverlay); + } + + @Subscribe + private void onInteractingChanged(InteractingChanged event) { + if (event.getSource() != client.getLocalPlayer()) { + return; + } + if (event.getTarget() == null && (config.npcSafeSpots() || config.playerSafeSpots())) { + tickCount = 10; + } + } + + @Subscribe + public void onGameTick(GameTick event) { + if (client.getLocalPlayer().getInteracting() != null) { + if (client.getLocalPlayer().getInteracting() instanceof Player && config.playerSafeSpots()) { + safeSpotsRenderable = true; + updateSafeSpots(); + } + if (client.getLocalPlayer().getInteracting() instanceof NPC && config.npcSafeSpots()) { + safeSpotsRenderable = true; + updateSafeSpots(); + } + } + else { + safeSpotsRenderable = false; + } + if (tickCount > 0) { + --tickCount; + safeSpotsRenderable = true; + } + } + + private void updateSafeSpots() + { + if (client.getLocalPlayer().getInteracting() != null) + { + Actor enemy = client.getLocalPlayer().getInteracting(); + + WorldArea worldArea = new WorldArea(enemy.getWorldLocation().getX() - 12, enemy.getWorldLocation().getY() - 12, 24, 24, client.getPlane()); + List worldPoints = worldArea.toWorldPointList(); + safeSpotList = getSafeSpotList(enemy, worldPoints); + } + } + + private ArrayList getSafeSpotList(Actor actor, List worldPoints) + { + ArrayList safeSpotList = new ArrayList(); + Tile[][][] tiles = client.getScene().getTiles(); + for (WorldPoint w : worldPoints) + { + LocalPoint toPoint = LocalPoint.fromWorld(client, w); + Tile fromTile = tiles[client.getPlane()][actor.getLocalLocation().getSceneX()][actor.getLocalLocation().getSceneY()]; + Tile toTile = tiles[client.getPlane()][toPoint.getSceneX()][toPoint.getSceneY()]; + if ((toTile.hasLineOfSightTo(fromTile)) && (!fromTile.hasLineOfSightTo(toTile))) + { + safeSpotList.add(toTile); + } + } + return safeSpotList; + } + + public ArrayList getSafeSpotList() { + return safeSpotList; + } + + public boolean isSafeSpotsRenderable() { + return safeSpotsRenderable; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java index d1de9d419b..37e3d0507b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java @@ -43,6 +43,7 @@ import java.awt.Color; name = "!Stronghold", description = "Highlights the correct answer to Stronghold of Security questions", tags = {"stronghold", "security", "overlay", "answer", "highlight"} + type = "utility", ) @Slf4j public class StrongholdPlugin extends Plugin { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java index af7cf94ab7..a05322590d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java @@ -57,6 +57,7 @@ import net.runelite.client.ui.overlay.OverlayManager; name = "!War", description = "War War War.", tags = {"skill", "total", "max", "PVP"}, + type = "PVP", enabledByDefault = false ) public class WarIndicatorPlugin extends Plugin diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java index 5f3397e900..df3a773aaa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java @@ -55,6 +55,7 @@ import net.runelite.client.ui.overlay.OverlayManager; name = "!MultiLines", description = "Show borders of multicombat and PvP safezones", tags = {"multicombat", "lines", "pvp", "deadman", "safezones", "bogla"}, + type = "utility", enabledByDefault = false ) public class ZoneIndicatorsPlugin extends Plugin From 72de982de897a67109f292e3d3d309bb63145ca0 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 19:09:19 +0100 Subject: [PATCH 05/21] changes + security fix --- .../client/plugins/groupitemlist/GroupItemListPlugin.java | 2 +- .../client/plugins/raidsthieving/RaidsThievingPlugin.java | 5 +++-- .../client/plugins/rememberclan/RememberClanPlugin.java | 2 +- .../runelite/client/plugins/stronghold/StrongholdPlugin.java | 4 ++-- .../client/plugins/warindicators/WarIndicatorPlugin.java | 2 +- .../client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java index 99d9b14831..c0939f04c9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java @@ -14,7 +14,7 @@ import java.util.ArrayList; import java.util.LinkedHashMap; @PluginDescriptor( - name = "!Group Item List", + name = "Group Item List", description = "Group the right click menu of a pile of items.", tags = {"ground", "compress", "pile", "group"}, type = "utility", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java index d9f7de646c..10873e02d8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java @@ -53,9 +53,10 @@ import java.util.Map; @Slf4j @PluginDescriptor( - name = "!Raids Bat Finder", + name = "Raids Bat Finder", description = "Tracks which chests need to be searched for bats and which poison", - tags = {"overlay", "skilling", "raid"} + tags = {"overlay", "skilling", "raid"}, + type = "PVM" ) public class RaidsThievingPlugin extends Plugin { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java index 33f702e072..2b5dd54b35 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/rememberclan/RememberClanPlugin.java @@ -43,7 +43,7 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( - name = "!Remember Clan", + name = "Remember Clan", description = "Remember a specific clan!", type = "utility", enabledByDefault = false diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java index 37e3d0507b..b150748e0a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java @@ -40,9 +40,9 @@ import javax.inject.Inject; import java.awt.Color; @PluginDescriptor( - name = "!Stronghold", + name = "Stronghold", description = "Highlights the correct answer to Stronghold of Security questions", - tags = {"stronghold", "security", "overlay", "answer", "highlight"} + tags = {"stronghold", "security", "overlay", "answer", "highlight"}, type = "utility", ) @Slf4j diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java index a05322590d..9dc378547c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/warindicators/WarIndicatorPlugin.java @@ -54,7 +54,7 @@ import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayManager; @PluginDescriptor( - name = "!War", + name = "War calling indicators", description = "War War War.", tags = {"skill", "total", "max", "PVP"}, type = "PVP", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java index df3a773aaa..b48ffa41e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java @@ -52,7 +52,7 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; @PluginDescriptor( - name = "!MultiLines", + name = "MultiLines", description = "Show borders of multicombat and PvP safezones", tags = {"multicombat", "lines", "pvp", "deadman", "safezones", "bogla"}, type = "utility", From 08015501b0e5a6c75f131d4e6f5412f3d029b7f2 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 19:12:28 +0100 Subject: [PATCH 06/21] Update StrongholdPlugin.java --- .../runelite/client/plugins/stronghold/StrongholdPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java index b150748e0a..cae099dc1e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stronghold/StrongholdPlugin.java @@ -43,7 +43,7 @@ import java.awt.Color; name = "Stronghold", description = "Highlights the correct answer to Stronghold of Security questions", tags = {"stronghold", "security", "overlay", "answer", "highlight"}, - type = "utility", + type = "utility" ) @Slf4j public class StrongholdPlugin extends Plugin { From b26e2bdf0a27e4e15211a03593a9b0bdc478bebd Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 19:16:35 +0100 Subject: [PATCH 07/21] remove inventorysetups --- .../inventorysetups/InventorySetup.java | 15 - .../InventorySetupBankOverlay.java | 113 ----- .../inventorysetups/InventorySetupConfig.java | 84 ---- .../inventorysetups/InventorySetupItem.java | 15 - .../inventorysetups/InventorySetupPlugin.java | 403 ------------------ .../ui/InventorySetupContainerPanel.java | 109 ----- .../ui/InventorySetupEquipmentPanel.java | 91 ---- .../ui/InventorySetupInventoryPanel.java | 78 ---- .../ui/InventorySetupPluginPanel.java | 287 ------------- .../ui/InventorySetupSlot.java | 45 -- 10 files changed, 1240 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java deleted file mode 100644 index 043d22a30c..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetup.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.runelite.client.plugins.inventorysetups; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.ArrayList; - -@AllArgsConstructor -public class InventorySetup -{ - @Getter - private ArrayList inventory; - @Getter - private ArrayList equipment; -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java deleted file mode 100644 index 34ba341fc7..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupBankOverlay.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.runelite.client.plugins.inventorysetups; - -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.Point; -import net.runelite.api.Query; -import net.runelite.api.SpritePixels; -import net.runelite.api.queries.BankItemQuery; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.api.widgets.WidgetItem; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.util.QueryRunner; - -import javax.inject.Inject; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.util.Arrays; -import java.util.Objects; - -@Slf4j -public class InventorySetupBankOverlay extends Overlay -{ - private final Client client; - private final QueryRunner queryRunner; - private final InventorySetupPlugin plugin; - private final InventorySetupConfig config; - - @Inject - public InventorySetupBankOverlay(Client client, QueryRunner queryRunner, InventorySetupPlugin plugin, InventorySetupConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.LOW); - setLayer(OverlayLayer.ABOVE_WIDGETS); - this.client = client; - this.queryRunner = queryRunner; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (config.getBankHighlight()) - { - int[] ids = plugin.getCurrentInventorySetupIds(); - if (ids == null) - { - return null; - } - ids = Arrays.stream(ids) - .filter(Objects::nonNull) - .filter(id -> id != -1) - .toArray(); - final Query query = new BankItemQuery().idEquals(ids); - final WidgetItem[] widgetItems = queryRunner.runQuery(query); - final Widget bankContainer = client.getWidget(WidgetInfo.BANK_CONTAINER); - for (final WidgetItem item : widgetItems) - { - Point canvasLocation = item.getCanvasLocation(); - Rectangle canvasBounds = item.getCanvasBounds(); - Point windowLocation = bankContainer.getCanvasLocation(); - - if (canvasLocation == null || windowLocation == null) - { - return null; - } - - if (!(canvasLocation.getY() + 60 >= windowLocation.getY() + bankContainer.getHeight()) && !(canvasLocation.getY() + canvasBounds.getHeight() <= windowLocation.getY() + 90)) - { - final Color color = config.getBankHighlightColor(); - - if (color != null) - { - final BufferedImage outline = loadItemOutline(item.getId(), item.getQuantity(), color); - graphics.drawImage(outline, item.getCanvasLocation().getX() + 1, item.getCanvasLocation().getY() + 1, null); - if (item.getQuantity() > 1) - { - drawQuantity(graphics, item, Color.YELLOW); - } - else if (item.getQuantity() == 0) - { - drawQuantity(graphics, item, Color.YELLOW.darker()); - } - } - } - } - } - return null; - } - - private void drawQuantity(Graphics2D graphics, WidgetItem item, Color darker) - { - graphics.setColor(Color.BLACK); - graphics.drawString(String.valueOf(item.getQuantity()), item.getCanvasLocation().getX() + 2, item.getCanvasLocation().getY() + 11); - graphics.setColor(darker); - graphics.setFont(FontManager.getRunescapeSmallFont()); - graphics.drawString(String.valueOf(item.getQuantity()), item.getCanvasLocation().getX() + 1, item.getCanvasLocation().getY() + 10); - } - - private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) - { - final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 2, 0, 0, true, 710); - return itemSprite.toBufferedOutline(outlineColor); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java deleted file mode 100644 index edcc47cd9c..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupConfig.java +++ /dev/null @@ -1,84 +0,0 @@ -package net.runelite.client.plugins.inventorysetups; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -import java.awt.Color; - -@ConfigGroup("inventorysetups") -public interface InventorySetupConfig extends Config -{ - @ConfigItem( - keyName = "highlightDifferences", - name = "Highlight Differences", - description = "Highlight slots that don't match the selected setup", - position = 0 - ) - - default boolean getHighlightDifferences() - { - return false; - } - - @ConfigItem( - keyName = "highlightDifferenceColor", - name = "Highlight Color", - description = "The color used to highlight differences between setups", - position = 1 - ) - - default Color getHighlightColor() - { - return Color.RED; - } - - @ConfigItem( - keyName = "stackDifference", - name = "Stack Difference", - description = "Differences between setups will be highlighted if the stack size is different", - position = 2 - ) - - default boolean getStackDifference() - { - return false; - } - - @ConfigItem( - keyName = "variationDifference", - name = "Variation Difference", - description = "Variations of items (E.g., charged jewellery) will be counted as different", - position = 2 - ) - - default boolean getVariationDifference() - { - return false; - } - - @ConfigItem( - keyName = "bankHighlight", - name = "Bank Highlight", - description = "Highlight setup items in bank", - position = 4 - ) - - default boolean getBankHighlight() - { - return false; - } - - @ConfigItem( - keyName = "bankHighlightColor", - name = "Bank Highlight Color", - description = "The color used to highlight setup items in bank", - position = 5 - ) - - default Color getBankHighlightColor() - { - return Color.RED; - } - -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java deleted file mode 100644 index c1af4e68fd..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupItem.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.runelite.client.plugins.inventorysetups; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -public class InventorySetupItem -{ - @Getter - private final int id; - @Getter - private final String name; - @Getter - private final int quantity; -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java deleted file mode 100644 index 8b9c632498..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/InventorySetupPlugin.java +++ /dev/null @@ -1,403 +0,0 @@ -package net.runelite.client.plugins.inventorysetups; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.google.inject.Provides; -import lombok.extern.slf4j.Slf4j; -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.ItemContainer; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.ItemContainerChanged; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemVariationMapping; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.inventorysetups.ui.InventorySetupPluginPanel; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.ImageUtil; - -import javax.inject.Inject; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import java.awt.image.BufferedImage; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; - -@PluginDescriptor( - name = "Inventory Setups", - description = "Save inventory setups", - tags = { "items", "inventory", "setups"}, - type = "utility", - enabledByDefault = false -) - -@Slf4j -public class InventorySetupPlugin extends Plugin -{ - - private static final String CONFIG_GROUP = "inventorysetups"; - private static final String CONFIG_KEY = "setups"; - private static final int NUM_INVENTORY_ITEMS = 28; - private static final int NUM_EQUIPMENT_ITEMS = 14; - - @Inject - private Client client; - - @Inject - private ItemManager itemManager; - - @Inject - private InventorySetupBankOverlay overlay; - - @Inject - private ClientToolbar clientToolbar; - - @Inject - private InventorySetupConfig config; - - @Inject - private OverlayManager overlayManager; - - @Inject - private ClientThread clientThread; - - @Inject - private ConfigManager configManager; - - private InventorySetupPluginPanel panel; - - private HashMap inventorySetups; - - private NavigationButton navButton; - - private boolean highlightDifference; - - @Override - public void startUp() - { - overlayManager.add(overlay); - - panel = new InventorySetupPluginPanel(this, itemManager); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "inventorysetups_icon.png"); - - navButton = NavigationButton.builder() - .tooltip("Inventory Setups") - .icon(icon) - .priority(9) - .panel(panel) - .build(); - - clientToolbar.addNavigation(navButton); - - // load all the inventory setups from the config file - clientThread.invokeLater(() -> - { - if (client.getGameState() != GameState.LOGIN_SCREEN) - { - return false; - } - - loadConfig(); - panel.showNoSetupsPanel(); - return true; - }); - - } - - public void addInventorySetup() - { - final String name = JOptionPane.showInputDialog(panel, - "Enter the name of this setup.", - "Add New Setup", - JOptionPane.PLAIN_MESSAGE); - - // cancel button was clicked - if (name == null) - { - return; - } - - if (name.isEmpty()) - { - JOptionPane.showMessageDialog(panel, - "Invalid Setup Name", - "Names must not be empty.", - JOptionPane.PLAIN_MESSAGE); - return; - } - - if (inventorySetups.containsKey(name)) - { - String builder = "The setup " + name + " already exists. " + - "Would you like to replace it with the current setup?"; - int confirm = JOptionPane.showConfirmDialog(panel, - builder, - "Warning", - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE); - - if (confirm == JOptionPane.CANCEL_OPTION) - { - return; - } - - // delete the old setup, no need to ask for confirmation - // because the user confirmed above - removeInventorySetup(name, false); - } - - clientThread.invoke(() -> - { - ArrayList inv = getNormalizedContainer(InventoryID.INVENTORY); - ArrayList eqp = getNormalizedContainer(InventoryID.EQUIPMENT); - - final InventorySetup invSetup = new InventorySetup(inv, eqp); - SwingUtilities.invokeLater(() -> - { - inventorySetups.put(name, invSetup); - panel.addInventorySetup(name); - panel.setCurrentInventorySetup(name); - - updateConfig(); - }); - }); - } - - public void removeInventorySetup(final String name, boolean askForConfirmation) - { - if (inventorySetups.containsKey(name)) - { - int confirm = JOptionPane.YES_OPTION; - - if (askForConfirmation) - { - confirm = JOptionPane.showConfirmDialog(panel, - "Are you sure you want to remove this setup?", - "Warning", - JOptionPane.YES_NO_OPTION, - JOptionPane.PLAIN_MESSAGE); - } - - if (confirm == JOptionPane.YES_OPTION) - { - inventorySetups.remove(name); - panel.removeInventorySetup(name); - } - - updateConfig(); - } - } - - public final InventorySetup getInventorySetup(final String name) - { - return inventorySetups.get(name); - } - - @Provides - InventorySetupConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(InventorySetupConfig.class); - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals(CONFIG_GROUP)) - { - // only allow highlighting if the config is enabled and the player is logged in - highlightDifference = config.getHighlightDifferences() && client.getGameState() == GameState.LOGGED_IN; - final String setupName = panel.getSelectedInventorySetup(); - if (highlightDifference && !setupName.isEmpty()) - { - panel.setCurrentInventorySetup(setupName); - } - } - } - - private void updateConfig() - { - if (inventorySetups.isEmpty()) - { - configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_KEY); - return; - } - - final Gson gson = new Gson(); - final String json = gson.toJson(inventorySetups); - configManager.setConfiguration(CONFIG_GROUP, CONFIG_KEY, json); - } - - private void loadConfig() - { - // serialize the internal data structure from the json in the configuration - final String json = configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY); - if (json == null || json.isEmpty()) - { - inventorySetups = new HashMap<>(); - } - else - { - // TODO add last resort?, serialize exception just make empty map - final Gson gson = new Gson(); - Type type = new TypeToken>() - { - - }.getType(); - inventorySetups = gson.fromJson(json, type); - } - - for (final String key : inventorySetups.keySet()) - { - panel.addInventorySetup(key); - } - - highlightDifference = false; - } - - @Subscribe - public void onItemContainerChanged(ItemContainerChanged event) - { - - if (!highlightDifference || client.getGameState() != GameState.LOGGED_IN) - { - return; - } - - // empty entry, no need to compare anything - final String selectedInventorySetup = panel.getSelectedInventorySetup(); - if (selectedInventorySetup.isEmpty()) - { - return; - } - - // check to see that the container is the equipment or inventory - ItemContainer container = event.getItemContainer(); - - if (container == client.getItemContainer(InventoryID.INVENTORY)) - { - ArrayList normContainer = getNormalizedContainer(InventoryID.INVENTORY); - final InventorySetup setup = inventorySetups.get(selectedInventorySetup); - panel.highlightDifferences(normContainer, setup, InventoryID.INVENTORY); - } - else if (container == client.getItemContainer(InventoryID.EQUIPMENT)) - { - ArrayList normContainer = getNormalizedContainer(InventoryID.EQUIPMENT); - final InventorySetup setup = inventorySetups.get(selectedInventorySetup); - panel.highlightDifferences(normContainer, setup, InventoryID.EQUIPMENT); - } - - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - switch (event.getGameState()) - { - // set the highlighting off if login screen shows up - case LOGIN_SCREEN: - highlightDifference = false; - final String setupName = panel.getSelectedInventorySetup(); - if (!setupName.isEmpty()) - { - panel.setCurrentInventorySetup(setupName); - } - break; - - // set highlighting - case LOGGED_IN: - highlightDifference = config.getHighlightDifferences(); - break; - } - } - - public ArrayList getNormalizedContainer(final InventoryID id) - { - assert id == InventoryID.INVENTORY || id == InventoryID.EQUIPMENT : "invalid inventory ID"; - - final ItemContainer container = client.getItemContainer(id); - - ArrayList newContainer = new ArrayList<>(); - - Item[] items = null; - if (container != null) - { - items = container.getItems(); - } - - int size = id == InventoryID.INVENTORY ? NUM_INVENTORY_ITEMS : NUM_EQUIPMENT_ITEMS; - - for (int i = 0; i < size; i++) - { - if (items == null || i >= items.length) - { - newContainer.add(new InventorySetupItem(-1, "", 0)); - } - else - { - final Item item = items[i]; - String itemName = ""; - if (client.isClientThread()) - { - itemName = itemManager.getItemComposition(item.getId()).getName(); - } - newContainer.add(new InventorySetupItem(item.getId(), itemName, item.getQuantity())); - } - } - - return newContainer; - } - - public final InventorySetupConfig getConfig() - { - return config; - } - - public boolean getHighlightDifference() - { - return highlightDifference; - } - - @Override - public void shutDown() - { - overlayManager.remove(overlay); - clientToolbar.removeNavigation(navButton); - } - - final int[] getCurrentInventorySetupIds() - { - InventorySetup setup = inventorySetups.get(panel.getSelectedInventorySetup()); - if (setup == null) - { - return null; - } - ArrayList items = new ArrayList<>(); - items.addAll(setup.getEquipment()); - items.addAll(setup.getInventory()); - ArrayList itemIds = new ArrayList<>(); - for (InventorySetupItem item : items) - { - int id = item.getId(); - ItemComposition itemComposition = itemManager.getItemComposition(id); - if (id > 0) - { - itemIds.add(ItemVariationMapping.map(id)); - itemIds.add(itemComposition.getPlaceholderId()); - } - - } - return itemIds.stream().mapToInt(i -> i).toArray(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java deleted file mode 100644 index d5eda3697f..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java +++ /dev/null @@ -1,109 +0,0 @@ -package net.runelite.client.plugins.inventorysetups.ui; - -import net.runelite.client.game.AsyncBufferedImage; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemVariationMapping; -import net.runelite.client.plugins.inventorysetups.InventorySetupConfig; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.ColorScheme; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Color; -import java.util.ArrayList; - -public abstract class InventorySetupContainerPanel extends JPanel -{ - - protected ItemManager itemManager; - - private final InventorySetupPlugin plugin; - - InventorySetupContainerPanel(final ItemManager itemManager, final InventorySetupPlugin plugin, String captionText) - { - this.itemManager = itemManager; - this.plugin = plugin; - JPanel containerPanel = new JPanel(); - - final JPanel containerSlotsPanel = new JPanel(); - - setupContainerPanel(containerSlotsPanel); - - // caption - final JLabel caption = new JLabel(captionText); - caption.setHorizontalAlignment(JLabel.CENTER); - caption.setVerticalAlignment(JLabel.CENTER); - - // panel that holds the caption and any other graphics - final JPanel captionPanel = new JPanel(); - captionPanel.add(caption); - - containerPanel.setLayout(new BorderLayout()); - containerPanel.add(captionPanel, BorderLayout.NORTH); - containerPanel.add(containerSlotsPanel, BorderLayout.CENTER); - - add(containerPanel); - } - - void setContainerSlot(int index, - final InventorySetupSlot containerSlot, - final ArrayList items) - { - if (index >= items.size() || items.get(index).getId() == -1) - { - containerSlot.setImageLabel(null, null); - return; - } - - int itemId = items.get(index).getId(); - int quantity = items.get(index).getQuantity(); - final String itemName = items.get(index).getName(); - AsyncBufferedImage itemImg = itemManager.getImage(itemId, quantity, quantity > 1); - String toolTip = itemName; - if (quantity > 1) - { - toolTip += " (" + quantity + ")"; - } - containerSlot.setImageLabel(toolTip, itemImg); - } - - void highlightDifferentSlotColor(InventorySetupItem savedItem, - InventorySetupItem currItem, - final InventorySetupSlot containerSlot) - { - // important note: do not use item names for comparisons - // they are all empty to avoid clientThread usage when highlighting - - final InventorySetupConfig config = plugin.getConfig(); - final Color highlightColor = config.getHighlightColor(); - - if (config.getStackDifference() && currItem.getQuantity() != savedItem.getQuantity()) - { - containerSlot.setBackground(highlightColor); - return; - } - - int currId = currItem.getId(); - int checkId = savedItem.getId(); - - if (!config.getVariationDifference()) - { - currId = ItemVariationMapping.map(currId); - checkId = ItemVariationMapping.map(checkId); - } - - if (currId != checkId) - { - containerSlot.setBackground(highlightColor); - return; - } - - // set the color back to the original, because they match - containerSlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); - } - - abstract public void setupContainerPanel(final JPanel containerSlotsPanel); - -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java deleted file mode 100644 index 7e0fecfa2b..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupEquipmentPanel.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.runelite.client.plugins.inventorysetups.ui; - -import net.runelite.api.EquipmentInventorySlot; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.inventorysetups.InventorySetup; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.ColorScheme; - -import javax.swing.JPanel; -import java.awt.GridLayout; -import java.util.ArrayList; -import java.util.HashMap; - -public class InventorySetupEquipmentPanel extends InventorySetupContainerPanel -{ - private HashMap equipmentSlots; - - InventorySetupEquipmentPanel(final ItemManager itemManager, final InventorySetupPlugin plugin) - { - super(itemManager, plugin, "Equipment"); - } - - @Override - public void setupContainerPanel(final JPanel containerSlotsPanel) - { - this.equipmentSlots = new HashMap<>(); - for (EquipmentInventorySlot slot : EquipmentInventorySlot.values()) - { - equipmentSlots.put(slot, new InventorySetupSlot(ColorScheme.DARKER_GRAY_COLOR)); - } - - final GridLayout gridLayout = new GridLayout(5, 3, 1, 1); - containerSlotsPanel.setLayout(gridLayout); - - // add the grid layouts, including invisible ones - containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.HEAD)); - containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.CAPE)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.AMULET)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.AMMO)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.WEAPON)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.BODY)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.SHIELD)); - containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.LEGS)); - containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.GLOVES)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.BOOTS)); - containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.RING)); - - } - - void setEquipmentSetupSlots(final InventorySetup setup) - { - final ArrayList equipment = setup.getEquipment(); - - for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values()) - { - int i = slot.getSlotIdx(); - super.setContainerSlot(i, equipmentSlots.get(slot), equipment); - } - - validate(); - repaint(); - - } - - void highlightDifferences(final ArrayList currEquipment, final InventorySetup inventorySetup) - { - final ArrayList equipToCheck = inventorySetup.getEquipment(); - - assert currEquipment.size() == equipToCheck.size() : "size mismatch"; - - for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values()) - { - - int slotIdx = slot.getSlotIdx(); - super.highlightDifferentSlotColor(equipToCheck.get(slotIdx), currEquipment.get(slotIdx), equipmentSlots.get(slot)); - } - } - - void resetEquipmentSlotsColor() - { - for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values()) - { - equipmentSlots.get(slot).setBackground(ColorScheme.DARKER_GRAY_COLOR); - } - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java deleted file mode 100644 index 136f4603ea..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupInventoryPanel.java +++ /dev/null @@ -1,78 +0,0 @@ -package net.runelite.client.plugins.inventorysetups.ui; - -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.inventorysetups.InventorySetup; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.ColorScheme; - -import javax.swing.JPanel; -import java.awt.GridLayout; -import java.util.ArrayList; - -public class InventorySetupInventoryPanel extends InventorySetupContainerPanel -{ - - private static final int ITEMS_PER_ROW = 4; - private static final int NUM_INVENTORY_ITEMS = 28; - - private ArrayList inventorySlots; - - InventorySetupInventoryPanel(final ItemManager itemManager, final InventorySetupPlugin plugin) - { - super(itemManager, plugin, "Inventory"); - } - - - @Override - public void setupContainerPanel(final JPanel containerSlotsPanel) - { - this.inventorySlots = new ArrayList<>(); - for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) - { - inventorySlots.add(new InventorySetupSlot(ColorScheme.DARKER_GRAY_COLOR)); - } - - int numRows = (NUM_INVENTORY_ITEMS + ITEMS_PER_ROW - 1) / ITEMS_PER_ROW; - containerSlotsPanel.setLayout(new GridLayout(numRows, ITEMS_PER_ROW, 1, 1)); - for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) - { - containerSlotsPanel.add(inventorySlots.get(i)); - } - } - - void setInventorySetupSlots(final InventorySetup setup) - { - ArrayList inventory = setup.getInventory(); - - for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) - { - super.setContainerSlot(i, inventorySlots.get(i), inventory); - } - - validate(); - repaint(); - - } - - void highlightDifferentSlots(final ArrayList currInventory, final InventorySetup inventorySetup) - { - - final ArrayList inventoryToCheck = inventorySetup.getInventory(); - - assert currInventory.size() == inventoryToCheck.size() : "size mismatch"; - - for (int i = 0; i < NUM_INVENTORY_ITEMS; i++) - { - super.highlightDifferentSlotColor(inventoryToCheck.get(i), currInventory.get(i), inventorySlots.get(i)); - } - } - - void resetInventorySlotsColor() - { - for (InventorySetupSlot inventorySlot : inventorySlots) - { - inventorySlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); - } - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java deleted file mode 100644 index b1b88a02c7..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java +++ /dev/null @@ -1,287 +0,0 @@ -package net.runelite.client.plugins.inventorysetups.ui; - -import net.runelite.api.InventoryID; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.inventorysetups.InventorySetup; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.ui.components.PluginErrorPanel; -import net.runelite.client.util.ImageUtil; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.border.EmptyBorder; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.event.ItemEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.util.ArrayList; - -public class InventorySetupPluginPanel extends PluginPanel -{ - - private static ImageIcon ADD_ICON; - private static ImageIcon ADD_HOVER_ICON; - private static ImageIcon REMOVE_ICON; - private static ImageIcon REMOVE_HOVER_ICON; - - private final JPanel noSetupsPanel; - private final JPanel invEqPanel; - - private final InventorySetupInventoryPanel invPanel; - private final InventorySetupEquipmentPanel eqpPanel; - - private final JComboBox setupComboBox; - - private final JLabel removeMarker; - - private final InventorySetupPlugin plugin; - - static - { - final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "add_icon.png"); - ADD_ICON = new ImageIcon(addIcon); - ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); - - final BufferedImage removeIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "remove_icon.png"); - REMOVE_ICON = new ImageIcon(removeIcon); - REMOVE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(removeIcon, 0.53f)); - } - - public InventorySetupPluginPanel(final InventorySetupPlugin plugin, final ItemManager itemManager) - { - super(false); - this.plugin = plugin; - this.removeMarker = new JLabel(REMOVE_ICON); - this.invPanel = new InventorySetupInventoryPanel(itemManager, plugin); - this.eqpPanel = new InventorySetupEquipmentPanel(itemManager, plugin); - this.noSetupsPanel = new JPanel(); - this.invEqPanel = new JPanel(); - this.setupComboBox = new JComboBox<>(); - - // setup the title - final JLabel addMarker = new JLabel(ADD_ICON); - final JLabel title = new JLabel(); - title.setText("Inventory Setups"); - title.setForeground(Color.WHITE); - - // setup the add marker (+ sign in the top right) - addMarker.setToolTipText("Add a new inventory setup"); - addMarker.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - plugin.addInventorySetup(); - } - - @Override - public void mouseEntered(MouseEvent e) - { - addMarker.setIcon(ADD_HOVER_ICON); - } - - @Override - public void mouseExited(MouseEvent e) - { - addMarker.setIcon(ADD_ICON); - } - }); - - // setup the remove marker (X sign in the top right) - removeMarker.setToolTipText("Remove the current inventory setup"); - removeMarker.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - final String name = (String)setupComboBox.getSelectedItem(); - plugin.removeInventorySetup(name, true); - } - - @Override - public void mouseEntered(MouseEvent e) - { - if (removeMarker.isEnabled()) - { - removeMarker.setIcon(REMOVE_HOVER_ICON); - } - } - - @Override - public void mouseExited(MouseEvent e) - { - removeMarker.setIcon(REMOVE_ICON); - } - }); - - // setup the combo box for selection switching - // add empty to indicate the empty position - setupComboBox.addItem(""); - setupComboBox.setSelectedIndex(0); - setupComboBox.addItemListener(e -> - { - if (e.getStateChange() == ItemEvent.SELECTED) - { - String selection = (String)e.getItem(); - setCurrentInventorySetup(selection); - } - }); - - // the panel on the top right that holds the add and delete buttons - final JPanel markersPanel = new JPanel(); - markersPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 0)); - markersPanel.add(removeMarker); - markersPanel.add(addMarker); - - // the top panel that has the title and the buttons - final JPanel titleAndMarkersPanel = new JPanel(); - titleAndMarkersPanel.setLayout(new BorderLayout()); - titleAndMarkersPanel.add(title, BorderLayout.WEST); - titleAndMarkersPanel.add(markersPanel, BorderLayout.EAST); - - // the panel that stays at the top and doesn't scroll - // contains the title, buttons, and the combo box - final JPanel northAnchoredPanel = new JPanel(); - northAnchoredPanel.setLayout(new BoxLayout(northAnchoredPanel, BoxLayout.Y_AXIS)); - northAnchoredPanel.setBorder(new EmptyBorder(0, 0, 10, 0)); - northAnchoredPanel.add(titleAndMarkersPanel); - northAnchoredPanel.add(Box.createRigidArea(new Dimension(0, 10))); - northAnchoredPanel.add(setupComboBox); - - // the panel that holds the inventory and equipment panels - final BoxLayout invEqLayout = new BoxLayout(invEqPanel, BoxLayout.Y_AXIS); - invEqPanel.setLayout(invEqLayout); - invEqPanel.add(invPanel); - invEqPanel.add(Box.createRigidArea(new Dimension(0, 10))); - invEqPanel.add(eqpPanel); - - // setup the error panel. It's wrapped around a normal panel - // so it doesn't stretch to fill the parent panel - final PluginErrorPanel errorPanel = new PluginErrorPanel(); - errorPanel.setContent("Inventory Setups", "Select or create an inventory setup."); - noSetupsPanel.add(errorPanel); - - // the panel that holds the inventory panels, and the error panel - final JPanel contentPanel = new JPanel(); - final BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS); - contentPanel.setLayout(contentLayout); - contentPanel.add(invEqPanel); - contentPanel.add(noSetupsPanel); - - // wrapper for the main content panel to keep it from stretching - final JPanel contentWrapper = new JPanel(new BorderLayout()); - contentWrapper.add(Box.createGlue(), BorderLayout.CENTER); - contentWrapper.add(contentPanel, BorderLayout.NORTH); - final JScrollPane contentWrapperPane = new JScrollPane(contentWrapper); - contentWrapperPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(10, 10, 10, 10)); - add(northAnchoredPanel, BorderLayout.NORTH); - add(contentWrapperPane, BorderLayout.CENTER); - - // show the no setups panel on startup - showNoSetupsPanel(); - - } - - public void showNoSetupsPanel() - { - setupComboBox.setSelectedIndex(0); - removeMarker.setEnabled(false); - noSetupsPanel.setVisible(true); - invEqPanel.setVisible(false); - } - - private void showHasSetupPanel(final String name) - { - setupComboBox.setSelectedItem(name); - removeMarker.setEnabled(true); - noSetupsPanel.setVisible(false); - invEqPanel.setVisible(true); - } - - public void setCurrentInventorySetup(final String name) - { - if (name.isEmpty()) - { - showNoSetupsPanel(); - return; - } - - showHasSetupPanel(name); - - final InventorySetup inventorySetup = plugin.getInventorySetup(name); - - invPanel.setInventorySetupSlots(inventorySetup); - eqpPanel.setEquipmentSetupSlots(inventorySetup); - - if (plugin.getHighlightDifference()) - { - final ArrayList normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY); - final ArrayList normEqp = plugin.getNormalizedContainer(InventoryID.EQUIPMENT); - - highlightDifferences(normInv, inventorySetup, InventoryID.INVENTORY); - highlightDifferences(normEqp, inventorySetup, InventoryID.EQUIPMENT); - } - else - { - invPanel.resetInventorySlotsColor(); - eqpPanel.resetEquipmentSlotsColor(); - } - - validate(); - repaint(); - } - - public void addInventorySetup(final String name) - { - setupComboBox.addItem(name); - } - - public void removeInventorySetup(final String name) - { - setupComboBox.removeItem(name); - showNoSetupsPanel(); - - invPanel.resetInventorySlotsColor(); - eqpPanel.resetEquipmentSlotsColor(); - - validate(); - repaint(); - } - - public void highlightDifferences(final ArrayList container, - final InventorySetup setupToCheck, - final InventoryID type) - { - switch (type) - { - case INVENTORY: - invPanel.highlightDifferentSlots(container, setupToCheck); - break; - - case EQUIPMENT: - eqpPanel.highlightDifferences(container, setupToCheck); - break; - } - } - - public final String getSelectedInventorySetup() - { - return (String)setupComboBox.getSelectedItem(); - } - - -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java deleted file mode 100644 index 13bbbaef14..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupSlot.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.runelite.client.plugins.inventorysetups.ui; - -import net.runelite.client.game.AsyncBufferedImage; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import java.awt.Color; -import java.awt.Dimension; - -public class InventorySetupSlot extends JPanel -{ - - private final JLabel imageLabel; - - public InventorySetupSlot(Color color) - { - imageLabel = new JLabel(); - imageLabel.setVerticalAlignment(SwingConstants.CENTER); - setPreferredSize(new Dimension(46, 42)); - setBackground(color); - add(imageLabel); - - } - - public void setImageLabel(String toolTip, AsyncBufferedImage itemImage) - { - if (itemImage == null || toolTip == null) - { - imageLabel.setToolTipText(""); - imageLabel.setIcon(null); - imageLabel.revalidate(); - return; - } - - imageLabel.setToolTipText(toolTip); - itemImage.addTo(imageLabel); - - validate(); - repaint(); - } - - - -} \ No newline at end of file From 7740d4f6a061ceaa2e897c812af278f8cee1a886 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 19:34:13 +0100 Subject: [PATCH 08/21] remove lootingbagviewer --- .../LootingBagViewerOverlay.java | 123 ------------------ .../LootingBagViewerPlugin.java | 60 --------- 2 files changed, 183 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java deleted file mode 100644 index 85a07780de..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2018 AWPH-I - * 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.lootingbagviewer; - -import net.runelite.api.Client; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemContainer; -import net.runelite.client.game.ItemManager; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.components.ImageComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; - -import javax.inject.Inject; -import java.awt.*; -import java.awt.image.BufferedImage; - -class LootingBagViewerOverlay extends Overlay -{ - private static final int INVENTORY_SIZE = 28; - private static final int PLACEHOLDER_WIDTH = 36; - private static final int PLACEHOLDER_HEIGHT = 32; - private static final ImageComponent PLACEHOLDER_IMAGE = new ImageComponent(new BufferedImage(PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR)); - - private final Client client; - private final ItemManager itemManager; - - private final PanelComponent panelComponent = new PanelComponent(); - - private ItemContainer itemContainer; - private Item[] items; - - @Inject - private LootingBagViewerOverlay(Client client, ItemManager itemManager) - { - setPosition(OverlayPosition.BOTTOM_RIGHT); - panelComponent.setWrapping(4); - panelComponent.setGap(new Point(6, 4)); - panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); - this.itemManager = itemManager; - this.client = client; - - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (itemContainer == null) - { - if(client.getItemContainer(InventoryID.LOOTING_BAG) != null) { - itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); - items = itemContainer.getItems(); - } - return null; - } - else if(itemContainer != null && client.getItemContainer(InventoryID.LOOTING_BAG) != null) - { - itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); - Item[] tempItems = itemContainer.getItems(); - - for(int i = 0; i < items.length; i++) - { - if(!items[i].equals(tempItems[i])) - { - items = tempItems; - } - } - } - - panelComponent.getChildren().clear(); - - for (int i = 0; i < INVENTORY_SIZE; i++) - { - if (i < items.length) - { - final Item item = items[i]; - if (item.getQuantity() > 0) - { - final BufferedImage image = getImage(item); - if (image != null) - { - panelComponent.getChildren().add(new ImageComponent(image)); - continue; - } - } - } - - // put a placeholder image so each item is aligned properly and the panel is not resized - panelComponent.getChildren().add(PLACEHOLDER_IMAGE); - } - - return panelComponent.render(graphics); - } - - private BufferedImage getImage(Item item) - { - return itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java deleted file mode 100644 index 5729c69993..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2018 AWPH-I - * 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.lootingbagviewer; - -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -import javax.inject.Inject; - -@PluginDescriptor( - name = "PvP Looting Bag Viewer", - description = "Add an overlay showing the contents of your looting bag", - tags = {"alternate", "items", "overlay", "second"}, - type = "utility", - enabledByDefault = false -) -public class LootingBagViewerPlugin extends Plugin -{ - @Inject - private net.runelite.client.plugins.lootingbagviewer.LootingBagViewerOverlay overlay; - - @Inject - private OverlayManager overlayManager; - - @Override - public void startUp() - { - overlayManager.add(overlay); - } - - @Override - public void shutDown() - { - overlayManager.remove(overlay); - } -} \ No newline at end of file From 50a054ec86aff451a69f916035fd54733a1995ef Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 19:38:40 +0100 Subject: [PATCH 09/21] lootingbagviewer --- .../java/net/runelite/api/InventoryID.java | 6 +- .../LootingBagViewerOverlay.java | 123 ++++++++++++++++++ .../LootingBagViewerPlugin.java | 59 +++++++++ 3 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java diff --git a/runelite-api/src/main/java/net/runelite/api/InventoryID.java b/runelite-api/src/main/java/net/runelite/api/InventoryID.java index 000bb8aa52..ff099afd70 100644 --- a/runelite-api/src/main/java/net/runelite/api/InventoryID.java +++ b/runelite-api/src/main/java/net/runelite/api/InventoryID.java @@ -57,6 +57,10 @@ public enum InventoryID * Chambers of Xeric chest inventory. */ CHAMBERS_OF_XERIC_CHEST(581), + /** + * Looting Bag inventory + */ + LOOTING_BAG(516), /** * Theater of Blood reward chest inventory (Raids 2) */ @@ -78,4 +82,4 @@ public enum InventoryID { return id; } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java new file mode 100644 index 0000000000..85a07780de --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerOverlay.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2018 AWPH-I + * 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.lootingbagviewer; + +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.ImageComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +import javax.inject.Inject; +import java.awt.*; +import java.awt.image.BufferedImage; + +class LootingBagViewerOverlay extends Overlay +{ + private static final int INVENTORY_SIZE = 28; + private static final int PLACEHOLDER_WIDTH = 36; + private static final int PLACEHOLDER_HEIGHT = 32; + private static final ImageComponent PLACEHOLDER_IMAGE = new ImageComponent(new BufferedImage(PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR)); + + private final Client client; + private final ItemManager itemManager; + + private final PanelComponent panelComponent = new PanelComponent(); + + private ItemContainer itemContainer; + private Item[] items; + + @Inject + private LootingBagViewerOverlay(Client client, ItemManager itemManager) + { + setPosition(OverlayPosition.BOTTOM_RIGHT); + panelComponent.setWrapping(4); + panelComponent.setGap(new Point(6, 4)); + panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL); + this.itemManager = itemManager; + this.client = client; + + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (itemContainer == null) + { + if(client.getItemContainer(InventoryID.LOOTING_BAG) != null) { + itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); + items = itemContainer.getItems(); + } + return null; + } + else if(itemContainer != null && client.getItemContainer(InventoryID.LOOTING_BAG) != null) + { + itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG); + Item[] tempItems = itemContainer.getItems(); + + for(int i = 0; i < items.length; i++) + { + if(!items[i].equals(tempItems[i])) + { + items = tempItems; + } + } + } + + panelComponent.getChildren().clear(); + + for (int i = 0; i < INVENTORY_SIZE; i++) + { + if (i < items.length) + { + final Item item = items[i]; + if (item.getQuantity() > 0) + { + final BufferedImage image = getImage(item); + if (image != null) + { + panelComponent.getChildren().add(new ImageComponent(image)); + continue; + } + } + } + + // put a placeholder image so each item is aligned properly and the panel is not resized + panelComponent.getChildren().add(PLACEHOLDER_IMAGE); + } + + return panelComponent.render(graphics); + } + + private BufferedImage getImage(Item item) + { + return itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java new file mode 100644 index 0000000000..d9cfdd7bf9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 AWPH-I + * 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.lootingbagviewer; + +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; + +import javax.inject.Inject; + +@PluginDescriptor( + name = "PvP Looting Bag Viewer", + description = "Add an overlay showing the contents of your looting bag", + tags = {"alternate", "items", "overlay", "second"}, + enabledByDefault = false +) +public class LootingBagViewerPlugin extends Plugin +{ + @Inject + private net.runelite.client.plugins.lootingbagviewer.LootingBagViewerOverlay overlay; + + @Inject + private OverlayManager overlayManager; + + @Override + public void startUp() + { + overlayManager.add(overlay); + } + + @Override + public void shutDown() + { + overlayManager.remove(overlay); + } +} \ No newline at end of file From 1931a7e580bbf828e8b4a8e714e6949fec7fc678 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 20:33:06 +0100 Subject: [PATCH 10/21] Update LootingBagViewerPlugin.java --- .../plugins/lootingbagviewer/LootingBagViewerPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java index d9cfdd7bf9..5d28a4bbea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/lootingbagviewer/LootingBagViewerPlugin.java @@ -35,6 +35,7 @@ import javax.inject.Inject; name = "PvP Looting Bag Viewer", description = "Add an overlay showing the contents of your looting bag", tags = {"alternate", "items", "overlay", "second"}, + type = "utility", enabledByDefault = false ) public class LootingBagViewerPlugin extends Plugin @@ -56,4 +57,4 @@ public class LootingBagViewerPlugin extends Plugin { overlayManager.remove(overlay); } -} \ No newline at end of file +} From 55d7f64a08a7458653b373fbaf752b5ab8169b5c Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:31:36 +0100 Subject: [PATCH 11/21] Delete SafeSpotConfig.java --- .../plugins/safespot/SafeSpotConfig.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java deleted file mode 100644 index ec2e3cc105..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.runelite.client.plugins.safespot; - -import java.awt.Color; -import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.Config; - -@ConfigGroup("safespot") -public interface SafeSpotConfig extends Config -{ - @ConfigItem(position = 1, keyName = "playerSafeSpots", name = "Render for Players", description = "Renders 1 way safe spots vs other players") - default boolean playerSafeSpots() { - return true; - } - - @ConfigItem(position = 2, keyName = "npcSafeSpots", name = "Render for NPCs", description = "Renders 1 way safe spots vs NPCs") - default boolean npcSafeSpots() { - return false; - } - - @ConfigItem(position = 3, keyName = "tileColor", name = "Tile Color", description = "Color of safe spot tile") - default Color tileColor() { - return Color.MAGENTA; - } -} \ No newline at end of file From cb0bb31047f702f4fa0b9acecbdca83743beebe3 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:31:44 +0100 Subject: [PATCH 12/21] Delete SafeSpotOverlay.java --- .../plugins/safespot/SafeSpotOverlay.java | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java deleted file mode 100644 index 7259957f15..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotOverlay.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.runelite.client.plugins.safespot; - -import javax.inject.*; -import net.runelite.client.ui.overlay.*; -import java.awt.*; -import net.runelite.api.*; - -public class SafeSpotOverlay extends Overlay -{ - private final Client client; - private final SafeSpotPlugin safeSpotPlugin; - private final SafeSpotConfig config; - - @Inject - public SafeSpotOverlay( Client client, SafeSpotPlugin safeSpotPlugin, SafeSpotConfig config) { - this.client = client; - this.safeSpotPlugin = safeSpotPlugin; - this.config = config; - this.setPosition(OverlayPosition.DYNAMIC); - this.setPriority(OverlayPriority.LOW); - this.setLayer(OverlayLayer.ABOVE_SCENE); - } - - @Override - public Dimension render(Graphics2D graphics) { - if (safeSpotPlugin.isSafeSpotsRenderable() && safeSpotPlugin.getSafeSpotList() != null && safeSpotPlugin.getSafeSpotList().size() > 0) { - safeSpotPlugin.getSafeSpotList().forEach(tile -> { - Polygon poly; - if (tile != null && tile.getLocalLocation() != null) { - poly = Perspective.getCanvasTilePoly(client, tile.getLocalLocation()); - if (poly != null) { - OverlayUtil.renderPolygon(graphics, poly, config.tileColor()); - } - } - return; - }); - } - return null; - } -} From 82c372247073159457ab0415a9f7bcce3bf9598f Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:31:50 +0100 Subject: [PATCH 13/21] Delete SafeSpotPlugin.java --- .../plugins/safespot/SafeSpotPlugin.java | 135 ------------------ 1 file changed, 135 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java deleted file mode 100644 index 9955332d11..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/safespot/SafeSpotPlugin.java +++ /dev/null @@ -1,135 +0,0 @@ -package net.runelite.client.plugins.safespot; - - -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import java.util.List; -import net.runelite.api.Actor; -import net.runelite.api.coords.WorldArea; -import net.runelite.api.NPC; -import net.runelite.api.Player; -import net.runelite.api.events.GameTick; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.api.events.InteractingChanged; -import com.google.inject.Provides; -import net.runelite.client.config.ConfigManager; -import net.runelite.api.Tile; -import java.util.ArrayList; -import net.runelite.client.ui.overlay.OverlayManager; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.Plugin; - -@PluginDescriptor( - name = "1 Way Safe Spots", - description = "Renders tile overlays for one way safe spots", - tags = { "safe spot", "pvp", "safespots", "pklite" }, - type = "PVP", - enabledByDefault = false -) - -// TODO : filter tiles you cant stand on - -public class SafeSpotPlugin extends Plugin -{ - @Inject - private Client client; - @Inject - OverlayManager overlayManager; - @Inject - private SafeSpotConfig config; - private ArrayList safeSpotList; - private boolean safeSpotsRenderable; - private SafeSpotOverlay safeSpotOverlay; - private int tickCount; - - public SafeSpotPlugin() { - this.safeSpotsRenderable = false; - this.tickCount = 0; - } - - @Provides - SafeSpotConfig config(ConfigManager configManager) { - return configManager.getConfig(SafeSpotConfig.class); - } - - @Override - protected void startUp() throws Exception { - this.safeSpotOverlay = new SafeSpotOverlay(this.client, this, this.config); - this.overlayManager.add(safeSpotOverlay); - } - - @Override - protected void shutDown() throws Exception { - this.overlayManager.remove(safeSpotOverlay); - } - - @Subscribe - private void onInteractingChanged(InteractingChanged event) { - if (event.getSource() != client.getLocalPlayer()) { - return; - } - if (event.getTarget() == null && (config.npcSafeSpots() || config.playerSafeSpots())) { - tickCount = 10; - } - } - - @Subscribe - public void onGameTick(GameTick event) { - if (client.getLocalPlayer().getInteracting() != null) { - if (client.getLocalPlayer().getInteracting() instanceof Player && config.playerSafeSpots()) { - safeSpotsRenderable = true; - updateSafeSpots(); - } - if (client.getLocalPlayer().getInteracting() instanceof NPC && config.npcSafeSpots()) { - safeSpotsRenderable = true; - updateSafeSpots(); - } - } - else { - safeSpotsRenderable = false; - } - if (tickCount > 0) { - --tickCount; - safeSpotsRenderable = true; - } - } - - private void updateSafeSpots() - { - if (client.getLocalPlayer().getInteracting() != null) - { - Actor enemy = client.getLocalPlayer().getInteracting(); - - WorldArea worldArea = new WorldArea(enemy.getWorldLocation().getX() - 12, enemy.getWorldLocation().getY() - 12, 24, 24, client.getPlane()); - List worldPoints = worldArea.toWorldPointList(); - safeSpotList = getSafeSpotList(enemy, worldPoints); - } - } - - private ArrayList getSafeSpotList(Actor actor, List worldPoints) - { - ArrayList safeSpotList = new ArrayList(); - Tile[][][] tiles = client.getScene().getTiles(); - for (WorldPoint w : worldPoints) - { - LocalPoint toPoint = LocalPoint.fromWorld(client, w); - Tile fromTile = tiles[client.getPlane()][actor.getLocalLocation().getSceneX()][actor.getLocalLocation().getSceneY()]; - Tile toTile = tiles[client.getPlane()][toPoint.getSceneX()][toPoint.getSceneY()]; - if ((toTile.hasLineOfSightTo(fromTile)) && (!fromTile.hasLineOfSightTo(toTile))) - { - safeSpotList.add(toTile); - } - } - return safeSpotList; - } - - public ArrayList getSafeSpotList() { - return safeSpotList; - } - - public boolean isSafeSpotsRenderable() { - return safeSpotsRenderable; - } -} \ No newline at end of file From cb397e566b3735654b017ff35709e24f4c5ffd39 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:33:29 +0100 Subject: [PATCH 14/21] Delete GroupItemListPlugin.java --- .../groupitemlist/GroupItemListPlugin.java | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java deleted file mode 100644 index c0939f04c9..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupItemListPlugin.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.runelite.client.plugins.groupitemlist; - -import net.runelite.api.Client; -import net.runelite.api.MenuEntry; -import net.runelite.api.events.MenuOpened; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyManager; -import net.runelite.client.input.MouseManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.LinkedHashMap; - -@PluginDescriptor( - name = "Group Item List", - description = "Group the right click menu of a pile of items.", - tags = {"ground", "compress", "pile", "group"}, - type = "utility", - enabledByDefault = false -) - -/** - * Main class of plugin - Groups duplicate right click menu options to singular entries with a quantity. - * - */ -public class GroupItemListPlugin extends Plugin { - - @Inject - private Client client; - - /** - * Fired on a right click menu opening. Count all menu entries and build a new list of entries - * displaying item quantities. - * - * @param menu Right click menu opened - */ - @Subscribe - public void onMenuOpened(MenuOpened menu) { - - LinkedHashMap entryCount = new LinkedHashMap<>(); - ArrayList temp = new ArrayList<>(); - MenuEntry[] updatedMenuEntries; - - // Iterate over menu entries - for (MenuEntry e : menu.getMenuEntries()) { - - // Increment the count if entry has been seen before - if (entryCount.containsKey(e)) { - entryCount.get(e).incrementCount(); - } - - // Store in map if entry has not been seen before - else { - entryCount.put(e, new GroupedItem(e)); - } - } - - // Create a list of updated menu entries from the map of GroupedItem - for (MenuEntry e : entryCount.keySet()) { - MenuEntry entry = entryCount.get(e).getEntry(); - temp.add(entry); - } - - // Parse to an array and set the new menu entries - updatedMenuEntries = temp.toArray(new MenuEntry[0]); - client.setMenuEntries(updatedMenuEntries); - } -} From 7955ae016bf53d9cb7be63ce44eaa82a59912a1f Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:33:36 +0100 Subject: [PATCH 15/21] Delete GroupedItem.java --- .../plugins/groupitemlist/GroupedItem.java | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java deleted file mode 100644 index b4fbbda77f..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groupitemlist/GroupedItem.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.runelite.client.plugins.groupitemlist; - -import net.runelite.api.MenuEntry; - -/** - * Object used to store a MenuEntry and the quantity. Updates the entry target if necessary - * e.g Shark to Shark [4]. - */ -public class GroupedItem { - - private int count; - private MenuEntry entry; - - /** - * Constructor for GroupedItem. - * - * @param entry The menu entry to be tracked for duplicates - */ - public GroupedItem(MenuEntry entry) { - this.entry = entry; - this.count = 1; - } - - /** - * Getter for the count. - * - * @return count - */ - public int getCount() { - return count; - } - - /** - * Getter for the menu entry, updates the target to reflect the quantity if more than 1 - * was found. - * - * @return Updated MenuEntry containing quantity - */ - public MenuEntry getEntry() { - if (count > 1) { - updateTarget(); - } - return entry; - } - - /** - * Updates the target of the menu entry to contain the quantity found. - */ - private void updateTarget() { - String target = entry.getTarget(); - target = target + " [" + count + "]"; - entry.setTarget(target); - } - - /** - * Increment count when duplicate entries are found. - */ - public void incrementCount() { - count += 1; - } -} From 06d036780247a47a66211ed18b9284fb59e3054d Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:35:55 +0100 Subject: [PATCH 16/21] Delete MapLocations.java --- .../plugins/zoneIndicators/MapLocations.java | 3479 ----------------- 1 file changed, 3479 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java deleted file mode 100644 index 81e8e0f527..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/MapLocations.java +++ /dev/null @@ -1,3479 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.zoneIndicators; - -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.Area; -import java.util.ArrayList; -import java.util.List; -import net.runelite.api.Constants; - -public class MapLocations -{ - private static final List[] MULTICOMBAT = new List[Constants.MAX_Z]; - private static final List[] NOT_MULTICOMBAT = new List[Constants.MAX_Z]; - private static final List[] ROUGH_WILDERNESS = new List[Constants.MAX_Z]; - private static final List[] DEADMAN_SAFE_ZONES = new List[Constants.MAX_Z]; - private static final List[] PVP_WORLD_SAFE_ZONES = new List[Constants.MAX_Z]; - - private static Area getArea(List shapes) - { - Area area = new Area(); - for (Shape shape : shapes) - { - area.add(new Area(shape)); - } - return area; - } - - private static Area getArea(List shapes, Rectangle view) - { - Area area = new Area(); - for (Shape shape : shapes) - { - if (shape.intersects(view)) - { - area.add(new Area(shape)); - } - } - return area; - } - - public static Area getMulticombat(int plane) - { - Area area = getArea(MULTICOMBAT[plane]); - area.subtract(getArea(NOT_MULTICOMBAT[plane])); - return area; - } - - public static Area getMulticombat(Rectangle view, int plane) - { - Area area = getArea(MULTICOMBAT[plane], view); - area.subtract(getArea(NOT_MULTICOMBAT[plane], view)); - return area; - } - - public static Area getRoughWilderness(int plane) - { - return getArea(ROUGH_WILDERNESS[plane]); - } - - public static Area getRoughWilderness(Rectangle view, int plane) - { - return getArea(ROUGH_WILDERNESS[plane], view); - } - - public static Area getDeadmanSafeZones(int plane) - { - return getArea(DEADMAN_SAFE_ZONES[plane]); - } - - public static Area getDeadmanSafeZones(Rectangle view, int plane) - { - return getArea(DEADMAN_SAFE_ZONES[plane], view); - } - - public static Area getPvpSafeZones(int plane) - { - return getArea(PVP_WORLD_SAFE_ZONES[plane]); - } - - public static Area getPvpSafeZones(Rectangle view, int plane) - { - return getArea(PVP_WORLD_SAFE_ZONES[plane], view); - } - - static - { - for (int i = 0; i < MULTICOMBAT.length; i++) - { - MULTICOMBAT[i] = new ArrayList<>(); - } - for (int i = 0; i < NOT_MULTICOMBAT.length; i++) - { - NOT_MULTICOMBAT[i] = new ArrayList<>(); - } - for (int i = 0; i < ROUGH_WILDERNESS.length; i++) - { - ROUGH_WILDERNESS[i] = new ArrayList<>(); - } - for (int i = 0; i < DEADMAN_SAFE_ZONES.length; i++) - { - DEADMAN_SAFE_ZONES[i] = new ArrayList<>(); - } - for (int i = 0; i < PVP_WORLD_SAFE_ZONES.length; i++) - { - PVP_WORLD_SAFE_ZONES[i] = new ArrayList<>(); - } - - defineMulticombatAreas(); - defineDeadmanSafeZones(); - definePvpSafeZones(); - defineWilderness(); - } - - private static void defineMulticombatAreas() - { - // Main Wilderness - addPolygonOnPlane(MULTICOMBAT, 0, - 3200, 3968, - 3392, 3968, - 3392, 3840, - 3328, 3840, - 3328, 3520, - 3136, 3520, - 3136, 3648, - 3192, 3648, - 3192, 3752, - 3152, 3752, - 3152, 3840, - 3136, 3840, - 3136, 3872, - 3112, 3872, - 3112, 3880, - 3072, 3880, - 3072, 3896, - 3048, 3896, - 3048, 3872, - 3056, 3872, - 3056, 3864, - 3048, 3864, - 3048, 3856, - 3008, 3856, - 3008, 3904, - 3200, 3904); - - // South of wildy agility training arena - addPolygonOnPlane(MULTICOMBAT, 0, - 2984, 3928, - 3008, 3928, - 3008, 3912, - 2984, 3912); - - // Wildy zamorak temple - addPolygonOnPlane(MULTICOMBAT, 0, - 2944, 3832, - 2960, 3832, - 2960, 3816, - 2944, 3816); - - // Wildy bandit camp - addPolygonOnPlane(MULTICOMBAT, 0, - 3008, 3712, - 3072, 3712, - 3072, 3600, - 3008, 3600); - - // Chaos temple north of Falador - addPolygonOnPlane(MULTICOMBAT, 0, - 2928, 3520, - 2944, 3520, - 2944, 3512, - 2928, 3512); - - // Burthorpe - addPolygonOnPlane(MULTICOMBAT, 0, - 2880, 3544, - 2904, 3544, - 2904, 3520, - 2880, 3520); - - // White Wolf Mountain - addPolygonOnPlane(MULTICOMBAT, 0, - 2880, 3520, - 2816, 3520, - 2816, 3456, - 2880, 3456); - - // Death Plateu - addPolygonOnPlane(MULTICOMBAT, 0, - 2848, 3608, - 2880, 3608, - 2880, 3600, - 2848, 3600); - - // Trollheim/Godwars - addPolygonOnPlane(MULTICOMBAT, 0, - 2880, 3776, - 2912, 3776, - 2912, 3696, - 2920, 3696, - 2920, 3688, - 2896, 3688, - 2896, 3696, - 2880, 3696, - 2880, 3728, - 2888, 3728, - 2888, 3744, - 2880, 3744); - - // Northen Rellekka - addPolygonOnPlane(MULTICOMBAT, 0, - 2656, 3736, - 2704, 3736, - 2704, 3728, - 2712, 3728, - 2712, 3736, - 2736, 3736, - 2736, 3712, - 2656, 3712); - - // Northen Fremennik Isles - addPolygonOnPlane(MULTICOMBAT, 0, - 2304, 3904, - 2432, 3904, - 2432, 3840, - 2368, 3840, - 2368, 3816, - 2352, 3816, - 2352, 3824, - 2304, 3824); - - // Pirates Cove - addPolygonOnPlane(MULTICOMBAT, 0, - 2176, 3840, - 2240, 3840, - 2240, 3776, - 2176, 3776); - - // Lunar Isle - addPolygonOnPlane(MULTICOMBAT, 0, - 2048, 3968, - 2176, 3968, - 2176, 3840, - 2048, 3840); - - // Piscatoris Fishing Colony - addPolygonOnPlane(MULTICOMBAT, 0, - 2304, 3712, - 2368, 3712, - 2368, 3648, - 2304, 3648); - - // Ranging Guild - addPolygonOnPlane(MULTICOMBAT, 0, - 2656, 3448, - 2680, 3448, - 2680, 3440, - 2688, 3440, - 2688, 3416, - 2680, 3416, - 2680, 3408, - 2656, 3408, - 2656, 3416, - 2648, 3416, - 2648, 3440, - 2656, 3440); - - // Necromancer house, southeast of Ardy - addPolygonOnPlane(MULTICOMBAT, 0, - 2656, 3256, - 2680, 3256, - 2680, 3216, - 2664, 3216, - 2664, 3232, - 2656, 3232); - - // Battlefield noth of Tree Gnome Village - addPolygonOnPlane(MULTICOMBAT, 0, - 2504, 3248, - 2544, 3248, - 2544, 3232, - 2552, 3232, - 2552, 3208, - 2504, 3208); - - // Castle Wars - addPolygonOnPlane(MULTICOMBAT, 0, - 2368, 3136, - 2432, 3136, - 2432, 3072, - 2368, 3072); - - // Jiggig - addPolygonOnPlane(MULTICOMBAT, 0, - 2456, 3056, - 2496, 3056, - 2496, 3032, - 2456, 3032); - - // East feldip hills, near rantz - addPolygonOnPlane(MULTICOMBAT, 0, - 2648, 2976, - 2656, 2976, - 2656, 2952, - 2648, 2952); - - // Ape Atoll - addPolygonOnPlane(MULTICOMBAT, 0, - 2688, 2816, - 2816, 2816, - 2816, 2688, - 2688, 2688); - - // Pest Control - addPolygonOnPlane(MULTICOMBAT, 0, - 2624, 2624, - 2688, 2624, - 2688, 2560, - 2624, 2560); - - // Desert Bandit Camp - addPolygonOnPlane(MULTICOMBAT, 0, - 3152, 3000, - 3192, 3000, - 3192, 2960, - 3152, 2960); - - // Al Kharid - addPolygonOnPlane(MULTICOMBAT, 0, - 3264, 3200, - 3328, 3200, - 3328, 3136, - 3264, 3136); - - // Wizards Tower - addPolygonOnPlane(MULTICOMBAT, 0, - 3094, 3176, - 3126, 3176, - 3126, 3144, - 3094, 3144); - - // Draynor Village - addPolygonOnPlane(MULTICOMBAT, 0, - 3112, 3264, - 3136, 3264, - 3136, 3232, - 3104, 3232, - 3104, 3256, - 3112, 3256); - - // Falador - addPolygonOnPlane(MULTICOMBAT, 0, - 2944, 3456, - 3008, 3456, - 3008, 3328, - 3016, 3328, - 3016, 3304, - 2944, 3304); - - // Southwest fally castle isn't multicombat downstairs - addPolygonOnPlane(NOT_MULTICOMBAT, 0, - 2968, 3336, - 2968, 3328, - 2960, 3328, - 2960, 3336); - - // Barbarian Village - addPolygonOnPlane(MULTICOMBAT, 0, - 3072, 3456, - 3136, 3456, - 3136, 3392, - 3048, 3392, - 3048, 3408, - 3056, 3408, - 3056, 3440, - 3064, 3440, - 3064, 3448, - 3072, 3448); - - // Ammoniate crabs at northwest fossil island - addPolygonOnPlane(MULTICOMBAT, 0, - 3648, 3885, - 3663, 3885, - 3663, 3882, - 3664, 3882, - 3664, 3872, - 3663, 3872, - 3663, 3868, - 3648, 3868); - - // Ammoniate crabs at north fossil island - addPolygonOnPlane(MULTICOMBAT, 0, - 3680, 3904, - 3744, 3904, - 3744, 3856, - 3756, 3856, - 3756, 3852, - 3755, 3852, - 3755, 3851, - 3754, 3851, - 3754, 3850, - 3751, 3850, - 3751, 3849, - 3750, 3849, - 3750, 3848, - 3749, 3848, - 3749, 3847, - 3748, 3847, - 3748, 3846, - 3747, 3846, - 3747, 3845, - 3746, 3845, - 3746, 3844, - 3742, 3844, - 3742, 3845, - 3740, 3845, - 3740, 3844, - 3732, 3844, - 3732, 3843, - 3730, 3843, - 3730, 3842, - 3724, 3842, - 3724, 3843, - 3717, 3843, - 3717, 3842, - 3712, 3842, - 3712, 3846, - 3710, 3846, - 3710, 3847, - 3709, 3847, - 3709, 3848, - 3708, 3848, - 3708, 3859, - 3709, 3859, - 3709, 3860, - 3710, 3860, - 3710, 3861, - 3712, 3861, - 3712, 3866, - 3713, 3866, - 3713, 3870, - 3714, 3870, - 3714, 3873, - 3713, 3873, - 3713, 3876, - 3712, 3876, - 3712, 3881, - 3710, 3881, - 3710, 3888, - 3712, 3888, - 3712, 3890, - 3714, 3890, - 3714, 3891, - 3716, 3891, - 3716, 3892, - 3717, 3892, - 3717, 3893, - 3716, 3893, - 3716, 3894, - 3714, 3894, - 3714, 3895, - 3713, 3895, - 3713, 3896, - 3712, 3896, - 3712, 3897, - 3705, 3897, - 3705, 3898, - 3704, 3898, - 3704, 3899, - 3692, 3899, - 3692, 3898, - 3688, 3898, - 3688, 3897, - 3686, 3897, - 3686, 3896, - 3680, 3896); - - // Zeah, southwest of Wintertodt, snowy area with ice giants and wolves - addPolygonOnPlane(MULTICOMBAT, 0, - 1540, 3898, - 1543, 3898, - 1543, 3901, - 1546, 3901, - 1546, 3903, - 1547, 3903, - 1547, 3904, - 1550, 3904, - 1550, 3903, - 1553, 3903, - 1553, 3904, - 1559, 3904, - 1559, 3902, - 1564, 3902, - 1564, 3903, - 1565, 3903, - 1565, 3904, - 1568, 3904, - 1568, 3903, - 1569, 3903, - 1569, 3902, - 1570, 3902, - 1570, 3901, - 1573, 3901, - 1573, 3898, - 1577, 3898, - 1577, 3899, - 1578, 3899, - 1578, 3902, - 1579, 3902, - 1579, 3903, - 1584, 3903, - 1584, 3902, - 1586, 3902, - 1586, 3901, - 1590, 3901, - 1590, 3891, - 1588, 3891, - 1588, 3887, - 1572, 3887, - 1572, 3872, - 1567, 3872, - 1567, 3868, - 1563, 3868, - 1563, 3867, - 1558, 3867, - 1558, 3868, - 1557, 3868, - 1557, 3870, - 1549, 3870, - 1549, 3874, - 1545, 3874, - 1545, 3876, - 1543, 3876, - 1543, 3877, - 1542, 3877, - 1542, 3879, - 1541, 3879, - 1541, 3882, - 1539, 3882, - 1539, 3887, - 1540, 3887, - 1540, 3888, - 1539, 3888, - 1539, 3894, - 1540, 3894); - - // Zeah arceuus area - addPolygonOnPlane(MULTICOMBAT, 0, - 1664, 3776, - 1664, 3785, - 1667, 3785, - 1667, 3805, - 1671, 3805, - 1671, 3811, - 1675, 3811, - 1675, 3819, - 1690, 3819, - 1690, 3814, - 1695, 3814, - 1695, 3806, - 1719, 3806, - 1719, 3787, - 1725, 3787, - 1725, 3778, - 1711, 3778, - 1711, 3776); - - // Arceuus teletab-making house - addPolygonOnPlane(MULTICOMBAT, 0, - 1667, 3772, - 1679, 3772, - 1679, 3775, - 1691, 3775, - 1691, 3761, - 1679, 3761, - 1679, 3764, - 1667, 3764); - // Next house east - addPolygonOnPlane(MULTICOMBAT, 0, - 1696, 3775, - 1708, 3775, - 1708, 3763, - 1696, 3763); - // Next house east - addPolygonOnPlane(MULTICOMBAT, 0, - 1713, 3775, - 1727, 3775, - 1727, 3763, - 1724, 3763, - 1724, 3752, - 1716, 3752, - 1716, 3763, - 1713, 3763); - // Arceuus rune shop house - addPolygonOnPlane(MULTICOMBAT, 0, - 1716, 3750, - 1728, 3750, - 1728, 3736, - 1716, 3736); - // Arceuus general store house - addPolygonOnPlane(MULTICOMBAT, 0, - 1717, 3732, - 1725, 3732, - 1725, 3715, - 1715, 3715, - 1715, 3725, - 1717, 3725); - // Arceuus pub - addPolygonOnPlane(MULTICOMBAT, 0, - 1683, 3732, - 1691, 3732, - 1691, 3725, - 1697, 3725, - 1697, 3730, - 1703, 3730, - 1703, 3712, - 1683, 3712); - // Arceuus staff store - addPolygonOnPlane(MULTICOMBAT, 0, - 1664, 3732, - 1676, 3732, - 1676, 3720, - 1664, 3720); - // Next house to the west - addPolygonOnPlane(MULTICOMBAT, 0, - 1647, 3738, - 1655, 3738, - 1655, 3726, - 1658, 3726, - 1658, 3714, - 1644, 3714, - 1644, 3726, - 1647, 3726); - // Next house to the north - addPolygonOnPlane(MULTICOMBAT, 0, - 1647, 3762, - 1657, 3762, - 1657, 3752, - 1655, 3752, - 1655, 3745, - 1647, 3745); - - // Arceuus house magic trees - addPolygonOnPlane(MULTICOMBAT, 0, - 1682, 3755, - 1692, 3755, - 1692, 3745, - 1690, 3745, - 1690, 3738, - 1682, 3738); - // West of that ^ - addPolygonOnPlane(MULTICOMBAT, 0, - 1667, 3756, - 1675, 3756, - 1675, 3740, - 1665, 3740, - 1665, 3746, - 1667, 3746); - - // This one goes through western piscarilius, northen hosidius - // and southwestern arceuus - addPolygonOnPlane(MULTICOMBAT, 0, - 1728, 3808, - 1792, 3808, - 1792, 3764, - 1856, 3764, - 1856, 3712, - 1792, 3712, - 1792, 3648, - 1664, 3648, - 1664, 3706, - 1665, 3706, - 1665, 3705, - 1668, 3705, - 1668, 3706, - 1671, 3706, - 1671, 3705, - 1675, 3705, - 1675, 3704, - 1683, 3704, - 1683, 3701, - 1684, 3701, - 1684, 3700, - 1686, 3700, - 1686, 3702, - 1687, 3702, - 1687, 3700, - 1688, 3700, - 1688, 3701, - 1690, 3701, - 1690, 3703, - 1689, 3703, - 1689, 3704, - 1690, 3704, - 1690, 3705, - 1704, 3705, - 1704, 3707, - 1706, 3707, - 1706, 3712, - 1711, 3712, - 1711, 3711, - 1710, 3711, - 1710, 3710, - 1712, 3710, - 1712, 3707, - 1728, 3707); - - // Kourend castle - addPolygonOnPlane(MULTICOMBAT, 0, - 1614, 3691, - 1619, 3691, - 1619, 3690, - 1620, 3690, - 1620, 3689, - 1653, 3689, - 1653, 3690, - 1654, 3690, - 1654, 3691, - 1657, 3691, - 1657, 3690, - 1658, 3690, - 1658, 3689, - 1659, 3689, - 1659, 3686, - 1658, 3686, - 1658, 3685, - 1657, 3685, - 1657, 3662, - 1658, 3662, - 1658, 3661, - 1659, 3661, - 1659, 3658, - 1658, 3658, - 1658, 3657, - 1657, 3657, - 1657, 3656, - 1654, 3656, - 1654, 3657, - 1653, 3657, - 1653, 3658, - 1620, 3658, - 1620, 3657, - 1619, 3657, - 1619, 3656, - 1614, 3656, - 1614, 3657, - 1613, 3657, - 1613, 3661, - 1612, 3661, - 1612, 3662, - 1611, 3662, - 1611, 3663, - 1600, 3663, - 1600, 3662, - 1599, 3662, - 1599, 3661, - 1594, 3661, - 1594, 3662, - 1593, 3662, - 1593, 3685, - 1594, 3685, - 1594, 3686, - 1599, 3686, - 1599, 3685, - 1600, 3685, - 1600, 3684, - 1611, 3684, - 1611, 3685, - 1612, 3685, - 1612, 3686, - 1613, 3686, - 1613, 3690, - 1614, 3690); - - // Western hosidius area, including woodcutting guild and western sand crabs - addPolygonOnPlane(MULTICOMBAT, 0, - 1650, 3648, - 1664, 3648, - 1664, 3520, - 1689, 3520, - 1689, 3496, - 1707, 3496, - 1707, 3485, - 1708, 3485, - 1708, 3484, - 1710, 3484, - 1710, 3483, - 1713, 3483, - 1713, 3482, - 1720, 3482, - 1720, 3481, - 1721, 3481, - 1721, 3480, - 1722, 3480, - 1722, 3479, - 1723, 3479, - 1723, 3478, - 1724, 3478, - 1724, 3477, - 1726, 3477, - 1726, 3476, - 1728, 3476, - 1728, 3472, - 1708, 3472, - 1708, 3456, - 1600, 3456, - 1600, 3584, - 1608, 3584, - 1608, 3616, - 1650, 3616); - - // Hosidius sand crabs - addPolygonOnPlane(MULTICOMBAT, 0, - 1740, 3478, - 1741, 3478, - 1741, 3479, - 1745, 3479, - 1745, 3480, - 1751, 3480, - 1751, 3479, - 1752, 3479, - 1752, 3478, - 1753, 3478, - 1753, 3477, - 1755, 3477, - 1755, 3476, - 1757, 3476, - 1757, 3475, - 1758, 3475, - 1758, 3474, - 1759, 3474, - 1759, 3473, - 1779, 3473, - 1779, 3474, - 1781, 3474, - 1781, 3475, - 1786, 3475, - 1786, 3476, - 1800, 3476, - 1800, 3475, - 1805, 3475, - 1805, 3474, - 1807, 3474, - 1807, 3473, - 1808, 3473, - 1808, 3472, - 1810, 3472, - 1810, 3471, - 1833, 3471, - 1833, 3470, - 1834, 3470, - 1834, 3469, - 1852, 3469, - 1852, 3449, - 1792, 3449, - 1792, 3424, - 1800, 3424, - 1800, 3449, - 1800, 3400, - 1728, 3400, - 1728, 3462, - 1729, 3462, - 1729, 3466, - 1730, 3466, - 1730, 3469, - 1731, 3469, - 1731, 3470, - 1732, 3470, - 1732, 3471, - 1733, 3471, - 1733, 3473, - 1734, 3473, - 1734, 3474, - 1736, 3474, - 1736, 3475, - 1737, 3475, - 1737, 3476, - 1738, 3476, - 1738, 3477, - 1740, 3477); - - // Apparently there is a 1x1 single zone on the sand crab island - addPolygonOnPlane(NOT_MULTICOMBAT, 0, - 1777, 3416, - 1777, 3417, - 1778, 3417, - 1778, 3416); - - // Eastern hosidius area - addPolygonOnPlane(MULTICOMBAT, 0, - 1834, 3584, - 1888, 3584, - 1888, 3528, - 1856, 3528, - 1856, 3520, - 1834, 3520, - 1834, 3522, - 1833, 3522, - 1833, 3535, - 1834, 3535, - 1834, 3538, - 1835, 3538, - 1835, 3539, - 1836, 3539, - 1836, 3540, - 1837, 3540, - 1837, 3541, - 1838, 3541, - 1838, 3542, - 1840, 3542, - 1840, 3543, - 1841, 3543, - 1841, 3545, - 1842, 3545, - 1842, 3546, - 1844, 3546, - 1844, 3547, - 1845, 3547, - 1845, 3548, - 1851, 3548, - 1851, 3551, - 1853, 3551, - 1853, 3563, - 1851, 3563, - 1851, 3566, - 1847, 3566, - 1847, 3567, - 1845, 3567, - 1845, 3568, - 1844, 3568, - 1844, 3569, - 1843, 3569, - 1843, 3571, - 1842, 3571, - 1842, 3573, - 1841, 3573, - 1841, 3574, - 1840, 3574, - 1840, 3575, - 1839, 3575, - 1839, 3576, - 1838, 3576, - 1838, 3577, - 1837, 3577, - 1837, 3578, - 1836, 3578, - 1836, 3579, - 1835, 3579, - 1835, 3581, - 1834, 3581); - - // Eastern hosidius area also has a 1x1 multi area - addPolygonOnPlane(MULTICOMBAT, 0, - 1849, 3563, - 1849, 3564, - 1850, 3564, - 1850, 3563); - - // Hosidius cows/chickens/pigs - addPolygonOnPlane(MULTICOMBAT, 0, - 1792, 3513, - 1802, 3513, - 1802, 3520, - 1810, 3520, - 1810, 3513, - 1816, 3513, - 1816, 3512, - 1836, 3512, - 1836, 3494, - 1796, 3494, - 1796, 3495, - 1792, 3495); - - // Hosidius southeast of tithe farm - addPolygonOnPlane(MULTICOMBAT, 0, - 1777, 3597, - 1794, 3597, - 1794, 3561, - 1777, 3561, - 1777, 3591, - 1779, 3591, - 1779, 3592, - 1777, 3592); - - // West of shayzien house - addPolygonOnPlane(MULTICOMBAT, 0, - 1408, 3584, - 1408, 3582, - 1486, 3582, - 1486, 3568, - 1528, 3568, - 1528, 3520, - 1408, 3520, - 1408, 3464, - 1380, 3464, - 1380, 3486, - 1377, 3486, - 1377, 3488, - 1373, 3488, - 1373, 3492, - 1364, 3492, - 1364, 3512, - 1358, 3512, - 1358, 3520, - 1356, 3520, - 1356, 3532, - 1358, 3532, - 1358, 3540, - 1359, 3540, - 1359, 3542, - 1360, 3542, - 1360, 3557, - 1356, 3557, - 1356, 3560, - 1351, 3560, - 1351, 3570, - 1354, 3570, - 1354, 3581, - 1346, 3581, - 1346, 3584); - - // South of chambers of xeric - addPolygonOnPlane(MULTICOMBAT, 0, - 1261, 3489, - 1259, 3489, - 1259, 3488, - 1255, 3488, - 1255, 3487, - 1243, 3487, - 1243, 3490, - 1234, 3490, - 1234, 3480, - 1192, 3480, - 1192, 3568, - 1209, 3568, - 1209, 3548, - 1215, 3548, - 1215, 3544, - 1217, 3544, - 1217, 3536, - 1235, 3536, - 1235, 3532, - 1249, 3532, - 1249, 3525, - 1248, 3525, - 1248, 3517, - 1254, 3517, - 1254, 3513, - 1274, 3513, - 1274, 3510, - 1296, 3510, - 1296, 3511, - 1300, 3511, - 1300, 3501, - 1287, 3501, - 1287, 3490, - 1280, 3490, - 1280, 3489, - 1264, 3489, - 1264, 3490, - 1261, 3490); - - // Lizardman shamans - addPolygonOnPlane(MULTICOMBAT, 0, - 1416, 3728, - 1456, 3728, - 1456, 3688, - 1416, 3688); - - // Other lizardman area at shayzien (west side) - addPolygonOnPlane(MULTICOMBAT, 0, - 1472, 3712, - 1510, 3712, - 1510, 3702, - 1509, 3702, - 1509, 3701, - 1506, 3701, - 1506, 3696, - 1500, 3696, - 1500, 3680, - 1472, 3680); - - // Other lizardman area at shayzien (east side) - addPolygonOnPlane(MULTICOMBAT, 0, - 1538, 3704, - 1560, 3704, - 1560, 3672, - 1538, 3672); - - // Lovakengj house - addPolygonOnPlane(MULTICOMBAT, 0, - 1600, 3712, - 1472, 3712, - 1472, 3840, - 1547, 3840, - 1547, 3816, - 1556, 3816, - 1556, 3809, - 1562, 3809, - 1562, 3800, - 1568, 3800, - 1568, 3793, - 1571, 3793, - 1571, 3816, - 1571, 3776, - 1600, 3776); - - // Shayzien house - addPolygonOnPlane(MULTICOMBAT, 0, - 1475, 3587, - 1475, 3641, - 1534, 3641, - 1534, 3587); - - // Shayzien house bank is non-multi - addPolygonOnPlane(NOT_MULTICOMBAT, 0, - 1495, 3622, - 1515, 3622, - 1515, 3612, - 1495, 3612); - - // Shayzien house general store - addPolygonOnPlane(MULTICOMBAT, 0, - 1539, 3640, - 1551, 3640, - 1551, 3621, - 1539, 3621); - - // Kourend woodland barbarian area - addPolygonOnPlane(MULTICOMBAT, 0, - 1572, 3442, - 1591, 3442, - 1591, 3424, - 1572, 3424); - - // Catacombs - addPolygonTo(MULTICOMBAT, - 1600, 9984, - 1600, 10067, - 1628, 10067, - 1628, 10070, - 1639, 10070, - 1639, 10112, - 1730, 10112, - 1730, 9984); - - // Zeah dungeon with sand crabs - addPolygonTo(MULTICOMBAT, - 1632, 9792, - 1632, 9856, - 1728, 9856, - 1728, 9792); - - // Waterbirth island near the doors where people use rune throwing axes - addPolygonTo(MULTICOMBAT, - 2536, 10136, - 2536, 10152, - 2552, 10152, - 2552, 10136); - - // Waterbirth island dungeon, on the path to dks - addPolygonTo(MULTICOMBAT, - 1792, 4352, - 1792, 4416, - 1984, 4416, - 1984, 4352); - - // Dagannoths in lighthouse - addPolygonTo(MULTICOMBAT, - 2496, 10048, - 2560, 10048, - 2560, 9984, - 2496, 9984); - - // Dagannoth kings (DKs) including slayer only dks - addPolygonTo(MULTICOMBAT, - 2944, 4352, - 2944, 4480, - 2880, 4480, - 2880, 4352); - - // White wolf mountain dungeon at ice queen - addPolygonTo(MULTICOMBAT, - 2856, 9928, - 2856, 9968, - 2880, 9968, - 2880, 9928); - - // Kharazi jungle dungeon (in dragon slayer 2 quest) - addPolygonTo(MULTICOMBAT, - 2816, 9296, - 2880, 9296, - 2880, 9216, - 2816, 9216); - - // Tzhaar, fight pits and inferno area - addPolygonTo(MULTICOMBAT, - 2368, 5184, - 2560, 5184, - 2560, 5056, - 2368, 5056); - - // Smoke devils - addPolygonTo(MULTICOMBAT, - 2432, 9408, - 2344, 9408, - 2344, 9472, - 2432, 9472); - - // Kraken - addPolygonTo(MULTICOMBAT, - 2270, 10045, - 2291, 10045, - 2291, 10022, - 2270, 10022); - - // Giant mole - addPolygonTo(MULTICOMBAT, - 1728, 5240, - 1792, 5240, - 1792, 5120, - 1728, 5120); - - // Godwars dungeon - addPolygonTo(MULTICOMBAT, - 2816, 5376, - 2944, 5376, - 2944, 5248, - 2816, 5248); - - // Desert treasure shadow diamond area - addPolygonTo(MULTICOMBAT, - 2752, 5064, - 2728, 5064, - 2728, 5088, - 2720, 5088, - 2720, 5096, - 2712, 5096, - 2712, 5112, - 2736, 5112, - 2736, 5120, - 2752, 5120); - - // Kalphite slayer area - addPolygonTo(MULTICOMBAT, - 3264, 9544, - 3344, 9544, - 3344, 9472, - 3264, 9472); - - // Normal kalphite area including kalphite queen - addPolygonTo(MULTICOMBAT, - 3456, 9536, - 3520, 9536, - 3520, 9472, - 3456, 9472); - - // Tarns lair - addPolygonTo(MULTICOMBAT, - 3136, 4664, - 3200, 4664, - 3200, 4544, - 3136, 4544); - - // Haunted mine boss area - addPolygonTo(MULTICOMBAT, - 2752, 4416, - 2752, 4480, - 2816, 4480, - 2816, 4416); - - // Entrance to dorgesh kaan - addPolygonTo(MULTICOMBAT, - 3328, 9600, - 3312, 9600, - 3312, 9640, - 3304, 9640, - 3304, 9664, - 3328, 9664); - - // Hammerspikes hangout in dwarven mines - addPolygonTo(MULTICOMBAT, - 2960, 9824, - 2976, 9824, - 2976, 9800, - 2960, 9800); - - // Fremennik isles dungeon - addPolygonTo(MULTICOMBAT, - 2432, 10304, - 2432, 10240, - 2368, 10240, - 2368, 10304); - - // Varrock sewers - addPolygonTo(MULTICOMBAT, - 3152, 9920, - 3288, 9920, - 3288, 9856, - 3152, 9856); - - // Stronghold of security 1st floor - addPolygonTo(MULTICOMBAT, - 1856, 5248, - 1920, 5248, - 1920, 5184, - 1856, 5184); - - // Corp cave - addPolygonTo(MULTICOMBAT, - 2960, 4400, - 3000, 4400, - 3000, 4368, - 2960, 4368); - - // ZMI altar area - addPolygonTo(MULTICOMBAT, - 3008, 5632, - 3072, 5632, - 3072, 5568, - 3008, 5568); - - // Dragon slayer 2 zeah underground puzzle - addPolygonTo(MULTICOMBAT, - 1472, 9984, - 1536, 9984, - 1536, 9920, - 1472, 9920); - - // Wildy revenant caves - addPolygonTo(MULTICOMBAT, - 3136, 10062, - 3136, 10240, - 3236, 10240, - 3236, 10229, - 3264, 10229, - 3264, 10048, - 3208, 10048, - 3208, 10062); - - // King black dragon (Kbd) - addPolygonTo(MULTICOMBAT, - 2240, 4672, - 2240, 4736, - 2304, 4736, - 2304, 4672); - - // Scorpia - addPolygonTo(MULTICOMBAT, - 3248, 10352, - 3248, 10328, - 3216, 10328, - 3216, 10352); - - // Inside mage bank - addPolygonTo(MULTICOMBAT, - 2496, 4672, - 2496, 4736, - 2560, 4736, - 2560, 4672); - - // Wildy godwars dungeon - addPolygonTo(MULTICOMBAT, - 3072, 10112, - 3008, 10112, - 3008, 10176, - 3048, 10176, - 3048, 10152, - 3056, 10152, - 3056, 10144, - 3064, 10144, - 3064, 10136, - 3072, 10136); - - // Enchanted valley - addPolygonTo(MULTICOMBAT, - 3008, 4480, - 3008, 4544, - 3072, 4544, - 3072, 4480); - - // Zulrah - addPolygonTo(MULTICOMBAT, - 2256, 3080, - 2280, 3080, - 2280, 3064, - 2256, 3064); - - // Abyssal sire and abyss - addPolygonTo(MULTICOMBAT, - 3008, 4736, - 2944, 4736, - 2944, 4864, - 3136, 4864, - 3136, 4736, - 3072, 4736, - 3072, 4800, - 3008, 4800); - } - - private static void defineDeadmanSafeZones() - { - // Varrock - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3182, 3382, - 3182, 3399, - 3174, 3399, - 3174, 3448, - 3198, 3448, - 3198, 3449, - 3197, 3449, - 3197, 3450, - 3196, 3450, - 3196, 3451, - 3195, 3451, - 3195, 3452, - 3194, 3452, - 3194, 3453, - 3193, 3453, - 3193, 3454, - 3192, 3454, - 3192, 3455, - 3191, 3455, - 3191, 3456, - 3190, 3456, - 3190, 3457, - 3185, 3457, - 3185, 3463, - 3186, 3463, - 3186, 3464, - 3187, 3464, - 3187, 3467, - 3167, 3467, - 3167, 3468, - 3163, 3468, - 3163, 3467, - 3142, 3467, - 3142, 3468, - 3141, 3468, - 3141, 3469, - 3140, 3469, - 3140, 3470, - 3139, 3470, - 3139, 3471, - 3138, 3471, - 3138, 3484, - 3139, 3484, - 3139, 3485, - 3140, 3485, - 3140, 3486, - 3141, 3486, - 3141, 3491, - 3140, 3491, - 3140, 3492, - 3139, 3492, - 3139, 3493, - 3138, 3493, - 3138, 3515, - 3139, 3515, - 3139, 3516, - 3140, 3516, - 3140, 3517, - 3141, 3517, - 3141, 3518, - 3160, 3518, - 3160, 3517, - 3161, 3517, - 3161, 3516, - 3162, 3516, - 3162, 3515, - 3167, 3515, - 3167, 3516, - 3168, 3516, - 3168, 3517, - 3169, 3517, - 3169, 3518, - 3191, 3518, - 3191, 3517, - 3192, 3517, - 3192, 3516, - 3193, 3516, - 3193, 3515, - 3194, 3515, - 3194, 3514, - 3195, 3514, - 3195, 3513, - 3196, 3513, - 3196, 3512, - 3197, 3512, - 3197, 3511, - 3198, 3511, - 3198, 3510, - 3199, 3510, - 3199, 3509, - 3200, 3509, - 3200, 3508, - 3230, 3508, - 3230, 3507, - 3231, 3507, - 3231, 3506, - 3232, 3506, - 3232, 3505, - 3233, 3505, - 3233, 3504, - 3234, 3504, - 3234, 3503, - 3235, 3503, - 3235, 3502, - 3252, 3502, - 3252, 3496, - 3253, 3496, - 3253, 3495, - 3254, 3495, - 3254, 3494, - 3255, 3494, - 3255, 3493, - 3263, 3493, - 3263, 3472, - 3264, 3472, - 3264, 3471, - 3265, 3471, - 3265, 3470, - 3266, 3470, - 3266, 3469, - 3267, 3469, - 3267, 3468, - 3268, 3468, - 3268, 3467, - 3269, 3467, - 3269, 3466, - 3270, 3466, - 3270, 3465, - 3271, 3465, - 3271, 3437, - 3274, 3437, - 3274, 3424, - 3277, 3424, - 3277, 3420, - 3274, 3420, - 3274, 3411, - 3275, 3411, - 3275, 3410, - 3276, 3410, - 3276, 3409, - 3277, 3409, - 3277, 3408, - 3288, 3408, - 3288, 3391, - 3289, 3391, - 3289, 3385, - 3290, 3385, - 3290, 3378, - 3289, 3378, - 3289, 3377, - 3288, 3377, - 3288, 3376, - 3265, 3376, - 3265, 3380, - 3253, 3380, - 3253, 3382, - 3245, 3382, - 3245, 3380, - 3242, 3380, - 3242, 3382, - 3239, 3382, - 3239, 3381, - 3209, 3381, - 3209, 3382, - 3282, 3382); - - // Lumbridge - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3201, 3257, - 3213, 3257, - 3213, 3264, - 3233, 3264, - 3233, 3257, - 3235, 3257, - 3235, 3241, - 3237, 3241, - 3237, 3237, - 3239, 3237, - 3239, 3231, - 3243, 3231, - 3243, 3220, - 3253, 3220, - 3253, 3217, - 3256, 3217, - 3256, 3212, - 3259, 3212, - 3259, 3190, - 3247, 3190, - 3247, 3191, - 3238, 3191, - 3238, 3195, - 3230, 3195, - 3230, 3201, - 3228, 3201, - 3228, 3202, - 3227, 3202, - 3227, 3205, - 3228, 3205, - 3228, 3207, - 3225, 3207, - 3225, 3206, - 3224, 3206, - 3224, 3205, - 3223, 3205, - 3223, 3204, - 3222, 3204, - 3222, 3203, - 3215, 3203, - 3215, 3202, - 3214, 3202, - 3214, 3201, - 3203, 3201, - 3203, 3202, - 3202, 3202, - 3202, 3203, - 3201, 3203, - 3201, 3217, - 3199, 3217, - 3199, 3220, - 3201, 3220); - - // Falador - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2986, 3395, - 2986, 3394, - 2987, 3394, - 2987, 3393, - 2996, 3393, - 2996, 3394, - 3002, 3394, - 3002, 3395, - 3009, 3395, - 3009, 3394, - 3010, 3394, - 3010, 3393, - 3011, 3393, - 3011, 3392, - 3021, 3392, - 3021, 3391, - 3022, 3391, - 3022, 3390, - 3041, 3390, - 3041, 3389, - 3047, 3389, - 3047, 3390, - 3062, 3390, - 3062, 3389, - 3063, 3389, - 3063, 3388, - 3064, 3388, - 3064, 3387, - 3065, 3387, - 3065, 3386, - 3066, 3386, - 3066, 3368, - 3065, 3368, - 3065, 3367, - 3064, 3367, - 3064, 3366, - 3063, 3366, - 3063, 3365, - 3062, 3365, - 3062, 3364, - 3061, 3364, - 3061, 3363, - 3060, 3363, - 3060, 3331, - 3061, 3331, - 3061, 3328, - 3058, 3328, - 3058, 3329, - 3025, 3329, - 3025, 3328, - 3024, 3328, - 3024, 3327, - 3016, 3327, - 3016, 3326, - 3015, 3326, - 3015, 3325, - 3014, 3325, - 3014, 3324, - 3013, 3324, - 3013, 3323, - 3008, 3323, - 3008, 3324, - 3006, 3324, - 3006, 3323, - 3002, 3323, - 3002, 3322, - 3001, 3322, - 3001, 3321, - 3000, 3321, - 3000, 3320, - 2999, 3320, - 2999, 3319, - 2998, 3319, - 2998, 3318, - 2997, 3318, - 2997, 3317, - 2996, 3317, - 2996, 3316, - 2992, 3316, - 2992, 3315, - 2991, 3315, - 2991, 3314, - 2990, 3314, - 2990, 3313, - 2989, 3313, - 2989, 3312, - 2988, 3312, - 2988, 3311, - 2987, 3311, - 2987, 3310, - 2986, 3310, - 2986, 3309, - 2966, 3309, - 2966, 3310, - 2956, 3310, - 2956, 3311, - 2941, 3311, - 2941, 3312, - 2940, 3312, - 2940, 3320, - 2936, 3320, - 2936, 3354, - 2937, 3354, - 2937, 3357, - 2936, 3357, - 2936, 3389, - 2937, 3389, - 2937, 3390, - 2938, 3390, - 2938, 3391, - 2939, 3391, - 2939, 3392, - 2940, 3392, - 2940, 3393, - 2943, 3393, - 2943, 3394, - 2944, 3394, - 2944, 3395, - 2950, 3395, - 2950, 3394, - 2956, 3394, - 2956, 3395); - - // Port phasmatys - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3650, 3456, - 3650, 3472, - 3651, 3472, - 3651, 3473, - 3652, 3473, - 3652, 3474, - 3653, 3474, - 3653, 3507, - 3654, 3507, - 3654, 3508, - 3668, 3508, - 3668, 3509, - 3669, 3509, - 3669, 3510, - 3670, 3510, - 3670, 3511, - 3671, 3511, - 3671, 3512, - 3672, 3512, - 3672, 3513, - 3673, 3513, - 3673, 3514, - 3674, 3514, - 3674, 3515, - 3675, 3515, - 3675, 3516, - 3676, 3516, - 3676, 3517, - 3687, 3517, - 3687, 3494, - 3690, 3494, - 3690, 3493, - 3696, 3493, - 3696, 3482, - 3699, 3482, - 3699, 3481, - 3712, 3481, - 3712, 3456); - - // Sophanem - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3274, 2752, - 3274, 2784, - 3277, 2784, - 3277, 2786, - 3274, 2786, - 3274, 2789, - 3272, 2789, - 3272, 2810, - 3322, 2810, - 3322, 2752); - - // Ardy - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2560, 3256, - 2560, 3264, - 2559, 3264, - 2559, 3328, - 2560, 3328, - 2560, 3339, - 2561, 3339, - 2561, 3340, - 2562, 3340, - 2562, 3341, - 2563, 3341, - 2563, 3342, - 2616, 3342, - 2616, 3341, - 2617, 3341, - 2617, 3340, - 2669, 3340, - 2669, 3339, - 2670, 3339, - 2670, 3338, - 2671, 3338, - 2671, 3337, - 2672, 3337, - 2672, 3336, - 2673, 3336, - 2673, 3335, - 2674, 3335, - 2674, 3334, - 2683, 3334, - 2683, 3333, - 2684, 3333, - 2684, 3332, - 2685, 3332, - 2685, 3331, - 2686, 3331, - 2686, 3330, - 2687, 3330, - 2687, 3329, - 2688, 3329, - 2688, 3264, - 2638, 3264, - 2638, 3263, - 2625, 3263, - 2625, 3264, - 2611, 3264, - 2611, 3257, - 2602, 3257, - 2602, 3264, - 2587, 3264, - 2587, 3263, - 2586, 3263, - 2586, 3262, - 2584, 3262, - 2584, 3261, - 2583, 3261, - 2583, 3260, - 2582, 3260, - 2582, 3259, - 2581, 3259, - 2581, 3258, - 2572, 3258, - 2572, 3260, - 2571, 3260, - 2571, 3261, - 2566, 3261, - 2566, 3260, - 2565, 3260, - 2565, 3259, - 2564, 3259, - 2564, 3256); - - // Yanille - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2613, 3103, - 2614, 3103, - 2614, 3102, - 2615, 3102, - 2615, 3101, - 2616, 3101, - 2616, 3100, - 2617, 3100, - 2617, 3099, - 2618, 3099, - 2618, 3098, - 2619, 3098, - 2619, 3097, - 2620, 3097, - 2620, 3075, - 2590, 3075, - 2590, 3074, - 2589, 3074, - 2589, 3073, - 2584, 3073, - 2584, 3074, - 2583, 3074, - 2583, 3075, - 2543, 3075, - 2543, 3076, - 2542, 3076, - 2542, 3077, - 2539, 3077, - 2539, 3107, - 2542, 3107, - 2542, 3108, - 2543, 3108, - 2543, 3109, - 2608, 3109, - 2608, 3108, - 2609, 3108, - 2609, 3107, - 2610, 3107, - 2610, 3106, - 2611, 3106, - 2611, 3105, - 2612, 3105, - 2612, 3104, - 2613, 3104); - - // Gnome stronghold - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2495, 3439, - 2494, 3439, - 2494, 3432, - 2495, 3432, - 2495, 3431, - 2496, 3431, - 2496, 3430, - 2497, 3430, - 2497, 3429, - 2498, 3429, - 2498, 3417, - 2497, 3417, - 2497, 3416, - 2496, 3416, - 2496, 3412, - 2495, 3412, - 2495, 3408, - 2494, 3408, - 2494, 3404, - 2495, 3404, - 2495, 3403, - 2496, 3403, - 2496, 3402, - 2497, 3402, - 2497, 3401, - 2498, 3401, - 2498, 3400, - 2499, 3400, - 2499, 3399, - 2500, 3399, - 2500, 3398, - 2501, 3398, - 2501, 3397, - 2502, 3397, - 2502, 3396, - 2506, 3396, - 2506, 3391, - 2502, 3391, - 2502, 3390, - 2492, 3390, - 2492, 3391, - 2489, 3391, - 2489, 3390, - 2488, 3390, - 2488, 3389, - 2485, 3389, - 2485, 3390, - 2482, 3390, - 2482, 3389, - 2476, 3389, - 2476, 3390, - 2471, 3390, - 2471, 3391, - 2468, 3391, - 2468, 3390, - 2467, 3390, - 2467, 3389, - 2466, 3389, - 2466, 3385, - 2465, 3385, - 2465, 3384, - 2458, 3384, - 2458, 3385, - 2457, 3385, - 2457, 3389, - 2456, 3389, - 2456, 3390, - 2455, 3390, - 2455, 3391, - 2450, 3391, - 2450, 3390, - 2446, 3390, - 2446, 3391, - 2443, 3391, - 2443, 3390, - 2442, 3390, - 2442, 3389, - 2440, 3389, - 2440, 3388, - 2434, 3388, - 2434, 3389, - 2433, 3389, - 2433, 3390, - 2432, 3390, - 2432, 3391, - 2428, 3391, - 2428, 3392, - 2427, 3392, - 2427, 3393, - 2420, 3393, - 2420, 3394, - 2419, 3394, - 2419, 3395, - 2418, 3395, - 2418, 3396, - 2417, 3396, - 2417, 3397, - 2416, 3397, - 2416, 3399, - 2415, 3399, - 2415, 3400, - 2414, 3400, - 2414, 3408, - 2413, 3408, - 2413, 3409, - 2412, 3409, - 2412, 3410, - 2411, 3410, - 2411, 3411, - 2410, 3411, - 2410, 3412, - 2387, 3412, - 2387, 3407, - 2383, 3407, - 2383, 3408, - 2380, 3408, - 2380, 3409, - 2379, 3409, - 2379, 3410, - 2377, 3410, - 2377, 3411, - 2376, 3411, - 2376, 3413, - 2375, 3413, - 2375, 3417, - 2374, 3417, - 2374, 3418, - 2373, 3418, - 2373, 3419, - 2372, 3419, - 2372, 3420, - 2371, 3420, - 2371, 3421, - 2370, 3421, - 2370, 3422, - 2369, 3422, - 2369, 3433, - 2370, 3433, - 2370, 3434, - 2371, 3434, - 2371, 3444, - 2372, 3444, - 2372, 3445, - 2373, 3445, - 2373, 3446, - 2374, 3446, - 2374, 3447, - 2375, 3447, - 2375, 3459, - 2376, 3459, - 2376, 3460, - 2377, 3460, - 2377, 3461, - 2378, 3461, - 2378, 3462, - 2379, 3462, - 2379, 3463, - 2380, 3463, - 2380, 3464, - 2381, 3464, - 2381, 3476, - 2379, 3476, - 2379, 3477, - 2378, 3477, - 2378, 3478, - 2377, 3478, - 2377, 3485, - 2376, 3485, - 2376, 3486, - 2375, 3486, - 2375, 3499, - 2376, 3499, - 2376, 3500, - 2377, 3500, - 2377, 3507, - 2378, 3507, - 2378, 3508, - 2379, 3508, - 2379, 3509, - 2380, 3509, - 2380, 3521, - 2382, 3521, - 2382, 3522, - 2384, 3522, - 2384, 3523, - 2393, 3523, - 2393, 3524, - 2399, 3524, - 2399, 3525, - 2404, 3525, - 2404, 3524, - 2405, 3524, - 2405, 3523, - 2407, 3523, - 2407, 3522, - 2415, 3522, - 2415, 3521, - 2425, 3521, - 2425, 3522, - 2427, 3522, - 2427, 3523, - 2430, 3523, - 2430, 3522, - 2431, 3522, - 2431, 3521, - 2432, 3521, - 2432, 3520, - 2448, 3520, - 2448, 3517, - 2454, 3517, - 2454, 3516, - 2455, 3516, - 2455, 3515, - 2456, 3515, - 2456, 3514, - 2457, 3514, - 2457, 3513, - 2460, 3513, - 2460, 3512, - 2461, 3512, - 2461, 3511, - 2465, 3511, - 2465, 3510, - 2468, 3510, - 2468, 3511, - 2472, 3511, - 2472, 3512, - 2473, 3512, - 2473, 3513, - 2475, 3513, - 2475, 3514, - 2476, 3514, - 2476, 3515, - 2477, 3515, - 2477, 3516, - 2478, 3516, - 2478, 3517, - 2483, 3517, - 2483, 3516, - 2487, 3516, - 2487, 3515, - 2488, 3515, - 2488, 3512, - 2487, 3512, - 2487, 3509, - 2488, 3509, - 2488, 3508, - 2489, 3508, - 2489, 3507, - 2491, 3507, - 2491, 3506, - 2492, 3506, - 2492, 3505, - 2493, 3505, - 2493, 3499, - 2492, 3499, - 2492, 3498, - 2491, 3498, - 2491, 3497, - 2490, 3497, - 2490, 3495, - 2491, 3495, - 2491, 3494, - 2492, 3494, - 2492, 3493, - 2493, 3493, - 2493, 3485, - 2490, 3485, - 2490, 3484, - 2489, 3484, - 2489, 3483, - 2488, 3483, - 2488, 3482, - 2487, 3482, - 2487, 3481, - 2486, 3481, - 2486, 3474, - 2488, 3474, - 2488, 3471, - 2489, 3471, - 2489, 3470, - 2490, 3470, - 2490, 3460, - 2491, 3460, - 2491, 3456, - 2496, 3456, - 2496, 3440, - 2495, 3440); - - // Rellekka - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2620, 3682, - 2624, 3682, - 2624, 3683, - 2625, 3683, - 2625, 3687, - 2629, 3687, - 2629, 3686, - 2630, 3686, - 2630, 3685, - 2632, 3685, - 2632, 3686, - 2636, 3686, - 2636, 3692, - 2645, 3692, - 2645, 3695, - 2647, 3695, - 2647, 3696, - 2649, 3696, - 2649, 3702, - 2650, 3702, - 2650, 3703, - 2651, 3703, - 2651, 3704, - 2652, 3704, - 2652, 3711, - 2653, 3711, - 2653, 3712, - 2691, 3712, - 2691, 3709, - 2692, 3709, - 2692, 3707, - 2693, 3707, - 2693, 3703, - 2692, 3703, - 2692, 3701, - 2691, 3701, - 2691, 3699, - 2690, 3699, - 2690, 3695, - 2691, 3695, - 2691, 3693, - 2692, 3693, - 2692, 3691, - 2693, 3691, - 2693, 3685, - 2692, 3685, - 2692, 3683, - 2691, 3683, - 2691, 3681, - 2690, 3681, - 2690, 3680, - 2689, 3680, - 2689, 3672, - 2690, 3672, - 2690, 3671, - 2691, 3671, - 2691, 3666, - 2690, 3666, - 2690, 3664, - 2689, 3664, - 2689, 3660, - 2690, 3660, - 2690, 3658, - 2691, 3658, - 2691, 3656, - 2692, 3656, - 2692, 3654, - 2693, 3654, - 2693, 3651, - 2692, 3651, - 2692, 3649, - 2690, 3649, - 2690, 3648, - 2688, 3648, - 2688, 3647, - 2686, 3647, - 2686, 3646, - 2673, 3646, - 2673, 3645, - 2636, 3645, - 2636, 3647, - 2627, 3647, - 2627, 3648, - 2625, 3648, - 2625, 3649, - 2624, 3649, - 2624, 3650, - 2622, 3650, - 2622, 3651, - 2620, 3651, - 2620, 3652, - 2618, 3652, - 2618, 3653, - 2616, 3653, - 2616, 3654, - 2609, 3654, - 2609, 3655, - 2607, 3655, - 2607, 3656, - 2603, 3656, - 2603, 3657, - 2602, 3657, - 2602, 3658, - 2601, 3658, - 2601, 3663, - 2602, 3663, - 2602, 3664, - 2603, 3664, - 2603, 3665, - 2604, 3665, - 2604, 3666, - 2605, 3666, - 2605, 3667, - 2606, 3667, - 2606, 3671, - 2609, 3671, - 2609, 3672, - 2610, 3672, - 2610, 3673, - 2611, 3673, - 2611, 3675, - 2612, 3675, - 2612, 3676, - 2614, 3676, - 2614, 3677, - 2616, 3677, - 2616, 3679, - 2618, 3679, - 2618, 3681, - 2620, 3681); - - // Jatizo - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2407, 3797, - 2407, 3793, - 2399, 3793, - 2399, 3792, - 2391, 3792, - 2391, 3791, - 2386, 3791, - 2386, 3796, - 2388, 3796, - 2388, 3802, - 2386, 3802, - 2386, 3807, - 2388, 3807, - 2388, 3809, - 2402, 3809, - 2402, 3819, - 2406, 3819, - 2406, 3824, - 2408, 3824, - 2408, 3826, - 2413, 3826, - 2413, 3824, - 2419, 3824, - 2419, 3826, - 2424, 3826, - 2424, 3821, - 2423, 3821, - 2423, 3798, - 2422, 3798, - 2422, 3797); - - // Neitiznot - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2329, 3812, - 2333, 3812, - 2333, 3813, - 2334, 3813, - 2334, 3814, - 2335, 3814, - 2335, 3815, - 2338, 3815, - 2338, 3816, - 2339, 3816, - 2339, 3817, - 2368, 3817, - 2368, 3776, - 2352, 3776, - 2352, 3796, - 2344, 3796, - 2344, 3795, - 2331, 3795, - 2331, 3797, - 2330, 3797, - 2330, 3798, - 2329, 3798); - - // Pest control - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2624, 2688, - 2688, 2688, - 2688, 2624, - 2624, 2624); - - // Tutorial island - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 3052, 3135, - 3156, 3135, - 3156, 3057, - 3052, 3057); - - // Camelot bank - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2724, 3487, - 2724, 3490, - 2721, 3490, - 2721, 3494, - 2719, 3494, - 2719, 3497, - 2721, 3497, - 2721, 3498, - 2731, 3498, - 2731, 3490, - 2728, 3490, - 2728, 3487); - - // Catherby bank - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 2806, 3438, - 2806, 3446, - 2813, 3446, - 2813, 3438); - - // Kourend castle - addPolygonOnPlane(DEADMAN_SAFE_ZONES, 0, - 1627, 3658, - 1620, 3658, - 1620, 3657, - 1619, 3657, - 1619, 3656, - 1614, 3656, - 1614, 3657, - 1613, 3657, - 1613, 3661, - 1612, 3661, - 1612, 3662, - 1611, 3662, - 1611, 3663, - 1600, 3663, - 1600, 3662, - 1599, 3662, - 1599, 3661, - 1594, 3661, - 1594, 3662, - 1593, 3662, - 1593, 3685, - 1594, 3685, - 1594, 3686, - 1599, 3686, - 1599, 3685, - 1600, 3685, - 1600, 3684, - 1611, 3684, - 1611, 3685, - 1612, 3685, - 1612, 3686, - 1613, 3686, - 1613, 3690, - 1614, 3690, - 1614, 3691, - 1619, 3691, - 1619, 3690, - 1620, 3690, - 1620, 3689, - 1630, 3689, - 1630, 3686, - 1620, 3686, - 1620, 3685, - 1619, 3685, - 1619, 3683, - 1620, 3683, - 1620, 3682, - 1621, 3682, - 1621, 3681, - 1622, 3681, - 1622, 3680, - 1623, 3680, - 1623, 3679, - 1624, 3679, - 1624, 3668, - 1623, 3668, - 1623, 3667, - 1622, 3667, - 1622, 3666, - 1621, 3666, - 1621, 3665, - 1620, 3665, - 1620, 3664, - 1619, 3664, - 1619, 3662, - 1620, 3662, - 1620, 3661, - 1627, 3661); - } - - private static void definePvpSafeZones() - { - // Grand exchange - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3159, 3473, - 3159, 3474, - 3157, 3474, - 3157, 3475, - 3155, 3475, - 3155, 3476, - 3153, 3476, - 3153, 3477, - 3152, 3477, - 3152, 3478, - 3151, 3478, - 3151, 3480, - 3150, 3480, - 3150, 3482, - 3149, 3482, - 3149, 3484, - 3148, 3484, - 3148, 3496, - 3149, 3496, - 3149, 3498, - 3150, 3498, - 3150, 3500, - 3151, 3500, - 3151, 3502, - 3152, 3502, - 3152, 3503, - 3153, 3503, - 3153, 3504, - 3155, 3504, - 3155, 3505, - 3157, 3505, - 3157, 3506, - 3159, 3506, - 3159, 3507, - 3171, 3507, - 3171, 3506, - 3173, 3506, - 3173, 3505, - 3175, 3505, - 3175, 3504, - 3177, 3504, - 3177, 3503, - 3178, 3503, - 3178, 3502, - 3179, 3502, - 3179, 3500, - 3180, 3500, - 3180, 3498, - 3181, 3498, - 3181, 3496, - 3182, 3496, - 3182, 3484, - 3181, 3484, - 3181, 3482, - 3180, 3482, - 3180, 3480, - 3179, 3480, - 3179, 3478, - 3178, 3478, - 3178, 3477, - 3177, 3477, - 3177, 3476, - 3175, 3476, - 3175, 3475, - 3173, 3475, - 3173, 3474, - 3171, 3474, - 3171, 3473); - - // Edgeville - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3091, 3488, - 3091, 3493, - 3090, 3493, - 3090, 3498, - 3091, 3498, - 3091, 3500, - 3099, 3500, - 3099, 3488); - - // Fally west bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2943, 3368, - 2943, 3374, - 2948, 3374, - 2948, 3370, - 2950, 3370, - 2950, 3366, - 2949, 3366, - 2949, 3359, - 2945, 3359, - 2945, 3362, - 2946, 3362, - 2946, 3366, - 2945, 3366, - 2945, 3368); - - // Fally east bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3009, 3353, - 3009, 3359, - 3019, 3359, - 3019, 3357, - 3022, 3357, - 3022, 3353); - - // Fally castle - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2964, 3354, - 2966, 3354, - 2966, 3352, - 2967, 3352, - 2967, 3349, - 2976, 3349, - 2976, 3348, - 2977, 3348, - 2977, 3347, - 2981, 3347, - 2981, 3343, - 2982, 3343, - 2982, 3339, - 2981, 3339, - 2981, 3337, - 2967, 3337, - 2967, 3330, - 2963, 3330, - 2963, 3331, - 2962, 3331, - 2962, 3332, - 2961, 3332, - 2961, 3334, - 2964, 3334, - 2964, 3335, - 2965, 3335, - 2965, 3343, - 2964, 3343, - 2964, 3344, - 2961, 3344, - 2961, 3350, - 2963, 3350, - 2963, 3352, - 2964, 3352); - - // Varrock east bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3250, 3425, - 3258, 3425, - 3258, 3416, - 3250, 3416); - - // Varrock west bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3180, 3433, - 3180, 3448, - 3191, 3448, - 3191, 3433); - - // Port phasmatys - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3686, 3472, - 3700, 3472, - 3700, 3461, - 3686, 3461); - - // Yanille bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2609, 3088, - 2609, 3098, - 2617, 3098, - 2617, 3088); - - // Ardy east bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2649, 3280, - 2649, 3288, - 2659, 3288, - 2659, 3280); - - // Ardy west bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2612, 3330, - 2612, 3336, - 2615, 3336, - 2615, 3335, - 2619, 3335, - 2619, 3336, - 2622, 3336, - 2622, 3330); - - // Fishing guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2593, 3413, - 2588, 3413, - 2588, 3418, - 2583, 3418, - 2583, 3423, - 2590, 3423, - 2590, 3420, - 2593, 3420); - - // Gnome stronghold bank near slayer cave (2nd floor) - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, - 2444, 3431, - 2444, 3435, - 2448, 3435, - 2448, 3431, - 2447, 3431, - 2447, 3428, - 2449, 3428, - 2449, 3422, - 2447, 3422, - 2447, 3419, - 2448, 3419, - 2448, 3415, - 2444, 3415, - 2444, 3419, - 2445, 3419, - 2445, 3422, - 2443, 3422, - 2443, 3428, - 2445, 3428, - 2445, 3431); - - // Gnome stronghold bank in grand tree - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, - 2456, 3488, - 2452, 3488, - 2452, 3486, - 2450, 3486, - 2450, 3483, - 2451, 3483, - 2451, 3478, - 2448, 3478, - 2448, 3483, - 2449, 3483, - 2449, 3486, - 2447, 3486, - 2447, 3488, - 2443, 3488, - 2443, 3487, - 2438, 3487, - 2438, 3490, - 2443, 3490, - 2443, 3489, - 2447, 3489, - 2447, 3491, - 2449, 3491, - 2449, 3494, - 2448, 3494, - 2448, 3496, - 2451, 3496, - 2451, 3494, - 2450, 3494, - 2450, 3491, - 2452, 3491, - 2452, 3489, - 2456, 3489); - - // Al kharid bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3265, 3161, - 3265, 3174, - 3273, 3174, - 3273, 3161); - - // Shantay pass bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3308, 3119, - 3308, 3125, - 3310, 3125, - 3310, 3119); - - // Nardah bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3431, 2891, - 3431, 2889, - 3427, 2889, - 3427, 2887, - 3424, 2887, - 3424, 2895, - 3431, 2895, - 3431, 2893, - 3432, 2893, - 3432, 2891); - - // Sophanem bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2807, 5158, - 2792, 5158, - 2792, 5175, - 2807, 5175); - - // Canifis bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3509, 3474, - 3509, 3478, - 3508, 3478, - 3508, 3483, - 3509, 3483, - 3509, 3484, - 3517, 3484, - 3517, 3477, - 3516, 3477, - 3516, 3476, - 3513, 3476, - 3513, 3474); - - // Lumbridge castle outside - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3216, 3209, - 3216, 3210, - 3217, 3210, - 3217, 3228, - 3216, 3228, - 3216, 3229, - 3227, 3229, - 3227, 3221, - 3230, 3221, - 3230, 3217, - 3227, 3217, - 3227, 3209); - - // Lumbridge bank upstairs - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, - 3211, 3223, - 3211, 3215, - 3207, 3215, - 3207, 3223); - - // Draynor bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3098, 3240, - 3088, 3240, - 3088, 3247, - 3098, 3247); - - // Pest control bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2665, 2656, - 2670, 2656, - 2670, 2651, - 2665, 2651); - - // Shilo village bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2843, 2957, - 2846, 2957, - 2846, 2956, - 2849, 2956, - 2849, 2957, - 2850, 2957, - 2850, 2958, - 2855, 2958, - 2855, 2957, - 2856, 2957, - 2856, 2956, - 2858, 2956, - 2858, 2957, - 2862, 2957, - 2862, 2952, - 2858, 2952, - 2858, 2953, - 2856, 2953, - 2856, 2952, - 2855, 2952, - 2855, 2951, - 2850, 2951, - 2850, 2952, - 2849, 2952, - 2849, 2953, - 2847, 2953, - 2847, 2952, - 2843, 2952); - - // Legends guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 2, - 2731, 3374, - 2731, 3383, - 2734, 3383, - 2734, 3374); - - // Legends guild middle floor - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 1, - 2724, 3374, - 2724, 3383, - 2734, 3383, - 2734, 3382, - 2736, 3382, - 2736, 3375, - 2734, 3375, - 2734, 3374); - - // Warriors guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2843, 3537, - 2843, 3540, - 2841, 3540, - 2841, 3546, - 2849, 3546, - 2849, 3537, - 2847, 3537, - 2847, 3536, - 2846, 3536, - 2846, 3537); - - // Camelot bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2724, 3487, - 2724, 3490, - 2721, 3490, - 2721, 3494, - 2719, 3494, - 2719, 3497, - 2721, 3497, - 2721, 3498, - 2731, 3498, - 2731, 3490, - 2728, 3490, - 2728, 3487); - - // Camelot respawn point - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2761, 3483, - 2761, 3476, - 2755, 3476, - 2755, 3483); - - // Catherby bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2806, 3438, - 2806, 3446, - 2813, 3446, - 2813, 3438); - - // Barbarian outpost bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2536, 3572, - 2536, 3575, - 2538, 3575, - 2538, 3572); - - // Piscatoris bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2327, 3686, - 2327, 3694, - 2333, 3694, - 2333, 3686); - - // Lletya bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2350, 3161, - 2350, 3165, - 2351, 3165, - 2351, 3167, - 2357, 3167, - 2357, 3165, - 2356, 3165, - 2356, 3164, - 2355, 3164, - 2355, 3161); - - // Castle wars bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2446, 3087, - 2445, 3087, - 2445, 3085, - 2447, 3085, - 2447, 3081, - 2443, 3081, - 2443, 3082, - 2439, 3082, - 2439, 3081, - 2435, 3081, - 2435, 3099, - 2439, 3099, - 2439, 3098, - 2443, 3098, - 2443, 3099, - 2447, 3099, - 2447, 3095, - 2445, 3095, - 2445, 3093, - 2446, 3093); - - // Duel arena bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3380, 3267, - 3380, 3273, - 3381, 3273, - 3381, 3274, - 3385, 3274, - 3385, 3267); - - // Clan wars bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3375, 3165, - 3361, 3165, - 3361, 3173, - 3375, 3173); - - // Lumbridge cellar bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 3218, 9622, - 3218, 9624, - 3220, 9624, - 3220, 9622); - - // Dorgesh kaan bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2709, 5348, - 2707, 5348, - 2707, 5345, - 2701, 5345, - 2701, 5347, - 2697, 5347, - 2697, 5353, - 2701, 5353, - 2701, 5355, - 2707, 5355, - 2707, 5350, - 2709, 5350); - - // Keldagrim bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2842, 10204, - 2834, 10204, - 2834, 10216, - 2842, 10216); - - // Tzhaar bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2438, 5176, - 2438, 5180, - 2441, 5180, - 2441, 5182, - 2449, 5182, - 2449, 5181, - 2450, 5181, - 2450, 5180, - 2452, 5180, - 2452, 5175, - 2441, 5175, - 2441, 5176); - - // Inferno bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2542, 5135, - 2542, 5139, - 2539, 5139, - 2539, 5140, - 2538, 5140, - 2538, 5141, - 2537, 5141, - 2537, 5144, - 2541, 5144, - 2541, 5145, - 2543, 5145, - 2543, 5144, - 2544, 5144, - 2544, 5142, - 2545, 5142, - 2545, 5135); - - // Port khazard bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2661, 3160, - 2661, 3163, - 2666, 3163, - 2666, 3160); - - // Corsair cove bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2569, 2863, - 2569, 2868, - 2572, 2868, - 2572, 2863); - - // Burgh de rott bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3495, 3210, - 3495, 3214, - 3501, 3214, - 3501, 3210); - - // Edgeville respawn point - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3092, 3468, - 3092, 3474, - 3098, 3474, - 3098, 3468); - - // Mage bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2529, 4711, - 2529, 4724, - 2548, 4724, - 2548, 4711); - - // Lunar bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2097, 3917, - 2097, 3922, - 2105, 3922, - 2105, 3917); - - // Jatizo bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2414, 3801, - 2414, 3804, - 2420, 3804, - 2420, 3801); - - // Neitiznot bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2334, 3805, - 2334, 3809, - 2340, 3809, - 2340, 3805); - - // Hosidius bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1671, 3558, - 1671, 3577, - 1682, 3577, - 1682, 3558); - - // Woodcutting guild bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1589, 3475, - 1589, 3481, - 1594, 3481, - 1594, 3475); - - // Lands end bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1508, 3415, - 1508, 3424, - 1514, 3424, - 1514, 3415); - - // Chambers of xeric bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1252, 3570, - 1252, 3574, - 1257, 3574, - 1257, 3570); - - // Arceuus bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1621, 3736, - 1621, 3754, - 1627, 3754, - 1627, 3751, - 1633, 3751, - 1633, 3754, - 1639, 3754, - 1639, 3736); - - // Piscarilius bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1794, 3784, - 1794, 3794, - 1812, 3794, - 1812, 3784); - - // Lovakengj bank southeast - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1518, 3735, - 1518, 3744, - 1535, 3744, - 1535, 3735); - - // Lovakenj bank west - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1433, 3820, - 1433, 3837, - 1442, 3837, - 1442, 3820); - - // Lovakenj sulphur mine bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1452, 3855, - 1452, 3860, - 1455, 3860, - 1455, 3855); - - // Blast mine bank southeast - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1500, 3856, - 1500, 3858, - 1503, 3858, - 1503, 3856); - - // Wintertodt bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1638, 3942, - 1638, 3947, - 1642, 3947, - 1642, 3942); - - // Shayzien bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1495, 3612, - 1495, 3622, - 1515, 3622, - 1515, 3612); - - // Hosidius grape farm bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1804, 3571, - 1804, 3572, - 1808, 3572, - 1808, 3571); - - // Hosidius cooking bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 1652, 3605, - 1652, 3615, - 1661, 3615, - 1661, 3605); - - // Ecteria bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 2618, 3893, - 2618, 3897, - 2622, 3897, - 2622, 3893); - - // Mining guild expanded area - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 3018, 9733, - 3021, 9733, - 3021, 9729, - 3022, 9729, - 3022, 9728, - 3023, 9728, - 3023, 9727, - 3025, 9727, - 3025, 9726, - 3026, 9726, - 3026, 9725, - 3030, 9725, - 3030, 9726, - 3032, 9726, - 3032, 9727, - 3035, 9727, - 3035, 9726, - 3038, 9726, - 3038, 9727, - 3041, 9727, - 3041, 9728, - 3042, 9728, - 3042, 9730, - 3045, 9730, - 3045, 9727, - 3047, 9727, - 3047, 9726, - 3048, 9726, - 3048, 9724, - 3052, 9724, - 3052, 9725, - 3053, 9725, - 3053, 9726, - 3055, 9726, - 3055, 9725, - 3056, 9725, - 3056, 9723, - 3057, 9723, - 3057, 9720, - 3056, 9720, - 3056, 9719, - 3054, 9719, - 3054, 9718, - 3052, 9718, - 3052, 9717, - 3050, 9717, - 3050, 9718, - 3045, 9718, - 3045, 9716, - 3044, 9716, - 3044, 9715, - 3041, 9715, - 3041, 9714, - 3039, 9714, - 3039, 9713, - 3037, 9713, - 3037, 9714, - 3036, 9714, - 3036, 9715, - 3034, 9715, - 3034, 9716, - 3029, 9716, - 3029, 9715, - 3028, 9715, - 3028, 9714, - 3026, 9714, - 3026, 9709, - 3027, 9709, - 3027, 9708, - 3028, 9708, - 3028, 9705, - 3029, 9705, - 3029, 9701, - 3028, 9701, - 3028, 9700, - 3027, 9700, - 3027, 9699, - 3023, 9699, - 3023, 9700, - 3019, 9700, - 3019, 9701, - 3018, 9701, - 3018, 9705, - 3019, 9705, - 3019, 9707, - 3020, 9707, - 3020, 9708, - 3021, 9708, - 3021, 9709, - 3022, 9709, - 3022, 9713, - 3021, 9713, - 3021, 9714, - 3019, 9714, - 3019, 9715, - 3018, 9715, - 3018, 9717, - 3015, 9717, - 3015, 9716, - 3013, 9716, - 3013, 9717, - 3012, 9717, - 3012, 9720, - 3013, 9720, - 3013, 9721, - 3015, 9721, - 3015, 9723, - 3016, 9723, - 3016, 9727, - 3017, 9727, - 3017, 9730, - 3018, 9730); - - // Motherlode mine bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 3760, 5671, - 3760, 5668, - 3761, 5668, - 3761, 5665, - 3760, 5665, - 3760, 5663, - 3758, 5663, - 3758, 5671); - - // Mos le harmles bank - addPolygonOnPlane(PVP_WORLD_SAFE_ZONES, 0, - 3679, 2980, - 3679, 2985, - 3681, 2985, - 3681, 2984, - 3682, 2984, - 3682, 2985, - 3684, 2985, - 3684, 2980, - 3682, 2980, - 3682, 2981, - 3681, 2981, - 3681, 2980); - - // Zanaris bank - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 2388, 4454, - 2380, 4454, - 2380, 4463, - 2388, 4463); - - // Wodcuting guild bank underground - addPolygonTo(PVP_WORLD_SAFE_ZONES, - 1550, 9872, - 1550, 9874, - 1553, 9874, - 1553, 9872); - } - - private static void defineWilderness() - { - // Above ground - addPolygonTo(ROUGH_WILDERNESS, - 2944, 3523, - 3392, 3523, - 3392, 3971, - 2944, 3971); - - // Underground - addPolygonTo(ROUGH_WILDERNESS, - 2944, 9918, - 2944, 10360, - 3264, 10360, - 3264, 9918); - } - - private static void addPolygonTo(List[] shapes, int... coords) - { - Polygon poly = new Polygon(); - for (int i = 0; i < coords.length; i += 2) - { - poly.addPoint(coords[i], coords[i + 1]); - } - for (int i = 0; i < shapes.length; i++) - { - shapes[i].add(poly); - } - } - - private static void addPolygonOnPlane(List[] shapes, int plane, int... coords) - { - Polygon poly = new Polygon(); - for (int i = 0; i < coords.length; i += 2) - { - poly.addPoint(coords[i], coords[i + 1]); - } - shapes[plane].add(poly); - } - - private static void addPolygonOnPlanes(List[] shapes, int minPlane, int maxPlane, int... coords) - { - Polygon poly = new Polygon(); - for (int i = 0; i < coords.length; i += 2) - { - poly.addPoint(coords[i], coords[i + 1]); - } - for (int i = minPlane; i <= maxPlane; i++) - { - shapes[i].add(poly); - } - } -} \ No newline at end of file From 9be2b74747c09b3c3a8bfd84cc3129591a64da42 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:36:00 +0100 Subject: [PATCH 17/21] Delete ZoneIndicatorsConfig.java --- .../zoneIndicators/ZoneIndicatorsConfig.java | 111 ------------------ 1 file changed, 111 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java deleted file mode 100644 index 370533dac7..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsConfig.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.zoneIndicators; - -import java.awt.Color; -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("zoneIndicators") -public interface ZoneIndicatorsConfig extends Config -{ - @ConfigItem( - keyName = "multicombatZoneVisibility", - name = "Multicombat zones", - description = "Determine where multicombat zones should be shown", - position = 1 - ) - default ZoneVisibility multicombatZoneVisibility() - { - return ZoneVisibility.SHOW_IN_PVP; - } - - @ConfigItem( - keyName = "pvpSafeZones", - name = "PvP safe zones", - description = "Show safe zones in PvP worlds", - position = 2 - ) - default boolean showPvpSafeZones() - { - return true; - } - - @ConfigItem( - keyName = "deadmanSafeZones", - name = "Deadman safe zones", - description = "Show safe zones in Deadman worlds", - position = 3 - ) - default boolean showDeadmanSafeZones() - { - return true; - } - - @ConfigItem( - keyName = "collisionDetection", - name = "Collision detection", - description = "Only show lines where they can be walked through", - position = 4 - ) - default boolean collisionDetection() - { - return false; - } - - @ConfigItem( - keyName = "showMinimapLines", - name = "Show on minimap", - description = "Show multicombat and safe zones on the minimap", - position = 5 - ) - default boolean showMinimapLines() - { - return true; - } - - @ConfigItem( - keyName = "multicombatColor", - name = "Multicombat zone color", - description = "Choose color to use for marking multicombat zones", - position = 6 - ) - default Color multicombatColor() - { - return Color.MAGENTA; - } - - @ConfigItem( - keyName = "safeZoneColor", - name = "Safe zone color", - description = "Choose color to use for marking safe zones in PvP/Deadman", - position = 7 - ) - default Color safeZoneColor() - { - return Color.GREEN; - } -} \ No newline at end of file From fd1678463f771262f0fca6b6871b69cc09bd2bfa Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:36:07 +0100 Subject: [PATCH 18/21] Delete ZoneIndicatorsMinimapOverlay.java --- .../ZoneIndicatorsMinimapOverlay.java | 116 ------------------ 1 file changed, 116 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java deleted file mode 100644 index 699b0f0ddf..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsMinimapOverlay.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.zoneIndicators; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.GeneralPath; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.geometry.Geometry; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; - -public class ZoneIndicatorsMinimapOverlay extends Overlay -{ - private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; - - @Inject - private Client client; - - @Inject - private ZoneIndicatorsPlugin plugin; - - @Inject - private ZoneIndicatorsConfig config; - - @Inject - public ZoneIndicatorsMinimapOverlay() - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ALWAYS_ON_TOP); - setPriority(OverlayPriority.LOW); - } - - private Color getTransparentColorVersion(Color c) - { - return new Color(c.getRed(), c.getGreen(), c.getBlue(), 192); - } - - private void renderPath(Graphics2D graphics, GeneralPath path, Color color) - { - LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); - Rectangle viewArea = new Rectangle( - playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, - playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, - MAX_LOCAL_DRAW_LENGTH * 2, - MAX_LOCAL_DRAW_LENGTH * 2); - - graphics.setColor(color); - - path = Geometry.clipPath(path, viewArea); - path = Geometry.filterPath(path, (p1, p2) -> - Perspective.localToMinimap(client, new LocalPoint((int)p1[0], (int)p1[1])) != null && - Perspective.localToMinimap(client, new LocalPoint((int)p2[0], (int)p2[1])) != null); - path = Geometry.transformPath(path, coords -> - { - Point point = Perspective.localToMinimap(client, new LocalPoint((int)coords[0], (int)coords[1])); - coords[0] = point.getX(); - coords[1] = point.getY(); - }); - - graphics.draw(path); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!config.showMinimapLines()) - { - return null; - } - - GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; - GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; - - if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) - { - renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); - } - if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) - { - renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); - } - - return null; - } -} \ No newline at end of file From 114f3a35a15e14acd36522ee60f3e65dd286d75b Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:36:13 +0100 Subject: [PATCH 19/21] Delete ZoneIndicatorsOverlay.java --- .../zoneIndicators/ZoneIndicatorsOverlay.java | 113 ------------------ 1 file changed, 113 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java deleted file mode 100644 index 0f52222e8b..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsOverlay.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.zoneIndicators; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.GeneralPath; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.Point; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.geometry.Geometry; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; - -public class ZoneIndicatorsOverlay extends Overlay -{ - private final static int MAX_LOCAL_DRAW_LENGTH = 20 * Perspective.LOCAL_TILE_SIZE; - - @Inject - private Client client; - - @Inject - private ZoneIndicatorsPlugin plugin; - - @Inject - private ZoneIndicatorsConfig config; - - @Inject - public ZoneIndicatorsOverlay() - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_SCENE); - setPriority(OverlayPriority.LOW); - } - - private Color getTransparentColorVersion(Color c) - { - return new Color(c.getRed(), c.getGreen(), c.getBlue(), 92); - } - - private void renderPath(Graphics2D graphics, GeneralPath path, Color color) - { - LocalPoint playerLp = client.getLocalPlayer().getLocalLocation(); - Rectangle viewArea = new Rectangle( - playerLp.getX() - MAX_LOCAL_DRAW_LENGTH, - playerLp.getY() - MAX_LOCAL_DRAW_LENGTH, - MAX_LOCAL_DRAW_LENGTH * 2, - MAX_LOCAL_DRAW_LENGTH * 2); - - graphics.setColor(color); - graphics.setStroke(new BasicStroke(2)); - - path = Geometry.clipPath(path, viewArea); - path = Geometry.filterPath(path, (p1, p2) -> - Perspective.localToCanvas(client, new LocalPoint((int)p1[0], (int)p1[1]), client.getPlane()) != null && - Perspective.localToCanvas(client, new LocalPoint((int)p2[0], (int)p2[1]), client.getPlane()) != null); - path = Geometry.transformPath(path, coords -> - { - Point point = Perspective.localToCanvas(client, new LocalPoint((int)coords[0], (int)coords[1]), client.getPlane()); - coords[0] = point.getX(); - coords[1] = point.getY(); - }); - - graphics.draw(path); - } - - @Override - public Dimension render(Graphics2D graphics) - { - GeneralPath multicombatPath = plugin.getMulticombatPathToDisplay()[client.getPlane()]; - GeneralPath pvpPath = plugin.getPvpPathToDisplay()[client.getPlane()]; - - if (config.multicombatZoneVisibility() != ZoneVisibility.HIDE && multicombatPath != null) - { - renderPath(graphics, multicombatPath, getTransparentColorVersion(config.multicombatColor())); - } - if ((config.showPvpSafeZones() || config.showDeadmanSafeZones()) && pvpPath != null) - { - renderPath(graphics, pvpPath, getTransparentColorVersion(config.safeZoneColor())); - } - - return null; - } -} \ No newline at end of file From 8b81946a9093b31173449034a8388f42f48528e0 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:36:19 +0100 Subject: [PATCH 20/21] Delete ZoneIndicatorsPlugin.java --- .../zoneIndicators/ZoneIndicatorsPlugin.java | 298 ------------------ 1 file changed, 298 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java deleted file mode 100644 index b48ffa41e9..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneIndicatorsPlugin.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.zoneIndicators; - -import net.runelite.client.eventbus.Subscribe; -import com.google.inject.Provides; -import java.awt.Rectangle; -import java.awt.geom.GeneralPath; -import java.util.Arrays; -import javax.inject.Inject; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.Constants; -import net.runelite.api.GameState; -import net.runelite.api.ObjectComposition; -import net.runelite.api.Perspective; -import net.runelite.api.Tile; -import net.runelite.api.WallObject; -import net.runelite.api.WorldType; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldArea; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.geometry.Geometry; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.OverlayManager; - -@PluginDescriptor( - name = "MultiLines", - description = "Show borders of multicombat and PvP safezones", - tags = {"multicombat", "lines", "pvp", "deadman", "safezones", "bogla"}, - type = "utility", - enabledByDefault = false -) -public class ZoneIndicatorsPlugin extends Plugin -{ - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private ZoneIndicatorsConfig config; - - @Inject - private ZoneIndicatorsOverlay overlay; - - @Inject - private ZoneIndicatorsMinimapOverlay minimapOverlay; - - @Inject - private OverlayManager overlayManager; - - @Getter - private GeneralPath[] multicombatPathToDisplay; - - @Getter - private GeneralPath[] pvpPathToDisplay; - - @Getter - private boolean inPvp; - - @Getter - private boolean inDeadman; - - private int currentPlane; - - @Provides - ZoneIndicatorsConfig getConfig(ConfigManager configManager) - { - return configManager.getConfig(ZoneIndicatorsConfig.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - overlayManager.add(minimapOverlay); - - multicombatPathToDisplay = new GeneralPath[Constants.MAX_Z]; - pvpPathToDisplay = new GeneralPath[Constants.MAX_Z]; - - clientThread.invokeLater(() -> - { - if (client.getGameState() == GameState.LOGGED_IN) - { - findLinesInScene(); - } - }); - } - - @Override - protected void shutDown() throws Exception - { - overlayManager.remove(overlay); - overlayManager.remove(minimapOverlay); - - multicombatPathToDisplay = null; - pvpPathToDisplay = null; - } - - private void transformWorldToLocal(float[] coords) - { - LocalPoint lp = LocalPoint.fromWorld(client, (int)coords[0], (int)coords[1]); - coords[0] = lp.getX() - Perspective.LOCAL_TILE_SIZE / 2; - coords[1] = lp.getY() - Perspective.LOCAL_TILE_SIZE / 2; - } - - private boolean isOpenableAt(WorldPoint wp) - { - int sceneX = wp.getX() - client.getBaseX(); - int sceneY = wp.getY() - client.getBaseY(); - - Tile tile = client.getScene().getTiles()[wp.getPlane()][sceneX][sceneY]; - if (tile == null) - { - return false; - } - - WallObject wallObject = tile.getWallObject(); - if (wallObject == null) - { - return false; - } - - ObjectComposition objectComposition = client.getObjectDefinition(wallObject.getId()); - if (objectComposition == null) - { - return false; - } - - String[] actions = objectComposition.getActions(); - if (actions == null) - { - return false; - } - - return Arrays.stream(actions).anyMatch(x -> x != null && x.toLowerCase().equals("open")); - } - - private boolean collisionFilter(float[] p1, float[] p2) - { - int x1 = (int)p1[0]; - int y1 = (int)p1[1]; - int x2 = (int)p2[0]; - int y2 = (int)p2[1]; - - if (x1 > x2) - { - int temp = x1; - x1 = x2; - x2 = temp; - } - if (y1 > y2) - { - int temp = y1; - y1 = y2; - y2 = temp; - } - int dx = x2 - x1; - int dy = y2 - y1; - WorldArea wa1 = new WorldArea(new WorldPoint( - x1, y1, currentPlane), 1, 1); - WorldArea wa2 = new WorldArea(new WorldPoint( - x1 - dy, y1 - dx, currentPlane), 1, 1); - - if (isOpenableAt(wa1.toWorldPoint()) || isOpenableAt(wa2.toWorldPoint())) - { - // When there's something with the open option (e.g. a door) on the tile, - // we assume it can be opened and walked through afterwards. Without this - // check, the line for that tile wouldn't render with collision detection - // because the collision check isn't done if collision data changes. - return true; - } - - boolean b1 = wa1.canTravelInDirection(client, -dy, -dx); - boolean b2 = wa2.canTravelInDirection(client, dy, dx); - return b1 && b2; - } - - private void findLinesInScene() - { - inDeadman = client.getWorldType().stream().anyMatch(x -> - x == WorldType.DEADMAN || x == WorldType.SEASONAL_DEADMAN); - inPvp = client.getWorldType().stream().anyMatch(x -> - x == WorldType.PVP || x == WorldType.PVP_HIGH_RISK); - - Rectangle sceneRect = new Rectangle( - client.getBaseX() + 1, client.getBaseY() + 1, - Constants.SCENE_SIZE - 2, Constants.SCENE_SIZE - 2); - - // Generate lines for multicombat zones - if (config.multicombatZoneVisibility() == ZoneVisibility.HIDE) - { - for (int i = 0; i < multicombatPathToDisplay.length; i++) - { - multicombatPathToDisplay[i] = null; - } - } - else - { - for (int i = 0; i < multicombatPathToDisplay.length; i++) - { - currentPlane = i; - - GeneralPath lines = new GeneralPath(MapLocations.getMulticombat(sceneRect, i)); - lines = Geometry.clipPath(lines, sceneRect); - if (config.multicombatZoneVisibility() == ZoneVisibility.SHOW_IN_PVP && - !isInDeadman() && !isInPvp()) - { - lines = Geometry.clipPath(lines, MapLocations.getRoughWilderness(i)); - } - lines = Geometry.splitIntoSegments(lines, 1); - if (config.collisionDetection()) - { - lines = Geometry.filterPath(lines, this::collisionFilter); - } - lines = Geometry.transformPath(lines, this::transformWorldToLocal); - multicombatPathToDisplay[i] = lines; - } - } - - // Generate safezone lines for deadman/pvp worlds - for (int i = 0; i < pvpPathToDisplay.length; i++) - { - currentPlane = i; - - GeneralPath safeZonePath = null; - if (config.showDeadmanSafeZones() && isInDeadman()) - { - safeZonePath = new GeneralPath(MapLocations.getDeadmanSafeZones(sceneRect, i)); - } - else if (config.showPvpSafeZones() && isInPvp()) - { - safeZonePath = new GeneralPath(MapLocations.getPvpSafeZones(sceneRect, i)); - } - if (safeZonePath != null) - { - safeZonePath = Geometry.clipPath(safeZonePath, sceneRect); - safeZonePath = Geometry.splitIntoSegments(safeZonePath, 1); - if (config.collisionDetection()) - { - safeZonePath = Geometry.filterPath(safeZonePath, this::collisionFilter); - } - safeZonePath = Geometry.transformPath(safeZonePath, this::transformWorldToLocal); - } - pvpPathToDisplay[i] = safeZonePath; - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getKey().equals("collisionDetection") || - event.getKey().equals("multicombatZoneVisibility") || - event.getKey().equals("deadmanSafeZones") || - event.getKey().equals("pvpSafeZones")) - { - findLinesInScene(); - } - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGGED_IN) - { - findLinesInScene(); - } - } -} From 6444b004e4cf850d0305c236ab4a528d314fc1b2 Mon Sep 17 00:00:00 2001 From: Kyleeld <48519776+Kyleeld@users.noreply.github.com> Date: Sat, 20 Apr 2019 23:36:25 +0100 Subject: [PATCH 21/21] Delete ZoneVisibility.java --- .../zoneIndicators/ZoneVisibility.java | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java deleted file mode 100644 index 9a457d9e50..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zoneIndicators/ZoneVisibility.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018, Woox - * 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.zoneIndicators; - -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public enum ZoneVisibility -{ - HIDE("Hide"), - SHOW_IN_PVP("Show in PvP"), - SHOW_EVERYWHERE("Show everywhere"); - - private final String visibility; - - @Override - public String toString() - { - return visibility; - } -} \ No newline at end of file