Added pvp deaths to loottracking plugin.

Signed-off-by: PKLite <stonewall@pklite.xyz>
This commit is contained in:
PKLite
2019-06-06 23:57:10 -04:00
parent 79ed69ccdf
commit 0d0bccada5
4 changed files with 175 additions and 53 deletions

View File

@@ -29,5 +29,6 @@ public enum LootRecordType
NPC,
PLAYER,
EVENT,
DEATH,
UNKNOWN
}

View File

@@ -229,7 +229,7 @@ class LootTrackerBox extends JPanel
}
}
if (quantity > 0)
if (quantity != 0)
{
int newQuantity = entry.getQuantity() + quantity;
long pricePerItem = entry.getPrice() == 0 ? 0 : (entry.getPrice() / entry.getQuantity());
@@ -263,7 +263,7 @@ class LootTrackerBox extends JPanel
imageLabel.setVerticalAlignment(SwingConstants.CENTER);
imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
AsyncBufferedImage itemImage = itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1);
AsyncBufferedImage itemImage = itemManager.getImage(item.getId(), Math.abs(item.getQuantity()), Math.abs(item.getQuantity()) > 1);
if (item.isIgnored())
{

View File

@@ -27,6 +27,7 @@ package net.runelite.client.plugins.loottracker;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multiset;
import com.google.common.collect.Multisets;
import com.google.inject.Provides;
@@ -58,10 +59,13 @@ import net.runelite.api.ItemContainer;
import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.SpriteID;
import net.runelite.api.Varbits;
import net.runelite.api.WorldType;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.LocalPlayerDeath;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.WidgetID;
import net.runelite.client.account.AccountSession;
@@ -116,6 +120,16 @@ public class LootTrackerPlugin extends Plugin
11573, "Crystal Chest"
);
// Player death handling
private static final String PLAYER_DEATH_MESSAGE = "Oh dear, you are dead!";
private static final Set<Integer> RESPAWN_REGIONS = ImmutableSet.of(
12850, // Lumbridge
11828, // Falador
12342, // Edgeville
11062 // Camelot
);
private boolean pvpDeath = false;
@Inject
private ClientToolbar clientToolbar;
@@ -151,6 +165,7 @@ public class LootTrackerPlugin extends Plugin
private Multiset<Integer> inventorySnapshot;
@Getter(AccessLevel.PACKAGE)
private LootTrackerClient lootTrackerClient;
@@ -209,6 +224,16 @@ public class LootTrackerPlugin extends Plugin
lootTrackerClient = null;
}
@Subscribe
public void onLocalPlayerDeath(LocalPlayerDeath event)
{
if (client.getVar(Varbits.IN_WILDERNESS) == 1 || WorldType.isPvpWorld(client.getWorldType()))
{
deathInventorySnapshot();
pvpDeath = true;
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
@@ -416,6 +441,34 @@ public class LootTrackerPlugin extends Plugin
final String message = event.getMessage();
if (message.equals(PLAYER_DEATH_MESSAGE))
{
ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
if (inventorySnapshot != null)
{
Multiset<Integer> currentInventory = HashMultiset.create();
if (inventory != null)
{
Arrays.stream(client.getItemContainer(InventoryID.INVENTORY).getItems())
.forEach(item -> currentInventory.add(item.getId(), item.getQuantity()));
}
final Multiset<Integer> diff = Multisets.difference(inventorySnapshot, currentInventory);
log.info(inventorySnapshot.toString());
log.info(currentInventory.toString());
log.info(diff.toString());
List<ItemStack> itemsLost = diff.entrySet().stream()
.map(e -> new ItemStack(e.getElement(), (-1 * e.getCount()), client.getLocalPlayer().getLocalLocation()))
.collect(Collectors.toList());
final LootTrackerItem[] entries = buildEntries(stack(itemsLost));
SwingUtilities.invokeLater(() -> panel.add("Death: " + client.getLocalPlayer().getName(),
client.getLocalPlayer().getCombatLevel(), entries));
}
}
if (message.equals(CHEST_LOOTED_MESSAGE))
{
final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
@@ -470,6 +523,50 @@ public class LootTrackerPlugin extends Plugin
@Subscribe
public void onItemContainerChanged(ItemContainerChanged event)
{
final ItemContainer itemContainer = event.getItemContainer();
if (pvpDeath && RESPAWN_REGIONS.contains(client.getLocalPlayer().getWorldLocation().getRegionID()))
{
Multiset snapshot = HashMultiset.create();
snapshot = inventorySnapshot;
deathInventorySnapshot();
if (inventorySnapshot != snapshot)
{
inventorySnapshot = snapshot;
ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
if (inventorySnapshot != null)
{
Multiset<Integer> currentInventory = HashMultiset.create();
if (inventory != null)
{
Arrays.stream(client.getItemContainer(InventoryID.INVENTORY).getItems())
.forEach(item -> currentInventory.add(item.getId(), item.getQuantity()));
}
final Multiset<Integer> diff = Multisets.difference(inventorySnapshot, currentInventory);
List<ItemStack> itemsLost = diff.entrySet().stream()
.map(e -> new ItemStack(e.getElement(), (-1 * e.getCount()), client.getLocalPlayer().getLocalLocation()))
.collect(Collectors.toList());
final LootTrackerItem[] entries = buildEntries(stack(itemsLost));
String name = "Death: " + client.getLocalPlayer().getName();
SwingUtilities.invokeLater(() -> panel.add(name,
client.getLocalPlayer().getCombatLevel(), entries));
if (lootTrackerClient != null && config.saveLoot())
{
LootRecord lootRecord = new LootRecord(name, LootRecordType.DEATH, toGameItems(itemsLost),
Instant.now());
lootTrackerClient.submit(lootRecord);
}
pvpDeath = false;
inventorySnapshot = null;
}
}
}
if (eventType != null && (CHEST_EVENT_TYPES.containsValue(eventType) || HERBIBOR_EVENT.equals(eventType)))
{
if (event.getItemContainer() != client.getItemContainer(InventoryID.INVENTORY))
@@ -482,6 +579,28 @@ public class LootTrackerPlugin extends Plugin
}
}
/**
* Takes a snapshot of the local player's inventory and equipment right before respawn.
*/
private void deathInventorySnapshot()
{
final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);
inventorySnapshot = HashMultiset.create();
if (inventory != null)
{
Arrays.stream(inventory.getItems())
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
}
if (equipment != null)
{
Arrays.stream(equipment.getItems())
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
}
}
private void takeInventorySnapshot()
{
final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY);

View File

@@ -1,52 +1,54 @@
/*
* Copyright (c) 2018, Psikoi <https://github.com/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.loottracker;
import lombok.Value;
@Value
class LootTrackerRecord
{
private final String title;
private final String subTitle;
private final LootTrackerItem[] items;
private final long timestamp;
/**
* Checks if this record matches specified id
*
* @param id other record id
* @return true if match is made
*/
boolean matches(final String id)
{
if (id == null)
{
return true;
}
return title.equals(id);
}
/*
* Copyright (c) 2018, Psikoi <https://github.com/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.loottracker;
import com.google.gson.annotations.SerializedName;
import lombok.Value;
@Value
class LootTrackerRecord
{
private final String title;
private final String subTitle;
@SerializedName("item_records")
private final LootTrackerItem[] items;
private final long timestamp;
/**
* Checks if this record matches specified id
*
* @param id other record id
* @return true if match is made
*/
boolean matches(final String id)
{
if (id == null)
{
return true;
}
return title.equals(id);
}
}