From 73e472af3a3642a9562e9e4f585333fcc4aa8835 Mon Sep 17 00:00:00 2001 From: hyperdefined Date: Sun, 26 Jan 2025 14:37:24 -0500 Subject: [PATCH] add reset token --- .../java/lol/hyper/toolstats/ToolStats.java | 17 ++ .../toolstats/events/GrindstoneEvent.java | 165 ++++++++++++++++++ .../hyper/toolstats/tools/TokenCrafting.java | 7 + .../toolstats/tools/config/TokenItems.java | 19 ++ src/main/resources/config.yml | 9 +- 5 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 src/main/java/lol/hyper/toolstats/events/GrindstoneEvent.java diff --git a/src/main/java/lol/hyper/toolstats/ToolStats.java b/src/main/java/lol/hyper/toolstats/ToolStats.java index 3b079a8..018eea4 100644 --- a/src/main/java/lol/hyper/toolstats/ToolStats.java +++ b/src/main/java/lol/hyper/toolstats/ToolStats.java @@ -34,6 +34,8 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.File; import java.io.IOException; +import java.util.HashSet; +import java.util.Set; import java.util.logging.Logger; public final class ToolStats extends JavaPlugin { @@ -114,6 +116,7 @@ public final class ToolStats extends JavaPlugin { public final Logger logger = this.getLogger(); public final File configFile = new File(this.getDataFolder(), "config.yml"); public boolean tokens = false; + public Set tokenKeys = new HashSet<>(); public BlocksMined blocksMined; public ChunkPopulate chunkPopulate; @@ -142,6 +145,7 @@ public final class ToolStats extends JavaPlugin { public TokenCrafting tokenCrafting; public AnvilEvent anvilEvent; public PrepareCraft prepareCraft; + public GrindstoneEvent grindstoneEvent; @Override public void onEnable() { @@ -183,6 +187,18 @@ public final class ToolStats extends JavaPlugin { shootBow = new ShootBow(this); anvilEvent = new AnvilEvent(this); prepareCraft = new PrepareCraft(this); + grindstoneEvent = new GrindstoneEvent(this); + + // save which stat can be used by a reset token + tokenKeys.add(genericMined); + tokenKeys.add(swordPlayerKills); + tokenKeys.add(swordMobKills); + tokenKeys.add(cropsHarvested); + tokenKeys.add(shearsSheared); + tokenKeys.add(fishingRodCaught); + tokenKeys.add(flightTime); + tokenKeys.add(arrowsShot); + tokenKeys.add(armorDamage); Bukkit.getServer().getPluginManager().registerEvents(blocksMined, this); Bukkit.getServer().getPluginManager().registerEvents(chunkPopulate, this); @@ -202,6 +218,7 @@ public final class ToolStats extends JavaPlugin { Bukkit.getServer().getPluginManager().registerEvents(playerMove, this); Bukkit.getServer().getPluginManager().registerEvents(anvilEvent, this); Bukkit.getServer().getPluginManager().registerEvents(prepareCraft, this); + Bukkit.getServer().getPluginManager().registerEvents(grindstoneEvent, this); this.getCommand("toolstats").setExecutor(commandToolStats); diff --git a/src/main/java/lol/hyper/toolstats/events/GrindstoneEvent.java b/src/main/java/lol/hyper/toolstats/events/GrindstoneEvent.java new file mode 100644 index 0000000..38730ad --- /dev/null +++ b/src/main/java/lol/hyper/toolstats/events/GrindstoneEvent.java @@ -0,0 +1,165 @@ +/* + * This file is part of ToolStats. + * + * ToolStats is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ToolStats is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ToolStats. If not, see . + */ + +package lol.hyper.toolstats.events; + +import lol.hyper.toolstats.ToolStats; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.PrepareGrindstoneEvent; +import org.bukkit.inventory.GrindstoneInventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +public class GrindstoneEvent implements Listener { + + private final ToolStats toolStats; + + public GrindstoneEvent(ToolStats toolStats) { + this.toolStats = toolStats; + } + + @EventHandler + public void onGrindstone(PrepareGrindstoneEvent event) { + if (!toolStats.config.getBoolean("tokens.enabled")) { + return; + } + + GrindstoneInventory inventory = event.getInventory(); + ItemStack upperSlotItem = inventory.getUpperItem(); + ItemStack lowerSlotItem = inventory.getLowerItem(); + + // make sure both slots have an item + if (upperSlotItem == null || lowerSlotItem == null) { + return; + } + + // make sure the first item is a valid item + if (!toolStats.itemChecker.isValidItem(upperSlotItem.getType())) { + return; + } + + PersistentDataContainer lowerSlotContainer = lowerSlotItem.getItemMeta().getPersistentDataContainer(); + // check to see if the lower item is a token + if (lowerSlotItem.getType() != Material.PAPER || !lowerSlotContainer.has(toolStats.tokenType, PersistentDataType.STRING)) { + return; + } + + // check to see if the token is a reset token + String tokenType = lowerSlotContainer.get(toolStats.tokenType, PersistentDataType.STRING); + if (tokenType == null) { + return; + } + if (!tokenType.equalsIgnoreCase("reset")) { + return; + } + + // make sure the upper slot item has tokens applied + PersistentDataContainer upperSlotContainer = upperSlotItem.getItemMeta().getPersistentDataContainer(); + if (!upperSlotContainer.has(toolStats.tokenApplied, PersistentDataType.STRING)) { + return; + } + + String appliedTokens = upperSlotContainer.get(toolStats.tokenApplied, PersistentDataType.STRING); + if (appliedTokens == null) { + return; + } + + // perform the reset + ItemStack resetItem = reset(upperSlotItem.clone(), appliedTokens); + if (resetItem != null) { + inventory.setResult(resetItem); + } + } + + /** + * Reset a given item's stat and lore to zero. + * + * @param inputItem The input item. + * @param appliedTokens The tokens this item has. + * @return The reset item, or null if it broke. + */ + private ItemStack reset(ItemStack inputItem, String appliedTokens) { + ItemMeta meta = inputItem.getItemMeta(); + if (meta == null) { + return null; + } + + ItemMeta finalMeta = meta.clone(); + PersistentDataContainer container = meta.getPersistentDataContainer(); + String[] tokens = appliedTokens.split(","); + for (String token : tokens) { + switch (appliedTokens) { + case "player-kills": { + container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updatePlayerKills(inputItem, 0); + break; + } + case "mob-kills": { + container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateMobKills(inputItem, 0); + break; + } + case "blocks-mined": { + container.set(toolStats.genericMined, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateBlocksMined(inputItem, 0); + break; + } + case "crops-mined": { + container.set(toolStats.cropsHarvested, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateCropsMined(inputItem, 0); + break; + } + case "fish-caught": { + container.set(toolStats.fishingRodCaught, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateFishCaught(inputItem, 0); + break; + } + case "sheep-sheared": { + container.set(toolStats.shearsSheared, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateSheepSheared(inputItem, 0); + break; + } + case "damage-taken": { + container.set(toolStats.armorDamage, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateDamage(inputItem, 0.0); + break; + } + case "arrows-shot": { + container.set(toolStats.arrowsShot, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateArrowsShot(inputItem, 0); + break; + } + case "flight-time": { + container.set(toolStats.flightTime, PersistentDataType.INTEGER, 0); + finalMeta = toolStats.itemLore.updateFlightTime(inputItem, 0); + break; + } + } + } + + // return the final item + if (finalMeta != null) { + inputItem.setItemMeta(finalMeta); + return inputItem; + } + return null; + } +} diff --git a/src/main/java/lol/hyper/toolstats/tools/TokenCrafting.java b/src/main/java/lol/hyper/toolstats/tools/TokenCrafting.java index 88b730c..9b3b82f 100644 --- a/src/main/java/lol/hyper/toolstats/tools/TokenCrafting.java +++ b/src/main/java/lol/hyper/toolstats/tools/TokenCrafting.java @@ -100,6 +100,12 @@ public class TokenCrafting { flightTimeRecipe.setIngredient('F', Material.FEATHER); recipes.add(flightTimeRecipe); + NamespacedKey resetKey = new NamespacedKey(toolStats, "reset-token"); + ShapedRecipe resetRecipe = new ShapedRecipe(resetKey, toolStats.tokenItems.resetToken()); + resetRecipe.shape(" P ", "P P", " P "); + resetRecipe.setIngredient('P', Material.PAPER); + recipes.add(resetRecipe); + tokenTypes.add("crops-mined"); tokenTypes.add("blocks-mined"); tokenTypes.add("damage-taken"); @@ -109,6 +115,7 @@ public class TokenCrafting { tokenTypes.add("sheep-sheared"); tokenTypes.add("flight-time"); tokenTypes.add("fish-caught"); + tokenTypes.add("reset"); } public Set getRecipes() { diff --git a/src/main/java/lol/hyper/toolstats/tools/config/TokenItems.java b/src/main/java/lol/hyper/toolstats/tools/config/TokenItems.java index d434d2c..b6f332e 100644 --- a/src/main/java/lol/hyper/toolstats/tools/config/TokenItems.java +++ b/src/main/java/lol/hyper/toolstats/tools/config/TokenItems.java @@ -215,4 +215,23 @@ public class TokenItems { token.setItemMeta(tokenMeta); return token; } + public ItemStack resetToken() { + // set up the item + ItemStack token = new ItemStack(Material.PAPER); + ItemMeta tokenMeta = token.getItemMeta(); + PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer(); + + // set the title and lore + Component title = toolStats.configTools.format("tokens.data.reset.title"); + Component lore = toolStats.configTools.format("tokens.data.reset.lore"); + tokenMeta.displayName(title); + List newLore = new ArrayList<>(); + newLore.add(lore); + tokenMeta.lore(newLore); + + // set the PDC + tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "reset"); + token.setItemMeta(tokenMeta); + return token; + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 17bb55d..70caec3 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -5,9 +5,9 @@ tokens: craft-tokens: true data: player-kills: - title: "&7ToolStats: &8Player Kills Token" - lore: "&8Combine with a melee or ranged weapon in an anvil to track player kills." - levels: 1 + title: "&7ToolStats: &8Player Kills Token" + lore: "&8Combine with a melee or ranged weapon in an anvil to track player kills." + levels: 1 mob-kills: title: "&7ToolStats: &8Mob Kills Token" lore: "&8Combine with a melee or ranged weapon in an anvil to track mob kills." @@ -40,6 +40,9 @@ tokens: title: "&7ToolStats: &8Flight Time Token" lore: "&8Combine with an elytra in an anvil to track flight time." levels: 1 + reset: + title: "&7ToolStats: &8Reset Item" + lore: "&8Use in a grindstone to reset ALL stats for this item. Tokens on this item stay." enabled: # Will show ownership of items when they are created/found.