Compare commits

...

18 Commits
1.2.3 ... 1.3.2

Author SHA1 Message Date
hyperdefined
df23f40d6b Update pom.xml 2022-02-22 15:08:38 -05:00
hyperdefined
0221ee40cf handle logic of lore reset better 2022-02-22 15:07:51 -05:00
hyperdefined
a01d07af4a fixed removing new tag for elytras
this fixes #5
2022-02-22 15:07:30 -05:00
hyperdefined
e402d3078a Merge pull request #4 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.10.0
Bump maven-compiler-plugin from 3.9.0 to 3.10.0
2022-02-14 21:07:02 -05:00
dependabot[bot]
4f44ca0777 Bump maven-compiler-plugin from 3.9.0 to 3.10.0
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.9.0 to 3.10.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.9.0...maven-compiler-plugin-3.10.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 11:38:14 +00:00
hyperdefined
53fd7f734c Update pom.xml 2022-02-12 20:47:52 -05:00
hyperdefined
75cd4fa17e fixed small typo 2022-02-12 20:47:32 -05:00
hyperdefined
e296c27a5b added comments to better explain what is going on 2022-02-11 19:19:05 -05:00
hyperdefined
adb1c637dc smh 2022-02-11 18:34:42 -05:00
hyperdefined
4b8f8061b4 Merge branch 'master' of https://github.com/hyperdefined/ToolStats 2022-02-11 15:09:49 -05:00
hyperdefined
464916e08b Update CommandToolStats.java 2022-02-11 15:09:32 -05:00
hyperdefined
6b6b65d1df Update README.md 2022-02-11 15:05:55 -05:00
hyperdefined
a1c39dffd0 Update pom.xml 2022-02-11 15:05:18 -05:00
hyperdefined
88eab81906 added tab completions to sub commands 2022-02-11 15:03:37 -05:00
hyperdefined
be233de90d fixed plugin.yml 2022-02-11 15:03:21 -05:00
hyperdefined
2437424e39 added reset lore command 2022-02-11 14:46:25 -05:00
hyperdefined
63b08062c8 Update CraftItem.java 2022-02-11 14:04:12 -05:00
hyperdefined
d23c2446dd fix fishing rods not updating lore correctly 2022-02-11 14:03:51 -05:00
15 changed files with 361 additions and 19 deletions

View File

@@ -23,6 +23,8 @@ Here is everything it tracks:
The best part is, this data is stored on the item itself. You can also change how the lore is displayed on the items! The best part is, this data is stored on the item itself. You can also change how the lore is displayed on the items!
If item lore is ever incorrect, you can run `/toolstats reset` to reset the item lore so it's correct.
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image.png) ![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image2.png) ![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image2.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image3.png) ![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image3.png)

View File

@@ -23,7 +23,7 @@
<groupId>lol.hyper</groupId> <groupId>lol.hyper</groupId>
<artifactId>toolstats</artifactId> <artifactId>toolstats</artifactId>
<version>1.2.3</version> <version>1.3.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>ToolStats</name> <name>ToolStats</name>
@@ -51,7 +51,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version> <version>3.10.0</version>
<configuration> <configuration>
<source>${java.version}</source> <source>${java.version}</source>
<target>${java.version}</target> <target>${java.version}</target>

View File

@@ -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) { public boolean checkConfig(ItemStack itemStack, String configName) {
String itemName = itemStack.getType().toString().toLowerCase(); String itemName = itemStack.getType().toString().toLowerCase();
String itemType = null; String itemType = null;
@@ -202,6 +208,12 @@ public final class ToolStats extends JavaPlugin {
return false; 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) { public String getLoreFromConfig(String configName, boolean raw) {
String lore = config.getString("messages." + configName); String lore = config.getString("messages." + configName);
if (lore == null) { if (lore == null) {
@@ -235,6 +247,9 @@ public final class ToolStats extends JavaPlugin {
if (lore.contains("{damage}")) { if (lore.contains("{damage}")) {
lore = lore.replace("{damage}", ""); lore = lore.replace("{damage}", "");
} }
if (lore.contains("{fish}")) {
lore = lore.replace("{fish}", "");
}
} }
return lore; return lore;
} }

View File

@@ -18,36 +18,255 @@
package lol.hyper.toolstats.commands; package lol.hyper.toolstats.commands;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor; import lol.hyper.toolstats.UUIDDataType;
import org.bukkit.*;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CommandToolStats implements CommandExecutor { import java.text.SimpleDateFormat;
import java.util.*;
public class CommandToolStats implements TabExecutor {
private final ToolStats toolStats; private final ToolStats toolStats;
public CommandToolStats(ToolStats toolStats) { public CommandToolStats(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
} }
private final SimpleDateFormat format = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH);
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!sender.hasPermission("toolstats.use")) {
sender.sendMessage(ChatColor.RED + "You do not have permission for this command.");
return true;
}
if (args.length == 0) { if (args.length == 0) {
sender.sendMessage(ChatColor.GREEN + "ToolStats version " + toolStats.getDescription().getVersion() + ". Created by hyperdefined."); sender.sendMessage(ChatColor.GREEN + "ToolStats version " + toolStats.getDescription().getVersion() + ". Created by hyperdefined.");
} else if (args.length == 1) { }
if (args[0].equalsIgnoreCase("reload")) { switch (args[0]) {
case "reload": {
if (sender.isOp() || sender.hasPermission("toolstats.reload")) { if (sender.isOp() || sender.hasPermission("toolstats.reload")) {
toolStats.loadConfig(); toolStats.loadConfig();
sender.sendMessage(ChatColor.GREEN + "Configuration reloaded!"); sender.sendMessage(ChatColor.GREEN + "Configuration reloaded!");
} else { } else {
sender.sendMessage(ChatColor.RED + "You do not have permission for this command."); sender.sendMessage(ChatColor.RED + "You do not have permission for this command.");
} }
} else { return true;
}
case "reset": {
if (args.length == 2 && args[1].equalsIgnoreCase("confirm")) {
Player player = (Player) sender;
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (heldItem.getType() == Material.AIR) {
sender.sendMessage(ChatColor.RED + "You must hold an item!");
return true;
}
fixItemLore(heldItem, player);
sender.sendMessage(ChatColor.GREEN + "The lore was reset!");
return true;
}
sender.sendMessage(ChatColor.GREEN + "This will remove ALL current lore from the held item and replace it with the correct lore.");
sender.sendMessage(ChatColor.GREEN + "The item owner will be who ever is currently running this command.");
sender.sendMessage(ChatColor.GREEN + "Only use this if the tags on the tool are incorrect.");
sender.sendMessage(ChatColor.GREEN + "Type /toolstats reset confirm to confirm this.");
return true;
}
default: {
sender.sendMessage(ChatColor.RED + "Invalid sub-command."); sender.sendMessage(ChatColor.RED + "Invalid sub-command.");
} }
} }
return true; return true;
} }
/**
* 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;
}
PersistentDataContainer container = finalMeta.getPersistentDataContainer();
List<String> lore = new ArrayList<>();
String caughtByLore = toolStats.getLoreFromConfig("fished.caught-by", false);
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;
}
// 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) {
for (String line : finalMeta.getLore()) {
if (line.contains(caughtByLore)) {
type = "CAUGHT";
}
if (line.contains(lootedByLore)) {
type = "LOOTED";
}
if (line.contains(tradedByLore)) {
type = "TRADED";
}
}
}
}
// hard code elytras
if (finalItem.getType() == Material.ELYTRA) {
if (toolStats.config.getBoolean("enabled.elytra-tag")) {
lore.add(toolStats.getLoreFromConfig("looted.found-by", true).replace("{player}", player.getName()));
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) {
Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG);
if (time != null) {
lore.add(toolStats.getLoreFromConfig("looted.found-on", true).replace("{date}", format.format(new Date(time))));
}
}
finalMeta.setLore(lore);
finalItem.setItemMeta(finalMeta);
int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem);
return;
}
}
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()));
break;
}
case "CAUGHT": {
lore.add(toolStats.getLoreFromConfig("fished.caught-by", true).replace("{player}", player.getName()));
break;
}
case "LOOTED": {
lore.add(toolStats.getLoreFromConfig("looted.found-by", true).replace("{player}", player.getName()));
break;
}
case "TRADED": {
lore.add(toolStats.getLoreFromConfig("traded.traded-by", true).replace("{player}", player.getName()));
break;
}
}
}
}
if (toolStats.checkConfig(original, "created-date")) {
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) {
Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG);
if (time != null) {
// show how when the item was created based on the previous lore
switch (type) {
case "DEFAULT": {
lore.add(toolStats.getLoreFromConfig("created.created-on", true).replace("{date}", format.format(new Date(time))));
break;
}
case "CAUGHT": {
lore.add(toolStats.getLoreFromConfig("fished.caught-on", true).replace("{date}", format.format(new Date(time))));
break;
}
case "LOOTED": {
lore.add(toolStats.getLoreFromConfig("looted.foundon", true).replace("{date}", format.format(new Date(time))));
break;
}
case "TRADED": {
lore.add(toolStats.getLoreFromConfig("traded.traded-on", true).replace("{date}", format.format(new Date(time))));
break;
}
}
}
}
}
if (toolStats.checkConfig(original, "player-kills")) {
if (container.has(toolStats.swordPlayerKills, PersistentDataType.INTEGER)) {
Integer kills = container.get(toolStats.swordPlayerKills, PersistentDataType.INTEGER);
if (kills != null) {
lore.add(toolStats.getLoreFromConfig("kills.player", true).replace("{kills}", Integer.toString(kills)));
}
}
}
if (toolStats.checkConfig(original, "mob-kills")) {
if (container.has(toolStats.swordMobKills, PersistentDataType.INTEGER)) {
Integer kills = container.get(toolStats.swordMobKills, PersistentDataType.INTEGER);
if (kills != null) {
lore.add(toolStats.getLoreFromConfig("kills.mob", true).replace("{kills}", Integer.toString(kills)));
}
}
}
if (toolStats.checkConfig(original, "blocks-mined")) {
if (container.has(toolStats.genericMined, PersistentDataType.INTEGER)) {
Integer blocksMined = container.get(toolStats.genericMined, PersistentDataType.INTEGER);
if (blocksMined != null) {
lore.add(toolStats.getLoreFromConfig("blocks-mined", true).replace("{blocks}", Integer.toString(blocksMined)));
}
}
}
if (toolStats.config.getBoolean("enabled.fish-caught")) {
if (container.has(toolStats.fishingRodCaught, PersistentDataType.INTEGER)) {
Integer fish = container.get(toolStats.fishingRodCaught, PersistentDataType.INTEGER);
if (fish != null) {
lore.add(toolStats.getLoreFromConfig("fished.fish-caught", true).replace("{fish}", Integer.toString(fish)));
}
}
}
if (toolStats.config.getBoolean("enabled.sheep-sheared")) {
if (container.has(toolStats.shearsSheared, PersistentDataType.INTEGER)) {
Integer sheep = container.get(toolStats.shearsSheared, PersistentDataType.INTEGER);
if (sheep != null) {
lore.add(toolStats.getLoreFromConfig("sheep-sheared", true).replace("{sheep}", Integer.toString(sheep)));
}
}
}
if (toolStats.config.getBoolean("enabled.armor-damage")) {
if (container.has(toolStats.armorDamage, PersistentDataType.INTEGER)) {
Integer damage = container.get(toolStats.armorDamage, PersistentDataType.INTEGER);
if (damage != null) {
lore.add(toolStats.getLoreFromConfig("damage-taken", true).replace("{damage}", Integer.toString(damage)));
}
}
}
finalMeta.setLore(lore);
finalItem.setItemMeta(finalMeta);
int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem);
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
if (args.length == 1) {
if (sender.hasPermission("toolstats.reload")) {
return Arrays.asList("reset", "reload");
} else {
return Collections.singletonList("reset");
}
}
if (args.length == 2) {
if (args[0].equalsIgnoreCase("reset")) {
return Collections.singletonList("confirm");
}
}
return null;
}
} }

View File

@@ -48,17 +48,21 @@ public class BlocksMined implements Listener {
return; return;
} }
Player player = event.getPlayer(); Player player = event.getPlayer();
// ignore creative mode
if (player.getGameMode() != GameMode.SURVIVAL) { if (player.getGameMode() != GameMode.SURVIVAL) {
return; return;
} }
// if the player mines something with their fist
ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot());
if (heldItem == null || heldItem.getType() == Material.AIR) { if (heldItem == null || heldItem.getType() == Material.AIR) {
return; return;
} }
// only check certain items
String itemName = heldItem.getType().toString().toLowerCase(); String itemName = heldItem.getType().toString().toLowerCase();
if (Arrays.stream(validTools).noneMatch(itemName::contains)) { if (Arrays.stream(validTools).noneMatch(itemName::contains)) {
return; return;
} }
// if it's an item we want, update the stats
updateBlocksMined(heldItem); updateBlocksMined(heldItem);
} }
@@ -67,6 +71,8 @@ public class BlocksMined implements Listener {
if (meta == null) { if (meta == null) {
return; return;
} }
// read the current stats from the item
// if they don't exist, then start from 0
Integer blocksMined = 0; Integer blocksMined = 0;
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.genericMined, PersistentDataType.INTEGER)) { if (container.has(toolStats.genericMined, PersistentDataType.INTEGER)) {
@@ -82,6 +88,11 @@ public class BlocksMined implements Listener {
String configLore = toolStats.getLoreFromConfig("blocks-mined", false); String configLore = toolStats.getLoreFromConfig("blocks-mined", false);
String configLoreRaw = toolStats.getLoreFromConfig("blocks-mined", true); 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<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -89,10 +100,6 @@ public class BlocksMined implements Listener {
boolean hasLore = false; boolean hasLore = false;
// we do a for loop like this, we can keep track of index // we do a for loop like this, we can keep track of index
// this doesn't mess the lore up of existing items // 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++) { for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains(configLore)) { if (lore.get(x).contains(configLore)) {
hasLore = true; hasLore = true;
@@ -109,6 +116,7 @@ public class BlocksMined implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(configLoreRaw.replace("{blocks}", Integer.toString(blocksMined))); lore.add(configLoreRaw.replace("{blocks}", Integer.toString(blocksMined)));
} }
// do we add the lore based on the config?
if (toolStats.checkConfig(itemStack, "blocks-mined")) { if (toolStats.checkConfig(itemStack, "blocks-mined")) {
meta.setLore(lore); meta.setLore(lore);
} }

View File

@@ -53,14 +53,17 @@ public class ChunkPopulate implements Listener {
Bukkit.getScheduler().runTaskLater(toolStats, () -> { Bukkit.getScheduler().runTaskLater(toolStats, () -> {
Chunk chunk = event.getChunk(); Chunk chunk = event.getChunk();
for (Entity entity : chunk.getEntities()) { for (Entity entity : chunk.getEntities()) {
// if there is a new item frame
if (entity instanceof ItemFrame) { if (entity instanceof ItemFrame) {
ItemFrame itemFrame = (ItemFrame) entity; ItemFrame itemFrame = (ItemFrame) entity;
// if the item frame has an elytra
if (itemFrame.getItem().getType() == Material.ELYTRA) { if (itemFrame.getItem().getType() == Material.ELYTRA) {
ItemStack elytraCopy = itemFrame.getItem(); ItemStack elytraCopy = itemFrame.getItem();
ItemMeta meta = elytraCopy.getItemMeta(); ItemMeta meta = elytraCopy.getItemMeta();
if (meta == null) { if (meta == null) {
return; return;
} }
// add the new tag so we know it's new
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(toolStats.newElytra, PersistentDataType.INTEGER, 1); container.set(toolStats.newElytra, PersistentDataType.INTEGER, 1);
elytraCopy.setItemMeta(meta); elytraCopy.setItemMeta(meta);

View File

@@ -56,32 +56,48 @@ public class CraftItem implements Listener {
return; return;
} }
String name = itemStack.getType().toString().toLowerCase(Locale.ROOT); String name = itemStack.getType().toString().toLowerCase(Locale.ROOT);
// only check for items we want
for (String x : validItems) { for (String x : validItems) {
if (name.contains(x)) { if (name.contains(x)) {
// if the player shift clicks, send them this warning
if (event.isShiftClick()) { if (event.isShiftClick()) {
String configMessage = toolStats.config.getString("messages.shift-click-warning.crafting"); String configMessage = toolStats.config.getString("messages.shift-click-warning.crafting");
if (configMessage != null) { if (configMessage != null) {
event.getWhoClicked().sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage)); if (configMessage.length() != 0) {
event.getWhoClicked().sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage));
}
} }
} }
// test the item before setting it
if (addLore(itemStack, player) == null) { if (addLore(itemStack, player) == null) {
return; return;
} }
// set the result
event.setCurrentItem(addLore(itemStack, player)); 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) { private ItemStack addLore(ItemStack itemStack, Player owner) {
// clone the item
ItemStack newItem = itemStack.clone(); ItemStack newItem = itemStack.clone();
ItemMeta meta = newItem.getItemMeta(); ItemMeta meta = newItem.getItemMeta();
if (meta == null) { if (meta == null) {
return null; return null;
} }
// get the current time
long timeCreated = System.currentTimeMillis(); long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated); Date finalDate = new Date(timeCreated);
PersistentDataContainer container = meta.getPersistentDataContainer(); 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)) { if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.genericOwner, PersistentDataType.LONG)) {
return null; return null;
} }
@@ -102,12 +118,14 @@ public class CraftItem implements Listener {
} }
List<String> lore; List<String> lore;
// get the current lore the item
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
assert lore != null; assert lore != null;
} else { } else {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
// do we add the lore based on the config?
if (toolStats.checkConfig(itemStack, "created-date")) { if (toolStats.checkConfig(itemStack, "created-date")) {
lore.add(createdOnRaw.replace("{date}", format.format(finalDate))); lore.add(createdOnRaw.replace("{date}", format.format(finalDate)));
} }

View File

@@ -64,10 +64,12 @@ public class EntityDamage implements Listener {
if (player.getGameMode() != GameMode.SURVIVAL) { if (player.getGameMode() != GameMode.SURVIVAL) {
return; return;
} }
// a player killed something with their fist
ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot());
if (heldItem == null || heldItem.getType() == Material.AIR) { if (heldItem == null || heldItem.getType() == Material.AIR) {
return; return;
} }
// check items we want
String itemName = heldItem.getType().toString().toLowerCase(); String itemName = heldItem.getType().toString().toLowerCase();
if (Arrays.stream(validTools).noneMatch(itemName::contains)) { if (Arrays.stream(validTools).noneMatch(itemName::contains)) {
return; return;
@@ -81,9 +83,11 @@ public class EntityDamage implements Listener {
player.getInventory().setItem(player.getInventory().getHeldItemSlot(), updateMobKills(heldItem)); player.getInventory().setItem(player.getInventory().getHeldItemSlot(), updateMobKills(heldItem));
trackedMobs.add(livingEntity.getUniqueId()); trackedMobs.add(livingEntity.getUniqueId());
} }
// trident is being thrown at something
if (event.getDamager() instanceof Trident) { if (event.getDamager() instanceof Trident) {
Trident trident = (Trident) event.getDamager(); Trident trident = (Trident) event.getDamager();
ItemStack clone; ItemStack clone;
// trident is killing player
if (livingEntity instanceof Player) { if (livingEntity instanceof Player) {
clone = updatePlayerKills(trident.getItem()); clone = updatePlayerKills(trident.getItem());
} else { } else {
@@ -94,14 +98,18 @@ public class EntityDamage implements Listener {
} }
trident.setItem(clone); trident.setItem(clone);
} }
// arrow is being shot
if (event.getDamager() instanceof Arrow) { if (event.getDamager() instanceof Arrow) {
Arrow arrow = (Arrow) event.getDamager(); Arrow arrow = (Arrow) event.getDamager();
// if the shooter is a player
if (arrow.getShooter() instanceof Player) { if (arrow.getShooter() instanceof Player) {
Player player = (Player) arrow.getShooter(); Player player = (Player) arrow.getShooter();
ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot());
if (heldItem == null) { if (heldItem == null) {
return; 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 (heldItem.getType() == Material.BOW || heldItem.getType() == Material.CROSSBOW) {
if (livingEntity instanceof Player) { if (livingEntity instanceof Player) {
player.getInventory().setItem(player.getInventory().getHeldItemSlot(), updatePlayerKills(heldItem)); player.getInventory().setItem(player.getInventory().getHeldItemSlot(), updatePlayerKills(heldItem));
@@ -130,6 +138,7 @@ public class EntityDamage implements Listener {
return; return;
} }
LivingEntity livingEntity = (LivingEntity) event.getEntity(); LivingEntity livingEntity = (LivingEntity) event.getEntity();
// player is taken damage but not being killed
if (livingEntity instanceof Player) { if (livingEntity instanceof Player) {
Player player = (Player) livingEntity; Player player = (Player) livingEntity;
PlayerInventory inventory = player.getInventory(); PlayerInventory inventory = player.getInventory();
@@ -147,6 +156,7 @@ public class EntityDamage implements Listener {
return; return;
} }
LivingEntity livingEntity = (LivingEntity) event.getEntity(); LivingEntity livingEntity = (LivingEntity) event.getEntity();
// player is taken damage but not being killed
if (livingEntity instanceof Player) { if (livingEntity instanceof Player) {
Player player = (Player) livingEntity; Player player = (Player) livingEntity;
PlayerInventory inventory = player.getInventory(); 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) { private ItemStack updatePlayerKills(ItemStack itemStack) {
ItemStack finalItem = itemStack.clone(); ItemStack finalItem = itemStack.clone();
ItemMeta meta = finalItem.getItemMeta(); ItemMeta meta = finalItem.getItemMeta();
@@ -207,6 +222,7 @@ public class EntityDamage implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(playerKillsLoreRaw.replace("{kills}", Integer.toString(playerKills))); lore.add(playerKillsLoreRaw.replace("{kills}", Integer.toString(playerKills)));
} }
// do we add the lore based on the config?
if (toolStats.checkConfig(itemStack, "player-kills")) { if (toolStats.checkConfig(itemStack, "player-kills")) {
meta.setLore(lore); meta.setLore(lore);
} }
@@ -214,6 +230,11 @@ public class EntityDamage implements Listener {
return finalItem; 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) { private ItemStack updateMobKills(ItemStack itemStack) {
ItemStack finalItem = itemStack.clone(); ItemStack finalItem = itemStack.clone();
ItemMeta meta = finalItem.getItemMeta(); ItemMeta meta = finalItem.getItemMeta();
@@ -263,6 +284,7 @@ public class EntityDamage implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(mobKillsLoreRaw.replace("{kills}", Integer.toString(mobKills))); lore.add(mobKillsLoreRaw.replace("{kills}", Integer.toString(mobKills)));
} }
// do we add the lore based on the config?
if (toolStats.checkConfig(itemStack, "mob-kills")) { if (toolStats.checkConfig(itemStack, "mob-kills")) {
meta.setLore(lore); meta.setLore(lore);
} }
@@ -270,6 +292,11 @@ public class EntityDamage implements Listener {
return finalItem; 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) { private void updateArmorDamage(ItemStack itemStack, double damage) {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {

View File

@@ -43,6 +43,7 @@ public class EntityDeath implements Listener {
return; return;
} }
UUID livingEntityUUID = event.getEntity().getUniqueId(); UUID livingEntityUUID = event.getEntity().getUniqueId();
// if it's a mob we are tracking that matters
if (toolStats.mobKill.trackedMobs.contains(livingEntityUUID)) { if (toolStats.mobKill.trackedMobs.contains(livingEntityUUID)) {
for (ItemStack current : event.getDrops()) { for (ItemStack current : event.getDrops()) {
String name = current.getType().toString().toLowerCase(Locale.ROOT); 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) { private void addLore(ItemStack itemStack, String mob) {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {
@@ -87,7 +93,7 @@ public class EntityDeath implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
if (!hasTag) { if (!hasTag) {
lore.add(droppedByLoreRaw.replace("X", mob)); lore.add(droppedByLoreRaw.replace("{name}", mob));
} }
if (toolStats.config.getBoolean("enabled.dropped-by")) { if (toolStats.config.getBoolean("enabled.dropped-by")) {
meta.setLore(lore); meta.setLore(lore);

View File

@@ -57,10 +57,13 @@ public class GenerateLoot implements Listener {
return; return;
} }
Inventory chest = inventoryHolder.getInventory(); Inventory chest = inventoryHolder.getInventory();
// run task later since if it runs on the same tick it breaks idk
Bukkit.getScheduler().runTaskLater(toolStats, () -> { Bukkit.getScheduler().runTaskLater(toolStats, () -> {
Player player = (Player) chest.getViewers().get(0); 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++) { for (int i = 0; i < chest.getContents().length; i++) {
ItemStack itemStack = chest.getItem(i); ItemStack itemStack = chest.getItem(i);
// ignore air
if (itemStack == null || itemStack.getType() == Material.AIR) { if (itemStack == null || itemStack.getType() == Material.AIR) {
continue; continue;
} }
@@ -75,6 +78,12 @@ public class GenerateLoot implements Listener {
},1); },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) { private ItemStack addLore(ItemStack itemStack, Player owner) {
ItemStack newItem = itemStack.clone(); ItemStack newItem = itemStack.clone();
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();

View File

@@ -61,13 +61,17 @@ public class PickupItem implements Listener {
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
// the elytra has the new key, set the lore to it // the elytra has the new key, set the lore to it
if (container.has(toolStats.newElytra, PersistentDataType.INTEGER)) { if (container.has(toolStats.newElytra, PersistentDataType.INTEGER)) {
container.remove(toolStats.newElytra);
addLore(itemStack, (Player) event.getEntity()); addLore(itemStack, (Player) event.getEntity());
} }
} }
} }
} }
/**
* 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) { private void addLore(ItemStack itemStack, Player owner) {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {
@@ -78,6 +82,7 @@ public class PickupItem implements Listener {
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated); container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.genericOwner, new UUIDDataType(), owner.getUniqueId()); container.set(toolStats.genericOwner, new UUIDDataType(), owner.getUniqueId());
container.remove(toolStats.newElytra);
String foundByLoreRaw = toolStats.getLoreFromConfig("looted.found-by", true); String foundByLoreRaw = toolStats.getLoreFromConfig("looted.found-by", true);
String foundOnLoreRaw = toolStats.getLoreFromConfig("looted.found-on", true); String foundOnLoreRaw = toolStats.getLoreFromConfig("looted.found-on", true);

View File

@@ -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) { private void updateFishCount(ItemStack itemStack) {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {
@@ -129,6 +133,11 @@ public class PlayerFish implements Listener {
itemStack.setItemMeta(meta); 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) { private void addNewLore(ItemStack itemStack, Player owner) {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {

View File

@@ -51,17 +51,23 @@ public class SheepShear implements Listener {
if (!(entity instanceof Sheep)) { if (!(entity instanceof Sheep)) {
return; return;
} }
// check if the player is right-clicking with shears only
ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot()); ItemStack heldItem = player.getInventory().getItem(player.getInventory().getHeldItemSlot());
if (heldItem == null || heldItem.getType() == Material.AIR || heldItem.getType() != Material.SHEARS) { if (heldItem == null || heldItem.getType() == Material.AIR || heldItem.getType() != Material.SHEARS) {
return; return;
} }
Sheep sheep = (Sheep) entity; Sheep sheep = (Sheep) entity;
// make sure the sheep is not sheared
if (!sheep.isSheared()) { if (!sheep.isSheared()) {
addLore(heldItem); addLore(heldItem);
} }
} }
/**
* Adds tags to shears.
* @param itemStack The shears.
*/
private void addLore(ItemStack itemStack) { private void addLore(ItemStack itemStack) {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {

View File

@@ -57,11 +57,15 @@ public class VillagerTrade implements Listener {
return; return;
} }
Inventory inventory = event.getClickedInventory(); Inventory inventory = event.getClickedInventory();
// only check villager inventories
if (inventory instanceof MerchantInventory) { if (inventory instanceof MerchantInventory) {
// only check the result slot (the item you receive)
if (event.getSlotType() == InventoryType.SlotType.RESULT) { if (event.getSlotType() == InventoryType.SlotType.RESULT) {
ItemStack item = event.getCurrentItem(); ItemStack item = event.getCurrentItem();
// only check items we want
for (String x : validItems) { for (String x : validItems) {
if (item.getType().toString().toLowerCase(Locale.ROOT).contains(x)) { if (item.getType().toString().toLowerCase(Locale.ROOT).contains(x)) {
// if the player shift clicks show the warning
if (event.isShiftClick()) { if (event.isShiftClick()) {
String configMessage = toolStats.config.getString("messages.shift-click-warning.trading"); String configMessage = toolStats.config.getString("messages.shift-click-warning.trading");
if (configMessage != null) { if (configMessage != null) {
@@ -72,6 +76,8 @@ public class VillagerTrade implements Listener {
if (newItem == null) { if (newItem == null) {
return; 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); 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) { private ItemStack addLore(ItemStack itemStack, Player owner) {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {

View File

@@ -8,8 +8,11 @@ commands:
toolstats: toolstats:
usage: /toolstats usage: /toolstats
description: Main command. description: Main command.
permission: randomenchant.reload permission: toolstats.main
permissions: permissions:
randomenchant.reload: toolstats.main:
description: Allows the usage of /randomenchant reload description: Allows the usage of /toolstats
default: op default: true
toolstats.reload:
description: Allows the usage of /toolstats reload
default: op