From 86cbdd58ff8f09d68353f9d132b425b4a61925cb Mon Sep 17 00:00:00 2001 From: hyperdefined Date: Wed, 23 Jul 2025 11:29:20 -0400 Subject: [PATCH] new purge command --- .../toolstats/commands/CommandToolStats.java | 37 ++++ .../hyper/toolstats/events/AnvilEvent.java | 155 +-------------- .../lol/hyper/toolstats/tools/ItemLore.java | 185 ++++++++++++++++-- src/main/resources/plugin.yml | 6 + 4 files changed, 217 insertions(+), 166 deletions(-) diff --git a/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java b/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java index a63a960..b0d3ed5 100644 --- a/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java +++ b/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java @@ -155,6 +155,37 @@ public class CommandToolStats implements TabExecutor { sender.sendMessage(Component.text("Type /toolstats reset confirm to confirm this.", NamedTextColor.GREEN)); return true; } + case "purge": { + if (!sender.hasPermission("toolstats.purge")) { + sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); + return true; + } + if (sender instanceof ConsoleCommandSender) { + sender.sendMessage(Component.text("You must be a player for this command.", NamedTextColor.RED)); + return true; + } + if (args.length == 2 && args[1].equalsIgnoreCase("confirm")) { + if (!sender.hasPermission("toolstats.purge.confirm")) { + sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); + return true; + } + Player player = (Player) sender; + ItemStack heldItem = player.getInventory().getItemInMainHand(); + if (!toolStats.itemChecker.isValidItem(heldItem.getType())) { + sender.sendMessage(Component.text("You must hold a valid item.", NamedTextColor.RED)); + return true; + } + ItemStack purgedItem = toolStats.itemLore.removeAll(heldItem, true); + player.getInventory().setItemInMainHand(purgedItem); + sender.sendMessage(Component.text("The item was purged!", NamedTextColor.GREEN)); + return true; + } + sender.sendMessage(Component.text("This will purge ALL ToolStats data from this item.", NamedTextColor.GREEN)); + sender.sendMessage(Component.text("This includes all stats, ownership, and creation time.", NamedTextColor.GREEN)); + sender.sendMessage(Component.text("THIS CANNOT BE UNDONE!", NamedTextColor.GREEN)); + sender.sendMessage(Component.text("Type /toolstats purge confirm to confirm this.", NamedTextColor.GREEN)); + return true; + } case "givetokens": { if (!sender.hasPermission("toolstats.givetokens")) { sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); @@ -992,12 +1023,18 @@ public class CommandToolStats implements TabExecutor { if (sender.hasPermission("toolstats.remove")) { suggestions.add("remove"); } + if (sender.hasPermission("toolstats.purge")) { + suggestions.add("purge"); + } return suggestions.isEmpty() ? null : suggestions; } if (args.length == 2 && args[0].equalsIgnoreCase("reset") && sender.hasPermission("toolstats.reset.confirm")) { return Collections.singletonList("confirm"); } + if (args.length == 2 && args[0].equalsIgnoreCase("purge") && sender.hasPermission("toolstats.purge.confirm")) { + return Collections.singletonList("confirm"); + } if (args.length == 2 && args[0].equalsIgnoreCase("edit") && sender.hasPermission("toolstats.edit")) { // yes I am lazy return toolStats.tokenData.getTokenTypes().stream() diff --git a/src/main/java/lol/hyper/toolstats/events/AnvilEvent.java b/src/main/java/lol/hyper/toolstats/events/AnvilEvent.java index 768a8fc..d7231f2 100644 --- a/src/main/java/lol/hyper/toolstats/events/AnvilEvent.java +++ b/src/main/java/lol/hyper/toolstats/events/AnvilEvent.java @@ -90,7 +90,9 @@ public class AnvilEvent implements Listener { } if (tokenType.equalsIgnoreCase("remove")) { - remove(event, clone); + ItemStack removedStats = toolStats.itemLore.removeAll(clone, false); + event.setResult(removedStats); + event.getView().setRepairCost(toolStats.itemChecker.getCost("remove")); return; } @@ -394,155 +396,4 @@ public class AnvilEvent implements Listener { event.setResult(finalItem); event.getView().setRepairCost(toolStats.itemChecker.getCost("reset")); } - - /** - * Remove all stats from an item. - * - * @param event The PrepareAnvilEvent event. - * @param inputItem The input item to remove stats from. - */ - private void remove(PrepareAnvilEvent event, ItemStack inputItem) { - ItemStack finalItem = inputItem.clone(); - ItemMeta meta = finalItem.getItemMeta(); - PersistentDataContainer container = meta.getPersistentDataContainer(); - - // remove the applied tokens - if (container.has(toolStats.tokenApplied)) { - container.remove(toolStats.tokenApplied); - } - - if (container.has(toolStats.playerKills)) { - Integer playerKills = container.get(toolStats.playerKills, PersistentDataType.INTEGER); - if (playerKills == null) { - return; - } - - container.remove(toolStats.playerKills); - - String playerKillsFormatted = toolStats.numberFormat.formatInt(playerKills); - Component lineToRemove = toolStats.configTools.formatLore("kills.player", "{kills}", playerKillsFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.mobKills)) { - Integer mobKills = container.get(toolStats.mobKills, PersistentDataType.INTEGER); - if (mobKills == null) { - return; - } - - container.remove(toolStats.mobKills); - - String mobKillsFormatted = toolStats.numberFormat.formatInt(mobKills); - Component lineToRemove = toolStats.configTools.formatLore("kills.mob", "{kills}", mobKillsFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.blocksMined)) { - Integer blocksMined = container.get(toolStats.blocksMined, PersistentDataType.INTEGER); - if (blocksMined == null) { - return; - } - - container.remove(toolStats.blocksMined); - - String blocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined); - Component lineToRemove = toolStats.configTools.formatLore("blocks-mined", "{blocks}", blocksMinedFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.cropsHarvested)) { - Integer cropsHarvested = container.get(toolStats.playerKills, PersistentDataType.INTEGER); - if (cropsHarvested == null) { - return; - } - - container.remove(toolStats.cropsHarvested); - - String cropsHarvestedFormatted = toolStats.numberFormat.formatInt(cropsHarvested); - Component lineToRemove = toolStats.configTools.formatLore("crops-harvested", "{crops}", cropsHarvestedFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.fishCaught)) { - Integer fishCaught = container.get(toolStats.fishCaught, PersistentDataType.INTEGER); - if (fishCaught == null) { - return; - } - - container.remove(toolStats.fishCaught); - - String fishCaughtFormatted = toolStats.numberFormat.formatInt(fishCaught); - Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", fishCaughtFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.sheepSheared)) { - Integer sheepSheared = container.get(toolStats.sheepSheared, PersistentDataType.INTEGER); - if (sheepSheared == null) { - return; - } - - container.remove(toolStats.sheepSheared); - - String sheepShearedFormatted = toolStats.numberFormat.formatInt(sheepSheared); - Component lineToRemove = toolStats.configTools.formatLore("sheep.sheared", "{sheep}", sheepShearedFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.armorDamage)) { - Double armorDamage = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE); - if (armorDamage == null) { - return; - } - - container.remove(toolStats.armorDamage); - - String armorDamageFormatted = toolStats.numberFormat.formatDouble(armorDamage); - Component lineToRemove = toolStats.configTools.formatLore("damage-taken", "{damage}", armorDamageFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.damageDone)) { - Double damageDone = container.get(toolStats.damageDone, PersistentDataType.DOUBLE); - if (damageDone == null) { - return; - } - - container.remove(toolStats.damageDone); - - String damageDoneFormatted = toolStats.numberFormat.formatDouble(damageDone); - Component lineToRemove = toolStats.configTools.formatLore("damage-done", "{damage}", damageDoneFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.arrowsShot)) { - Integer arrowsShot = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER); - if (arrowsShot == null) { - return; - } - - container.remove(toolStats.arrowsShot); - - String arrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot); - Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", arrowsShotFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - if (container.has(toolStats.flightTime)) { - Long flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG); - if (flightTime == null) { - return; - } - - container.remove(toolStats.flightTime); - - String flightTimeFormatted = toolStats.numberFormat.formatDouble(flightTime); - Component lineToRemove = toolStats.configTools.formatLore("flight-time", "{time}", flightTimeFormatted); - meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove)); - finalItem.setItemMeta(meta); - } - - event.setResult(finalItem); - event.getView().setRepairCost(toolStats.itemChecker.getCost("remove")); - } } diff --git a/src/main/java/lol/hyper/toolstats/tools/ItemLore.java b/src/main/java/lol/hyper/toolstats/tools/ItemLore.java index 1eff24c..16e150f 100644 --- a/src/main/java/lol/hyper/toolstats/tools/ItemLore.java +++ b/src/main/java/lol/hyper/toolstats/tools/ItemLore.java @@ -19,17 +19,17 @@ package lol.hyper.toolstats.tools; import lol.hyper.toolstats.ToolStats; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; public class ItemLore { @@ -99,6 +99,9 @@ public class ItemLore { * @return The lore with the line removed. */ public List removeLore(List inputLore, Component toRemove) { + if (inputLore == null) { + return Collections.emptyList(); + } List newLore = new ArrayList<>(inputLore); newLore.removeIf(line -> PlainTextComponentSerializer.plainText().serialize(line).equals(PlainTextComponentSerializer.plainText().serialize(toRemove))); return newLore; @@ -198,7 +201,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -297,7 +300,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -395,7 +398,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -493,7 +496,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -599,7 +602,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -705,7 +708,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -821,7 +824,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -919,7 +922,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -1019,7 +1022,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -1117,7 +1120,7 @@ public class ItemLore { if (oldLine == null || newLine == null) { return null; } - List newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); + List newLore = updateItemLore(meta, oldLine, newLine); meta.lore(newLore); return meta; } @@ -1228,4 +1231,158 @@ public class ItemLore { } return null; } + + /** + * Remove all stats, ownership, and creation time from an item. + * + * @param inputItem The input item to remove stats from. + * @param removeMeta Remove ownership and creation time? + */ + public ItemStack removeAll(ItemStack inputItem, boolean removeMeta) { + ItemStack finalItem = inputItem.clone(); + ItemMeta meta = finalItem.getItemMeta(); + PersistentDataContainer container = meta.getPersistentDataContainer(); + + // remove the applied tokens + if (container.has(toolStats.tokenApplied)) { + container.remove(toolStats.tokenApplied); + } + + if (container.has(toolStats.playerKills)) { + Integer playerKills = container.get(toolStats.playerKills, PersistentDataType.INTEGER); + if (playerKills != null) { + container.remove(toolStats.playerKills); + + String playerKillsFormatted = toolStats.numberFormat.formatInt(playerKills); + Component lineToRemove = toolStats.configTools.formatLore("kills.player", "{kills}", playerKillsFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.mobKills)) { + Integer mobKills = container.get(toolStats.mobKills, PersistentDataType.INTEGER); + if (mobKills != null) { + container.remove(toolStats.mobKills); + String mobKillsFormatted = toolStats.numberFormat.formatInt(mobKills); + Component lineToRemove = toolStats.configTools.formatLore("kills.mob", "{kills}", mobKillsFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.blocksMined)) { + Integer blocksMined = container.get(toolStats.blocksMined, PersistentDataType.INTEGER); + if (blocksMined != null) { + container.remove(toolStats.blocksMined); + String blocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined); + Component lineToRemove = toolStats.configTools.formatLore("blocks-mined", "{blocks}", blocksMinedFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.cropsHarvested)) { + Integer cropsHarvested = container.get(toolStats.playerKills, PersistentDataType.INTEGER); + if (cropsHarvested != null) { + container.remove(toolStats.cropsHarvested); + String cropsHarvestedFormatted = toolStats.numberFormat.formatInt(cropsHarvested); + Component lineToRemove = toolStats.configTools.formatLore("crops-harvested", "{crops}", cropsHarvestedFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.fishCaught)) { + Integer fishCaught = container.get(toolStats.fishCaught, PersistentDataType.INTEGER); + if (fishCaught != null) { + container.remove(toolStats.fishCaught); + String fishCaughtFormatted = toolStats.numberFormat.formatInt(fishCaught); + Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", fishCaughtFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.sheepSheared)) { + Integer sheepSheared = container.get(toolStats.sheepSheared, PersistentDataType.INTEGER); + if (sheepSheared != null) { + container.remove(toolStats.sheepSheared); + String sheepShearedFormatted = toolStats.numberFormat.formatInt(sheepSheared); + Component lineToRemove = toolStats.configTools.formatLore("sheep.sheared", "{sheep}", sheepShearedFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.armorDamage)) { + Double armorDamage = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE); + if (armorDamage != null) { + container.remove(toolStats.armorDamage); + String armorDamageFormatted = toolStats.numberFormat.formatDouble(armorDamage); + Component lineToRemove = toolStats.configTools.formatLore("damage-taken", "{damage}", armorDamageFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.damageDone)) { + Double damageDone = container.get(toolStats.damageDone, PersistentDataType.DOUBLE); + if (damageDone != null) { + container.remove(toolStats.damageDone); + String damageDoneFormatted = toolStats.numberFormat.formatDouble(damageDone); + Component lineToRemove = toolStats.configTools.formatLore("damage-done", "{damage}", damageDoneFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.arrowsShot)) { + Integer arrowsShot = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER); + if (arrowsShot != null) { + container.remove(toolStats.arrowsShot); + + String arrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot); + Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", arrowsShotFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (container.has(toolStats.flightTime)) { + Long flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG); + if (flightTime != null) { + container.remove(toolStats.flightTime); + Map flightTimeFormatted = toolStats.numberFormat.formatTime(flightTime); + Component lineToRemove = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", flightTimeFormatted); + meta.lore(removeLore(meta.lore(), lineToRemove)); + finalItem.setItemMeta(meta); + } + } + if (removeMeta) { + Integer origin = null; + if (container.has(toolStats.originType)) { + origin = container.get(toolStats.originType, PersistentDataType.INTEGER); + } + + if (container.has(toolStats.timeCreated)) { + Long timeCreated = container.get(toolStats.timeCreated, PersistentDataType.LONG); + if (timeCreated != null && origin != null) { + container.remove(toolStats.timeCreated); + Component timeCreatedLore = formatCreationTime(timeCreated, origin, finalItem); + meta.lore(removeLore(meta.lore(), timeCreatedLore)); + } + } + if (container.has(toolStats.itemOwner)) { + UUID owner = container.get(toolStats.itemOwner, new UUIDDataType()); + if (owner != null && origin != null) { + container.remove(toolStats.itemOwner); + String ownerName = Bukkit.getOfflinePlayer(owner).getName(); + if (ownerName != null) { + Component ownerLore = formatOwner(ownerName, origin, finalItem); + meta.lore(removeLore(meta.lore(), ownerLore)); + } + } + } + + if (origin != null) { + container.remove(toolStats.originType); + } + + finalItem.setItemMeta(meta); + } + + return finalItem; + } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 90136ad..a20d087 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -23,6 +23,12 @@ permissions: toolstats.reset.confirm: description: Allows the usage of /toolstats reset confirm. default: true + toolstats.purge: + description: Allows the usage of /toolstats purge. + default: true + toolstats.purge.confirm: + description: Allows the usage of /toolstats purge confirm. + default: true toolstats.givetokens: description: Allows the usage of /toolstats givetoken. default: op