Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add npc id to loot metadata #550

Merged
merged 7 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Unreleased

- Minor: Include NPC ID in loot notification metadata. (#550)

## 1.10.9

- Minor: Don't include boss/icon images when rich embed is disabled. (#541)
Expand Down
5 changes: 4 additions & 1 deletion docs/json-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,8 @@ JSON for Loot Notifications:
"party": ["%USERNAME%", "another RSN", "yet another RSN"],
"category": "EVENT",
"killCount": 60,
"rarestProbability": 0.001
"rarestProbability": 0.001,
"npcId": null
},
"type": "LOOT"
}
Expand All @@ -253,6 +254,8 @@ The items are valued at GE prices (when possible) if the user has not disabled t

The `extra.party` field is only populated for raids loot (i.e., COX, TOA, TOB).

The `extra.npcId` field is populated only if the `category` is NPC or PICKPOCKET.

### Slayer

JSON for Slayer Notifications:
Expand Down
27 changes: 21 additions & 6 deletions src/main/java/dinkplugin/notifiers/LootNotifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.OptionalDouble;
import java.util.concurrent.CopyOnWriteArrayList;
Expand Down Expand Up @@ -110,15 +111,15 @@ public void onNpcLootReceived(NpcLootReceived event) {
return;
}

this.handleNotify(event.getItems(), npc.getName(), LootRecordType.NPC);
this.handleNotify(event.getItems(), npc.getName(), LootRecordType.NPC, id);
}

public void onPlayerLootReceived(PlayerLootReceived event) {
if (WorldUtils.isSafeArea(client))
return;

if (config.includePlayerLoot() && isEnabled())
this.handleNotify(event.getItems(), event.getPlayer().getName(), LootRecordType.PLAYER);
this.handleNotify(event.getItems(), event.getPlayer().getName(), LootRecordType.PLAYER, null);
}

public void onLootReceived(LootReceived lootReceived) {
Expand All @@ -132,14 +133,14 @@ public void onLootReceived(LootReceived lootReceived) {
}

String source = killCountService.getStandardizedSource(lootReceived);
this.handleNotify(lootReceived.getItems(), source, lootReceived.getType());
this.handleNotify(lootReceived.getItems(), source, lootReceived.getType(), null);
} else if (lootReceived.getType() == LootRecordType.NPC && KillCountService.SPECIAL_LOOT_NPC_NAMES.contains(lootReceived.getName())) {
// Special case: upstream fires LootReceived for certain NPCs, but not NpcLootReceived
this.handleNotify(lootReceived.getItems(), lootReceived.getName(), lootReceived.getType());
this.handleNotify(lootReceived.getItems(), lootReceived.getName(), lootReceived.getType(), null);
}
}

private void handleNotify(Collection<ItemStack> items, String dropper, LootRecordType type) {
private void handleNotify(Collection<ItemStack> items, String dropper, LootRecordType type, Integer npcId) {
final Integer kc = killCountService.getKillCount(type, dropper);
final int minValue = config.minLootValue();
final boolean icons = config.lootIcons();
Expand Down Expand Up @@ -218,6 +219,20 @@ private void handleNotify(Collection<ItemStack> items, String dropper, LootRecor
}

if (sendMessage) {
if (npcId == null && (type == LootRecordType.NPC || type == LootRecordType.PICKPOCKET)) {
var player = client.getLocalPlayer();
var location = WorldUtils.getLocation(client, player);
var comparator = Comparator.<NPC, Boolean>comparing(npc -> npc.getInteracting() == player)
.thenComparing(npc -> npc.isDead() == (type == LootRecordType.NPC))
.thenComparingInt(npc -> -location.distanceTo2D(WorldUtils.getLocation(client, npc)))
.thenComparingInt(NPC::getCombatLevel);
npcId = client.getTopLevelWorldView().npcs().stream()
.filter(npc -> dropper.equals(npc.getName()))
.max(comparator)
.map(NPC::getId)
.orElse(null);
iProdigy marked this conversation as resolved.
Show resolved Hide resolved
}

String overrideUrl = getWebhookUrl();
if (config.lootRedirectPlayerKill() && !config.pkWebhook().isBlank()) {
if (type == LootRecordType.PLAYER || (type == LootRecordType.EVENT && "Loot Chest".equals(dropper))) {
Expand All @@ -242,7 +257,7 @@ private void handleNotify(Collection<ItemStack> items, String dropper, LootRecor
NotificationBody.builder()
.text(notifyMessage)
.embeds(embeds)
.extra(new LootNotificationData(serializedItems, dropper, type, kc, rarity, party))
.extra(new LootNotificationData(serializedItems, dropper, type, kc, rarity, party, npcId))
.type(NotificationType.LOOT)
.thumbnailUrl(ItemUtils.getItemImageUrl(max.getId()))
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public class LootNotificationData extends NotificationData {
@Nullable
Collection<String> party;

@Nullable
Integer npcId;

@Override
public List<Field> getFields() {
List<Field> fields = new ArrayList<>(4);
Expand Down
Loading
Loading