Compare commits

...

7 Commits
1.1 ... 1.2.3

Author SHA1 Message Date
hyperdefined
77b1be62d4 fixes 2022-02-10 21:41:23 -05:00
hyperdefined
29e6c998cf bump 2022-02-06 12:27:58 -05:00
hyperdefined
89951611fe changed api version to support more versions 2022-02-06 12:27:18 -05:00
hyperdefined
1c18a1a90c added missing check (fixes #2) 2022-02-05 16:42:42 -05:00
hyperdefined
f0ec409ef4 Update README.md 2022-01-31 17:40:51 -05:00
hyperdefined
0f9d75db06 Update pom.xml 2022-01-31 17:40:32 -05:00
hyperdefined
975445b8f3 support for custom lore messages 2022-01-31 17:40:10 -05:00
14 changed files with 276 additions and 68 deletions

View File

@@ -1,7 +1,7 @@
<h1 align="center">ToolStats</h1> <h1 align="center">ToolStats</h1>
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/Minecraft-1.18+-orange" alt="Minecraft versions"> <img src="https://img.shields.io/badge/Minecraft-1.15+-orange" alt="Minecraft versions">
<img src="https://img.shields.io/github/v/release/hyperdefined/ToolStats" alt="GitHub release (latest by date)"> <img src="https://img.shields.io/github/v/release/hyperdefined/ToolStats" alt="GitHub release (latest by date)">
<a href="https://github.com/hyperdefined/ToolStats/releases"><img src="https://img.shields.io/github/downloads/hyperdefined/ToolStats/total?logo=github" alt="Downloads"></a> <a href="https://github.com/hyperdefined/ToolStats/releases"><img src="https://img.shields.io/github/downloads/hyperdefined/ToolStats/total?logo=github" alt="Downloads"></a>
<a href="https://en.cryptobadges.io/donate/1F29aNKQzci3ga5LDcHHawYzFPXvELTFoL"><img src="https://en.cryptobadges.io/badge/micro/1F29aNKQzci3ga5LDcHHawYzFPXvELTFoL" alt="Donate with Bitcoin"></a> <a href="https://en.cryptobadges.io/donate/1F29aNKQzci3ga5LDcHHawYzFPXvELTFoL"><img src="https://en.cryptobadges.io/badge/micro/1F29aNKQzci3ga5LDcHHawYzFPXvELTFoL" alt="Donate with Bitcoin"></a>
@@ -21,7 +21,7 @@ Here is everything it tracks:
* Fish caught. * Fish caught.
* Sheep sheared. * Sheep sheared.
The best part is, this data is stored on the item itself. The best part is, this data is stored on the item itself. You can also change how the lore is displayed on the items!
![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)

View File

@@ -23,7 +23,7 @@
<groupId>lol.hyper</groupId> <groupId>lol.hyper</groupId>
<artifactId>toolstats</artifactId> <artifactId>toolstats</artifactId>
<version>1.1</version> <version>1.2.3</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>ToolStats</name> <name>ToolStats</name>

View File

@@ -23,6 +23,7 @@ import lol.hyper.toolstats.commands.CommandToolStats;
import lol.hyper.toolstats.events.*; import lol.hyper.toolstats.events.*;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
@@ -73,7 +74,7 @@ public final class ToolStats extends JavaPlugin {
public final Logger logger = this.getLogger(); public final Logger logger = this.getLogger();
public final File configFile = new File(this.getDataFolder(), "config.yml"); public final File configFile = new File(this.getDataFolder(), "config.yml");
public FileConfiguration config; public FileConfiguration config;
public final int CONFIG_VERSION = 2; public final int CONFIG_VERSION = 3;
@Override @Override
public void onEnable() { public void onEnable() {
@@ -200,4 +201,41 @@ public final class ToolStats extends JavaPlugin {
} }
return false; return false;
} }
public String getLoreFromConfig(String configName, boolean raw) {
String lore = config.getString("messages." + configName);
if (lore == null) {
return null;
}
if (raw) {
return ChatColor.translateAlternateColorCodes('&', lore);
} else {
// we basically add the color codes then remove them
// this is a dirty trick to remove color codes
lore = ChatColor.translateAlternateColorCodes('&', lore);
lore = ChatColor.stripColor(lore);
if (lore.contains("{player}")) {
lore = lore.replace("{player}", "");
}
if (lore.contains("{date}")) {
lore = lore.replace("{date}", "");
}
if (lore.contains("{name}")) {
lore = lore.replace("{name}", "");
}
if (lore.contains("{kills}")) {
lore = lore.replace("{kills}", "");
}
if (lore.contains("{blocks}")) {
lore = lore.replace("{blocks}", "");
}
if (lore.contains("{sheep}")) {
lore = lore.replace("{sheep}", "");
}
if (lore.contains("{damage}")) {
lore = lore.replace("{damage}", "");
}
}
return lore;
}
} }

View File

@@ -18,7 +18,6 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -38,7 +37,6 @@ public class BlocksMined implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String[] validTools = {"pickaxe", "axe", "hoe", "shovel", "shear"}; private final String[] validTools = {"pickaxe", "axe", "hoe", "shovel", "shear"};
private final String blocksMinedLore = ChatColor.GRAY + "Blocks mined: " + ChatColor.DARK_GRAY + "X";
public BlocksMined(ToolStats toolStats) { public BlocksMined(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
@@ -46,6 +44,9 @@ public class BlocksMined implements Listener {
@EventHandler @EventHandler
public void onBreak(BlockBreakEvent event) { public void onBreak(BlockBreakEvent event) {
if (event.isCancelled()) {
return;
}
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getGameMode() != GameMode.SURVIVAL) { if (player.getGameMode() != GameMode.SURVIVAL) {
return; return;
@@ -78,6 +79,9 @@ public class BlocksMined implements Listener {
} }
container.set(toolStats.genericMined, PersistentDataType.INTEGER, blocksMined); container.set(toolStats.genericMined, PersistentDataType.INTEGER, blocksMined);
String configLore = toolStats.getLoreFromConfig("blocks-mined", false);
String configLoreRaw = toolStats.getLoreFromConfig("blocks-mined", true);
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -85,21 +89,25 @@ 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("Blocks mined")) { if (lore.get(x).contains(configLore)) {
hasLore = true; hasLore = true;
lore.set(x, blocksMinedLore.replace("X", Integer.toString(blocksMined))); lore.set(x, configLoreRaw.replace("{blocks}", Integer.toString(blocksMined)));
break; break;
} }
} }
// if the item has lore but doesn't have the tag, add it // if the item has lore but doesn't have the tag, add it
if (!hasLore) { if (!hasLore) {
lore.add(blocksMinedLore.replace("X", Integer.toString(blocksMined))); lore.add(configLoreRaw.replace("{blocks}", Integer.toString(blocksMined)));
} }
} else { } else {
// if the item has no lore, create a new list and add the string // if the item has no lore, create a new list and add the string
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(blocksMinedLore.replace("X", Integer.toString(blocksMined))); lore.add(configLoreRaw.replace("{blocks}", Integer.toString(blocksMined)));
} }
if (toolStats.checkConfig(itemStack, "blocks-mined")) { if (toolStats.checkConfig(itemStack, "blocks-mined")) {
meta.setLore(lore); meta.setLore(lore);

View File

@@ -39,8 +39,6 @@ public class CraftItem implements Listener {
public final String[] validItems = { public final String[] validItems = {
"pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing" "pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing"
}; };
private final String timeCreatedLore = ChatColor.GRAY + "Crafted on: " + ChatColor.DARK_GRAY + "X";
private final String ownerLore = ChatColor.GRAY + "Crafted by: " + ChatColor.DARK_GRAY + "X";
private final SimpleDateFormat format = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH); private final SimpleDateFormat format = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH);
public CraftItem(ToolStats toolStats) { public CraftItem(ToolStats toolStats) {
@@ -49,6 +47,9 @@ public class CraftItem implements Listener {
@EventHandler @EventHandler
public void onCraft(CraftItemEvent event) { public void onCraft(CraftItemEvent event) {
if (event.isCancelled()) {
return;
}
Player player = (Player) event.getWhoClicked(); Player player = (Player) event.getWhoClicked();
ItemStack itemStack = event.getCurrentItem(); ItemStack itemStack = event.getCurrentItem();
if (itemStack == null || itemStack.getType() == Material.AIR) { if (itemStack == null || itemStack.getType() == Material.AIR) {
@@ -57,6 +58,15 @@ public class CraftItem implements Listener {
String name = itemStack.getType().toString().toLowerCase(Locale.ROOT); String name = itemStack.getType().toString().toLowerCase(Locale.ROOT);
for (String x : validItems) { for (String x : validItems) {
if (name.contains(x)) { if (name.contains(x)) {
if (event.isShiftClick()) {
String configMessage = toolStats.config.getString("messages.shift-click-warning.crafting");
if (configMessage != null) {
event.getWhoClicked().sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage));
}
}
if (addLore(itemStack, player) == null) {
return;
}
event.setCurrentItem(addLore(itemStack, player)); event.setCurrentItem(addLore(itemStack, player));
} }
} }
@@ -71,8 +81,26 @@ public class CraftItem implements Listener {
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 (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.genericOwner, PersistentDataType.LONG)) {
return null;
}
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());
String createdByRaw = toolStats.getLoreFromConfig("created.created-by", true);
String createdOnRaw = toolStats.getLoreFromConfig("created.created-on", true);
if (createdOnRaw == null) {
toolStats.logger.warning("There is no lore message for messages.created.created-on!");
return null;
}
if (createdByRaw == null) {
toolStats.logger.warning("There is no lore message for messages.created.created-by!");
return null;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -81,10 +109,10 @@ public class CraftItem implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
if (toolStats.checkConfig(itemStack, "created-date")) { if (toolStats.checkConfig(itemStack, "created-date")) {
lore.add(timeCreatedLore.replace("X", format.format(finalDate))); lore.add(createdOnRaw.replace("{date}", format.format(finalDate)));
} }
if (toolStats.checkConfig(itemStack, "created-by")) { if (toolStats.checkConfig(itemStack, "created-by")) {
lore.add(ownerLore.replace("X", owner.getName())); lore.add(createdByRaw.replace("{player}", owner.getName()));
} }
meta.setLore(lore); meta.setLore(lore);
newItem.setItemMeta(meta); newItem.setItemMeta(meta);

View File

@@ -18,7 +18,6 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.*; import org.bukkit.entity.*;
@@ -41,9 +40,6 @@ public class EntityDamage implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String[] validTools = {"sword", "trident", "axe"}; private final String[] validTools = {"sword", "trident", "axe"};
private final String playerKillsLore = ChatColor.GRAY + "Player kills: " + ChatColor.DARK_GRAY + "X";
private final String mobKillsLore = ChatColor.GRAY + "Mob kills: " + ChatColor.DARK_GRAY + "X";
private final String damageTakenLore = ChatColor.GRAY + "Damage taken: " + ChatColor.DARK_GRAY + "X";
private final DecimalFormat decimalFormat = new DecimalFormat("0.00"); private final DecimalFormat decimalFormat = new DecimalFormat("0.00");
public final Set<UUID> trackedMobs = new HashSet<>(); public final Set<UUID> trackedMobs = new HashSet<>();
@@ -53,6 +49,9 @@ public class EntityDamage implements Listener {
@EventHandler @EventHandler
public void onDamage(EntityDamageByEntityEvent event) { public void onDamage(EntityDamageByEntityEvent event) {
if (event.isCancelled()) {
return;
}
if (!(event.getEntity() instanceof LivingEntity)) { if (!(event.getEntity() instanceof LivingEntity)) {
return; return;
} }
@@ -144,6 +143,9 @@ public class EntityDamage implements Listener {
@EventHandler @EventHandler
public void onDamage(EntityDamageByBlockEvent event) { public void onDamage(EntityDamageByBlockEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
return;
}
LivingEntity livingEntity = (LivingEntity) event.getEntity(); LivingEntity livingEntity = (LivingEntity) event.getEntity();
if (livingEntity instanceof Player) { if (livingEntity instanceof Player) {
Player player = (Player) livingEntity; Player player = (Player) livingEntity;
@@ -174,6 +176,14 @@ public class EntityDamage implements Listener {
} }
container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, playerKills); container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, playerKills);
String playerKillsLore = toolStats.getLoreFromConfig("kills.player", false);
String playerKillsLoreRaw = toolStats.getLoreFromConfig("kills.player", true);
if (playerKillsLore == null || playerKillsLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.kills.player!");
return null;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -182,20 +192,20 @@ public class EntityDamage implements Listener {
// 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
for (int x = 0; x < lore.size(); x++) { for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Player kills")) { if (lore.get(x).contains(playerKillsLore)) {
hasLore = true; hasLore = true;
lore.set(x, playerKillsLore.replace("X", Integer.toString(playerKills))); lore.set(x, playerKillsLoreRaw.replace("{kills}", Integer.toString(playerKills)));
break; break;
} }
} }
// if the item has lore but doesn't have the tag, add it // if the item has lore but doesn't have the tag, add it
if (!hasLore) { if (!hasLore) {
lore.add(playerKillsLore.replace("X", Integer.toString(playerKills))); lore.add(playerKillsLoreRaw.replace("{kills}", Integer.toString(playerKills)));
} }
} else { } else {
// if the item has no lore, create a new list and add the string // if the item has no lore, create a new list and add the string
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(playerKillsLore.replace("X", Integer.toString(playerKills))); lore.add(playerKillsLoreRaw.replace("{kills}", Integer.toString(playerKills)));
} }
if (toolStats.checkConfig(itemStack, "player-kills")) { if (toolStats.checkConfig(itemStack, "player-kills")) {
meta.setLore(lore); meta.setLore(lore);
@@ -222,6 +232,14 @@ public class EntityDamage implements Listener {
} }
container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, mobKills); container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, mobKills);
String mobKillsLore = toolStats.getLoreFromConfig("kills.mob", false);
String mobKillsLoreRaw = toolStats.getLoreFromConfig("kills.mob", true);
if (mobKillsLore == null || mobKillsLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.kills.mob!");
return null;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -230,20 +248,20 @@ public class EntityDamage implements Listener {
// 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
for (int x = 0; x < lore.size(); x++) { for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Mob kills")) { if (lore.get(x).contains(mobKillsLore)) {
hasLore = true; hasLore = true;
lore.set(x, mobKillsLore.replace("X", Integer.toString(mobKills))); lore.set(x, mobKillsLoreRaw.replace("{kills}", Integer.toString(mobKills)));
break; break;
} }
} }
// if the item has lore but doesn't have the tag, add it // if the item has lore but doesn't have the tag, add it
if (!hasLore) { if (!hasLore) {
lore.add(mobKillsLore.replace("X", Integer.toString(mobKills))); lore.add(mobKillsLoreRaw.replace("{kills}", Integer.toString(mobKills)));
} }
} else { } else {
// if the item has no lore, create a new list and add the string // if the item has no lore, create a new list and add the string
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(mobKillsLore.replace("X", Integer.toString(mobKills))); lore.add(mobKillsLoreRaw.replace("{kills}", Integer.toString(mobKills)));
} }
if (toolStats.checkConfig(itemStack, "mob-kills")) { if (toolStats.checkConfig(itemStack, "mob-kills")) {
meta.setLore(lore); meta.setLore(lore);
@@ -270,6 +288,14 @@ public class EntityDamage implements Listener {
decimalFormat.setRoundingMode(RoundingMode.DOWN); decimalFormat.setRoundingMode(RoundingMode.DOWN);
container.set(toolStats.armorDamage, PersistentDataType.DOUBLE, damageTaken); container.set(toolStats.armorDamage, PersistentDataType.DOUBLE, damageTaken);
String damageTakenLore = toolStats.getLoreFromConfig("damage-taken", false);
String damageTakenLoreRaw = toolStats.getLoreFromConfig("damage-taken", true);
if (damageTakenLore == null || damageTakenLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.damage-taken!");
return;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -278,20 +304,20 @@ public class EntityDamage implements Listener {
// 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
for (int x = 0; x < lore.size(); x++) { for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Damage taken")) { if (lore.get(x).contains(damageTakenLore)) {
hasLore = true; hasLore = true;
lore.set(x, damageTakenLore.replace("X", decimalFormat.format(damageTaken))); lore.set(x, damageTakenLoreRaw.replace("{damage}", decimalFormat.format(damageTaken)));
break; break;
} }
} }
// if the item has lore but doesn't have the tag, add it // if the item has lore but doesn't have the tag, add it
if (!hasLore) { if (!hasLore) {
lore.add(damageTakenLore.replace("X", decimalFormat.format(damageTaken))); lore.add(damageTakenLoreRaw.replace("{damage}", decimalFormat.format(damageTaken)));
} }
} else { } else {
// if the item has no lore, create a new list and add the string // if the item has no lore, create a new list and add the string
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(damageTakenLore.replace("X", decimalFormat.format(damageTaken))); lore.add(damageTakenLoreRaw.replace("{damage}", decimalFormat.format(damageTaken)));
} }
if (toolStats.config.getBoolean("enabled.armor-damage")) { if (toolStats.config.getBoolean("enabled.armor-damage")) {
meta.setLore(lore); meta.setLore(lore);

View File

@@ -18,7 +18,6 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -32,7 +31,6 @@ import java.util.*;
public class EntityDeath implements Listener { public class EntityDeath implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String droppedLore = ChatColor.GRAY + "Dropped by: " + ChatColor.DARK_GRAY + "X";
public EntityDeath(ToolStats toolStats) { public EntityDeath(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
@@ -64,14 +62,23 @@ public class EntityDeath implements Listener {
return; return;
} }
boolean hasTag = false; boolean hasTag = false;
String droppedByLore = toolStats.getLoreFromConfig("dropped-by", false);
String droppedByLoreRaw = toolStats.getLoreFromConfig("dropped-by", true);
if (droppedByLore == null || droppedByLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.dropped-by!");
return;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
assert lore != null; assert lore != null;
for (int x = 0; x < lore.size(); x++) { for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Dropped by")) { if (lore.get(x).contains(droppedByLore)) {
// replace existing tag // replace existing tag
lore.set(x, droppedLore.replace("X", mob)); lore.set(x, droppedByLoreRaw.replace("{name}", mob));
hasTag = true; hasTag = true;
} }
} }
@@ -80,7 +87,7 @@ public class EntityDeath implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
if (!hasTag) { if (!hasTag) {
lore.add(droppedLore.replace("X", mob)); lore.add(droppedByLoreRaw.replace("X", mob));
} }
if (toolStats.config.getBoolean("enabled.dropped-by")) { if (toolStats.config.getBoolean("enabled.dropped-by")) {
meta.setLore(lore); meta.setLore(lore);

View File

@@ -20,7 +20,6 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.UUIDDataType; import lol.hyper.toolstats.UUIDDataType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -42,8 +41,6 @@ import java.util.Locale;
public class GenerateLoot implements Listener { public class GenerateLoot implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String LOOT_OWNER = ChatColor.GRAY + "Looted by: " + ChatColor.DARK_GRAY + "X";
private final String LOOT_TIME = ChatColor.GRAY + "Looted on: " + ChatColor.DARK_GRAY + "X";
public final String[] validItems = { public final String[] validItems = {
"pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing" "pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing"
}; };
@@ -87,8 +84,22 @@ public class GenerateLoot implements Listener {
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 (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.genericOwner, PersistentDataType.LONG)) {
return null;
}
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());
String foundByLoreRaw = toolStats.getLoreFromConfig("looted.found-by", true);
String foundOnLoreRaw = toolStats.getLoreFromConfig("looted.found-on", true);
if (foundByLoreRaw == null || foundOnLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.looted!");
return null;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -97,8 +108,8 @@ public class GenerateLoot implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
if (toolStats.checkConfig(newItem, "looted-tag")) { if (toolStats.checkConfig(newItem, "looted-tag")) {
lore.add(LOOT_TIME.replace("X", format.format(finalDate))); lore.add(foundOnLoreRaw.replace("{date}", format.format(finalDate)));
lore.add(LOOT_OWNER.replace("X", owner.getName())); lore.add(foundByLoreRaw.replace("{player}", owner.getName()));
} }
meta.setLore(lore); meta.setLore(lore);
newItem.setItemMeta(meta); newItem.setItemMeta(meta);

View File

@@ -19,7 +19,6 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.UUIDDataType; import lol.hyper.toolstats.UUIDDataType;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -40,8 +39,6 @@ import java.util.Locale;
public class PickupItem implements Listener { public class PickupItem implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String FOUND_BY = ChatColor.GRAY + "Found by: " + ChatColor.DARK_GRAY + "X";
private final String FOUND_ON = ChatColor.GRAY + "Found on: " + ChatColor.DARK_GRAY + "X";
private final SimpleDateFormat format = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH); private final SimpleDateFormat format = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH);
public PickupItem(ToolStats toolStats) { public PickupItem(ToolStats toolStats) {
@@ -50,6 +47,9 @@ public class PickupItem implements Listener {
@EventHandler @EventHandler
public void onPickup(EntityPickupItemEvent event) { public void onPickup(EntityPickupItemEvent event) {
if (event.isCancelled()) {
return;
}
Entity entity = event.getEntity(); Entity entity = event.getEntity();
if (entity instanceof Player) { if (entity instanceof Player) {
ItemStack itemStack = event.getItem().getItemStack(); ItemStack itemStack = event.getItem().getItemStack();
@@ -78,6 +78,15 @@ 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());
String foundByLoreRaw = toolStats.getLoreFromConfig("looted.found-by", true);
String foundOnLoreRaw = toolStats.getLoreFromConfig("looted.found-on", true);
if (foundByLoreRaw == null || foundOnLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.looted!");
return;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -86,8 +95,8 @@ public class PickupItem implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
if (toolStats.config.getBoolean("enabled.elytra-tag")) { if (toolStats.config.getBoolean("enabled.elytra-tag")) {
lore.add(FOUND_ON.replace("X", format.format(finalDate))); lore.add(foundOnLoreRaw.replace("{date}", format.format(finalDate)));
lore.add(FOUND_BY.replace("X", owner.getName())); lore.add(foundByLoreRaw.replace("{player}", owner.getName()));
} }
meta.setLore(lore); meta.setLore(lore);
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);

View File

@@ -19,7 +19,6 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.UUIDDataType; import lol.hyper.toolstats.UUIDDataType;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Item; import org.bukkit.entity.Item;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -40,9 +39,6 @@ import java.util.Locale;
public class PlayerFish implements Listener { public class PlayerFish implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String fishCaughtLore = ChatColor.GRAY + "Fish caught: " + ChatColor.DARK_GRAY + "X";
private final String FISH_OWNER = ChatColor.GRAY + "Caught by: " + ChatColor.DARK_GRAY + "X";
private final String FISH_TIME = ChatColor.GRAY + "Caught on: " + ChatColor.DARK_GRAY + "X";
public final String[] validItems = { public final String[] validItems = {
"pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing" "pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing"
}; };
@@ -54,6 +50,9 @@ public class PlayerFish implements Listener {
@EventHandler @EventHandler
public void onFish(PlayerFishEvent event) { public void onFish(PlayerFishEvent event) {
if (event.isCancelled()) {
return;
}
// only listen to when a player catches a fish // only listen to when a player catches a fish
if (event.getState() != PlayerFishEvent.State.CAUGHT_FISH) { if (event.getState() != PlayerFishEvent.State.CAUGHT_FISH) {
return; return;
@@ -92,6 +91,15 @@ public class PlayerFish implements Listener {
fishCaught++; fishCaught++;
} }
container.set(toolStats.fishingRodCaught, PersistentDataType.INTEGER, fishCaught); container.set(toolStats.fishingRodCaught, PersistentDataType.INTEGER, fishCaught);
String fishCaughtLore = toolStats.getLoreFromConfig("fished.fish-caught", false);
String fishCaughtLoreRaw = toolStats.getLoreFromConfig("fished.fish-caught", true);
if (fishCaughtLore == null || fishCaughtLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.fish-caught!");
return;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -100,20 +108,20 @@ public class PlayerFish implements Listener {
// 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
for (int x = 0; x < lore.size(); x++) { for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Fish caught")) { if (lore.get(x).contains(fishCaughtLore)) {
hasLore = true; hasLore = true;
lore.set(x, fishCaughtLore.replace("X", Integer.toString(fishCaught))); lore.set(x, fishCaughtLoreRaw.replace("{fish}", Integer.toString(fishCaught)));
break; break;
} }
} }
// if the item has lore but doesn't have the tag, add it // if the item has lore but doesn't have the tag, add it
if (!hasLore) { if (!hasLore) {
lore.add(fishCaughtLore.replace("X", Integer.toString(fishCaught))); lore.add(fishCaughtLoreRaw.replace("{fish}", Integer.toString(fishCaught)));
} }
} else { } else {
// if the item has no lore, create a new list and add the string // if the item has no lore, create a new list and add the string
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(fishCaughtLore.replace("X", Integer.toString(fishCaught))); lore.add(fishCaughtLoreRaw.replace("{fish}", Integer.toString(fishCaught)));
} }
if (toolStats.config.getBoolean("enabled.fish-caught")) { if (toolStats.config.getBoolean("enabled.fish-caught")) {
meta.setLore(lore); meta.setLore(lore);
@@ -129,8 +137,22 @@ public class PlayerFish implements Listener {
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 (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.genericOwner, PersistentDataType.LONG)) {
return;
}
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());
String caughtByLoreRaw = toolStats.getLoreFromConfig("fished.caught-by", true);
String caughtOnLoreRaw = toolStats.getLoreFromConfig("fished.caught-on", true);
if (caughtByLoreRaw == null || caughtOnLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.fished!");
return;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -139,8 +161,8 @@ public class PlayerFish implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
if (toolStats.checkConfig(itemStack, "fished-tag")) { if (toolStats.checkConfig(itemStack, "fished-tag")) {
lore.add(FISH_TIME.replace("X", format.format(finalDate))); lore.add(caughtOnLoreRaw.replace("{date}", format.format(finalDate)));
lore.add(FISH_OWNER.replace("X", owner.getName())); lore.add(caughtByLoreRaw.replace("{player}", owner.getName()));
} }
meta.setLore(lore); meta.setLore(lore);
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);

View File

@@ -18,7 +18,6 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -37,7 +36,6 @@ import java.util.List;
public class SheepShear implements Listener { public class SheepShear implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String sheepShearLore = ChatColor.GRAY + "Sheep sheared: " + ChatColor.DARK_GRAY + "X";
public SheepShear(ToolStats toolStats) { public SheepShear(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
@@ -45,6 +43,9 @@ public class SheepShear implements Listener {
@EventHandler @EventHandler
public void onShear(PlayerInteractEntityEvent event) { public void onShear(PlayerInteractEntityEvent event) {
if (event.isCancelled()) {
return;
}
Player player = event.getPlayer(); Player player = event.getPlayer();
Entity entity = event.getRightClicked(); Entity entity = event.getRightClicked();
if (!(entity instanceof Sheep)) { if (!(entity instanceof Sheep)) {
@@ -77,6 +78,15 @@ public class SheepShear implements Listener {
sheepSheared++; sheepSheared++;
} }
container.set(toolStats.shearsSheared, PersistentDataType.INTEGER, sheepSheared); container.set(toolStats.shearsSheared, PersistentDataType.INTEGER, sheepSheared);
String sheepShearedLore = toolStats.getLoreFromConfig("sheep-sheared", false);
String sheepShearedLoreRaw = toolStats.getLoreFromConfig("sheep-sheared", true);
if (sheepShearedLore == null || sheepShearedLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.sheep-sheared!");
return;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -85,20 +95,20 @@ public class SheepShear implements Listener {
// 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
for (int x = 0; x < lore.size(); x++) { for (int x = 0; x < lore.size(); x++) {
if (lore.get(x).contains("Sheep sheared")) { if (lore.get(x).contains(sheepShearedLore)) {
hasLore = true; hasLore = true;
lore.set(x, sheepShearLore.replace("X", Integer.toString(sheepSheared))); lore.set(x, sheepShearedLoreRaw.replace("{sheep}", Integer.toString(sheepSheared)));
break; break;
} }
} }
// if the item has lore but doesn't have the tag, add it // if the item has lore but doesn't have the tag, add it
if (!hasLore) { if (!hasLore) {
lore.add(sheepShearLore.replace("X", Integer.toString(sheepSheared))); lore.add(sheepShearedLoreRaw.replace("{sheep}", Integer.toString(sheepSheared)));
} }
} else { } else {
// if the item has no lore, create a new list and add the string // if the item has no lore, create a new list and add the string
lore = new ArrayList<>(); lore = new ArrayList<>();
lore.add(sheepShearLore.replace("X", Integer.toString(sheepSheared))); lore.add(sheepShearedLoreRaw.replace("{sheep}", Integer.toString(sheepSheared)));
} }
if (toolStats.config.getBoolean("enabled.sheep-sheared")) { if (toolStats.config.getBoolean("enabled.sheep-sheared")) {
meta.setLore(lore); meta.setLore(lore);

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.UUIDDataType; import lol.hyper.toolstats.UUIDDataType;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -41,8 +42,6 @@ import java.util.Locale;
public class VillagerTrade implements Listener { public class VillagerTrade implements Listener {
private final ToolStats toolStats; private final ToolStats toolStats;
private final String TRADED_OWNER = ChatColor.GRAY + "Traded by: " + ChatColor.DARK_GRAY + "X";
private final String TRADED_TIME = ChatColor.GRAY + "Traded on: " + ChatColor.DARK_GRAY + "X";
public final String[] validItems = { public final String[] validItems = {
"pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing" "pickaxe", "sword", "shovel", "axe", "hoe", "bow", "helmet", "chestplate", "leggings", "boots", "fishing"
}; };
@@ -63,8 +62,17 @@ public class VillagerTrade implements Listener {
ItemStack item = event.getCurrentItem(); ItemStack item = event.getCurrentItem();
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 (event.isShiftClick()) {
String configMessage = toolStats.config.getString("messages.shift-click-warning.trading");
if (configMessage != null) {
event.getWhoClicked().sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage));
}
}
ItemStack newItem = addLore(item, (Player) event.getWhoClicked()); ItemStack newItem = addLore(item, (Player) event.getWhoClicked());
event.getView().setCursor(newItem); if (newItem == null) {
return;
}
Bukkit.getScheduler().runTaskLater(toolStats, ()-> event.setCurrentItem(newItem), 5);
} }
} }
} }
@@ -79,8 +87,22 @@ public class VillagerTrade implements Listener {
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 (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.genericOwner, PersistentDataType.LONG)) {
return null;
}
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());
String tradedByLoreRaw = toolStats.getLoreFromConfig("traded.traded-by", true);
String tradedOnLoreRaw = toolStats.getLoreFromConfig("traded.traded-on", true);
if (tradedByLoreRaw == null || tradedOnLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages.traded!");
return null;
}
List<String> lore; List<String> lore;
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.getLore();
@@ -89,8 +111,8 @@ public class VillagerTrade implements Listener {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
if (toolStats.checkConfig(itemStack, "traded-tag")) { if (toolStats.checkConfig(itemStack, "traded-tag")) {
lore.add(TRADED_TIME.replace("X", format.format(finalDate))); lore.add(tradedOnLoreRaw.replace("{date}", format.format(finalDate)));
lore.add(TRADED_OWNER.replace("X", owner.getName())); lore.add(tradedByLoreRaw.replace("{player}", owner.getName()));
} }
meta.setLore(lore); meta.setLore(lore);
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);

View File

@@ -71,4 +71,31 @@ enabled:
dropped-by: true dropped-by: true
elytra-tag: true elytra-tag: true
config-version: 2 messages:
created:
created-by: "&7Crafted by: &8{player}"
created-on: "&7Crafted on: &8{date}"
fished:
caught-by: "&7Caught by: &8{player}"
caught-on: "&7Caught on: &8{date}"
fish-caught: "&7Fish caught: &8{fish}"
looted:
found-by: "&7Found by: &8{player}"
found-on: "&7Found on: &8{date}"
traded:
traded-by: "&7Traded by: &8{player}"
traded-on: "&7Traded on: &8{date}"
kills:
mob: "&7Mob kills: &8{kills}"
player: "&7Player kills: &8{kills}"
blocks-mined: "&7Blocks mined: &8{blocks}"
sheep-sheared: "&7Sheep sheared: &8{sheep}"
dropped-by: "&7Dropped by: &8{name}" # name will be player/mob name
damage-taken: "&7Damage taken: &8{damage}"
# Display this message if the player shift click trades/crafts items. It's not really easy to get every single item
# that is crafted. The tag will only be added to the first item. If you don't want this message, simply replace them both with ""
shift-click-warning:
crafting: "&cCrafting items via shift clicking does not fully apply tags to each item. This is a limitation with the Bukkit API."
trading: "&cTrading items via shift clicking does not fully apply tags to each item. This is a limitation with the Bukkit API."
config-version: 3

View File

@@ -1,7 +1,7 @@
name: ToolStats name: ToolStats
version: '${project.version}' version: '${project.version}'
main: lol.hyper.toolstats.ToolStats main: lol.hyper.toolstats.ToolStats
api-version: 1.18 api-version: 1.15
author: hyperdefined author: hyperdefined
description: Track various tool stats! description: Track various tool stats!
commands: commands: