diff --git a/pom.xml b/pom.xml index 0139a8f..64f6e8a 100644 --- a/pom.xml +++ b/pom.xml @@ -105,7 +105,7 @@ io.papermc.paper paper-api - 1.21.9-R0.1-SNAPSHOT + 1.21.10-R0.1-SNAPSHOT provided diff --git a/src/main/java/lol/hyper/toolstats/ToolStats.java b/src/main/java/lol/hyper/toolstats/ToolStats.java index 77e20ba..2c37b94 100644 --- a/src/main/java/lol/hyper/toolstats/ToolStats.java +++ b/src/main/java/lol/hyper/toolstats/ToolStats.java @@ -151,6 +151,7 @@ public final class ToolStats extends JavaPlugin { public TokenData tokenData; public AnvilEvent anvilEvent; public PrepareCraft prepareCraft; + public BlockDispenseEvent blockDispenseEvent; public HyperLib hyperLib; public TextUtils textUtils; @@ -201,6 +202,7 @@ public final class ToolStats extends JavaPlugin { shootBow = new ShootBow(this); anvilEvent = new AnvilEvent(this); prepareCraft = new PrepareCraft(this); + blockDispenseEvent = new BlockDispenseEvent(this); // save which stat can be used by a reset token tokenKeys.add(blocksMined); @@ -231,6 +233,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(blockDispenseEvent, this); this.getCommand("toolstats").setExecutor(commandToolStats); diff --git a/src/main/java/lol/hyper/toolstats/events/BlockDispenseEvent.java b/src/main/java/lol/hyper/toolstats/events/BlockDispenseEvent.java new file mode 100644 index 0000000..f68daa6 --- /dev/null +++ b/src/main/java/lol/hyper/toolstats/events/BlockDispenseEvent.java @@ -0,0 +1,136 @@ +/* + * 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.hyperlib.datatypes.UUIDDataType; +import lol.hyper.toolstats.ToolStats; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockDispenseLootEvent; +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.Objects; + +public class BlockDispenseEvent implements Listener { + + private final ToolStats toolStats; + + public BlockDispenseEvent(ToolStats toolStats) { + this.toolStats = toolStats; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDispense(BlockDispenseLootEvent event) { + Player player = event.getPlayer(); + + if (player == null) { + return; + } + + List loot = event.getDispensedLoot(); + // probably won't ever happen + if (loot.isEmpty()) { + return; + } + + List newLoot = new ArrayList<>(); + for (ItemStack lootItem : loot) { + ItemStack newLootItem = lootItem.clone(); + Material lootItemMaterial = newLootItem.getType(); + // if the item is one we want, do stuff + if (toolStats.itemChecker.isValidItem(lootItemMaterial)) { + newLootItem = addLootedOrigin(newLootItem, player); + } + + // if the item returned null, add the original item + newLoot.add(Objects.requireNonNullElse(newLootItem, lootItem)); + } + event.setDispensedLoot(newLoot); + } + + /** + * Adds lore to newly generated items. + * + * @param itemStack The item to add lore to. + * @param owner The player that found the item. + * @return The item with the lore. + */ + private ItemStack addLootedOrigin(ItemStack itemStack, Player owner) { + ItemStack newItem = itemStack.clone(); + ItemMeta meta = itemStack.getItemMeta(); + if (meta == null) { + return null; + } + long timeCreated = System.currentTimeMillis(); + Date finalDate; + if (toolStats.config.getBoolean("normalize-time-creation")) { + finalDate = toolStats.numberFormat.normalizeTime(timeCreated); + timeCreated = finalDate.getTime(); + } + PersistentDataContainer container = meta.getPersistentDataContainer(); + + if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.itemOwner, PersistentDataType.LONG)) { + return null; + } + + // get the current lore the item + List lore; + if (meta.hasLore()) { + lore = meta.lore(); + } else { + lore = new ArrayList<>(); + } + + // if creation date is enabled, add it + Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 2, newItem); + if (creationDate != null) { + container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated); + container.set(toolStats.originType, PersistentDataType.INTEGER, 2); + lore.add(creationDate); + meta.lore(lore); + } + + // if ownership is enabled, add it + Component itemOwner = toolStats.itemLore.formatOwner(owner.getName(), 2, newItem); + if (itemOwner != null) { + container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId()); + container.set(toolStats.originType, PersistentDataType.INTEGER, 2); + lore.add(itemOwner); + meta.lore(lore); + } + + // if hash is enabled, add it + if (toolStats.config.getBoolean("generate-hash-for-items")) { + String hash = toolStats.hashMaker.makeHash(newItem.getType(), owner.getUniqueId(), timeCreated); + container.set(toolStats.hash, PersistentDataType.STRING, hash); + } + + newItem.setItemMeta(meta); + return newItem; + } +} diff --git a/src/main/java/lol/hyper/toolstats/events/PlayerInteract.java b/src/main/java/lol/hyper/toolstats/events/PlayerInteract.java index 7ca538b..da4bdb0 100644 --- a/src/main/java/lol/hyper/toolstats/events/PlayerInteract.java +++ b/src/main/java/lol/hyper/toolstats/events/PlayerInteract.java @@ -20,8 +20,8 @@ package lol.hyper.toolstats.events; import lol.hyper.toolstats.ToolStats; import org.bukkit.Bukkit; import org.bukkit.GameMode; -import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -31,6 +31,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.InventoryHolder; import java.util.HashMap; import java.util.Map; @@ -62,7 +63,8 @@ public class PlayerInteract implements Listener { return; } // store when a player opens a chest - if (block.getType() != Material.AIR && block.getType() == Material.CHEST) { + BlockState state = block.getState(); + if (state instanceof InventoryHolder) { openedChests.put(block, player); Bukkit.getGlobalRegionScheduler().runDelayed(toolStats, scheduledTask -> openedChests.remove(block), 20); }