diff --git a/src/main/java/lol/hyper/toolstats/ToolStats.java b/src/main/java/lol/hyper/toolstats/ToolStats.java index c6c1990..3efed9b 100644 --- a/src/main/java/lol/hyper/toolstats/ToolStats.java +++ b/src/main/java/lol/hyper/toolstats/ToolStats.java @@ -152,6 +152,12 @@ public final class ToolStats extends JavaPlugin { } } + /** + * Checks the config to see if we want to show lore on certain items. + * @param itemStack The item to check. + * @param configName The config we are checking under. + * @return If we want to allow lore or not. + */ public boolean checkConfig(ItemStack itemStack, String configName) { String itemName = itemStack.getType().toString().toLowerCase(); String itemType = null; @@ -202,6 +208,12 @@ public final class ToolStats extends JavaPlugin { return false; } + /** + * Gets the lore message from the config. + * @param configName The config name, "messages." is already in front. + * @param raw If you want the raw message with the formatting codes and placeholders. + * @return The lore message. + */ public String getLoreFromConfig(String configName, boolean raw) { String lore = config.getString("messages." + configName); if (lore == null) { diff --git a/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java b/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java index bb30128..144dcbe 100644 --- a/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java +++ b/src/main/java/lol/hyper/toolstats/commands/CommandToolStats.java @@ -21,7 +21,6 @@ import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.UUIDDataType; import org.bukkit.*; import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; import org.bukkit.entity.Player; @@ -88,11 +87,16 @@ public class CommandToolStats implements TabExecutor { return true; } - private ItemStack fixItemLore(ItemStack original, Player player) { + /** + * Fixes lore on a given item. This will wipe all lore and reapply our custom ones. + * @param original The item we are fixing. + * @param player The player running the command. + */ + private void fixItemLore(ItemStack original, Player player) { ItemStack finalItem = original.clone(); ItemMeta finalMeta = finalItem.getItemMeta(); if (finalMeta == null) { - return null; + return; } PersistentDataContainer container = finalMeta.getPersistentDataContainer(); List lore = new ArrayList<>(); @@ -101,10 +105,14 @@ public class CommandToolStats implements TabExecutor { String lootedByLore = toolStats.getLoreFromConfig("looted.found-by", false); String tradedByLore = toolStats.getLoreFromConfig("traded.traded-by", false); + // make sure the config messages are not null if (caughtByLore == null || lootedByLore == null || tradedByLore == null) { - return null; + return; } + // determine how the item was originally created + // this doesn't get saved, so we just rely on the lore + // if there isn't a tag, default to crafted String type = "DEFAULT"; if (finalMeta.hasLore()) { if (finalMeta.getLore() != null) { @@ -124,6 +132,7 @@ public class CommandToolStats implements TabExecutor { if (toolStats.checkConfig(original, "created-by")) { if (container.has(toolStats.genericOwner, new UUIDDataType())) { container.set(toolStats.genericOwner, new UUIDDataType(), player.getUniqueId()); + // show how the item was created based on the previous lore switch (type) { case "DEFAULT": { lore.add(toolStats.getLoreFromConfig("created.created-by", true).replace("{player}", player.getName())); @@ -148,8 +157,9 @@ public class CommandToolStats implements TabExecutor { if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) { Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG); if (time == null) { - return null; + return; } + // show how when the item was created based on the previous lore switch (type) { case "DEFAULT": { lore.add(toolStats.getLoreFromConfig("created.created-by", true).replace("{date}", format.format(new Date(time)))); @@ -174,7 +184,7 @@ public class CommandToolStats implements TabExecutor { if (container.has(toolStats.swordPlayerKills, PersistentDataType.INTEGER)) { Integer kills = container.get(toolStats.swordPlayerKills, PersistentDataType.INTEGER); if (kills == null) { - return null; + return; } lore.add(toolStats.getLoreFromConfig("kills.player", true).replace("{kills}", Integer.toString(kills))); } @@ -183,7 +193,7 @@ public class CommandToolStats implements TabExecutor { if (container.has(toolStats.swordMobKills, PersistentDataType.INTEGER)) { Integer kills = container.get(toolStats.swordMobKills, PersistentDataType.INTEGER); if (kills == null) { - return null; + return; } lore.add(toolStats.getLoreFromConfig("kills.mob", true).replace("{kills}", Integer.toString(kills))); } @@ -192,7 +202,7 @@ public class CommandToolStats implements TabExecutor { if (container.has(toolStats.genericMined, PersistentDataType.INTEGER)) { Integer blocksMined = container.get(toolStats.genericMined, PersistentDataType.INTEGER); if (blocksMined == null) { - return null; + return; } lore.add(toolStats.getLoreFromConfig("blocks-mined", true).replace("{blocks}", Integer.toString(blocksMined))); } @@ -201,7 +211,7 @@ public class CommandToolStats implements TabExecutor { if (container.has(toolStats.fishingRodCaught, PersistentDataType.INTEGER)) { Integer fish = container.get(toolStats.fishingRodCaught, PersistentDataType.INTEGER); if (fish == null) { - return null; + return; } lore.add(toolStats.getLoreFromConfig("fished.fish-caught", true).replace("{fish}", Integer.toString(fish))); } @@ -210,7 +220,7 @@ public class CommandToolStats implements TabExecutor { if (container.has(toolStats.shearsSheared, PersistentDataType.INTEGER)) { Integer sheep = container.get(toolStats.shearsSheared, PersistentDataType.INTEGER); if (sheep == null) { - return null; + return; } lore.add(toolStats.getLoreFromConfig("sheep-sheared", true).replace("{sheep}", Integer.toString(sheep))); } @@ -219,14 +229,13 @@ public class CommandToolStats implements TabExecutor { if (container.has(toolStats.armorDamage, PersistentDataType.INTEGER)) { Integer damage = container.get(toolStats.armorDamage, PersistentDataType.INTEGER); if (damage == null) { - return null; + return; } lore.add(toolStats.getLoreFromConfig("damage-taken", true).replace("{damage}", Integer.toString(damage))); } } finalMeta.setLore(lore); finalItem.setItemMeta(finalMeta); - return finalItem; } @Nullable diff --git a/src/main/java/lol/hyper/toolstats/events/BlocksMined.java b/src/main/java/lol/hyper/toolstats/events/BlocksMined.java index 1864fe8..cbc4ea9 100644 --- a/src/main/java/lol/hyper/toolstats/events/BlocksMined.java +++ b/src/main/java/lol/hyper/toolstats/events/BlocksMined.java @@ -48,17 +48,21 @@ public class BlocksMined implements Listener { return; } Player player = event.getPlayer(); + // ignore creative mode if (player.getGameMode() != GameMode.SURVIVAL) { return; } + // if the player mines something with their fist ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); if (heldItem == null || heldItem.getType() == Material.AIR) { return; } + // only check certain items String itemName = heldItem.getType().toString().toLowerCase(); if (Arrays.stream(validTools).noneMatch(itemName::contains)) { return; } + // if it's an item we want, update the stats updateBlocksMined(heldItem); } @@ -67,6 +71,8 @@ public class BlocksMined implements Listener { if (meta == null) { return; } + // read the current stats from the item + // if they don't exist, then start from 0 Integer blocksMined = 0; PersistentDataContainer container = meta.getPersistentDataContainer(); if (container.has(toolStats.genericMined, PersistentDataType.INTEGER)) { @@ -82,6 +88,11 @@ public class BlocksMined implements Listener { String configLore = toolStats.getLoreFromConfig("blocks-mined", false); String configLoreRaw = toolStats.getLoreFromConfig("blocks-mined", true); + if (configLore == null || configLoreRaw == null) { + toolStats.logger.warning("There is no lore message for messages.blocks-mined!"); + return; + } + List lore; if (meta.hasLore()) { lore = meta.getLore(); @@ -89,10 +100,6 @@ public class BlocksMined implements Listener { boolean hasLore = false; // we do a for loop like this, we can keep track of index // this doesn't mess the lore up of existing items - if (configLore == null || configLoreRaw == null) { - toolStats.logger.warning("There is no lore message for messages.blocks-mined!"); - return; - } for (int x = 0; x < lore.size(); x++) { if (lore.get(x).contains(configLore)) { hasLore = true; @@ -109,6 +116,7 @@ public class BlocksMined implements Listener { lore = new ArrayList<>(); lore.add(configLoreRaw.replace("{blocks}", Integer.toString(blocksMined))); } + // do we add the lore based on the config? if (toolStats.checkConfig(itemStack, "blocks-mined")) { meta.setLore(lore); } diff --git a/src/main/java/lol/hyper/toolstats/events/ChunkPopulate.java b/src/main/java/lol/hyper/toolstats/events/ChunkPopulate.java index ef3f2fe..2705d39 100644 --- a/src/main/java/lol/hyper/toolstats/events/ChunkPopulate.java +++ b/src/main/java/lol/hyper/toolstats/events/ChunkPopulate.java @@ -53,14 +53,17 @@ public class ChunkPopulate implements Listener { Bukkit.getScheduler().runTaskLater(toolStats, () -> { Chunk chunk = event.getChunk(); for (Entity entity : chunk.getEntities()) { + // if there is a new item frame if (entity instanceof ItemFrame) { ItemFrame itemFrame = (ItemFrame) entity; + // if the item frame has an elytra if (itemFrame.getItem().getType() == Material.ELYTRA) { ItemStack elytraCopy = itemFrame.getItem(); ItemMeta meta = elytraCopy.getItemMeta(); if (meta == null) { return; } + // add the new tag so we know it's new PersistentDataContainer container = meta.getPersistentDataContainer(); container.set(toolStats.newElytra, PersistentDataType.INTEGER, 1); elytraCopy.setItemMeta(meta); diff --git a/src/main/java/lol/hyper/toolstats/events/CraftItem.java b/src/main/java/lol/hyper/toolstats/events/CraftItem.java index 9b4fa9a..623a30f 100644 --- a/src/main/java/lol/hyper/toolstats/events/CraftItem.java +++ b/src/main/java/lol/hyper/toolstats/events/CraftItem.java @@ -56,8 +56,10 @@ public class CraftItem implements Listener { return; } String name = itemStack.getType().toString().toLowerCase(Locale.ROOT); + // only check for items we want for (String x : validItems) { if (name.contains(x)) { + // if the player shift clicks, send them this warning if (event.isShiftClick()) { String configMessage = toolStats.config.getString("messages.shift-click-warning.crafting"); if (configMessage != null) { @@ -66,24 +68,36 @@ public class CraftItem implements Listener { } } } + // test the item before setting it if (addLore(itemStack, player) == null) { return; } + // set the result event.setCurrentItem(addLore(itemStack, player)); } } } + /** + * Adds crafted tags to item. + * @param itemStack The item add item to. + * @param owner The player crafting. + * @return A copy of the item with the tags + lore. + */ private ItemStack addLore(ItemStack itemStack, Player owner) { + // clone the item ItemStack newItem = itemStack.clone(); ItemMeta meta = newItem.getItemMeta(); if (meta == null) { return null; } + // get the current time long timeCreated = System.currentTimeMillis(); Date finalDate = new Date(timeCreated); PersistentDataContainer container = meta.getPersistentDataContainer(); + // if the item already has the tag + // this is to prevent duplicate tags if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.genericOwner, PersistentDataType.LONG)) { return null; } @@ -104,12 +118,14 @@ public class CraftItem implements Listener { } List lore; + // get the current lore the item if (meta.hasLore()) { lore = meta.getLore(); assert lore != null; } else { lore = new ArrayList<>(); } + // do we add the lore based on the config? if (toolStats.checkConfig(itemStack, "created-date")) { lore.add(createdOnRaw.replace("{date}", format.format(finalDate))); } diff --git a/src/main/java/lol/hyper/toolstats/events/EntityDamage.java b/src/main/java/lol/hyper/toolstats/events/EntityDamage.java index 203ab94..b4a9d1b 100644 --- a/src/main/java/lol/hyper/toolstats/events/EntityDamage.java +++ b/src/main/java/lol/hyper/toolstats/events/EntityDamage.java @@ -64,10 +64,12 @@ public class EntityDamage implements Listener { if (player.getGameMode() != GameMode.SURVIVAL) { return; } + // a player killed something with their fist ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); if (heldItem == null || heldItem.getType() == Material.AIR) { return; } + // check items we want String itemName = heldItem.getType().toString().toLowerCase(); if (Arrays.stream(validTools).noneMatch(itemName::contains)) { return; @@ -81,9 +83,11 @@ public class EntityDamage implements Listener { player.getInventory().setItem(player.getInventory().getHeldItemSlot(), updateMobKills(heldItem)); trackedMobs.add(livingEntity.getUniqueId()); } + // trident is being thrown at something if (event.getDamager() instanceof Trident) { Trident trident = (Trident) event.getDamager(); ItemStack clone; + // trident is killing player if (livingEntity instanceof Player) { clone = updatePlayerKills(trident.getItem()); } else { @@ -94,14 +98,18 @@ public class EntityDamage implements Listener { } trident.setItem(clone); } + // arrow is being shot if (event.getDamager() instanceof Arrow) { Arrow arrow = (Arrow) event.getDamager(); + // if the shooter is a player if (arrow.getShooter() instanceof Player) { Player player = (Player) arrow.getShooter(); ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); if (heldItem == null) { return; } + // if the player is holding the bow/crossbow + // if they switch then oh well if (heldItem.getType() == Material.BOW || heldItem.getType() == Material.CROSSBOW) { if (livingEntity instanceof Player) { player.getInventory().setItem(player.getInventory().getHeldItemSlot(), updatePlayerKills(heldItem)); @@ -130,6 +138,7 @@ public class EntityDamage implements Listener { return; } LivingEntity livingEntity = (LivingEntity) event.getEntity(); + // player is taken damage but not being killed if (livingEntity instanceof Player) { Player player = (Player) livingEntity; PlayerInventory inventory = player.getInventory(); @@ -147,6 +156,7 @@ public class EntityDamage implements Listener { return; } LivingEntity livingEntity = (LivingEntity) event.getEntity(); + // player is taken damage but not being killed if (livingEntity instanceof Player) { Player player = (Player) livingEntity; PlayerInventory inventory = player.getInventory(); @@ -158,6 +168,11 @@ public class EntityDamage implements Listener { } } + /** + * Updates a weapon's player kills. + * @param itemStack The item to update. + * @return A copy of the item. + */ private ItemStack updatePlayerKills(ItemStack itemStack) { ItemStack finalItem = itemStack.clone(); ItemMeta meta = finalItem.getItemMeta(); @@ -207,6 +222,7 @@ public class EntityDamage implements Listener { lore = new ArrayList<>(); lore.add(playerKillsLoreRaw.replace("{kills}", Integer.toString(playerKills))); } + // do we add the lore based on the config? if (toolStats.checkConfig(itemStack, "player-kills")) { meta.setLore(lore); } @@ -214,6 +230,11 @@ public class EntityDamage implements Listener { return finalItem; } + /** + * Updates a weapon's mob kills. + * @param itemStack The item to update. + * @return A copy of the item. + */ private ItemStack updateMobKills(ItemStack itemStack) { ItemStack finalItem = itemStack.clone(); ItemMeta meta = finalItem.getItemMeta(); @@ -263,6 +284,7 @@ public class EntityDamage implements Listener { lore = new ArrayList<>(); lore.add(mobKillsLoreRaw.replace("{kills}", Integer.toString(mobKills))); } + // do we add the lore based on the config? if (toolStats.checkConfig(itemStack, "mob-kills")) { meta.setLore(lore); } @@ -270,6 +292,11 @@ public class EntityDamage implements Listener { return finalItem; } + /** + * Updates a player's armor damage stats. + * @param itemStack The armor piece. + * @param damage How much damage is being added. + */ private void updateArmorDamage(ItemStack itemStack, double damage) { ItemMeta meta = itemStack.getItemMeta(); if (meta == null) { diff --git a/src/main/java/lol/hyper/toolstats/events/EntityDeath.java b/src/main/java/lol/hyper/toolstats/events/EntityDeath.java index e585a62..c9faae1 100644 --- a/src/main/java/lol/hyper/toolstats/events/EntityDeath.java +++ b/src/main/java/lol/hyper/toolstats/events/EntityDeath.java @@ -43,6 +43,7 @@ public class EntityDeath implements Listener { return; } UUID livingEntityUUID = event.getEntity().getUniqueId(); + // if it's a mob we are tracking that matters if (toolStats.mobKill.trackedMobs.contains(livingEntityUUID)) { for (ItemStack current : event.getDrops()) { String name = current.getType().toString().toLowerCase(Locale.ROOT); @@ -56,6 +57,11 @@ public class EntityDeath implements Listener { } } + /** + * Adds "drop by" tag to item. + * @param itemStack The item to add lore to. + * @param mob The mob or player name. + */ private void addLore(ItemStack itemStack, String mob) { ItemMeta meta = itemStack.getItemMeta(); if (meta == null) { diff --git a/src/main/java/lol/hyper/toolstats/events/GenerateLoot.java b/src/main/java/lol/hyper/toolstats/events/GenerateLoot.java index a74598d..55b2a6f 100644 --- a/src/main/java/lol/hyper/toolstats/events/GenerateLoot.java +++ b/src/main/java/lol/hyper/toolstats/events/GenerateLoot.java @@ -57,10 +57,13 @@ public class GenerateLoot implements Listener { return; } Inventory chest = inventoryHolder.getInventory(); + // run task later since if it runs on the same tick it breaks idk Bukkit.getScheduler().runTaskLater(toolStats, () -> { Player player = (Player) chest.getViewers().get(0); + // do a classic for loot so we keep track of chest index of item for (int i = 0; i < chest.getContents().length; i++) { ItemStack itemStack = chest.getItem(i); + // ignore air if (itemStack == null || itemStack.getType() == Material.AIR) { continue; } @@ -75,6 +78,12 @@ public class GenerateLoot implements Listener { },1); } + /** + * 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 addLore(ItemStack itemStack, Player owner) { ItemStack newItem = itemStack.clone(); ItemMeta meta = itemStack.getItemMeta(); diff --git a/src/main/java/lol/hyper/toolstats/events/PickupItem.java b/src/main/java/lol/hyper/toolstats/events/PickupItem.java index d6234dc..eda86f4 100644 --- a/src/main/java/lol/hyper/toolstats/events/PickupItem.java +++ b/src/main/java/lol/hyper/toolstats/events/PickupItem.java @@ -68,6 +68,11 @@ public class PickupItem implements Listener { } } + /** + * Adds "looted by" tags for elytras. + * @param itemStack The elytra to add lore to. + * @param owner The player who found it. + */ private void addLore(ItemStack itemStack, Player owner) { ItemMeta meta = itemStack.getItemMeta(); if (meta == null) { diff --git a/src/main/java/lol/hyper/toolstats/events/PlayerFish.java b/src/main/java/lol/hyper/toolstats/events/PlayerFish.java index 20787ad..d815a10 100644 --- a/src/main/java/lol/hyper/toolstats/events/PlayerFish.java +++ b/src/main/java/lol/hyper/toolstats/events/PlayerFish.java @@ -75,6 +75,10 @@ public class PlayerFish implements Listener { } } + /** + * Updates a fishing rod's count. + * @param itemStack The fishing rod to update. + */ private void updateFishCount(ItemStack itemStack) { ItemMeta meta = itemStack.getItemMeta(); if (meta == null) { @@ -129,6 +133,11 @@ public class PlayerFish implements Listener { itemStack.setItemMeta(meta); } + /** + * Adds "caught by" tags to newly fished items. + * @param itemStack The item to add lore to. + * @param owner The player who caught the item. + */ private void addNewLore(ItemStack itemStack, Player owner) { ItemMeta meta = itemStack.getItemMeta(); if (meta == null) { diff --git a/src/main/java/lol/hyper/toolstats/events/SheepShear.java b/src/main/java/lol/hyper/toolstats/events/SheepShear.java index 3bd0c71..e5c48c7 100644 --- a/src/main/java/lol/hyper/toolstats/events/SheepShear.java +++ b/src/main/java/lol/hyper/toolstats/events/SheepShear.java @@ -51,17 +51,23 @@ public class SheepShear implements Listener { if (!(entity instanceof Sheep)) { return; } + // check if the player is right-clicking with shears only ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); if (heldItem == null || heldItem.getType() == Material.AIR || heldItem.getType() != Material.SHEARS) { return; } Sheep sheep = (Sheep) entity; + // make sure the sheep is not sheared if (!sheep.isSheared()) { addLore(heldItem); } } + /** + * Adds tags to shears. + * @param itemStack The shears. + */ private void addLore(ItemStack itemStack) { ItemMeta meta = itemStack.getItemMeta(); if (meta == null) { diff --git a/src/main/java/lol/hyper/toolstats/events/VillagerTrade.java b/src/main/java/lol/hyper/toolstats/events/VillagerTrade.java index 6eec1b2..cef456f 100644 --- a/src/main/java/lol/hyper/toolstats/events/VillagerTrade.java +++ b/src/main/java/lol/hyper/toolstats/events/VillagerTrade.java @@ -57,11 +57,15 @@ public class VillagerTrade implements Listener { return; } Inventory inventory = event.getClickedInventory(); + // only check villager inventories if (inventory instanceof MerchantInventory) { + // only check the result slot (the item you receive) if (event.getSlotType() == InventoryType.SlotType.RESULT) { ItemStack item = event.getCurrentItem(); + // only check items we want for (String x : validItems) { if (item.getType().toString().toLowerCase(Locale.ROOT).contains(x)) { + // if the player shift clicks show the warning if (event.isShiftClick()) { String configMessage = toolStats.config.getString("messages.shift-click-warning.trading"); if (configMessage != null) { @@ -72,6 +76,8 @@ public class VillagerTrade implements Listener { if (newItem == null) { return; } + // this gets delayed since villager inventories suck for no reason + // if you don't delay this it doesn't work idk Bukkit.getScheduler().runTaskLater(toolStats, ()-> event.setCurrentItem(newItem), 5); } } @@ -79,6 +85,12 @@ public class VillagerTrade implements Listener { } } + /** + * Adds "traded by" tags to item. + * @param itemStack The item to add lore. + * @param owner The player who traded. + * @return The item with lore. + */ private ItemStack addLore(ItemStack itemStack, Player owner) { ItemMeta meta = itemStack.getItemMeta(); if (meta == null) {