Compare commits

...

33 Commits

Author SHA1 Message Date
hyperdefined
e38ffdef07 forgot these 2025-08-06 19:43:24 -04:00
hyperdefined
c7540244bc update things 2025-08-06 19:34:59 -04:00
hyperdefined
613957fadf hyperlib updates 2025-08-06 19:09:13 -04:00
hyperdefined
e48be6ba20 hyperlib demo 2025-08-04 13:29:26 -04:00
hyperdefined
c0d79fd740 Update pom.xml 2025-07-23 12:31:06 -04:00
hyperdefined
b056972d30 swap order of anvil checking to account 2025-07-23 12:30:46 -04:00
hyperdefined
525df4bcf6 use the new GLIDER DataComponent 2025-07-23 12:19:40 -04:00
hyperdefined
86cbdd58ff new purge command 2025-07-23 11:29:20 -04:00
hyperdefined
27a89fd67c unify owner and timestamp creation 2025-07-23 10:53:22 -04:00
hyperdefined
70ed50ce9e 1.9.8
closes #109
2025-07-15 10:49:19 -04:00
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
hyperdefined
67d141c452 Update README.md 2025-05-07 18:10:52 -04:00
hyperdefined
c1300e916f Update pom.xml 2025-05-07 18:01:03 -04:00
hyperdefined
6d6f1aab8a add allow-creative 2025-05-07 17:58:44 -04:00
hyperdefined
b2ef154cc6 add dropped-by 2025-05-07 17:51:54 -04:00
hyperdefined
bc8f4948fe add normalize-time-creation 2025-05-06 20:29:27 -04:00
hyperdefined
70e19269ee rename many config things 2025-05-06 20:05:13 -04:00
hyperdefined
5373792480 new perms and suggestions 2025-05-06 18:42:52 -04:00
hyperdefined
f71d079e23 add remove ability 2025-05-06 18:36:17 -04:00
hyperdefined
bcb85c7a28 add edit ability 2025-05-06 17:07:57 -04:00
67 changed files with 1855 additions and 1157 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://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://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://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://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> <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> </p>
@@ -12,37 +12,38 @@
ToolStats is a Paper plugin that display various stats about tools. This plugin is inspired off of [GearStats](https://www.spigotmc.org/resources/gearstats.12960/). You can either track all statistics by default, or a use a token system to add statistics to tool/armor. You can configure how each statistic is shown on the item, or disable it! ToolStats is a Paper plugin that display various stats about tools. This plugin is inspired off of [GearStats](https://www.spigotmc.org/resources/gearstats.12960/). You can either track all statistics by default, or a use a token system to add statistics to tool/armor. You can configure how each statistic is shown on the item, or disable it!
Here is everything it tracks: Here is everything it tracks:
* Blocks mined (pickaxes, shovels, axes, hoes, shears) * Blocks mined (pickaxes, shovels, axes, hoes, shears).
* Crops mined (hoes) * Crops mined (hoes).
* Player/mob kills (swords, axes, tridents, bows/crossbows, mace) * Player/mob kills (swords, axes, tridents, bows/crossbows, mace).
* Ownership of items when crafted, looted (from chests), traded, spawned via creative, and caught from fishing. * Ownership of items when crafted, looted (from chests), traded, spawned via creative, and caught from fishing.
* Armor damage taken. * Armor damage taken.
* Damage done with weapons.
* Fish caught. * Fish caught.
* Sheep sheared. * Sheep sheared.
* Arrows shot (bows/crossbows) * Arrows shot (bows/crossbows).
* Flight time with elytras. * Flight time with elytras.
The best part is, this data is stored on the item itself. 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. 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://docs.hyper.lol/plugins/toolstats/assets/image.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image2.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image2.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image3.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image3.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image4.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image4.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image5.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image5.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image6.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image6.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image7.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image7.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image8.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image8.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image9.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image9.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image10.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image10.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image11.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image11.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image13.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image13.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image14.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image14.png)
![Image](https://raw.githubusercontent.com/hyperdefined/ToolStats/master/images/image12.png) ![Image](https://docs.hyper.lol/plugins/toolstats/assets/image12.png)
## Documentation ## 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 ## License
This plugin is released under GNU General Public License v3. See [LICENSE](https://github.com/hyperdefined/ToolStats/blob/master/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

30
pom.xml
View File

@@ -23,7 +23,7 @@
<groupId>lol.hyper</groupId> <groupId>lol.hyper</groupId>
<artifactId>toolstats</artifactId> <artifactId>toolstats</artifactId>
<version>1.9.5</version> <version>1.9.9</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>ToolStats</name> <name>ToolStats</name>
@@ -37,7 +37,7 @@
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.4.1</version> <version>3.5.0</version>
<executions> <executions>
<execution> <execution>
<id>auto-clean</id> <id>auto-clean</id>
@@ -64,12 +64,8 @@
<configuration> <configuration>
<relocations> <relocations>
<relocation> <relocation>
<pattern>org.bstats</pattern> <pattern>lol.hyper.hyperlib</pattern>
<shadedPattern>lol.hyper.toolstats.bstats</shadedPattern> <shadedPattern>lol.hyper.toolstats.hyperlib</shadedPattern>
</relocation>
<relocation>
<pattern>lol.hyper.githubreleaseapi</pattern>
<shadedPattern>lol.hyper.toolstats.updater</shadedPattern>
</relocation> </relocation>
</relocations> </relocations>
</configuration> </configuration>
@@ -99,25 +95,23 @@
<id>papermc</id> <id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url> <url>https://repo.papermc.io/repository/maven-public/</url>
</repository> </repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>io.papermc.paper</groupId> <groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId> <artifactId>paper-api</artifactId>
<version>1.21.5-R0.1-SNAPSHOT</version> <version>1.21.8-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bstats</groupId> <groupId>com.github.hyperdefined</groupId>
<artifactId>bstats-bukkit</artifactId> <artifactId>hyperlib</artifactId>
<version>3.1.0</version> <version>1.0.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>lol.hyper</groupId>
<artifactId>github-release-api</artifactId>
<version>1.0.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -17,16 +17,16 @@
package lol.hyper.toolstats; package lol.hyper.toolstats;
import lol.hyper.githubreleaseapi.GitHubRelease; import lol.hyper.hyperlib.HyperLib;
import lol.hyper.githubreleaseapi.GitHubReleaseAPI; import lol.hyper.hyperlib.bstats.HyperStats;
import lol.hyper.githubreleaseapi.ReleaseNotFoundException; import lol.hyper.hyperlib.releases.HyperUpdater;
import lol.hyper.hyperlib.utils.TextUtils;
import lol.hyper.toolstats.commands.CommandToolStats; import lol.hyper.toolstats.commands.CommandToolStats;
import lol.hyper.toolstats.events.*; import lol.hyper.toolstats.events.*;
import lol.hyper.toolstats.tools.*; import lol.hyper.toolstats.tools.*;
import lol.hyper.toolstats.tools.config.ConfigTools; import lol.hyper.toolstats.tools.config.ConfigTools;
import lol.hyper.toolstats.tools.config.ConfigUpdater; import lol.hyper.toolstats.tools.config.ConfigUpdater;
import lol.hyper.toolstats.tools.config.TokenItems; import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
@@ -34,10 +34,8 @@ import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.logging.Logger;
public final class ToolStats extends JavaPlugin { public final class ToolStats extends JavaPlugin {
@@ -93,6 +91,10 @@ public final class ToolStats extends JavaPlugin {
* Key for arrows shot. * Key for arrows shot.
*/ */
public final NamespacedKey arrowsShot = new NamespacedKey(this, "arrows-shot"); public final NamespacedKey arrowsShot = new NamespacedKey(this, "arrows-shot");
/**
* Key for arrows shot.
*/
public final NamespacedKey droppedBy = new NamespacedKey(this, "dropped-by");
/** /**
* Key for tracking flight time. * Key for tracking flight time.
*/ */
@@ -117,8 +119,8 @@ public final class ToolStats extends JavaPlugin {
*/ */
public final NamespacedKey originType = new NamespacedKey(this, "origin"); public final NamespacedKey originType = new NamespacedKey(this, "origin");
public final int CONFIG_VERSION = 11; public final int CONFIG_VERSION = 13;
public final Logger logger = this.getLogger(); public final ComponentLogger logger = this.getComponentLogger();
public final File configFile = new File(this.getDataFolder(), "config.yml"); public final File configFile = new File(this.getDataFolder(), "config.yml");
public boolean tokens = false; public boolean tokens = false;
public final Set<NamespacedKey> tokenKeys = new HashSet<>(); public final Set<NamespacedKey> tokenKeys = new HashSet<>();
@@ -146,13 +148,22 @@ public final class ToolStats extends JavaPlugin {
public ItemChecker itemChecker; public ItemChecker itemChecker;
public ShootBow shootBow; public ShootBow shootBow;
public ConfigTools configTools; public ConfigTools configTools;
public TokenItems tokenItems; public TokenData tokenData;
public TokenCrafting tokenCrafting;
public AnvilEvent anvilEvent; public AnvilEvent anvilEvent;
public PrepareCraft prepareCraft; public PrepareCraft prepareCraft;
public HyperLib hyperLib;
public TextUtils textUtils;
@Override @Override
public void onEnable() { public void onEnable() {
hyperLib = new HyperLib(this);
hyperLib.setup();
HyperStats stats = new HyperStats(hyperLib, 14110);
stats.setup();
textUtils = new TextUtils(hyperLib);
if (!configFile.exists()) { if (!configFile.exists()) {
this.saveResource("config.yml", true); this.saveResource("config.yml", true);
logger.info("Copying default config!"); logger.info("Copying default config!");
@@ -160,10 +171,9 @@ public final class ToolStats extends JavaPlugin {
loadConfig(); loadConfig();
configTools = new ConfigTools(this); configTools = new ConfigTools(this);
tokenItems = new TokenItems(this); tokenData = new TokenData(this);
tokenCrafting = new TokenCrafting(this); tokenData.setup();
tokenCrafting.setup(); for (ShapedRecipe recipe : tokenData.getRecipes()) {
for (ShapedRecipe recipe : tokenCrafting.getRecipes()) {
if (tokens && config.getBoolean("tokens.craft-tokens")) { if (tokens && config.getBoolean("tokens.craft-tokens")) {
Bukkit.addRecipe(recipe); Bukkit.addRecipe(recipe);
} }
@@ -224,14 +234,17 @@ public final class ToolStats extends JavaPlugin {
this.getCommand("toolstats").setExecutor(commandToolStats); this.getCommand("toolstats").setExecutor(commandToolStats);
new Metrics(this, 14110); HyperUpdater updater = new HyperUpdater(hyperLib);
Bukkit.getAsyncScheduler().runNow(this, scheduledTask -> checkForUpdates()); updater.setGitHub("hyperdefined", "ToolStats");
updater.setModrinth("oBZj9E15");
updater.setHangar("ToolStats", "paper");
updater.check();
} }
public void loadConfig() { public void loadConfig() {
config = YamlConfiguration.loadConfiguration(configFile); config = YamlConfiguration.loadConfiguration(configFile);
if (config.getInt("config-version") != CONFIG_VERSION) { if (config.getInt("config-version") != CONFIG_VERSION) {
logger.warning("Your config file is outdated! We will try to update it, but you should regenerate it!"); logger.warn("Your config file is outdated! We will try to update it, but you should regenerate it!");
ConfigUpdater configUpdater = new ConfigUpdater(this); ConfigUpdater configUpdater = new ConfigUpdater(this);
configUpdater.updateConfig(); configUpdater.updateConfig();
} }
@@ -246,29 +259,4 @@ public final class ToolStats extends JavaPlugin {
numberFormat = new NumberFormat(this); numberFormat = new NumberFormat(this);
} }
public void checkForUpdates() {
GitHubReleaseAPI api;
try {
api = new GitHubReleaseAPI("ToolStats", "hyperdefined");
} catch (IOException e) {
logger.warning("Unable to check updates!");
e.printStackTrace();
return;
}
GitHubRelease current;
try {
current = api.getReleaseByTag(this.getPluginMeta().getVersion());
} catch (ReleaseNotFoundException e) {
logger.warning("You are running a version that does not exist on GitHub. If you are in a dev environment, you can ignore this. Otherwise, this is a bug!");
return;
}
GitHubRelease latest = api.getLatestVersion();
int buildsBehind = api.getBuildsBehind(current);
if (buildsBehind == 0) {
logger.info("You are running the latest version.");
} else {
logger.warning("A new version is available (" + latest.getTagVersion() + ")! You are running version " + current.getTagVersion() + ". You are " + buildsBehind + " version(s) behind.");
}
}
} }

View File

@@ -17,12 +17,11 @@
package lol.hyper.toolstats.commands; package lol.hyper.toolstats.commands;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -38,6 +37,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class CommandToolStats implements TabExecutor { public class CommandToolStats implements TabExecutor {
@@ -62,8 +62,8 @@ public class CommandToolStats implements TabExecutor {
if (sender.hasPermission("toolstats.reload")) { if (sender.hasPermission("toolstats.reload")) {
boolean oldTokensStatus = toolStats.tokens; boolean oldTokensStatus = toolStats.tokens;
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.tokenCrafting.getRecipes().clear(); toolStats.tokenData.getRecipes().clear();
toolStats.tokenCrafting.setup(); toolStats.tokenData.setup();
// if the server went from tokens off -> on, add the recipes // if the server went from tokens off -> on, add the recipes
// if the server went from tokens on -> off, remove the recipes // if the server went from tokens on -> off, remove the recipes
if (toolStats.tokens != oldTokensStatus) { if (toolStats.tokens != oldTokensStatus) {
@@ -71,14 +71,14 @@ public class CommandToolStats implements TabExecutor {
if (toolStats.tokens) { 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)); 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")) { if (toolStats.config.getBoolean("tokens.craft-token")) {
for (ShapedRecipe recipe : toolStats.tokenCrafting.getRecipes()) { for (ShapedRecipe recipe : toolStats.tokenData.getRecipes()) {
Bukkit.addRecipe(recipe); Bukkit.addRecipe(recipe);
} }
} }
} else { } else {
// tokens are now disabled // 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)); 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()); Bukkit.removeRecipe(recipe.getKey());
} }
} }
@@ -89,6 +89,41 @@ public class CommandToolStats implements TabExecutor {
} }
return true; return true;
} }
// /toolstats edit stat value
case "edit": {
if (!sender.hasPermission("toolstats.edit")) {
sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true;
}
if (sender instanceof ConsoleCommandSender) {
sender.sendMessage(Component.text("You must be a player for this command.", NamedTextColor.RED));
return true;
}
if (args.length < 3) {
sender.sendMessage(Component.text("Invalid syntax. Usage: /toolstats edit <stat> <value>", NamedTextColor.RED));
return true;
}
handleEdit(args[1], args[2], (Player) sender);
return true;
}
// /toolstats remove stat
case "remove": {
if (!sender.hasPermission("toolstats.remove")) {
sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true;
}
if (sender instanceof ConsoleCommandSender) {
sender.sendMessage(Component.text("You must be a player for this command.", NamedTextColor.RED));
return true;
}
if (args.length < 2) {
sender.sendMessage(Component.text("Invalid syntax. Usage: /toolstats remove <stat>", NamedTextColor.RED));
return true;
}
handleRemove(args[1], (Player) sender);
return true;
}
case "reset": { case "reset": {
if (!sender.hasPermission("toolstats.reset")) { if (!sender.hasPermission("toolstats.reset")) {
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));
@@ -119,6 +154,37 @@ public class CommandToolStats implements TabExecutor {
sender.sendMessage(Component.text("Type /toolstats reset confirm to confirm this.", NamedTextColor.GREEN)); sender.sendMessage(Component.text("Type /toolstats reset confirm to confirm this.", NamedTextColor.GREEN));
return true; return true;
} }
case "purge": {
if (!sender.hasPermission("toolstats.purge")) {
sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true;
}
if (sender instanceof ConsoleCommandSender) {
sender.sendMessage(Component.text("You must be a player for this command.", NamedTextColor.RED));
return true;
}
if (args.length == 2 && args[1].equalsIgnoreCase("confirm")) {
if (!sender.hasPermission("toolstats.purge.confirm")) {
sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true;
}
Player player = (Player) sender;
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (!toolStats.itemChecker.isValidItem(heldItem.getType())) {
sender.sendMessage(Component.text("You must hold a valid item.", NamedTextColor.RED));
return true;
}
ItemStack purgedItem = toolStats.itemLore.removeAll(heldItem, true);
player.getInventory().setItemInMainHand(purgedItem);
sender.sendMessage(Component.text("The item was purged!", NamedTextColor.GREEN));
return true;
}
sender.sendMessage(Component.text("This will purge ALL ToolStats data from this item.", NamedTextColor.GREEN));
sender.sendMessage(Component.text("This includes all stats, ownership, and creation time.", NamedTextColor.GREEN));
sender.sendMessage(Component.text("THIS CANNOT BE UNDONE!", NamedTextColor.GREEN));
sender.sendMessage(Component.text("Type /toolstats purge confirm to confirm this.", NamedTextColor.GREEN));
return true;
}
case "givetokens": { case "givetokens": {
if (!sender.hasPermission("toolstats.givetokens")) { if (!sender.hasPermission("toolstats.givetokens")) {
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));
@@ -135,7 +201,7 @@ public class CommandToolStats implements TabExecutor {
return true; return true;
} }
String tokenType = args[2]; 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)); sender.sendMessage(Component.text("Invalid token type.", NamedTextColor.RED));
return true; return true;
} }
@@ -197,39 +263,17 @@ public class CommandToolStats implements TabExecutor {
origin = -1; origin = -1;
} }
// hard code elytras if (container.has(toolStats.droppedBy, PersistentDataType.STRING)) {
if (finalItem.getType() == Material.ELYTRA) { if (toolStats.config.getBoolean("enabled.dropped-by")) {
Long flightTime = null; if (container.has(toolStats.droppedBy)) {
Long timeCreated = null; String droppedBy = container.get(toolStats.droppedBy, PersistentDataType.STRING);
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) { lore.add(toolStats.configTools.formatLore("dropped-by", "{name}", droppedBy));
timeCreated = container.get(toolStats.timeCreated, PersistentDataType.LONG); } else {
player.sendMessage(Component.text("Unable to set 'dropped-by', as this item has no record of it."));
} }
if (container.has(toolStats.flightTime, PersistentDataType.LONG)) {
flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG);
}
if (flightTime != null) {
if (toolStats.config.getBoolean("enabled.flight-time")) {
Map<String, String> flightTimeFormatted = toolStats.numberFormat.formatTime(flightTime);
Component line = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", flightTimeFormatted);
lore.add(line);
} }
} }
if (timeCreated != null) {
Component timeCreatedLine = toolStats.configTools.formatLore("looted.found-by", "{player}", player.getName());
Component playerOwnerLine = toolStats.configTools.formatLore("looted.found-on", "{date}", toolStats.numberFormat.formatDate(new Date(timeCreated)));
lore.add(timeCreatedLine);
lore.add(playerOwnerLine);
}
finalMeta.lore(lore);
finalItem.setItemMeta(finalMeta);
int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem);
}
if (toolStats.configTools.checkConfig(original.getType(), "created-by")) {
if (container.has(toolStats.itemOwner, new UUIDDataType())) { if (container.has(toolStats.itemOwner, new UUIDDataType())) {
UUID owner = container.get(toolStats.itemOwner, new UUIDDataType()); UUID owner = container.get(toolStats.itemOwner, new UUIDDataType());
String ownerName = null; String ownerName = null;
@@ -247,68 +291,31 @@ public class CommandToolStats implements TabExecutor {
container.set(toolStats.itemOwner, new UUIDDataType(), player.getUniqueId()); container.set(toolStats.itemOwner, new UUIDDataType(), player.getUniqueId());
} }
// show how the item was created based on the previous lore // add the ownership lore
switch (origin) { Component ownerLore = toolStats.itemLore.formatOwner(ownerName, origin, original);
case 0: { if (ownerLore != null) {
lore.add(toolStats.configTools.formatLore("created.created-by", "{player}", ownerName)); lore.add(ownerLore);
break;
} }
case 2: {
lore.add(toolStats.configTools.formatLore("looted.looted-by", "{player}", ownerName));
break;
} }
case 3: {
lore.add(toolStats.configTools.formatLore("traded.traded-by", "{player}", ownerName));
break;
}
case 4: {
lore.add(toolStats.configTools.formatLore("looted.found-by", "{player}", ownerName));
break;
}
case 5: {
lore.add(toolStats.configTools.formatLore("fished.caught-by", "{player}", ownerName));
break;
}
case 6: {
lore.add(toolStats.configTools.formatLore("spawned-in.spawned-by", "{player}", ownerName));
break;
}
}
}
}
if (toolStats.configTools.checkConfig(original.getType(), "created-date")) {
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) { if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) {
Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG); Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG);
if (time != null) { if (time != null) {
String date = toolStats.numberFormat.formatDate(new Date(time)); // add the creation time lore
// show how when the item was created based on the previous lore Component creationTimeLore = toolStats.itemLore.formatCreationTime(time, origin, original);
switch (origin) { if (creationTimeLore != null) {
case 0: { lore.add(creationTimeLore);
lore.add(toolStats.configTools.formatLore("created.created-on", "{date}", date));
break;
}
case 2: {
lore.add(toolStats.configTools.formatLore("looted.looted-on", "{date}", date));
break;
}
case 3: {
lore.add(toolStats.configTools.formatLore("traded.traded-on", "{date}", date));
break;
}
case 4: {
lore.add(toolStats.configTools.formatLore("looted.found-on", "{date}", date));
break;
}
case 5: {
lore.add(toolStats.configTools.formatLore("fished.caught-on", "{date}", date));
break;
}
case 6: {
lore.add(toolStats.configTools.formatLore("spawned-in.spawned-on", "{date}", date));
break;
} }
} }
} }
if (toolStats.config.getBoolean("enabled.flight-time")) {
if (container.has(toolStats.flightTime, PersistentDataType.LONG)) {
Long flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG);
if (flightTime != null) {
Map<String, String> flightTimeFormatted = toolStats.numberFormat.formatTime(flightTime);
Component line = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", flightTimeFormatted);
lore.add(line);
}
} }
} }
if (toolStats.configTools.checkConfig(original.getType(), "player-kills")) { if (toolStats.configTools.checkConfig(original.getType(), "player-kills")) {
@@ -396,80 +403,603 @@ public class CommandToolStats implements TabExecutor {
* @param tokenType The token type. * @param tokenType The token type.
*/ */
private void giveToken(Player target, String tokenType, int amount) { private void giveToken(Player target, String tokenType, int amount) {
switch (tokenType) { ItemStack token = toolStats.tokenData.createToken(tokenType);
case "crops-mined": { token.setAmount(amount);
ItemStack itemStack = toolStats.tokenItems.cropsMined(); target.getInventory().addItem(token);
itemStack.setAmount(amount); }
target.getInventory().addItem(itemStack);
/**
* Handle edit subcommand.
*
* @param stat The stat to edit.
* @param userValue The value the user entered.
* @param player The player using the command.
*/
private void handleEdit(String stat, Object userValue, Player player) {
ItemStack editedItem = player.getInventory().getItemInMainHand().clone();
if (!toolStats.itemChecker.isValidItem(editedItem.getType())) {
player.sendMessage(Component.text("This is not a valid item.", NamedTextColor.RED));
return;
}
ItemMeta editedItemMeta = editedItem.getItemMeta();
PersistentDataContainer container = editedItemMeta.getPersistentDataContainer();
switch (stat) {
case "crops-harvested": {
if (!toolStats.config.getBoolean("enabled.crops-harvested")) {
player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
return;
}
if (container.has(toolStats.cropsHarvested)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Integer statValue = container.get(toolStats.cropsHarvested, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
int difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateCropsMined(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "blocks-mined": { case "blocks-mined": {
ItemStack itemStack = toolStats.tokenItems.blocksMined(); if (!toolStats.configTools.checkConfig(editedItem.getType(), "blocks-mined")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.blocksMined)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Integer statValue = container.get(toolStats.blocksMined, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
int difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateBlocksMined(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "damage-taken": { case "damage-taken": {
ItemStack itemStack = toolStats.tokenItems.damageTaken(); if (!toolStats.config.getBoolean("enabled.armor-damage")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.armorDamage)) {
double value;
try {
value = Double.parseDouble((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Double statValue = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
double difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateArmorDamage(editedItem, difference, false);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "damage-done": { case "damage-done": {
ItemStack itemStack = toolStats.tokenItems.damageDone(); if (!toolStats.configTools.checkConfig(editedItem.getType(), "damage-done")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.damageDone)) {
double value;
try {
value = Double.parseDouble((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Double statValue = container.get(toolStats.damageDone, PersistentDataType.DOUBLE);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
double difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateWeaponDamage(editedItem, difference, false);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "mob-kills": { case "mob-kills": {
ItemStack itemStack = toolStats.tokenItems.mobKills(); if (!toolStats.configTools.checkConfig(editedItem.getType(), "mob-kills")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.mobKills)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Integer statValue = container.get(toolStats.mobKills, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
int difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateMobKills(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "player-kills": { case "player-kills": {
ItemStack itemStack = toolStats.tokenItems.playerKills(); if (!toolStats.configTools.checkConfig(editedItem.getType(), "player-kills")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.playerKills)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Integer statValue = container.get(toolStats.playerKills, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
int difference = value - statValue;
editedItemMeta = toolStats.itemLore.updatePlayerKills(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "arrows-shot": { case "arrows-shot": {
ItemStack itemStack = toolStats.tokenItems.arrowsShot(); if (!toolStats.config.getBoolean("enabled.arrows-shot")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.arrowsShot)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Integer statValue = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
int difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateArrowsShot(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "sheep-sheared": { case "sheep-sheared": {
ItemStack itemStack = toolStats.tokenItems.sheepSheared(); if (!toolStats.config.getBoolean("enabled.sheep-sheared")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.sheepSheared)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Integer statValue = container.get(toolStats.sheepSheared, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
int difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateSheepSheared(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "flight-time": { case "flight-time": {
ItemStack itemStack = toolStats.tokenItems.flightTime(); if (!toolStats.config.getBoolean("enabled.flight-time")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.flightTime)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Long statValue = container.get(toolStats.flightTime, PersistentDataType.LONG);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
long difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateFlightTime(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "fish-caught": { case "fight-caught": {
ItemStack itemStack = toolStats.tokenItems.fishCaught(); if (!toolStats.config.getBoolean("enabled.fight-caught")) {
itemStack.setAmount(amount); player.sendMessage(Component.text("This stat is disabled.", NamedTextColor.RED));
target.getInventory().addItem(itemStack); return;
}
if (container.has(toolStats.fishCaught)) {
int value;
try {
value = Integer.parseInt((String) userValue);
} catch (NumberFormatException exception) {
player.sendMessage(Component.text("That is not a valid number.", NamedTextColor.RED));
return;
}
if (value < 0) {
player.sendMessage(Component.text("Number must be positive.", NamedTextColor.RED));
return;
}
Integer statValue = container.get(toolStats.fishCaught, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
int difference = value - statValue;
editedItemMeta = toolStats.itemLore.updateFishCaught(editedItem, difference);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "reset": { default: {
ItemStack itemStack = toolStats.tokenItems.resetToken(); player.sendMessage(Component.text("That is not a valid stat to update.", NamedTextColor.RED));
itemStack.setAmount(amount); return;
target.getInventory().addItem(itemStack); }
}
editedItem.setItemMeta(editedItemMeta);
player.getInventory().setItemInMainHand(editedItem);
player.sendMessage(Component.text("Updated stat " + stat + " for held item!", NamedTextColor.GREEN));
}
/**
* Handle remove subcommand.
*
* @param stat The stat to remove.
* @param player The player using the command.
*/
private void handleRemove(String stat, Player player) {
ItemStack editedItem = player.getInventory().getItemInMainHand().clone();
if (!toolStats.itemChecker.isValidItem(editedItem.getType())) {
player.sendMessage(Component.text("This is not a valid item.", NamedTextColor.RED));
return;
}
ItemMeta editedItemMeta = editedItem.getItemMeta();
PersistentDataContainer container = editedItemMeta.getPersistentDataContainer();
switch (stat) {
case "crops-harvested": {
if (container.has(toolStats.cropsHarvested)) {
Integer statValue = container.get(toolStats.cropsHarvested, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.cropsHarvested);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "crops-mined");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("crops-harvested", "{crops}", toolStats.numberFormat.formatInt(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "remove": { case "blocks-mined": {
ItemStack itemStack = toolStats.tokenItems.removeToken(); if (container.has(toolStats.blocksMined)) {
itemStack.setAmount(amount); Integer statValue = container.get(toolStats.blocksMined, PersistentDataType.INTEGER);
target.getInventory().addItem(itemStack); if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.blocksMined);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "blocks-mined");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("blocks-mined", "{blocks}", toolStats.numberFormat.formatInt(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break; break;
} }
case "damage-taken": {
if (container.has(toolStats.armorDamage)) {
Double statValue = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
} }
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.armorDamage);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "damage-taken");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("damage-taken", "{damage}", toolStats.numberFormat.formatDouble(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break;
}
case "damage-done": {
if (container.has(toolStats.damageDone)) {
Double statValue = container.get(toolStats.damageDone, PersistentDataType.DOUBLE);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.damageDone);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "damage-done");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("damage-done", "{damage}", toolStats.numberFormat.formatDouble(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break;
}
case "mob-kills": {
if (container.has(toolStats.mobKills)) {
Integer statValue = container.get(toolStats.mobKills, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.mobKills);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "mob-kills");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("kills.mob", "{kills}", toolStats.numberFormat.formatInt(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break;
}
case "player-kills": {
if (container.has(toolStats.playerKills)) {
Integer statValue = container.get(toolStats.playerKills, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.playerKills);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "player-kills");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("kills.player", "{kills}", toolStats.numberFormat.formatInt(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break;
}
case "sheep-sheared": {
if (container.has(toolStats.sheepSheared)) {
Integer statValue = container.get(toolStats.sheepSheared, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.sheepSheared);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "sheep-sheared");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", toolStats.numberFormat.formatInt(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break;
}
case "flight-time": {
if (container.has(toolStats.flightTime)) {
Long statValue = container.get(toolStats.flightTime, PersistentDataType.LONG);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.flightTime);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "flight-time");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Map<String, String> timeFormatted = toolStats.numberFormat.formatTime(statValue);
Component oldLine = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", timeFormatted);
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break;
}
case "fight-caught": {
if (container.has(toolStats.fishCaught)) {
Integer statValue = container.get(toolStats.fishCaught, PersistentDataType.INTEGER);
if (statValue == null) {
player.sendMessage(Component.text("Unable to get stat from item.", NamedTextColor.RED));
return;
}
String tokens = container.get(toolStats.tokenApplied, PersistentDataType.STRING);
if (tokens == null) {
player.sendMessage(Component.text("Unable to get tokens from item.", NamedTextColor.RED));
return;
}
container.remove(toolStats.fishCaught);
List<String> newTokens = toolStats.itemChecker.removeToken(tokens, "fight-caught");
if (newTokens.isEmpty()) {
container.remove(toolStats.tokenApplied);
} else {
container.set(toolStats.tokenApplied, PersistentDataType.STRING, String.join(",", newTokens));
}
Component oldLine = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", toolStats.numberFormat.formatInt(statValue));
List<Component> newLore = toolStats.itemLore.removeLore(editedItemMeta.lore(), oldLine);
editedItemMeta.lore(newLore);
} else {
player.sendMessage(Component.text("This item does not have that stat.", NamedTextColor.RED));
}
break;
}
default: {
player.sendMessage(Component.text("That is not a valid stat to update.", NamedTextColor.RED));
return;
}
}
editedItem.setItemMeta(editedItemMeta);
player.getInventory().setItemInMainHand(editedItem);
player.sendMessage(Component.text("Removed stat " + stat + " for held item!", NamedTextColor.GREEN));
} }
@Nullable @Nullable
@@ -486,14 +1016,40 @@ public class CommandToolStats implements TabExecutor {
if (sender.hasPermission("toolstats.givetokens")) { if (sender.hasPermission("toolstats.givetokens")) {
suggestions.add("givetokens"); suggestions.add("givetokens");
} }
if (sender.hasPermission("toolstats.edit")) {
suggestions.add("edit");
}
if (sender.hasPermission("toolstats.remove")) {
suggestions.add("remove");
}
if (sender.hasPermission("toolstats.purge")) {
suggestions.add("purge");
}
return suggestions.isEmpty() ? null : suggestions; return suggestions.isEmpty() ? null : suggestions;
} }
if (args.length == 2 && args[0].equalsIgnoreCase("reset") && sender.hasPermission("toolstats.reset.confirm")) { if (args.length == 2 && args[0].equalsIgnoreCase("reset") && sender.hasPermission("toolstats.reset.confirm")) {
return Collections.singletonList("confirm"); return Collections.singletonList("confirm");
} }
if (args.length == 2 && args[0].equalsIgnoreCase("purge") && sender.hasPermission("toolstats.purge.confirm")) {
return Collections.singletonList("confirm");
}
if (args.length == 2 && args[0].equalsIgnoreCase("edit") && sender.hasPermission("toolstats.edit")) {
// yes I am lazy
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.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")) { if (args.length == 3 && args[0].equalsIgnoreCase("givetokens") && sender.hasPermission("toolstats.givetokens")) {
return toolStats.tokenCrafting.getTokenTypes(); return toolStats.tokenData.getTokenTypes();
} }
return null; return null;

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 net.kyori.adventure.text.Component;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@@ -57,7 +56,6 @@ public class AnvilEvent implements Listener {
} }
Material firstSlotMaterial = firstSlot.getType(); Material firstSlotMaterial = firstSlot.getType();
Material secondSlotMaterial = secondSlot.getType();
// make sure the first item is a valid item // make sure the first item is a valid item
if (!toolStats.itemChecker.isValidItem(firstSlotMaterial)) { if (!toolStats.itemChecker.isValidItem(firstSlotMaterial)) {
@@ -67,7 +65,7 @@ public class AnvilEvent implements Listener {
PersistentDataContainer secondSlotContainer = secondSlot.getItemMeta().getPersistentDataContainer(); PersistentDataContainer secondSlotContainer = secondSlot.getItemMeta().getPersistentDataContainer();
// make sure the 2nd item is one of ours // 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; return;
} }
@@ -91,7 +89,9 @@ public class AnvilEvent implements Listener {
} }
if (tokenType.equalsIgnoreCase("remove")) { if (tokenType.equalsIgnoreCase("remove")) {
remove(event, clone); ItemStack removedStats = toolStats.itemLore.removeAll(clone, false);
event.setResult(removedStats);
event.getView().setRepairCost(toolStats.itemChecker.getCost("remove"));
return; return;
} }
@@ -123,7 +123,15 @@ public class AnvilEvent implements Listener {
addToken(event, tokenType, "mob-kills", clone); addToken(event, tokenType, "mob-kills", clone);
return; return;
} }
if (tokenType.equalsIgnoreCase("damage-done")) {
addToken(event, tokenType, "damage-done", clone);
return;
} }
}
return;
}
if (toolStats.itemChecker.canGlide(clone)) {
addToken(event, tokenType, "flight-time", clone);
return; return;
} }
if (toolStats.itemChecker.isArmor(firstSlotMaterial)) { if (toolStats.itemChecker.isArmor(firstSlotMaterial)) {
@@ -164,10 +172,6 @@ public class AnvilEvent implements Listener {
} }
return; return;
} }
if (firstSlotMaterial == Material.ELYTRA) {
addToken(event, tokenType, "flight-time", clone);
return;
}
if (firstSlotMaterial == Material.FISHING_ROD) { if (firstSlotMaterial == Material.FISHING_ROD) {
addToken(event, tokenType, "fish-caught", clone); addToken(event, tokenType, "fish-caught", clone);
} }
@@ -391,155 +395,4 @@ public class AnvilEvent implements Listener {
event.setResult(finalItem); event.setResult(finalItem);
event.getView().setRepairCost(toolStats.itemChecker.getCost("reset")); event.getView().setRepairCost(toolStats.itemChecker.getCost("reset"));
} }
/**
* Remove all stats from an item.
*
* @param event The PrepareAnvilEvent event.
* @param inputItem The input item to remove stats from.
*/
private void remove(PrepareAnvilEvent event, ItemStack inputItem) {
ItemStack finalItem = inputItem.clone();
ItemMeta meta = finalItem.getItemMeta();
PersistentDataContainer container = meta.getPersistentDataContainer();
// remove the applied tokens
if (container.has(toolStats.tokenApplied)) {
container.remove(toolStats.tokenApplied);
}
if (container.has(toolStats.playerKills)) {
Integer playerKills = container.get(toolStats.playerKills, PersistentDataType.INTEGER);
if (playerKills == null) {
return;
}
container.remove(toolStats.playerKills);
String playerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
Component lineToRemove = toolStats.configTools.formatLore("kills.player", "{kills}", playerKillsFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.mobKills)) {
Integer mobKills = container.get(toolStats.mobKills, PersistentDataType.INTEGER);
if (mobKills == null) {
return;
}
container.remove(toolStats.mobKills);
String mobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
Component lineToRemove = toolStats.configTools.formatLore("kills.mob", "{kills}", mobKillsFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.blocksMined)) {
Integer blocksMined = container.get(toolStats.blocksMined, PersistentDataType.INTEGER);
if (blocksMined == null) {
return;
}
container.remove(toolStats.blocksMined);
String blocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined);
Component lineToRemove = toolStats.configTools.formatLore("blocks-mined", "{blocks}", blocksMinedFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.cropsHarvested)) {
Integer cropsHarvested = container.get(toolStats.playerKills, PersistentDataType.INTEGER);
if (cropsHarvested == null) {
return;
}
container.remove(toolStats.cropsHarvested);
String cropsHarvestedFormatted = toolStats.numberFormat.formatInt(cropsHarvested);
Component lineToRemove = toolStats.configTools.formatLore("crops-harvested", "{crops}", cropsHarvestedFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.fishCaught)) {
Integer fishCaught = container.get(toolStats.fishCaught, PersistentDataType.INTEGER);
if (fishCaught == null) {
return;
}
container.remove(toolStats.fishCaught);
String fishCaughtFormatted = toolStats.numberFormat.formatInt(fishCaught);
Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", fishCaughtFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.sheepSheared)) {
Integer sheepSheared = container.get(toolStats.sheepSheared, PersistentDataType.INTEGER);
if (sheepSheared == null) {
return;
}
container.remove(toolStats.sheepSheared);
String sheepShearedFormatted = toolStats.numberFormat.formatInt(sheepSheared);
Component lineToRemove = toolStats.configTools.formatLore("sheep.sheared", "{sheep}", sheepShearedFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.armorDamage)) {
Double armorDamage = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE);
if (armorDamage == null) {
return;
}
container.remove(toolStats.armorDamage);
String armorDamageFormatted = toolStats.numberFormat.formatDouble(armorDamage);
Component lineToRemove = toolStats.configTools.formatLore("damage-taken", "{damage}", armorDamageFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.damageDone)) {
Double damageDone = container.get(toolStats.damageDone, PersistentDataType.DOUBLE);
if (damageDone == null) {
return;
}
container.remove(toolStats.damageDone);
String damageDoneFormatted = toolStats.numberFormat.formatDouble(damageDone);
Component lineToRemove = toolStats.configTools.formatLore("damage-done", "{damage}", damageDoneFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.arrowsShot)) {
Integer arrowsShot = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER);
if (arrowsShot == null) {
return;
}
container.remove(toolStats.arrowsShot);
String arrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot);
Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", arrowsShotFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
if (container.has(toolStats.flightTime)) {
Long flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG);
if (flightTime == null) {
return;
}
container.remove(toolStats.flightTime);
String flightTimeFormatted = toolStats.numberFormat.formatDouble(flightTime);
Component lineToRemove = toolStats.configTools.formatLore("flight-time", "{time}", flightTimeFormatted);
meta.lore(toolStats.itemLore.removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
event.setResult(finalItem);
event.getView().setRepairCost(toolStats.itemChecker.getCost("remove"));
}
} }

View File

@@ -48,7 +48,7 @@ public class BlockBreak implements Listener {
return; return;
} }
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
PlayerInventory inventory = player.getInventory(); PlayerInventory inventory = player.getInventory();

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
@@ -50,7 +50,7 @@ public class CraftItem implements Listener {
return; return;
} }
Player player = (Player) event.getWhoClicked(); Player player = (Player) event.getWhoClicked();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
ItemStack craftedItem = event.getCurrentItem(); ItemStack craftedItem = event.getCurrentItem();
@@ -116,12 +116,16 @@ public class CraftItem implements Listener {
ItemStack newItem = itemStack.clone(); ItemStack newItem = itemStack.clone();
ItemMeta meta = newItem.getItemMeta(); ItemMeta meta = newItem.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(itemStack + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", itemStack);
return null; return null;
} }
// get the current time // get the current time
long timeCreated = System.currentTimeMillis(); long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated); Date finalDate;
if (toolStats.config.getBoolean("normalize-time-creation")) {
finalDate = toolStats.numberFormat.normalizeTime(timeCreated);
timeCreated = finalDate.getTime();
}
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
// if the item already has the tag // if the item already has the tag
@@ -139,29 +143,20 @@ public class CraftItem implements Listener {
} }
// if creation date is enabled, add it // if creation date is enabled, add it
if (toolStats.configTools.checkConfig(itemStack.getType(), "created-date")) { Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 0, newItem);
if (creationDate != null) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated); container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.originType, PersistentDataType.INTEGER, 0); container.set(toolStats.originType, PersistentDataType.INTEGER, 0);
lore.add(creationDate);
String date = toolStats.numberFormat.formatDate(finalDate);
Component newLine = toolStats.configTools.formatLore("created.created-on", "{date}", date);
if (newLine == null) {
return null;
}
lore.add(newLine);
meta.lore(lore); meta.lore(lore);
} }
// if creation owner is enabled, add it // if ownership is enabled, add it
if (toolStats.configTools.checkConfig(itemStack.getType(), "created-by")) { Component itemOwner = toolStats.itemLore.formatOwner(owner.getName(), 0, newItem);
if (itemOwner != null) {
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId()); container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 0); container.set(toolStats.originType, PersistentDataType.INTEGER, 0);
lore.add(itemOwner);
Component newLine = toolStats.configTools.formatLore("created.created-by", "{player}", owner.getName());
if (newLine == null) {
return null;
}
lore.add(newLine);
meta.lore(lore); meta.lore(lore);
} }

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -30,6 +30,7 @@ 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.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -82,12 +83,16 @@ public class CreativeEvent implements Listener {
ItemStack newSpawnedItem = itemStack.clone(); ItemStack newSpawnedItem = itemStack.clone();
ItemMeta meta = newSpawnedItem.getItemMeta(); ItemMeta meta = newSpawnedItem.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(itemStack + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", itemStack);
return null; return null;
} }
// get the current time // get the current time
long timeCreated = System.currentTimeMillis(); long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated); Date finalDate;
if (toolStats.config.getBoolean("normalize-time-creation")) {
finalDate = toolStats.numberFormat.normalizeTime(timeCreated);
timeCreated = finalDate.getTime();
}
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
// if the item already has the tag // if the item already has the tag
@@ -96,22 +101,38 @@ public class CreativeEvent implements Listener {
return null; return null;
} }
// get the current lore the item
List<Component> lore;
if (meta.hasLore()) {
lore = meta.lore();
} else {
lore = new ArrayList<>();
}
// if creation date is enabled, add it
Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 6, newSpawnedItem);
if (creationDate != null) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.originType, PersistentDataType.INTEGER, 6);
lore.add(creationDate);
meta.lore(lore);
}
// if ownership is enabled, add it
Component itemOwner = toolStats.itemLore.formatOwner(owner.getName(), 6, newSpawnedItem);
if (itemOwner != null) {
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 6);
lore.add(itemOwner);
meta.lore(lore);
}
// if hash is enabled, add it // if hash is enabled, add it
if (toolStats.config.getBoolean("generate-hash-for-items")) { if (toolStats.config.getBoolean("generate-hash-for-items")) {
String hash = toolStats.hashMaker.makeHash(newSpawnedItem.getType(), owner.getUniqueId(), timeCreated); String hash = toolStats.hashMaker.makeHash(newSpawnedItem.getType(), owner.getUniqueId(), timeCreated);
container.set(toolStats.hash, PersistentDataType.STRING, hash); container.set(toolStats.hash, PersistentDataType.STRING, hash);
} }
// if spawned in is enabled, add it
if (toolStats.configTools.checkConfig(newSpawnedItem.getType(), "spawned-in")) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 6);
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
}
newSpawnedItem.setItemMeta(meta); newSpawnedItem.setItemMeta(meta);
return newSpawnedItem; return newSpawnedItem;
} }

View File

@@ -156,7 +156,7 @@ public class EntityDamage implements Listener {
// player is taking damage // player is taking damage
if (mobBeingAttacked instanceof Player playerTakingDamage) { if (mobBeingAttacked instanceof Player playerTakingDamage) {
if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) { if (playerTakingDamage.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
updateArmorDamage(playerTakingDamage.getInventory(), event.getFinalDamage()); updateArmorDamage(playerTakingDamage.getInventory(), event.getFinalDamage());

View File

@@ -30,6 +30,8 @@ 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.Date;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@@ -84,19 +86,43 @@ public class EntityDeath implements Listener {
return null; return null;
} }
if (!toolStats.config.getBoolean("enabled.dropped-by")) { long timeCreated = System.currentTimeMillis();
return null; Date finalDate;
if (toolStats.config.getBoolean("normalize-time-creation")) {
finalDate = toolStats.numberFormat.normalizeTime(timeCreated);
timeCreated = finalDate.getTime();
} }
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(toolStats.originType, PersistentDataType.INTEGER, 1);
String mobName = toolStats.config.getString("messages.mob." + entity.getType()); String mobName = toolStats.config.getString("messages.mob." + entity.getType());
if (mobName == null) { if (mobName == null) {
mobName = entity.getName(); mobName = entity.getName();
} }
Component newLine = toolStats.configTools.formatLore("dropped-by", "{name}", mobName);
List<Component> newLore = toolStats.itemLore.addItemLore(meta, newLine); List<Component> lore;
meta.lore(newLore); if (meta.hasLore()) {
lore = meta.lore();
} else {
lore = new ArrayList<>();
}
// if creation date is enabled, add it
Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 1, newItem);
if (creationDate != null) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.originType, PersistentDataType.INTEGER, 1);
lore.add(creationDate);
meta.lore(lore);
}
if (toolStats.config.getBoolean("enabled.dropped-by")) {
container.set(toolStats.originType, PersistentDataType.INTEGER, 1);
container.set(toolStats.droppedBy, PersistentDataType.STRING, mobName);
Component droppedBy = toolStats.configTools.formatLore("dropped-by", "{name}", mobName);
lore.add(droppedBy);
}
meta.lore(lore);
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;
} }

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@@ -36,6 +36,7 @@ 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.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -99,29 +100,49 @@ public class GenerateLoot implements Listener {
return null; return null;
} }
long timeCreated = System.currentTimeMillis(); long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated); Date finalDate;
PersistentDataContainer container = meta.getPersistentDataContainer(); if (toolStats.config.getBoolean("normalize-time-creation")) {
finalDate = toolStats.numberFormat.normalizeTime(timeCreated);
if (!toolStats.configTools.checkConfig(newItem.getType(), "looted-tag")) { timeCreated = finalDate.getTime();
return null;
} }
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.itemOwner, PersistentDataType.LONG)) { if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.itemOwner, PersistentDataType.LONG)) {
return null; return null;
} }
// only make the hash if it's enabled // get the current lore the item
List<Component> lore;
if (meta.hasLore()) {
lore = meta.lore();
} else {
lore = new ArrayList<>();
}
// if creation date is enabled, add it
Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 2, newItem);
if (creationDate != null) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.originType, PersistentDataType.INTEGER, 2);
lore.add(creationDate);
meta.lore(lore);
}
// if ownership is enabled, add it
Component itemOwner = toolStats.itemLore.formatOwner(owner.getName(), 2, newItem);
if (itemOwner != null) {
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 2);
lore.add(itemOwner);
meta.lore(lore);
}
// if hash is enabled, add it
if (toolStats.config.getBoolean("generate-hash-for-items")) { if (toolStats.config.getBoolean("generate-hash-for-items")) {
String hash = toolStats.hashMaker.makeHash(newItem.getType(), owner.getUniqueId(), timeCreated); String hash = toolStats.hashMaker.makeHash(newItem.getType(), owner.getUniqueId(), timeCreated);
container.set(toolStats.hash, PersistentDataType.STRING, hash); container.set(toolStats.hash, PersistentDataType.STRING, hash);
} }
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 2);
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;
} }

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.entity.Player; 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;

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
@@ -35,6 +35,7 @@ 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.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -53,7 +54,7 @@ public class PickupItem implements Listener {
} }
Entity entity = event.getEntity(); Entity entity = event.getEntity();
if (entity instanceof Player player) { if (entity instanceof Player player) {
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
Item item = event.getItem(); Item item = event.getItem();
@@ -90,7 +91,11 @@ public class PickupItem implements Listener {
return null; return null;
} }
long timeCreated = System.currentTimeMillis(); long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated); Date finalDate;
if (toolStats.config.getBoolean("normalize-time-creation")) {
finalDate = toolStats.numberFormat.normalizeTime(timeCreated);
timeCreated = finalDate.getTime();
}
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
if (!toolStats.config.getBoolean("enabled.elytra-tag")) { if (!toolStats.config.getBoolean("enabled.elytra-tag")) {
@@ -103,13 +108,35 @@ public class PickupItem implements Listener {
container.set(toolStats.hash, PersistentDataType.STRING, hash); container.set(toolStats.hash, PersistentDataType.STRING, hash);
} }
// get the current lore the item
List<Component> lore;
if (meta.hasLore()) {
lore = meta.lore();
} else {
lore = new ArrayList<>();
}
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated); container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId()); container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 4); container.set(toolStats.originType, PersistentDataType.INTEGER, 4);
container.remove(toolStats.newElytra); container.remove(toolStats.newElytra);
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate); Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 4, finalItem);
meta.lore(newLore); if (creationDate != null) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.originType, PersistentDataType.INTEGER, 4);
lore.add(creationDate);
meta.lore(lore);
}
Component itemOwner = toolStats.itemLore.formatOwner(owner.getName(), 4, finalItem);
if (itemOwner != null) {
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 4);
lore.add(itemOwner);
meta.lore(lore);
}
finalItem.setItemMeta(meta); finalItem.setItemMeta(meta);
return finalItem; return finalItem;
} }

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
@@ -34,6 +34,7 @@ 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.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -56,7 +57,7 @@ public class PlayerFish implements Listener {
} }
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
@@ -88,7 +89,7 @@ public class PlayerFish implements Listener {
ItemStack caughtItem = ((Item) event.getCaught()).getItemStack(); ItemStack caughtItem = ((Item) event.getCaught()).getItemStack();
Item caughtItemEntity = (Item) event.getCaught(); Item caughtItemEntity = (Item) event.getCaught();
if (toolStats.itemChecker.isValidItem(caughtItem.getType())) { if (toolStats.itemChecker.isValidItem(caughtItem.getType())) {
ItemStack newItem = addNewLore(caughtItem, player); ItemStack newItem = addFishedOrigin(caughtItem, player);
if (newItem != null) { if (newItem != null) {
caughtItemEntity.setItemStack(newItem); caughtItemEntity.setItemStack(newItem);
} }
@@ -102,36 +103,56 @@ public class PlayerFish implements Listener {
* @param owner The player who caught it. * @param owner The player who caught it.
* @return A copy of the new item with lore. * @return A copy of the new item with lore.
*/ */
private ItemStack addNewLore(ItemStack originalItem, Player owner) { private ItemStack addFishedOrigin(ItemStack originalItem, Player owner) {
ItemStack newItem = originalItem.clone(); ItemStack newItem = originalItem.clone();
ItemMeta meta = originalItem.getItemMeta(); ItemMeta meta = originalItem.getItemMeta();
if (meta == null) { if (meta == null) {
return null; return null;
} }
long timeCreated = System.currentTimeMillis(); long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated); Date finalDate;
PersistentDataContainer container = meta.getPersistentDataContainer(); if (toolStats.config.getBoolean("normalize-time-creation")) {
finalDate = toolStats.numberFormat.normalizeTime(timeCreated);
if (!toolStats.configTools.checkConfig(newItem.getType(), "fished-tag")) { timeCreated = finalDate.getTime();
return null;
} }
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.itemOwner, PersistentDataType.LONG)) { if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.itemOwner, PersistentDataType.LONG)) {
return null; return null;
} }
// only make the hash if it's enabled // get the current lore the item
List<Component> lore;
if (meta.hasLore()) {
lore = meta.lore();
} else {
lore = new ArrayList<>();
}
// if creation date is enabled, add it
Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 5, newItem);
if (creationDate != null) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.originType, PersistentDataType.INTEGER, 5);
lore.add(creationDate);
meta.lore(lore);
}
// if ownership is enabled, add it
Component itemOwner = toolStats.itemLore.formatOwner(owner.getName(), 5, newItem);
if (itemOwner != null) {
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 5);
lore.add(itemOwner);
meta.lore(lore);
}
// if hash is enabled, add it
if (toolStats.config.getBoolean("generate-hash-for-items")) { if (toolStats.config.getBoolean("generate-hash-for-items")) {
String hash = toolStats.hashMaker.makeHash(newItem.getType(), owner.getUniqueId(), timeCreated); String hash = toolStats.hashMaker.makeHash(newItem.getType(), owner.getUniqueId(), timeCreated);
container.set(toolStats.hash, PersistentDataType.STRING, hash); container.set(toolStats.hash, PersistentDataType.STRING, hash);
} }
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 5);
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;
} }

View File

@@ -58,7 +58,7 @@ public class PlayerInteract implements Listener {
} }
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
// store when a player opens a chest // store when a player opens a chest
@@ -72,7 +72,7 @@ public class PlayerInteract implements Listener {
public void onInteract(PlayerInteractEntityEvent event) { public void onInteract(PlayerInteractEntityEvent event) {
Entity clicked = event.getRightClicked(); Entity clicked = event.getRightClicked();
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
// store when a player opens a minecart // store when a player opens a minecart

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.entity.Player; 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;

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.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@@ -53,15 +52,23 @@ public class PlayerMove implements Listener {
// player is not flying // player is not flying
if (playerStartFlight.containsKey(player)) { if (playerStartFlight.containsKey(player)) {
PlayerInventory inventory = player.getInventory(); PlayerInventory inventory = player.getInventory();
ItemStack chest = inventory.getChestplate(); // copy their current armor
// make sure the player is wearing an elytra ItemStack[] armor = inventory.getArmorContents().clone();
if (chest != null && chest.getType() == Material.ELYTRA) { for (ItemStack armorPiece : armor) {
// skip missing slots
if (armorPiece == null) {
continue;
}
// if the armor piece can glide, track the flight time
if (toolStats.itemChecker.canGlide(armorPiece)) {
long duration = (System.currentTimeMillis() - playerStartFlight.get(player)); long duration = (System.currentTimeMillis() - playerStartFlight.get(player));
ItemMeta newItem = toolStats.itemLore.updateFlightTime(chest, duration); ItemMeta newMeta = toolStats.itemLore.updateFlightTime(armorPiece, duration);
if (newItem != null) { if (newMeta != null) {
inventory.getChestplate().setItemMeta(newItem); armorPiece.setItemMeta(newMeta);
} }
} }
}
inventory.setArmorContents(armor);
playerStartFlight.remove(player); playerStartFlight.remove(player);
} }
} }

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.Material;
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;
@@ -40,7 +39,7 @@ public class PrepareCraft implements Listener {
// get the items in the crafting grid // get the items in the crafting grid
ItemStack[] grid = event.getInventory().getMatrix(); ItemStack[] grid = event.getInventory().getMatrix();
for (ItemStack item : grid) { for (ItemStack item : grid) {
if (item == null || item.getType() != Material.PAPER) { if (item == null) {
continue; continue;
} }
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();

View File

@@ -45,7 +45,7 @@ public class SheepShear implements Listener {
return; return;
} }
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }
Entity entity = event.getRightClicked(); Entity entity = event.getRightClicked();

View File

@@ -46,7 +46,7 @@ public class ShootBow implements Listener {
return; return;
} }
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.ADVENTURE) { if (player.getGameMode() == GameMode.CREATIVE && !toolStats.config.getBoolean("allow-creative")) {
return; return;
} }

View File

@@ -17,8 +17,8 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
@@ -35,6 +35,7 @@ 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.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -122,33 +123,54 @@ public class VillagerTrade implements Listener {
ItemStack newItem = oldItem.clone(); ItemStack newItem = oldItem.clone();
ItemMeta meta = newItem.getItemMeta(); ItemMeta meta = newItem.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(newItem + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", newItem);
return null; return null;
} }
long timeCreated = System.currentTimeMillis(); long timeCreated = System.currentTimeMillis();
Date finalDate = new Date(timeCreated); Date finalDate;
if (toolStats.config.getBoolean("normalize-time-creation")) {
finalDate = toolStats.numberFormat.normalizeTime(timeCreated);
timeCreated = finalDate.getTime();
}
PersistentDataContainer container = meta.getPersistentDataContainer(); PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.itemOwner, PersistentDataType.LONG)) { if (container.has(toolStats.timeCreated, PersistentDataType.LONG) || container.has(toolStats.itemOwner, PersistentDataType.LONG)) {
return null; return null;
} }
if (!toolStats.configTools.checkConfig(newItem.getType(), "traded-tag")) { // get the current lore the item
return null; List<Component> lore;
if (meta.hasLore()) {
lore = meta.lore();
} else {
lore = new ArrayList<>();
} }
// only make the hash if it's enabled
// if creation date is enabled, add it
Component creationDate = toolStats.itemLore.formatCreationTime(timeCreated, 3, newItem);
if (creationDate != null) {
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.originType, PersistentDataType.INTEGER, 3);
lore.add(creationDate);
meta.lore(lore);
}
// if ownership is enabled, add it
Component itemOwner = toolStats.itemLore.formatOwner(owner.getName(), 3, newItem);
if (itemOwner != null) {
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 3);
lore.add(itemOwner);
meta.lore(lore);
}
// if hash is enabled, add it
if (toolStats.config.getBoolean("generate-hash-for-items")) { if (toolStats.config.getBoolean("generate-hash-for-items")) {
String hash = toolStats.hashMaker.makeHash(newItem.getType(), owner.getUniqueId(), timeCreated); String hash = toolStats.hashMaker.makeHash(newItem.getType(), owner.getUniqueId(), timeCreated);
container.set(toolStats.hash, PersistentDataType.STRING, hash); container.set(toolStats.hash, PersistentDataType.STRING, hash);
} }
container.set(toolStats.timeCreated, PersistentDataType.LONG, timeCreated);
container.set(toolStats.itemOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 3);
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;
} }

View File

@@ -51,9 +51,9 @@ public class HashMaker {
return hexString.toString(); return hexString.toString();
} catch (NoSuchAlgorithmException exception) { } catch (NoSuchAlgorithmException exception) {
toolStats.logger.warning("Unable to generate hash for " + player + "!"); toolStats.logger.error("Unable to generate hash", exception);
toolStats.logger.warning("Generating a random UUID instead."); toolStats.logger.warn("Unable to generate hash for {}!", player);
exception.printStackTrace(); toolStats.logger.warn("Generating a random UUID instead.");
return java.util.UUID.randomUUID().toString(); return java.util.UUID.randomUUID().toString();
} }
} }

View File

@@ -17,6 +17,7 @@
package lol.hyper.toolstats.tools; package lol.hyper.toolstats.tools;
import io.papermc.paper.datacomponent.DataComponentTypes;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@@ -116,6 +117,22 @@ public class ItemChecker {
return mineItems.contains(itemType); return mineItems.contains(itemType);
} }
/**
* In newer versions of Minecraft, you can make items glide, which works
* like an Elytra.
*
* @param itemStack The item to check.
* @return True/false if the item can glide like an Elytra.
*/
public boolean canGlide(ItemStack itemStack) {
// if it's an elytra, we are good
if (itemStack.getType() == Material.ELYTRA) {
return true;
}
// otherwise if it has the GLIDER data
return itemStack.hasData(DataComponentTypes.GLIDER);
}
/** /**
* Check a given item for a target token. * Check a given item for a target token.
* *

View File

@@ -17,17 +17,17 @@
package lol.hyper.toolstats.tools; package lol.hyper.toolstats.tools;
import lol.hyper.hyperlib.datatypes.UUIDDataType;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; 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.*;
import java.util.List;
import java.util.Map;
public class ItemLore { public class ItemLore {
@@ -70,25 +70,6 @@ public class ItemLore {
return itemLore; return itemLore;
} }
/**
* Add lore to a given item.
*
* @param itemMeta The item's meta.
* @param newLine The new line to add to the lore.
* @return The new item's lore.
*/
public List<Component> addItemLore(ItemMeta itemMeta, Component newLine) {
List<Component> itemLore;
if (itemMeta.hasLore()) {
itemLore = itemMeta.lore();
itemLore.add(newLine);
} else {
itemLore = new ArrayList<>();
itemLore.add(newLine);
}
return itemLore;
}
/** /**
* Remove a given lore from an item. * Remove a given lore from an item.
* *
@@ -97,136 +78,14 @@ public class ItemLore {
* @return The lore with the line removed. * @return The lore with the line removed.
*/ */
public List<Component> removeLore(List<Component> inputLore, Component toRemove) { public List<Component> removeLore(List<Component> inputLore, Component toRemove) {
if (inputLore == null) {
return Collections.emptyList();
}
List<Component> newLore = new ArrayList<>(inputLore); List<Component> newLore = new ArrayList<>(inputLore);
newLore.removeIf(line -> PlainTextComponentSerializer.plainText().serialize(line).equals(PlainTextComponentSerializer.plainText().serialize(toRemove))); newLore.removeIf(line -> PlainTextComponentSerializer.plainText().serialize(line).equals(PlainTextComponentSerializer.plainText().serialize(toRemove)));
return newLore; return newLore;
} }
/**
* Adds new ownership to an item.
*
* @param itemMeta The item meta.
* @param playerName The new owner of item.
* @param formattedDate The date of the ownership.
* @return The item's new lore.
*/
public List<Component> addNewOwner(ItemMeta itemMeta, String playerName, String formattedDate) {
Component dateCreatedLore;
Component itemOwnerLore;
Integer origin = null;
PersistentDataContainer container = itemMeta.getPersistentDataContainer();
if (container.has(toolStats.originType, PersistentDataType.INTEGER)) {
origin = container.get(toolStats.originType, PersistentDataType.INTEGER);
}
// if the origin is broken, don't try to set the lore
if (origin == null) {
toolStats.logger.info("Unable to determine origin for item " + itemMeta.getAsString());
toolStats.logger.info("This IS a bug, please report this to the GitHub.");
return itemMeta.lore();
}
// set the lore based on the origin
switch (origin) {
case 2: {
dateCreatedLore = toolStats.configTools.formatLore("looted.looted-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("looted.looted-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.looted.looted-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.looted.looted-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
break;
}
case 3: {
dateCreatedLore = toolStats.configTools.formatLore("traded.traded-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("traded.traded-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.traded.traded-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.traded.traded-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
break;
}
case 4: {
dateCreatedLore = toolStats.configTools.formatLore("looted.found-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("looted.found-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.looted.found-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.looted.found-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
break;
}
case 5: {
dateCreatedLore = toolStats.configTools.formatLore("fished.caught-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("fished.caught-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.fished.caught-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.fished.caught-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
break;
}
case 6: {
dateCreatedLore = toolStats.configTools.formatLore("spawned-in.spawned-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("spawned-in.spawned-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.spawned-in.spawned-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.spawned-in.spawned-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.lore();
}
break;
}
default: {
toolStats.logger.warning("Origin " + origin + " was found. Data was modified OR something REALLY broke.");
toolStats.logger.warning(itemMeta.getAsString());
return itemMeta.lore();
}
}
List<Component> newLore;
if (itemMeta.hasLore()) {
newLore = itemMeta.lore();
} else {
newLore = new ArrayList<>();
}
newLore.add(dateCreatedLore);
newLore.add(itemOwnerLore);
return newLore;
}
/** /**
* Add x to the crops mined stat. * Add x to the crops mined stat.
* *
@@ -236,7 +95,7 @@ public class ItemLore {
ItemStack clone = playerTool.clone(); ItemStack clone = playerTool.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
// read the current stats from the item // read the current stats from the item
@@ -310,7 +169,7 @@ public class ItemLore {
if (cropsMined == null) { if (cropsMined == null) {
cropsMined = 0; cropsMined = 0;
toolStats.logger.warning(clone + " does not have valid crops-mined set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid crops-mined set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.cropsHarvested, PersistentDataType.INTEGER, cropsMined + add); container.set(toolStats.cropsHarvested, PersistentDataType.INTEGER, cropsMined + add);
@@ -321,7 +180,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -335,7 +194,7 @@ public class ItemLore {
ItemStack clone = playerTool.clone(); ItemStack clone = playerTool.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -409,7 +268,7 @@ public class ItemLore {
if (blocksMined == null) { if (blocksMined == null) {
blocksMined = 0; blocksMined = 0;
toolStats.logger.warning(clone + " does not have valid generic-mined set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid generic-mined set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.blocksMined, PersistentDataType.INTEGER, blocksMined + add); container.set(toolStats.blocksMined, PersistentDataType.INTEGER, blocksMined + add);
@@ -420,7 +279,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -434,7 +293,7 @@ public class ItemLore {
ItemStack clone = playerWeapon.clone(); ItemStack clone = playerWeapon.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -507,7 +366,7 @@ public class ItemLore {
if (playerKills == null) { if (playerKills == null) {
playerKills = 0; playerKills = 0;
toolStats.logger.warning(clone + " does not have valid player-kills set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid player-kills set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.playerKills, PersistentDataType.INTEGER, playerKills + add); container.set(toolStats.playerKills, PersistentDataType.INTEGER, playerKills + add);
@@ -518,7 +377,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -532,7 +391,7 @@ public class ItemLore {
ItemStack clone = playerWeapon.clone(); ItemStack clone = playerWeapon.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -605,7 +464,7 @@ public class ItemLore {
if (mobKills == null) { if (mobKills == null) {
mobKills = 0; mobKills = 0;
toolStats.logger.warning(clone + " does not have valid mob-kills set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid mob-kills set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.mobKills, PersistentDataType.INTEGER, mobKills + add); container.set(toolStats.mobKills, PersistentDataType.INTEGER, mobKills + add);
@@ -616,7 +475,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -638,7 +497,7 @@ public class ItemLore {
ItemStack clone = armorPiece.clone(); ItemStack clone = armorPiece.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -711,7 +570,7 @@ public class ItemLore {
if (damageTaken == null) { if (damageTaken == null) {
damageTaken = 0.0; damageTaken = 0.0;
toolStats.logger.warning(clone + " does not have valid damage-taken set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid damage-taken set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.armorDamage, PersistentDataType.DOUBLE, damageTaken + damage); container.set(toolStats.armorDamage, PersistentDataType.DOUBLE, damageTaken + damage);
@@ -722,7 +581,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -744,7 +603,7 @@ public class ItemLore {
ItemStack clone = weapon.clone(); ItemStack clone = weapon.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -817,7 +676,7 @@ public class ItemLore {
if (damageDone == null) { if (damageDone == null) {
damageDone = 0.0; damageDone = 0.0;
toolStats.logger.warning(clone + " does not have valid damage-done set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid damage-done set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.damageDone, PersistentDataType.DOUBLE, damageDone + damage); container.set(toolStats.damageDone, PersistentDataType.DOUBLE, damageDone + damage);
@@ -828,7 +687,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -842,7 +701,7 @@ public class ItemLore {
ItemStack clone = elytra.clone(); ItemStack clone = elytra.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -925,7 +784,7 @@ public class ItemLore {
if (flightTime == null) { if (flightTime == null) {
flightTime = 0L; flightTime = 0L;
toolStats.logger.warning(flightTime + " does not have valid flight-time set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid flight-time set! Resting to zero. This should NEVER happen.", flightTime);
} }
container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime + duration); container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime + duration);
@@ -944,7 +803,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -958,7 +817,7 @@ public class ItemLore {
ItemStack clone = shears.clone(); ItemStack clone = shears.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -1031,7 +890,7 @@ public class ItemLore {
if (sheepSheared == null) { if (sheepSheared == null) {
sheepSheared = 0; sheepSheared = 0;
toolStats.logger.warning(clone + " does not have valid sheared set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid sheared set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.sheepSheared, PersistentDataType.INTEGER, sheepSheared + add); container.set(toolStats.sheepSheared, PersistentDataType.INTEGER, sheepSheared + add);
@@ -1042,7 +901,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -1056,7 +915,7 @@ public class ItemLore {
ItemStack clone = bow.clone(); ItemStack clone = bow.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -1131,7 +990,7 @@ public class ItemLore {
if (arrowsShot == null) { if (arrowsShot == null) {
arrowsShot = 0; arrowsShot = 0;
toolStats.logger.warning(arrowsShot + " does not have valid arrows-shot set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid arrows-shot set! Resting to zero. This should NEVER happen.", arrowsShot);
} }
container.set(toolStats.arrowsShot, PersistentDataType.INTEGER, arrowsShot + add); container.set(toolStats.arrowsShot, PersistentDataType.INTEGER, arrowsShot + add);
@@ -1142,7 +1001,7 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
@@ -1156,7 +1015,7 @@ public class ItemLore {
ItemStack clone = fishingRod.clone(); ItemStack clone = fishingRod.clone();
ItemMeta meta = clone.getItemMeta(); ItemMeta meta = clone.getItemMeta();
if (meta == null) { if (meta == null) {
toolStats.logger.warning(clone + " does NOT have any meta! Unable to update stats."); toolStats.logger.warn("{} does NOT have any meta! Unable to update stats.", clone);
return null; return null;
} }
@@ -1229,7 +1088,7 @@ public class ItemLore {
if (fishCaught == null) { if (fishCaught == null) {
fishCaught = 0; fishCaught = 0;
toolStats.logger.warning(clone + " does not have valid fish-caught set! Resting to zero. This should NEVER happen."); toolStats.logger.warn("{} does not have valid fish-caught set! Resting to zero. This should NEVER happen.", clone);
} }
container.set(toolStats.fishCaught, PersistentDataType.INTEGER, fishCaught + add); container.set(toolStats.fishCaught, PersistentDataType.INTEGER, fishCaught + add);
@@ -1240,8 +1099,269 @@ public class ItemLore {
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = updateItemLore(meta, oldLine, newLine);
meta.lore(newLore); meta.lore(newLore);
return meta; return meta;
} }
/**
* Format the item owner lore.
*
* @param playerName The player's name who owns the items.
* @param origin The origin type.
* @param item The item.
* @return A component with the lore.
*/
public Component formatOwner(String playerName, int origin, ItemStack item) {
switch (origin) {
case 0: {
if (toolStats.configTools.checkConfig(item.getType(), "crafted-by")) {
return toolStats.configTools.formatLore("crafted.crafted-by", "{player}", playerName);
}
break;
}
case 2: {
if (toolStats.configTools.checkConfig(item.getType(), "looted-by")) {
return toolStats.configTools.formatLore("looted.looted-by", "{player}", playerName);
}
break;
}
case 3: {
if (toolStats.configTools.checkConfig(item.getType(), "traded-by")) {
return toolStats.configTools.formatLore("traded.traded-by", "{player}", playerName);
}
break;
}
case 4: {
if (toolStats.config.getBoolean("enabled.elytra-tag")) {
return toolStats.configTools.formatLore("looted.found-by", "{player}", playerName);
}
break;
}
case 5: {
if (toolStats.configTools.checkConfig(item.getType(), "fished-by")) {
return toolStats.configTools.formatLore("fished.caught-by", "{player}", playerName);
}
break;
}
case 6: {
if (toolStats.configTools.checkConfig(item.getType(), "spawned-in-by")) {
return toolStats.configTools.formatLore("spawned-in.spawned-by", "{player}", playerName);
}
break;
}
}
return null;
}
/**
* Format the item creation time.
*
* @param creationDate When the item was created.
* @param origin The origin type.
* @param item The item.
* @return A component with the lore.
*/
public Component formatCreationTime(long creationDate, int origin, ItemStack item) {
String date = toolStats.numberFormat.formatDate(new Date(creationDate));
switch (origin) {
case 0: {
if (toolStats.configTools.checkConfig(item.getType(), "crafted-on")) {
return toolStats.configTools.formatLore("crafted.crafted-on", "{date}", date);
}
break;
}
case 1: {
if (toolStats.config.getBoolean("enabled.dropped-on")) {
return toolStats.configTools.formatLore("dropped-on", "{date}", date);
}
break;
}
case 2: {
if (toolStats.configTools.checkConfig(item.getType(), "looted-on")) {
return toolStats.configTools.formatLore("looted.looted-on", "{date}", date);
}
break;
}
case 3: {
if (toolStats.configTools.checkConfig(item.getType(), "traded-on")) {
return toolStats.configTools.formatLore("traded.traded-on", "{date}", date);
}
break;
}
case 4: {
if (toolStats.config.getBoolean("enabled.elytra-tag")) {
return toolStats.configTools.formatLore("looted.found-on", "{date}", date);
}
break;
}
case 5: {
if (toolStats.configTools.checkConfig(item.getType(), "fished-on")) {
return toolStats.configTools.formatLore("fished.caught-on", "{date}", date);
}
break;
}
case 6: {
if (toolStats.configTools.checkConfig(item.getType(), "spawned-in-on")) {
return toolStats.configTools.formatLore("spawned-in.spawned-on", "{date}", date);
}
break;
}
}
return null;
}
/**
* Remove all stats, ownership, and creation time from an item.
*
* @param inputItem The input item to remove stats from.
* @param removeMeta Remove ownership and creation time?
*/
public ItemStack removeAll(ItemStack inputItem, boolean removeMeta) {
ItemStack finalItem = inputItem.clone();
ItemMeta meta = finalItem.getItemMeta();
PersistentDataContainer container = meta.getPersistentDataContainer();
// remove the applied tokens
if (container.has(toolStats.tokenApplied)) {
container.remove(toolStats.tokenApplied);
}
if (container.has(toolStats.playerKills)) {
Integer playerKills = container.get(toolStats.playerKills, PersistentDataType.INTEGER);
if (playerKills != null) {
container.remove(toolStats.playerKills);
String playerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
Component lineToRemove = toolStats.configTools.formatLore("kills.player", "{kills}", playerKillsFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.mobKills)) {
Integer mobKills = container.get(toolStats.mobKills, PersistentDataType.INTEGER);
if (mobKills != null) {
container.remove(toolStats.mobKills);
String mobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
Component lineToRemove = toolStats.configTools.formatLore("kills.mob", "{kills}", mobKillsFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.blocksMined)) {
Integer blocksMined = container.get(toolStats.blocksMined, PersistentDataType.INTEGER);
if (blocksMined != null) {
container.remove(toolStats.blocksMined);
String blocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined);
Component lineToRemove = toolStats.configTools.formatLore("blocks-mined", "{blocks}", blocksMinedFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.cropsHarvested)) {
Integer cropsHarvested = container.get(toolStats.playerKills, PersistentDataType.INTEGER);
if (cropsHarvested != null) {
container.remove(toolStats.cropsHarvested);
String cropsHarvestedFormatted = toolStats.numberFormat.formatInt(cropsHarvested);
Component lineToRemove = toolStats.configTools.formatLore("crops-harvested", "{crops}", cropsHarvestedFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.fishCaught)) {
Integer fishCaught = container.get(toolStats.fishCaught, PersistentDataType.INTEGER);
if (fishCaught != null) {
container.remove(toolStats.fishCaught);
String fishCaughtFormatted = toolStats.numberFormat.formatInt(fishCaught);
Component lineToRemove = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", fishCaughtFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.sheepSheared)) {
Integer sheepSheared = container.get(toolStats.sheepSheared, PersistentDataType.INTEGER);
if (sheepSheared != null) {
container.remove(toolStats.sheepSheared);
String sheepShearedFormatted = toolStats.numberFormat.formatInt(sheepSheared);
Component lineToRemove = toolStats.configTools.formatLore("sheep.sheared", "{sheep}", sheepShearedFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.armorDamage)) {
Double armorDamage = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE);
if (armorDamage != null) {
container.remove(toolStats.armorDamage);
String armorDamageFormatted = toolStats.numberFormat.formatDouble(armorDamage);
Component lineToRemove = toolStats.configTools.formatLore("damage-taken", "{damage}", armorDamageFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.damageDone)) {
Double damageDone = container.get(toolStats.damageDone, PersistentDataType.DOUBLE);
if (damageDone != null) {
container.remove(toolStats.damageDone);
String damageDoneFormatted = toolStats.numberFormat.formatDouble(damageDone);
Component lineToRemove = toolStats.configTools.formatLore("damage-done", "{damage}", damageDoneFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.arrowsShot)) {
Integer arrowsShot = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER);
if (arrowsShot != null) {
container.remove(toolStats.arrowsShot);
String arrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot);
Component lineToRemove = toolStats.configTools.formatLore("arrows-shot", "{arrows}", arrowsShotFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (container.has(toolStats.flightTime)) {
Long flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG);
if (flightTime != null) {
container.remove(toolStats.flightTime);
Map<String, String> flightTimeFormatted = toolStats.numberFormat.formatTime(flightTime);
Component lineToRemove = toolStats.configTools.formatLoreMultiplePlaceholders("flight-time", flightTimeFormatted);
meta.lore(removeLore(meta.lore(), lineToRemove));
finalItem.setItemMeta(meta);
}
}
if (removeMeta) {
Integer origin = null;
if (container.has(toolStats.originType)) {
origin = container.get(toolStats.originType, PersistentDataType.INTEGER);
}
if (container.has(toolStats.timeCreated)) {
Long timeCreated = container.get(toolStats.timeCreated, PersistentDataType.LONG);
if (timeCreated != null && origin != null) {
container.remove(toolStats.timeCreated);
Component timeCreatedLore = formatCreationTime(timeCreated, origin, finalItem);
meta.lore(removeLore(meta.lore(), timeCreatedLore));
}
}
if (container.has(toolStats.itemOwner)) {
UUID owner = container.get(toolStats.itemOwner, new UUIDDataType());
if (owner != null && origin != null) {
container.remove(toolStats.itemOwner);
String ownerName = Bukkit.getOfflinePlayer(owner).getName();
if (ownerName != null) {
Component ownerLore = formatOwner(ownerName, origin, finalItem);
meta.lore(removeLore(meta.lore(), ownerLore));
}
}
}
if (origin != null) {
container.remove(toolStats.originType);
}
finalItem.setItemMeta(meta);
}
return finalItem;
}
} }

View File

@@ -22,6 +22,10 @@ import lol.hyper.toolstats.ToolStats;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@@ -35,6 +39,7 @@ public class NumberFormat {
/** /**
* Utility class to format different numbers * Utility class to format different numbers
*
* @param toolStats Plugin instance. * @param toolStats Plugin instance.
*/ */
public NumberFormat(ToolStats toolStats) { public NumberFormat(ToolStats toolStats) {
@@ -48,35 +53,35 @@ public class NumberFormat {
// if these config values are missing, use the default ones // if these config values are missing, use the default ones
if (dateFormat == null) { if (dateFormat == null) {
dateFormat = "M/dd/yyyy"; dateFormat = "M/dd/yyyy";
toolStats.logger.warning("date-format is missing! Using default American English format."); toolStats.logger.warn("date-format is missing! Using default American English format.");
} }
if (decimalSeparator == null) { if (decimalSeparator == null) {
decimalSeparator = "."; decimalSeparator = ".";
toolStats.logger.warning("number-formats.decimal-separator is missing! Using default \".\" instead."); toolStats.logger.warn("number-formats.decimal-separator is missing! Using default \".\" instead.");
} }
if (commaSeparator == null) { if (commaSeparator == null) {
commaSeparator = ","; commaSeparator = ",";
toolStats.logger.warning("number-formats.comma-separator is missing! Using default \",\" instead."); toolStats.logger.warn("number-formats.comma-separator is missing! Using default \",\" instead.");
} }
if (commaFormat == null) { if (commaFormat == null) {
commaFormat = "#,###"; commaFormat = "#,###";
toolStats.logger.warning("number-formats.comma-format is missing! Using default #,### instead."); toolStats.logger.warn("number-formats.comma-format is missing! Using default #,### instead.");
} }
if (decimalFormat == null) { if (decimalFormat == null) {
decimalFormat = "#,##0.00"; decimalFormat = "#,##0.00";
toolStats.logger.warning("number-formats.comma-separator is missing! Using default #,###.00 instead."); toolStats.logger.warn("number-formats.comma-separator is missing! Using default #,###.00 instead.");
} }
// test the date format // test the date format
try { try {
DATE_FORMAT = new SimpleDateFormat(dateFormat, Locale.getDefault()); DATE_FORMAT = new SimpleDateFormat(dateFormat, Locale.getDefault());
} catch (NullPointerException | IllegalArgumentException exception) { } catch (NullPointerException | IllegalArgumentException exception) {
toolStats.logger.warning("date-format is NOT a valid format! Using default American English format."); toolStats.logger.error("Invalid format or missing format", exception);
exception.printStackTrace(); toolStats.logger.warn("date-format is NOT a valid format! Using default American English format.");
DATE_FORMAT = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH); DATE_FORMAT = new SimpleDateFormat("M/dd/yyyy", Locale.ENGLISH);
} }
@@ -90,8 +95,8 @@ public class NumberFormat {
try { try {
COMMA_FORMAT = new DecimalFormat(commaFormat, formatSymbols); COMMA_FORMAT = new DecimalFormat(commaFormat, formatSymbols);
} catch (NullPointerException | IllegalArgumentException exception) { } catch (NullPointerException | IllegalArgumentException exception) {
toolStats.logger.warning("number-formats.comma-format is NOT a valid format! Using default #,### instead."); toolStats.logger.error("Invalid comma or missing format", exception);
exception.printStackTrace(); toolStats.logger.warn("number-formats.comma-format is NOT a valid format! Using default #,### instead.");
COMMA_FORMAT = new DecimalFormat("#,###", formatSymbols); COMMA_FORMAT = new DecimalFormat("#,###", formatSymbols);
} }
@@ -99,8 +104,8 @@ public class NumberFormat {
try { try {
DECIMAL_FORMAT = new DecimalFormat(decimalFormat, formatSymbols); DECIMAL_FORMAT = new DecimalFormat(decimalFormat, formatSymbols);
} catch (NullPointerException | IllegalArgumentException exception) { } catch (NullPointerException | IllegalArgumentException exception) {
toolStats.logger.warning("number-formats.decimal-format is NOT a valid format! Using default #,###.00 instead."); toolStats.logger.error("Invalid decimal or missing format", exception);
exception.printStackTrace(); toolStats.logger.warn("number-formats.decimal-format is NOT a valid format! Using default #,###.00 instead.");
DECIMAL_FORMAT = new DecimalFormat("#,###.00", formatSymbols); DECIMAL_FORMAT = new DecimalFormat("#,###.00", formatSymbols);
} }
} }
@@ -140,8 +145,9 @@ public class NumberFormat {
} }
/** /**
* Returns a human readable form of time in milliseconds. * 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. * E.g. given 3752348000L outputs 1 year, 5 months, 3 days, 14 hours, 12 minutes, 28 seconds.
*
* @param time The time in ms. * @param time The time in ms.
* @return Map with units as keys and time value, e.g. "years" (key) -> 1 (value) * @return Map with units as keys and time value, e.g. "years" (key) -> 1 (value)
*/ */
@@ -193,4 +199,13 @@ public class NumberFormat {
return timeUnits; return timeUnits;
} }
public Date normalizeTime(Long time) {
Instant instant = Instant.ofEpochMilli(time);
ZoneId zone = ZoneId.systemDefault();
LocalDate localDate = instant.atZone(zone).toLocalDate();
ZonedDateTime midnight = localDate.atStartOfDay(zone);
return Date.from(midnight.toInstant());
}
} }

View File

@@ -17,104 +17,110 @@
package lol.hyper.toolstats.tools; package lol.hyper.toolstats.tools;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.CustomModelData;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe; 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.*;
import java.util.HashSet;
import java.util.Set;
public class TokenCrafting { public class TokenData {
private final ToolStats toolStats; private final ToolStats toolStats;
private final Set<ShapedRecipe> recipes = new HashSet<>(); private final Set<ShapedRecipe> recipes = new HashSet<>();
private final ArrayList<String> tokenTypes = new ArrayList<>(); private final ArrayList<String> tokenTypes = new ArrayList<>();
public TokenCrafting(ToolStats toolStats) { public TokenData(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
} }
public void setup() { public void setup() {
NamespacedKey playerKillsKey = new NamespacedKey(toolStats, "player-kills-token"); 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.shape(" P ", "PSP", " P ");
playerKillRecipe.setIngredient('P', Material.PAPER); playerKillRecipe.setIngredient('P', Material.PAPER);
playerKillRecipe.setIngredient('S', Material.WOODEN_SWORD); playerKillRecipe.setIngredient('S', Material.WOODEN_SWORD);
recipes.add(playerKillRecipe); recipes.add(playerKillRecipe);
NamespacedKey mobKillsKey = new NamespacedKey(toolStats, "mob-kills-token"); 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.shape(" P ", "PRP", " P ");
mobKillsRecipe.setIngredient('P', Material.PAPER); mobKillsRecipe.setIngredient('P', Material.PAPER);
mobKillsRecipe.setIngredient('R', Material.ROTTEN_FLESH); mobKillsRecipe.setIngredient('R', Material.ROTTEN_FLESH);
recipes.add(mobKillsRecipe); recipes.add(mobKillsRecipe);
NamespacedKey blocksMinedKey = new NamespacedKey(toolStats, "blocks-mined-token"); 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.shape(" P ", "PSP", " P ");
blocksMinedRecipe.setIngredient('P', Material.PAPER); blocksMinedRecipe.setIngredient('P', Material.PAPER);
blocksMinedRecipe.setIngredient('S', Material.WOODEN_PICKAXE); blocksMinedRecipe.setIngredient('S', Material.WOODEN_PICKAXE);
recipes.add(blocksMinedRecipe); recipes.add(blocksMinedRecipe);
NamespacedKey cropsMinedKey = new NamespacedKey(toolStats, "crops-mined-token"); 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.shape(" P ", "PHP", " P ");
cropsMinedRecipe.setIngredient('P', Material.PAPER); cropsMinedRecipe.setIngredient('P', Material.PAPER);
cropsMinedRecipe.setIngredient('H', Material.WOODEN_HOE); cropsMinedRecipe.setIngredient('H', Material.WOODEN_HOE);
recipes.add(cropsMinedRecipe); recipes.add(cropsMinedRecipe);
NamespacedKey fishCaughtKey = new NamespacedKey(toolStats, "fish-caught-token"); 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.shape(" P ", "PCP", " P ");
fishCaughtRecipe.setIngredient('P', Material.PAPER); fishCaughtRecipe.setIngredient('P', Material.PAPER);
fishCaughtRecipe.setIngredient('C', Material.COD); fishCaughtRecipe.setIngredient('C', Material.COD);
recipes.add(fishCaughtRecipe); recipes.add(fishCaughtRecipe);
NamespacedKey sheepShearedKey = new NamespacedKey(toolStats, "sheep-sheared-token"); 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.shape(" P ", "PWP", " P ");
sheepShearedRecipe.setIngredient('P', Material.PAPER); sheepShearedRecipe.setIngredient('P', Material.PAPER);
sheepShearedRecipe.setIngredient('W', Material.WHITE_WOOL); sheepShearedRecipe.setIngredient('W', Material.WHITE_WOOL);
recipes.add(sheepShearedRecipe); recipes.add(sheepShearedRecipe);
NamespacedKey armorDamageKey = new NamespacedKey(toolStats, "damage-taken-token"); 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.shape(" P ", "PCP", " P ");
armorDamageRecipe.setIngredient('P', Material.PAPER); armorDamageRecipe.setIngredient('P', Material.PAPER);
armorDamageRecipe.setIngredient('C', Material.LEATHER_CHESTPLATE); armorDamageRecipe.setIngredient('C', Material.LEATHER_CHESTPLATE);
recipes.add(armorDamageRecipe); recipes.add(armorDamageRecipe);
NamespacedKey damageDoneKey = new NamespacedKey(toolStats, "damage-done-token"); 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.shape(" P ", "PSP", " P ");
damageDoneRecipe.setIngredient('P', Material.PAPER); damageDoneRecipe.setIngredient('P', Material.PAPER);
damageDoneRecipe.setIngredient('S', Material.SHIELD); damageDoneRecipe.setIngredient('S', Material.SHIELD);
recipes.add(damageDoneRecipe); recipes.add(damageDoneRecipe);
NamespacedKey arrowsShotKey = new NamespacedKey(toolStats, "arrows-shot-token"); 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.shape(" P ", "PAP", " P ");
arrowsShotRecipe.setIngredient('P', Material.PAPER); arrowsShotRecipe.setIngredient('P', Material.PAPER);
arrowsShotRecipe.setIngredient('A', Material.ARROW); arrowsShotRecipe.setIngredient('A', Material.ARROW);
recipes.add(arrowsShotRecipe); recipes.add(arrowsShotRecipe);
NamespacedKey flightTimeKey = new NamespacedKey(toolStats, "flight-time-token"); 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.shape(" P ", "PFP", " P ");
flightTimeRecipe.setIngredient('P', Material.PAPER); flightTimeRecipe.setIngredient('P', Material.PAPER);
flightTimeRecipe.setIngredient('F', Material.FEATHER); flightTimeRecipe.setIngredient('F', Material.FEATHER);
recipes.add(flightTimeRecipe); recipes.add(flightTimeRecipe);
NamespacedKey resetKey = new NamespacedKey(toolStats, "reset-token"); 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.shape(" P ", "PPP", " P ");
resetRecipe.setIngredient('P', Material.PAPER); resetRecipe.setIngredient('P', Material.PAPER);
recipes.add(resetRecipe); recipes.add(resetRecipe);
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, createToken("remove"));
removeRecipe.shape(" P ", "P P", " P "); removeRecipe.shape(" P ", "P P", " P ");
removeRecipe.setIngredient('P', Material.PAPER); removeRecipe.setIngredient('P', Material.PAPER);
recipes.add(removeRecipe); recipes.add(removeRecipe);
@@ -140,4 +146,80 @@ public class TokenCrafting {
public ArrayList<String> getTokenTypes() { public ArrayList<String> getTokenTypes() {
return tokenTypes; 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.warn("Could not find material config for token {}", tokenType);
toolStats.logger.warn("Using PAPER as default.");
materialFromConfig = "PAPER";
}
Material material = Material.getMaterial(materialFromConfig);
if (material == null) {
toolStats.logger.warn("Material {} is not a valid Minecraft material.", materialFromConfig);
toolStats.logger.warn("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
String titleFromConfig = toolStats.config.getString("tokens.data." + tokenType + ".title");
Component title = toolStats.textUtils.format(titleFromConfig);
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("{} is not a valid float!", data);
return null;
}
return CustomModelData.customModelData().addFloat(f).build();
}
case "string": {
return CustomModelData.customModelData().addString(data.toString()).build();
}
default: {
toolStats.logger.info("{} is not a valid data type!", data);
return null;
}
}
}
} }

View File

@@ -1,54 +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;
import org.bukkit.persistence.PersistentDataAdapterContext;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import java.nio.ByteBuffer;
import java.util.UUID;
public class UUIDDataType implements PersistentDataType<byte[], UUID> {
@Override
public @NotNull Class<byte[]> getPrimitiveType() {
return byte[].class;
}
@Override
public @NotNull Class<UUID> getComplexType() {
return UUID.class;
}
@Override
public byte @NotNull [] toPrimitive(UUID complex, @NotNull PersistentDataAdapterContext context) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(complex.getMostSignificantBits());
bb.putLong(complex.getLeastSignificantBits());
return bb.array();
}
@Override
public @NotNull UUID fromPrimitive(byte @NotNull [] primitive, @NotNull PersistentDataAdapterContext context) {
ByteBuffer bb = ByteBuffer.wrap(primitive);
long firstLong = bb.getLong();
long secondLong = bb.getLong();
return new UUID(firstLong, secondLong);
}
}

View File

@@ -20,8 +20,6 @@ package lol.hyper.toolstats.tools.config;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Material; import org.bukkit.Material;
import java.util.ArrayList; import java.util.ArrayList;
@@ -34,8 +32,6 @@ import java.util.regex.Pattern;
public class ConfigTools { public class ConfigTools {
private final ToolStats toolStats; private final ToolStats toolStats;
public static final Pattern COLOR_CODES = Pattern.compile("[&§]([0-9a-fk-or])");
public static final Pattern CONFIG_HEX_PATTERN = Pattern.compile("[&§]#([A-Fa-f0-9]{6})");
public ConfigTools(ToolStats toolStats) { public ConfigTools(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
@@ -49,6 +45,11 @@ public class ConfigTools {
* @return If we want to add data or not. * @return If we want to add data or not.
*/ */
public boolean checkConfig(Material material, String configName) { public boolean checkConfig(Material material, String configName) {
if (toolStats.config.getConfigurationSection("enabled." + configName) == null) {
toolStats.logger.warn("Missing config section for enabled{}", configName);
return false;
}
String itemName = material.toString().toLowerCase(); String itemName = material.toString().toLowerCase();
String itemType = null; String itemType = null;
// hardcode these // hardcode these
@@ -75,7 +76,6 @@ public class ConfigTools {
} else { } else {
itemType = itemName.substring(itemName.indexOf('_') + 1); itemType = itemName.substring(itemName.indexOf('_') + 1);
} }
return switch (itemType) { return switch (itemType) {
case "pickaxe" -> toolStats.config.getBoolean("enabled." + configName + ".pickaxe"); case "pickaxe" -> toolStats.config.getBoolean("enabled." + configName + ".pickaxe");
case "sword" -> toolStats.config.getBoolean("enabled." + configName + ".sword"); case "sword" -> toolStats.config.getBoolean("enabled." + configName + ".sword");
@@ -104,7 +104,7 @@ public class ConfigTools {
public Component formatLore(String configName, String placeHolder, Object value) { public Component formatLore(String configName, String placeHolder, Object value) {
String lore = toolStats.config.getString("messages." + configName); String lore = toolStats.config.getString("messages." + configName);
if (lore == null) { if (lore == null) {
toolStats.logger.warning("Unable to find config message for: messages." + configName); toolStats.logger.warn("Unable to find config message for: messages.{}", configName);
return null; return null;
} }
@@ -121,16 +121,7 @@ public class ConfigTools {
lore = lore.replace(placeHolder, String.valueOf(value)); lore = lore.replace(placeHolder, String.valueOf(value));
} }
// if we match the old color codes, then format them as so component = toolStats.textUtils.format(lore);
Matcher hexMatcher = CONFIG_HEX_PATTERN.matcher(lore);
Matcher colorMatcher = COLOR_CODES.matcher(lore);
if (hexMatcher.find() || colorMatcher.find()) {
component = LegacyComponentSerializer.legacyAmpersand().deserialize(lore);
} else {
// otherwise format them normally
component = MiniMessage.miniMessage().deserialize(lore);
}
return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE); return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE);
} }
@@ -144,7 +135,7 @@ public class ConfigTools {
public Component formatLoreMultiplePlaceholders(String configName, Map<String, String> placeHoldersValues) { public Component formatLoreMultiplePlaceholders(String configName, Map<String, String> placeHoldersValues) {
String lore = toolStats.config.getString("messages." + configName); String lore = toolStats.config.getString("messages." + configName);
if (lore == null) { if (lore == null) {
toolStats.logger.warning("Unable to find config message for: messages." + configName); toolStats.logger.warn("Unable to find config message for: messages.{}", configName);
return null; return null;
} }
@@ -179,49 +170,7 @@ public class ConfigTools {
Component component; Component component;
// Clean output text // Clean output text
String outputText = result.toString().replaceAll("\\s+", " ").trim(); String outputText = result.toString().replaceAll("\\s+", " ").trim();
component = toolStats.textUtils.format(outputText);
// 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.
*
* @param configName The config to format.
* @return Formatted string, null if the configName doesn't exist.
*/
public Component format(String configName) {
String message = toolStats.config.getString(configName);
if (message == null) {
toolStats.logger.warning("Unable to find config message for: " + configName);
return null;
}
// if the config message is empty, don't send it
if (message.isEmpty()) {
return null;
}
// the final component for this lore
Component component;
// if we match the old color codes, then format them as so
Matcher hexMatcher = CONFIG_HEX_PATTERN.matcher(message);
Matcher colorMatcher = COLOR_CODES.matcher(message);
if (hexMatcher.find() || colorMatcher.find()) {
component = LegacyComponentSerializer.legacyAmpersand().deserialize(message);
} else {
// otherwise format them normally
component = MiniMessage.miniMessage().deserialize(message);
}
return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE); return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE);
} }
@@ -240,16 +189,14 @@ public class ConfigTools {
List<Component> finalLore = new ArrayList<>(); List<Component> finalLore = new ArrayList<>();
for (String line : raw) { for (String line : raw) {
Component component; if (line.contains("{levels}")) {
// if we match the old color codes, then format them as so Integer levels = toolStats.config.getInt("tokens.data." + tokenType + ".levels");
Matcher hexMatcher = CONFIG_HEX_PATTERN.matcher(line); // will return 0 if it doesn't exist
Matcher colorMatcher = COLOR_CODES.matcher(line); if (levels != 0) {
if (hexMatcher.find() || colorMatcher.find()) { line = line.replace("{levels}", String.valueOf(levels));
component = LegacyComponentSerializer.legacyAmpersand().deserialize(line);
} else {
// otherwise format them normally
component = MiniMessage.miniMessage().deserialize(line);
} }
}
Component component = toolStats.textUtils.format(line);
component = component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE); component = component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE);
finalLore.add(component); finalLore.add(component);
} }

View File

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

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

@@ -43,8 +43,7 @@ public class Version10 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-9.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-9.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config-9.yml!"); toolStats.logger.error("Unable to save config-9.yml!", exception);
throw new RuntimeException(exception);
} }
// we make this super verbose so that admins can see what's being added // we make this super verbose so that admins can see what's being added
@@ -72,8 +71,7 @@ public class Version10 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!"); toolStats.logger.error("Unable to save config.yml!", exception);
throw new RuntimeException(exception);
} }
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 10. A copy of version 9 has been saved as config-9.yml"); toolStats.logger.info("Config has been updated to version 10. A copy of version 9 has been saved as config-9.yml");

View File

@@ -45,8 +45,7 @@ public class Version11 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-10.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-10.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config-10.yml!"); toolStats.logger.error("Unable to save config-10.yml!", exception);
throw new RuntimeException(exception);
} }
// we make this super verbose so that admins can see what's being added // we make this super verbose so that admins can see what's being added
@@ -95,8 +94,7 @@ public class Version11 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!"); toolStats.logger.error("Unable to save config.yml!", exception);
throw new RuntimeException(exception);
} }
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

@@ -0,0 +1,115 @@
/*
* 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 org.bukkit.configuration.ConfigurationSection;
import java.io.File;
import java.io.IOException;
public class Version12 {
private final ToolStats toolStats;
/**
* Used for updating from version 11 to 12.
*
* @param toolStats ToolStats instance.
*/
public Version12(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-11.yml");
} catch (IOException exception) {
toolStats.logger.error("Unable to save config-11.yml!", exception);
}
toolStats.logger.info("Updating config.yml to version 12.");
toolStats.config.set("config-version", 12);
transfer("enabled.created-by", "enabled.crafted-by");
transfer("enabled.created-date", "enabled.crafted-on");
transfer("enabled.fished-tag", "enabled.fished-by");
transfer("enabled.fished-tag", "enabled.fished-on");
transfer("enabled.looted-tag", "enabled.looted-by");
transfer("enabled.looted-tag", "enabled.looted-on");
transfer("enabled.traded-tag", "enabled.traded-by");
transfer("enabled.traded-tag", "enabled.traded-on");
transfer("enabled.spawned-in", "enabled.spawned-in-by");
transfer("enabled.spawned-in", "enabled.spawned-in-on");
transfer("messages.created", "messages.crafted");
toolStats.config.set("enabled.created-by", null);
toolStats.config.set("enabled.created-date", null);
toolStats.config.set("enabled.fished-tag", null);
toolStats.config.set("enabled.looted-tag", null);
toolStats.config.set("enabled.traded-tag", null);
toolStats.config.set("enabled.spawned-in", null);
toolStats.logger.info("Adding enabled.dropped-on");
boolean droppedBy = toolStats.config.getBoolean("enabled.dropped-by");
toolStats.config.set("enabled.dropped-on", droppedBy);
toolStats.logger.info("Adding messages.dropped-on");
toolStats.config.set("messages.dropped-on", "&7Dropped on: &8{date}");
// rename crafted to crafted here
// copy the old ones first
String craftedByMessage = toolStats.config.getString("messages.created.created-by");
String craftedOnMessage = toolStats.config.getString("messages.created.created-on");
toolStats.config.set("messages.created", null);
toolStats.config.set("messages.crafted.created-by", null);
toolStats.config.set("messages.crafted.created-on", null);
toolStats.config.set("messages.crafted.crafted-by", craftedByMessage);
toolStats.config.set("messages.crafted.crafted-on", craftedOnMessage);
toolStats.logger.info("Adding normalize-time-creation");
toolStats.config.set("normalize-time-creation", false);
// save the config and reload it
try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) {
toolStats.logger.error("Unable to save config.yml!", exception);
}
toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 12. A copy of version 11 has been saved as config-11.yml");
}
private void transfer(String oldSection, String newSection) {
toolStats.logger.info("Moving {} to {}", oldSection, newSection);
ConfigurationSection old = toolStats.config.getConfigurationSection(oldSection);
toolStats.config.set(newSection, old);
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.error("Unable to save config-12.yml!", 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.{}.material", key);
toolStats.config.set("tokens.data." + key + ".material", "PAPER");
toolStats.logger.info("Adding tokens.data.{}.custom-model-data.enabled", key);
toolStats.config.set("tokens.data." + key + ".custom-model-data.enabled", false);
toolStats.logger.info("Adding tokens.data.{}.custom-model-data.type", key);
toolStats.config.set("tokens.data." + key + ".custom-model-data.type", "float");
toolStats.logger.info("Adding tokens.data.{}.custom-model-data.value", key);
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.error("Unable to save config.yml!", 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

@@ -46,8 +46,7 @@ public class Version6 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-5.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-5.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config-5.yml!"); toolStats.logger.error("Unable to save config-5.yml!", exception);
throw new RuntimeException(exception);
} }
// we make this super verbose so that admins can see what's being added // we make this super verbose so that admins can see what's being added
@@ -107,8 +106,7 @@ public class Version6 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!"); toolStats.logger.error("Unable to save config.yml!", exception);
throw new RuntimeException(exception);
} }
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 6. A copy of version 5 has been saved as config-5.yml"); toolStats.logger.info("Config has been updated to version 6. A copy of version 5 has been saved as config-5.yml");

View File

@@ -43,8 +43,7 @@ public class Version7 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-6.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-6.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config-6.yml!"); toolStats.logger.error("Unable to save config-6.yml!", exception);
throw new RuntimeException(exception);
} }
// we make this super verbose so that admins can see what's being added // we make this super verbose so that admins can see what's being added
@@ -61,8 +60,7 @@ public class Version7 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!"); toolStats.logger.error("Unable to save config.yml!", exception);
throw new RuntimeException(exception);
} }
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 7. A copy of version 6 has been saved as config-6.yml"); toolStats.logger.info("Config has been updated to version 7. A copy of version 6 has been saved as config-6.yml");

View File

@@ -45,8 +45,7 @@ public class Version8 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-7.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-7.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config-7.yml!"); toolStats.logger.error("Unable to save config-7.yml!", exception);
throw new RuntimeException(exception);
} }
// we make this super verbose so that admins can see what's being added // we make this super verbose so that admins can see what's being added
@@ -78,8 +77,7 @@ public class Version8 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!"); toolStats.logger.error("Unable to save config.yml!", exception);
throw new RuntimeException(exception);
} }
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 8. A copy of version 7 has been saved as config-7.yml"); toolStats.logger.info("Config has been updated to version 8. A copy of version 7 has been saved as config-7.yml");

View File

@@ -45,8 +45,7 @@ public class Version9 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-8.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config-8.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config-8.yml!"); toolStats.logger.error("Unable to save config-8.yml!", exception);
throw new RuntimeException(exception);
} }
toolStats.logger.info("Updating config.yml to version 9."); toolStats.logger.info("Updating config.yml to version 9.");
@@ -78,8 +77,7 @@ public class Version9 {
try { try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml"); toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) { } catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!"); toolStats.logger.error("Unable to save config.yml!", exception);
throw new RuntimeException(exception);
} }
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 9. A copy of version 8 has been saved as config-8.yml"); toolStats.logger.info("Config has been updated to version 9. A copy of version 8 has been saved as config-8.yml");
@@ -93,7 +91,7 @@ public class Version9 {
* @param lore The lore of the item. * @param lore The lore of the item.
*/ */
private void addToken(String tokenType, String title, String lore) { private void addToken(String tokenType, String title, String lore) {
toolStats.logger.info("Adding token type configuration for " + tokenType); toolStats.logger.info("Adding token type configuration for {}", tokenType);
toolStats.config.set("tokens.data." + tokenType + ".title", title); toolStats.config.set("tokens.data." + tokenType + ".title", title);
List<String> loreList = new ArrayList<>(); List<String> loreList = new ArrayList<>();
loreList.add(lore); loreList.add(lore);

View File

@@ -8,66 +8,138 @@ tokens:
title: "&7ToolStats: &8Player Kills Token" title: "&7ToolStats: &8Player Kills Token"
lore: lore:
- "&8Combine with a melee or ranged weapon in an anvil to track player kills." - "&8Combine with a melee or ranged weapon in an anvil to track player kills."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
mob-kills: mob-kills:
title: "&7ToolStats: &8Mob Kills Token" title: "&7ToolStats: &8Mob Kills Token"
lore: lore:
- "&8Combine with a melee or ranged weapon in an anvil to track mob kills." - "&8Combine with a melee or ranged weapon in an anvil to track mob kills."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
blocks-mined: blocks-mined:
title: "&7ToolStats: &8Blocks Mined Token" title: "&7ToolStats: &8Blocks Mined Token"
lore: lore:
- "&8Combine with a pickaxe, axe, shovel, or shears in an anvil to track blocks mined." - "&8Combine with a pickaxe, axe, shovel, or shears in an anvil to track blocks mined."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
crops-mined: crops-mined:
title: "&7ToolStats: &8Crops Mined Token" title: "&7ToolStats: &8Crops Mined Token"
lore: lore:
- "&8Combine with a hoe in an anvil to track crops broken." - "&8Combine with a hoe in an anvil to track crops broken."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
fish-caught: fish-caught:
title: "&7ToolStats: &8Fish Caught Token" title: "&7ToolStats: &8Fish Caught Token"
lore: lore:
- "&8Combine with a fishing rod in an anvil to track fish caught." - "&8Combine with a fishing rod in an anvil to track fish caught."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
sheep-sheared: sheep-sheared:
title: "&7ToolStats: &8Sheep Sheared Token" title: "&7ToolStats: &8Sheep Sheared Token"
lore: lore:
- "&8Combine with shears in an anvil to track sheep sheared." - "&8Combine with shears in an anvil to track sheep sheared."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
damage-taken: damage-taken:
title: "&7ToolStats: &8Damage Taken Token" title: "&7ToolStats: &8Damage Taken Token"
lore: lore:
- "&8Combine with an armor piece in an anvil to track damage taken." - "&8Combine with an armor piece in an anvil to track damage taken."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
damage-done: damage-done:
title: "&7ToolStats: &8Damage Done Token" title: "&7ToolStats: &8Damage Done Token"
lore: lore:
- "&8Combine with a melee or ranged weapon in an anvil to track damage done." - "&8Combine with a melee or ranged weapon in an anvil to track damage done."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
arrows-shot: arrows-shot:
title: "&7ToolStats: &8Arrows Shot Token" title: "&7ToolStats: &8Arrows Shot Token"
lore: lore:
- "&8Combine with a bow or crossbow in an anvil to track arrows shot." - "&8Combine with a bow or crossbow in an anvil to track arrows shot."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
flight-time: flight-time:
title: "&7ToolStats: &8Flight Time Token" title: "&7ToolStats: &8Flight Time Token"
lore: lore:
- "&8Combine with an elytra in an anvil to track flight time." - "&8Combine with an elytra in an anvil to track flight time."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
reset: reset:
title: "&7ToolStats: &8Reset Token" title: "&7ToolStats: &8Reset Token"
lore: lore:
- "&8Combine in an anvil with to reset ALL stats for this item. Tokens on this item stay." - "&8Combine in an anvil with to reset ALL stats for this item. Tokens on this item stay."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
remove: remove:
title: "&7ToolStats: &8Remove Token" title: "&7ToolStats: &8Remove Token"
lore: lore:
- "&8Combine in an anvil with to REMOVE ALL stats and tokens for this item." - "&8Combine in an anvil with to REMOVE ALL stats and tokens for this item."
- "&8Uses &7{levels} &8level."
levels: 1 levels: 1
material: PAPER
custom-model-data:
enabled: false
type: float
value: 1001
enabled: enabled:
# Will show ownership of items when they are created/found. # Will show "Crafted by <player>"
created-by: crafted-by:
pickaxe: true pickaxe: true
sword: true sword: true
shovel: true shovel: true
@@ -78,8 +150,8 @@ enabled:
armor: true armor: true
mace: true mace: true
fishing-rod: true fishing-rod: true
# Will show time the item is created # Will show "Crafted on <date>"
created-date: crafted-on:
pickaxe: true pickaxe: true
sword: true sword: true
shovel: true shovel: true
@@ -91,7 +163,18 @@ enabled:
mace: true mace: true
fishing-rod: true fishing-rod: true
# Will show "Fished by <player>" # Will show "Fished by <player>"
fished-tag: fished-by:
pickaxe: true
sword: true
shovel: true
axe: true
hoe: true
shears: true
bow: true
armor: true
fishing-rod: true
# Will show "Fished on <date>"
fished-on:
pickaxe: true pickaxe: true
sword: true sword: true
shovel: true shovel: true
@@ -102,7 +185,7 @@ enabled:
armor: true armor: true
fishing-rod: true fishing-rod: true
# Will show "Found by <player>" # Will show "Found by <player>"
looted-tag: looted-by:
pickaxe: true pickaxe: true
sword: true sword: true
shovel: true shovel: true
@@ -112,8 +195,30 @@ enabled:
bow: true bow: true
armor: true armor: true
fishing-rod: true fishing-rod: true
# Will show "Trade by <player>" # Will show "Found on <date>"
traded-tag: looted-on:
pickaxe: true
sword: true
shovel: true
axe: true
hoe: true
shears: true
bow: true
armor: true
fishing-rod: true
# Will show "Traded by <player>"
traded-by:
pickaxe: true
sword: true
shovel: true
axe: true
hoe: true
shears: true
bow: true
armor: true
fishing-rod: true
# Will show "Traded on <date>"
traded-on:
pickaxe: true pickaxe: true
sword: true sword: true
shovel: true shovel: true
@@ -148,7 +253,19 @@ enabled:
hoe: true hoe: true
shears: true shears: true
# Will show "Spawned in by <player>" # Will show "Spawned in by <player>"
spawned-in: spawned-in-by:
pickaxe: true
sword: true
shovel: true
axe: true
hoe: true
shears: true
bow: true
armor: true
mace: true
fishing-rod: true
# Will show "Spawned in on <date>"
spawned-in-on:
pickaxe: true pickaxe: true
sword: true sword: true
shovel: true shovel: true
@@ -163,15 +280,16 @@ enabled:
sheep-sheared: true sheep-sheared: true
armor-damage: true armor-damage: true
dropped-by: true dropped-by: true
dropped-on: true
elytra-tag: true elytra-tag: true
arrows-shot: true arrows-shot: true
flight-time: true flight-time: true
crops-harvested: true crops-harvested: true
messages: messages:
created: crafted:
created-by: "&7Crafted by: &8{player}" crafted-by: "&7Crafted by: &8{player}"
created-on: "&7Crafted on: &8{date}" crafted-on: "&7Crafted on: &8{date}"
fished: fished:
caught-by: "&7Caught by: &8{player}" caught-by: "&7Caught by: &8{player}"
caught-on: "&7Caught on: &8{date}" caught-on: "&7Caught on: &8{date}"
@@ -193,7 +311,8 @@ messages:
blocks-mined: "&7Blocks mined: &8{blocks}" blocks-mined: "&7Blocks mined: &8{blocks}"
crops-harvested: "&7Crops harvested: &8{crops}" crops-harvested: "&7Crops harvested: &8{crops}"
sheep-sheared: "&7Sheep sheared: &8{sheep}" sheep-sheared: "&7Sheep sheared: &8{sheep}"
dropped-by: "&7Dropped by: &8{name}" # name will be player/mob name dropped-by: "&7Dropped by: &8{name}" # name will be mob name
dropped-on: "&7Dropped on: &8{date}"
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{years}y {months}m {days}d {hours}h {minutes}m {seconds}s" flight-time: "&7Flight time: &8{years}y {months}m {days}d {hours}h {minutes}m {seconds}s"
@@ -220,4 +339,11 @@ number-formats:
# This has no use currently, but can be used for future features for dupe detection. # This has no use currently, but can be used for future features for dupe detection.
generate-hash-for-items: false generate-hash-for-items: false
config-version: 11 # Make when items are created at midnight on the date.
# This makes dates for items more "normalized" instead of being at different times.
normalize-time-creation: false
# Allows stats and origins to be tracked if the player is in creative mode.
allow-creative: false
config-version: 13

View File

@@ -23,6 +23,18 @@ permissions:
toolstats.reset.confirm: toolstats.reset.confirm:
description: Allows the usage of /toolstats reset confirm. description: Allows the usage of /toolstats reset confirm.
default: true default: true
toolstats.purge:
description: Allows the usage of /toolstats purge.
default: true
toolstats.purge.confirm:
description: Allows the usage of /toolstats purge confirm.
default: true
toolstats.givetokens: toolstats.givetokens:
description: Allows the usage of /toolstats givetoken. description: Allows the usage of /toolstats givetoken.
default: op default: op
toolstats.edit:
description: Allows the usage of /toolstats edit.
default: op
toolstats.remove:
description: Allows the usage of /toolstats remove.
default: op