add bosses killed stat

This commit is contained in:
hyperdefined
2026-01-14 13:24:51 -05:00
parent b5040a4636
commit 7beaa151c1
5 changed files with 247 additions and 4 deletions

View File

@@ -107,6 +107,15 @@ public final class ToolStats extends JavaPlugin {
* Key for applied token. This is what goes onto the tool/armor to record the type. * Key for applied token. This is what goes onto the tool/armor to record the type.
*/ */
public final NamespacedKey tokenApplied = new NamespacedKey(this, "token-applied"); public final NamespacedKey tokenApplied = new NamespacedKey(this, "token-applied");
/**
* Key for withers killed.
*/
public final NamespacedKey witherKills = new NamespacedKey(this, "wither-kills");
/**
* Key for withers killed.
*/
public final NamespacedKey enderDragonKills = new NamespacedKey(this, "enderdragon-kills");
/** /**
* Stores how an item was created. * Stores how an item was created.
* 0 = crafted. * 0 = crafted.

View File

@@ -127,6 +127,14 @@ public class AnvilEvent implements Listener {
addToken(event, tokenType, "damage-done", clone); addToken(event, tokenType, "damage-done", clone);
return; return;
} }
if (tokenType.equalsIgnoreCase("wither-kills")) {
addToken(event, tokenType, "wither-kills", clone);
return;
}
if (tokenType.equalsIgnoreCase("enderdragon-kills")) {
addToken(event, tokenType, "enderdragon-kills", clone);
return;
}
} }
return; return;
} }
@@ -151,6 +159,14 @@ public class AnvilEvent implements Listener {
addToken(event, tokenType, "damage-done", clone); addToken(event, tokenType, "damage-done", clone);
return; return;
} }
if (tokenType.equalsIgnoreCase("wither-kills")) {
addToken(event, tokenType, "wither-kills", clone);
return;
}
if (tokenType.equalsIgnoreCase("enderdragon-kills")) {
addToken(event, tokenType, "enderdragon-kills", clone);
return;
}
return; return;
} }
if (firstSlotMaterial == Material.BOW || firstSlotMaterial == Material.CROSSBOW) { if (firstSlotMaterial == Material.BOW || firstSlotMaterial == Material.CROSSBOW) {
@@ -170,6 +186,14 @@ public class AnvilEvent implements Listener {
addToken(event, tokenType, "damage-done", clone); addToken(event, tokenType, "damage-done", clone);
return; return;
} }
if (tokenType.equalsIgnoreCase("wither-kills")) {
addToken(event, tokenType, "wither-kills", clone);
return;
}
if (tokenType.equalsIgnoreCase("enderdragon-kills")) {
addToken(event, tokenType, "enderdragon-kills", clone);
return;
}
return; return;
} }
if (firstSlotMaterial == Material.FISHING_ROD) { if (firstSlotMaterial == Material.FISHING_ROD) {
@@ -291,6 +315,24 @@ public class AnvilEvent implements Listener {
} }
break; break;
} }
case "wither-kills": {
if (toolStats.config.getBoolean("enabled.bosses-killed.wither")) {
newItem.setItemMeta(toolStats.itemLore.updateBossesKilled(newItem, 0, "wither"));
} else {
event.setResult(null);
return;
}
break;
}
case "enderdragon-kills": {
if (toolStats.config.getBoolean("enabled.bosses-killed.enderdragon")) {
newItem.setItemMeta(toolStats.itemLore.updateBossesKilled(newItem, 0, "enderdragon"));
} else {
event.setResult(null);
return;
}
break;
}
} }
event.setResult(newItem); event.setResult(newItem);
event.getView().setRepairCost(toolStats.itemChecker.getCost(targetToken)); event.getView().setRepairCost(toolStats.itemChecker.getCost(targetToken));
@@ -392,6 +434,22 @@ public class AnvilEvent implements Listener {
meta = toolStats.itemLore.updateFlightTime(finalItem, -flightTime); meta = toolStats.itemLore.updateFlightTime(finalItem, -flightTime);
finalItem.setItemMeta(meta); finalItem.setItemMeta(meta);
} }
if (container.has(toolStats.witherKills)) {
Integer witherKills = container.get(toolStats.witherKills, PersistentDataType.INTEGER);
if (witherKills == null) {
return;
}
meta = toolStats.itemLore.updateBossesKilled(finalItem, -witherKills, "wither");
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.enderDragonKills)) {
Integer enderDragonKills = container.get(toolStats.enderDragonKills, PersistentDataType.INTEGER);
if (enderDragonKills == null) {
return;
}
meta = toolStats.itemLore.updateBossesKilled(finalItem, -enderDragonKills, "enderdragon");
finalItem.setItemMeta(meta);
}
event.setResult(finalItem); event.setResult(finalItem);
event.getView().setRepairCost(toolStats.itemChecker.getCost("reset")); event.getView().setRepairCost(toolStats.itemChecker.getCost("reset"));
} }

View File

@@ -22,6 +22,7 @@ import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
@@ -848,7 +849,7 @@ public class ItemLore {
} }
} }
if (meta.hasLore()) { if (meta.hasLore()) {
String oldSheepShearedFormatted = toolStats.numberFormat.formatDouble(sheepSheared); String oldSheepShearedFormatted = toolStats.numberFormat.formatInt(sheepSheared);
Component lineToRemove = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", oldSheepShearedFormatted); Component lineToRemove = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", oldSheepShearedFormatted);
List<Component> newLore = removeLore(meta.lore(), lineToRemove); List<Component> newLore = removeLore(meta.lore(), lineToRemove);
meta.lore(newLore); meta.lore(newLore);
@@ -946,7 +947,7 @@ public class ItemLore {
} }
} }
if (meta.hasLore()) { if (meta.hasLore()) {
String oldArrowsShotFormatted = toolStats.numberFormat.formatDouble(arrowsShot); String oldArrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot);
Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", oldArrowsShotFormatted); Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", oldArrowsShotFormatted);
List<Component> newLore = removeLore(meta.lore(), lineToRemove); List<Component> newLore = removeLore(meta.lore(), lineToRemove);
meta.lore(newLore); meta.lore(newLore);
@@ -1046,7 +1047,7 @@ public class ItemLore {
} }
} }
if (meta.hasLore()) { if (meta.hasLore()) {
String oldFishCaught = toolStats.numberFormat.formatDouble(fishCaught); String oldFishCaught = toolStats.numberFormat.formatInt(fishCaught);
Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", oldFishCaught); Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", oldFishCaught);
List<Component> newLore = removeLore(meta.lore(), lineToRemove); List<Component> newLore = removeLore(meta.lore(), lineToRemove);
meta.lore(newLore); meta.lore(newLore);
@@ -1104,6 +1105,118 @@ public class ItemLore {
return meta; return meta;
} }
/**
* Add x to bosses killed stat.
*
* @param weapon The weapon used.
* @param add How many to add.
* @param boss The boss killed
*/
public ItemMeta updateBossesKilled(ItemStack weapon, int add, String boss) {
ItemStack clone = weapon.clone();
ItemMeta meta = clone.getItemMeta();
if (meta == null) {
toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
NamespacedKey bossesKey = null;
if (boss.equalsIgnoreCase("wither")) {
bossesKey = toolStats.witherKills;
}
if (boss.equalsIgnoreCase("enderdragon")) {
bossesKey = toolStats.enderDragonKills;
}
if (bossesKey == null) {
return null;
}
// if it's disabled, don't update the stats
// check to see if the item has the stats, remove them if it does
if (!toolStats.config.getBoolean("enabled.bosses-killed." + boss)) {
if (container.has(bossesKey)) {
Integer bossesKilled = container.get(bossesKey, PersistentDataType.INTEGER);
if (bossesKilled == null) {
return null;
}
container.remove(bossesKey);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "wither-kills");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) {
String oldBossesKilled = toolStats.numberFormat.formatInt(bossesKilled);
Component lineToRemove = toolStats.configTools.formatLore("bosses-killed." + boss, "{kills}", oldBossesKilled);
List<Component> newLore = removeLore(meta.lore(), lineToRemove);
meta.lore(newLore);
}
return meta;
}
return null;
}
// check for tokens
boolean validToken = toolStats.itemChecker.checkTokens(container, "wither-kills");
// check for tokens
if (toolStats.config.getBoolean("tokens.enabled")) {
// if the item has stats but no token, add the token
if (container.has(bossesKey) && !validToken) {
String newTokens = toolStats.itemChecker.addTokensToExisting(clone);
if (newTokens != null) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, newTokens);
}
}
// the item does not have a valid token
if (!validToken) {
return null;
}
} else {
if (!validToken) {
String newTokens = toolStats.itemChecker.addTokensToExisting(clone);
if (newTokens != null) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, newTokens);
}
}
}
Integer bossesKilled = 0;
if (container.has(bossesKey, PersistentDataType.INTEGER)) {
bossesKilled = container.get(bossesKey, PersistentDataType.INTEGER);
}
if (bossesKilled == null) {
bossesKilled = 0;
toolStats.logger.warn("{} does not have valid {} set! Resting to zero. This should NEVER happen.", clone, boss);
}
container.set(bossesKey, PersistentDataType.INTEGER, bossesKilled + add);
String oldBossesKilledFormatted = toolStats.numberFormat.formatInt(bossesKilled);
String newBossesKilledFormatted = toolStats.numberFormat.formatInt(bossesKilled + add);
Component oldLine = toolStats.configTools.formatLore("bosses-killed." + boss, "{kills}", oldBossesKilledFormatted);
Component newLine = toolStats.configTools.formatLore("bosses-killed." + boss, "{kills}", newBossesKilledFormatted);
if (oldLine == null || newLine == null) {
return null;
}
List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
return meta;
}
/** /**
* Format the item owner lore. * Format the item owner lore.
* *
@@ -1312,7 +1425,6 @@ public class ItemLore {
Integer arrowsShot = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER); Integer arrowsShot = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER);
if (arrowsShot != null) { if (arrowsShot != null) {
container.remove(toolStats.arrowsShot); container.remove(toolStats.arrowsShot);
String arrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot); String arrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot);
Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", arrowsShotFormatted); Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", arrowsShotFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove)); meta.lore(removeLore(meta.lore(), lineToRemove));
@@ -1329,6 +1441,26 @@ public class ItemLore {
finalItem.setItemMeta(meta); finalItem.setItemMeta(meta);
} }
} }
if (container.has(toolStats.witherKills)) {
Integer witherKills = container.get(toolStats.witherKills, PersistentDataType.INTEGER);
if (witherKills != null) {
container.remove(toolStats.witherKills);
String witherKillsFormatted = toolStats.numberFormat.formatInt(witherKills);
Component lineToRemove = toolStats.configTools.formatLore("bosses-killed.wither", "{kills}", witherKillsFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.enderDragonKills)) {
Integer enderDragonKills = container.get(toolStats.enderDragonKills, PersistentDataType.INTEGER);
if (enderDragonKills != null) {
container.remove(toolStats.enderDragonKills);
String enderDragonKillsFormatted = toolStats.numberFormat.formatInt(enderDragonKills);
Component lineToRemove = toolStats.configTools.formatLore("bosses-killed.enderdragon", "{kills}", enderDragonKillsFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (removeMeta) { if (removeMeta) {
Integer origin = null; Integer origin = null;
if (container.has(toolStats.originType)) { if (container.has(toolStats.originType)) {

View File

@@ -125,6 +125,20 @@ public class TokenData {
removeRecipe.setIngredient('P', Material.PAPER); removeRecipe.setIngredient('P', Material.PAPER);
recipes.add(removeRecipe); recipes.add(removeRecipe);
NamespacedKey witherKillsKey = new NamespacedKey(toolStats, "wither-kills-token");
ShapedRecipe witherKillsRecipe = new ShapedRecipe(witherKillsKey, createToken("wither-kills"));
witherKillsRecipe.shape(" P ", "PWP", " P ");
witherKillsRecipe.setIngredient('P', Material.PAPER);
witherKillsRecipe.setIngredient('W', Material.WITHER_ROSE);
recipes.add(witherKillsRecipe);
NamespacedKey enderDragonKillsKey = new NamespacedKey(toolStats, "enderdragon-kills-token");
ShapedRecipe enderDragonKillsRecipe = new ShapedRecipe(enderDragonKillsKey, createToken("enderdragon-kills"));
enderDragonKillsRecipe.shape(" P ", "PEP", " P ");
enderDragonKillsRecipe.setIngredient('P', Material.PAPER);
enderDragonKillsRecipe.setIngredient('W', Material.ENDER_PEARL);
recipes.add(enderDragonKillsRecipe);
tokenTypes.add("crops-mined"); tokenTypes.add("crops-mined");
tokenTypes.add("blocks-mined"); tokenTypes.add("blocks-mined");
tokenTypes.add("damage-taken"); tokenTypes.add("damage-taken");
@@ -137,6 +151,8 @@ public class TokenData {
tokenTypes.add("fish-caught"); tokenTypes.add("fish-caught");
tokenTypes.add("reset"); tokenTypes.add("reset");
tokenTypes.add("remove"); tokenTypes.add("remove");
tokenTypes.add("wither-kills");
tokenTypes.add("enderdragon-kills");
} }
public Set<ShapedRecipe> getRecipes() { public Set<ShapedRecipe> getRecipes() {

View File

@@ -136,6 +136,28 @@ tokens:
enabled: false enabled: false
type: float type: float
value: 1001 value: 1001
wither-kills:
title: "&7ToolStats: &8Wither Kills Token"
lore:
- "&8Combine with a melee or ranged weapon in an anvil to track wither kills."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
enderdragon-kills:
title: "&7ToolStats: &8Ender Dragon Kills Token"
lore:
- "&8Combine with a melee or ranged weapon in an anvil to track Ender Dragon kills."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
enabled: enabled:
# Will show "Crafted by <player>" # Will show "Crafted by <player>"
@@ -285,6 +307,9 @@ enabled:
mace: true mace: true
fishing-rod: true fishing-rod: true
spear: true spear: true
bosses-killed:
wither: true
enderdragon: true
fish-caught: true fish-caught: true
sheep-sheared: true sheep-sheared: true
armor-damage: true armor-damage: true
@@ -317,6 +342,9 @@ messages:
spawned-in: spawned-in:
spawned-by: "&7Spawned in by: &8{player}" spawned-by: "&7Spawned in by: &8{player}"
spawned-on: "&7Spawned on: &8{date}" spawned-on: "&7Spawned on: &8{date}"
bosses-killed:
wither: "&7Withers killed: &8{kills}"
enderdragon: "&7Ender Dragons killed: &8{kills}"
blocks-mined: "&7Blocks mined: &8{blocks}" blocks-mined: "&7Blocks mined: &8{blocks}"
crops-harvested: "&7Crops harvested: &8{crops}" crops-harvested: "&7Crops harvested: &8{crops}"
sheep-sheared: "&7Sheep sheared: &8{sheep}" sheep-sheared: "&7Sheep sheared: &8{sheep}"