From 023860f928bac02a9b6006bffdd147aca1f9d9b8 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 13 Mar 2020 18:55:50 -0400 Subject: [PATCH] client: add dps plugin Co-authored-by: Max Weber --- .../client/plugins/dpscounter/DpsConfig.java | 55 ++++ .../plugins/dpscounter/DpsCounterPlugin.java | 293 ++++++++++++++++++ .../client/plugins/dpscounter/DpsMember.java | 99 ++++++ .../client/plugins/dpscounter/DpsOverlay.java | 167 ++++++++++ .../client/plugins/dpscounter/DpsUpdate.java | 36 +++ 5 files changed, 650 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsConfig.java new file mode 100644 index 0000000000..5720f57016 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsConfig.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 Adam + * 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.dpscounter; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("dpscounter") +public interface DpsConfig extends Config +{ + @ConfigItem( + position = 0, + keyName = "showDamage", + name = "Show damage", + description = "Show total damage instead of DPS" + ) + default boolean showDamage() + { + return false; + } + + @ConfigItem( + position = 1, + keyName = "autopause", + name = "Auto pause", + description = "Pause the DPS tracker when a boss dies" + ) + default boolean autopause() + { + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java new file mode 100644 index 0000000000..186c52d561 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2020 Adam + * 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.dpscounter; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Provides; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.Hitsplat; +import net.runelite.api.NPC; +import static net.runelite.api.NpcID.*; +import net.runelite.api.Player; +import net.runelite.api.events.HitsplatApplied; +import net.runelite.api.events.NpcDespawned; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.OverlayMenuClicked; +import net.runelite.client.events.PartyChanged; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ws.PartyMember; +import net.runelite.client.ws.PartyService; +import net.runelite.client.ws.WSClient; + +@PluginDescriptor( + name = "DPS Counter", + description = "Counts damage (per second) by a party", + enabledByDefault = false +) +@Slf4j +public class DpsCounterPlugin extends Plugin +{ + private static final ImmutableSet BOSSES = ImmutableSet.of( + ABYSSAL_SIRE, ABYSSAL_SIRE_5887, ABYSSAL_SIRE_5888, ABYSSAL_SIRE_5889, ABYSSAL_SIRE_5890, ABYSSAL_SIRE_5891, ABYSSAL_SIRE_5908, + CALLISTO, CALLISTO_6609, + CERBERUS, CERBERUS_5863, CERBERUS_5866, + CHAOS_ELEMENTAL, CHAOS_ELEMENTAL_6505, + CORPOREAL_BEAST, + GENERAL_GRAARDOR, GENERAL_GRAARDOR_6494, + GIANT_MOLE, GIANT_MOLE_6499, + KALPHITE_QUEEN, KALPHITE_QUEEN_963, KALPHITE_QUEEN_965, KALPHITE_QUEEN_4303, KALPHITE_QUEEN_4304, KALPHITE_QUEEN_6500, KALPHITE_QUEEN_6501, + KING_BLACK_DRAGON, KING_BLACK_DRAGON_2642, KING_BLACK_DRAGON_6502, + KRIL_TSUTSAROTH, KRIL_TSUTSAROTH_6495, + SARACHNIS, + VENENATIS, VENENATIS_6610, + VETION, VETION_REBORN, + + // ToB + THE_MAIDEN_OF_SUGADINTI, THE_MAIDEN_OF_SUGADINTI_8361, THE_MAIDEN_OF_SUGADINTI_8362, THE_MAIDEN_OF_SUGADINTI_8363, THE_MAIDEN_OF_SUGADINTI_8364, THE_MAIDEN_OF_SUGADINTI_8365, + PESTILENT_BLOAT, + NYLOCAS_VASILIAS, NYLOCAS_VASILIAS_8355, NYLOCAS_VASILIAS_8356, NYLOCAS_VASILIAS_8357, + SOTETSEG, SOTETSEG_8388, + XARPUS_8340, XARPUS_8341, + VERZIK_VITUR_8370, + VERZIK_VITUR_8372, + VERZIK_VITUR_8374, + + // CoX + TEKTON, TEKTON_7541, TEKTON_7542, TEKTON_ENRAGED, TEKTON_ENRAGED_7544, TEKTON_7545, + VESPULA, VESPULA_7531, VESPULA_7532, ABYSSAL_PORTAL, + VANGUARD, VANGUARD_7526, VANGUARD_7527, VANGUARD_7528, VANGUARD_7529, + GREAT_OLM, GREAT_OLM_LEFT_CLAW, GREAT_OLM_RIGHT_CLAW_7553, GREAT_OLM_7554, GREAT_OLM_LEFT_CLAW_7555, + DEATHLY_RANGER, DEATHLY_MAGE, + MUTTADILE, MUTTADILE_7562, MUTTADILE_7563, + VASA_NISTIRIO, VASA_NISTIRIO_7567, + GUARDIAN, GUARDIAN_7570, GUARDIAN_7571, GUARDIAN_7572, + LIZARDMAN_SHAMAN_7573, LIZARDMAN_SHAMAN_7574, + ICE_DEMON, ICE_DEMON_7585, + SKELETAL_MYSTIC, SKELETAL_MYSTIC_7605, SKELETAL_MYSTIC_7606, + + THE_NIGHTMARE, THE_NIGHTMARE_9426, THE_NIGHTMARE_9427, THE_NIGHTMARE_9428, THE_NIGHTMARE_9429, THE_NIGHTMARE_9430, THE_NIGHTMARE_9431, THE_NIGHTMARE_9432, THE_NIGHTMARE_9433 + ); + + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private PartyService partyService; + + @Inject + private WSClient wsClient; + + @Inject + private DpsOverlay dpsOverlay; + + @Inject + private DpsConfig dpsConfig; + + @Getter(AccessLevel.PACKAGE) + private final Map members = new ConcurrentHashMap<>(); + @Getter(AccessLevel.PACKAGE) + private final DpsMember total = new DpsMember("Total"); + + @Provides + DpsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(DpsConfig.class); + } + + @Override + protected void startUp() + { + total.reset(); + overlayManager.add(dpsOverlay); + wsClient.registerMessage(DpsUpdate.class); + } + + @Override + protected void shutDown() + { + wsClient.unregisterMessage(DpsUpdate.class); + overlayManager.remove(dpsOverlay); + members.clear(); + } + + @Subscribe + public void onPartyChanged(PartyChanged partyChanged) + { + members.clear(); + } + + @Subscribe + public void onHitsplatApplied(HitsplatApplied hitsplatApplied) + { + Player player = client.getLocalPlayer(); + Actor actor = hitsplatApplied.getActor(); + if (!(actor instanceof NPC)) + { + return; + } + + Hitsplat hitsplat = hitsplatApplied.getHitsplat(); + + switch (hitsplat.getHitsplatType()) + { + case DAMAGE_ME: + int hit = hitsplat.getAmount(); + // Update local member + PartyMember localMember = partyService.getLocalMember(); + // If not in a party, user local player name + final String name = localMember == null ? player.getName() : localMember.getName(); + DpsMember dpsMember = members.computeIfAbsent(name, DpsMember::new); + dpsMember.addDamage(hit); + + // broadcast damage + if (localMember != null) + { + final DpsUpdate specialCounterUpdate = new DpsUpdate(hit); + specialCounterUpdate.setMemberId(localMember.getMemberId()); + wsClient.send(specialCounterUpdate); + } + // apply to total + break; + case DAMAGE_OTHER: + final int npcId = ((NPC) actor).getId(); + boolean isBoss = BOSSES.contains(npcId); + if (actor != player.getInteracting() && !isBoss) + { + // only track damage to npcs we are attacking, or is a nearby common boss + return; + } + // apply to total + break; + default: + return; + } + + unpause(); + total.addDamage(hitsplat.getAmount()); + } + + @Subscribe + public void onDpsUpdate(DpsUpdate dpsUpdate) + { + if (partyService.getLocalMember().getMemberId().equals(dpsUpdate.getMemberId())) + { + return; + } + + String name = partyService.getMemberById(dpsUpdate.getMemberId()).getName(); + if (name == null) + { + return; + } + + unpause(); + + DpsMember dpsMember = members.computeIfAbsent(name, DpsMember::new); + dpsMember.addDamage(dpsUpdate.getHit()); + } + + @Subscribe + public void onOverlayMenuClicked(OverlayMenuClicked event) + { + if (event.getEntry() == DpsOverlay.RESET_ENTRY) + { + members.clear(); + total.reset(); + } + else if (event.getEntry() == DpsOverlay.UNPAUSE_ENTRY) + { + unpause(); + } + else if (event.getEntry() == DpsOverlay.PAUSE_ENTRY) + { + pause(); + } + } + + @Subscribe + public void onNpcDespawned(NpcDespawned npcDespawned) + { + NPC npc = npcDespawned.getNpc(); + + if (npc.isDead() && BOSSES.contains(npc.getId())) + { + log.debug("Boss has died!"); + + if (dpsConfig.autopause()) + { + pause(); + } + } + } + + private void pause() + { + if (total.isPaused()) + { + return; + } + + log.debug("Pausing"); + + for (DpsMember dpsMember : members.values()) + { + dpsMember.pause(); + } + total.pause(); + + dpsOverlay.setPaused(true); + } + + private void unpause() + { + if (!total.isPaused()) + { + return; + } + + log.debug("Unpausing"); + + for (DpsMember dpsMember : members.values()) + { + dpsMember.unpause(); + } + total.unpause(); + + dpsOverlay.setPaused(false); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java new file mode 100644 index 0000000000..e35bbedbd2 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 Adam + * 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.dpscounter; + +import java.time.Duration; +import java.time.Instant; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +class DpsMember +{ + private final String name; + private Instant start; + private Instant end; + private int damage; + + void addDamage(int amount) + { + if (start == null) + { + start = Instant.now(); + } + + damage += amount; + } + + float getDps() + { + if (start == null) + { + return 0; + } + + Instant now = end == null ? Instant.now() : end; + int diff = (int) (now.toEpochMilli() - start.toEpochMilli()) / 1000; + if (diff == 0) + { + return 0; + } + + return (float) damage / (float) diff; + } + + void pause() + { + end = Instant.now(); + } + + boolean isPaused() + { + return start == null || end != null; + } + + void unpause() + { + if (end == null) + { + return; + } + + start = start.plus(Duration.between(end, Instant.now())); + end = null; + } + + void reset() + { + damage = 0; + start = end = Instant.now(); + } + + Duration elapsed() + { + return Duration.between(start, end == null ? Instant.now() : end); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java new file mode 100644 index 0000000000..44b31c481c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020 Adam + * 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.dpscounter; + +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.text.DecimalFormat; +import java.time.Duration; +import java.util.Map; +import javax.inject.Inject; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY; +import net.runelite.api.Player; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayMenuEntry; +import net.runelite.client.ui.overlay.components.ComponentConstants; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; +import net.runelite.client.ui.overlay.tooltip.Tooltip; +import net.runelite.client.ui.overlay.tooltip.TooltipManager; +import net.runelite.client.util.QuantityFormatter; +import net.runelite.client.ws.PartyService; + +class DpsOverlay extends Overlay +{ + private static final DecimalFormat DPS_FORMAT = new DecimalFormat("#0.0"); + private static final int PANEL_WIDTH_OFFSET = 10; // assumes 8 for panel component border + 2px between left and right + + static final OverlayMenuEntry RESET_ENTRY = new OverlayMenuEntry(RUNELITE_OVERLAY, "Reset", "DPS counter"); + static final OverlayMenuEntry PAUSE_ENTRY = new OverlayMenuEntry(RUNELITE_OVERLAY, "Pause", "DPS counter"); + static final OverlayMenuEntry UNPAUSE_ENTRY = new OverlayMenuEntry(RUNELITE_OVERLAY, "Unpause", "DPS counter"); + + private final DpsCounterPlugin dpsCounterPlugin; + private final DpsConfig dpsConfig; + private final PartyService partyService; + private final Client client; + private final TooltipManager tooltipManager; + + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + DpsOverlay(DpsCounterPlugin dpsCounterPlugin, DpsConfig dpsConfig, PartyService partyService, Client client, + TooltipManager tooltipManager) + { + super(dpsCounterPlugin); + this.dpsCounterPlugin = dpsCounterPlugin; + this.dpsConfig = dpsConfig; + this.partyService = partyService; + this.client = client; + this.tooltipManager = tooltipManager; + getMenuEntries().add(RESET_ENTRY); + setPaused(false); + } + + @Override + public void onMouseOver() + { + DpsMember total = dpsCounterPlugin.getTotal(); + Duration elapsed = total.elapsed(); + long s = elapsed.getSeconds(); + String format; + if (s >= 3600) + { + format = String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60)); + } + else + { + format = String.format("%d:%02d", s / 60, (s % 60)); + } + tooltipManager.add(new Tooltip("Elapsed time: " + format)); + } + + @Override + public Dimension render(Graphics2D graphics) + { + Map dpsMembers = dpsCounterPlugin.getMembers(); + if (dpsMembers.isEmpty()) + { + return null; + } + + boolean inParty = !partyService.getMembers().isEmpty(); + boolean showDamage = dpsConfig.showDamage(); + DpsMember total = dpsCounterPlugin.getTotal(); + boolean paused = total.isPaused(); + + panelComponent.getChildren().clear(); + + final String title = (inParty ? "Party " : "") + (showDamage ? "Damage" : "DPS") + (paused ? " (paused)" : ""); + panelComponent.getChildren().add( + TitleComponent.builder() + .text(title) + .build()); + + int maxWidth = ComponentConstants.STANDARD_WIDTH; + FontMetrics fontMetrics = graphics.getFontMetrics(); + + for (DpsMember dpsMember : dpsMembers.values()) + { + String left = dpsMember.getName(); + String right = showDamage ? QuantityFormatter.formatNumber(dpsMember.getDamage()) : DPS_FORMAT.format(dpsMember.getDps()); + maxWidth = Math.max(maxWidth, fontMetrics.stringWidth(left) + fontMetrics.stringWidth(right)); + panelComponent.getChildren().add( + LineComponent.builder() + .left(left) + .right(right) + .build()); + } + + panelComponent.setPreferredSize(new Dimension(maxWidth + PANEL_WIDTH_OFFSET, 0)); + + if (!inParty) + { + Player player = client.getLocalPlayer(); + if (player.getName() != null) + { + DpsMember self = dpsMembers.get(player.getName()); + + if (self != null && total.getDamage() > self.getDamage()) + { + panelComponent.getChildren().add( + LineComponent.builder() + .left(total.getName()) + .right(showDamage ? Integer.toString(total.getDamage()) : DPS_FORMAT.format(total.getDps())) + .build()); + } + } + } + + return panelComponent.render(graphics); + } + + void setPaused(boolean paused) + { + OverlayMenuEntry remove = paused ? PAUSE_ENTRY : UNPAUSE_ENTRY; + OverlayMenuEntry add = paused ? UNPAUSE_ENTRY : PAUSE_ENTRY; + getMenuEntries().remove(remove); + if (!getMenuEntries().contains(add)) + { + getMenuEntries().add(add); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java new file mode 100644 index 0000000000..81e5859b38 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 Adam + * 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.dpscounter; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import net.runelite.http.api.ws.messages.party.PartyMemberMessage; + +@Value +@EqualsAndHashCode(callSuper = true) +public class DpsUpdate extends PartyMemberMessage +{ + private int hit; +}