Compare commits

...

14 Commits

Author SHA1 Message Date
hyperdefined
84c1f8313a Merge pull request #108 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-clean-plugin-3.5.0
Bump org.apache.maven.plugins:maven-clean-plugin from 3.4.1 to 3.5.0
2025-06-08 20:07:25 -04:00
dependabot[bot]
f7ec488396 Bump org.apache.maven.plugins:maven-clean-plugin from 3.4.1 to 3.5.0
Bumps [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) from 3.4.1 to 3.5.0.
- [Release notes](https://github.com/apache/maven-clean-plugin/releases)
- [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.4.1...maven-clean-plugin-3.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 11:58:28 +00:00
hyperdefined
df014fd888 docs update 2025-05-21 15:12:54 -04:00
hyperdefined
1d617706a6 Update pom.xml 2025-05-15 18:56:27 -04:00
hyperdefined
49e1acc66a imports 2025-05-15 18:52:00 -04:00
hyperdefined
eddaec1543 remove hard coded paper material 2025-05-15 18:51:17 -04:00
hyperdefined
57ec36d5a7 oops lol 2025-05-15 18:49:35 -04:00
hyperdefined
a617875975 Update CommandToolStats.java 2025-05-15 18:47:38 -04:00
hyperdefined
3ee53e0cf7 config updater for 13 2025-05-15 18:44:48 -04:00
hyperdefined
364859bc0a few fixes 2025-05-15 18:33:27 -04:00
hyperdefined
0efc07b12b Update TokenData.java 2025-05-15 18:15:27 -04:00
hyperdefined
e73ba5376c Update config.yml 2025-05-15 18:14:00 -04:00
hyperdefined
68318e3af2 {levels} placeholder 2025-05-15 18:13:47 -04:00
hyperdefined
c7cd25e866 custom model data & massive cleanup
closes #105
2025-05-15 17:59:44 -04:00
40 changed files with 299 additions and 423 deletions

View File

@@ -4,7 +4,7 @@
<a href="https://modrinth.com/plugin/ToolStats"><img alt="modrinth" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/available/modrinth_vector.svg"></a>
<a href="https://hangar.papermc.io/hyperdefined/ToolStats"><img alt="hangar" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/available/hangar_vector.svg"></a>
<a href="https://papermc.io"><img alt="paper" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/paper_vector.svg"></a>
<a href="https://github.com/hyperdefined/ToolStats/wiki"><img alt="ghpages" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/ghpages_vector.svg"></a>
<a href="https://docs.hyper.lol/plugins/toolstats/about/"><img alt="ghpages" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/ghpages_vector.svg"></a>
<a href="https://discord.gg/rJuQXVcJz8"><img alt="discord-singular" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/discord-singular_vector.svg"></a>
<a href="https://buymeacoffee.com/hyperdefined"><img alt="buymeacoffee-singular" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/donate/buymeacoffee-singular_vector.svg"></a>
</p>
@@ -27,23 +27,23 @@ The best part is, this data is stored on the item itself.
If item lore is ever incorrect/missing, you can run `/toolstats reset`. This command fixes the lore on whatever item you are holding.
![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/image3.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image4.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image5.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image6.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image7.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image8.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image9.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image10.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image11.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image13.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image14.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image12.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image2.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image3.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image4.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image5.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image6.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image7.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image8.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image9.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image10.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image11.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image13.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image14.png)
![Image](https://docs.hyper.lol/plugins/toolstats/assets/image12.png)
## Documentation
Visit the [wiki](https://github.com/hyperdefined/ToolStats/wiki) for help.
Visit the [wiki](https://docs.hyper.lol/plugins/toolstats/about/) for help.
## License
This plugin is released under GNU General Public License v3. See [LICENSE](https://github.com/hyperdefined/ToolStats/blob/master/LICENSE).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -23,7 +23,7 @@
<groupId>lol.hyper</groupId>
<artifactId>toolstats</artifactId>
<version>1.9.6</version>
<version>1.9.7</version>
<packaging>jar</packaging>
<name>ToolStats</name>
@@ -37,7 +37,7 @@
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.4.1</version>
<version>3.5.0</version>
<executions>
<execution>
<id>auto-clean</id>

View File

@@ -25,7 +25,6 @@ import lol.hyper.toolstats.events.*;
import lol.hyper.toolstats.tools.*;
import lol.hyper.toolstats.tools.config.ConfigTools;
import lol.hyper.toolstats.tools.config.ConfigUpdater;
import lol.hyper.toolstats.tools.config.TokenItems;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
@@ -121,7 +120,7 @@ public final class ToolStats extends JavaPlugin {
*/
public final NamespacedKey originType = new NamespacedKey(this, "origin");
public final int CONFIG_VERSION = 12;
public final int CONFIG_VERSION = 13;
public final Logger logger = this.getLogger();
public final File configFile = new File(this.getDataFolder(), "config.yml");
public boolean tokens = false;
@@ -150,8 +149,7 @@ public final class ToolStats extends JavaPlugin {
public ItemChecker itemChecker;
public ShootBow shootBow;
public ConfigTools configTools;
public TokenItems tokenItems;
public TokenCrafting tokenCrafting;
public TokenData tokenData;
public AnvilEvent anvilEvent;
public PrepareCraft prepareCraft;
@@ -164,10 +162,9 @@ public final class ToolStats extends JavaPlugin {
loadConfig();
configTools = new ConfigTools(this);
tokenItems = new TokenItems(this);
tokenCrafting = new TokenCrafting(this);
tokenCrafting.setup();
for (ShapedRecipe recipe : tokenCrafting.getRecipes()) {
tokenData = new TokenData(this);
tokenData.setup();
for (ShapedRecipe recipe : tokenData.getRecipes()) {
if (tokens && config.getBoolean("tokens.craft-tokens")) {
Bukkit.addRecipe(recipe);
}

View File

@@ -30,7 +30,6 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
@@ -64,8 +63,8 @@ public class CommandToolStats implements TabExecutor {
if (sender.hasPermission("toolstats.reload")) {
boolean oldTokensStatus = toolStats.tokens;
toolStats.loadConfig();
toolStats.tokenCrafting.getRecipes().clear();
toolStats.tokenCrafting.setup();
toolStats.tokenData.getRecipes().clear();
toolStats.tokenData.setup();
// if the server went from tokens off -> on, add the recipes
// if the server went from tokens on -> off, remove the recipes
if (toolStats.tokens != oldTokensStatus) {
@@ -73,14 +72,14 @@ public class CommandToolStats implements TabExecutor {
if (toolStats.tokens) {
sender.sendMessage(Component.text("It looks like you ENABLED the token system. While this is fine, it can break. Please restart your server instead.", NamedTextColor.YELLOW));
if (toolStats.config.getBoolean("tokens.craft-token")) {
for (ShapedRecipe recipe : toolStats.tokenCrafting.getRecipes()) {
for (ShapedRecipe recipe : toolStats.tokenData.getRecipes()) {
Bukkit.addRecipe(recipe);
}
}
} else {
// tokens are now disabled
sender.sendMessage(Component.text("It looks like you DISABLED the token system. While this is fine, it can break. Please restart your server instead.", NamedTextColor.YELLOW));
for (ShapedRecipe recipe : toolStats.tokenCrafting.getRecipes()) {
for (ShapedRecipe recipe : toolStats.tokenData.getRecipes()) {
Bukkit.removeRecipe(recipe.getKey());
}
}
@@ -172,7 +171,7 @@ public class CommandToolStats implements TabExecutor {
return true;
}
String tokenType = args[2];
if (!toolStats.tokenCrafting.getTokenTypes().contains(tokenType)) {
if (!toolStats.tokenData.getTokenTypes().contains(tokenType)) {
sender.sendMessage(Component.text("Invalid token type.", NamedTextColor.RED));
return true;
}
@@ -458,80 +457,9 @@ public class CommandToolStats implements TabExecutor {
* @param tokenType The token type.
*/
private void giveToken(Player target, String tokenType, int amount) {
switch (tokenType) {
case "crops-mined": {
ItemStack itemStack = toolStats.tokenItems.cropsMined();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "blocks-mined": {
ItemStack itemStack = toolStats.tokenItems.blocksMined();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "damage-taken": {
ItemStack itemStack = toolStats.tokenItems.damageTaken();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "damage-done": {
ItemStack itemStack = toolStats.tokenItems.damageDone();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "mob-kills": {
ItemStack itemStack = toolStats.tokenItems.mobKills();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "player-kills": {
ItemStack itemStack = toolStats.tokenItems.playerKills();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "arrows-shot": {
ItemStack itemStack = toolStats.tokenItems.arrowsShot();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "sheep-sheared": {
ItemStack itemStack = toolStats.tokenItems.sheepSheared();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "flight-time": {
ItemStack itemStack = toolStats.tokenItems.flightTime();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "fish-caught": {
ItemStack itemStack = toolStats.tokenItems.fishCaught();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "reset": {
ItemStack itemStack = toolStats.tokenItems.resetToken();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
case "remove": {
ItemStack itemStack = toolStats.tokenItems.removeToken();
itemStack.setAmount(amount);
target.getInventory().addItem(itemStack);
break;
}
}
ItemStack token = toolStats.tokenData.createToken(tokenType);
token.setAmount(amount);
target.getInventory().addItem(token);
}
/**
@@ -847,6 +775,7 @@ public class CommandToolStats implements TabExecutor {
}
editedItem.setItemMeta(editedItemMeta);
player.getInventory().setItemInMainHand(editedItem);
player.sendMessage(Component.text("Updated stat " + stat + " for held item!", NamedTextColor.GREEN));
}
/**
@@ -1124,6 +1053,7 @@ public class CommandToolStats implements TabExecutor {
}
editedItem.setItemMeta(editedItemMeta);
player.getInventory().setItemInMainHand(editedItem);
player.sendMessage(Component.text("Removed stat " + stat + " for held item!", NamedTextColor.GREEN));
}
@Nullable
@@ -1154,20 +1084,20 @@ public class CommandToolStats implements TabExecutor {
}
if (args.length == 2 && args[0].equalsIgnoreCase("edit") && sender.hasPermission("toolstats.edit")) {
// yes I am lazy
return toolStats.tokenCrafting.getTokenTypes().stream()
return toolStats.tokenData.getTokenTypes().stream()
.filter(s -> !s.equals("remove") && !s.equals("reset"))
.map(s -> s.equals("crops-mined") ? "crops-harvested" : s)
.collect(Collectors.toList());
}
if (args.length == 2 && args[0].equalsIgnoreCase("remove") && sender.hasPermission("toolstats.remove")) {
// yes I am lazy
return toolStats.tokenCrafting.getTokenTypes().stream()
return toolStats.tokenData.getTokenTypes().stream()
.filter(s -> !s.equals("remove") && !s.equals("reset"))
.map(s -> s.equals("crops-mined") ? "crops-harvested" : s)
.collect(Collectors.toList());
}
if (args.length == 3 && args[0].equalsIgnoreCase("givetokens") && sender.hasPermission("toolstats.givetokens")) {
return toolStats.tokenCrafting.getTokenTypes();
return toolStats.tokenData.getTokenTypes();
}
return null;

View File

@@ -57,7 +57,6 @@ public class AnvilEvent implements Listener {
}
Material firstSlotMaterial = firstSlot.getType();
Material secondSlotMaterial = secondSlot.getType();
// make sure the first item is a valid item
if (!toolStats.itemChecker.isValidItem(firstSlotMaterial)) {
@@ -67,7 +66,7 @@ public class AnvilEvent implements Listener {
PersistentDataContainer secondSlotContainer = secondSlot.getItemMeta().getPersistentDataContainer();
// make sure the 2nd item is one of ours
if (secondSlotMaterial != Material.PAPER || !secondSlotContainer.has(toolStats.tokenType, PersistentDataType.STRING)) {
if (!secondSlotContainer.has(toolStats.tokenType, PersistentDataType.STRING)) {
return;
}

View File

@@ -18,7 +18,6 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@@ -40,7 +39,7 @@ public class PrepareCraft implements Listener {
// get the items in the crafting grid
ItemStack[] grid = event.getInventory().getMatrix();
for (ItemStack item : grid) {
if (item == null || item.getType() != Material.PAPER) {
if (item == null) {
continue;
}
ItemMeta meta = item.getItemMeta();

View File

@@ -17,104 +17,110 @@
package lol.hyper.toolstats.tools;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.CustomModelData;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
public class TokenCrafting {
public class TokenData {
private final ToolStats toolStats;
private final Set<ShapedRecipe> recipes = new HashSet<>();
private final ArrayList<String> tokenTypes = new ArrayList<>();
public TokenCrafting(ToolStats toolStats) {
public TokenData(ToolStats toolStats) {
this.toolStats = toolStats;
}
public void setup() {
NamespacedKey playerKillsKey = new NamespacedKey(toolStats, "player-kills-token");
ShapedRecipe playerKillRecipe = new ShapedRecipe(playerKillsKey, toolStats.tokenItems.playerKills());
ShapedRecipe playerKillRecipe = new ShapedRecipe(playerKillsKey, createToken("player-kills"));
playerKillRecipe.shape(" P ", "PSP", " P ");
playerKillRecipe.setIngredient('P', Material.PAPER);
playerKillRecipe.setIngredient('S', Material.WOODEN_SWORD);
recipes.add(playerKillRecipe);
NamespacedKey mobKillsKey = new NamespacedKey(toolStats, "mob-kills-token");
ShapedRecipe mobKillsRecipe = new ShapedRecipe(mobKillsKey, toolStats.tokenItems.mobKills());
ShapedRecipe mobKillsRecipe = new ShapedRecipe(mobKillsKey, createToken("mob-kills"));
mobKillsRecipe.shape(" P ", "PRP", " P ");
mobKillsRecipe.setIngredient('P', Material.PAPER);
mobKillsRecipe.setIngredient('R', Material.ROTTEN_FLESH);
recipes.add(mobKillsRecipe);
NamespacedKey blocksMinedKey = new NamespacedKey(toolStats, "blocks-mined-token");
ShapedRecipe blocksMinedRecipe = new ShapedRecipe(blocksMinedKey, toolStats.tokenItems.blocksMined());
ShapedRecipe blocksMinedRecipe = new ShapedRecipe(blocksMinedKey, createToken("blocks-mined"));
blocksMinedRecipe.shape(" P ", "PSP", " P ");
blocksMinedRecipe.setIngredient('P', Material.PAPER);
blocksMinedRecipe.setIngredient('S', Material.WOODEN_PICKAXE);
recipes.add(blocksMinedRecipe);
NamespacedKey cropsMinedKey = new NamespacedKey(toolStats, "crops-mined-token");
ShapedRecipe cropsMinedRecipe = new ShapedRecipe(cropsMinedKey, toolStats.tokenItems.cropsMined());
ShapedRecipe cropsMinedRecipe = new ShapedRecipe(cropsMinedKey, createToken("crops-mined"));
cropsMinedRecipe.shape(" P ", "PHP", " P ");
cropsMinedRecipe.setIngredient('P', Material.PAPER);
cropsMinedRecipe.setIngredient('H', Material.WOODEN_HOE);
recipes.add(cropsMinedRecipe);
NamespacedKey fishCaughtKey = new NamespacedKey(toolStats, "fish-caught-token");
ShapedRecipe fishCaughtRecipe = new ShapedRecipe(fishCaughtKey, toolStats.tokenItems.fishCaught());
ShapedRecipe fishCaughtRecipe = new ShapedRecipe(fishCaughtKey, createToken("fish-caught"));
fishCaughtRecipe.shape(" P ", "PCP", " P ");
fishCaughtRecipe.setIngredient('P', Material.PAPER);
fishCaughtRecipe.setIngredient('C', Material.COD);
recipes.add(fishCaughtRecipe);
NamespacedKey sheepShearedKey = new NamespacedKey(toolStats, "sheep-sheared-token");
ShapedRecipe sheepShearedRecipe = new ShapedRecipe(sheepShearedKey, toolStats.tokenItems.sheepSheared());
ShapedRecipe sheepShearedRecipe = new ShapedRecipe(sheepShearedKey, createToken("sheep-sheared"));
sheepShearedRecipe.shape(" P ", "PWP", " P ");
sheepShearedRecipe.setIngredient('P', Material.PAPER);
sheepShearedRecipe.setIngredient('W', Material.WHITE_WOOL);
recipes.add(sheepShearedRecipe);
NamespacedKey armorDamageKey = new NamespacedKey(toolStats, "damage-taken-token");
ShapedRecipe armorDamageRecipe = new ShapedRecipe(armorDamageKey, toolStats.tokenItems.damageTaken());
ShapedRecipe armorDamageRecipe = new ShapedRecipe(armorDamageKey, createToken("damage-taken"));
armorDamageRecipe.shape(" P ", "PCP", " P ");
armorDamageRecipe.setIngredient('P', Material.PAPER);
armorDamageRecipe.setIngredient('C', Material.LEATHER_CHESTPLATE);
recipes.add(armorDamageRecipe);
NamespacedKey damageDoneKey = new NamespacedKey(toolStats, "damage-done-token");
ShapedRecipe damageDoneRecipe = new ShapedRecipe(damageDoneKey, toolStats.tokenItems.damageDone());
ShapedRecipe damageDoneRecipe = new ShapedRecipe(damageDoneKey, createToken("damage-done"));
damageDoneRecipe.shape(" P ", "PSP", " P ");
damageDoneRecipe.setIngredient('P', Material.PAPER);
damageDoneRecipe.setIngredient('S', Material.SHIELD);
recipes.add(damageDoneRecipe);
NamespacedKey arrowsShotKey = new NamespacedKey(toolStats, "arrows-shot-token");
ShapedRecipe arrowsShotRecipe = new ShapedRecipe(arrowsShotKey, toolStats.tokenItems.arrowsShot());
ShapedRecipe arrowsShotRecipe = new ShapedRecipe(arrowsShotKey, createToken("arrows-shot"));
arrowsShotRecipe.shape(" P ", "PAP", " P ");
arrowsShotRecipe.setIngredient('P', Material.PAPER);
arrowsShotRecipe.setIngredient('A', Material.ARROW);
recipes.add(arrowsShotRecipe);
NamespacedKey flightTimeKey = new NamespacedKey(toolStats, "flight-time-token");
ShapedRecipe flightTimeRecipe = new ShapedRecipe(flightTimeKey, toolStats.tokenItems.flightTime());
ShapedRecipe flightTimeRecipe = new ShapedRecipe(flightTimeKey, createToken("flight-time"));
flightTimeRecipe.shape(" P ", "PFP", " P ");
flightTimeRecipe.setIngredient('P', Material.PAPER);
flightTimeRecipe.setIngredient('F', Material.FEATHER);
recipes.add(flightTimeRecipe);
NamespacedKey resetKey = new NamespacedKey(toolStats, "reset-token");
ShapedRecipe resetRecipe = new ShapedRecipe(resetKey, toolStats.tokenItems.resetToken());
ShapedRecipe resetRecipe = new ShapedRecipe(resetKey, createToken("reset"));
resetRecipe.shape(" P ", "PPP", " P ");
resetRecipe.setIngredient('P', Material.PAPER);
recipes.add(resetRecipe);
NamespacedKey removeKey = new NamespacedKey(toolStats, "remove-token");
ShapedRecipe removeRecipe = new ShapedRecipe(removeKey, toolStats.tokenItems.removeToken());
ShapedRecipe removeRecipe = new ShapedRecipe(removeKey, createToken("remove"));
removeRecipe.shape(" P ", "P P", " P ");
removeRecipe.setIngredient('P', Material.PAPER);
recipes.add(removeRecipe);
@@ -140,4 +146,79 @@ public class TokenCrafting {
public ArrayList<String> getTokenTypes() {
return tokenTypes;
}
public ItemStack createToken(String tokenType) {
// we don't have to check if the token exists
// we do that prior
ConfigurationSection tokenConfig = toolStats.config.getConfigurationSection("tokens.data." + tokenType);
String materialFromConfig = tokenConfig.getString("material");
if (materialFromConfig == null) {
toolStats.logger.warning("Could not find material config for token " + tokenType);
toolStats.logger.warning("Using PAPER as default.");
materialFromConfig = "PAPER";
}
Material material = Material.getMaterial(materialFromConfig);
if (material == null) {
toolStats.logger.warning("Material " + materialFromConfig + " is not a valid Minecraft material.");
toolStats.logger.warning("Using PAPER as default.");
material = Material.PAPER;
}
ItemStack token = new ItemStack(material);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data." + tokenType + ".title");
List<Component> lore = toolStats.configTools.getTokenLore(tokenType);
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, tokenType);
token.setItemMeta(tokenMeta);
// set the custom model data
if (tokenConfig.getBoolean("custom-model-data.enabled")) {
String type = tokenConfig.getString("custom-model-data.type");
Object value = tokenConfig.get("custom-model-data.value");
if (type == null || value == null) {
toolStats.logger.info("Could not find custom model data for token " + tokenType);
toolStats.logger.info("Type: " + type);
toolStats.logger.info("Value: " + value);
return null;
}
CustomModelData data = setData(type, value);
if (data != null) {
token.setData(DataComponentTypes.CUSTOM_MODEL_DATA, data);
} else {
return null;
}
}
return token;
}
private CustomModelData setData(String type, Object data) {
switch (type.toLowerCase(Locale.ROOT)) {
case "float": {
float f;
try {
f = Float.parseFloat(data.toString());
} catch (NumberFormatException e) {
toolStats.logger.info(data + " is not a valid float!");
return null;
}
return CustomModelData.customModelData().addFloat(f).build();
}
case "string": {
return CustomModelData.customModelData().addString(data.toString()).build();
}
default: {
toolStats.logger.info(data + " is not a valid data type!");
return null;
}
}
}
}

View File

@@ -244,6 +244,13 @@ public class ConfigTools {
List<Component> finalLore = new ArrayList<>();
for (String line : raw) {
if (line.contains("{levels}")) {
Integer levels = toolStats.config.getInt("tokens.data." + tokenType + ".levels");
// will return 0 if it doesn't exist
if (levels != 0) {
line = line.replace("{levels}", String.valueOf(levels));
}
}
Component component;
// if we match the old color codes, then format them as so
Matcher hexMatcher = CONFIG_HEX_PATTERN.matcher(line);

View File

@@ -31,40 +31,15 @@ public class ConfigUpdater {
public void updateConfig() {
int version = toolStats.config.getInt("config-version");
// Version 5 to 6
if (version == 5) {
Version6 version6 = new Version6(toolStats);
version6.update();
}
// Version 6 to 7
if (version == 6) {
Version7 version7 = new Version7(toolStats);
version7.update();
}
// Version 7 to 8
if (version == 7) {
Version8 version8 = new Version8(toolStats);
version8.update();
}
// Version 8 to 9
if (version == 8) {
Version9 version9 = new Version9(toolStats);
version9.update();
}
// Version 9 to 10
if (version == 9) {
Version10 version10 = new Version10(toolStats);
version10.update();
}
// Version 10 to 11
if (version == 10) {
Version11 version11 = new Version11(toolStats);
version11.update();
}
// Version 11 to 12
if (version == 11) {
Version12 version12 = new Version12(toolStats);
version12.update();
switch (version) {
case 5 -> new Version6(toolStats).update(); // 5 to 6
case 6 -> new Version7(toolStats).update(); // 6 to 7
case 7 -> new Version8(toolStats).update(); // 7 to 8
case 8 -> new Version9(toolStats).update(); // 8 to 9
case 9 -> new Version10(toolStats).update(); // 9 to 10
case 10 -> new Version11(toolStats).update(); // 10 to 11
case 11 -> new Version12(toolStats).update(); // 11 to 12
case 12 -> new Version13(toolStats).update(); // 12 to 13
}
}
}

View File

@@ -1,253 +0,0 @@
/*
* This file is part of ToolStats.
*
* ToolStats is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ToolStats is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ToolStats. If not, see <https://www.gnu.org/licenses/>.
*/
package lol.hyper.toolstats.tools.config;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.List;
public class TokenItems {
private final ToolStats toolStats;
public TokenItems(ToolStats toolStats) {
this.toolStats = toolStats;
}
public ItemStack playerKills() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.player-kills.title");
List<Component> lore = toolStats.configTools.getTokenLore("player-kills");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "player-kills");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack mobKills() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.mob-kills.title");
List<Component> lore = toolStats.configTools.getTokenLore("mob-kills");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "mob-kills");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack blocksMined() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.blocks-mined.title");
List<Component> lore = toolStats.configTools.getTokenLore("blocks-mined");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "blocks-mined");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack cropsMined() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.crops-mined.title");
List<Component> lore = toolStats.configTools.getTokenLore("crops-mined");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "crops-mined");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack fishCaught() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.fish-caught.title");
List<Component> lore = toolStats.configTools.getTokenLore("fight-caught");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "fish-caught");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack sheepSheared() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.sheep-sheared.title");
List<Component> lore = toolStats.configTools.getTokenLore("sheep-sheared");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "sheep-sheared");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack damageTaken() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.damage-taken.title");
List<Component> lore = toolStats.configTools.getTokenLore("damage-taken");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "damage-taken");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack damageDone() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.damage-done.title");
List<Component> lore = toolStats.configTools.getTokenLore("damage-done");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "damage-done");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack arrowsShot() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.arrows-shot.title");
List<Component> lore = toolStats.configTools.getTokenLore("arrows-shot");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "arrows-shot");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack flightTime() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.flight-time.title");
List<Component> lore = toolStats.configTools.getTokenLore("flight-time");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "flight-time");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack resetToken() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.reset.title");
List<Component> lore = toolStats.configTools.getTokenLore("reset");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "reset");
token.setItemMeta(tokenMeta);
return token;
}
public ItemStack removeToken() {
// set up the item
ItemStack token = new ItemStack(Material.PAPER);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
Component title = toolStats.configTools.format("tokens.data.remove.title");
List<Component> lore = toolStats.configTools.getTokenLore("remove");
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.tokenType, PersistentDataType.STRING, "remove");
token.setItemMeta(tokenMeta);
return token;
}
}

View File

@@ -17,16 +17,11 @@
package lol.hyper.toolstats.tools.config.versions;
import it.unimi.dsi.fastutil.Pair;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
public class Version12 {

View File

@@ -0,0 +1,74 @@
/*
* This file is part of ToolStats.
*
* ToolStats is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ToolStats is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ToolStats. If not, see <https://www.gnu.org/licenses/>.
*/
package lol.hyper.toolstats.tools.config.versions;
import lol.hyper.toolstats.ToolStats;
import java.io.File;
import java.io.IOException;
public class Version13 {
private final ToolStats toolStats;
/**
* Used for updating from version 12 to 13.
*
* @param toolStats ToolStats instance.
*/
public Version13(ToolStats toolStats) {
this.toolStats = toolStats;
}
/**
* Perform the config update.
*/
public void update() {
// save the old config first
try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-12.yml");
} catch (IOException exception) {
toolStats.logger.severe("Unable to save config-12.yml!");
throw new RuntimeException(exception);
}
toolStats.logger.info("Updating config.yml to version 13.");
toolStats.config.set("config-version", 13);
for (String key : toolStats.config.getConfigurationSection("tokens.data").getKeys(false)) {
toolStats.logger.info("Adding tokens.data." + key + ".material");
toolStats.config.set("tokens.data." + key + ".material", "PAPER");
toolStats.logger.info("Adding tokens.data." + key + ".custom-model-data.enabled");
toolStats.config.set("tokens.data." + key + ".custom-model-data.enabled", false);
toolStats.logger.info("Adding tokens.data." + key + ".custom-model-data.type");
toolStats.config.set("tokens.data." + key + ".custom-model-data.type", "float");
toolStats.logger.info("Adding tokens.data." + key + ".custom-model-data.value");
toolStats.config.set("tokens.data." + key + ".custom-model-data.value", 1001);
}
// save the config and reload it
try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!");
throw new RuntimeException(exception);
}
toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 13. A copy of version 12 has been saved as config-12.yml");
}
}

View File

@@ -8,62 +8,134 @@ tokens:
title: "&7ToolStats: &8Player Kills Token"
lore:
- "&8Combine with a melee or ranged weapon in an anvil to track player kills."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
mob-kills:
title: "&7ToolStats: &8Mob Kills Token"
lore:
- "&8Combine with a melee or ranged weapon in an anvil to track mob kills."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
blocks-mined:
title: "&7ToolStats: &8Blocks Mined Token"
lore:
- "&8Combine with a pickaxe, axe, shovel, or shears in an anvil to track blocks mined."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
crops-mined:
title: "&7ToolStats: &8Crops Mined Token"
lore:
- "&8Combine with a hoe in an anvil to track crops broken."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
fish-caught:
title: "&7ToolStats: &8Fish Caught Token"
lore:
- "&8Combine with a fishing rod in an anvil to track fish caught."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
sheep-sheared:
title: "&7ToolStats: &8Sheep Sheared Token"
lore:
- "&8Combine with shears in an anvil to track sheep sheared."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
damage-taken:
title: "&7ToolStats: &8Damage Taken Token"
lore:
- "&8Combine with an armor piece in an anvil to track damage taken."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
damage-done:
title: "&7ToolStats: &8Damage Done Token"
lore:
- "&8Combine with a melee or ranged weapon in an anvil to track damage done."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
arrows-shot:
title: "&7ToolStats: &8Arrows Shot Token"
lore:
- "&8Combine with a bow or crossbow in an anvil to track arrows shot."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
flight-time:
title: "&7ToolStats: &8Flight Time Token"
lore:
- "&8Combine with an elytra in an anvil to track flight time."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
reset:
title: "&7ToolStats: &8Reset Token"
lore:
- "&8Combine in an anvil with to reset ALL stats for this item. Tokens on this item stay."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
remove:
title: "&7ToolStats: &8Remove Token"
lore:
- "&8Combine in an anvil with to REMOVE ALL stats and tokens for this item."
- "&8Uses &7{levels} &8level."
levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
enabled:
# Will show "Crafted by <player>"
@@ -274,4 +346,4 @@ normalize-time-creation: false
# Allows stats and origins to be tracked if the player is in creative mode.
allow-creative: false
config-version: 12
config-version: 13