oops
This commit is contained in:
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Adam <Adam@sigterm.info>
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,293 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Adam <Adam@sigterm.info>
|
|
||||||
* 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<Integer> 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<String, DpsMember> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Adam <Adam@sigterm.info>
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Adam <Adam@sigterm.info>
|
|
||||||
* 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<String, DpsMember> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Adam <Adam@sigterm.info>
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020, Jake Wilson <https://github.com/jakewilson>
|
|
||||||
* 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.timetracking;
|
|
||||||
|
|
||||||
public enum SortOrder
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
ASC,
|
|
||||||
DESC
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020, Adam <Adam@sigterm.info>
|
|
||||||
* 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.keyremapping;
|
|
||||||
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.testing.fieldbinder.Bind;
|
|
||||||
import com.google.inject.testing.fieldbinder.BoundFieldModule;
|
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import net.runelite.api.Client;
|
|
||||||
import net.runelite.api.GameState;
|
|
||||||
import net.runelite.client.config.ModifierlessKeybind;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
|
||||||
public class KeyRemappingListenerTest
|
|
||||||
{
|
|
||||||
@Inject
|
|
||||||
private KeyRemappingListener keyRemappingListener;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
@Bind
|
|
||||||
private Client client;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
@Bind
|
|
||||||
private KeyRemappingPlugin keyRemappingPlugin;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
@Bind
|
|
||||||
private KeyRemappingConfig keyRemappingConfig;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp()
|
|
||||||
{
|
|
||||||
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
|
|
||||||
|
|
||||||
when(client.getGameState()).thenReturn(GameState.LOGGED_IN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTypingStateChange()
|
|
||||||
{
|
|
||||||
when(keyRemappingConfig.cameraRemap()).thenReturn(true);
|
|
||||||
when(keyRemappingConfig.up()).thenReturn(new ModifierlessKeybind(KeyEvent.VK_W, 0));
|
|
||||||
when(keyRemappingConfig.down()).thenReturn(new ModifierlessKeybind(KeyEvent.VK_S, 0));
|
|
||||||
when(keyRemappingConfig.left()).thenReturn(new ModifierlessKeybind(KeyEvent.VK_A, 0));
|
|
||||||
when(keyRemappingConfig.right()).thenReturn(new ModifierlessKeybind(KeyEvent.VK_D, 0));
|
|
||||||
|
|
||||||
when(keyRemappingPlugin.chatboxFocused()).thenReturn(true);
|
|
||||||
KeyEvent event = mock(KeyEvent.class);
|
|
||||||
when(event.getKeyCode()).thenReturn(KeyEvent.VK_D);
|
|
||||||
when(event.getExtendedKeyCode()).thenReturn(KeyEvent.VK_D); // for keybind matches()
|
|
||||||
keyRemappingListener.keyPressed(event);
|
|
||||||
verify(event).setKeyCode(KeyEvent.VK_RIGHT);
|
|
||||||
|
|
||||||
// with the plugin now in typing mode, previously pressed and remapped keys should still be mapped
|
|
||||||
// on key release regardless
|
|
||||||
when(keyRemappingPlugin.isTyping()).thenReturn(true);
|
|
||||||
event = mock(KeyEvent.class);
|
|
||||||
when(event.getKeyCode()).thenReturn(KeyEvent.VK_D);
|
|
||||||
keyRemappingListener.keyReleased(event);
|
|
||||||
verify(event).setKeyCode(KeyEvent.VK_RIGHT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user