From 15ac022e59f5a13cd39e366181254b9918e104f7 Mon Sep 17 00:00:00 2001 From: Ganom Date: Fri, 26 Apr 2019 23:01:31 -0400 Subject: [PATCH 1/3] Updating raids plugin with lyzrds dc scouter, and adding pts/hr. --- .../client/plugins/raids/RaidsConfig.java | 10 ++ .../client/plugins/raids/RaidsPanel.java | 124 ++++++++++++++++++ .../client/plugins/raids/RaidsPlugin.java | 69 +++++++++- .../plugins/raids/RaidsPointsOverlay.java | 9 +- .../plugins/raids/instancereloadhelper.png | Bin 0 -> 65907 bytes 5 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/raids/instancereloadhelper.png diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java index c8bd785eac..527123889b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java @@ -178,6 +178,16 @@ public interface RaidsConfig extends Config return false; } + @ConfigItem( + position = 1, + keyName = "ptsHr", + name = "Enable points per hour message", + description = "Enable the message" + ) + default boolean ptsHr() + { + return true; + } @ConfigItem( position = 16, keyName = "showRecommendedItems", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java new file mode 100644 index 0000000000..bfedc4b4dd --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPanel.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2018, Lyzrds + * 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.raids; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.lang.reflect.Method; +import javax.inject.Inject; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.PluginPanel; + +public class RaidsPanel extends PluginPanel +{ + @Inject + private Client client; + @Inject + private RaidsPlugin raidsPlugin; + + @Inject + private ClientThread clientThread; + private JButton reloadButton = new JButton("Reload Instance"); + private JButton reloadScouter = new JButton("Reload Raid Overlay"); + private JLabel reloadMessage = new JLabel("

Instance Reload Helper

Reloading an instance will cause your client to disconnect temporarily.
"); + + void init(RaidsConfig config) + { + + // this may or may not qualify as a hack + // but this lets the editor pane expand to fill the whole parent panel + getParent().setLayout(new FlowLayout()); + getParent().add(this, BorderLayout.CENTER); + + setLayout(new BorderLayout()); + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + setBackground(ColorScheme.DARK_GRAY_COLOR); + + JPanel reloadContainer = new JPanel(); + JPanel scouterContainer = new JPanel(); + JPanel buttons = new JPanel(); + reloadContainer.setLayout(new BorderLayout()); + buttons.setLayout(new BorderLayout()); + buttons.setBackground(ColorScheme.DARKER_GRAY_COLOR); + reloadContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); + scouterContainer.setLayout(new BorderLayout()); + scouterContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + JPanel reloadFrame = new JPanel(); + JPanel scoutFrame = new JPanel(); + reloadButton.addActionListener((ActionEvent e) -> + { + + + if ((client.getGameState() == GameState.LOGGED_IN)) + { + + try + { + //look for client.gameStateChanged(-1); in src files to find + Method m = client.getClass().getClassLoader().loadClass("jr").getDeclaredMethod("fn", int.class, int.class); + m.setAccessible(true); + m.invoke(null, 40, -1893789506); + + //Method m = client.getClass().getClassLoader().loadClass("jr").getDeclaredMethod("fn", int.class, int.class); + //m.setAccessible(true); + //m.invoke(null, 40, -1893789506); + //TODO: Since this is mainly for raids i'd like to reload the raids scouting plugin after the dc is finished + + } + catch (ReflectiveOperationException f) + { + throw new RuntimeException(f); + } + } + else + { + //TODO: User is still in a dc, or not logged in. Possibly provide a meaningful message somewhere. + } + }); + reloadScouter.addActionListener((ActionEvent e) -> + { + if ((client.getGameState() == GameState.LOGGED_IN)) + { + raidsPlugin.checkRaidPresence(true); + } + }); + + reloadFrame.add(reloadButton); + scoutFrame.add(reloadScouter); + reloadContainer.add(reloadFrame, BorderLayout.NORTH); + reloadContainer.add(scoutFrame, BorderLayout.SOUTH); + add(reloadMessage, BorderLayout.PAGE_START); + add(reloadContainer, BorderLayout.CENTER); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 79c4055264..5729d20cd6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -79,13 +79,16 @@ import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.raids.solver.Layout; import net.runelite.client.plugins.raids.solver.LayoutSolver; import net.runelite.client.plugins.raids.solver.RotationSolver; +import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.DrawManager; import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.WidgetOverlay; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.ui.overlay.tooltip.Tooltip; import net.runelite.client.ui.overlay.tooltip.TooltipManager; +import net.runelite.client.util.ImageUtil; import net.runelite.client.util.Text; import net.runelite.client.util.HotkeyListener; import org.apache.commons.lang3.StringUtils; @@ -174,12 +177,17 @@ public class RaidsPlugin extends Plugin @Getter private boolean inRaidChambers; + @Inject + private ClientToolbar clientToolbar; + private RaidsPanel panel; private int upperTime = -1; private int middleTime = -1; private int lowerTime = -1; private int raidTime = -1; private WidgetOverlay widgetOverlay; private String tooltip; + public boolean canShow; + private NavigationButton navButton; @Provides RaidsConfig provideConfig(ConfigManager configManager) @@ -201,6 +209,16 @@ public class RaidsPlugin extends Plugin updateLists(); clientThread.invokeLater(() -> checkRaidPresence(true)); widgetOverlay = overlayManager.getWidgetOverlay(WidgetInfo.RAIDS_POINTS_INFOBOX); + panel = injector.getInstance(RaidsPanel.class); + panel.init(config); + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "instancereloadhelper.png"); + navButton = NavigationButton.builder() + .tooltip("Raids Reload") + .icon(icon) + .priority(8) + .panel(panel) + .build(); + clientToolbar.addNavigation(navButton); } @Override @@ -208,6 +226,7 @@ public class RaidsPlugin extends Plugin { overlayManager.remove(overlay); overlayManager.remove(pointsOverlay); + clientToolbar.removeNavigation(navButton); inRaidChambers = false; widgetOverlay = null; raid = null; @@ -286,12 +305,14 @@ public class RaidsPlugin extends Plugin if (matcher.find()) { raidTime = timeToSeconds(matcher.group(1)); + int timesec = timeToSeconds(matcher.group(1)); updateTooltip(); if (config.pointsMessage()) { int totalPoints = client.getVar(Varbits.TOTAL_POINTS); int personalPoints = client.getVar(Varbits.PERSONAL_POINTS); + int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); double percentage = personalPoints / (totalPoints / 100.0); @@ -316,6 +337,52 @@ public class RaidsPlugin extends Plugin .type(ChatMessageType.FRIENDSCHATNOTIFICATION) .runeLiteFormattedMessage(chatMessage) .build()); + if (config.ptsHr()) + { + String ptssolo; + { + ptssolo = POINTS_FORMAT.format(((float) personalPoints / (float) timesec) * 3600); + } + + String ptsteam; + { + ptsteam = POINTS_FORMAT.format(((float) totalPoints / (float) timesec) * 3600); + } + + String ptssplit; + { + ptssplit = POINTS_FORMAT.format(((float) (totalPoints / (float) timesec) * 3600) / (partySize)); + } + + + String chatMessage2 = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Solo Pts/Hr: ") + .append(ChatColorType.HIGHLIGHT) + .append(ptssolo) + .append(ChatColorType.NORMAL) + .append("Team Pts/Hr: ") + .append(ChatColorType.HIGHLIGHT) + .append(ptsteam) + .build(); + + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.FRIENDSCHATNOTIFICATION) + .runeLiteFormattedMessage(chatMessage2) + .build()); + + String chatMessage3 = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Split Pts/Hr: ") + .append(ChatColorType.HIGHLIGHT) + .append(ptssplit) + .build(); + + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.FRIENDSCHATNOTIFICATION) + .runeLiteFormattedMessage(chatMessage3) + .build()); + } } } } @@ -338,7 +405,7 @@ public class RaidsPlugin extends Plugin } } - private void checkRaidPresence(boolean force) + public void checkRaidPresence(boolean force) { if (client.getGameState() != GameState.LOGGED_IN) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java index 3c2cc3e5f1..5e4c98f4c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPointsOverlay.java @@ -104,16 +104,17 @@ public class RaidsPointsOverlay extends Overlay .left("Unique:") .right(UNIQUE_FORMAT.format(uniqueChance)) .build()); - + //TODO this is annoyingly bugged, personalpoints returns null for some reason +/* if (partySize > 1) { - double personalChance = uniqueChance * (personalPoints / totalPoints); + double personalChance = uniqueChance * (double)(personalPoints / totalPoints); - panel.getChildren().add(LineComponent.builder() + panel.getChildren().add(LineComponent.builder() .left("Personal:") .right(UNIQUE_FORMAT.format(personalChance)) .build()); - } + }*/ return panel.render(graphics); } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/raids/instancereloadhelper.png b/runelite-client/src/main/resources/net/runelite/client/plugins/raids/instancereloadhelper.png new file mode 100644 index 0000000000000000000000000000000000000000..13109b4b2650546acc872b1dc738816180e2e723 GIT binary patch literal 65907 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%0AK6;bSIv?H2gyklyr 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 literal 0 HcmV?d00001 From 484efbcbc3020cd0f1565763d4583d753c45988b Mon Sep 17 00:00:00 2001 From: Ganom Date: Fri, 26 Apr 2019 23:02:12 -0400 Subject: [PATCH 2/3] Removing lyzrd scouter in favor of updated one --- .../client/plugins/newraids/PointsPanel.java | 502 --------- .../client/plugins/newraids/Raid.java | 182 ---- .../client/plugins/newraids/RaidRoom.java | 161 --- .../client/plugins/newraids/RaidsConfig.java | 209 ---- .../client/plugins/newraids/RaidsOverlay.java | 162 --- .../client/plugins/newraids/RaidsPanel.java | 127 --- .../client/plugins/newraids/RaidsPlugin.java | 958 ------------------ .../plugins/newraids/RaidsPointsOverlay.java | 87 -- .../client/plugins/newraids/RaidsTimer.java | 159 --- .../client/plugins/newraids/SoloBox.java | 209 ---- .../client/plugins/newraids/XpInfoBox.java | 210 ---- .../client/plugins/newraids/data.java | 29 - .../plugins/newraids/solver/Layout.java | 71 -- .../plugins/newraids/solver/LayoutSolver.java | 226 ----- .../client/plugins/newraids/solver/Room.java | 51 - .../newraids/solver/RotationSolver.java | 150 --- .../client/plugins/newraids/timerSpecial.java | 63 -- 17 files changed, 3556 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/PointsPanel.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/Raid.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidRoom.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsConfig.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsOverlay.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPanel.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPlugin.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPointsOverlay.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsTimer.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/SoloBox.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/XpInfoBox.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/data.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Layout.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/LayoutSolver.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Room.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/RotationSolver.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/newraids/timerSpecial.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/PointsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/PointsPanel.java deleted file mode 100644 index 0adacc78f2..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/PointsPanel.java +++ /dev/null @@ -1,502 +0,0 @@ -package net.runelite.client.plugins.newraids; - -import com.google.inject.Provides; -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import javax.inject.Inject; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.SwingUtilities; -import javax.swing.border.EmptyBorder; -import net.runelite.api.Client; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.util.ImageUtil; - -public class PointsPanel extends PluginPanel -{ - - static final JPanel infoBoxPanel = new JPanel(); - public static ArrayList raids = new ArrayList(); - @Inject - private static RaidsPlugin raidsPlugin; - @Inject - private static Client client; - @Inject - private static SkillIconManager iconManager; - final JMenuItem pausePopup = new JMenuItem("Pause Timer"); - final JButton pauseButton = new JButton("Pause Timer"); - final JPanel overallInfo = new JPanel(); - private final Map infoBoxes = new HashMap<>(); - private final JLabel overallPointsGained = new JLabel(XpInfoBox.htmlLabel("Personal Points: ", 0)); - private final JLabel overallPointsPerHour = new JLabel(XpInfoBox.htmlLabel("Per Hour: ", 0)); - private final JLabel teamPointsGained = new JLabel(XpInfoBox.htmlLabel("Team Points: ", 0)); - private final JLabel teamPointsPerHour = new JLabel(XpInfoBox.htmlLabel("Per Hour: ", 0)); - private final JLabel raidsCompleted = new JLabel(XpInfoBox.htmlLabel("Raids Done: ", 0)); - private final JLabel averageTime = new JLabel(XpInfoBox.htmlLabel("Avg. Raid Time: ", "00:00:00")); - private final JLabel averagePoints = new JLabel(XpInfoBox.htmlLabel("Avg. Points: ", 0)); - private final JLabel averagePointsTeam = new JLabel(XpInfoBox.htmlLabel("Avg. Points: ", 0)); - private final JLabel elapsedTime = new JLabel(XpInfoBox.htmlLabel("Elapsed Time: ", "00:00:00")); - private final JLabel blankline1 = new JLabel("
"); - private final JLabel blankline = new JLabel("
"); - private final JLabel blankline2 = new JLabel("
"); - private final JPanel overallPanel = new JPanel(); - public Date finalTime = new Date(); - public Date tempTime = new Date(); - public boolean paused = false; - public boolean soloMode; - timerSpecial timer = new timerSpecial(); - ActionListener action = new ActionListener() - { - @Override - public void actionPerformed(ActionEvent event) - { - updateTime(); - } - }; - @Inject - private RaidsConfig raidsConfig; - - PointsPanel(RaidsPlugin raidsPlugin, RaidsConfig raidsConfig, Client client, SkillIconManager iconManager) - { - - super(); - setBorder(new EmptyBorder(6, 6, 6, 6)); - setBackground(ColorScheme.DARK_GRAY_COLOR); - setLayout(new BorderLayout()); - - final JPanel layoutPanel = new JPanel(); - BoxLayout boxLayout = new BoxLayout(layoutPanel, BoxLayout.Y_AXIS); - layoutPanel.setLayout(boxLayout); - add(layoutPanel, BorderLayout.NORTH); - - overallPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); - overallPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - overallPanel.setLayout(new BorderLayout()); - overallPanel.setVisible(true); // this will only become visible when the player gets exp - - // Create reset all menu - final JMenuItem reset = new JMenuItem("Reset Tracker"); - reset.addActionListener(e -> resetAll(true)); - - pausePopup.addActionListener(e -> pauseTime()); - pauseButton.addActionListener(e -> pauseTime()); - - - // Create popup menu - final JPopupMenu popupMenu = new JPopupMenu(); - popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); - popupMenu.add(reset); - popupMenu.add(pausePopup); - overallPanel.setComponentPopupMenu(popupMenu); - final BufferedImage image = ImageUtil.getResourceStreamFromClass(this.getClass(), "cox.png"); - ImageIcon i = new ImageIcon(image); - final JLabel overallIcon = new JLabel(i); - - - overallInfo.setBackground(ColorScheme.DARKER_GRAY_COLOR); - overallInfo.setLayout(new GridLayout(12, 1)); - overallInfo.setBorder(new EmptyBorder(0, 10, 0, 0)); - pauseButton.setFont(FontManager.getRunescapeSmallFont()); - overallInfo.add(pauseButton); - overallPointsGained.setFont(FontManager.getRunescapeSmallFont()); - overallPointsPerHour.setFont(FontManager.getRunescapeSmallFont()); - teamPointsGained.setFont(FontManager.getRunescapeSmallFont()); - raidsCompleted.setFont(FontManager.getRunescapeSmallFont()); - averagePoints.setFont(FontManager.getRunescapeSmallFont()); - averageTime.setFont(FontManager.getRunescapeSmallFont()); - teamPointsPerHour.setFont(FontManager.getRunescapeSmallFont()); - blankline1.setFont(FontManager.getRunescapeSmallFont()); - blankline.setFont(FontManager.getRunescapeSmallFont()); - blankline2.setFont(FontManager.getRunescapeSmallFont()); - averagePointsTeam.setFont(FontManager.getRunescapeSmallFont()); - elapsedTime.setFont(FontManager.getRunescapeSmallFont()); - overallInfo.add(teamPointsGained); - overallInfo.add(teamPointsPerHour); - overallInfo.add(averagePointsTeam); - - overallInfo.add(blankline1); - overallInfo.add(overallPointsGained); - - overallInfo.add(overallPointsPerHour); - - overallInfo.add(averagePoints); - overallInfo.add(blankline2); - overallInfo.add(raidsCompleted); - - overallInfo.add(averageTime); - overallInfo.add(elapsedTime); - - overallPanel.add(overallIcon, BorderLayout.WEST); - overallPanel.add(overallInfo, BorderLayout.CENTER); - - - infoBoxPanel.setLayout(new BoxLayout(infoBoxPanel, BoxLayout.Y_AXIS)); - layoutPanel.add(overallPanel); - layoutPanel.add(infoBoxPanel); - - try - { - for (data d : raids) - { - infoBoxPanel.add(new XpInfoBox(raidsPlugin, raidsConfig, client, infoBoxPanel, d, iconManager)); - } - } - catch (IOException e) - { - - } - - - } - - /* - for(data d : raids){ - try { - infoBoxPanel.add(new XpInfoBox(raidsPlugin, raidsConfig, client, infoBoxPanel, Skill.AGILITY, iconManager)); - } catch (IOException e) { - e.printStackTrace(); - } - } - */ - public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) - { - long diffInMillies = date2.getTime() - date1.getTime(); - return timeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS); - } - - public static String formatSeconds(int timeInSeconds) - { - int hours = timeInSeconds / 3600; - int secondsLeft = timeInSeconds - hours * 3600; - int minutes = secondsLeft / 60; - int seconds = secondsLeft - minutes * 60; - - String formattedTime = ""; - if (hours < 10) - { - formattedTime += "0"; - } - formattedTime += hours + ":"; - - if (minutes < 10) - { - formattedTime += "0"; - } - formattedTime += minutes + ":"; - - if (seconds < 10) - { - formattedTime += "0"; - } - formattedTime += seconds; - - return formattedTime; - } - - @Provides - RaidsConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(RaidsConfig.class); - } - - XpInfoBox test(data d) - { - try - { - XpInfoBox x; - x = new XpInfoBox(raidsPlugin, raidsConfig, client, infoBoxPanel, d, iconManager); - return x; - } - catch (IOException e) - { - e.printStackTrace(); - } - return null; - } - - SoloBox testS(data d) - { - try - { - SoloBox x; - x = new SoloBox(raidsPlugin, raidsConfig, client, infoBoxPanel, d, iconManager); - return x; - } - catch (IOException e) - { - e.printStackTrace(); - } - return null; - } - - void init() - { - - } - - void update() - { - int totalPoints = 0; - int totalTeamPoints = 0; - float teamperhour = 0; - infoBoxPanel.removeAll(); - Date startTime = null; - Date finishTime = null; - int totalTime = 0; - float difference = 0; - int raidsDone = 0; - for (data d : raids) - { - SwingUtilities.invokeLater(() -> infoBoxPanel.add(test(d))); - totalPoints = totalPoints + d.personal; - totalTeamPoints = totalTeamPoints + d.total; - raidsDone++; - totalTime = totalTime + d.timeTaken; - } - if (timer.getElapsedTime() > 0) - { - difference = timer.getElapsedTime(); - teamperhour = (totalTeamPoints / difference) * 3600; - difference = (totalPoints / difference) * 3600; - } - - overallInfo.removeAll(); - overallInfo.setLayout(new GridLayout(12, 1)); - teamPointsPerHour.setVisible(true); - teamPointsGained.setVisible(true); - overallInfo.add(pauseButton); - overallInfo.add(teamPointsGained); - overallInfo.add(teamPointsPerHour); - overallInfo.add(averagePointsTeam); - - overallInfo.add(blankline1); - overallInfo.add(overallPointsGained); - - overallInfo.add(overallPointsPerHour); - - overallInfo.add(averagePoints); - overallInfo.add(blankline2); - overallInfo.add(raidsCompleted); - - overallInfo.add(averageTime); - overallInfo.add(elapsedTime); - overallPointsGained.setText(XpInfoBox.htmlLabel("Personal Points: ", totalPoints)); - overallPointsPerHour.setText(XpInfoBox.htmlLabel("Per Hour: ", (int) difference)); - teamPointsGained.setText(XpInfoBox.htmlLabel("Team Points: ", totalTeamPoints)); - teamPointsPerHour.setText(XpInfoBox.htmlLabel("Per Hour: ", (int) teamperhour)); - - raidsCompleted.setText(XpInfoBox.htmlLabel("Raids Done: ", raidsDone)); - if (raidsDone > 0) - { - elapsedTime.setText(XpInfoBox.htmlLabel("Elapsed Time: ", formatSeconds((int) timer.getElapsedTime()))); - averageTime.setText(XpInfoBox.htmlLabel("Avg. Raid Time: ", formatSeconds(totalTime / raidsDone))); - averagePoints.setText(XpInfoBox.htmlLabel("Avg. Points: ", totalPoints / raidsDone)); - averagePointsTeam.setText(XpInfoBox.htmlLabel("Avg. Points: ", totalTeamPoints / raidsDone)); - } - else - { - elapsedTime.setText(XpInfoBox.htmlLabel("Elapsed Time: ", "00:00:00")); - averageTime.setText(XpInfoBox.htmlLabel("Avg. Raid Time: ", "00:00:00")); - averagePoints.setText(XpInfoBox.htmlLabel("Avg. Points: ", 0)); - averagePointsTeam.setText(XpInfoBox.htmlLabel("Avg. Points: ", 0)); - } - - - infoBoxPanel.revalidate(); - } - - void updateSolo() - { - int totalPoints = 0; - int totalTeamPoints = 0; - float teamperhour = 0; - infoBoxPanel.removeAll(); - Date startTime = null; - Date finishTime = null; - int totalTime = 0; - float difference = 0; - int raidsDone = 0; - if (raids.size() > 0) - { - startTime = raids.get(0).start; - finishTime = raids.get(raids.size() - 1).finish; - difference = getDateDiff(startTime, finishTime, TimeUnit.SECONDS); - } - for (data d : raids) - { - SwingUtilities.invokeLater(() -> infoBoxPanel.add(testS(d))); - totalPoints = totalPoints + d.personal; - totalTeamPoints = totalTeamPoints + d.total; - raidsDone++; - totalTime = totalTime + d.timeTaken; - } - - if (timer.getElapsedTime() > 0) - { - difference = timer.getElapsedTime(); - teamperhour = (totalTeamPoints / difference) * 3600; - difference = (totalPoints / difference) * 3600; - } - overallInfo.removeAll(); - overallInfo.setLayout(new GridLayout(7, 1)); - overallInfo.add(pauseButton); - overallInfo.add(overallPointsGained); - overallInfo.add(overallPointsPerHour); - overallInfo.add(blankline); - overallInfo.add(raidsCompleted); - overallInfo.add(averageTime); - overallInfo.add(elapsedTime); - overallPointsGained.setText(XpInfoBox.htmlLabel("Personal Points: ", totalPoints)); - overallPointsPerHour.setText(XpInfoBox.htmlLabel("Per Hour: ", (int) difference)); - teamPointsGained.setText(XpInfoBox.htmlLabel("Team Points: ", totalTeamPoints)); - teamPointsPerHour.setText(XpInfoBox.htmlLabel("Per Hour: ", (int) teamperhour)); - - raidsCompleted.setText(XpInfoBox.htmlLabel("Raids Done: ", raidsDone)); - if (raidsDone > 0) - { - elapsedTime.setText(XpInfoBox.htmlLabel("Elapsed Time: ", formatSeconds((int) timer.getElapsedTime()))); - averageTime.setText(XpInfoBox.htmlLabel("Avg. Raid Time: ", formatSeconds(totalTime / raidsDone))); - averagePoints.setText(XpInfoBox.htmlLabel("Avg. Points: ", totalPoints / raidsDone)); - averagePointsTeam.setText(XpInfoBox.htmlLabel("Avg. Points: ", totalTeamPoints / raidsDone)); - } - else - { - elapsedTime.setText(XpInfoBox.htmlLabel("Elapsed Time: ", "00:00:00")); - averageTime.setText(XpInfoBox.htmlLabel("Avg. Raid Time: ", "00:00:00")); - averagePoints.setText(XpInfoBox.htmlLabel("Avg. Points: ", 0)); - averagePointsTeam.setText(XpInfoBox.htmlLabel("Avg. Points: ", 0)); - } - teamPointsPerHour.setVisible(false); - teamPointsGained.setVisible(false); - infoBoxPanel.revalidate(); - } - - void unpauseTime() - { - if (!timer.started) - { - return; - } - timer.unpause(); - pausePopup.setText("Pause Timer"); - pauseButton.setText("Pause Timer"); - for (ActionListener d : pausePopup.getActionListeners()) - { - pausePopup.removeActionListener(d); - } - for (ActionListener d : pauseButton.getActionListeners()) - { - pauseButton.removeActionListener(d); - } - pausePopup.addActionListener(e -> pauseTime()); - pauseButton.addActionListener(e -> pauseTime()); - } - - public void updateTime() - { - finalTime = new Date(); - int totalPoints = 0; - int totalTeamPoints = 0; - int raidsDone = 0; - int totalTime = 0; - if (raids.size() > 0) - { - int difference; - int teamperhour; - for (data d : raids) - { - totalPoints = totalPoints + d.personal; - totalTeamPoints = totalTeamPoints + d.total; - raidsDone++; - totalTime = totalTime + d.timeTaken; - } - if (timer.getElapsedTime() > 0) - { - difference = (int) timer.getElapsedTime(); - teamperhour = (int) ((totalTeamPoints / (float) difference) * 3600); - difference = (int) ((totalPoints / (float) difference) * 3600); - overallPointsGained.setText(XpInfoBox.htmlLabel("Personal Points: ", totalPoints)); - overallPointsPerHour.setText(XpInfoBox.htmlLabel("Per Hour: ", difference)); - teamPointsGained.setText(XpInfoBox.htmlLabel("Team Points: ", totalTeamPoints)); - teamPointsPerHour.setText(XpInfoBox.htmlLabel("Per Hour: ", teamperhour)); - } - - elapsedTime.setText(XpInfoBox.htmlLabel("Elapsed Time: ", formatSeconds((int) timer.getElapsedTime()))); - revalidate(); - } - - } - - void pauseTime() - { - - if (!timer.started) - { - return; - } - timer.pause(); - pausePopup.setText("Resume Timer"); - pauseButton.setText("Resume Timer"); - for (ActionListener d : pausePopup.getActionListeners()) - { - pausePopup.removeActionListener(d); - } - for (ActionListener d : pauseButton.getActionListeners()) - { - pauseButton.removeActionListener(d); - } - pausePopup.addActionListener(e -> unpauseTime()); - pauseButton.addActionListener(e -> unpauseTime()); - } - - void resetAll(boolean solo) - { - timer = new timerSpecial(); - pausePopup.setText("Pause Timer"); - pauseButton.setText("Pause Timer"); - for (ActionListener d : pausePopup.getActionListeners()) - { - pausePopup.removeActionListener(d); - } - for (ActionListener d : pauseButton.getActionListeners()) - { - pauseButton.removeActionListener(d); - } - pausePopup.addActionListener(e -> pauseTime()); - pauseButton.addActionListener(e -> pauseTime()); - raids.clear(); - if (soloMode) - { - updateSolo(); - } - else - { - update(); - } - - } - - void setSolo(boolean solo) - { - soloMode = solo; - } - -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/Raid.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/Raid.java deleted file mode 100644 index cf644f0bc1..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/Raid.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids; - -import com.google.common.base.Joiner; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import lombok.Getter; -import net.runelite.client.plugins.newraids.solver.Layout; -import net.runelite.client.plugins.newraids.solver.Room; - -public class Raid -{ - @Getter - private final RaidRoom[] rooms = new RaidRoom[16]; - - @Getter - private Layout layout; - - public void updateLayout(Layout layout) - { - if (layout == null) - { - return; - } - - this.layout = layout; - - for (int i = 0; i < rooms.length; i++) - { - if (layout.getRoomAt(i) == null) - { - continue; - } - - RaidRoom room = rooms[i]; - - if (room == null) - { - RaidRoom.Type type = RaidRoom.Type.fromCode(layout.getRoomAt(i).getSymbol()); - room = new RaidRoom(null, type); - - if (type == RaidRoom.Type.COMBAT) - { - room.setBoss(RaidRoom.Boss.UNKNOWN); - } - - if (type == RaidRoom.Type.PUZZLE) - { - room.setPuzzle(RaidRoom.Puzzle.UNKNOWN); - } - - setRoom(room, i); - } - } - } - - public RaidRoom getRoom(int position) - { - return rooms[position]; - } - - public void setRoom(RaidRoom room, int position) - { - if (position < rooms.length) - { - rooms[position] = room; - } - } - - public RaidRoom[] getCombatRooms() - { - List combatRooms = new ArrayList<>(); - - for (Room room : layout.getRooms()) - { - if (room == null) - { - continue; - } - - if (rooms[room.getPosition()].getType() == RaidRoom.Type.COMBAT) - { - combatRooms.add(rooms[room.getPosition()]); - } - } - - return combatRooms.toArray(new RaidRoom[combatRooms.size()]); - } - - public String getRotationString() - { - return Joiner.on(",").join(Arrays.stream(getCombatRooms()).map(r -> r.getBoss().getName()).toArray()); - } - - public String toCode() - { - StringBuilder builder = new StringBuilder(); - - for (RaidRoom room : rooms) - { - if (room != null) - { - builder.append(room.getType().getCode()); - } - else - { - builder.append(" "); - } - } - - return builder.toString(); - } - - public String toRoomString() - { - final StringBuilder sb = new StringBuilder(); - - for (Room r : getLayout().getRooms()) - { - final int position = r.getPosition(); - final RaidRoom room = getRoom(position); - - if (room == null || !(room.getType() == RaidRoom.Type.COMBAT || room.getType() == RaidRoom.Type.PUZZLE)) - { - continue; - } - - switch (room.getType()) - { - case PUZZLE: - final RaidRoom.Puzzle puzzle = room.getPuzzle(); - sb.append(puzzle.getName()); - - if (puzzle == RaidRoom.Puzzle.UNKNOWN) - { - sb.append(" (puzzle)"); - } - - sb.append(", "); - break; - case COMBAT: - final RaidRoom.Boss boss = room.getBoss(); - sb.append(boss.getName()); - - if (boss == RaidRoom.Boss.UNKNOWN) - { - sb.append(" (combat)"); - } - - sb.append(", "); - break; - } - } - - final String roomsString = sb.toString(); - return roomsString.substring(0, roomsString.length() - 2); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidRoom.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidRoom.java deleted file mode 100644 index 37367f7e8f..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidRoom.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import net.runelite.api.Tile; - -public class RaidRoom -{ - public static final int ROOM_MAX_SIZE = 32; - @Getter - private final Tile base; - @Getter - @Setter - private Type type; - @Getter - @Setter - private Boss boss; - @Getter - @Setter - private Puzzle puzzle; - @Getter - @Setter - private RaidRoom previousRoom; - @Getter - @Setter - private RaidRoom nextRoom; - - public RaidRoom(Tile base, Type type) - { - this.base = base; - this.type = type; - } - - @Override - public String toString() - { - switch (type) - { - case COMBAT: - return "RaidRoom (type: " + type.getName() + ", " + boss.getName() + ")"; - - case PUZZLE: - return "RaidRoom (type: " + type.getName() + ", " + puzzle.getName() + ")"; - - default: - return "RaidRoom (type: " + type.getName() + ")"; - } - } - - @AllArgsConstructor - public enum Type - { - START("Start", "#"), - END("End", "¤"), - SCAVENGERS("Scavengers", "S"), - FARMING("Farming", "F"), - COMBAT("Combat", "C"), - PUZZLE("Puzzle", "P"), - EMPTY("Empty", " "); - - @Getter - private final String name; - - @Getter - private final String code; - - public static Type fromCode(char code) - { - for (Type type : Type.values()) - { - if (type.getCode().equalsIgnoreCase(String.valueOf(code))) - { - return type; - } - } - - return Type.EMPTY; - } - } - - @AllArgsConstructor - public enum Boss - { - TEKTON("Tekton"), - MUTTADILES("Muttadiles"), - GUARDIANS("Guardians"), - VESPULA("Vespula"), - SHAMANS("Shamans"), - VASA("Vasa"), - VANGUARDS("Vanguards"), - MYSTICS("Mystics"), - UNKNOWN("Unknown"); - - @Getter - private final String name; - - public static Boss fromString(String name) - { - for (Boss boss : Boss.values()) - { - if (boss.getName().equalsIgnoreCase(name)) - { - return boss; - } - } - - return null; - } - } - - @AllArgsConstructor - public enum Puzzle - { - CRABS("Crabs"), - ICE_DEMON("Ice Demon"), - TIGHTROPE("Tightrope"), - THIEVING("Thieving"), - UNKNOWN("Unknown"); - - @Getter - private final String name; - - public static Puzzle fromString(String name) - { - for (Puzzle puzzle : Puzzle.values()) - { - if (puzzle.getName().equalsIgnoreCase(name)) - { - return puzzle; - } - } - - return null; - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsConfig.java deleted file mode 100644 index 57d1e648f3..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsConfig.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids; - -import net.runelite.client.config.Config; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigItem; - -@ConfigGroup("raids") -public interface RaidsConfig extends Config -{ - @ConfigItem( - position = 0, - keyName = "raidsTimer", - name = "Display elapsed raid time", - description = "Display elapsed raid time" - ) - default boolean raidsTimer() - { - return true; - } - - @ConfigItem( - position = 1, - keyName = "pointsMessage", - name = "Display points in chatbox after raid", - description = "Display a message with total points, individual points and percentage at the end of a raid" - ) - default boolean pointsMessage() - { - return true; - } - - @ConfigItem( - position = 2, - keyName = "scoutOverlay", - name = "Show scout overlay", - description = "Display an overlay that shows the current raid layout (when entering lobby)" - ) - default boolean scoutOverlay() - { - return true; - } - - @ConfigItem( - position = 3, - keyName = "scoutOverlayAtBank", - name = "Show scout overlay outside lobby", - description = "Keep the overlay active while at the raids area" - ) - default boolean scoutOverlayAtBank() - { - return true; - } - - @ConfigItem( - position = 4, - keyName = "scoutOverlayInRaid", - name = "Show scout overlay inside raid", - description = "Keep the overlay active while inside raid" - ) - default boolean scoutOverlayInRaid() - { - return false; - } - - @ConfigItem( - position = 5, - keyName = "whitelistedRooms", - name = "Whitelisted rooms", - description = "Display whitelisted rooms in green on the overlay. Separate with comma (full name)" - ) - default String whitelistedRooms() - { - return ""; - } - - @ConfigItem( - position = 6, - keyName = "blacklistedRooms", - name = "Blacklisted rooms", - description = "Display blacklisted rooms in red on the overlay. Separate with comma (full name)" - ) - default String blacklistedRooms() - { - return ""; - } - - @ConfigItem( - position = 7, - keyName = "enableRotationWhitelist", - name = "Enable rotation whitelist", - description = "Enable the rotation whitelist" - ) - default boolean enableRotationWhitelist() - { - return false; - } - - @ConfigItem( - position = 8, - keyName = "whitelistedRotations", - name = "Whitelisted rotations", - description = "Warn when boss rotation doesn't match a whitelisted one. Add rotations like [tekton, muttadile, guardians]" - ) - default String whitelistedRotations() - { - return ""; - } - - @ConfigItem( - position = 9, - keyName = "enableLayoutWhitelist", - name = "Enable layout whitelist", - description = "Enable the layout whitelist" - ) - default boolean enableLayoutWhitelist() - { - return false; - } - - @ConfigItem( - position = 10, - keyName = "whitelistedLayouts", - name = "Whitelisted layouts", - description = "Warn when layout doesn't match a whitelisted one. Add layouts like CFSCPPCSCF separated with comma" - ) - default String whitelistedLayouts() - { - return ""; - } - - @ConfigItem( - position = 12, - keyName = "ptsHr", - name = "Enable points per hour message", - description = "Enable the message" - ) - default boolean ptsHr() - { - return true; - } - - @ConfigItem( - position = 11, - keyName = "layoutMessage", - name = "Send raid layout message when entering raid", - description = "Sends game message with raid layout on entering new raid" - ) - default boolean layoutMessage() - { - return true; - } - - @ConfigItem( - position = 13, - keyName = "ptsPanelUpdate", - name = "Enable points panel", - description = "Enable the panel" - ) - default boolean ptsPanel() - { - return true; - } - - @ConfigItem( - position = 14, - keyName = "soloPanel", - name = "Solo Points Only", - description = "Display Only Solo Points Info" - ) - default boolean soloPanel() - { - return false; - } - - @ConfigItem( - position = 15, - keyName = "oldOverlay", - name = "Old Points Overlay", - description = "Use the old points overlay" - ) - default boolean oldOverlay() - { - return false; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsOverlay.java deleted file mode 100644 index 9a02e5723c..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsOverlay.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; -import lombok.Setter; -import net.runelite.api.Client; -import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; -import net.runelite.client.plugins.newraids.solver.Room; -import net.runelite.client.ui.overlay.Overlay; -import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; -import net.runelite.client.ui.overlay.OverlayMenuEntry; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; -import net.runelite.client.ui.overlay.components.TitleComponent; - -public class RaidsOverlay extends Overlay -{ - private static final int OLM_PLANE = 0; - private final PanelComponent panelComponent = new PanelComponent(); - private Client client; - private RaidsPlugin plugin; - private RaidsConfig config; - @Setter - private boolean scoutOverlayShown = false; - - @Inject - private RaidsOverlay(Client client, RaidsPlugin plugin, RaidsConfig config) - { - super(plugin); - setPosition(OverlayPosition.TOP_LEFT); - setPriority(OverlayPriority.LOW); - this.client = client; - this.plugin = plugin; - this.config = config; - getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Raids overlay")); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!config.scoutOverlay() || !scoutOverlayShown || plugin.isInRaidChambers() && client.getPlane() == OLM_PLANE) - { - return null; - } - - panelComponent.getChildren().clear(); - - if (plugin.getRaid() == null || plugin.getRaid().getLayout() == null) - { - panelComponent.getChildren().add(TitleComponent.builder() - .text("Unable to scout this raid!") - .color(Color.RED) - .build()); - - return panelComponent.render(graphics); - } - - Color color = Color.WHITE; - String layout = plugin.getRaid().getLayout().toCodeString(); - - if (config.enableLayoutWhitelist() && !plugin.getLayoutWhitelist().contains(layout.toLowerCase())) - { - color = Color.RED; - } - - panelComponent.getChildren().add(TitleComponent.builder() - .text(layout) - .color(color) - .build()); - - int bossMatches = 0; - int bossCount = 0; - - if (config.enableRotationWhitelist()) - { - bossMatches = plugin.getRotationMatches(); - } - - for (Room layoutRoom : plugin.getRaid().getLayout().getRooms()) - { - int position = layoutRoom.getPosition(); - RaidRoom room = plugin.getRaid().getRoom(position); - - if (room == null) - { - continue; - } - - color = Color.WHITE; - - switch (room.getType()) - { - case COMBAT: - bossCount++; - if (plugin.getRoomWhitelist().contains(room.getBoss().getName().toLowerCase())) - { - color = Color.GREEN; - } - else if (plugin.getRoomBlacklist().contains(room.getBoss().getName().toLowerCase()) - || config.enableRotationWhitelist() && bossCount > bossMatches) - { - color = Color.RED; - } - - panelComponent.getChildren().add(LineComponent.builder() - .left(room.getType().getName()) - .right(room.getBoss().getName()) - .rightColor(color) - .build()); - - break; - - case PUZZLE: - if (plugin.getRoomWhitelist().contains(room.getPuzzle().getName().toLowerCase())) - { - color = Color.GREEN; - } - else if (plugin.getRoomBlacklist().contains(room.getPuzzle().getName().toLowerCase())) - { - color = Color.RED; - } - - panelComponent.getChildren().add(LineComponent.builder() - .left(room.getType().getName()) - .right(room.getPuzzle().getName()) - .rightColor(color) - .build()); - break; - } - } - - return panelComponent.render(graphics); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPanel.java deleted file mode 100644 index 0671a1f1d0..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPanel.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2018, Lyzrds - * 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.newraids; - -import java.awt.BorderLayout; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.lang.reflect.Method; -import javax.inject.Inject; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.PluginPanel; - -public class RaidsPanel extends PluginPanel -{ - @Inject - private Client client; - @Inject - private RaidsPlugin raidsPlugin; - - @Inject - private ClientThread clientThread; - private JButton reloadButton = new JButton("Reload Instance"); - private JButton reloadScouter = new JButton("Reload Raid Overlay"); - private JLabel reloadMessage = new JLabel("

Instance Reload Helper

Reloading an instance will cause your client to disconnect temporarily.
"); - - void init(RaidsConfig config) - { - - // this may or may not qualify as a hack - // but this lets the editor pane expand to fill the whole parent panel - getParent().setLayout(new FlowLayout()); - getParent().add(this, BorderLayout.CENTER); - - setLayout(new BorderLayout()); - setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - setBackground(ColorScheme.DARK_GRAY_COLOR); - - JPanel reloadContainer = new JPanel(); - JPanel scouterContainer = new JPanel(); - JPanel buttons = new JPanel(); - reloadContainer.setLayout(new BorderLayout()); - buttons.setLayout(new BorderLayout()); - buttons.setBackground(ColorScheme.DARKER_GRAY_COLOR); - reloadContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - scouterContainer.setLayout(new BorderLayout()); - scouterContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - JPanel reloadFrame = new JPanel(); - JPanel scoutFrame = new JPanel(); - reloadButton.addActionListener((ActionEvent e) -> - { - - - if ((client.getGameState() == GameState.LOGGED_IN)) - { - - try - { - //look for client.gameStateChanged(-1); in src files to find - Method m = client.getClass().getClassLoader().loadClass("jr").getDeclaredMethod("fn", int.class, int.class); - m.setAccessible(true); - m.invoke(null, 40, -1893789506); - - //Method m = client.getClass().getClassLoader().loadClass("jr").getDeclaredMethod("fn", int.class, int.class); - //m.setAccessible(true); - //m.invoke(null, 40, -1893789506); - raidsPlugin.canShow = false; - raidsPlugin.timerOverride = true; - //TODO: Since this is mainly for raids i'd like to reload the raids scouting plugin after the dc is finished - - } - catch (ReflectiveOperationException f) - { - throw new RuntimeException(f); - } - } - else - { - //TODO: User is still in a dc, or not logged in. Possibly provide a meaningful message somewhere. - } - }); - reloadScouter.addActionListener((ActionEvent e) -> - { - if ((client.getGameState() == GameState.LOGGED_IN)) - { - raidsPlugin.canShow = false; - raidsPlugin.checkRaidPresence(true); - } - }); - - reloadFrame.add(reloadButton); - scoutFrame.add(reloadScouter); - reloadContainer.add(reloadFrame, BorderLayout.NORTH); - reloadContainer.add(scoutFrame, BorderLayout.SOUTH); - add(reloadMessage, BorderLayout.PAGE_START); - add(reloadContainer, BorderLayout.CENTER); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPlugin.java deleted file mode 100644 index ee2e83af94..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPlugin.java +++ /dev/null @@ -1,958 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids; - -import com.google.inject.Binder; -import com.google.inject.Provides; -import java.awt.image.BufferedImage; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.text.DecimalFormat; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.Vector; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.inject.Inject; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.InstanceTemplates; -import net.runelite.api.NullObjectID; -import static net.runelite.api.Perspective.SCENE_SIZE; -import net.runelite.api.Point; -import static net.runelite.api.SpriteID.TAB_QUESTS_BROWN_RAIDING_PARTY; -import net.runelite.api.Tile; -import net.runelite.api.VarPlayer; -import net.runelite.api.Varbits; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.VarbitChanged; -import net.runelite.api.events.WidgetHiddenChanged; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -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.game.SkillIconManager; -import net.runelite.client.game.SpriteManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.newraids.solver.Layout; -import net.runelite.client.plugins.newraids.solver.LayoutSolver; -import net.runelite.client.plugins.newraids.solver.RotationSolver; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.ui.overlay.infobox.InfoBoxManager; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.Text; - -@PluginDescriptor( - name = "Raids Scouter", - description = "Show helpful information for the Chambers of Xeric raid", - tags = {"combat", "raid", "overlay", "pve", "pvm", "bosses"}, - type = PluginType.PVM -) -@Slf4j -public class RaidsPlugin extends Plugin -{ - static final DecimalFormat POINTS_FORMAT = new DecimalFormat("#,###"); - private static final int LOBBY_PLANE = 3; - private static final String RAID_START_MESSAGE = "The raid has begun!"; - private static final String LEVEL_COMPLETE_MESSAGE = "level complete!"; - private static final String KC_MESSAGE = "Your completed Chambers of Xeric count is:"; - private static final String KC_MESSAGECM = "Your completed Chambers of Xeric Challenge Mode count is:"; - private static final String RAID_COMPLETE_MESSAGE = "Congratulations - your raid is complete!"; - private static final String RAID_COMPLETE_MESSAGE2 = "Congratulations - your raid is complete! Duration:"; - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##"); - private static final String SPLIT_REGEX = "\\s*,\\s*"; - private static final Pattern ROTATION_REGEX = Pattern.compile("\\[(.*?)]"); - @Getter - private final ArrayList roomWhitelist = new ArrayList<>(); - @Getter - private final ArrayList roomBlacklist = new ArrayList<>(); - @Getter - private final ArrayList rotationWhitelist = new ArrayList<>(); - @Getter - private final ArrayList layoutWhitelist = new ArrayList<>(); - public boolean canShow; - public boolean timerOverride = false; - data raidToAdd = new data(); - int ticks = 0; - int raidSeconds; - int backupTime; - @Inject - private ChatMessageManager chatMessageManager; - @Inject - private InfoBoxManager infoBoxManager; - @Inject - private SkillIconManager iconManager; - @Inject - private Client client; - @Inject - private RaidsConfig config; - @Inject - private OverlayManager overlayManager; - @Inject - private RaidsOverlay overlay; - @Inject - private RaidsPointsOverlay pointsOverlay; - @Inject - private LayoutSolver layoutSolver; - @Inject - private SpriteManager spriteManager; - @Inject - private ClientThread clientThread; - @Getter - private Raid raid; - private RaidsPanel panel; - private PointsPanel pointsPanel; - private NavigationButton navButton; - private NavigationButton navButton2; - @Getter - private boolean inRaidChambers; - private RaidsTimer timer; - @Inject - private ClientToolbar clientToolbar; - - @Provides - RaidsConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(RaidsConfig.class); - } - - @Override - public void configure(Binder binder) - { - binder.bind(RaidsOverlay.class); - } - - @Override - protected void startUp() throws Exception - { - overlayManager.add(overlay); - if (config.oldOverlay()) - { - overlayManager.add(pointsOverlay); - } - updateLists(); - clientThread.invokeLater(() -> checkRaidPresence(true)); - panel = injector.getInstance(RaidsPanel.class); - pointsPanel = new PointsPanel(this, config, client, iconManager); - pointsPanel.init(); - if (config.soloPanel()) - { - pointsPanel.setSolo(true); - pointsPanel.updateSolo(); - } - else - { - pointsPanel.setSolo(false); - pointsPanel.update(); - } - panel.init(config); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "instancereloadhelper.png"); - final BufferedImage iconPoint = ImageUtil.getResourceStreamFromClass(this.getClass(), "cox.png"); - - navButton = NavigationButton.builder() - .tooltip("Raids Reload") - .icon(icon) - .priority(8) - .panel(panel) - .build(); - navButton2 = NavigationButton.builder() - .tooltip("CoX Points") - .icon(iconPoint) - .priority(9) - .panel(pointsPanel) - .build(); - clientToolbar.addNavigation(navButton); - if (config.ptsPanel()) - { - clientToolbar.addNavigation(navButton2); - } - } - - @Override - protected void shutDown() throws Exception - { - clientToolbar.removeNavigation(navButton); - clientToolbar.removeNavigation(navButton2); - overlayManager.remove(overlay); - infoBoxManager.removeInfoBox(timer); - overlayManager.remove(pointsOverlay); - inRaidChambers = false; - raid = null; - timer = null; - - final Widget widget = client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX); - if (widget != null) - { - widget.setHidden(false); - } - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (config.ptsPanel()) - { - if (config.soloPanel()) - { - pointsPanel.updateSolo(); - pointsPanel.setSolo(true); - } - else - { - pointsPanel.update(); - pointsPanel.setSolo(false); - } - pointsPanel.revalidate(); - } - if (!config.oldOverlay()) - { - overlayManager.remove(pointsOverlay); - } - if (!event.getGroup().equals("raids")) - { - return; - } - - if (event.getKey().equals("raidsTimer")) - { - updateInfoBoxState(); - return; - } - - updateLists(); - clientThread.invokeLater(() -> checkRaidPresence(true)); - } - - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - checkRaidPresence(false); - } - - - @Subscribe - public void onWidgetHiddenChanged(WidgetHiddenChanged event) - { - if (!inRaidChambers || event.isHidden()) - { - return; - } - - Widget widget = event.getWidget(); - - if (widget == client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX)) - { - - if (config.oldOverlay()) - { - widget.setHidden(true); - overlayManager.add(pointsOverlay); - } - else - { - widget.setHidden(false); - overlayManager.remove(pointsOverlay); - } - - } - } - - @Subscribe - public void onChatMessage(ChatMessage event) - { -/* - String t = Text.removeTags(event.getMessage()); - System.out.println(t); - if(t.equals("Test")){ - long timeTake = r(2000,5000); - data test = new data(); - test.add(r(50000,75000),r(10000,20000),r(20000,40000), (int) timeTake,2000,"TEST",new Date(),new Date()); - pointsPanel.raids.add(test); - if(config.soloPanel()){ - pointsPanel.updateSolo(); - }else{ - pointsPanel.update(); - } - if(!pointsPanel.timer.started){ - pointsPanel.timer.start(timeTake); - } - - } -*/ - String test = Text.removeTags(event.getMessage()); - if (raidToAdd != null) - { - raidToAdd.cm = false; - } - if (test.startsWith(KC_MESSAGE)) - { - PointsPanel.raids.get(PointsPanel.raids.size() - 1).kc = Integer.parseInt(test.replaceAll("\\D+", "")); - PointsPanel.raids.get(PointsPanel.raids.size() - 1).cm = false; - - if (config.soloPanel()) - { - pointsPanel.updateSolo(); - } - else - { - pointsPanel.update(); - } - - //raidToAdd.kc = Integer.parseInt(test.replaceAll("\\D+","")); - } - if (test.startsWith(KC_MESSAGECM)) - { - PointsPanel.raids.get(PointsPanel.raids.size() - 1).kc = Integer.parseInt(test.replaceAll("\\D+", "")); - PointsPanel.raids.get(PointsPanel.raids.size() - 1).cm = true; - - if (config.soloPanel()) - { - pointsPanel.updateSolo(); - } - else - { - pointsPanel.update(); - } - - //raidToAdd.kc = Integer.parseInt(test.replaceAll("\\D+","")); - } - if (inRaidChambers && event.getType() == ChatMessageType.FRIENDSCHATNOTIFICATION) - { - String message = Text.removeTags(event.getMessage()); - if (message.startsWith(RAID_START_MESSAGE)) - { - raidToAdd.start = new Date(); - } - if (message.startsWith(RAID_COMPLETE_MESSAGE)) - { - raidToAdd.finish = new Date(); - } - - if (config.raidsTimer() && message.startsWith(RAID_START_MESSAGE)) - { - - timer = new RaidsTimer(spriteManager.getSprite(TAB_QUESTS_BROWN_RAIDING_PARTY, 0), this, Instant.now()); - infoBoxManager.addInfoBox(timer); - } - - if (timer != null && message.contains(LEVEL_COMPLETE_MESSAGE)) - { - timer.timeFloor(); - } - - - if (message.startsWith(RAID_COMPLETE_MESSAGE)) - { - String stripped = message.replaceAll("[^\\d]", ""); - backupTime = 0; - int sSec = 0; - int sMin = 0; - int sHour = 0; - if (stripped.length() > 1) - { - sSec = Integer.parseInt(stripped.substring(stripped.length() - 2)); - stripped = stripped.substring(0, stripped.length() - 2); - } - if (stripped.length() > 1) - { - sMin = Integer.parseInt(stripped.substring(stripped.length() - 2)); - stripped = stripped.substring(0, stripped.length() - 2); - } - else if (stripped.length() > 0) - { - sMin = Integer.parseInt(stripped.substring(stripped.length() - 1)); - stripped = stripped.substring(0, stripped.length() - 1); - } - if (stripped.length() > 1) - { - sHour = Integer.parseInt(stripped.substring(stripped.length() - 2)); - stripped = stripped.substring(0, stripped.length() - 2); - } - else if (stripped.length() > 0) - { - sHour = Integer.parseInt(stripped.substring(stripped.length() - 1)); - stripped = stripped.substring(0, stripped.length() - 1); - } - backupTime = (sSec) + (sMin * 60) + (sHour * 3600); - raidToAdd.timeTaken = backupTime; - if (timer != null) - { - - timer.timeOlm(); - raidSeconds = backupTime; - timerOverride = false; - timer.setStopped(true); - } - raidToAdd.personal = client.getVar(Varbits.PERSONAL_POINTS); - raidToAdd.total = client.getVar(Varbits.TOTAL_POINTS); - raidToAdd.hr = (int) (((float) raidToAdd.personal / (float) raidToAdd.timeTaken) * 3600); - if (config.ptsPanel()) - { - PointsPanel.raids.add(raidToAdd); - if (!pointsPanel.timer.started) - { - pointsPanel.timer.start(raidToAdd.timeTaken); - } - if (config.soloPanel()) - { - pointsPanel.updateSolo(); - } - else - { - pointsPanel.update(); - } - raidToAdd = new data(); - } - if (config.pointsMessage()) - { - int totalPoints = client.getVar(Varbits.TOTAL_POINTS); - int personalPoints = client.getVar(Varbits.PERSONAL_POINTS); - - double percentage = personalPoints / (totalPoints / 100.0); - - String chatMessage = new ChatMessageBuilder() - .append(ChatColorType.NORMAL) - .append("Total points: ") - .append(ChatColorType.HIGHLIGHT) - .append(POINTS_FORMAT.format(totalPoints)) - .append(ChatColorType.NORMAL) - .append(", Personal points: ") - .append(ChatColorType.HIGHLIGHT) - .append(POINTS_FORMAT.format(personalPoints)) - .append(ChatColorType.NORMAL) - .append(" (") - .append(ChatColorType.HIGHLIGHT) - .append(DECIMAL_FORMAT.format(percentage)) - .append(ChatColorType.NORMAL) - .append("%)") - .build(); - - - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.FRIENDSCHATNOTIFICATION) - .runeLiteFormattedMessage(chatMessage) - .build()); - if (config.ptsHr()) - { - String pts; - if (timer != null) - { - pts = POINTS_FORMAT.format(((float) personalPoints / (float) raidSeconds) * 3600); - } - else - { - pts = POINTS_FORMAT.format(((float) personalPoints / (float) backupTime) * 3600); - } - - - String chatMessage2 = new ChatMessageBuilder() - .append(ChatColorType.NORMAL) - .append("Pts/Hr: ") - .append(ChatColorType.HIGHLIGHT) - .append(pts) - .build(); - - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.FRIENDSCHATNOTIFICATION) - .runeLiteFormattedMessage(chatMessage2) - .build()); - } - } - } - } - } - - public void checkRaidPresence(boolean force) - { - - if (client.getGameState() != GameState.LOGGED_IN) - { - return; - } - boolean setting = true; - if (!force) - { - setting = client.getVar(Varbits.IN_RAID) == 1; - } - else - { - - } - if (force || inRaidChambers != setting) - { - inRaidChambers = setting; - updateInfoBoxState(); - - if (inRaidChambers) - { - raid = buildRaid(); - - if (raid == null) - { - System.out.println("in cm"); - log.debug("Failed to build raid"); - return; - } - - Layout layout = layoutSolver.findLayout(raid.toCode()); - - if (layout == null) - { - log.debug("Could not find layout match"); - return; - } - - raid.updateLayout(layout); - RotationSolver.solve(raid.getCombatRooms()); - raidToAdd.raid = getRaid().toRoomString(); - sendRaidLayoutMessage(); - Vector puzzles = new Vector(); - puzzles.clear(); - for (RaidRoom r : raid.getRooms()) - { - if (r != null) - { - if (r.getPuzzle() != null) - { - if (r.getPuzzle().getName() != null) - { - puzzles.add(r.getPuzzle().getName()); - } - } - } - } - //Push puzzles to api - String urlString = "http://lyzrds.com/puzzles/api.php"; - boolean add = true; - if (puzzles.size() > 3) - { - add = false; - } - if (puzzles.size() == 0) - { - add = false; - } - switch (puzzles.size()) - { - case 1: - urlString = urlString + "?p1=" + puzzles.get(0); - break; - case 2: - urlString = urlString + "?p1=" + puzzles.get(0) + "&p2=" + puzzles.get(1); - break; - case 3: - urlString = urlString + "?p1=" + puzzles.get(0) + "&p2=" + puzzles.get(1) + "&p3=" + puzzles.get(2); - break; - - } - urlString = urlString + "&r=" + getRaid().getLayout().toCodeString() + ":" + getRaid().toRoomString(); - //System.out.println(urlString +"&r=" + getRaid().getLayout().toCodeString() +":"+ getRaid().toRoomString()); - if (add && canShow) - { - URL oracle = null; - try - { - oracle = new URL(urlString.replace(" ", "")); - } - catch (MalformedURLException e) - { - e.printStackTrace(); - } - URLConnection yc = null; - try - { - yc = oracle.openConnection(); - } - catch (IOException e) - { - e.printStackTrace(); - } - BufferedReader in = null; - try - { - in = new BufferedReader(new InputStreamReader( - yc.getInputStream())); - } - catch (IOException e) - { - e.printStackTrace(); - } - try - { - in.close(); - } - catch (IOException e) - { - e.printStackTrace(); - } - - } - canShow = true; - overlay.setScoutOverlayShown(true); - } - else if (!config.scoutOverlayAtBank()) - { - overlay.setScoutOverlayShown(false); - } - } - - // If we left party raid was started or we left raid - if (client.getVar(VarPlayer.IN_RAID_PARTY) == -1 && (!inRaidChambers || !config.scoutOverlayInRaid())) - { - overlay.setScoutOverlayShown(false); - canShow = true; - } - } - - private void sendRaidLayoutMessage() - { - if (!config.layoutMessage()) - { - return; - } - - final String layout = getRaid().getLayout().toCodeString(); - final String rooms = getRaid().toRoomString(); - final String raidData = "[" + layout + "]: " + rooms; - - chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.FRIENDSCHATNOTIFICATION) - .runeLiteFormattedMessage(new ChatMessageBuilder() - .append(ChatColorType.HIGHLIGHT) - .append("Layout: ") - .append(ChatColorType.NORMAL) - .append(raidData) - .build()) - .build()); - } - - private void updateInfoBoxState() - { - if (timer == null) - { - return; - } - - if (inRaidChambers && config.raidsTimer()) - { - if (!infoBoxManager.getInfoBoxes().contains(timer)) - { - infoBoxManager.addInfoBox(timer); - } - } - else - { - infoBoxManager.removeInfoBox(timer); - } - - if (!inRaidChambers) - { - timer = null; - } - } - - private void updateLists() - { - updateList(roomWhitelist, config.whitelistedRooms()); - updateList(roomBlacklist, config.blacklistedRooms()); - updateList(rotationWhitelist, config.whitelistedRotations()); - updateList(layoutWhitelist, config.whitelistedLayouts()); - } - - private void updateList(ArrayList list, String input) - { - list.clear(); - - if (list == rotationWhitelist) - { - Matcher m = ROTATION_REGEX.matcher(input); - while (m.find()) - { - String rotation = m.group(1).toLowerCase(); - - if (!list.contains(rotation)) - { - list.add(rotation); - } - } - } - else - { - list.addAll(Arrays.asList(input.toLowerCase().split(SPLIT_REGEX))); - } - } - - int getRotationMatches() - { - String rotation = raid.getRotationString().toLowerCase(); - String[] bosses = rotation.split(SPLIT_REGEX); - - if (rotationWhitelist.contains(rotation)) - { - return bosses.length; - } - - for (String whitelisted : rotationWhitelist) - { - int matches = 0; - String[] whitelistedBosses = whitelisted.split(SPLIT_REGEX); - - for (int i = 0; i < whitelistedBosses.length; i++) - { - if (i < bosses.length && whitelistedBosses[i].equals(bosses[i])) - { - matches++; - } - else - { - matches = 0; - break; - } - } - - if (matches >= 2) - { - return matches; - } - } - - return 0; - } - - private Point findLobbyBase() - { - Tile[][] tiles = client.getScene().getTiles()[LOBBY_PLANE]; - - for (int x = 0; x < SCENE_SIZE; x++) - { - for (int y = 0; y < SCENE_SIZE; y++) - { - if (tiles[x][y] == null || tiles[x][y].getWallObject() == null) - { - continue; - } - - if (tiles[x][y].getWallObject().getId() == NullObjectID.NULL_12231) - { - return tiles[x][y].getSceneLocation(); - } - } - } - - return null; - } - - private Raid buildRaid() - { - Point gridBase = findLobbyBase(); - - if (gridBase == null) - { - return null; - } - - Raid raid = new Raid(); - Tile[][] tiles; - int position, x, y, offsetX; - int startX = -2; - - for (int plane = 3; plane > 1; plane--) - { - tiles = client.getScene().getTiles()[plane]; - - if (tiles[gridBase.getX() + RaidRoom.ROOM_MAX_SIZE][gridBase.getY()] == null) - { - position = 1; - } - else - { - position = 0; - } - - for (int i = 1; i > -2; i--) - { - y = gridBase.getY() + (i * RaidRoom.ROOM_MAX_SIZE); - - for (int j = startX; j < 4; j++) - { - x = gridBase.getX() + (j * RaidRoom.ROOM_MAX_SIZE); - offsetX = 0; - - if (x > SCENE_SIZE && position > 1 && position < 4) - { - position++; - } - - if (x < 0) - { - offsetX = Math.abs(x) + 1; //add 1 because the tile at x=0 will always be null - } - - if (x < SCENE_SIZE && y >= 0 && y < SCENE_SIZE) - { - if (tiles[x + offsetX][y] == null) - { - if (position == 4) - { - position++; - break; - } - - continue; - } - - if (position == 0 && startX != j) - { - startX = j; - } - - Tile base = tiles[offsetX > 0 ? 1 : x][y]; - RaidRoom room = determineRoom(base); - raid.setRoom(room, position + Math.abs((plane - 3) * 8)); - position++; - } - } - } - } - - return raid; - } - - private RaidRoom determineRoom(Tile base) - { - RaidRoom room = new RaidRoom(base, RaidRoom.Type.EMPTY); - int chunkData = client.getInstanceTemplateChunks()[base.getPlane()][(base.getSceneLocation().getX()) / 8][base.getSceneLocation().getY() / 8]; - InstanceTemplates template = InstanceTemplates.findMatch(chunkData); - - if (template == null) - { - return room; - } - - switch (template) - { - case RAIDS_LOBBY: - case RAIDS_START: - room.setType(RaidRoom.Type.START); - break; - - case RAIDS_END: - room.setType(RaidRoom.Type.END); - break; - - case RAIDS_SCAVENGERS: - case RAIDS_SCAVENGERS2: - room.setType(RaidRoom.Type.SCAVENGERS); - break; - - case RAIDS_SHAMANS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.SHAMANS); - break; - - case RAIDS_VASA: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.VASA); - break; - - case RAIDS_VANGUARDS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.VANGUARDS); - break; - - case RAIDS_ICE_DEMON: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.ICE_DEMON); - break; - - case RAIDS_THIEVING: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.THIEVING); - break; - - case RAIDS_FARMING: - case RAIDS_FARMING2: - room.setType(RaidRoom.Type.FARMING); - break; - - case RAIDS_MUTTADILES: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.MUTTADILES); - break; - - case RAIDS_MYSTICS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.MYSTICS); - break; - - case RAIDS_TEKTON: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.TEKTON); - break; - - case RAIDS_TIGHTROPE: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.TIGHTROPE); - break; - - case RAIDS_GUARDIANS: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.GUARDIANS); - break; - - case RAIDS_CRABS: - room.setType(RaidRoom.Type.PUZZLE); - room.setPuzzle(RaidRoom.Puzzle.CRABS); - break; - - case RAIDS_VESPULA: - room.setType(RaidRoom.Type.COMBAT); - room.setBoss(RaidRoom.Boss.VESPULA); - break; - } - - return room; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPointsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPointsOverlay.java deleted file mode 100644 index b3db041b28..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsPointsOverlay.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.Varbits; -import static net.runelite.client.plugins.newraids.RaidsPlugin.POINTS_FORMAT; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; -import net.runelite.client.ui.overlay.components.LineComponent; -import net.runelite.client.ui.overlay.components.PanelComponent; - -public class RaidsPointsOverlay extends Overlay -{ - private final PanelComponent panel = new PanelComponent(); - @Inject - private Client client; - @Inject - private RaidsPlugin plugin; - - @Inject - public RaidsPointsOverlay() - { - setPosition(OverlayPosition.TOP_RIGHT); - setPriority(OverlayPriority.HIGH); - } - - @Override - public Dimension render(Graphics2D graphics) - { - if (!plugin.isInRaidChambers()) - { - return null; - } - - int totalPoints = client.getVar(Varbits.TOTAL_POINTS); - int personalPoints = client.getVar(Varbits.PERSONAL_POINTS); - int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); - - panel.getChildren().clear(); - panel.getChildren().add(LineComponent.builder() - .left("Total:") - .right(POINTS_FORMAT.format(totalPoints)) - .build()); - - panel.getChildren().add(LineComponent.builder() - .left(client.getLocalPlayer().getName() + ":") - .right(POINTS_FORMAT.format(personalPoints)) - .build()); - - if (partySize > 1) - { - panel.getChildren().add(LineComponent.builder() - .left("Party size:") - .right(String.valueOf(partySize)) - .build()); - } - - return panel.render(graphics); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsTimer.java deleted file mode 100644 index a6db312c02..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/RaidsTimer.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids; - -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; -import lombok.Setter; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.ui.overlay.infobox.InfoBox; - -public class RaidsTimer extends InfoBox -{ - private final Instant startTime; - public LocalTime time; - private Instant floorTime; - private LocalTime firstFloorTime; - private LocalTime secondFloorTime; - private LocalTime thirdFloorTime; - private LocalTime olmTime; - - @Setter - private boolean stopped; - - public RaidsTimer(BufferedImage image, Plugin plugin, Instant startTime) - { - super(image, plugin); - this.startTime = startTime; - floorTime = startTime; - stopped = false; - } - - public void timeFloor() - { - Duration elapsed = Duration.between(floorTime, Instant.now()); - - if (firstFloorTime == null) - { - firstFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); - } - else if (secondFloorTime == null) - { - secondFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); - } - else if (thirdFloorTime == null) - { - - thirdFloorTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); - } - - floorTime = Instant.now(); - } - - - public int getSeconds() - { - return time.getSecond() + (time.getMinute() * 60) + (time.getHour() * 3600); - } - - - public void timeOlm() - { - Duration elapsed = Duration.between(floorTime, Instant.now()); - olmTime = LocalTime.ofSecondOfDay(elapsed.getSeconds()); - } - - @Override - public String getTooltip() - { - StringBuilder builder = new StringBuilder(); - builder.append("Elapsed raid time: "); - builder.append(time.format(DateTimeFormatter.ofPattern("HH:mm:ss"))); - - if (firstFloorTime != null) - { - builder.append("
First floor: "); - builder.append(firstFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); - } - - if (secondFloorTime != null) - { - builder.append("
Second floor: "); - builder.append(secondFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); - } - - if (thirdFloorTime != null) - { - - builder.append("
Third floor: "); - builder.append(thirdFloorTime.format(DateTimeFormatter.ofPattern("mm:ss"))); - } - - if (olmTime != null) - { - builder.append("
Olm: "); - builder.append(olmTime.format(DateTimeFormatter.ofPattern("mm:ss"))); - } - - return builder.toString(); - } - - @Override - public String getText() - { - if (startTime == null) - { - return ""; - } - - if (!stopped) - { - Duration elapsed = Duration.between(startTime, Instant.now()); - time = LocalTime.ofSecondOfDay(elapsed.getSeconds()); - } - - if (time.getHour() > 0) - { - return time.format(DateTimeFormatter.ofPattern("HH:mm")); - } - - return time.format(DateTimeFormatter.ofPattern("mm:ss")); - } - - @Override - public Color getTextColor() - { - if (stopped) - { - return Color.GREEN; - } - - return Color.WHITE; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/SoloBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/SoloBox.java deleted file mode 100644 index f6b7805782..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/SoloBox.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2018, Adam - * Copyright (c) 2018, Psikoi - * 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.newraids; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.text.DecimalFormat; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.DynamicGridLayout; -import net.runelite.client.ui.FontManager; -import net.runelite.client.util.ColorUtil; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.StackFormatter; - -class SoloBox extends JPanel -{ - static final DecimalFormat POINTS_FORMAT = new DecimalFormat("#,###"); - private static final DecimalFormat TWO_DECIMAL_FORMAT = new DecimalFormat("0.00"); - // Templates - private static final String HTML_TOOL_TIP_TEMPLATE = - "%s %s done
" - + "%s %s/hr
" - + "%s till goal lvl"; - private static final String HTML_LABEL_TEMPLATE = - "%s%s"; - - // Instance members - private final JPanel panel; - - @Getter(AccessLevel.PACKAGE) - private final data raid; - - /* The tracker's wrapping container */ - private final JPanel container = new JPanel(); - - /* Contains the skill icon and the stats panel */ - private final JPanel headerPanel = new JPanel(); - - /* Contains all the skill information (exp gained, per hour, etc) */ - private final JPanel statsPanel = new JPanel(); - - - private final JLabel personalPoints = new JLabel(); - private final JLabel hourlyPoints = new JLabel(); - private final JLabel totalPoints = new JLabel(); - private final JLabel raidTime = new JLabel(); - private final JLabel layout = new JLabel(); - private final JLabel teamHour = new JLabel(); - private final JLabel killCount = new JLabel(); - private final JMenuItem pauseSkill = new JMenuItem("Pause"); - - private RaidsConfig raidsConfig; - - private boolean paused = false; - - SoloBox(RaidsPlugin raidsPlugin, RaidsConfig raidsConfig, Client client, JPanel panel, data raid, SkillIconManager iconManager) throws IOException - { - this.raidsConfig = raidsConfig; - this.panel = panel; - this.raid = raid; - - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(5, 0, 0, 0)); - - container.setLayout(new BorderLayout()); - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - - // Create reset others menu - //pauseSkill.addActionListener(e -> raidsPlugin.pauseSkill(skill, !paused)); - - BufferedImage image = ImageUtil.getResourceStreamFromClass(this.getClass(), "cox.png"); - ImageIcon i = new ImageIcon(image); - - JLabel skillIcon = new JLabel(i); - skillIcon.setHorizontalAlignment(SwingConstants.CENTER); - skillIcon.setVerticalAlignment(SwingConstants.CENTER); - skillIcon.setPreferredSize(new Dimension(35, 35)); - - headerPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - headerPanel.setLayout(new BorderLayout()); - - - statsPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - statsPanel.setBorder(new EmptyBorder(9, 2, 9, 2)); - statsPanel.setLayout(new DynamicGridLayout(2, 2)); - personalPoints.setFont(FontManager.getRunescapeSmallFont()); - personalPoints.setText("Personal: " + POINTS_FORMAT.format(raid.personal)); - hourlyPoints.setFont(FontManager.getRunescapeSmallFont()); - hourlyPoints.setText("Points/Hr: " + POINTS_FORMAT.format(raid.hr)); - totalPoints.setFont(FontManager.getRunescapeSmallFont()); - totalPoints.setText("Total: " + POINTS_FORMAT.format(raid.total)); - teamHour.setFont(FontManager.getRunescapeSmallFont()); - teamHour.setText("Points/Hr: " + POINTS_FORMAT.format((((float) raid.total / raid.timeTaken) * 3600))); - killCount.setFont(FontManager.getRunescapeSmallFont()); - killCount.setText("KC: " + raid.kc); - raidTime.setFont(FontManager.getRunescapeSmallFont()); - raidTime.setText("Time: " + formatSeconds(raid.timeTaken)); - //maybe add drop rate - statsPanel.add(personalPoints); - statsPanel.add(hourlyPoints); - statsPanel.add(killCount); - statsPanel.add(raidTime); - - - headerPanel.add(skillIcon, BorderLayout.WEST); - headerPanel.add(statsPanel, BorderLayout.CENTER); - - JPanel progressWrapper = new JPanel(); - progressWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR); - progressWrapper.setLayout(new BorderLayout()); - progressWrapper.setBorder(new EmptyBorder(0, 7, 7, 7)); - layout.setFont(FontManager.getRunescapeSmallFont()); - if (raid.cm) - { - layout.setText("

Challenge Mode

"); - } - else - { - layout.setText("

" + raid.raid + "

"); - } - - - progressWrapper.add(layout, BorderLayout.NORTH); - - container.add(headerPanel, BorderLayout.NORTH); - container.add(progressWrapper, BorderLayout.SOUTH); - - - add(container, BorderLayout.NORTH); - } - - - static String htmlLabel(String key, int value) - { - String valueStr = StackFormatter.quantityToRSDecimalStack(value); - return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); - } - - static String htmlLabel(String key, String value) - { - String valueStr = value; - return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); - } - - public static String formatSeconds(int timeInSeconds) - { - int hours = timeInSeconds / 3600; - int secondsLeft = timeInSeconds - hours * 3600; - int minutes = secondsLeft / 60; - int seconds = secondsLeft - minutes * 60; - - String formattedTime = ""; - if (hours < 10) - { - formattedTime += "0"; - } - formattedTime += hours + ":"; - - if (minutes < 10) - { - formattedTime += "0"; - } - formattedTime += minutes + ":"; - - if (seconds < 10) - { - formattedTime += "0"; - } - formattedTime += seconds; - - return formattedTime; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/XpInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/XpInfoBox.java deleted file mode 100644 index defbe55a7a..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/XpInfoBox.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2018, Adam - * Copyright (c) 2018, Psikoi - * 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.newraids; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.text.DecimalFormat; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.DynamicGridLayout; -import net.runelite.client.ui.FontManager; -import net.runelite.client.util.ColorUtil; -import net.runelite.client.util.ImageUtil; - -class XpInfoBox extends JPanel -{ - static final DecimalFormat POINTS_FORMAT = new DecimalFormat("#,###"); - private static final DecimalFormat TWO_DECIMAL_FORMAT = new DecimalFormat("0.00"); - // Templates - private static final String HTML_TOOL_TIP_TEMPLATE = - "%s %s done
" - + "%s %s/hr
" - + "%s till goal lvl"; - private static final String HTML_LABEL_TEMPLATE = - "%s%s"; - - // Instance members - private final JPanel panel; - - @Getter(AccessLevel.PACKAGE) - private final data raid; - - /* The tracker's wrapping container */ - private final JPanel container = new JPanel(); - - /* Contains the skill icon and the stats panel */ - private final JPanel headerPanel = new JPanel(); - - /* Contains all the skill information (exp gained, per hour, etc) */ - private final JPanel statsPanel = new JPanel(); - - - private final JLabel personalPoints = new JLabel(); - private final JLabel hourlyPoints = new JLabel(); - private final JLabel totalPoints = new JLabel(); - private final JLabel raidTime = new JLabel(); - private final JLabel layout = new JLabel(); - private final JLabel teamHour = new JLabel(); - private final JLabel killCount = new JLabel(); - private final JMenuItem pauseSkill = new JMenuItem("Pause"); - - private RaidsConfig raidsConfig; - - private boolean paused = false; - - XpInfoBox(RaidsPlugin raidsPlugin, RaidsConfig raidsConfig, Client client, JPanel panel, data raid, SkillIconManager iconManager) throws IOException - { - this.raidsConfig = raidsConfig; - this.panel = panel; - this.raid = raid; - - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(5, 0, 0, 0)); - - container.setLayout(new BorderLayout()); - container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - - // Create reset others menu - //pauseSkill.addActionListener(e -> raidsPlugin.pauseSkill(skill, !paused)); - - BufferedImage image = ImageUtil.getResourceStreamFromClass(this.getClass(), "cox.png"); - ImageIcon i = new ImageIcon(image); - - JLabel skillIcon = new JLabel(i); - skillIcon.setHorizontalAlignment(SwingConstants.CENTER); - skillIcon.setVerticalAlignment(SwingConstants.CENTER); - skillIcon.setPreferredSize(new Dimension(35, 35)); - - headerPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - headerPanel.setLayout(new BorderLayout()); - - - statsPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - statsPanel.setBorder(new EmptyBorder(9, 2, 9, 2)); - statsPanel.setLayout(new DynamicGridLayout(3, 2)); - personalPoints.setFont(FontManager.getRunescapeSmallFont()); - personalPoints.setText("Personal: " + POINTS_FORMAT.format(raid.personal)); - hourlyPoints.setFont(FontManager.getRunescapeSmallFont()); - hourlyPoints.setText("Points/Hr: " + POINTS_FORMAT.format(raid.hr)); - totalPoints.setFont(FontManager.getRunescapeSmallFont()); - totalPoints.setText("Total: " + POINTS_FORMAT.format(raid.total)); - teamHour.setFont(FontManager.getRunescapeSmallFont()); - teamHour.setText("Points/Hr: " + POINTS_FORMAT.format((((float) raid.total / raid.timeTaken) * 3600))); - killCount.setFont(FontManager.getRunescapeSmallFont()); - killCount.setText("KC: " + raid.kc); - raidTime.setFont(FontManager.getRunescapeSmallFont()); - raidTime.setText("Time: " + formatSeconds(raid.timeTaken)); - //maybe add drop rate - statsPanel.add(personalPoints); - statsPanel.add(totalPoints); - statsPanel.add(hourlyPoints); - statsPanel.add(teamHour); - statsPanel.add(killCount); - statsPanel.add(raidTime); - - - headerPanel.add(skillIcon, BorderLayout.WEST); - headerPanel.add(statsPanel, BorderLayout.CENTER); - - JPanel progressWrapper = new JPanel(); - progressWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR); - progressWrapper.setLayout(new BorderLayout()); - progressWrapper.setBorder(new EmptyBorder(0, 7, 7, 7)); - layout.setFont(FontManager.getRunescapeSmallFont()); - if (raid.cm) - { - layout.setText("

Challenge Mode

"); - } - else - { - layout.setText("

" + raid.raid + "

"); - } - - - progressWrapper.add(layout, BorderLayout.NORTH); - - container.add(headerPanel, BorderLayout.NORTH); - container.add(progressWrapper, BorderLayout.SOUTH); - - - add(container, BorderLayout.NORTH); - } - - - static String htmlLabel(String key, int value) - { - String valueStr = POINTS_FORMAT.format(value); - return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); - } - - static String htmlLabel(String key, String value) - { - String valueStr = value; - return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); - } - - public static String formatSeconds(int timeInSeconds) - { - int hours = timeInSeconds / 3600; - int secondsLeft = timeInSeconds - hours * 3600; - int minutes = secondsLeft / 60; - int seconds = secondsLeft - minutes * 60; - - String formattedTime = ""; - if (hours < 10) - { - formattedTime += "0"; - } - formattedTime += hours + ":"; - - if (minutes < 10) - { - formattedTime += "0"; - } - formattedTime += minutes + ":"; - - if (seconds < 10) - { - formattedTime += "0"; - } - formattedTime += seconds; - - return formattedTime; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/data.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/data.java deleted file mode 100644 index 0e5be9e9c4..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/data.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.runelite.client.plugins.newraids; - -import java.util.Date; - -public class data -{ - int total; - int personal; - int hr; - int timeTaken; - int kc; - boolean cm; - String raid; - Date start; - Date finish; - - void add(int total, int personal, int hr, int timeTaken, int kc, boolean cm, String raid, Date start, Date finish) - { - this.total = total; - this.personal = personal; - this.hr = hr; - this.kc = kc; - this.cm = cm; - this.timeTaken = timeTaken; - this.raid = raid; - this.start = start; - this.finish = finish; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Layout.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Layout.java deleted file mode 100644 index 0ad48a725a..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Layout.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids.solver; - -import java.util.ArrayList; -import java.util.List; -import lombok.Getter; - -public class Layout -{ - @Getter - private final List rooms = new ArrayList<>(); - - public void add(Room room) - { - rooms.add(room); - } - - public Room getRoomAt(int position) - { - for (Room room : rooms) - { - if (room.getPosition() == position) - { - return room; - } - } - - return null; - } - - public String toCode() - { - StringBuilder builder = new StringBuilder(); - - for (Room room : rooms) - { - builder.append(room.getSymbol()); - } - - return builder.toString(); - } - - public String toCodeString() - { - return toCode().replaceAll("#", "").replaceAll("¤", ""); - } - -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/LayoutSolver.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/LayoutSolver.java deleted file mode 100644 index f766ea9d3c..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/LayoutSolver.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids.solver; - -import com.google.inject.Singleton; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -/* - * Implementation of https://github.com/WooxSolo/raids-layout - * Copyright (c) 2017 WooxSolo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - */ -@Slf4j -@Singleton -public class LayoutSolver -{ - @Getter - private static final List layouts = new ArrayList<>(); - private static final Pattern regex = Pattern.compile("^([A-Z]*)\\.([A-Z]*) - #([A-Z]*)#([A-Z]*)$"); - private static final String[] codes = - { - "FSCCP.PCSCF - #WNWSWN#ESEENW", - "FSCCS.PCPSF - #WSEEEN#WSWNWS", - "FSCPC.CSCPF - #WNWWSE#EENWWW", - "SCCFC.PSCSF - #EEENWW#WSEEEN", - "SCCFP.CCSPF - #NESEEN#WSWNWS", - "SCFCP.CCSPF - #ESEENW#ESWWNW", - "SCFCP.CSCFS - #ENEESW#ENWWSW", - "SCFCPC.CSPCSF - #ESWWNWS#NESENES", - "SCFPC.CSPCF - #WSWWNE#WSEENE", - "SCFPC.PCCSF - #WSEENE#WWWSEE", - "SCFPC.SCPCF - #NESENE#WSWWNE", - "SCPFC.CCPSF - #NWWWSE#WNEESE", - "SCPFC.CSPCF - #NEEESW#WWNEEE", - "SCPFC.CSPSF - #WWSEEE#NWSWWN", - "SCSPF.CCSPF - #ESWWNW#ESENES", - "SFCCP.CSCPF - #WNEESE#NWSWWN", - "SFCCS.PCPSF - #ENWWSW#ENESEN", - "SPCFC.CSPCF - #WWNEEE#WSWNWS", - "SPCFC.SCCPF - #ESENES#WWWNEE", - "SPSFP.CCCSF - #NWSWWN#ESEENW", - "SCFCP.CSCPF - #ENESEN#WWWSEE", - "SCPFC.PCSCF - #WNEEES#NWSWNW", - "SFCCPC.PCSCPF - #WSEENES#WWWNEEE", - "FSPCC.PSCCF - #WWWSEE#ENWWSW", - "FSCCP.PCSCF - #ENWWWS#NEESEN", - "SCPFC.CCSSF - #NEESEN#WSWWNE" - }; - - public LayoutSolver() - { - build(); - } - - public Layout findLayout(String code) - { - Layout solution = null; - int matches = 0; - boolean match; - - for (Layout layout : layouts) - { - match = true; - - for (int i = 0; i < code.length(); i++) - { - Room room = layout.getRoomAt(i); - char c = code.charAt(i); - - if (room != null && c != ' ' && c != room.getSymbol()) - { - match = false; - break; - } - } - - if (match) - { - solution = layout; - matches++; - log.debug("Found matching layout: " + layout.toCode()); - } - else - { - - } - } - - if (matches == 1) - { - return solution; - } - - return null; - } - - private int calcStart(String directions) - { - int startPos = 0; - int position = 0; - - for (int i = 0; i < directions.length(); i++) - { - char c = directions.charAt(i); - int delta = dirToPosDelta(c); - position += delta; - - if (position < 0 || position >= 8 || (position == 3 && delta == -1) || (position == 4 && delta == 1)) - { - position -= delta; - startPos -= delta; - } - } - - return startPos; - } - - private int dirToPosDelta(char direction) - { - switch (String.valueOf(direction)) - { - case "N": - return -4; - - case "E": - return 1; - - case "S": - return 4; - - case "W": - return -1; - - default: - return 0; - } - } - - private void build() - { - for (String code : codes) - { - Matcher match = regex.matcher(code); - - if (!match.find()) - { - continue; - } - - String symbols, directions; - int position = calcStart(match.group(3)); - Layout layout = new Layout(); - Room lastRoom = null; - Room room; - - for (int floor = 0; floor < 2; floor++) - { - symbols = match.group(1 + floor); - directions = match.group(3 + floor); - - for (int i = 0; i < directions.length(); i++) - { - char symbol = (i == 0 ? '#' : symbols.charAt(i - 1)); - - room = new Room(position, symbol); - - if (lastRoom != null) - { - lastRoom.setNext(room); - room.setPrevious(lastRoom); - } - - layout.add(room); - lastRoom = room; - - int delta = dirToPosDelta(directions.charAt(i)); - position += delta; - } - - room = new Room(position, '¤'); - room.setPrevious(lastRoom); - lastRoom.setNext(room); - layout.add(room); - position += 8; - } - - layouts.add(layout); - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Room.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Room.java deleted file mode 100644 index f63d7cd779..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/Room.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids.solver; - -import lombok.Getter; -import lombok.Setter; - -public class Room -{ - @Getter - private final int position; - - @Getter - private final char symbol; - - @Getter - @Setter - private Room next; - - @Getter - @Setter - private Room previous; - - Room(int position, char symbol) - { - this.position = position; - this.symbol = symbol; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/RotationSolver.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/RotationSolver.java deleted file mode 100644 index eb27ede0ca..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/solver/RotationSolver.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2018, Kamiel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.newraids.solver; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import net.runelite.client.plugins.newraids.RaidRoom; -import net.runelite.client.plugins.newraids.RaidRoom.Boss; - -public class RotationSolver -{ - private static final Rotation[] ROTATIONS = - { - new Rotation<>(Arrays.asList(Boss.TEKTON, Boss.VASA, Boss.GUARDIANS, Boss.MYSTICS, Boss.SHAMANS, Boss.MUTTADILES, Boss.VANGUARDS, Boss.VESPULA)), - new Rotation<>(Arrays.asList(Boss.TEKTON, Boss.MUTTADILES, Boss.GUARDIANS, Boss.VESPULA, Boss.SHAMANS, Boss.VASA, Boss.VANGUARDS, Boss.MYSTICS)), - new Rotation<>(Arrays.asList(Boss.VESPULA, Boss.VANGUARDS, Boss.MUTTADILES, Boss.SHAMANS, Boss.MYSTICS, Boss.GUARDIANS, Boss.VASA, Boss.TEKTON)), - new Rotation<>(Arrays.asList(Boss.MYSTICS, Boss.VANGUARDS, Boss.VASA, Boss.SHAMANS, Boss.VESPULA, Boss.GUARDIANS, Boss.MUTTADILES, Boss.TEKTON)) - }; - - public static boolean solve(RaidRoom[] rooms) - { - if (rooms == null) - { - return false; - } - - Rotation match = null; - Integer start = null; - Integer index = null; - int known = 0; - - for (int i = 0; i < rooms.length; i++) - { - if (rooms[i] == null || rooms[i].getBoss() == null || rooms[i].getBoss() == Boss.UNKNOWN) - { - continue; - } - - if (start == null) - { - start = i; - } - - known++; - } - - if (known < 2) - { - return false; - } - - if (known == rooms.length) - { - return true; - } - - for (Rotation rotation : ROTATIONS) - { - COMPARE: - for (int i = 0; i < rotation.size(); i++) - { - if (rooms[start].getBoss() == rotation.get(i)) - { - for (int j = start + 1; j < rooms.length; j++) - { - if (rooms[j].getBoss() == null || rooms[j].getBoss() == Boss.UNKNOWN) - { - continue; - } - - if (rooms[j].getBoss() != rotation.get(i + j - start)) - { - break COMPARE; - } - } - - if (match != null && match != rotation) - { - return false; - } - - index = i - start; - match = rotation; - } - } - } - - if (match == null) - { - return false; - } - - for (int i = 0; i < rooms.length; i++) - { - if (rooms[i] == null) - { - continue; - } - - if (rooms[i].getBoss() == null || rooms[i].getBoss() == Boss.UNKNOWN) - { - rooms[i].setBoss(match.get(index + i)); - } - } - - return true; - } - - private static class Rotation extends ArrayList - { - Rotation(Collection bosses) - { - super(bosses); - } - - @Override - public E get(int index) - { - if (index < 0) - { - index = index + size(); - } - - return super.get(index % size()); - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/timerSpecial.java b/runelite-client/src/main/java/net/runelite/client/plugins/newraids/timerSpecial.java deleted file mode 100644 index 5be382f076..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/newraids/timerSpecial.java +++ /dev/null @@ -1,63 +0,0 @@ -package net.runelite.client.plugins.newraids; - -public class timerSpecial -{ - public boolean started = false; - private long startTime = 0; - private long difference = 0; - private long pause = 0; - private long unpaused = 0; - private long tempTime = 0; - private boolean paused = false; - - public void start() - { - startTime = System.currentTimeMillis(); - tempTime = startTime; - } - - public void start(long offset) - { - startTime = System.currentTimeMillis() - offset * 1000; - tempTime = startTime; - started = true; - } - - public void pause() - { - pause = System.currentTimeMillis(); - tempTime = (System.currentTimeMillis() - startTime) / 1000; - paused = true; - } - - public void unpause() - { - paused = false; - unpaused = System.currentTimeMillis(); - difference = unpaused - pause; - startTime = startTime + difference; - } - - public void reset() - { - startTime = 0; - difference = 0; - pause = 0; - unpaused = 0; - tempTime = 0; - paused = false; - startTime = System.currentTimeMillis(); - tempTime = startTime; - started = false; - } - - public long getElapsedTime() - { - if (paused) - { - return (tempTime); - } - return (System.currentTimeMillis() - startTime) / 1000; - // return (System.currentTimeMillis() - startTime + difference) / 1000; //returns in seconds - } -} From 6f25dd08428b28a8bb159d93756c3ae1dff5d062 Mon Sep 17 00:00:00 2001 From: Ganom Date: Fri, 26 Apr 2019 23:02:54 -0400 Subject: [PATCH 3/3] Removing leftover resources --- .../runelite/client/plugins/newraids/cox.png | Bin 2498 -> 0 bytes .../plugins/newraids/instancereloadhelper.png | Bin 65907 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/newraids/cox.png delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/newraids/instancereloadhelper.png diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/newraids/cox.png b/runelite-client/src/main/resources/net/runelite/client/plugins/newraids/cox.png deleted file mode 100644 index c33cafc39fa2a4bcb0af08af48163f1a7c65d70c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2498 zcmV;z2|f0SP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D30Fx(K~z{rl~-GD zTvrwT&i%}NJTtzH?=endCvlv%iA+ROqynvis08ATOL?exK}Zl)0t7`uq)3rKB0m87 zf>MN3MMB~Qqyhz`HqEVy6LM?pu|1v{d#>lq%(y{`ap-4Xt**u)aFBQ7qs6?6aq?zWvv~J?DGgKU00lFYAr2@a|u(epjy;h2E4W zn$Y`wqP_U-PxGVs(br1F@|pMFyOt3-v0BH22#RHtPeizJnc zR@oe1PvK!d$qCNzQ65hciR)d;ivXLTdy}RdV-gq zIxqrAKHR{C)p0PhFp2(r7PVT90Ey_-O$_8SIC^pxoa)05Jki#@=lgTH%Z+O5v7&rz z7A!2z&NOPRKSeU~jNWd;G8{xx3gn24ZqtPC_;fG9vTeE#Ao3zUbz}mDWujWDBNq4!MC0fmKl{ZNX?*X+H=~E*zhGW99z3-wW~3b_L)#*3a5{ z=WCwpp)Z$2wOmJiRR^UPh9?FfN+KdL1)?A#nM@+!d_IQvO%p3OH_*|#kfS02 zuwfczp8WAzv-5T@#6t_W;LMpb%B4$}e&TuFlwlZwVHz)S9G5h@U5II5t6as@>^N4I z)}cgY*rp3vmB8~H1W|zJ`mnk-B!$FjyXYV9!`5m8>5(|JRSVH*gjjC>kL64I+{YiqAlP=V)pP(G7$o+brwe4^TSks64H0TTTYaIS=SUj)sX z21QX2iL2OHE@NOkiw8H>AjuN6N(Ztc!M8Y&-|%97nUQZlo6Wv9KR>~^6x^8%}NyG|G^ymu*IVQm690;5U*K5ZvUpfU|;6puFlmQcy<5*r|qBf z)%6fStJOlI(LmQQV3K3QFiA`XI-L%5O#?9oiNvU=N;sa4F-;4)-iFaN!XVV7s7^Fc zB{1xn`QKrK#iPaX0*T_M^nzzEB!R=^Km_}SQ@C+^6-k9dCIT$4R&Z=z7Gv26c$aE` zZHB*dqiL9W6KUDU?d1)awue@&iuuVjIMU6XF^BAI%On4v@?)^k7PmVTPP6(6% za6Q_8nxMkMRznZxGl4VTyeNf%*>kus7JvnO2uOyf=3nvP*Xqz09s8o}l=ABxCBAcXhUs!$}R`fdNr2+JeJQ@#fbVHkvfi4KY>5K#UI^E7JBhFe9zPqp{4{YORaq%{CUNQaTyj#!E-4ssau-9hzhYamWyF#G>Zdc8I)_3ru2<1nl6i5TwMIY z%F4jqX<>npI!82bt66P%-CxrpAL=44330kR(EYCLN^ zl>*iL6LV;Fn$X)iG-^;j$xqjGb^=0kQ$wd=FzOq0w0nhu|GVe@5!;o49UC0Weo2t{ zH?#XvF`iOXq5}pU2vFN-gkoa-zglX9De4n7>lS>}T-&P<&OZch&<;Ed$J5bVx<5gck(x_PV%xQSRLexeBRid(3$Eq=imKN4w5{&l zo}0(o6B+oZ#gdVO`2)FM8=5`O1)SE=%?ZkUE1p#iS&>`xPm9~E=&zbB`_ClE|2BX< z>=OalvGKX#qoOPn=tT6}q0s@gSSX*(45aJJORL4L^`_n%_Aw0j53G>Z)S}QmApigX M07*qoM6N<$g4~_2h5!Hn diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/newraids/instancereloadhelper.png b/runelite-client/src/main/resources/net/runelite/client/plugins/newraids/instancereloadhelper.png deleted file mode 100644 index 13109b4b2650546acc872b1dc738816180e2e723..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65907 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%0AK6;bSIv?H2gyklyr zO5~^bu@EASK7HW!r}dNc_4~JqjpM%Q#xosW18840oR?C-pk^2%IvtH3+zDMVsSH&N zngH_xpA&%m_-Bjzi`X(_Ipp}2T9^5%`k*~ zVHDq(GO#b}uGL{L$Q3fd<@W~uj&rDI%LcC`DBg`RKf1xwF(!1?b;AYID<=rHqYplPs`PsyrgdLp zj)`cV#czov^>Lqdb>?ZD<(sw}G7YCpNOO?<;vl6TTrwFO|8=hRMM?})y+F3H;rmpL zJF~AfYh5{Y#o!l;a4Rd;nQBc=+$WEupEpr4&^I@@x>y}-U!(4FDW4{eCa2S z9gh_kt?MadTIGH}FsK*#@zlGF+W`WLGaH1FOCz_q{O8jMFPa$V4B1}U#K0JhLW6LH zbSMraLn(ePRRx#{WJeR4+QO)J$1*Tvx1y)So;$ABOU-R)2PHVtE%3&0M(mZxAx7rJ zg*Gr$doOK<8{{eUkzOmn-K`3xU8w8CL~b>hO1Dr=gSV7h<-oB~Z7_F&qSyHsjyBVP zjrqyxNCP>~!F&ygfN)lPM^@ZWQ;t6a$&VW6WUqn@Mi_&x>m3~Qor-9XTu2h^;s4u( zOD?Jhh(czi7WS(yMV53uH0dq~n0e!<#{|muqZ3OH`oLSj5!2#bkO;QY6j392VsaBM za6T1!{kh*t>-Z_`_;wl2nWb62N_1~_+6nu0sCzKyvg%~~4~dkj_H#76wqIhyAg8)l zOG`iZW}?*b_r?a}eGyy+qRv||2jRN1oa3Q&m0U?Sb4O2^UBib?BI8!Er#QRX+ zoUQHT&}ZPb^CD_P2Qc6L1mq}Hv%X@xb>=U+;SW~(bC08oUP&l9DL)rg!wW9}Ef;|n zT(#_LYGCYY_Ecr`(S}svMRH`H53r@uh9uPAN(095jS=4=S@_Y>N3S1w2S1OP0r|X#(cVpd5D#{hF-Ufqd>??!tlxT0dor$-N23 z&V8Te`b56R==}tqf!FhmZc8)3pnvum36Cm_x$IoaB2Gqs#6_`00fc0sCw&a>RzDUp zTpAOoo_pOsV*%UAwUS{k2c=riM!&o~KDhI8sLD#t>y~W6*O8q=u7P4&@!KTH3}U7s zBzfWOxA_pAmU@yeCAv!LyVf~!gTx^o?Fbj^mT51J@d(uY{EjeG!*q2}N_H^zxga!b zr1xv7N_xl8{d#8DC|ejz0CIN+u#7bag#XT2msx_4nWeecq9*3@4ctH)Iip z(FG5iLi;FN>=i5)w^8fTr?W47dPm*vM0}IHCpu=t? z<@B+Bt99R6b>u@tm9n|ar#PPl#r98m7n3lpMC9H8|Mh8vZ~zNHF42t#%a{%qBS`!a z}aL#wcz%c<@$Sc(Fu;Cf5r#`IiTXo=% zG<%&ugj-!AYu^$M4wI-T<6?~pmRupF-fU})Plg7VOP&Y}Gcf1u7(3E%ED3Hi)_ zZSG9wE!?sekI1T3s>cFr>2})={kmCO{mnmKB)cn)DxD`L)k$uQkd>q!yU#Sx&&Cj* z=2H@`)xt|rMzz-j0(uS}#jz}9Y1|=|C2~f?9X*B^*|;%rRQ#dRrRFgCZY48)&a^-Q z>UXuy#N*4EApTteho)D3ldOQr#-_h5>sVOlJ%`~0pp8Y_-RAYoO>)$wsRpuI2g&Ud z5N4k$3)V^A@6o{@JIHh5JDo!l*|^r~UqCan6bd_5l8@mrrUZDiQy_!tiqrzn=PME! z1kOwHgI?KZ5}cQZY-cQvV?kS|7rW`lg@0>mCCzOL~Z&6RGS%_}YnO-kCb z8$0GRT#POe4yK*7!YDRYS0vIDk0vRr`+Nb(z1m@P%33R29BBz5+Vq-X(Ya8VHUf9M-8<^;M0$gw^-E3BW3TG z)*-NLPA;1fJCbW_Z#d(DputX++1x-1H1lUZ(|)kuz2iwHt{NJQE*v3g>Ad*U+3~m8 zkL54LsIFmrp==|3d@d2Juq5!2|4Mt~@Y>9oix{cXu~t!UBQZvbjOT7b-6ottLF7}V zEz1>eYx2!VN@By)&+il{hc8}TUQF?Q46C-@V%xU+e8a=!5)I#Q=|AgXe&fVbU`xQM z>=`R*&(58G51{(N%H*V#gz12ik&uZrP!mGKR!GJzgh&28Olns@5rUt*xx^0( z>z-a%T0eeBI(u(vD*$iX=?s59x;V-acED(0mr*TRbt0~ceYW2o?)ccE>?+?)w`Op^ zgPTSTNK?nFSX9ddp3#V5{$x}2*ve$Iy{^MN7hB7TVt-gXD$g>Zw$$lcPD)~0DArgc z2(bvhQd61IqVZ30LpXk*@@=0Sd#+P7yV@5M>0m;H z!%qfhK2qNK5J#*l8-IP_U5jjGJ81_wMT6p`U>CLreso|}%{{wlg29;E@DWg_2(hjj z@XoKmfEk~Jvz0Kcg?2VhjE?6>ooSdZGF*ozlLhSe2(78!7kx3A3r3QE75_6-P(2s5 zaw+-p%S7>2Pp`5=pBL4&oGZT7Mi7&_M#8#{0*11eB|!2AJaW5S0+j8I@J` zQxXz=(Nj%cw}=qMg8%jsLJG5ut{>v#u&^9=G;}|wG$dYAHB#G)tcS1ei1sRX+`T|4 z)fS9CcjS`Z#rhtW=Zm@ycaTo$Xu4tuF^|5iy;MW85(`*Sxf$d?UsWLkz0l1rLnfIN z3^Oec;wSv%Vlthbw!)UF^aS)IhDnN|q)IuZD1vnmOnu`|Q7U}~9DU;nctDMIz>JI^ z+pC#d>G$IF9kp5jU+RmXYN~-iyPe>*IK?hUj$AvM|2ub)xqxSErQX_uUy3tr^nTp! zUBNt1X_YgX1W9vQltet>HcW}xenCcF!(cE^1;iUkL_i8k6^9;M65CLfkkB7}yW~%n zFfYLGVFGg(7r3>3?y*}sb5NF34aMiAbuVHM7eRkpRDKiXpx#$q75e2W6txINPF;Nx z>bn2#_SMIZ?@v7D#W6t*{_bAo8pCVo3M0zQUNlHC3TBG=3B(vLK_EP!<>ujR(Q{aN zL3)Vlc)MZn0lwp*Y=H`Gg8uUYRWPJ(@%TZ41qTDb3KC)>Ad&zh*)(DnsLEnV$lS>y zCPE#^!le4lGYt&iD3$0jedFaUekSIaM}nX$wcFYELaq{>Pz6RVV-z>DEGt8TIp4DJ z1;Vhg{<~iQ;l5^Un0#x`x6mZ!!%IK8KH%G|YP<{!ZtmP767I{yK~d z$DAq5>J9RuyA9S910%#fo|ur|@5dZbILumXR}x8%h7y)nJ9v$gFJfojRHTK z-%RCm512uoYJTkajGQ-}`4IVd=v0C$Uu|KR@#_`*_$)Et^YIZsaqq3LgH5k_D<`>D ziR$&kK2CCExhx*w#z#~!lp(sDx(*v9$0uP08CTIBLhV|w*lW33HN^hhL$^l~ChK(! zDIwl-!YcBC>;U|Bbrm)$YOZIH8JAIU@{H%7R1!m3wgHu9L6{ZIGOPu_f429cz6<$u zkgJz^aUka{?;mx73PrS(7j$x+DC+DAG^`ZDuRpDP#CM$$gjPx>4~8rf*F7$ySRY?Q z(5=hCps`1ot0E6~cV7`+pywM<&wB2maH)95qEj&WmKr_DHGYM-&6b;yqCJSD}a!s zdGKq~Qad3yL>PX?f?ttWebnwQ1h1<3d+C?hk@A-^ln?sS5q;bH@Gilux(8Ktz8c1C z7}|eZjMHGmPXKDtzf;rLd%o`A5r@$)=0+j+M6MjYW9%5?2fShpUI_lVJ2P2fC_(g( z3f4X=0iKXz5FrEgj6CFxE})~YNg%{0?MY7g1Y@ zV#bpL(@2zbR~MhLdvQixUIdVJG_DdYwv4ZhecgjwcQN)$zSF)I&JgeXeoBU&nzMz9 zAFm}t1w~9OXH4tmfTm+N`@1NGd1hqqW2dB6k`)SqXi zXNczJoHP8`{JAXtA&&Do^MJK{g2?O)RxBJ;Rpu@nQc-xO7MG6~mv58J8SIBzH#%D` zJidR?ungzP!dQ%f>Y6^ydr~FY(TQJXQBdG{nMi@j(iIBAk#cQ1sW2Cv+vxP z{sHi8>hC(DZN`eD!JJ<*e(7*cz6+`2+YajcJRP6NNfq?|*_c}g1266SiR;)oR*|}V zF||%@!g?Cg_$@YP0O5~REJHew*^@u*JiZ#?1}Z{nCOJ;;-`_7e#eZ(tr@UOdD|K{z z$^NT{%<1^HHAF1*I>3?B<$#o%{52&g{EBF%l~@@5Xz05TEHIhiIHf7p#lrkg8pGd# zzi&g*k+d|h%;ks5)ttq-IENBqwI{lAMB59Y>c1Cc6;Vp_mlcn;MRh*xLrljF9LDmt za~KU=+=9OmC%+fc`c|Iu9I_tIva#pNoSQfN6kxf4P8A@?g)3@ai; z$ilzz!Sw!-N>F_4P*KI<0@^JYXKw=_ul@;zREb|N-)jw`45c(|8Stuuh^~GJ#Obo2 z`&1yxA{-VmjM0j{_6K(L_89xhrQv(A!?-e>kqkchk^N4BFcGypCx_gfn>>b|cAxIE zbME6!=hegLzO^K(ozgrR%V=7;_MAHcAw1$dF#ae28!J;t^4Dc{oF=;C{*!}Z^#H@3 zYXR?*fo#zNN^;2gP6jE-@H`j@qqAjS+iW>dsYk#lD2)3%?d_WUCt&;-FsI zJ_;IB1eaxZR03qB01NZ@NxyBm>bn zbNwZuP~fQrSVn#L;v8~}F5rHdF|)-|dyAls|2f~c_`QNGl&5FOg2r;&>vQmgCO&}T z4--QhgkXjGkrqEGo>GDTsL8g}EJ!d-YB6PHwHHEQLmYlO*nc9y`B_lU((za2oSWiC zDCM#a<74XqI-*oR)FJ)2ayCtHSB!1Pr`GDZ-K77$US{$#65@my!t6OoQDHn(#0-X` zRt{b7NX#}#1q|Q|77qi7HK9Rn&qnP3J}Qtq=S~2r?Sv0-R5(zPInt$b6Na-8`zc`( zrKoE91&N43=`!c#*L^M8rE}G=dCes;X{ zCY~Lx<#DT2+ul03&Lr{>jMJoU`;2WC{od`)A0d%W6;+td9YLiN8$~lL5s}IgB@uCr ze`E6bEE)qsH>6W_Q`zd^dQJ{*LOoQfkRFMMl~OY9^(TLC7fx$0=G+l^L5I23mjTTO zZCf9F4?@P<4&fip_Zp^)T7MP1MQI3d?Bmsg?G?L`*t+3ukA6m8I|sHBoC9 zg_hF-U$Kv}u9SYg`Ewp*1hw9^BckU*K!D{JzW9nu3vclK6Il%pq?kB^<;nDWr{(Xm zJAF%sgw~3A^MLzPdrTswpV-HI5z-PNIg#2j2&h8x)7p_~8Ic+Gv1>JGs?k-_5jLoI zVCvL&vvV%rR5Z%mM*y;UsrQ|h;!fW1goq?7Gx8uZW&}0KoHpRry#{A7ZwXgBmNZc6 z&!xJB_4|-k)8ov?y#JyBU=c(OGu5ZE*&(bku_zD&A5ezV9}BL;bVM{Y3q34(Cd|go zC6!k1`6@e`N_$;=T`Rqk>YbaXB_sZtR9|HFd>Bjt{D;3L++~waD_r+oPJ{L9C)6)1 z-(eS>w}mn$eq1eu9i1C|OFO%B>|%nyF1Gt<^CXL2LR)*WYizYWCV$(T3)2yG8?+m< zq>hf{>nI5pFM{J%s^mK;S7p=>KUE|Qrxz)86~93Gy}xVs8IuQ=?d>-S($HFHmody$ zn~Khsjx-mt^oOKi{dkom{Uao>7x|3r$@7|rRFgJ%K9?3*dcj*o(VfmqmHK|)L(9kC zF57l3)4a5+szV$AFmQCY1(cqh>G)1d@MKmPuRL|&?-AECF$4o)J~XNaDs2{;RAw!)1rY z)o)^MxB*+n8j@u*+XWVf-9J6w7?6ccL-LlYADp!dO`(t2COo5k`%k)MyE{?QFV{2P z<(YLa=^p(!1BlINw>>zJUnI(w#CKD5F(eTI<`EfOFF$d$ZZ9DYh{JQ_gx)`84ZDcw zRt{_ZHnn82KJcNZ5&lCAk@3Q7Y2eY!DI}lIV3F5FnDd=HYUghzLtFnQ<0oy((kWE` z->2r-rS9VJP2_eXIbYL#uSUwBzoaYG5593vc$>xJaRFQ)TfJqwM4r~}%f)UtFX&i7 z4ytrlfgJyR1gjnKR*dR$f87i+1A?P7jSEEbDG|M@>NKTuy|~j$M`iq%&_t4Jr!vNe z@r*_dEog03uc(~E`@`6Xd;HE(mF1nHEhQAue#X)F#fKFGnV(4bXbG*-*!BBV|6Ci8 zJVAf-tzFj+)r2|yC5+yGxN`>MLmwkT2lz}rn5XETqRUOZC1|kI=Le<>)6nMTq%RtK zU%u2A*$-r<|7Qe*#313sn$&wN-rs5#?5VbEwhbxmA6j3!Z6AoPp z%;!6KgE#$9MeO+6EHu>dG(;^-*}S;=_GJ90t? z%CIw^fY&1D^9;l?O$F)~o_u!PD4LydbLFiqr=hhHl5#d?!S%k@#!yj5G zgWO&Ng6`=HjIh}|k@>9CwN`N_JwbuxzlDS;)2yM`o34Aoq+Vewt7hn2+$@5HKX_Dr z!598!34wP}e9)vSn18UXsV2sFGmF6jmU4=s{<}}AH@~j(WLGO;MeJYpI*lZ~@7IzB zSXgD-cwe=K)Awo|$%*yQ+wQd#VH;n!@$CZ5EbT@koMB^pD}#^g&&@P{$VgMg^;?Px zZSghVqL9ZIw<$6kfmrGT%1c$0ZPAk3YISfp7xw7@qN{oVnVO4+7RFF-w4mIVwvx#UzA4RpygL*|6EuV^a<1_a7WCJb@*v|)a-4{| zdPnA-Qg{9(J@h-`7}<Nm>#+=iBSxHj*%RnKG)1U^8T7{Q*oA!A8Ob$ejKZ(N^d*piW91LUU0 zYHsBnie)!NLRnqxtGMLGJ+nc-_05yK&wO3S|%+@_%kuhUmF)S@Zba^TMefH8K2O0u_ zIcUikO}iEI6wt8X=K8C0Xi72xl0C*QhX z3Nu`##IY``Uq0wIpus1lZcjX!jUjtBTz4CwtF9N1F4?MihhAGc=2{pqyGyk1Y8USo zJ<7hi#d2)@6IhML2Z(@~Me+ij)B=tIx7e`Uu2**tOnkvQ`A-8dJbR~omIhn`KcQ||f&SUo5&Y8;t{*Z#vS{nFg`oV`VxVM`leA%` zJJx*eO$~qI@(tX_I?}W(l%oCL-|}tf3}q2~{0w$&+&mA+X;QCJ*$Uh}%$?Vi$id}A)u^Sd2X8wT@!JWG2FS0z|SE_Cs>DtQU^H%sZi@xxC> znEE^~Xs_KhJ@N_!0ScIzCnJ#7CqE#d*Z)AH;oo?{uB6;Gtqer#K|P5ZE)LdvT316{ zgfaT@JE^Vflrbx%rc^O;Y*};Q^5@)ph|#&H)^0Q3K*HC)-lGiOQilO=9wM!Y80u~s zrpGl4>-P|^u@Pt0E>oBCwP&$X-Q&f({}~)W+h#=8~v~{ z4L_q$grw^PsZ9+Cfl+rM zAYr;Tab0qM=OYj2u9oJGccZf4eTFjwYNDh0wS5~oOp`-C>q?D#tFWSatO8f#C#1#q zPEjqdyOxEIaGmJ&pCR1G)lwhgC;M;zV&}~bgyX-QWr>H{8x%8 zC_-(d_AY6SE+>^>55H)4FrE9J*W%um9MEaa4GuiP|3d;Y3V&j}htT){%U7c!x(Hgk zv-+40yz-(ddVo=oM2Cbl_LM=4c=p>Pyjg3S!M=erV<-Al<>l9Wl68-m=WCq0y_L|g!} zX_4HL7o2^v5gtp$MbAS2kx0>^;QrfB^PCAy(8&4QVy232*P#aDb4K@feJjSV z#i%f9MWJWBD^TmL1XHd22gT@7=A#SzV|+nvz@B1xKT6tEb;r-BxZ_8luad_{)r#P` z+orRpsa4~g#4GVDjq-mZg&=t4HsqHU-5>45ymrMHC*ye)jbP=)68B{u%Nf}ikMkl1 z2$%PDKqE4F4i7Y4IQw(AE;GsFzV0Rc3XYE0a}kUgI4$3{?HKpDdZU*6q^Mdm<&y8V zb<8ZNLF$`+iETyymL_Ts`{U7c>ts>WqilSD4OrHD39ehy5hXg4F>V0A0`as>ED3=# zR~3T=hm@E-RS}#9tn6W*SFSTu=pg7}Q9xaDfY0k)FrW6NH;>!UmCoRoGG0*vV5@&< zt}~_d^^Ivt%{{+#s*pPIPt+Loi$Knh4iAi%Kid$T2kr71f*{`s0v}8*9dg6(&;&wh zi{Jnr;QuKC8HA_Li!M>j=MQp;Ly9`uhlsXm2@%x`pR#zrb~UZ{CaQ{he>bug9sbU} z*YJrRlYdqezc_cLc)Y(S=rTo>N2siIutrM!N5*09i+sG_a&hvBPFC`A96uGDuxkD& zSH7F-f%(&Y2$nus*=Tl?==eXk9iqXzFKIvArX4M6Ph|2ps+o^aEVjyBwU^({9cQMR>iD~3|#oPU5UrSNRCdN^=Ix3=ff0e(7U)wHhk?$ zG~v&IRfVMPQ?IDojn~`oi-YpuyI9X4?WOp|H;EVjIVdfVUH2eXwP1jL`IT|oCP}g& zp$DhEcjnRkkHmqDhvIT%1BztTQ0cAj62##vAGWs~<~LvwpH9c~b694HQcm!oi?S-x zFEA+Jb-RJAAlF|(hJ|Yxk6T;gB7`vtCVFyF5#bd(AOGWxKnN8S00A(F2RHbE4akB_ z2;|V$X%pRPxoP~|Wb}Q-6yn9OpqxbbRZGns0Y+Q0rc*Xr$^d`3^1|J(TY;uDm=Xc| zi?YGbRemiTJxwbYPiHWH{goVP-w&wwoc8=9O3CPGFehFxPVcz0GhKwPuRL&`aJC2_WQTWR*o~0#9t_sD{|WQ zZ3^mwMD_Jm+gTN&ni?)TycBn~f5^~F2?Kym(U$}yDc}Dd=+T}v2mf32aV6__?|67)wL*6-@HC4Mq7*tp|aAS#qJn6h{{{OxJkpH^^ xT>rZv|98U~{QrIafBo_Q%d?jEyRZaIKqDce?Pl5gkN^ECZ4G_(DpmWi{|7te{-yu`