Compare commits

...

23 Commits

Author SHA1 Message Date
hyperdefined
1e4e963fe1 remove debug 2025-04-07 11:00:55 -04:00
hyperdefined
298a8dd592 Update pom.xml 2025-04-07 10:57:27 -04:00
hyperdefined
49a3c03f94 typing with paws is hard 2025-04-07 10:56:51 -04:00
hyperdefined
ecd241ac52 fix #99 2025-04-07 10:56:25 -04:00
hyperdefined
5a1be37339 remove token if stat is disabled
this was missing prior
2025-04-07 10:56:13 -04:00
hyperdefined
a07782df5b added missing stat for reset command 2025-04-07 10:55:17 -04:00
hyperdefined
31123fdfd5 woops 2025-04-07 10:04:20 -04:00
hyperdefined
e310f1cb18 fix #98 2025-04-05 18:24:23 -04:00
hyperdefined
3d850ef00c Create FUNDING.yml 2025-03-31 19:39:35 -04:00
hyperdefined
dfd2ef7d7b added missing entries 2025-03-31 19:27:03 -04:00
hyperdefined
957d4d95cb Create damage-done.png 2025-03-31 19:24:57 -04:00
hyperdefined
2143daa133 cleanup 2025-03-31 19:21:09 -04:00
hyperdefined
be8fcc2d57 Update TokenCrafting.java 2025-03-31 19:20:24 -04:00
hyperdefined
ed9afc1812 backwards compatibility with old flight time format 2025-03-31 19:06:43 -04:00
hyperdefined
706175a13a Merge pull request #97 from sebampuero/impr-flighttime-fmt
Elytra flight time as human readable format
2025-03-31 18:44:50 -04:00
sebampuero
256581fa08 fix: use char instead of str 2025-03-31 18:42:47 -04:00
sebampuero
818f2e7a39 feat: update lore formatting 2025-03-31 18:41:33 -04:00
sebampuero
d83bc55eec feat: fix function for several placeholders. It was appending wrongly. Use version11 class for updater. 2025-03-31 18:41:33 -04:00
sebampuero
3196223d30 docs: javadoc fix 2025-03-31 18:39:09 -04:00
sebampuero
02d5d1c17e feat: adding updater for config version 11 2025-03-31 18:39:05 -04:00
sebampuero
d675549209 feat: add format lore that replaces several placeholders with a map 2025-03-31 18:14:51 -04:00
sebampuero
d5324b5db6 feat: some first changes
Add placeholders for time values, new formatting function and call for new function.
2025-03-31 18:13:45 -04:00
hyperdefined
4fe4c2be25 fix #94 2025-03-31 18:03:07 -04:00
16 changed files with 350 additions and 23 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
buy_me_a_coffee: hyperdefined

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

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

View File

@@ -48,7 +48,7 @@ public class CommandToolStats implements TabExecutor {
} }
@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 @NotNull [] args) {
if (!sender.hasPermission("toolstats.command")) { if (!sender.hasPermission("toolstats.command")) {
sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true; return true;
@@ -210,7 +210,8 @@ public class CommandToolStats implements TabExecutor {
if (flightTime != null) { if (flightTime != null) {
if (toolStats.config.getBoolean("enabled.flight-time")) { if (toolStats.config.getBoolean("enabled.flight-time")) {
Component line = toolStats.configTools.formatLore("flight-time", "{time}", toolStats.numberFormat.formatDouble((double) flightTime / 1000)); Map<String, String> flightTimeFormatted = toolStats.numberFormat.formatTime(flightTime);
Component line = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", flightTimeFormatted);
lore.add(line); lore.add(line);
} }
} }
@@ -366,6 +367,14 @@ public class CommandToolStats implements TabExecutor {
} }
} }
} }
if (toolStats.configTools.checkConfig(original.getType(), "damage-done")) {
if (container.has(toolStats.damageDone, PersistentDataType.DOUBLE)) {
Double damage = container.get(toolStats.damageDone, PersistentDataType.DOUBLE);
if (damage != null) {
lore.add(toolStats.configTools.formatLore("damage-done", "{damage}", toolStats.numberFormat.formatDouble(damage)));
}
}
}
if (toolStats.config.getBoolean("enabled.arrows-shot")) { if (toolStats.config.getBoolean("enabled.arrows-shot")) {
if (container.has(toolStats.arrowsShot, PersistentDataType.INTEGER)) { if (container.has(toolStats.arrowsShot, PersistentDataType.INTEGER)) {
Integer arrows = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER); Integer arrows = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER);
@@ -406,6 +415,12 @@ public class CommandToolStats implements TabExecutor {
target.getInventory().addItem(itemStack); target.getInventory().addItem(itemStack);
break; break;
} }
case "damage-done": {
ItemStack itemStack = toolStats.tokenItems.damageDone();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "mob-kills": { case "mob-kills": {
ItemStack itemStack = toolStats.tokenItems.mobKills(); ItemStack itemStack = toolStats.tokenItems.mobKills();
itemStack.setAmount(amount); itemStack.setAmount(amount);
@@ -459,7 +474,7 @@ public class CommandToolStats implements TabExecutor {
@Nullable @Nullable
@Override @Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String @NotNull [] args) {
if (args.length == 1) { if (args.length == 1) {
List<String> suggestions = new ArrayList<>(); List<String> suggestions = new ArrayList<>();
if (sender.hasPermission("toolstats.reload")) { if (sender.hasPermission("toolstats.reload")) {

View File

@@ -25,7 +25,6 @@ import org.bukkit.entity.*;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@@ -188,7 +187,7 @@ public class EntityDamage implements Listener {
boolean isMain = playerInventory.getItemInMainHand().getType() == Material.BOW || playerInventory.getItemInMainHand().getType() == Material.CROSSBOW; boolean isMain = playerInventory.getItemInMainHand().getType() == Material.BOW || playerInventory.getItemInMainHand().getType() == Material.CROSSBOW;
boolean isOffHand = playerInventory.getItemInOffHand().getType() == Material.BOW || playerInventory.getItemInOffHand().getType() == Material.CROSSBOW; boolean isOffHand = playerInventory.getItemInOffHand().getType() == Material.BOW || playerInventory.getItemInOffHand().getType() == Material.CROSSBOW;
ItemMeta newBowDamage = toolStats.itemLore.updateWeaponDamage(playerInventory.getItemInMainHand(), damage, false); ItemMeta newBowDamage = toolStats.itemLore.updateWeaponDamage(heldBow, damage, false);
//toolStats.logger.info(newBowDamage.toString()); //toolStats.logger.info(newBowDamage.toString());
// player is shooting another player // player is shooting another player

View File

@@ -23,6 +23,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
@@ -46,6 +47,11 @@ public class InventoryOpen implements Listener {
} }
Inventory inventory = event.getInventory(); Inventory inventory = event.getInventory();
// only check these
if (inventory.getType() != InventoryType.CHEST || inventory.getType() != InventoryType.BARREL || inventory.getType() != InventoryType.SHULKER_BOX || inventory.getType() != InventoryType.ENDER_CHEST) {
return;
}
Player player = (Player) event.getPlayer(); Player player = (Player) event.getPlayer();
for (ItemStack itemStack : inventory) { for (ItemStack itemStack : inventory) {
if (itemStack == null) { if (itemStack == null) {

View File

@@ -41,7 +41,7 @@ public class PlayerMove implements Listener {
} }
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onCraft(PlayerMoveEvent event) { public void onMove(PlayerMoveEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
// player starts to fly // player starts to fly
if (player.isGliding()) { if (player.isGliding()) {

View File

@@ -27,10 +27,7 @@ import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
public class ItemChecker { public class ItemChecker {
@@ -343,6 +340,26 @@ public class ItemChecker {
return String.join(",", tokens); return String.join(",", tokens);
} }
/**
* Remove a given token from a list of tokens.
*
* @param appliedTokens The tokens on the item.
* @param toRemove The token to remove.
* @return The list of tokens.
*/
public List<String> removeToken(String appliedTokens, String toRemove) {
// remove the tokens if they exist
List<String> tokenList = new ArrayList<>(Arrays.asList(appliedTokens.split(",")));
tokenList.remove(toRemove);
if (tokenList.isEmpty()) {
return Collections.emptyList();
} else {
return tokenList;
}
}
/** /**
* Check to see if a given container has our keys for stats. * Check to see if a given container has our keys for stats.
* *

View File

@@ -27,6 +27,7 @@ import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
public class ItemLore { public class ItemLore {
@@ -251,6 +252,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.cropsHarvested); container.remove(toolStats.cropsHarvested);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "crops-mined");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined); String oldCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined);
Component lineToRemove = toolStats.configTools.formatLore("crops-harvested", "{crops}", oldCropsMinedFormatted); Component lineToRemove = toolStats.configTools.formatLore("crops-harvested", "{crops}", oldCropsMinedFormatted);
@@ -334,6 +350,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.blocksMined); container.remove(toolStats.blocksMined);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "blocks-mined");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined); String oldBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined);
Component lineToRemove = toolStats.configTools.formatLore("blocks-mined", "{blocks}", oldBlocksMinedFormatted); Component lineToRemove = toolStats.configTools.formatLore("blocks-mined", "{blocks}", oldBlocksMinedFormatted);
@@ -418,6 +449,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.playerKills); container.remove(toolStats.playerKills);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "player-kills");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills); String oldPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
Component lineToRemove = toolStats.configTools.formatLore("player-kills", "{kills}", oldPlayerKillsFormatted); Component lineToRemove = toolStats.configTools.formatLore("player-kills", "{kills}", oldPlayerKillsFormatted);
@@ -501,6 +547,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.mobKills); container.remove(toolStats.mobKills);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "mob-kills");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills); String oldMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
Component lineToRemove = toolStats.configTools.formatLore("mob-kills", "{kills}", oldMobKillsFormatted); Component lineToRemove = toolStats.configTools.formatLore("mob-kills", "{kills}", oldMobKillsFormatted);
@@ -592,6 +653,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.armorDamage); container.remove(toolStats.armorDamage);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "damage-taken");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldDamageTakenFormatted = toolStats.numberFormat.formatDouble(armorDamage); String oldDamageTakenFormatted = toolStats.numberFormat.formatDouble(armorDamage);
Component lineToRemove = toolStats.configTools.formatLore("damage-taken", "{damage}", oldDamageTakenFormatted); Component lineToRemove = toolStats.configTools.formatLore("damage-taken", "{damage}", oldDamageTakenFormatted);
@@ -683,6 +759,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.damageDone); container.remove(toolStats.damageDone);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "damage-done");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldDamageDoneFormatted = toolStats.numberFormat.formatDouble(damageDone); String oldDamageDoneFormatted = toolStats.numberFormat.formatDouble(damageDone);
Component lineToRemove = toolStats.configTools.formatLore("damage-done", "{damage}", oldDamageDoneFormatted); Component lineToRemove = toolStats.configTools.formatLore("damage-done", "{damage}", oldDamageDoneFormatted);
@@ -766,9 +857,32 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.flightTime); container.remove(toolStats.flightTime);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "flight-time");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldFlightTimeFormatted = toolStats.numberFormat.formatDouble(flightTime); // if the old format is in the config, check to see if the old format is on the elytra
Component lineToRemove = toolStats.configTools.formatLore("flight-time", "{time}", oldFlightTimeFormatted); if (toolStats.config.getString("messages.flight-time-old") != null) {
String oldFormatFormatted = toolStats.numberFormat.formatDouble((double) flightTime / 1000);
Component oldFormat = toolStats.configTools.formatLore("flight-time-old", "{time}", oldFormatFormatted);
List<Component> newLore = removeLore(meta.lore(), oldFormat);
meta.lore(newLore);
}
Map<String, String> oldFlightTimeFormatted = toolStats.numberFormat.formatTime(flightTime);
Component lineToRemove = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", oldFlightTimeFormatted);
List<Component> newLore = removeLore(meta.lore(), lineToRemove); List<Component> newLore = removeLore(meta.lore(), lineToRemove);
meta.lore(newLore); meta.lore(newLore);
} }
@@ -815,10 +929,18 @@ public class ItemLore {
} }
container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime + duration); container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime + duration);
String oldFlightFormatted = toolStats.numberFormat.formatDouble((double) flightTime / 1000); Map<String, String> oldFlightFormatted = toolStats.numberFormat.formatTime(flightTime);
String newFlightFormatted = toolStats.numberFormat.formatDouble((double) (flightTime + duration) / 1000); Map<String, String> newFlightFormatted = toolStats.numberFormat.formatTime(flightTime + duration);
Component oldLine = toolStats.configTools.formatLore("flight-time", "{time}", oldFlightFormatted); // if the old format is in the config, check to see if the old format is on the elytra
Component newLine = toolStats.configTools.formatLore("flight-time", "{time}", newFlightFormatted); if (toolStats.config.getString("messages.flight-time-old") != null) {
if (meta.hasLore()) {
String oldFormatFormatted = toolStats.numberFormat.formatDouble((double) flightTime / 1000);
Component oldFormat = toolStats.configTools.formatLore("flight-time-old", "{time}", oldFormatFormatted);
meta.lore(removeLore(meta.lore(), oldFormat));
}
}
Component oldLine = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", oldFlightFormatted);
Component newLine = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", newFlightFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
@@ -851,6 +973,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.sheepSheared); container.remove(toolStats.sheepSheared);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "sheep-sheared");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldSheepShearedFormatted = toolStats.numberFormat.formatDouble(sheepSheared); String oldSheepShearedFormatted = toolStats.numberFormat.formatDouble(sheepSheared);
Component lineToRemove = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", oldSheepShearedFormatted); Component lineToRemove = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", oldSheepShearedFormatted);
@@ -934,6 +1071,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.arrowsShot); container.remove(toolStats.arrowsShot);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "arrows-shot");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldArrowsShotFormatted = toolStats.numberFormat.formatDouble(arrowsShot); String oldArrowsShotFormatted = toolStats.numberFormat.formatDouble(arrowsShot);
Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", oldArrowsShotFormatted); Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", oldArrowsShotFormatted);
@@ -1019,6 +1171,21 @@ public class ItemLore {
return null; return null;
} }
container.remove(toolStats.fishCaught); container.remove(toolStats.fishCaught);
// remove the applied token if this stat is disabled
if (container.has(toolStats.tokenApplied)) {
String appliedTokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (appliedTokens != null) {
// remove the token from the list
// if the list is empty, remove the PDC
// otherwise set the PDC back with the new list
List<String> newTokens = toolStats.itemChecker.removeToken(appliedTokens, "fish-caught");
if (!newTokens.isEmpty()) {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
} else {
container.remove(toolStats.tokenApplied);
}
}
}
if (meta.hasLore()) { if (meta.hasLore()) {
String oldFishCaught = toolStats.numberFormat.formatDouble(fishCaught); String oldFishCaught = toolStats.numberFormat.formatDouble(fishCaught);
Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", oldFishCaught); Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", oldFishCaught);

View File

@@ -23,7 +23,9 @@ import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
public class NumberFormat { public class NumberFormat {
@@ -136,4 +138,59 @@ public class NumberFormat {
public String formatDate(Date date) { public String formatDate(Date date) {
return DATE_FORMAT.format(date); return DATE_FORMAT.format(date);
} }
/**
* Returns a human readable form of time in milliseconds.
* E.g. given 3752348000L outputs 1 years, 5 months, 3 days, 14 hours, 12 minutes, 28 seconds.
* @param time The time in ms.
* @return Map with units as keys and time value, e.g. "years" (key) -> 1 (value)
*/
public Map<String, String> formatTime(Long time) {
final int SECONDS_PER_MINUTE = 60;
final int MINUTES_PER_HOUR = 60;
final int HOURS_PER_DAY = 24;
final int DAYS_PER_MONTH = 30; // Approximation
final int DAYS_PER_YEAR = 365; // Approximation
long totalSeconds = time / 1000;
Map<String, String> timeUnits = new HashMap<>();
long years = totalSeconds / (DAYS_PER_YEAR * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
if (years > 0) {
timeUnits.put("years", Long.toString(years));
}
totalSeconds %= (DAYS_PER_YEAR * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
long months = totalSeconds / (DAYS_PER_MONTH * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
if (months > 0) {
timeUnits.put("months", Long.toString(months));
}
totalSeconds %= (DAYS_PER_MONTH * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
long days = totalSeconds / (HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
if (days > 0) {
timeUnits.put("days", Long.toString(days));
}
totalSeconds %= (HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
long hours = totalSeconds / (MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
if (hours > 0) {
timeUnits.put("hours", Long.toString(hours));
}
totalSeconds %= (MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
long minutes = totalSeconds / SECONDS_PER_MINUTE;
if (minutes > 0) {
timeUnits.put("minutes", Long.toString(minutes));
}
totalSeconds %= SECONDS_PER_MINUTE;
long seconds = totalSeconds;
if (seconds > 0 || timeUnits.isEmpty()) { // Always include seconds if everything else is zero
timeUnits.put("seconds", Long.toString(seconds));
}
return timeUnits;
}
} }

View File

@@ -115,13 +115,14 @@ public class TokenCrafting {
NamespacedKey removeKey = new NamespacedKey(toolStats, "remove-token"); NamespacedKey removeKey = new NamespacedKey(toolStats, "remove-token");
ShapedRecipe removeRecipe = new ShapedRecipe(removeKey, toolStats.tokenItems.removeToken()); ShapedRecipe removeRecipe = new ShapedRecipe(removeKey, toolStats.tokenItems.removeToken());
resetRecipe.shape(" P ", "P P", " P "); removeRecipe.shape(" P ", "P P", " P ");
resetRecipe.setIngredient('P', Material.PAPER); removeRecipe.setIngredient('P', Material.PAPER);
recipes.add(removeRecipe); recipes.add(removeRecipe);
tokenTypes.add("crops-mined"); tokenTypes.add("crops-mined");
tokenTypes.add("blocks-mined"); tokenTypes.add("blocks-mined");
tokenTypes.add("damage-taken"); tokenTypes.add("damage-taken");
tokenTypes.add("damage-done");
tokenTypes.add("mob-kills"); tokenTypes.add("mob-kills");
tokenTypes.add("player-kills"); tokenTypes.add("player-kills");
tokenTypes.add("arrows-shot"); tokenTypes.add("arrows-shot");

View File

@@ -27,6 +27,7 @@ import org.bukkit.Material;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -133,6 +134,65 @@ public class ConfigTools {
return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE); return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE);
} }
/**
* Format a string with several placeholders to be ready for lore usage.
*
* @param configName The message to use.
* @param placeHoldersValues Map containing placeholders names as keys and values.
* @return Formatted string, null if the configName doesn't exist.
*/
public Component formatLoreMultiplePlaceholders(String configName, Map<String, String> placeHoldersValues) {
String lore = toolStats.config.getString("messages." + configName);
if (lore == null) {
toolStats.logger.warning("Unable to find config message for: messages." + configName);
return null;
}
// if the config message is empty, don't send it
if (lore.isEmpty()) {
return null;
}
Pattern pattern = Pattern.compile("\\{([^}]+)\\}(\\S*)\\s*");
Matcher matcher = pattern.matcher(lore);
StringBuilder result = new StringBuilder();
int lastEnd = 0;
while (matcher.find()) {
String placeholder = matcher.group(1);
String unit = matcher.group(2);
result.append(lore, lastEnd, matcher.start());
if (placeHoldersValues.containsKey(placeholder)) {
result.append(placeHoldersValues.get(placeholder)).append(unit).append(" ");
}
// Update lastEnd to end of the match
lastEnd = matcher.end();
}
if (lastEnd < lore.length()) {
result.append(lore.substring(lastEnd));
}
Component component;
// Clean output text
String outputText = result.toString().replaceAll("\\s+", " ").trim();
// if we match the old color codes, then format them as so
Matcher hexMatcher = CONFIG_HEX_PATTERN.matcher(outputText);
Matcher colorMatcher = COLOR_CODES.matcher(outputText);
if (hexMatcher.find() || colorMatcher.find()) {
component = LegacyComponentSerializer.legacyAmpersand().deserialize(outputText);
} else {
// otherwise format them normally
component = MiniMessage.miniMessage().deserialize(outputText);
}
return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE);
}
/** /**
* Format a string from the config. * Format a string from the config.
* *

View File

@@ -62,4 +62,4 @@ public class ConfigUpdater {
version11.update(); version11.update();
} }
} }
} }

View File

@@ -25,7 +25,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class TokenItems { public class TokenItems {

View File

@@ -86,6 +86,11 @@ public class Version11 {
toolStats.logger.info("Adding enabled.damage-done.bow to config.yml"); toolStats.logger.info("Adding enabled.damage-done.bow to config.yml");
toolStats.logger.info("Adding enabled.damage-done.mace to config.yml"); toolStats.logger.info("Adding enabled.damage-done.mace to config.yml");
toolStats.logger.info("Updating entry for messages.flight-time");
String oldFlightTime = toolStats.config.getString("messages.flight-time");
toolStats.config.set("messages.flight-time-old", oldFlightTime);
toolStats.config.set("messages.flight-time", "&7Flight time: &8{years}y {months}m {days}d {hours}h {minutes}m {seconds}s");
// save the config and reload it // save the config and reload it
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
@@ -96,4 +101,4 @@ public class Version11 {
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 11. A copy of version 10 has been saved as config-10.yml"); toolStats.logger.info("Config has been updated to version 11. A copy of version 10 has been saved as config-10.yml");
} }
} }

View File

@@ -196,7 +196,7 @@ messages:
dropped-by: "&7Dropped by: &8{name}" # name will be player/mob name dropped-by: "&7Dropped by: &8{name}" # name will be player/mob name
damage-taken: "&7Damage taken: &8{damage}" damage-taken: "&7Damage taken: &8{damage}"
arrows-shot: "&7Arrows shot: &8{arrows}" arrows-shot: "&7Arrows shot: &8{arrows}"
flight-time: "&7Flight time: &8{time}" flight-time: "&7Flight time: &8{years}y {months}m {days}d {hours}h {minutes}m {seconds}s"
damage-done: "&7Damage done: &8{damage}" damage-done: "&7Damage done: &8{damage}"
# Set display name for mobs. See: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html # Set display name for mobs. See: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html
mobs: mobs: