Compare commits

...

44 Commits
1.8 ... 1.8.7

Author SHA1 Message Date
hyperdefined
ff578e170e 1.8.7 2025-01-22 18:19:12 -05:00
hyperdefined
87aa26c7e9 Update ItemChecker.java 2025-01-22 18:17:49 -05:00
hyperdefined
2b5f784b93 Update config.yml 2025-01-22 18:17:33 -05:00
hyperdefined
94ff8f251d go back to text comparison
this broke something with another plugin
2025-01-22 18:10:35 -05:00
hyperdefined
f9fa15dbaf finally handle shift clicking
closes #89
2025-01-22 17:54:50 -05:00
hyperdefined
1a15fb94f4 misc cleanup 2025-01-22 17:02:31 -05:00
hyperdefined
44b70a8394 fix #90 2025-01-22 17:02:05 -05:00
hyperdefined
98ee84ad13 fix handling empty messages 2025-01-18 13:06:38 -05:00
hyperdefined
c68a04851b Update README.md 2024-12-31 13:21:41 -05:00
hyperdefined
06e063a072 Update hangar.yml 2024-12-30 23:29:24 -05:00
hyperdefined
c00c534d49 test complete 2024-12-30 23:28:35 -05:00
hyperdefined
d6f8176ce1 remove deprecated thing 2024-12-30 23:27:11 -05:00
hyperdefined
eb06dff0bc bro 2024-12-30 23:23:36 -05:00
hyperdefined
9a72c509ef hangar API test 2024-12-30 23:22:31 -05:00
hyperdefined
eaca8ac87d Update README.md 2024-12-23 19:24:04 -05:00
hyperdefined
44a2c5cd26 Update README.md 2024-12-23 19:16:29 -05:00
hyperdefined
0957a1c989 Update README.md 2024-12-23 19:07:03 -05:00
hyperdefined
7b12a130a0 1.8.5 2024-12-17 17:47:14 -05:00
hyperdefined
6b263be041 patience wizard 2024-12-15 18:31:38 -05:00
hyperdefined
aeaeee680b revert this since we can now 2024-12-15 18:31:09 -05:00
hyperdefined
d8c7425a5a 1.8.4 2024-12-15 18:29:46 -05:00
hyperdefined
86c92c9706 change these 2024-12-15 17:10:57 -05:00
hyperdefined
cd62f7309e update these 2024-12-14 18:31:14 -05:00
hyperdefined
e2b18cb5f1 Update README.md 2024-12-14 18:06:16 -05:00
hyperdefined
150956b2c9 Update pom.xml 2024-12-14 18:05:01 -05:00
hyperdefined
585e020baf migration to Paper API 2024-12-14 17:28:02 -05:00
hyperdefined
50b5823daf remove debug 2024-10-07 21:19:21 -04:00
hyperdefined
c87d0ca3bf Update pom.xml 2024-10-07 21:18:52 -04:00
hyperdefined
d1a16ff2e6 added missing breaks 2024-10-07 21:18:02 -04:00
hyperdefined
9134da31f4 support for mace #82 2024-10-07 21:16:07 -04:00
hyperdefined
0cf85edda6 support for custom mob names
closes #71
2024-10-07 21:05:46 -04:00
hyperdefined
7fe0234785 fix for older MC versions
fixes #81
2024-10-05 18:37:51 -04:00
hyperdefined
6385814b52 Merge pull request #80 from hyperdefined/dependabot/maven/org.bstats-bstats-bukkit-3.1.0
Bump org.bstats:bstats-bukkit from 3.0.3 to 3.1.0
2024-10-05 18:10:25 -04:00
hyperdefined
603e1ac1fd fix #79 2024-09-25 19:50:26 -04:00
dependabot[bot]
86dc5f421a Bump org.bstats:bstats-bukkit from 3.0.3 to 3.1.0
Bumps [org.bstats:bstats-bukkit](https://github.com/Bastian/bStats-Metrics) from 3.0.3 to 3.1.0.
- [Release notes](https://github.com/Bastian/bStats-Metrics/releases)
- [Commits](https://github.com/Bastian/bStats-Metrics/compare/v3.0.3...v3.1.0)

---
updated-dependencies:
- dependency-name: org.bstats:bstats-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 11:36:47 +00:00
hyperdefined
7d9be0cfd1 Update README.md 2024-09-10 17:19:15 -04:00
hyperdefined
f7bacec617 Update README.md 2024-09-10 17:17:51 -04:00
hyperdefined
227723fe10 fix #75 2024-09-10 17:08:40 -04:00
hyperdefined
785333e8d1 Update pom.xml 2024-09-10 16:02:04 -04:00
hyperdefined
bc784b8d46 fix elytra flight calculations
fixes #74
2024-09-10 16:01:45 -04:00
hyperdefined
f5ddada892 support for gradient coloring
fixes #72
2024-09-10 16:01:24 -04:00
hyperdefined
a43155b0c5 Fix armor damage + arrows on reset command 2024-09-08 22:57:41 -04:00
hyperdefined
e327d132e2 Update pom.xml 2024-09-08 22:52:55 -04:00
hyperdefined
f09f2d3703 Fix armor damage breaking (#70) 2024-09-08 22:51:49 -04:00
32 changed files with 553 additions and 515 deletions

31
.github/workflows/hangar.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Update Hangar Description
on:
push:
branches: [ master ]
jobs:
update-hangar-page:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Authenticate with Hangar
id: authenticate
run: |
RESPONSE=$(curl -s -X POST "https://hangar.papermc.io/api/v1/authenticate?apiKey=${{ secrets.HANGAR }}" -H 'accept: application/json')
TOKEN=$(echo $RESPONSE | jq -r '.token')
if [[ "$TOKEN" == "null" ]]; then
echo "Error: Unable to fetch JWT token"
exit 1
fi
echo "::add-mask::$TOKEN"
echo "token=$TOKEN" >> $GITHUB_OUTPUT
- name: Update Project Description
run: |
README_CONTENT=$(cat README.md | jq -Rs .)
curl -s -X PATCH "https://hangar.papermc.io/api/v1/pages/editmain/ToolStats" \
-H "content-type: application/json" \
-H "Authorization: HangarAuth ${{ steps.authenticate.outputs.token }}" \
-d "{\"content\":$README_CONTENT}"

View File

@@ -15,10 +15,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Set up JDK 1.8 - name: Set up JDK 21
uses: actions/setup-java@v1 uses: actions/setup-java@v4
with: with:
java-version: 1.8 distribution: temurin
- name: Build with Maven java-version: 21
run: mvn -B package --file pom.xml - name: Build with Maven
run: mvn -B package --file pom.xml

View File

@@ -1,3 +1,4 @@
name: Update Modrinth Description
on: on:
push: push:
branches: [ master ] branches: [ master ]
@@ -9,4 +10,4 @@ jobs:
- uses: funnyboy-roks/modrinth-auto-desc@v1.6 - uses: funnyboy-roks/modrinth-auto-desc@v1.6
with: with:
auth-token: ${{ secrets.MODRINTH }} auth-token: ${{ secrets.MODRINTH }}
slug: 'oBZj9E15' slug: 'oBZj9E15'

View File

@@ -1,26 +1,26 @@
<h1 align="center">ToolStats</h1> <h1 align="center">ToolStats</h1>
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/Minecraft-1.15--1.21-orange" alt="Minecraft versions"> <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>
<img src="https://img.shields.io/github/v/release/hyperdefined/ToolStats" alt="GitHub release (latest by date)"> <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://github.com/hyperdefined/ToolStats/releases"><img src="https://img.shields.io/github/downloads/hyperdefined/ToolStats/total?logo=github" alt="Downloads"></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>
<img src="https://img.shields.io/badge/made%20with-love%20&%20fluff-red" alt="Made with love & fluff"> <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://ko-fi.com/hyperdefined"><img src="https://img.shields.io/badge/Donate-Ko--fi-red" alt="Donate via Ko-fi"></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://www.gnu.org/licenses/gpl-3.0"><img src="https://img.shields.io/badge/License-GPLv3-blue.svg" alt="License: GPL v3"></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://wakatime.com/badge/user/992a7647-176a-477c-8086-e1abfba87ff4/project/0200f07a-f303-4103-a5f2-34b38c9c1fa4"><img src="https://wakatime.com/badge/user/992a7647-176a-477c-8086-e1abfba87ff4/project/0200f07a-f303-4103-a5f2-34b38c9c1fa4.svg" alt="wakatime"></a>
</p> </p>
ToolStats is a small plugin that display various stats about tools. This plugin is inspired off of [GearStats](https://www.spigotmc.org/resources/gearstats.12960/). You can disable/enable which stats are shown on which tools via the config. Note: stats are tracked regardless of config setting. The config is to disable the lore on the item. 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 disable/enable which stats are shown on which tools via the config. Note: stats are tracked regardless of config setting. The config is to disable the lore on the item.
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) * 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.
* Fish caught. * Fish caught.
* Sheep sheared. * Sheep sheared.
* Arrows shot (bows/crossbows) * Arrows shot (bows/crossbows)
* Flight time with elytras.
The best part is, this data is stored on the item itself. You can also change how the lore is displayed on the items! The best part is, this data is stored on the item itself. You can also change how the lore is displayed on the items!
@@ -43,4 +43,4 @@ If item lore is ever incorrect/missing, you can run `/toolstats reset`. This com
Visit the [wiki](https://github.com/hyperdefined/ToolStats/wiki) for help. Visit the [wiki](https://github.com/hyperdefined/ToolStats/wiki) 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).

52
pom.xml
View File

@@ -23,13 +23,13 @@
<groupId>lol.hyper</groupId> <groupId>lol.hyper</groupId>
<artifactId>toolstats</artifactId> <artifactId>toolstats</artifactId>
<version>1.8</version> <version>1.8.7</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>ToolStats</name> <name>ToolStats</name>
<properties> <properties>
<java.version>1.8</java.version> <java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
@@ -67,18 +67,10 @@
<pattern>org.bstats</pattern> <pattern>org.bstats</pattern>
<shadedPattern>lol.hyper.toolstats.bstats</shadedPattern> <shadedPattern>lol.hyper.toolstats.bstats</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>net.kyori.adventure</pattern>
<shadedPattern>lol.hyper.toolstats.adventure</shadedPattern>
</relocation>
<relocation> <relocation>
<pattern>lol.hyper.githubreleaseapi</pattern> <pattern>lol.hyper.githubreleaseapi</pattern>
<shadedPattern>lol.hyper.toolstats.updater</shadedPattern> <shadedPattern>lol.hyper.toolstats.updater</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>space.arim.morepaperlib</pattern>
<shadedPattern>lol.hyper.toolstats.morepaperlib</shadedPattern>
</relocation>
</relocations> </relocations>
</configuration> </configuration>
<executions> <executions>
@@ -104,26 +96,22 @@
<repositories> <repositories>
<repository> <repository>
<id>spigotmc-repo</id> <id>papermc</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> <url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>arim-mvn-lgpl3</id>
<url>https://mvn-repo.arim.space/lesser-gpl3/</url>
</repository> </repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>io.papermc.paper</groupId>
<artifactId>spigot-api</artifactId> <artifactId>paper-api</artifactId>
<version>1.20.2-R0.1-SNAPSHOT</version> <version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bstats</groupId> <groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId> <artifactId>bstats-bukkit</artifactId>
<version>3.0.3</version> <version>3.1.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -132,29 +120,5 @@
<version>1.0.5</version> <version>1.0.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.17.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>space.arim.morepaperlib</groupId>
<artifactId>morepaperlib</artifactId>
<version>0.4.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
<version>1.20-R0.2</version>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -27,17 +27,11 @@ import lol.hyper.toolstats.tools.ItemLore;
import lol.hyper.toolstats.tools.NumberFormat; import lol.hyper.toolstats.tools.NumberFormat;
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 net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import space.arim.morepaperlib.MorePaperLib;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -81,10 +75,6 @@ public final class ToolStats extends JavaPlugin {
* Stores how much damage an armor piece has taken. * Stores how much damage an armor piece has taken.
*/ */
public final NamespacedKey armorDamage = new NamespacedKey(this, "damage-taken"); public final NamespacedKey armorDamage = new NamespacedKey(this, "damage-taken");
/**
* Stores how much damage an armor piece has taken (as an int).
*/
public final NamespacedKey armorDamageInt = new NamespacedKey(this, "damage-taken-int");
/** /**
* Key for tracking new elytras that spawn. * Key for tracking new elytras that spawn.
*/ */
@@ -113,7 +103,7 @@ 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 = 7; public final int CONFIG_VERSION = 8;
public final Logger logger = this.getLogger(); public final Logger logger = this.getLogger();
public final File configFile = new File(this.getDataFolder(), "config.yml"); public final File configFile = new File(this.getDataFolder(), "config.yml");
@@ -134,8 +124,6 @@ public final class ToolStats extends JavaPlugin {
public PlayerJoin playerJoin; public PlayerJoin playerJoin;
public NumberFormat numberFormat; public NumberFormat numberFormat;
public YamlConfiguration config; public YamlConfiguration config;
private BukkitAudiences adventure;
public MorePaperLib morePaperLib;
public HashMaker hashMaker; public HashMaker hashMaker;
public CreativeEvent creativeEvent; public CreativeEvent creativeEvent;
public PlayerMove playerMove; public PlayerMove playerMove;
@@ -145,8 +133,6 @@ public final class ToolStats extends JavaPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
this.adventure = BukkitAudiences.create(this);
morePaperLib = new MorePaperLib(this);
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!");
@@ -194,8 +180,7 @@ public final class ToolStats extends JavaPlugin {
this.getCommand("toolstats").setExecutor(commandToolStats); this.getCommand("toolstats").setExecutor(commandToolStats);
new Metrics(this, 14110); new Metrics(this, 14110);
Bukkit.getAsyncScheduler().runNow(this, scheduledTask -> checkForUpdates());
morePaperLib.scheduling().asyncScheduler().run(this::checkForUpdates);
} }
public void loadConfig() { public void loadConfig() {
@@ -218,7 +203,7 @@ public final class ToolStats extends JavaPlugin {
e.printStackTrace(); e.printStackTrace();
return; return;
} }
GitHubRelease current = api.getReleaseByTag(this.getDescription().getVersion()); GitHubRelease current = api.getReleaseByTag(this.getPluginMeta().getVersion());
GitHubRelease latest = api.getLatestVersion(); GitHubRelease latest = api.getLatestVersion();
if (current == null) { if (current == null) {
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!"); 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!");
@@ -231,23 +216,4 @@ public final class ToolStats extends JavaPlugin {
logger.warning("A new version is available (" + latest.getTagVersion() + ")! You are running version " + current.getTagVersion() + ". You are " + buildsBehind + " version(s) behind."); logger.warning("A new version is available (" + latest.getTagVersion() + ")! You are running version " + current.getTagVersion() + ". You are " + buildsBehind + " version(s) behind.");
} }
} }
public BukkitAudiences getAdventure() {
if (this.adventure == null) {
throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!");
}
return this.adventure;
}
public void scheduleEntity(BukkitRunnable runnable, Entity entity, int delay) {
morePaperLib.scheduling().entitySpecificScheduler(entity).runDelayed(runnable, null, delay);
}
public void scheduleGlobal(BukkitRunnable runnable, int delay) {
morePaperLib.scheduling().globalRegionalScheduler().runDelayed(runnable, delay);
}
public void scheduleRegion(BukkitRunnable runnable, World world, Chunk chunk, int delay) {
morePaperLib.scheduling().regionSpecificScheduler(world, chunk.getX(), chunk.getZ()).runDelayed(runnable, delay);
}
} }

View File

@@ -19,7 +19,6 @@ package lol.hyper.toolstats.commands;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
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;
@@ -42,65 +41,63 @@ import java.util.*;
public class CommandToolStats implements TabExecutor { public class CommandToolStats implements TabExecutor {
private final ToolStats toolStats; private final ToolStats toolStats;
private final BukkitAudiences audiences;
public CommandToolStats(ToolStats toolStats) { public CommandToolStats(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
this.audiences = toolStats.getAdventure();
} }
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!sender.hasPermission("toolstats.command")) { if (!sender.hasPermission("toolstats.command")) {
audiences.sender(sender).sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true; return true;
} }
if (args.length == 0) { if (args.length == 0) {
audiences.sender(sender).sendMessage(Component.text("ToolStats version " + toolStats.getDescription().getVersion() + ". Created by hyperdefined.", NamedTextColor.GREEN)); sender.sendMessage(Component.text("ToolStats version " + toolStats.getPluginMeta().getVersion() + ". Created by hyperdefined.", NamedTextColor.GREEN));
return true; return true;
} }
switch (args[0]) { switch (args[0]) {
case "reload": { case "reload": {
if (sender.hasPermission("toolstats.reload")) { if (sender.hasPermission("toolstats.reload")) {
toolStats.loadConfig(); toolStats.loadConfig();
audiences.sender(sender).sendMessage(Component.text("Configuration reloaded!", NamedTextColor.GREEN)); sender.sendMessage(Component.text("Configuration reloaded!", NamedTextColor.GREEN));
} else { } else {
audiences.sender(sender).sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
} }
return true; return true;
} }
case "reset": { case "reset": {
if (!sender.hasPermission("toolstats.reset")) { if (!sender.hasPermission("toolstats.reset")) {
audiences.sender(sender).sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true; return true;
} }
if (sender instanceof ConsoleCommandSender) { if (sender instanceof ConsoleCommandSender) {
audiences.sender(sender).sendMessage(Component.text("You must be a player for this command.", NamedTextColor.RED)); sender.sendMessage(Component.text("You must be a player for this command.", NamedTextColor.RED));
return true; return true;
} }
if (args.length == 2 && args[1].equalsIgnoreCase("confirm")) { if (args.length == 2 && args[1].equalsIgnoreCase("confirm")) {
if (!sender.hasPermission("toolstats.reset.confirm")) { if (!sender.hasPermission("toolstats.reset.confirm")) {
audiences.sender(sender).sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED)); sender.sendMessage(Component.text("You do not have permission for this command.", NamedTextColor.RED));
return true; return true;
} }
Player player = (Player) sender; Player player = (Player) sender;
ItemStack heldItem = player.getInventory().getItemInMainHand(); ItemStack heldItem = player.getInventory().getItemInMainHand();
if (!toolStats.itemChecker.isValidItem(heldItem.getType())) { if (!toolStats.itemChecker.isValidItem(heldItem.getType())) {
audiences.sender(sender).sendMessage(Component.text("You must hold a valid item.", NamedTextColor.RED)); sender.sendMessage(Component.text("You must hold a valid item.", NamedTextColor.RED));
return true; return true;
} }
fixItemLore(heldItem, player); fixItemLore(heldItem, player);
audiences.sender(sender).sendMessage(Component.text("The lore was reset!", NamedTextColor.GREEN)); sender.sendMessage(Component.text("The lore was reset!", NamedTextColor.GREEN));
return true; return true;
} }
audiences.sender(sender).sendMessage(Component.text("This will remove ALL current lore from the held item and replace it with the correct lore.", NamedTextColor.GREEN)); sender.sendMessage(Component.text("This will remove ALL current lore from the held item and replace it with the correct lore.", NamedTextColor.GREEN));
audiences.sender(sender).sendMessage(Component.text("If the owner of the item is broken, it will reset to the person holding it.", NamedTextColor.GREEN)); sender.sendMessage(Component.text("If the owner of the item is broken, it will reset to the person holding it.", NamedTextColor.GREEN));
audiences.sender(sender).sendMessage(Component.text("Only use this if the tags on the tool are incorrect.", NamedTextColor.GREEN)); sender.sendMessage(Component.text("Only use this if the tags on the tool are incorrect.", NamedTextColor.GREEN));
audiences.sender(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;
} }
default: { default: {
audiences.sender(sender).sendMessage(Component.text("Invalid sub-command.", NamedTextColor.RED)); sender.sendMessage(Component.text("Invalid sub-command.", NamedTextColor.RED));
} }
} }
return true; return true;
@@ -119,7 +116,7 @@ public class CommandToolStats implements TabExecutor {
return; return;
} }
PersistentDataContainer container = finalMeta.getPersistentDataContainer(); PersistentDataContainer container = finalMeta.getPersistentDataContainer();
List<String> lore = new ArrayList<>(); List<Component> lore = new ArrayList<>();
// set how the item was obtained // set how the item was obtained
Integer origin = -1; Integer origin = -1;
@@ -145,19 +142,19 @@ public class CommandToolStats implements TabExecutor {
if (flightTime != null) { if (flightTime != null) {
if (toolStats.config.getBoolean("enabled.flight-time")) { if (toolStats.config.getBoolean("enabled.flight-time")) {
String line = toolStats.configTools.formatLore("flight-time", "{time}", toolStats.numberFormat.formatDouble((double) flightTime / 1000)); Component line = toolStats.configTools.formatLore("flight-time", "{time}", toolStats.numberFormat.formatDouble((double) flightTime / 1000));
lore.add(line); lore.add(line);
} }
} }
if (timeCreated != null) { if (timeCreated != null) {
String timeCreatedLine = toolStats.configTools.formatLore("looted.found-by", "{player}", player.getName()); Component timeCreatedLine = toolStats.configTools.formatLore("looted.found-by", "{player}", player.getName());
String playerOwnerLine = toolStats.configTools.formatLore("looted.found-on", "{date}", toolStats.numberFormat.formatDate(new Date(timeCreated))); Component playerOwnerLine = toolStats.configTools.formatLore("looted.found-on", "{date}", toolStats.numberFormat.formatDate(new Date(timeCreated)));
lore.add(timeCreatedLine); lore.add(timeCreatedLine);
lore.add(playerOwnerLine); lore.add(playerOwnerLine);
} }
finalMeta.setLore(lore); finalMeta.lore(lore);
finalItem.setItemMeta(finalMeta); finalItem.setItemMeta(finalMeta);
int slot = player.getInventory().getHeldItemSlot(); int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem); player.getInventory().setItem(slot, finalItem);
@@ -176,7 +173,7 @@ public class CommandToolStats implements TabExecutor {
// if the owner's name is null for whatever reason, set the new owner // if the owner's name is null for whatever reason, set the new owner
// to the current player running the command // to the current player running the command
if (ownerName == null) { if (ownerName == null) {
audiences.player(player).sendMessage(Component.text("The owner of this item is null. Setting to " + player.getName() + ".", NamedTextColor.RED)); player.sendMessage(Component.text("The owner of this item is null. Setting to " + player.getName() + ".", NamedTextColor.RED));
ownerName = player.getName(); ownerName = player.getName();
container.set(toolStats.genericOwner, new UUIDDataType(), player.getUniqueId()); container.set(toolStats.genericOwner, new UUIDDataType(), player.getUniqueId());
} }
@@ -297,7 +294,7 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.armorDamage, PersistentDataType.DOUBLE)) { if (container.has(toolStats.armorDamage, PersistentDataType.DOUBLE)) {
Double damage = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE); Double damage = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE);
if (damage != null) { if (damage != null) {
toolStats.configTools.formatLore("damage-taken", "{damage}", toolStats.numberFormat.formatDouble(damage)); lore.add(toolStats.configTools.formatLore("damage-taken", "{damage}", toolStats.numberFormat.formatDouble(damage)));
} }
} }
} }
@@ -305,11 +302,11 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.arrowsShot, PersistentDataType.INTEGER)) { if (container.has(toolStats.arrowsShot, PersistentDataType.INTEGER)) {
Integer arrows = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER); Integer arrows = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER);
if (arrows != null) { if (arrows != null) {
toolStats.configTools.formatLore("arrows-shot", "{arrows}", toolStats.numberFormat.formatInt(arrows)); lore.add(toolStats.configTools.formatLore("arrows-shot", "{arrows}", toolStats.numberFormat.formatInt(arrows)));
} }
} }
} }
finalMeta.setLore(lore); finalMeta.lore(lore);
finalItem.setItemMeta(finalMeta); finalItem.setItemMeta(finalMeta);
int slot = player.getInventory().getHeldItemSlot(); int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem); player.getInventory().setItem(slot, finalItem);

View File

@@ -18,6 +18,8 @@
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.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@@ -32,7 +34,6 @@ import org.bukkit.inventory.PlayerInventory;
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 org.bukkit.scheduler.BukkitRunnable;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@@ -60,13 +61,7 @@ public class BlocksMined implements Listener {
if (block.getType() == Material.CHEST) { if (block.getType() == Material.CHEST) {
toolStats.playerInteract.openedChests.put(block, player); toolStats.playerInteract.openedChests.put(block, player);
BukkitRunnable runnable = new BukkitRunnable() { Bukkit.getGlobalRegionScheduler().runDelayed(toolStats, scheduledTask -> toolStats.playerInteract.openedChests.remove(block), 20);
@Override
public void run() {
toolStats.playerInteract.openedChests.remove(block);
}
};
toolStats.scheduleGlobal(runnable, 20);
} }
// only check certain items // only check certain items
@@ -110,13 +105,13 @@ public class BlocksMined implements Listener {
if (toolStats.configTools.checkConfig(playerTool.getType(), "blocks-mined")) { if (toolStats.configTools.checkConfig(playerTool.getType(), "blocks-mined")) {
String oldBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined); String oldBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined);
String newBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined + 1); String newBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined + 1);
String oldLine = toolStats.configTools.formatLore("blocks-mined", "{blocks}", oldBlocksMinedFormatted); Component oldLine = toolStats.configTools.formatLore("blocks-mined", "{blocks}", oldBlocksMinedFormatted);
String newLine = toolStats.configTools.formatLore("blocks-mined", "{blocks}", newBlocksMinedFormatted); Component newLine = toolStats.configTools.formatLore("blocks-mined", "{blocks}", newBlocksMinedFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
playerTool.setItemMeta(meta); playerTool.setItemMeta(meta);
} }
@@ -151,13 +146,13 @@ public class BlocksMined implements Listener {
if (toolStats.configTools.checkConfig(playerTool.getType(), "blocks-mined")) { if (toolStats.configTools.checkConfig(playerTool.getType(), "blocks-mined")) {
String oldCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined); String oldCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined);
String newCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined + 1); String newCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined + 1);
String oldLine = toolStats.configTools.formatLore("crops-harvested", "{crops}", oldCropsMinedFormatted); Component oldLine = toolStats.configTools.formatLore("crops-harvested", "{crops}", oldCropsMinedFormatted);
String newLine = toolStats.configTools.formatLore("crops-harvested", "{crops}", newCropsMinedFormatted); Component newLine = toolStats.configTools.formatLore("crops-harvested", "{crops}", newCropsMinedFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
playerTool.setItemMeta(meta); playerTool.setItemMeta(meta);
} }

View File

@@ -18,6 +18,7 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
@@ -31,7 +32,6 @@ 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 org.bukkit.scheduler.BukkitRunnable;
public class ChunkPopulate implements Listener { public class ChunkPopulate implements Listener {
@@ -49,34 +49,30 @@ public class ChunkPopulate implements Listener {
if (event.getChunk().getWorld().getEnvironment() != World.Environment.THE_END) { if (event.getChunk().getWorld().getEnvironment() != World.Environment.THE_END) {
return; return;
} }
World world = event.getChunk().getWorld();
// this is delayed because entities are not loaded instantly // this is delayed because entities are not loaded instantly
// we just check 1 second later // we just check 1 second later
Chunk chunk = event.getChunk(); Chunk chunk = event.getChunk();
BukkitRunnable runnable = new BukkitRunnable() { Bukkit.getRegionScheduler().runDelayed(toolStats, world, chunk.getX(), chunk.getZ(), scheduledTask -> {
@Override for (Entity entity : chunk.getEntities()) {
public void run() { // if there is a new item frame
for (Entity entity : chunk.getEntities()) { if (!(entity instanceof ItemFrame itemFrame)) {
// if there is a new item frame continue;
if (!(entity instanceof ItemFrame)) { }
// if the item frame has an elytra
if (itemFrame.getItem().getType() == Material.ELYTRA) {
ItemStack elytraCopy = itemFrame.getItem();
ItemMeta meta = elytraCopy.getItemMeta();
if (meta == null) {
continue; continue;
} }
ItemFrame itemFrame = (ItemFrame) entity; // add the new tag so we know it's new
// if the item frame has an elytra PersistentDataContainer container = meta.getPersistentDataContainer();
if (itemFrame.getItem().getType() == Material.ELYTRA) { container.set(toolStats.newElytra, PersistentDataType.INTEGER, 1);
ItemStack elytraCopy = itemFrame.getItem(); elytraCopy.setItemMeta(meta);
ItemMeta meta = elytraCopy.getItemMeta(); itemFrame.setItem(elytraCopy);
if (meta == null) {
continue;
}
// add the new tag so we know it's new
PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(toolStats.newElytra, PersistentDataType.INTEGER, 1);
elytraCopy.setItemMeta(meta);
itemFrame.setItem(elytraCopy);
}
} }
} }
}; }, 20);
toolStats.scheduleRegion(runnable, chunk.getWorld(), chunk, 20);
} }
} }

View File

@@ -17,9 +17,11 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.ChatColor; import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -27,12 +29,17 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
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.*; import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
public class CraftItem implements Listener { public class CraftItem implements Listener {
@@ -51,26 +58,51 @@ public class CraftItem implements Listener {
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
ItemStack itemStack = event.getCurrentItem(); ItemStack craftedItem = event.getCurrentItem();
if (itemStack == null || itemStack.getType() == Material.AIR) { if (craftedItem == null || craftedItem.getType() == Material.AIR) {
return; return;
} }
Material craftedMaterial = craftedItem.getType();
// only check certain items // only check certain items
if (!toolStats.itemChecker.isValidItem(itemStack.getType())) { if (!toolStats.itemChecker.isValidItem(craftedMaterial)) {
return; return;
} }
// if the player shift clicks, send them this warning // if the player shift clicks
if (event.isShiftClick()) { if (event.isShiftClick()) {
String configMessage = toolStats.config.getString("messages.shift-click-warning.crafting"); // store the player inventory before they craft the items
if (configMessage != null) { ItemStack[] beforeCraft = player.getInventory().getContents();
if (!configMessage.isEmpty()) { // run a tick after to see the changes
event.getWhoClicked().sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage)); player.getScheduler().runDelayed(toolStats, scheduledTask -> {
// get their inventory after the craft
ItemStack[] afterCraft = player.getInventory().getContents();
for (int i = 0; i < afterCraft.length; i++) {
ItemStack newSlotItem = afterCraft[i];
ItemStack oldSlotItem = beforeCraft[i];
// if this slot is empty after crafting, skip it
if (newSlotItem == null) {
continue;
}
// if the item matches what we crafted
if (newSlotItem.getType() == craftedMaterial) {
// if the slot was empty before we crafted, this means we just made it
if (oldSlotItem == null) {
// add the lore
ItemStack newItem = addLore(newSlotItem, player);
if (newItem != null) {
player.getInventory().setItem(i, newItem);
}
}
}
} }
} }, null, 1);
return;
} }
// test the item before setting it
ItemStack newItem = addLore(itemStack, player); // the player did not shift click
ItemStack newItem = addLore(craftedItem, player);
if (newItem != null) { if (newItem != null) {
// set the result // set the result
event.setCurrentItem(newItem); event.setCurrentItem(newItem);
@@ -113,30 +145,30 @@ public class CraftItem implements Listener {
container.set(toolStats.genericOwner, new UUIDDataType(), owner.getUniqueId()); container.set(toolStats.genericOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 0); container.set(toolStats.originType, PersistentDataType.INTEGER, 0);
List<String> lore; List<Component> lore;
// get the current lore the item // get the current lore the item
if (meta.hasLore()) { if (meta.hasLore()) {
lore = meta.getLore(); lore = meta.lore();
} else { } else {
lore = new ArrayList<>(); lore = new ArrayList<>();
} }
// do we add the lore based on the config? // do we add the lore based on the config?
if (toolStats.configTools.checkConfig(itemStack.getType(), "created-date")) { if (toolStats.configTools.checkConfig(itemStack.getType(), "created-date")) {
String date = toolStats.numberFormat.formatDate(finalDate); String date = toolStats.numberFormat.formatDate(finalDate);
String newLine = toolStats.configTools.formatLore("created.created-on", "{date}", date); Component newLine = toolStats.configTools.formatLore("created.created-on", "{date}", date);
if (newLine == null) { if (newLine == null) {
return null; return null;
} }
lore.add(newLine); lore.add(newLine);
meta.setLore(lore); meta.lore(lore);
} }
if (toolStats.configTools.checkConfig(itemStack.getType(), "created-by")) { if (toolStats.configTools.checkConfig(itemStack.getType(), "created-by")) {
String newLine = toolStats.configTools.formatLore("created.created-by", "{player}", owner.getName()); Component newLine = toolStats.configTools.formatLore("created.created-by", "{player}", owner.getName());
if (newLine == null) { if (newLine == null) {
return null; return null;
} }
lore.add(newLine); lore.add(newLine);
meta.setLore(lore); meta.lore(lore);
} }
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -104,8 +105,8 @@ public class CreativeEvent implements Listener {
if (toolStats.configTools.checkConfig(newSpawnedItem.getType(), "spawned-in")) { if (toolStats.configTools.checkConfig(newSpawnedItem.getType(), "spawned-in")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate); String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate); List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore); meta.lore(newLore);
} }
newSpawnedItem.setItemMeta(meta); newSpawnedItem.setItemMeta(meta);

View File

@@ -18,6 +18,7 @@
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.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.*; import org.bukkit.entity.*;
@@ -51,10 +52,9 @@ public class EntityDamage implements Listener {
return; return;
} }
if (!(event.getEntity() instanceof LivingEntity)) { if (!(event.getEntity() instanceof LivingEntity mobBeingAttacked)) {
return; return;
} }
LivingEntity mobBeingAttacked = (LivingEntity) event.getEntity();
// ignore void and /kill damage // ignore void and /kill damage
EntityDamageEvent.DamageCause cause = event.getCause(); EntityDamageEvent.DamageCause cause = event.getCause();
@@ -65,8 +65,7 @@ public class EntityDamage implements Listener {
// mob is going to die // mob is going to die
if (mobBeingAttacked.getHealth() - event.getFinalDamage() <= 0) { if (mobBeingAttacked.getHealth() - event.getFinalDamage() <= 0) {
// a player is killing something // a player is killing something
if (event.getDamager() instanceof Player) { if (event.getDamager() instanceof Player attackingPlayer) {
Player attackingPlayer = (Player) event.getDamager();
if (attackingPlayer.getGameMode() == GameMode.CREATIVE || attackingPlayer.getGameMode() == GameMode.SPECTATOR) { if (attackingPlayer.getGameMode() == GameMode.CREATIVE || attackingPlayer.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
@@ -86,45 +85,38 @@ public class EntityDamage implements Listener {
trackedMobs.add(mobBeingAttacked.getUniqueId()); trackedMobs.add(mobBeingAttacked.getUniqueId());
} }
// trident is being thrown at something // trident is being thrown at something
if (event.getDamager() instanceof Trident) { if (event.getDamager() instanceof Trident trident) {
Trident trident = (Trident) event.getDamager();
ItemStack newTrident; ItemStack newTrident;
// trident is killing player // trident is killing player
if (mobBeingAttacked instanceof Player) { if (mobBeingAttacked instanceof Player) {
newTrident = tridentPlayerKills(trident.getItem()); newTrident = tridentPlayerKills(trident.getItemStack());
} else { } else {
// trident is killing a mob // trident is killing a mob
newTrident = tridentMobKills(trident.getItem()); newTrident = tridentMobKills(trident.getItemStack());
trackedMobs.add(mobBeingAttacked.getUniqueId()); trackedMobs.add(mobBeingAttacked.getUniqueId());
} }
if (newTrident != null) { if (newTrident != null) {
trident.setItem(newTrident); trident.setItemStack(newTrident);
} }
} }
// arrow is being shot // arrow is being shot
if (event.getDamager() instanceof Arrow) { if (event.getDamager() instanceof Arrow arrow) {
Arrow arrow = (Arrow) event.getDamager();
// if the shooter is a player // if the shooter is a player
if (arrow.getShooter() instanceof Player) { if (arrow.getShooter() instanceof Player shootingPlayer) {
Player shootingPlayer = (Player) arrow.getShooter();
if (shootingPlayer.getGameMode() == GameMode.CREATIVE || shootingPlayer.getGameMode() == GameMode.SPECTATOR) { if (shootingPlayer.getGameMode() == GameMode.CREATIVE || shootingPlayer.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
PlayerInventory inventory = shootingPlayer.getInventory(); PlayerInventory inventory = shootingPlayer.getInventory();
boolean isMainHand = inventory.getItemInMainHand().getType() == Material.BOW || inventory.getItemInMainHand().getType() == Material.CROSSBOW; ItemStack main = inventory.getItemInMainHand();
boolean isOffHand = inventory.getItemInOffHand().getType() == Material.BOW || inventory.getItemInMainHand().getType() == Material.CROSSBOW; ItemStack offHand = inventory.getItemInOffHand();
boolean isMain = main.getType() == Material.BOW || main.getType() == Material.CROSSBOW;
boolean isOffHand = offHand.getType() == Material.BOW || offHand.getType() == Material.CROSSBOW;
ItemStack heldBow = null; ItemStack heldBow = null;
if (isMainHand) { if (isMain) {
heldBow = inventory.getItemInMainHand(); heldBow = main;
} }
if (isOffHand) { if (isOffHand) {
heldBow = inventory.getItemInOffHand(); heldBow = offHand;
}
// if the player is holding a bow in both hands
// default to main hand since that takes priority
if (isMainHand && isOffHand) {
heldBow = inventory.getItemInMainHand();
} }
// player swapped // player swapped
@@ -143,8 +135,7 @@ public class EntityDamage implements Listener {
} }
} }
// player is taken damage but not being killed // player is taken damage but not being killed
if (mobBeingAttacked instanceof Player) { if (mobBeingAttacked instanceof Player playerTakingDamage) {
Player playerTakingDamage = (Player) mobBeingAttacked;
if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) { if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
@@ -161,7 +152,7 @@ public class EntityDamage implements Listener {
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onDamage(EntityDamageEvent event) { public void onDamage(EntityDamageEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) { if (!(event.getEntity() instanceof LivingEntity mobBeingAttacked)) {
return; return;
} }
@@ -171,10 +162,8 @@ public class EntityDamage implements Listener {
return; return;
} }
LivingEntity mobBeingAttacked = (LivingEntity) event.getEntity();
// player is taken damage but not being killed // player is taken damage but not being killed
if (mobBeingAttacked instanceof Player) { if (mobBeingAttacked instanceof Player playerTakingDamage) {
Player playerTakingDamage = (Player) mobBeingAttacked;
if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) { if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
@@ -191,7 +180,7 @@ public class EntityDamage implements Listener {
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onDamage(EntityDamageByBlockEvent event) { public void onDamage(EntityDamageByBlockEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) { if (!(event.getEntity() instanceof LivingEntity mobBeingAttacked)) {
return; return;
} }
@@ -201,10 +190,8 @@ public class EntityDamage implements Listener {
return; return;
} }
LivingEntity mobBeingAttacked = (LivingEntity) event.getEntity();
// player is taken damage but not being killed // player is taken damage but not being killed
if (mobBeingAttacked instanceof Player) { if (mobBeingAttacked instanceof Player playerTakingDamage) {
Player playerTakingDamage = (Player) mobBeingAttacked;
if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) { if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
@@ -247,13 +234,13 @@ public class EntityDamage implements Listener {
if (toolStats.configTools.checkConfig(itemStack.getType(), "player-kills")) { if (toolStats.configTools.checkConfig(itemStack.getType(), "player-kills")) {
String oldPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills); String oldPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
String newPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills + 1); String newPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills + 1);
String oldLine = toolStats.configTools.formatLore("kills.player", "{kills}", oldPlayerKillsFormatted); Component oldLine = toolStats.configTools.formatLore("kills.player", "{kills}", oldPlayerKillsFormatted);
String newLine = toolStats.configTools.formatLore("kills.player", "{kills}", newPlayerKillsFormatted); Component newLine = toolStats.configTools.formatLore("kills.player", "{kills}", newPlayerKillsFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);
} }
@@ -286,13 +273,13 @@ public class EntityDamage implements Listener {
if (toolStats.configTools.checkConfig(itemStack.getType(), "mob-kills")) { if (toolStats.configTools.checkConfig(itemStack.getType(), "mob-kills")) {
String oldMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills); String oldMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
String newMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills + 1); String newMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills + 1);
String oldLine = toolStats.configTools.formatLore("kills.mob", "{kills}", oldMobKillsFormatted); Component oldLine = toolStats.configTools.formatLore("kills.mob", "{kills}", oldMobKillsFormatted);
String newLine = toolStats.configTools.formatLore("kills.mob", "{kills}", newMobKillsFormatted); Component newLine = toolStats.configTools.formatLore("kills.mob", "{kills}", newMobKillsFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);
} }
@@ -324,19 +311,18 @@ public class EntityDamage implements Listener {
toolStats.logger.warning(itemStack + " does not have valid damage-taken set! Resting to zero. This should NEVER happen."); toolStats.logger.warning(itemStack + " does not have valid damage-taken set! Resting to zero. This should NEVER happen.");
} }
damageTaken = damageTaken + damage;
container.set(toolStats.armorDamage, PersistentDataType.DOUBLE, damageTaken + damage); container.set(toolStats.armorDamage, PersistentDataType.DOUBLE, damageTaken + damage);
if (toolStats.config.getBoolean("enabled.armor-damage")) { if (toolStats.config.getBoolean("enabled.armor-damage")) {
String oldDamageFormatted = toolStats.numberFormat.formatDouble(damageTaken); String oldDamageFormatted = toolStats.numberFormat.formatDouble(damageTaken);
String newDamageFormatted = toolStats.numberFormat.formatDouble(damageTaken + damage); String newDamageFormatted = toolStats.numberFormat.formatDouble(damageTaken + damage);
String oldLine = toolStats.configTools.formatLore("damage-taken", "{damage}", oldDamageFormatted); Component oldLine = toolStats.configTools.formatLore("damage-taken", "{damage}", oldDamageFormatted);
String newLine = toolStats.configTools.formatLore("damage-taken", "{damage}", newDamageFormatted); Component newLine = toolStats.configTools.formatLore("damage-taken", "{damage}", newDamageFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);
} }
@@ -368,15 +354,15 @@ public class EntityDamage implements Listener {
// do we add the lore based on the config? // do we add the lore based on the config?
if (toolStats.configTools.checkConfig(newTrident.getType(), "mob-kills")) { if (toolStats.configTools.checkConfig(newTrident.getType(), "mob-kills")) {
String oldMobKillsFormatted = toolStats.numberFormat.formatDouble(mobKills); String oldMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
String newMobKillsFormatted = toolStats.numberFormat.formatDouble(mobKills + 1); String newMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills + 1);
String oldLine = toolStats.configTools.formatLore("kills.mob", "{kills}", oldMobKillsFormatted); Component oldLine = toolStats.configTools.formatLore("kills.mob", "{kills}", oldMobKillsFormatted);
String newLine = toolStats.configTools.formatLore("kills.mob", "{kills}", newMobKillsFormatted); Component newLine = toolStats.configTools.formatLore("kills.mob", "{kills}", newMobKillsFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
newTrident.setItemMeta(meta); newTrident.setItemMeta(meta);
return newTrident; return newTrident;
@@ -409,15 +395,15 @@ public class EntityDamage implements Listener {
// do we add the lore based on the config? // do we add the lore based on the config?
if (toolStats.configTools.checkConfig(newTrident.getType(), "player-kills")) { if (toolStats.configTools.checkConfig(newTrident.getType(), "player-kills")) {
String oldPlayerKillsFormatted = toolStats.numberFormat.formatDouble(playerKills); String oldPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
String newPlayerKillsFormatted = toolStats.numberFormat.formatDouble(playerKills + 1); String newPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills + 1);
String oldLine = toolStats.configTools.formatLore("kills.player", "{kills}", oldPlayerKillsFormatted); Component oldLine = toolStats.configTools.formatLore("kills.player", "{kills}", oldPlayerKillsFormatted);
String newLine = toolStats.configTools.formatLore("kills.player", "{kills}", newPlayerKillsFormatted); Component newLine = toolStats.configTools.formatLore("kills.player", "{kills}", newPlayerKillsFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return null; return null;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
newTrident.setItemMeta(meta); newTrident.setItemMeta(meta);
return newTrident; return newTrident;

View File

@@ -18,6 +18,7 @@
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.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -29,7 +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.*; import java.util.List;
import java.util.UUID;
public class EntityDeath implements Listener { public class EntityDeath implements Listener {
@@ -53,13 +55,13 @@ public class EntityDeath implements Listener {
ItemMeta droppedItemMeta = droppedItem.getItemMeta(); ItemMeta droppedItemMeta = droppedItem.getItemMeta();
if (droppedItemMeta != null) { if (droppedItemMeta != null) {
PersistentDataContainer container = droppedItemMeta.getPersistentDataContainer(); PersistentDataContainer container = droppedItemMeta.getPersistentDataContainer();
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) { if (container.has(toolStats.originType, PersistentDataType.INTEGER)) {
continue; // ignore any items that have our tags continue; // ignore any items that have our tags
} }
} }
if (toolStats.itemChecker.isValidItem(droppedItem.getType())) { if (toolStats.itemChecker.isValidItem(droppedItem.getType())) {
ItemStack newItem = addLore(droppedItem, livingEntity.getName()); ItemStack newItem = addLore(droppedItem, livingEntity);
if (newItem != null) { if (newItem != null) {
event.getDrops().set(i, newItem); event.getDrops().set(i, newItem);
} }
@@ -73,9 +75,9 @@ public class EntityDeath implements Listener {
* Adds "drop by" tag to item. * Adds "drop by" tag to item.
* *
* @param oldItem The item to add lore to. * @param oldItem The item to add lore to.
* @param mob The mob or player name. * @param entity The mob dying.
*/ */
private ItemStack addLore(ItemStack oldItem, String mob) { private ItemStack addLore(ItemStack oldItem, LivingEntity entity) {
ItemStack newItem = oldItem.clone(); ItemStack newItem = oldItem.clone();
ItemMeta meta = newItem.getItemMeta(); ItemMeta meta = newItem.getItemMeta();
if (meta == null) { if (meta == null) {
@@ -86,9 +88,13 @@ public class EntityDeath implements Listener {
container.set(toolStats.originType, PersistentDataType.INTEGER, 1); container.set(toolStats.originType, PersistentDataType.INTEGER, 1);
if (toolStats.config.getBoolean("enabled.dropped-by")) { if (toolStats.config.getBoolean("enabled.dropped-by")) {
String newLine = toolStats.configTools.formatLore("dropped-by", "{name}", mob); String mobName = toolStats.config.getString("messages.mob." + entity.getType());
List<String> newLore = toolStats.itemLore.addItemLore(meta, newLine); if (mobName == null) {
meta.setLore(newLore); mobName = entity.getName();
}
Component newLine = toolStats.configTools.formatLore("dropped-by", "{name}", mobName);
List<Component> newLore = toolStats.itemLore.addItemLore(meta, newLine);
meta.lore(newLore);
} }
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@@ -76,8 +77,7 @@ public class GenerateLoot implements Listener {
Player player = toolStats.playerInteract.openedChests.get(openedChest); Player player = toolStats.playerInteract.openedChests.get(openedChest);
setLoot(event.getLoot(), player); setLoot(event.getLoot(), player);
} }
if (inventoryHolder instanceof StorageMinecart) { if (inventoryHolder instanceof StorageMinecart mineCart) {
StorageMinecart mineCart = (StorageMinecart) inventoryHolder;
if (toolStats.playerInteract.openedMineCarts.containsKey(mineCart)) { if (toolStats.playerInteract.openedMineCarts.containsKey(mineCart)) {
Player player = toolStats.playerInteract.openedMineCarts.get(mineCart); Player player = toolStats.playerInteract.openedMineCarts.get(mineCart);
setLoot(event.getLoot(), player); setLoot(event.getLoot(), player);
@@ -118,8 +118,8 @@ public class GenerateLoot implements Listener {
if (toolStats.configTools.checkConfig(newItem.getType(), "looted-tag")) { if (toolStats.configTools.checkConfig(newItem.getType(), "looted-tag")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate); String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate); List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore); meta.lore(newLore);
} }
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@@ -28,7 +29,6 @@ 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 org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID; import java.util.UUID;
@@ -83,14 +83,8 @@ public class InventoryOpen implements Listener {
} }
} }
ItemMeta clone = itemMeta.clone(); ItemMeta clone = itemMeta.clone();
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
itemStack.setItemMeta(clone);
}
};
if (location != null) { if (location != null) {
toolStats.scheduleRegion(runnable, location.getWorld(), location.getChunk(), 1); Bukkit.getRegionScheduler().runDelayed(toolStats, location, scheduledTask -> itemStack.setItemMeta(clone), 1);
} }
} }
} }

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.*; import org.bukkit.entity.*;
@@ -48,13 +49,12 @@ public class PickupItem implements Listener {
return; return;
} }
Entity entity = event.getEntity(); Entity entity = event.getEntity();
if (entity instanceof Player) { if (entity instanceof Player player) {
Player player = (Player) entity;
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
Item item = event.getItem(); Item item = event.getItem();
if (item.getType() == EntityType.DROPPED_ITEM) { if (item.getType() == EntityType.ITEM) {
ItemStack itemStack = event.getItem().getItemStack(); ItemStack itemStack = event.getItem().getItemStack();
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {
@@ -103,8 +103,8 @@ public class PickupItem implements Listener {
if (toolStats.config.getBoolean("enabled.elytra-tag")) { if (toolStats.config.getBoolean("enabled.elytra-tag")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate); String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate); List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore); meta.lore(newLore);
} }
finalItem.setItemMeta(meta); finalItem.setItemMeta(meta);
return finalItem; return finalItem;

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Item; import org.bukkit.entity.Item;
@@ -130,13 +131,13 @@ public class PlayerFish implements Listener {
if (toolStats.config.getBoolean("enabled.fish-caught")) { if (toolStats.config.getBoolean("enabled.fish-caught")) {
String oldFishFormatted = toolStats.numberFormat.formatInt(fishCaught); String oldFishFormatted = toolStats.numberFormat.formatInt(fishCaught);
String newFishFormatted = toolStats.numberFormat.formatInt(fishCaught + 1); String newFishFormatted = toolStats.numberFormat.formatInt(fishCaught + 1);
String oldLine = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", oldFishFormatted); Component oldLine = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", oldFishFormatted);
String newLine = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", newFishFormatted); Component newLine = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", newFishFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
fishingRod.setItemMeta(meta); fishingRod.setItemMeta(meta);
} }
@@ -171,8 +172,8 @@ public class PlayerFish implements Listener {
if (toolStats.configTools.checkConfig(newItem.getType(), "fished-tag")) { if (toolStats.configTools.checkConfig(newItem.getType(), "fished-tag")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate); String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate); List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore); meta.lore(newLore);
} }
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;

View File

@@ -18,6 +18,7 @@
package lol.hyper.toolstats.events; package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@@ -30,7 +31,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -64,13 +64,7 @@ public class PlayerInteract implements Listener {
// store when a player opens a chest // store when a player opens a chest
if (block.getType() != Material.AIR && block.getType() == Material.CHEST) { if (block.getType() != Material.AIR && block.getType() == Material.CHEST) {
openedChests.put(block, player); openedChests.put(block, player);
BukkitRunnable runnable = new BukkitRunnable() { Bukkit.getGlobalRegionScheduler().runDelayed(toolStats, scheduledTask -> openedChests.remove(block), 20);
@Override
public void run() {
openedChests.remove(block);
}
};
toolStats.scheduleGlobal(runnable, 20);
} }
} }
@@ -82,16 +76,10 @@ public class PlayerInteract implements Listener {
return; return;
} }
// store when a player opens a minecart // store when a player opens a minecart
if (clicked.getType() == EntityType.MINECART_CHEST) { if (clicked.getType() == EntityType.CHEST_MINECART) {
StorageMinecart storageMinecart = (StorageMinecart) clicked; StorageMinecart storageMinecart = (StorageMinecart) clicked;
openedMineCarts.put(storageMinecart, player); openedMineCarts.put(storageMinecart, player);
BukkitRunnable runnable = new BukkitRunnable() { Bukkit.getGlobalRegionScheduler().runDelayed(toolStats, scheduledTask -> openedMineCarts.remove(storageMinecart), 20);
@Override
public void run() {
openedMineCarts.remove(storageMinecart);
}
};
toolStats.scheduleGlobal(runnable, 20);
} }
} }
} }

View File

@@ -28,7 +28,6 @@ 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 org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID; import java.util.UUID;
@@ -77,13 +76,7 @@ public class PlayerJoin implements Listener {
container.set(toolStats.hash, PersistentDataType.STRING, hash); container.set(toolStats.hash, PersistentDataType.STRING, hash);
} }
ItemMeta clone = itemMeta.clone(); ItemMeta clone = itemMeta.clone();
BukkitRunnable runnable = new BukkitRunnable() { player.getScheduler().runDelayed(toolStats, scheduledTask -> itemStack.setItemMeta(clone), null, 1);
@Override
public void run() {
itemStack.setItemMeta(clone);
}
};
toolStats.scheduleEntity(runnable, player, 1);
} }
} }
} }

View File

@@ -18,6 +18,7 @@
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.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -86,20 +87,21 @@ public class PlayerMove implements Listener {
} }
// get the duration of the flight // get the duration of the flight
long duration = (System.currentTimeMillis() - startTime) + flightTime; long duration = (System.currentTimeMillis() - startTime);
double newDuration = flightTime + duration;
container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime + duration); container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime + duration);
// do we add the lore based on the config? // do we add the lore based on the config?
if (toolStats.config.getBoolean("enabled.flight-time")) { if (toolStats.config.getBoolean("enabled.flight-time")) {
String oldFlightFormatted = toolStats.numberFormat.formatDouble((double) flightTime / 1000); String oldFlightFormatted = toolStats.numberFormat.formatDouble((double) flightTime / 1000);
String newFlightFormatted = toolStats.numberFormat.formatDouble((double) (flightTime + duration) / 1000); String newFlightFormatted = toolStats.numberFormat.formatDouble(newDuration / 1000);
String oldLine = toolStats.configTools.formatLore("flight-time", "{time}", oldFlightFormatted); Component oldLine = toolStats.configTools.formatLore("flight-time", "{time}", oldFlightFormatted);
String newLine = toolStats.configTools.formatLore("flight-time", "{time}", newFlightFormatted); Component newLine = toolStats.configTools.formatLore("flight-time", "{time}", newFlightFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
chest.setItemMeta(meta); chest.setItemMeta(meta);
} }

View File

@@ -18,6 +18,7 @@
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.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@@ -54,45 +55,43 @@ public class SheepShear implements Listener {
return; return;
} }
Entity entity = event.getRightClicked(); Entity entity = event.getRightClicked();
if (!(entity instanceof Sheep)) { if (!(entity instanceof Sheep sheep)) {
return; return;
} }
ItemStack shears = getShears(player); ItemStack heldShears = getShears(player.getInventory());
// player swapped items? // player swapped or we can't get the shears
if (shears == null) { if (heldShears == null) {
return; return;
} }
Sheep sheep = (Sheep) entity;
// make sure the sheep is not sheared // make sure the sheep is not sheared
if (sheep.isSheared()) { if (sheep.isSheared()) {
return; return;
} }
// update the stats // update the stats
ItemStack finalShears = shears; addLore(heldShears);
addLore(finalShears);
} }
private static @Nullable ItemStack getShears(Player player) { private static @Nullable ItemStack getShears(PlayerInventory inventory) {
PlayerInventory inventory = player.getInventory(); ItemStack main = inventory.getItemInMainHand();
boolean isMainHand = inventory.getItemInMainHand().getType() == Material.SHEARS; ItemStack offHand = inventory.getItemInOffHand();
boolean isOffHand = inventory.getItemInOffHand().getType() == Material.SHEARS;
ItemStack shears = null; boolean isMain = main.getType() == Material.SHEARS;
if (isMainHand) { boolean isOffHand = offHand.getType() == Material.SHEARS;
shears = inventory.getItemInMainHand();
// if the player is holding shears in their main hand, use that one
// if the shears are in their offhand instead, use that one after checking main hand
// Minecraft prioritizes main hand if the player holds in both hands
if (isMain) {
return main;
} }
if (isOffHand) { if (isOffHand) {
shears = inventory.getItemInOffHand(); return offHand;
} }
// if the player is hold shears in both hands return null;
// default to main hand since that takes priority
if (isMainHand && isOffHand) {
shears = inventory.getItemInMainHand();
}
return shears;
} }
/** /**
@@ -122,13 +121,13 @@ public class SheepShear implements Listener {
if (toolStats.config.getBoolean("enabled.sheep-sheared")) { if (toolStats.config.getBoolean("enabled.sheep-sheared")) {
String oldSheepFormatted = toolStats.numberFormat.formatInt(sheepSheared); String oldSheepFormatted = toolStats.numberFormat.formatInt(sheepSheared);
String newSheepFormatted = toolStats.numberFormat.formatInt(sheepSheared + 1); String newSheepFormatted = toolStats.numberFormat.formatInt(sheepSheared + 1);
String oldLine = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", oldSheepFormatted); Component oldLine = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", oldSheepFormatted);
String newLine = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", newSheepFormatted); Component newLine = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", newSheepFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
newShears.setItemMeta(meta); newShears.setItemMeta(meta);
} }

View File

@@ -18,6 +18,7 @@
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.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@@ -47,19 +48,16 @@ public class ShootBow implements Listener {
public void onShoot(EntityShootBowEvent event) { public void onShoot(EntityShootBowEvent event) {
Entity shooter = event.getEntity(); Entity shooter = event.getEntity();
// only listen for players // only listen for players
if (!(shooter instanceof Player)) { if (!(shooter instanceof Player player)) {
return; return;
} }
Player player = (Player) shooter;
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.ADVENTURE) { if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.ADVENTURE) {
return; return;
} }
PlayerInventory inventory = player.getInventory(); ItemStack heldBow = getBow(player.getInventory());
ItemStack heldBow = getBow(inventory); // player swapped or we can't get the bow
// player swapped
if (heldBow == null) { if (heldBow == null) {
return; return;
} }
@@ -68,22 +66,23 @@ public class ShootBow implements Listener {
} }
private static @Nullable ItemStack getBow(PlayerInventory inventory) { private static @Nullable ItemStack getBow(PlayerInventory inventory) {
boolean isMainHand = inventory.getItemInMainHand().getType() == Material.BOW || inventory.getItemInMainHand().getType() == Material.CROSSBOW; ItemStack main = inventory.getItemInMainHand();
boolean isOffHand = inventory.getItemInOffHand().getType() == Material.BOW || inventory.getItemInMainHand().getType() == Material.CROSSBOW; ItemStack offHand = inventory.getItemInOffHand();
ItemStack heldBow = null;
if (isMainHand) { boolean isMain = main.getType() == Material.BOW || main.getType() == Material.CROSSBOW;
heldBow = inventory.getItemInMainHand(); boolean isOffHand = offHand.getType() == Material.BOW || offHand.getType() == Material.CROSSBOW;
// if the player is holding a bow in their main hand, use that one
// if the bow is in their offhand instead, use that one after checking main hand
// Minecraft prioritizes main hand if the player holds in both hands
if (isMain) {
return main;
} }
if (isOffHand) { if (isOffHand) {
heldBow = inventory.getItemInOffHand(); return offHand;
} }
// if the player is holding a bow in both hands return null;
// default to main hand since that takes priority
if (isMainHand && isOffHand) {
heldBow = inventory.getItemInMainHand();
}
return heldBow;
} }
private void updateArrowsShot(ItemStack bow) { private void updateArrowsShot(ItemStack bow) {
@@ -111,13 +110,13 @@ public class ShootBow implements Listener {
if (toolStats.config.getBoolean("enabled.arrows-shot")) { if (toolStats.config.getBoolean("enabled.arrows-shot")) {
String oldArrowsFormatted = toolStats.numberFormat.formatInt(arrowsShot); String oldArrowsFormatted = toolStats.numberFormat.formatInt(arrowsShot);
String newArrowsFormatted = toolStats.numberFormat.formatInt(arrowsShot + 1); String newArrowsFormatted = toolStats.numberFormat.formatInt(arrowsShot + 1);
String oldLine = toolStats.configTools.formatLore("arrows-shot", "{arrows}", oldArrowsFormatted); Component oldLine = toolStats.configTools.formatLore("arrows-shot", "{arrows}", oldArrowsFormatted);
String newLine = toolStats.configTools.formatLore("arrows-shot", "{arrows}", newArrowsFormatted); Component newLine = toolStats.configTools.formatLore("arrows-shot", "{arrows}", newArrowsFormatted);
if (oldLine == null || newLine == null) { if (oldLine == null || newLine == null) {
return; return;
} }
List<String> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine); List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.setLore(newLore); meta.lore(newLore);
} }
bow.setItemMeta(meta); bow.setItemMeta(meta);
} }

View File

@@ -19,8 +19,9 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType; import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.ChatColor; import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
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;
@@ -51,35 +52,62 @@ public class VillagerTrade implements Listener {
return; return;
} }
Inventory inventory = event.getClickedInventory(); Inventory inventory = event.getClickedInventory();
if (!(event.getWhoClicked() instanceof Player)) { if (!(event.getWhoClicked() instanceof Player player)) {
return; return;
} }
Player player = (Player) event.getWhoClicked();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) {
return; return;
} }
// only check villager inventories // only check villager inventories
if (inventory instanceof MerchantInventory) { if (!(inventory instanceof MerchantInventory)) {
// only check the result slot (the item you receive) return;
if (event.getSlotType() == InventoryType.SlotType.RESULT) { }
ItemStack item = event.getCurrentItem(); // only check the result slot (the item you receive)
// only check items we want if (event.getSlotType() != InventoryType.SlotType.RESULT) {
if (!toolStats.itemChecker.isValidItem(item.getType())) { return;
return; }
} ItemStack tradedItem = event.getCurrentItem();
// if the player shift clicks, show the warning Material tradedMaterial = tradedItem.getType();
if (event.isShiftClick()) { // only check items we want
String configMessage = toolStats.config.getString("messages.shift-click-warning.trading"); if (!toolStats.itemChecker.isValidItem(tradedMaterial)) {
if (configMessage != null) { return;
player.sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage)); }
// if the player shift clicks
if (event.isShiftClick()) {
// store the player inventory before they trade the items
ItemStack[] beforeTrade = player.getInventory().getContents();
// run a tick after to see the changes
player.getScheduler().runDelayed(toolStats, scheduledTask -> {
// get their inventory after the trade
ItemStack[] afterTrade = player.getInventory().getContents();
for (int i = 0; i < afterTrade.length; i++) {
ItemStack newSlotItem = afterTrade[i];
ItemStack oldSlotItem = beforeTrade[i];
// if this slot is empty after trading, skip it
if (newSlotItem == null) {
continue;
}
// if the item matches what we traded
if (newSlotItem.getType() == tradedMaterial) {
// if the slot was empty before we traded, this means we just traded it
if (oldSlotItem == null) {
// add the lore
ItemStack newItem = addLore(newSlotItem, player);
if (newItem != null) {
player.getInventory().setItem(i, newItem);
}
}
} }
} }
ItemStack newItem = addLore(item, player); }, null, 1);
if (newItem != null) { return;
// set the new item }
inventory.setItem(event.getSlot(), newItem); ItemStack newItem = addLore(tradedItem, player);
} if (newItem != null) {
} // set the new item
inventory.setItem(event.getSlot(), newItem);
} }
} }
@@ -117,8 +145,8 @@ public class VillagerTrade implements Listener {
if (toolStats.configTools.checkConfig(newItem.getType(), "traded-tag")) { if (toolStats.configTools.checkConfig(newItem.getType(), "traded-tag")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate); String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate); List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore); meta.lore(newLore);
} }
newItem.setItemMeta(meta); newItem.setItemMeta(meta);
return newItem; return newItem;

View File

@@ -56,6 +56,7 @@ public class ItemChecker {
validItems.add(Material.FISHING_ROD); validItems.add(Material.FISHING_ROD);
validItems.add(Material.CROSSBOW); validItems.add(Material.CROSSBOW);
validItems.add(Material.ELYTRA); validItems.add(Material.ELYTRA);
validItems.add(Material.MACE);
// combine the lists // combine the lists
validItems.addAll(armorItems); validItems.addAll(armorItems);

View File

@@ -18,19 +18,18 @@
package lol.hyper.toolstats.tools; package lol.hyper.toolstats.tools;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
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.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
public class ItemLore { public class ItemLore {
private final ToolStats toolStats; private final ToolStats toolStats;
public static final Pattern COLOR_CODES = Pattern.compile("[&§]([0-9a-fk-or])");
public static final Pattern HEX_PATTERN = Pattern.compile("[&§]#([A-Fa-f0-9]{6})");
public ItemLore(ToolStats toolStats) { public ItemLore(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
@@ -44,18 +43,17 @@ public class ItemLore {
* @param newLine The new line to replace oldLine. * @param newLine The new line to replace oldLine.
* @return The item's new lore. * @return The item's new lore.
*/ */
public List<String> updateItemLore(ItemMeta itemMeta, String oldLine, String newLine) { public List<Component> updateItemLore(ItemMeta itemMeta, Component oldLine, Component newLine) {
List<String> itemLore; List<Component> itemLore;
oldLine = toolStats.configTools.removeColor(oldLine);
if (itemMeta.hasLore()) { if (itemMeta.hasLore()) {
itemLore = itemMeta.getLore(); itemLore = itemMeta.lore();
// keep track of line index // keep track of line index
// this doesn't mess the lore of existing items // this doesn't mess the lore of existing items
for (int x = 0; x < itemLore.size(); x++) { for (int x = 0; x < itemLore.size(); x++) {
// check to see if the line matches the config value String line = PlainTextComponentSerializer.plainText().serialize(itemLore.get(x));
// find the old line to update, keeping index
// this means we update this line only! // this means we update this line only!
String line = toolStats.configTools.removeColor(itemLore.get(x)); if (line.equals(PlainTextComponentSerializer.plainText().serialize(oldLine))) {
if (line.equals(oldLine)) {
itemLore.set(x, newLine); itemLore.set(x, newLine);
return itemLore; return itemLore;
} }
@@ -70,10 +68,10 @@ public class ItemLore {
return itemLore; return itemLore;
} }
public List<String> addItemLore(ItemMeta itemMeta, String newLine) { public List<Component> addItemLore(ItemMeta itemMeta, Component newLine) {
List<String> itemLore; List<Component> itemLore;
if (itemMeta.hasLore()) { if (itemMeta.hasLore()) {
itemLore = itemMeta.getLore(); itemLore = itemMeta.lore();
itemLore.add(newLine); itemLore.add(newLine);
} else { } else {
itemLore = new ArrayList<>(); itemLore = new ArrayList<>();
@@ -90,9 +88,9 @@ public class ItemLore {
* @param formattedDate The date of the ownership. * @param formattedDate The date of the ownership.
* @return The item's new lore. * @return The item's new lore.
*/ */
public List<String> addNewOwner(ItemMeta itemMeta, String playerName, String formattedDate) { public List<Component> addNewOwner(ItemMeta itemMeta, String playerName, String formattedDate) {
String dateCreatedLore; Component dateCreatedLore;
String itemOwnerLore; Component itemOwnerLore;
Integer origin = null; Integer origin = null;
PersistentDataContainer container = itemMeta.getPersistentDataContainer(); PersistentDataContainer container = itemMeta.getPersistentDataContainer();
if (container.has(toolStats.originType, PersistentDataType.INTEGER)) { if (container.has(toolStats.originType, PersistentDataType.INTEGER)) {
@@ -103,7 +101,7 @@ public class ItemLore {
if (origin == null) { if (origin == null) {
toolStats.logger.info("Unable to determine origin for item " + itemMeta.getAsString()); toolStats.logger.info("Unable to determine origin for item " + itemMeta.getAsString());
toolStats.logger.info("This IS a bug, please report this to the GitHub."); toolStats.logger.info("This IS a bug, please report this to the GitHub.");
return itemMeta.getLore(); return itemMeta.lore();
} }
// set the lore based on the origin // set the lore based on the origin
@@ -115,12 +113,12 @@ public class ItemLore {
if (dateCreatedLore == null) { if (dateCreatedLore == null) {
toolStats.logger.warning("messages.looted.looted-on is not set in your config!"); toolStats.logger.warning("messages.looted.looted-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
if (itemOwnerLore == null) { if (itemOwnerLore == null) {
toolStats.logger.warning("messages.looted.looted-by is not set in your config!"); toolStats.logger.warning("messages.looted.looted-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
break; break;
} }
@@ -131,12 +129,12 @@ public class ItemLore {
if (dateCreatedLore == null) { if (dateCreatedLore == null) {
toolStats.logger.warning("messages.traded.traded-on is not set in your config!"); toolStats.logger.warning("messages.traded.traded-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
if (itemOwnerLore == null) { if (itemOwnerLore == null) {
toolStats.logger.warning("messages.traded.traded-by is not set in your config!"); toolStats.logger.warning("messages.traded.traded-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
break; break;
} }
@@ -147,12 +145,12 @@ public class ItemLore {
if (dateCreatedLore == null) { if (dateCreatedLore == null) {
toolStats.logger.warning("messages.looted.found-on is not set in your config!"); toolStats.logger.warning("messages.looted.found-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
if (itemOwnerLore == null) { if (itemOwnerLore == null) {
toolStats.logger.warning("messages.looted.found-by is not set in your config!"); toolStats.logger.warning("messages.looted.found-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
break; break;
} }
@@ -163,12 +161,12 @@ public class ItemLore {
if (dateCreatedLore == null) { if (dateCreatedLore == null) {
toolStats.logger.warning("messages.fished.caught-on is not set in your config!"); toolStats.logger.warning("messages.fished.caught-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
if (itemOwnerLore == null) { if (itemOwnerLore == null) {
toolStats.logger.warning("messages.fished.caught-by is not set in your config!"); toolStats.logger.warning("messages.fished.caught-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
break; break;
} }
@@ -179,31 +177,31 @@ public class ItemLore {
if (dateCreatedLore == null) { if (dateCreatedLore == null) {
toolStats.logger.warning("messages.spawned-in.spawned-on is not set in your config!"); toolStats.logger.warning("messages.spawned-in.spawned-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
if (itemOwnerLore == null) { if (itemOwnerLore == null) {
toolStats.logger.warning("messages.spawned-in.spawned-by is not set in your config!"); toolStats.logger.warning("messages.spawned-in.spawned-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item."); toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore(); return itemMeta.lore();
} }
break; break;
} }
default: { default: {
toolStats.logger.warning("Origin " + origin + " was found. Data was modified OR something REALLY broke."); toolStats.logger.warning("Origin " + origin + " was found. Data was modified OR something REALLY broke.");
toolStats.logger.warning(itemMeta.getAsString()); toolStats.logger.warning(itemMeta.getAsString());
return itemMeta.getLore(); return itemMeta.lore();
} }
} }
List<String> newLore; List<Component> newLore;
if (itemMeta.hasLore()) { if (itemMeta.hasLore()) {
newLore = itemMeta.getLore(); newLore = itemMeta.lore();
} else { } else {
newLore = new ArrayList<>(); newLore = new ArrayList<>();
} }
newLore.add(dateCreatedLore.replace("{date}", formattedDate)); newLore.add(dateCreatedLore);
newLore.add(itemOwnerLore.replace("{player}", playerName)); newLore.add(itemOwnerLore);
return newLore; return newLore;
} }
} }

View File

@@ -15,23 +15,6 @@
* along with ToolStats. If not, see <https://www.gnu.org/licenses/>. * along with ToolStats. If not, see <https://www.gnu.org/licenses/>.
*/ */
/*
* 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; package lol.hyper.toolstats.tools;
import org.bukkit.persistence.PersistentDataAdapterContext; import org.bukkit.persistence.PersistentDataAdapterContext;

View File

@@ -18,15 +18,20 @@
package lol.hyper.toolstats.tools.config; package lol.hyper.toolstats.tools.config;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.ItemLore; import net.kyori.adventure.text.Component;
import org.bukkit.ChatColor; import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Material; import org.bukkit.Material;
import java.util.regex.Matcher; import java.util.regex.Matcher;
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 static final Pattern MINECRAFT_HEX_PATTERN = Pattern.compile("§x(?:§[a-fA-F0-9]){6}|§[a-fA-F0-9]");
public ConfigTools(ToolStats toolStats) { public ConfigTools(ToolStats toolStats) {
this.toolStats = toolStats; this.toolStats = toolStats;
@@ -67,43 +72,21 @@ public class ConfigTools {
itemType = itemName.substring(itemName.indexOf('_') + 1); itemType = itemName.substring(itemName.indexOf('_') + 1);
} }
switch (itemType) { return switch (itemType) {
case "pickaxe": { case "pickaxe" -> toolStats.config.getBoolean("enabled." + configName + ".pickaxe");
return toolStats.config.getBoolean("enabled." + configName + ".pickaxe"); case "sword" -> toolStats.config.getBoolean("enabled." + configName + ".sword");
} case "shovel" -> toolStats.config.getBoolean("enabled." + configName + ".shovel");
case "sword": { case "axe" -> toolStats.config.getBoolean("enabled." + configName + ".axe");
return toolStats.config.getBoolean("enabled." + configName + ".sword"); case "hoe" -> toolStats.config.getBoolean("enabled." + configName + ".hoe");
} case "shears" -> toolStats.config.getBoolean("enabled." + configName + ".shears");
case "shovel": { case "crossbow", "bow" -> toolStats.config.getBoolean("enabled." + configName + ".bow");
return toolStats.config.getBoolean("enabled." + configName + ".shovel"); case "trident" -> toolStats.config.getBoolean("enabled." + configName + ".trident");
} case "fishing-rod" -> toolStats.config.getBoolean("enabled." + configName + ".fishing-rod");
case "axe": { case "mace" -> toolStats.config.getBoolean("enabled." + configName + ".mace");
return toolStats.config.getBoolean("enabled." + configName + ".axe"); case "helmet", "chestplate", "leggings", "boots" ->
} toolStats.config.getBoolean("enabled." + configName + ".armor");
case "hoe": { default -> false;
return toolStats.config.getBoolean("enabled." + configName + ".hoe"); };
}
case "shears": {
return toolStats.config.getBoolean("enabled." + configName + ".shears");
}
case "crossbow":
case "bow": {
return toolStats.config.getBoolean("enabled." + configName + ".bow");
}
case "trident": {
return toolStats.config.getBoolean("enabled." + configName + ".trident");
}
case "fishing-rod": {
return toolStats.config.getBoolean("enabled." + configName + ".fishing-rod");
}
case "helmet":
case "chestplate":
case "leggings":
case "boots": {
return toolStats.config.getBoolean("enabled." + configName + ".armor");
}
}
return false;
} }
/** /**
@@ -114,28 +97,37 @@ public class ConfigTools {
* @param value The value to set the placeholder. * @param value The value to set the placeholder.
* @return Formatted string, null if the configName doesn't exist. * @return Formatted string, null if the configName doesn't exist.
*/ */
public String 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);
return null; return null;
} }
// if the config message is empty, don't send it
if (lore.isEmpty()) {
return null;
}
// the final component for this lore
Component component;
// set the placeholder to the value // set the placeholder to the value
lore = lore.replace(placeHolder, String.valueOf(value)); if (placeHolder != null && value != null) {
lore = lore.replace(placeHolder, String.valueOf(value));
Matcher hexMatcher = ItemLore.HEX_PATTERN.matcher(lore);
while (hexMatcher.find()) {
String hexCode = hexMatcher.group(1);
lore = lore.replaceAll(hexMatcher.group(), net.md_5.bungee.api.ChatColor.of("#" + hexCode).toString());
} }
Matcher colorMatcher = ItemLore.COLOR_CODES.matcher(lore); // if we match the old color codes, then format them as so
while (colorMatcher.find()) { Matcher hexMatcher = CONFIG_HEX_PATTERN.matcher(lore);
String colorCode = colorMatcher.group(1); Matcher colorMatcher = COLOR_CODES.matcher(lore);
lore = lore.replaceAll("&" + colorCode, ChatColor.getByChar(colorCode).toString()); if (hexMatcher.find() || colorMatcher.find()) {
component = LegacyComponentSerializer.legacyAmpersand().deserialize(lore);
} else {
// otherwise format them normally
component = Component.text(lore);
} }
return ChatColor.translateAlternateColorCodes('§', lore); return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE);
} }
/** /**
@@ -145,8 +137,9 @@ public class ConfigTools {
* @return The message without color codes. * @return The message without color codes.
*/ */
public String removeColor(String message) { public String removeColor(String message) {
message = ItemLore.COLOR_CODES.matcher(message).replaceAll(""); message = MINECRAFT_HEX_PATTERN.matcher(message).replaceAll("");
message = ItemLore.HEX_PATTERN.matcher(message).replaceAll(""); message = COLOR_CODES.matcher(message).replaceAll("");
message = CONFIG_HEX_PATTERN.matcher(message).replaceAll("");
return message; return message;
} }
} }

View File

@@ -15,28 +15,12 @@
* along with ToolStats. If not, see <https://www.gnu.org/licenses/>. * along with ToolStats. If not, see <https://www.gnu.org/licenses/>.
*/ */
/*
* 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; package lol.hyper.toolstats.tools.config;
import lol.hyper.toolstats.ToolStats; import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.config.versions.Version6; import lol.hyper.toolstats.tools.config.versions.Version6;
import lol.hyper.toolstats.tools.config.versions.Version7; import lol.hyper.toolstats.tools.config.versions.Version7;
import lol.hyper.toolstats.tools.config.versions.Version8;
public class ConfigUpdater { public class ConfigUpdater {
@@ -49,17 +33,25 @@ public class ConfigUpdater {
public void updateConfig() { public void updateConfig() {
int version = toolStats.config.getInt("config-version"); int version = toolStats.config.getInt("config-version");
// this will be a switch in the future switch(version) {
// Upgrade 5 to 6 case 5: {
if (version == 5) { // Version 5 to 6
Version6 version6 = new Version6(toolStats); Version6 version6 = new Version6(toolStats);
version6.update(); version6.update();
} break;
}
// Upgrade 6 to 7 case 6: {
if (version == 6) { // Version 6 to 7
Version7 version7 = new Version7(toolStats); Version7 version7 = new Version7(toolStats);
version7.update(); version7.update();
break;
}
case 7: {
// Version 7 to 8
Version8 version8 = new Version8(toolStats);
version8.update();
break;
}
} }
} }
} }

View File

@@ -43,7 +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-5.yml!"); toolStats.logger.severe("Unable to save config-6.yml!");
throw new RuntimeException(exception); throw new RuntimeException(exception);
} }
@@ -65,6 +65,6 @@ public class Version7 {
throw new RuntimeException(exception); throw new RuntimeException(exception);
} }
toolStats.loadConfig(); toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 7. A copy of version 5 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

@@ -0,0 +1,87 @@
/*
* 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;
import java.util.ArrayList;
import java.util.List;
public class Version8 {
private final ToolStats toolStats;
/**
* Used for updating from version 7 to 8.
*
* @param toolStats ToolStats instance.
*/
public Version8(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-7.yml");
} catch (IOException exception) {
toolStats.logger.severe("Unable to save config-7.yml!");
throw new RuntimeException(exception);
}
// we make this super verbose so that admins can see what's being added
toolStats.logger.info("Updating config.yml to version 8.");
toolStats.config.set("config-version", 8);
// Add example to setting mob names
toolStats.logger.info("Adding example for messages.mob.ZOMBIE");
toolStats.config.set("messages.mob.ZOMBIE", "Zombie");
// Add mace to enabled sections
toolStats.logger.info("Adding entry for enabled.created-by.mace");
toolStats.config.set("enabled.created-by.mace", true);
toolStats.logger.info("Adding entry for enabled.created-date.mace");
toolStats.config.set("enabled.created-date.mace", true);
toolStats.logger.info("Adding entry for enabled.player-kills.mace");
toolStats.config.set("enabled.player-kills.mace", true);
toolStats.logger.info("Adding entry for enabled.mob-kills.mace");
toolStats.config.set("enabled.mob-kills.mace", true);
List<String> mobComments = new ArrayList<>();
mobComments.add("Set display name for mobs. See: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html");
toolStats.config.setComments("messages.mob", mobComments);
// save the config and reload it
try {
toolStats.config.save("plugins" + File.separator + "ToolStats" + File.separator + "config.yml");
} catch (IOException exception) {
toolStats.logger.severe("Unable to save config.yml!");
throw new RuntimeException(exception);
}
toolStats.loadConfig();
toolStats.logger.info("Config has been updated to version 8. A copy of version 7 has been saved as config-7.yml");
}
}

View File

@@ -9,6 +9,7 @@ enabled:
shears: true shears: true
bow: true bow: true
armor: true armor: true
mace: true
# Will show time the item is created # Will show time the item is created
created-date: created-date:
pickaxe: true pickaxe: true
@@ -19,6 +20,7 @@ enabled:
shears: true shears: true
bow: true bow: true
armor: true armor: true
mace: true
# Will show "Fished by <player>" # Will show "Fished by <player>"
fished-tag: fished-tag:
pickaxe: true pickaxe: true
@@ -54,11 +56,13 @@ enabled:
axe: true axe: true
trident: true trident: true
bow: true bow: true
mace: true
mob-kills: mob-kills:
sword: true sword: true
axe: true axe: true
trident: true trident: true
bow: true bow: true
mace: true
blocks-mined: blocks-mined:
pickaxe: true pickaxe: true
shovel: true shovel: true
@@ -75,6 +79,7 @@ enabled:
shears: true shears: true
bow: true bow: true
armor: true armor: true
mace: true
fish-caught: true fish-caught: true
sheep-sheared: true sheep-sheared: true
armor-damage: true armor-damage: true
@@ -112,11 +117,9 @@ messages:
damage-taken: "&7Damage taken: &8{damage}" damage-taken: "&7Damage taken: &8{damage}"
arrows-shot: "&7Arrows shot: &8{arrows}" arrows-shot: "&7Arrows shot: &8{arrows}"
flight-time: "&7Flight time: &8{time}" flight-time: "&7Flight time: &8{time}"
# Display this message if the player shift click trades/crafts items. It's not really easy to get every single item # Set display name for mobs. See: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html
# that is crafted. The tag will only be added to the first item. If you don't want this message, simply replace them both with "" mobs:
shift-click-warning: ZOMBIE: "Zombie"
crafting: "&cCrafting items via shift clicking does not fully apply tags to each item. This is a limitation with the Bukkit API."
trading: "&cTrading items via shift clicking does not fully apply tags to each item. This is a limitation with the Bukkit API."
# Change the default formatting for dates. # Change the default formatting for dates.
# See: https://www.digitalocean.com/community/tutorials/java-simpledateformat-java-date-format # See: https://www.digitalocean.com/community/tutorials/java-simpledateformat-java-date-format
@@ -136,4 +139,4 @@ 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: true generate-hash-for-items: true
config-version: 7 config-version: 8

View File

@@ -1,9 +1,10 @@
name: ToolStats name: ToolStats
version: '${project.version}' version: '${project.version}'
main: lol.hyper.toolstats.ToolStats main: lol.hyper.toolstats.ToolStats
api-version: 1.15 api-version: 1.21
author: hyperdefined author: hyperdefined
description: Track various tool stats! description: Track various tool stats!
website: https://github.com/hyperdefined/ToolStats
folia-supported: true folia-supported: true
commands: commands:
toolstats: toolstats: