Compare commits

...

83 Commits
1.7.1 ... 1.8.6

Author SHA1 Message Date
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
hyperdefined
e9782c2985 bump to 1.8 instead 2024-09-07 15:50:27 -04:00
hyperdefined
b596310bfe redo lore replacement
Instead of partially matching the old lore, build the old lore and match it instead.
2024-09-06 17:47:07 -04:00
hyperdefined
6d1f0fe561 update config from 6 to 7 2024-08-29 00:16:22 -04:00
hyperdefined
fb0d179d37 add flight time (#62) 2024-08-29 00:10:01 -04:00
hyperdefined
e8ab578eef Update pom.xml 2024-08-28 23:23:20 -04:00
hyperdefined
57be2371e1 Merge pull request #67 from hyperdefined/dependabot/maven/net.kyori-adventure-platform-bukkit-4.3.4
Bump net.kyori:adventure-platform-bukkit from 4.3.3 to 4.3.4
2024-08-28 23:20:43 -04:00
hyperdefined
f3732a4eea Merge pull request #69 from hyperdefined/dependabot/maven/org.bstats-bstats-bukkit-3.0.3
Bump org.bstats:bstats-bukkit from 3.0.2 to 3.0.3
2024-08-28 23:20:33 -04:00
hyperdefined
7e13159056 support hex colors in lore (#68) 2024-08-28 23:20:16 -04:00
dependabot[bot]
7cdb8d55b5 Bump org.bstats:bstats-bukkit from 3.0.2 to 3.0.3
Bumps [org.bstats:bstats-bukkit](https://github.com/Bastian/bStats-Metrics) from 3.0.2 to 3.0.3.
- [Release notes](https://github.com/Bastian/bStats-Metrics/releases)
- [Commits](https://github.com/Bastian/bStats-Metrics/compare/v3.0.2...v3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 11:27:39 +00:00
dependabot[bot]
368e59b1e1 Bump net.kyori:adventure-platform-bukkit from 4.3.3 to 4.3.4
Bumps [net.kyori:adventure-platform-bukkit](https://github.com/KyoriPowered/adventure-platform) from 4.3.3 to 4.3.4.
- [Release notes](https://github.com/KyoriPowered/adventure-platform/releases)
- [Commits](https://github.com/KyoriPowered/adventure-platform/compare/v4.3.3...v4.3.4)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-platform-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 11:04:11 +00:00
hyperdefined
9412dc02d7 Update README.md 2024-07-24 21:32:03 -04:00
hyperdefined
0765c49622 Update pom.xml 2024-07-24 21:29:12 -04:00
hyperdefined
91959c223e new damage cause, fix #64 #65 2024-07-19 20:12:50 -04:00
hyperdefined
a53cebc589 Merge pull request #63 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-clean-plugin-3.4.0
Bump org.apache.maven.plugins:maven-clean-plugin from 3.3.2 to 3.4.0
2024-06-24 21:45:02 -04:00
dependabot[bot]
7f7c1d4656 Bump org.apache.maven.plugins:maven-clean-plugin from 3.3.2 to 3.4.0
Bumps [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) from 3.3.2 to 3.4.0.
- [Release notes](https://github.com/apache/maven-clean-plugin/releases)
- [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.3.2...maven-clean-plugin-3.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-20 11:04:51 +00:00
hyperdefined
1e99fa5076 Merge pull request #60 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.6.0
Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.3 to 3.6.0
2024-06-18 12:06:21 -04:00
hyperdefined
d50ee82a98 Merge pull request #61 from hyperdefined/dependabot/maven/net.kyori-adventure-platform-bukkit-4.3.3
Bump net.kyori:adventure-platform-bukkit from 4.3.2 to 4.3.3
2024-06-18 12:04:11 -04:00
dependabot[bot]
2a2c9a7376 Bump net.kyori:adventure-platform-bukkit from 4.3.2 to 4.3.3
Bumps [net.kyori:adventure-platform-bukkit](https://github.com/KyoriPowered/adventure-platform) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/KyoriPowered/adventure-platform/releases)
- [Commits](https://github.com/KyoriPowered/adventure-platform/compare/v4.3.2...v4.3.3)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-platform-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 11:19:58 +00:00
dependabot[bot]
813648e330 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.3 to 3.6.0
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.3 to 3.6.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.3...maven-shade-plugin-3.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-31 11:33:03 +00:00
hyperdefined
330001e6de Update README.md 2024-05-25 15:53:34 -04:00
hyperdefined
75b1a95cb5 Merge pull request #56 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.5.3
Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.5.3
2024-05-25 15:52:46 -04:00
hyperdefined
ca37021e5a Merge pull request #57 from hyperdefined/dependabot/maven/net.kyori-adventure-text-minimessage-4.17.0
Bump net.kyori:adventure-text-minimessage from 4.16.0 to 4.17.0
2024-05-25 15:52:39 -04:00
hyperdefined
f72ea3dbfa Update pom.xml 2024-05-25 15:41:49 -04:00
hyperdefined
03077d5e2f possibly fix #59 2024-05-25 15:41:16 -04:00
hyperdefined
608c870667 possibly fix #44 2024-05-25 15:38:44 -04:00
hyperdefined
ea27e4f4ab remove color codes when comparing 2024-05-25 15:37:52 -04:00
dependabot[bot]
8a7c6c720a Bump net.kyori:adventure-text-minimessage from 4.16.0 to 4.17.0
Bumps [net.kyori:adventure-text-minimessage](https://github.com/KyoriPowered/adventure) from 4.16.0 to 4.17.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.16.0...v4.17.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-minimessage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-08 11:41:03 +00:00
dependabot[bot]
12e2758ffd Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.5.3
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.2...maven-shade-plugin-3.5.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-24 11:09:18 +00:00
hyperdefined
5939b8f944 Merge pull request #54 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.13.0
Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.1 to 3.13.0
2024-03-26 18:12:54 -04:00
hyperdefined
021d67e505 Merge pull request #55 from hyperdefined/dependabot/maven/space.arim.morepaperlib-morepaperlib-0.4.4
Bump space.arim.morepaperlib:morepaperlib from 0.4.3 to 0.4.4
2024-03-26 18:10:25 -04:00
dependabot[bot]
c0ee457c4d Bump space.arim.morepaperlib:morepaperlib from 0.4.3 to 0.4.4
Bumps space.arim.morepaperlib:morepaperlib from 0.4.3 to 0.4.4.

---
updated-dependencies:
- dependency-name: space.arim.morepaperlib:morepaperlib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-25 11:28:14 +00:00
dependabot[bot]
4f4e4a961a Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.1 to 3.13.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-19 11:15:00 +00:00
hyperdefined
3412094f93 Merge pull request #51 from hyperdefined/dependabot/maven/net.kyori-adventure-text-minimessage-4.16.0
Bump net.kyori:adventure-text-minimessage from 4.15.0 to 4.16.0
2024-02-23 17:29:35 -05:00
hyperdefined
cdc46a1f5f Merge pull request #52 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.5.2 2024-02-22 09:33:56 -05:00
dependabot[bot]
d4c7770352 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.1 to 3.5.2
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.1...maven-shade-plugin-3.5.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-21 11:22:24 +00:00
dependabot[bot]
85db07877d Bump net.kyori:adventure-text-minimessage from 4.15.0 to 4.16.0
Bumps [net.kyori:adventure-text-minimessage](https://github.com/KyoriPowered/adventure) from 4.15.0 to 4.16.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.15.0...v4.16.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-minimessage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-20 11:46:47 +00:00
hyperdefined
1e37fcd3cb Merge pull request #49 from hyperdefined/dependabot/maven/net.kyori-adventure-platform-bukkit-4.3.2
Bump net.kyori:adventure-platform-bukkit from 4.3.1 to 4.3.2
2023-12-26 12:06:21 -05:00
hyperdefined
10f9b9404e Merge pull request #50 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.12.1
Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.0 to 3.12.1
2023-12-26 12:05:43 -05:00
dependabot[bot]
c350536ab6 Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.0 to 3.12.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.0...maven-compiler-plugin-3.12.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 11:07:40 +00:00
dependabot[bot]
e12a0a80f5 Bump net.kyori:adventure-platform-bukkit from 4.3.1 to 4.3.2
Bumps [net.kyori:adventure-platform-bukkit](https://github.com/KyoriPowered/adventure-platform) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/KyoriPowered/adventure-platform/releases)
- [Commits](https://github.com/KyoriPowered/adventure-platform/compare/v4.3.1...v4.3.2)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-platform-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-22 11:57:41 +00:00
hyperdefined
44a3fc7d63 Merge pull request #46 from hyperdefined/dependabot/maven/net.kyori-adventure-text-minimessage-4.15.0
Bump net.kyori:adventure-text-minimessage from 4.14.0 to 4.15.0
2023-12-19 17:21:21 -05:00
hyperdefined
6a5bb994cc Merge pull request #48 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.12.0
Bump org.apache.maven.plugins:maven-compiler-plugin from 3.11.0 to 3.12.0
2023-12-19 17:18:53 -05:00
dependabot[bot]
1c52664935 Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 12:01:49 +00:00
dependabot[bot]
4d18020065 Bump net.kyori:adventure-text-minimessage from 4.14.0 to 4.15.0
Bumps [net.kyori:adventure-text-minimessage](https://github.com/KyoriPowered/adventure) from 4.14.0 to 4.15.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.14.0...v4.15.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-minimessage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 11:40:53 +00:00
hyperdefined
ee5ebff614 Merge pull request #43 from hyperdefined/dependabot/maven/org.apache.maven.plugins-maven-clean-plugin-3.3.2
Bump org.apache.maven.plugins:maven-clean-plugin from 3.3.1 to 3.3.2
2023-10-27 13:35:41 -04:00
dependabot[bot]
fa7b19e3fc Bump org.apache.maven.plugins:maven-clean-plugin from 3.3.1 to 3.3.2
Bumps [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/apache/maven-clean-plugin/releases)
- [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.3.1...maven-clean-plugin-3.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-27 11:06:37 +00:00
31 changed files with 840 additions and 609 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
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Maven
run: mvn -B package --file pom.xml
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- name: Build with Maven
run: mvn -B package --file pom.xml

View File

@@ -1,3 +1,4 @@
name: Update Modrinth Description
on:
push:
branches: [ master ]

View File

@@ -1,26 +1,26 @@
<h1 align="center">ToolStats</h1>
<p align="center">
<img src="https://img.shields.io/badge/Minecraft-1.15--1.20.2-orange" alt="Minecraft versions">
<img src="https://img.shields.io/github/v/release/hyperdefined/ToolStats" alt="GitHub release (latest by date)">
<a href="https://github.com/hyperdefined/ToolStats/releases"><img src="https://img.shields.io/github/downloads/hyperdefined/ToolStats/total?logo=github" alt="Downloads"></a>
<img src="https://img.shields.io/badge/made%20with-love%20&%20fluff-red" alt="Made with love & fluff">
<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://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://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>
<a href="https://modrinth.com/plugin/ToolStats"><img alt="modrinth" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/available/modrinth_vector.svg"></a>
<a href="https://hangar.papermc.io/hyperdefined/ToolStats"><img alt="hangar" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/available/hangar_vector.svg"></a>
<a href="https://papermc.io"><img alt="paper" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/paper_vector.svg"></a>
<a href="https://github.com/hyperdefined/ToolStats/wiki"><img alt="ghpages" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/ghpages_vector.svg"></a>
<a href="https://discord.gg/rJuQXVcJz8"><img alt="discord-singular" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/discord-singular_vector.svg"></a>
<a href="https://buymeacoffee.com/hyperdefined"><img alt="buymeacoffee-singular" height="40" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/donate/buymeacoffee-singular_vector.svg"></a>
</p>
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:
* Blocks mined (pickaxes, shovels, axes, hoes, shears)
* 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.
* Armor damage taken.
* Fish caught.
* Sheep sheared.
* 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!

52
pom.xml
View File

@@ -23,13 +23,13 @@
<groupId>lol.hyper</groupId>
<artifactId>toolstats</artifactId>
<version>1.7.1</version>
<version>1.8.6</version>
<packaging>jar</packaging>
<name>ToolStats</name>
<properties>
<java.version>1.8</java.version>
<java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@@ -37,7 +37,7 @@
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.3.1</version>
<version>3.4.0</version>
<executions>
<execution>
<id>auto-clean</id>
@@ -51,7 +51,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.13.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
@@ -60,25 +60,17 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.6.0</version>
<configuration>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>lol.hyper.toolstats.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori.adventure</pattern>
<shadedPattern>lol.hyper.toolstats.adventure</shadedPattern>
</relocation>
<relocation>
<pattern>lol.hyper.githubreleaseapi</pattern>
<shadedPattern>lol.hyper.toolstats.updater</shadedPattern>
</relocation>
<relocation>
<pattern>space.arim.morepaperlib</pattern>
<shadedPattern>lol.hyper.toolstats.morepaperlib</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
@@ -104,26 +96,22 @@
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>arim-mvn-lgpl3</id>
<url>https://mvn-repo.arim.space/lesser-gpl3/</url>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.2-R0.1-SNAPSHOT</version>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.2</version>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -132,23 +120,5 @@
<version>1.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.14.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>space.arim.morepaperlib</groupId>
<artifactId>morepaperlib</artifactId>
<version>0.4.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -27,17 +27,13 @@ import lol.hyper.toolstats.tools.ItemLore;
import lol.hyper.toolstats.tools.NumberFormat;
import lol.hyper.toolstats.tools.config.ConfigTools;
import lol.hyper.toolstats.tools.config.ConfigUpdater;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import space.arim.morepaperlib.MorePaperLib;
import java.io.File;
import java.io.IOException;
@@ -81,10 +77,6 @@ public final class ToolStats extends JavaPlugin {
* Stores how much damage an armor piece has 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.
*/
@@ -97,6 +89,10 @@ public final class ToolStats extends JavaPlugin {
* Key for arrows shot.
*/
public final NamespacedKey arrowsShot = new NamespacedKey(this, "arrows-shot");
/**
* Key for tracking flight time.
*/
public final NamespacedKey flightTime = new NamespacedKey(this, "flightTime");
/**
* Stores how an item was created.
* 0 = crafted.
@@ -109,7 +105,7 @@ public final class ToolStats extends JavaPlugin {
*/
public final NamespacedKey originType = new NamespacedKey(this, "origin");
public final int CONFIG_VERSION = 6;
public final int CONFIG_VERSION = 8;
public final Logger logger = this.getLogger();
public final File configFile = new File(this.getDataFolder(), "config.yml");
@@ -130,18 +126,15 @@ public final class ToolStats extends JavaPlugin {
public PlayerJoin playerJoin;
public NumberFormat numberFormat;
public YamlConfiguration config;
private BukkitAudiences adventure;
public MorePaperLib morePaperLib;
public HashMaker hashMaker;
public CreativeEvent creativeEvent;
public PlayerMove playerMove;
public ItemChecker itemChecker;
public ShootBow shootBow;
public ConfigTools configTools;
@Override
public void onEnable() {
this.adventure = BukkitAudiences.create(this);
morePaperLib = new MorePaperLib(this);
if (!configFile.exists()) {
this.saveResource("config.yml", true);
logger.info("Copying default config!");
@@ -164,6 +157,7 @@ public final class ToolStats extends JavaPlugin {
inventoryOpen = new InventoryOpen(this);
playerJoin = new PlayerJoin(this);
creativeEvent = new CreativeEvent(this);
playerMove = new PlayerMove(this);
itemChecker = new ItemChecker();
shootBow = new ShootBow(this);
configTools = new ConfigTools(this);
@@ -183,12 +177,12 @@ public final class ToolStats extends JavaPlugin {
Bukkit.getServer().getPluginManager().registerEvents(playerJoin, this);
Bukkit.getServer().getPluginManager().registerEvents(creativeEvent, this);
Bukkit.getServer().getPluginManager().registerEvents(shootBow, this);
Bukkit.getServer().getPluginManager().registerEvents(playerMove, this);
this.getCommand("toolstats").setExecutor(commandToolStats);
new Metrics(this, 14110);
morePaperLib.scheduling().asyncScheduler().run(this::checkForUpdates);
Bukkit.getAsyncScheduler().runNow(this, scheduledTask -> checkForUpdates());
}
public void loadConfig() {
@@ -224,23 +218,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.");
}
}
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.tools.UUIDDataType;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
@@ -42,65 +41,63 @@ import java.util.*;
public class CommandToolStats implements TabExecutor {
private final ToolStats toolStats;
private final BukkitAudiences audiences;
public CommandToolStats(ToolStats toolStats) {
this.toolStats = toolStats;
this.audiences = toolStats.getAdventure();
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
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;
}
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;
}
switch (args[0]) {
case "reload": {
if (sender.hasPermission("toolstats.reload")) {
toolStats.loadConfig();
audiences.sender(sender).sendMessage(Component.text("Configuration reloaded!", NamedTextColor.GREEN));
sender.sendMessage(Component.text("Configuration reloaded!", NamedTextColor.GREEN));
} 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;
}
case "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;
}
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;
}
if (args.length == 2 && args[1].equalsIgnoreCase("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;
}
Player player = (Player) sender;
ItemStack heldItem = player.getInventory().getItemInMainHand();
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;
}
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;
}
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));
audiences.sender(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));
audiences.sender(sender).sendMessage(Component.text("Type /toolstats reset confirm to confirm this.", 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));
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("Only use this if the tags on the tool are incorrect.", NamedTextColor.GREEN));
sender.sendMessage(Component.text("Type /toolstats reset confirm to confirm this.", NamedTextColor.GREEN));
return true;
}
default: {
audiences.sender(sender).sendMessage(Component.text("Invalid sub-command.", NamedTextColor.RED));
sender.sendMessage(Component.text("Invalid sub-command.", NamedTextColor.RED));
}
}
return true;
@@ -119,17 +116,7 @@ public class CommandToolStats implements TabExecutor {
return;
}
PersistentDataContainer container = finalMeta.getPersistentDataContainer();
List<String> lore = new ArrayList<>();
String caughtByLore = toolStats.configTools.getLoreFromConfig("fished.caught-by", false);
String lootedByLore = toolStats.configTools.getLoreFromConfig("looted.found-by", false);
String tradedByLore = toolStats.configTools.getLoreFromConfig("traded.traded-by", false);
String spawnedByLore = toolStats.configTools.getLoreFromConfig("spawned-in.spawned-by", false);
// make sure the config messages are not null
if (caughtByLore == null || lootedByLore == null || tradedByLore == null || spawnedByLore == null) {
return;
}
List<Component> lore = new ArrayList<>();
// set how the item was obtained
Integer origin = -1;
@@ -144,20 +131,33 @@ public class CommandToolStats implements TabExecutor {
// hard code elytras
if (finalItem.getType() == Material.ELYTRA) {
if (toolStats.config.getBoolean("enabled.elytra-tag")) {
lore.add(toolStats.configTools.getLoreFromConfig("looted.found-by", true).replace("{player}", player.getName()));
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) {
Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG);
if (time != null) {
lore.add(toolStats.configTools.getLoreFromConfig("looted.found-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time))));
}
}
finalMeta.setLore(lore);
finalItem.setItemMeta(finalMeta);
int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem);
return;
Long flightTime = null;
Long timeCreated = null;
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) {
timeCreated = container.get(toolStats.timeCreated, PersistentDataType.LONG);
}
if (container.has(toolStats.flightTime, PersistentDataType.LONG)) {
flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG);
}
if (flightTime != null) {
if (toolStats.config.getBoolean("enabled.flight-time")) {
Component line = toolStats.configTools.formatLore("flight-time", "{time}", toolStats.numberFormat.formatDouble((double) flightTime / 1000));
lore.add(line);
}
}
if (timeCreated != null) {
Component timeCreatedLine = toolStats.configTools.formatLore("looted.found-by", "{player}", player.getName());
Component playerOwnerLine = toolStats.configTools.formatLore("looted.found-on", "{date}", toolStats.numberFormat.formatDate(new Date(timeCreated)));
lore.add(timeCreatedLine);
lore.add(playerOwnerLine);
}
finalMeta.lore(lore);
finalItem.setItemMeta(finalMeta);
int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem);
}
if (toolStats.configTools.checkConfig(original.getType(), "created-by")) {
@@ -173,7 +173,7 @@ public class CommandToolStats implements TabExecutor {
// if the owner's name is null for whatever reason, set the new owner
// to the current player running the command
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();
container.set(toolStats.genericOwner, new UUIDDataType(), player.getUniqueId());
}
@@ -181,27 +181,27 @@ public class CommandToolStats implements TabExecutor {
// show how the item was created based on the previous lore
switch (origin) {
case 0: {
lore.add(toolStats.configTools.getLoreFromConfig("created.created-by", true).replace("{player}", ownerName));
lore.add(toolStats.configTools.formatLore("created.created-by", "{player}", ownerName));
break;
}
case 2: {
lore.add(toolStats.configTools.getLoreFromConfig("looted.looted-by", true).replace("{player}", ownerName));
lore.add(toolStats.configTools.formatLore("looted.looted-by", "{player}", ownerName));
break;
}
case 3: {
lore.add(toolStats.configTools.getLoreFromConfig("traded.traded-by", true).replace("{player}", ownerName));
lore.add(toolStats.configTools.formatLore("traded.traded-by", "{player}", ownerName));
break;
}
case 4: {
lore.add(toolStats.configTools.getLoreFromConfig("looted.found-by", true).replace("{player}", ownerName));
lore.add(toolStats.configTools.formatLore("looted.found-by", "{player}", ownerName));
break;
}
case 5: {
lore.add(toolStats.configTools.getLoreFromConfig("fished.caught-by", true).replace("{player}", ownerName));
lore.add(toolStats.configTools.formatLore("fished.caught-by", "{player}", ownerName));
break;
}
case 6: {
lore.add(toolStats.configTools.getLoreFromConfig("spawned-in.spawned-by", true).replace("{player}", ownerName));
lore.add(toolStats.configTools.formatLore("spawned-in.spawned-by", "{player}", ownerName));
break;
}
}
@@ -211,30 +211,31 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.timeCreated, PersistentDataType.LONG)) {
Long time = container.get(toolStats.timeCreated, PersistentDataType.LONG);
if (time != null) {
String date = toolStats.numberFormat.formatDate(new Date(time));
// show how when the item was created based on the previous lore
switch (origin) {
case 0: {
lore.add(toolStats.configTools.getLoreFromConfig("created.created-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time))));
lore.add(toolStats.configTools.formatLore("created.created-on", "{date}", date));
break;
}
case 2: {
lore.add(toolStats.configTools.getLoreFromConfig("looted.looted-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time))));
lore.add(toolStats.configTools.formatLore("looted.looted-on", "{date}", date));
break;
}
case 3: {
lore.add(toolStats.configTools.getLoreFromConfig("traded.traded-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time))));
lore.add(toolStats.configTools.formatLore("traded.traded-on", "{date}", date));
break;
}
case 4: {
lore.add(toolStats.configTools.getLoreFromConfig("looted.found-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time))));
lore.add(toolStats.configTools.formatLore("looted.found-on", "{date}", date));
break;
}
case 5: {
lore.add(toolStats.configTools.getLoreFromConfig("fished.caught-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time))));
lore.add(toolStats.configTools.formatLore("fished.caught-on", "{date}", date));
break;
}
case 6: {
lore.add(toolStats.configTools.getLoreFromConfig("spawned-in.spawned-on", true).replace("{date}", toolStats.numberFormat.formatDate(new Date(time))));
lore.add(toolStats.configTools.formatLore("spawned-in.spawned-on", "{date}", date));
break;
}
}
@@ -245,7 +246,7 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.swordPlayerKills, PersistentDataType.INTEGER)) {
Integer kills = container.get(toolStats.swordPlayerKills, PersistentDataType.INTEGER);
if (kills != null) {
lore.add(toolStats.configTools.getLoreFromConfig("kills.player", true).replace("{kills}", toolStats.numberFormat.formatInt(kills)));
lore.add(toolStats.configTools.formatLore("kills.player", "{kills}", toolStats.numberFormat.formatInt(kills)));
}
}
}
@@ -253,7 +254,7 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.swordMobKills, PersistentDataType.INTEGER)) {
Integer kills = container.get(toolStats.swordMobKills, PersistentDataType.INTEGER);
if (kills != null) {
lore.add(toolStats.configTools.getLoreFromConfig("kills.mob", true).replace("{kills}", toolStats.numberFormat.formatInt(kills)));
lore.add(toolStats.configTools.formatLore("kills.mob", "{kills}", toolStats.numberFormat.formatInt(kills)));
}
}
}
@@ -262,14 +263,14 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.cropsHarvested, PersistentDataType.INTEGER)) {
Integer crops = container.get(toolStats.cropsHarvested, PersistentDataType.INTEGER);
if (crops != null) {
lore.add(toolStats.configTools.getLoreFromConfig("crops-harvested", true).replace("{crops}", toolStats.numberFormat.formatInt(crops)));
lore.add(toolStats.configTools.formatLore("crops-harvested", "{crops}", toolStats.numberFormat.formatInt(crops)));
}
}
}
if (container.has(toolStats.genericMined, PersistentDataType.INTEGER)) {
Integer blocksMined = container.get(toolStats.genericMined, PersistentDataType.INTEGER);
if (blocksMined != null) {
lore.add(toolStats.configTools.getLoreFromConfig("blocks-mined", true).replace("{blocks}", toolStats.numberFormat.formatInt(blocksMined)));
lore.add(toolStats.configTools.formatLore("blocks-mined", "{blocks}", toolStats.numberFormat.formatInt(blocksMined)));
}
}
}
@@ -277,7 +278,7 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.fishingRodCaught, PersistentDataType.INTEGER)) {
Integer fish = container.get(toolStats.fishingRodCaught, PersistentDataType.INTEGER);
if (fish != null) {
lore.add(toolStats.configTools.getLoreFromConfig("fished.fish-caught", true).replace("{fish}", toolStats.numberFormat.formatInt(fish)));
lore.add(toolStats.configTools.formatLore("fished.fish-caught", "{fish}", toolStats.numberFormat.formatInt(fish)));
}
}
}
@@ -285,7 +286,7 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.shearsSheared, PersistentDataType.INTEGER)) {
Integer sheep = container.get(toolStats.shearsSheared, PersistentDataType.INTEGER);
if (sheep != null) {
lore.add(toolStats.configTools.getLoreFromConfig("sheep-sheared", true).replace("{sheep}", toolStats.numberFormat.formatInt(sheep)));
lore.add(toolStats.configTools.formatLore("sheep-sheared", "{sheep}", toolStats.numberFormat.formatInt(sheep)));
}
}
}
@@ -293,7 +294,7 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.armorDamage, PersistentDataType.DOUBLE)) {
Double damage = container.get(toolStats.armorDamage, PersistentDataType.DOUBLE);
if (damage != null) {
lore.add(toolStats.configTools.getLoreFromConfig("damage-taken", true).replace("{damage}", toolStats.numberFormat.formatDouble(damage)));
lore.add(toolStats.configTools.formatLore("damage-taken", "{damage}", toolStats.numberFormat.formatDouble(damage)));
}
}
}
@@ -301,11 +302,11 @@ public class CommandToolStats implements TabExecutor {
if (container.has(toolStats.arrowsShot, PersistentDataType.INTEGER)) {
Integer arrows = container.get(toolStats.arrowsShot, PersistentDataType.INTEGER);
if (arrows != null) {
lore.add(toolStats.configTools.getLoreFromConfig("arrows-shot", true).replace("{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);
int slot = player.getInventory().getHeldItemSlot();
player.getInventory().setItem(slot, finalItem);

View File

@@ -17,7 +17,10 @@
package lol.hyper.toolstats.events;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -36,6 +39,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
public class BlocksMined implements Listener {
@@ -60,13 +64,7 @@ public class BlocksMined implements Listener {
if (block.getType() == Material.CHEST) {
toolStats.playerInteract.openedChests.put(block, player);
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
toolStats.playerInteract.openedChests.remove(block);
}
};
toolStats.scheduleGlobal(runnable, 20);
Bukkit.getGlobalRegionScheduler().runDelayed(toolStats, scheduledTask -> toolStats.playerInteract.openedChests.remove(block), 20);
}
// only check certain items
@@ -104,14 +102,19 @@ public class BlocksMined implements Listener {
toolStats.logger.warning(playerTool + " does not have valid generic-mined set! Resting to zero. This should NEVER happen.");
}
blocksMined++;
container.set(toolStats.genericMined, PersistentDataType.INTEGER, blocksMined);
container.set(toolStats.genericMined, PersistentDataType.INTEGER, blocksMined + 1);
// do we add the lore based on the config?
if (toolStats.configTools.checkConfig(playerTool.getType(), "blocks-mined")) {
String blocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{blocks}", blocksMinedFormatted, "blocks-mined");
meta.setLore(newLore);
String oldBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined);
String newBlocksMinedFormatted = toolStats.numberFormat.formatInt(blocksMined + 1);
Component oldLine = toolStats.configTools.formatLore("blocks-mined", "{blocks}", oldBlocksMinedFormatted);
Component newLine = toolStats.configTools.formatLore("blocks-mined", "{blocks}", newBlocksMinedFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
playerTool.setItemMeta(meta);
}
@@ -140,14 +143,19 @@ public class BlocksMined implements Listener {
toolStats.logger.warning(playerTool + " does not have valid crops-mined set! Resting to zero. This should NEVER happen.");
}
cropsMined++;
container.set(toolStats.cropsHarvested, PersistentDataType.INTEGER, cropsMined);
container.set(toolStats.cropsHarvested, PersistentDataType.INTEGER, cropsMined + 1);
// do we add the lore based on the config?
if (toolStats.configTools.checkConfig(playerTool.getType(), "blocks-mined")) {
String cropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{crops}", cropsMinedFormatted, "crops-harvested");
meta.setLore(newLore);
String oldCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined);
String newCropsMinedFormatted = toolStats.numberFormat.formatInt(cropsMined + 1);
Component oldLine = toolStats.configTools.formatLore("crops-harvested", "{crops}", oldCropsMinedFormatted);
Component newLine = toolStats.configTools.formatLore("crops-harvested", "{crops}", newCropsMinedFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
playerTool.setItemMeta(meta);
}

View File

@@ -18,6 +18,7 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
@@ -31,7 +32,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
public class ChunkPopulate implements Listener {
@@ -49,34 +49,30 @@ public class ChunkPopulate implements Listener {
if (event.getChunk().getWorld().getEnvironment() != World.Environment.THE_END) {
return;
}
World world = event.getChunk().getWorld();
// this is delayed because entities are not loaded instantly
// we just check 1 second later
Chunk chunk = event.getChunk();
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
for (Entity entity : chunk.getEntities()) {
// if there is a new item frame
if (!(entity instanceof ItemFrame)) {
Bukkit.getRegionScheduler().runDelayed(toolStats, world, chunk.getX(), chunk.getZ(), scheduledTask -> {
for (Entity entity : chunk.getEntities()) {
// if there is a new item frame
if (!(entity instanceof ItemFrame itemFrame)) {
continue;
}
// 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;
}
ItemFrame itemFrame = (ItemFrame) entity;
// 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;
}
// 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);
}
// 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);
}
}
};
toolStats.scheduleRegion(runnable, chunk.getWorld(), chunk, 20);
}, 20);
}
}

View File

@@ -19,7 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.ChatColor;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -32,7 +32,9 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class CraftItem implements Listener {
@@ -62,13 +64,12 @@ public class CraftItem implements Listener {
// if the player shift clicks, send them this warning
if (event.isShiftClick()) {
String configMessage = toolStats.config.getString("messages.shift-click-warning.crafting");
if (configMessage != null) {
if (configMessage.length() != 0) {
event.getWhoClicked().sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage));
}
Component component = toolStats.configTools.formatLore("shift-click-warning.crafting", null, null);
if (component != null) {
event.getWhoClicked().sendMessage(component);
}
}
// test the item before setting it
ItemStack newItem = addLore(itemStack, player);
if (newItem != null) {
@@ -113,31 +114,30 @@ public class CraftItem implements Listener {
container.set(toolStats.genericOwner, new UUIDDataType(), owner.getUniqueId());
container.set(toolStats.originType, PersistentDataType.INTEGER, 0);
List<String> lore;
List<Component> lore;
// get the current lore the item
if (meta.hasLore()) {
lore = meta.getLore();
lore = meta.lore();
} else {
lore = new ArrayList<>();
}
// do we add the lore based on the config?
if (toolStats.configTools.checkConfig(itemStack.getType(), "created-date")) {
String createdOnRaw = toolStats.configTools.getLoreFromConfig("created.created-on", true);
if (createdOnRaw == null) {
toolStats.logger.warning("There is no lore message for messages.created.created-on!");
String date = toolStats.numberFormat.formatDate(finalDate);
Component newLine = toolStats.configTools.formatLore("created.created-on", "{date}", date);
if (newLine == null) {
return null;
}
lore.add(createdOnRaw.replace("{date}", toolStats.numberFormat.formatDate(finalDate)));
meta.setLore(lore);
lore.add(newLine);
meta.lore(lore);
}
if (toolStats.configTools.checkConfig(itemStack.getType(), "created-by")) {
String createdByRaw = toolStats.configTools.getLoreFromConfig("created.created-by", true);
if (createdByRaw == null) {
toolStats.logger.warning("There is no lore message for messages.created.created-by!");
Component newLine = toolStats.configTools.formatLore("created.created-by", "{player}", owner.getName());
if (newLine == null) {
return null;
}
lore.add(createdByRaw.replace("{player}", owner.getName()));
meta.setLore(lore);
lore.add(newLine);
meta.lore(lore);
}
newItem.setItemMeta(meta);
return newItem;

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -87,6 +88,11 @@ public class CreativeEvent implements Listener {
Date finalDate = new Date(timeCreated);
PersistentDataContainer container = meta.getPersistentDataContainer();
// if the item already has an origin set, don't add it again
if (container.has(toolStats.originType, PersistentDataType.INTEGER)) {
return null;
}
// only make the hash if it's enabled
if (toolStats.config.getBoolean("generate-hash-for-items")) {
String hash = toolStats.hashMaker.makeHash(spawnedItem.getType(), owner.getUniqueId(), timeCreated);
@@ -99,8 +105,8 @@ public class CreativeEvent implements Listener {
if (toolStats.configTools.checkConfig(newSpawnedItem.getType(), "spawned-in")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
}
newSpawnedItem.setItemMeta(meta);

View File

@@ -18,6 +18,7 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.*;
@@ -39,7 +40,7 @@ public class EntityDamage implements Listener {
private final ToolStats toolStats;
public final Set<UUID> trackedMobs = new HashSet<>();
private final List<EntityDamageEvent.DamageCause> ignoredCauses = Arrays.asList(EntityDamageEvent.DamageCause.SUICIDE, EntityDamageEvent.DamageCause.VOID, EntityDamageEvent.DamageCause.CUSTOM);
private final List<EntityDamageEvent.DamageCause> ignoredCauses = Arrays.asList(EntityDamageEvent.DamageCause.SUICIDE, EntityDamageEvent.DamageCause.VOID, EntityDamageEvent.DamageCause.CUSTOM, EntityDamageEvent.DamageCause.KILL);
public EntityDamage(ToolStats toolStats) {
this.toolStats = toolStats;
@@ -51,10 +52,9 @@ public class EntityDamage implements Listener {
return;
}
if (!(event.getEntity() instanceof LivingEntity)) {
if (!(event.getEntity() instanceof LivingEntity mobBeingAttacked)) {
return;
}
LivingEntity mobBeingAttacked = (LivingEntity) event.getEntity();
// ignore void and /kill damage
EntityDamageEvent.DamageCause cause = event.getCause();
@@ -65,8 +65,7 @@ public class EntityDamage implements Listener {
// mob is going to die
if (mobBeingAttacked.getHealth() - event.getFinalDamage() <= 0) {
// a player is killing something
if (event.getDamager() instanceof Player) {
Player attackingPlayer = (Player) event.getDamager();
if (event.getDamager() instanceof Player attackingPlayer) {
if (attackingPlayer.getGameMode() == GameMode.CREATIVE || attackingPlayer.getGameMode() == GameMode.SPECTATOR) {
return;
}
@@ -86,27 +85,24 @@ public class EntityDamage implements Listener {
trackedMobs.add(mobBeingAttacked.getUniqueId());
}
// trident is being thrown at something
if (event.getDamager() instanceof Trident) {
Trident trident = (Trident) event.getDamager();
if (event.getDamager() instanceof Trident trident) {
ItemStack newTrident;
// trident is killing player
if (mobBeingAttacked instanceof Player) {
newTrident = tridentPlayerKills(trident.getItem());
newTrident = tridentPlayerKills(trident.getItemStack());
} else {
// trident is killing a mob
newTrident = tridentMobKills(trident.getItem());
newTrident = tridentMobKills(trident.getItemStack());
trackedMobs.add(mobBeingAttacked.getUniqueId());
}
if (newTrident != null) {
trident.setItem(newTrident);
trident.setItemStack(newTrident);
}
}
// arrow is being shot
if (event.getDamager() instanceof Arrow) {
Arrow arrow = (Arrow) event.getDamager();
if (event.getDamager() instanceof Arrow arrow) {
// if the shooter is a player
if (arrow.getShooter() instanceof Player) {
Player shootingPlayer = (Player) arrow.getShooter();
if (arrow.getShooter() instanceof Player shootingPlayer) {
if (shootingPlayer.getGameMode() == GameMode.CREATIVE || shootingPlayer.getGameMode() == GameMode.SPECTATOR) {
return;
}
@@ -143,8 +139,7 @@ public class EntityDamage implements Listener {
}
}
// player is taken damage but not being killed
if (mobBeingAttacked instanceof Player) {
Player playerTakingDamage = (Player) mobBeingAttacked;
if (mobBeingAttacked instanceof Player playerTakingDamage) {
if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) {
return;
}
@@ -161,7 +156,7 @@ public class EntityDamage implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onDamage(EntityDamageEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
if (!(event.getEntity() instanceof LivingEntity mobBeingAttacked)) {
return;
}
@@ -171,10 +166,8 @@ public class EntityDamage implements Listener {
return;
}
LivingEntity mobBeingAttacked = (LivingEntity) event.getEntity();
// player is taken damage but not being killed
if (mobBeingAttacked instanceof Player) {
Player playerTakingDamage = (Player) mobBeingAttacked;
if (mobBeingAttacked instanceof Player playerTakingDamage) {
if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) {
return;
}
@@ -191,7 +184,7 @@ public class EntityDamage implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onDamage(EntityDamageByBlockEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
if (!(event.getEntity() instanceof LivingEntity mobBeingAttacked)) {
return;
}
@@ -201,10 +194,8 @@ public class EntityDamage implements Listener {
return;
}
LivingEntity mobBeingAttacked = (LivingEntity) event.getEntity();
// player is taken damage but not being killed
if (mobBeingAttacked instanceof Player) {
Player playerTakingDamage = (Player) mobBeingAttacked;
if (mobBeingAttacked instanceof Player playerTakingDamage) {
if (playerTakingDamage.getGameMode() == GameMode.CREATIVE || playerTakingDamage.getGameMode() == GameMode.SPECTATOR) {
return;
}
@@ -241,14 +232,19 @@ public class EntityDamage implements Listener {
toolStats.logger.warning(itemStack + " does not have valid player-kills set! Resting to zero. This should NEVER happen.");
}
playerKills++;
container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, playerKills);
container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, playerKills + 1);
// do we add the lore based on the config?
if (toolStats.configTools.checkConfig(itemStack.getType(), "player-kills")) {
String playerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{kills}", playerKillsFormatted, "kills.player");
meta.setLore(newLore);
String oldPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
String newPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills + 1);
Component oldLine = toolStats.configTools.formatLore("kills.player", "{kills}", oldPlayerKillsFormatted);
Component newLine = toolStats.configTools.formatLore("kills.player", "{kills}", newPlayerKillsFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
itemStack.setItemMeta(meta);
}
@@ -275,14 +271,19 @@ public class EntityDamage implements Listener {
toolStats.logger.warning(itemStack + " does not have valid mob-kills set! Resting to zero. This should NEVER happen.");
}
mobKills++;
container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, mobKills);
container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, mobKills + 1);
// do we add the lore based on the config?
if (toolStats.configTools.checkConfig(itemStack.getType(), "mob-kills")) {
String mobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{kills}", mobKillsFormatted, "kills.mob");
meta.setLore(newLore);
String oldMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
String newMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills + 1);
Component oldLine = toolStats.configTools.formatLore("kills.mob", "{kills}", oldMobKillsFormatted);
Component newLine = toolStats.configTools.formatLore("kills.mob", "{kills}", newMobKillsFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
itemStack.setItemMeta(meta);
}
@@ -294,6 +295,10 @@ public class EntityDamage implements Listener {
* @param damage How much damage is being added.
*/
private void updateDamage(ItemStack itemStack, double damage) {
// ignore if the damage is zero or negative
if (damage < 0) {
return;
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
toolStats.logger.warning(itemStack + " does NOT have any meta! Unable to update stats.");
@@ -310,14 +315,18 @@ public class EntityDamage implements Listener {
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);
container.set(toolStats.armorDamageInt, PersistentDataType.INTEGER, damageTaken.intValue());
container.set(toolStats.armorDamage, PersistentDataType.DOUBLE, damageTaken + damage);
if (toolStats.config.getBoolean("enabled.armor-damage")) {
String damageTakenFormatted = toolStats.numberFormat.formatDouble(damageTaken);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{damage}", damageTakenFormatted, "damage-taken");
meta.setLore(newLore);
String oldDamageFormatted = toolStats.numberFormat.formatDouble(damageTaken);
String newDamageFormatted = toolStats.numberFormat.formatDouble(damageTaken + damage);
Component oldLine = toolStats.configTools.formatLore("damage-taken", "{damage}", oldDamageFormatted);
Component newLine = toolStats.configTools.formatLore("damage-taken", "{damage}", newDamageFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
itemStack.setItemMeta(meta);
}
@@ -345,14 +354,19 @@ public class EntityDamage implements Listener {
toolStats.logger.warning(newTrident + " does not have valid mob-kills set! Resting to zero. This should NEVER happen.");
}
mobKills++;
container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, mobKills);
container.set(toolStats.swordMobKills, PersistentDataType.INTEGER, mobKills + 1);
// do we add the lore based on the config?
if (toolStats.configTools.checkConfig(newTrident.getType(), "mob-kills")) {
String mobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{kills}", mobKillsFormatted, "kills.mob");
meta.setLore(newLore);
String oldMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills);
String newMobKillsFormatted = toolStats.numberFormat.formatInt(mobKills + 1);
Component oldLine = toolStats.configTools.formatLore("kills.mob", "{kills}", oldMobKillsFormatted);
Component newLine = toolStats.configTools.formatLore("kills.mob", "{kills}", newMobKillsFormatted);
if (oldLine == null || newLine == null) {
return null;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
newTrident.setItemMeta(meta);
return newTrident;
@@ -381,14 +395,19 @@ public class EntityDamage implements Listener {
toolStats.logger.warning(newTrident + " does not have valid player-kills set! Resting to zero. This should NEVER happen.");
}
playerKills++;
container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, playerKills);
container.set(toolStats.swordPlayerKills, PersistentDataType.INTEGER, playerKills + 1);
// do we add the lore based on the config?
if (toolStats.configTools.checkConfig(newTrident.getType(), "player-kills")) {
String playerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{kills}", playerKillsFormatted, "kills.player");
meta.setLore(newLore);
String oldPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills);
String newPlayerKillsFormatted = toolStats.numberFormat.formatInt(playerKills + 1);
Component oldLine = toolStats.configTools.formatLore("kills.player", "{kills}", oldPlayerKillsFormatted);
Component newLine = toolStats.configTools.formatLore("kills.player", "{kills}", newPlayerKillsFormatted);
if (oldLine == null || newLine == null) {
return null;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
newTrident.setItemMeta(meta);
return newTrident;

View File

@@ -18,6 +18,7 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -29,7 +30,8 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.*;
import java.util.List;
import java.util.UUID;
public class EntityDeath implements Listener {
@@ -53,13 +55,13 @@ public class EntityDeath implements Listener {
ItemMeta droppedItemMeta = droppedItem.getItemMeta();
if (droppedItemMeta != null) {
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
}
}
if (toolStats.itemChecker.isValidItem(droppedItem.getType())) {
ItemStack newItem = addLore(droppedItem, livingEntity.getName());
ItemStack newItem = addLore(droppedItem, livingEntity);
if (newItem != null) {
event.getDrops().set(i, newItem);
}
@@ -73,9 +75,9 @@ public class EntityDeath implements Listener {
* Adds "drop by" tag to item.
*
* @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();
ItemMeta meta = newItem.getItemMeta();
if (meta == null) {
@@ -86,8 +88,13 @@ public class EntityDeath implements Listener {
container.set(toolStats.originType, PersistentDataType.INTEGER, 1);
if (toolStats.config.getBoolean("enabled.dropped-by")) {
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{name}", mob, "dropped-by");
meta.setLore(newLore);
String mobName = toolStats.config.getString("messages.mob." + entity.getType());
if (mobName == null) {
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);
return newItem;

View File

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

View File

@@ -17,10 +17,11 @@
package lol.hyper.toolstats.events;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryOpenEvent;
@@ -32,6 +33,7 @@ import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID;
import java.util.function.Consumer;
public class InventoryOpen implements Listener {
@@ -83,23 +85,9 @@ public class InventoryOpen implements Listener {
container.set(toolStats.hash, PersistentDataType.STRING, hash);
}
}
// add origin tag
if (!container.has(toolStats.originType, PersistentDataType.INTEGER)) {
itemMeta = toolStats.itemLore.getOrigin(itemMeta, itemStack.getType() == Material.ELYTRA);
if (itemMeta == null) {
continue;
}
}
ItemMeta clone = itemMeta.clone();
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
itemStack.setItemMeta(clone);
}
};
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.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.*;
@@ -48,13 +49,12 @@ public class PickupItem implements Listener {
return;
}
Entity entity = event.getEntity();
if (entity instanceof Player) {
Player player = (Player) entity;
if (entity instanceof Player player) {
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) {
return;
}
Item item = event.getItem();
if (item.getType() == EntityType.DROPPED_ITEM) {
if (item.getType() == EntityType.ITEM) {
ItemStack itemStack = event.getItem().getItemStack();
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
@@ -103,8 +103,8 @@ public class PickupItem implements Listener {
if (toolStats.config.getBoolean("enabled.elytra-tag")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
}
finalItem.setItemMeta(meta);
return finalItem;

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Item;
@@ -32,6 +33,7 @@ import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.List;
@@ -58,25 +60,8 @@ public class PlayerFish implements Listener {
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) {
return;
}
// make sure the player is holding a fishing rod
// player can fish with their offhand
PlayerInventory inventory = player.getInventory();
boolean isMainHand = inventory.getItemInMainHand().getType() == Material.FISHING_ROD;
boolean isOffHand = inventory.getItemInOffHand().getType() == Material.FISHING_ROD;
ItemStack fishingRod = null;
if (isMainHand) {
fishingRod = inventory.getItemInMainHand();
}
if (isOffHand) {
fishingRod = inventory.getItemInOffHand();
}
// if the player is hold fishing rods in both hands
// default to main hand since that takes priority
if (isMainHand && isOffHand) {
fishingRod = inventory.getItemInMainHand();
}
ItemStack fishingRod = getItemStack(player);
// player swapped items?
if (fishingRod == null) {
return;
@@ -99,6 +84,26 @@ public class PlayerFish implements Listener {
}
}
private static @Nullable ItemStack getItemStack(Player player) {
PlayerInventory inventory = player.getInventory();
boolean isMainHand = inventory.getItemInMainHand().getType() == Material.FISHING_ROD;
boolean isOffHand = inventory.getItemInOffHand().getType() == Material.FISHING_ROD;
ItemStack fishingRod = null;
if (isMainHand) {
fishingRod = inventory.getItemInMainHand();
}
if (isOffHand) {
fishingRod = inventory.getItemInOffHand();
}
// if the player is hold fishing rods in both hands
// default to main hand since that takes priority
if (isMainHand && isOffHand) {
fishingRod = inventory.getItemInMainHand();
}
return fishingRod;
}
/**
* Update a fishing rod's fish count.
*
@@ -121,13 +126,18 @@ public class PlayerFish implements Listener {
toolStats.logger.warning(fishingRod + " does not have valid fish-caught set! Resting to zero. This should NEVER happen.");
}
fishCaught++;
container.set(toolStats.fishingRodCaught, PersistentDataType.INTEGER, fishCaught);
container.set(toolStats.fishingRodCaught, PersistentDataType.INTEGER, fishCaught + 1);
if (toolStats.config.getBoolean("enabled.fish-caught")) {
String fishCaughtFormatted = toolStats.numberFormat.formatInt(fishCaught);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{fish}", fishCaughtFormatted, "fished.fish-caught");
meta.setLore(newLore);
String oldFishFormatted = toolStats.numberFormat.formatInt(fishCaught);
String newFishFormatted = toolStats.numberFormat.formatInt(fishCaught + 1);
Component oldLine = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", oldFishFormatted);
Component newLine = toolStats.configTools.formatLore("fished.fish-caught", "{fish}", newFishFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
fishingRod.setItemMeta(meta);
}
@@ -162,8 +172,8 @@ public class PlayerFish implements Listener {
if (toolStats.configTools.checkConfig(newItem.getType(), "fished-tag")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
}
newItem.setItemMeta(meta);
return newItem;

View File

@@ -17,7 +17,9 @@
package lol.hyper.toolstats.events;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -34,6 +36,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
public class PlayerInteract implements Listener {
@@ -64,13 +67,7 @@ public class PlayerInteract implements Listener {
// store when a player opens a chest
if (block.getType() != Material.AIR && block.getType() == Material.CHEST) {
openedChests.put(block, player);
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
openedChests.remove(block);
}
};
toolStats.scheduleGlobal(runnable, 20);
Bukkit.getGlobalRegionScheduler().runDelayed(toolStats, scheduledTask -> openedChests.remove(block), 20);
}
}
@@ -82,16 +79,10 @@ public class PlayerInteract implements Listener {
return;
}
// store when a player opens a minecart
if (clicked.getType() == EntityType.MINECART_CHEST) {
if (clicked.getType() == EntityType.CHEST_MINECART) {
StorageMinecart storageMinecart = (StorageMinecart) clicked;
openedMineCarts.put(storageMinecart, player);
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
openedMineCarts.remove(storageMinecart);
}
};
toolStats.scheduleGlobal(runnable, 20);
Bukkit.getGlobalRegionScheduler().runDelayed(toolStats, scheduledTask -> openedMineCarts.remove(storageMinecart), 20);
}
}
}

View File

@@ -17,9 +17,9 @@
package lol.hyper.toolstats.events;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -32,6 +32,7 @@ import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID;
import java.util.function.Consumer;
public class PlayerJoin implements Listener {
@@ -77,22 +78,8 @@ public class PlayerJoin implements Listener {
String hash = toolStats.hashMaker.makeHash(itemStack.getType(), owner, timestamp);
container.set(toolStats.hash, PersistentDataType.STRING, hash);
}
// add origin tag
if (!container.has(toolStats.originType, PersistentDataType.INTEGER)) {
itemMeta = toolStats.itemLore.getOrigin(itemMeta, itemStack.getType() == Material.ELYTRA);
if (itemMeta == null) {
continue;
}
}
ItemMeta clone = itemMeta.clone();
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
itemStack.setItemMeta(clone);
}
};
toolStats.scheduleEntity(runnable, player, 1);
player.getScheduler().runDelayed(toolStats, scheduledTask -> itemStack.setItemMeta(clone), null, 1);
}
}
}

View File

@@ -0,0 +1,108 @@
/*
* 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.events;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PlayerMove implements Listener {
private final ToolStats toolStats;
private final Map<Player, Long> playerStartFlight = new HashMap<>();
public PlayerMove(ToolStats toolStats) {
this.toolStats = toolStats;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onCraft(PlayerMoveEvent event) {
Player player = event.getPlayer();
// player starts to fly
if (player.isGliding()) {
// if they are flying, and we don't have them tracked, add them
if (!playerStartFlight.containsKey(player)) {
playerStartFlight.put(player, System.currentTimeMillis());
}
} else {
// player is not flying
if (playerStartFlight.containsKey(player)) {
trackFlight(player, playerStartFlight.get(player));
playerStartFlight.remove(player);
}
}
}
private void trackFlight(Player player, long startTime) {
ItemStack chest = player.getInventory().getChestplate();
// make sure their chest piece is an elytra
if (chest == null || chest.getType() != Material.ELYTRA) {
return;
}
ItemMeta meta = chest.getItemMeta();
if (meta == null) {
toolStats.logger.warning(chest + " does NOT have any meta! Unable to update stats.");
return;
}
// read the current stats from the item
// if they don't exist, then start from 0
Long flightTime = 0L;
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(toolStats.flightTime, PersistentDataType.LONG)) {
flightTime = container.get(toolStats.flightTime, PersistentDataType.LONG);
}
if (flightTime == null) {
flightTime = 0L;
toolStats.logger.warning(flightTime + " does not have valid flight-time set! Resting to zero. This should NEVER happen.");
}
// get the duration of the flight
long duration = (System.currentTimeMillis() - startTime);
double newDuration = flightTime + duration;
container.set(toolStats.flightTime, PersistentDataType.LONG, flightTime + duration);
// do we add the lore based on the config?
if (toolStats.config.getBoolean("enabled.flight-time")) {
String oldFlightFormatted = toolStats.numberFormat.formatDouble((double) flightTime / 1000);
String newFlightFormatted = toolStats.numberFormat.formatDouble(newDuration / 1000);
Component oldLine = toolStats.configTools.formatLore("flight-time", "{time}", oldFlightFormatted);
Component newLine = toolStats.configTools.formatLore("flight-time", "{time}", newFlightFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
chest.setItemMeta(meta);
}
}

View File

@@ -18,6 +18,7 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
@@ -32,6 +33,7 @@ import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -53,12 +55,26 @@ public class SheepShear implements Listener {
return;
}
Entity entity = event.getRightClicked();
if (!(entity instanceof Sheep)) {
if (!(entity instanceof Sheep sheep)) {
return;
}
// make sure the player is holding shears
// player can shear with their offhand
ItemStack shears = getShears(player);
// player swapped items?
if (shears == null) {
return;
}
// make sure the sheep is not sheared
if (sheep.isSheared()) {
return;
}
// update the stats
addLore(shears);
}
private static @Nullable ItemStack getShears(Player player) {
PlayerInventory inventory = player.getInventory();
boolean isMainHand = inventory.getItemInMainHand().getType() == Material.SHEARS;
boolean isOffHand = inventory.getItemInOffHand().getType() == Material.SHEARS;
@@ -70,26 +86,12 @@ public class SheepShear implements Listener {
shears = inventory.getItemInOffHand();
}
// if the player is hold fishing rods in both hands
// if the player is hold shears in both hands
// default to main hand since that takes priority
if (isMainHand && isOffHand) {
shears = inventory.getItemInMainHand();
}
// player swapped items?
if (shears == null) {
return;
}
Sheep sheep = (Sheep) entity;
// make sure the sheep is not sheared
if (sheep.isSheared()) {
return;
}
// update the stats
ItemStack finalShears = shears;
addLore(finalShears);
return shears;
}
/**
@@ -114,13 +116,18 @@ public class SheepShear implements Listener {
toolStats.logger.warning(newShears + " does not have valid sheared set! Resting to zero. This should NEVER happen.");
}
sheepSheared++;
container.set(toolStats.shearsSheared, PersistentDataType.INTEGER, sheepSheared);
container.set(toolStats.shearsSheared, PersistentDataType.INTEGER, sheepSheared + 1);
if (toolStats.config.getBoolean("enabled.sheep-sheared")) {
String sheepShearedFormatted = toolStats.numberFormat.formatInt(sheepSheared);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{sheep}", sheepShearedFormatted, "sheep-sheared");
meta.setLore(newLore);
String oldSheepFormatted = toolStats.numberFormat.formatInt(sheepSheared);
String newSheepFormatted = toolStats.numberFormat.formatInt(sheepSheared + 1);
Component oldLine = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", oldSheepFormatted);
Component newLine = toolStats.configTools.formatLore("sheep-sheared", "{sheep}", newSheepFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
newShears.setItemMeta(meta);
}

View File

@@ -18,6 +18,7 @@
package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
@@ -31,6 +32,7 @@ import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -46,16 +48,26 @@ public class ShootBow implements Listener {
public void onShoot(EntityShootBowEvent event) {
Entity shooter = event.getEntity();
// only listen for players
if (!(shooter instanceof Player)) {
if (!(shooter instanceof Player player)) {
return;
}
Player player = (Player) shooter;
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.ADVENTURE) {
return;
}
PlayerInventory inventory = player.getInventory();
ItemStack heldBow = getBow(inventory);
// player swapped
if (heldBow == null) {
return;
}
updateArrowsShot(heldBow);
}
private static @Nullable ItemStack getBow(PlayerInventory inventory) {
boolean isMainHand = inventory.getItemInMainHand().getType() == Material.BOW || inventory.getItemInMainHand().getType() == Material.CROSSBOW;
boolean isOffHand = inventory.getItemInOffHand().getType() == Material.BOW || inventory.getItemInMainHand().getType() == Material.CROSSBOW;
ItemStack heldBow = null;
@@ -71,13 +83,7 @@ public class ShootBow implements Listener {
if (isMainHand && isOffHand) {
heldBow = inventory.getItemInMainHand();
}
// player swapped
if (heldBow == null) {
return;
}
updateArrowsShot(heldBow);
return heldBow;
}
private void updateArrowsShot(ItemStack bow) {
@@ -99,14 +105,19 @@ public class ShootBow implements Listener {
toolStats.logger.warning(arrowsShot + " does not have valid arrows-shot set! Resting to zero. This should NEVER happen.");
}
arrowsShot++;
container.set(toolStats.arrowsShot, PersistentDataType.INTEGER, arrowsShot);
container.set(toolStats.arrowsShot, PersistentDataType.INTEGER, arrowsShot + 1);
// do we add the lore based on the config?
if (toolStats.config.getBoolean("enabled.arrows-shot")) {
String arrowsShotFormatted = toolStats.numberFormat.formatInt(arrowsShot);
List<String> newLore = toolStats.itemLore.addItemLore(meta, "{arrows}", arrowsShotFormatted, "arrows-shot");
meta.setLore(newLore);
String oldArrowsFormatted = toolStats.numberFormat.formatInt(arrowsShot);
String newArrowsFormatted = toolStats.numberFormat.formatInt(arrowsShot + 1);
Component oldLine = toolStats.configTools.formatLore("arrows-shot", "{arrows}", oldArrowsFormatted);
Component newLine = toolStats.configTools.formatLore("arrows-shot", "{arrows}", newArrowsFormatted);
if (oldLine == null || newLine == null) {
return;
}
List<Component> newLore = toolStats.itemLore.updateItemLore(meta, oldLine, newLine);
meta.lore(newLore);
}
bow.setItemMeta(meta);
}

View File

@@ -19,6 +19,7 @@ package lol.hyper.toolstats.events;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.UUIDDataType;
import net.kyori.adventure.text.Component;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
@@ -51,10 +52,9 @@ public class VillagerTrade implements Listener {
return;
}
Inventory inventory = event.getClickedInventory();
if (!(event.getWhoClicked() instanceof Player)) {
if (!(event.getWhoClicked() instanceof Player player)) {
return;
}
Player player = (Player) event.getWhoClicked();
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) {
return;
}
@@ -69,9 +69,9 @@ public class VillagerTrade implements Listener {
}
// if the player shift clicks, show the warning
if (event.isShiftClick()) {
String configMessage = toolStats.config.getString("messages.shift-click-warning.trading");
if (configMessage != null) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', configMessage));
Component component = toolStats.configTools.formatLore("shift-click-warning.trading", null, null);
if (component != null) {
event.getWhoClicked().sendMessage(component);
}
}
ItemStack newItem = addLore(item, player);
@@ -117,8 +117,8 @@ public class VillagerTrade implements Listener {
if (toolStats.configTools.checkConfig(newItem.getType(), "traded-tag")) {
String formattedDate = toolStats.numberFormat.formatDate(finalDate);
List<String> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.setLore(newLore);
List<Component> newLore = toolStats.itemLore.addNewOwner(meta, owner.getName(), formattedDate);
meta.lore(newLore);
}
newItem.setItemMeta(meta);
return newItem;

View File

@@ -47,6 +47,9 @@ public class ItemChecker {
if (lowerCase.contains("_helmet") || lowerCase.contains("_chestplate") || lowerCase.contains("_leggings") || lowerCase.contains("_boots")) {
armorItems.add(material);
}
if (lowerCase.equalsIgnoreCase("mace")) {
meleeItems.add(material);
}
}
// hardcode these
@@ -55,6 +58,7 @@ public class ItemChecker {
validItems.add(Material.BOW);
validItems.add(Material.FISHING_ROD);
validItems.add(Material.CROSSBOW);
validItems.add(Material.ELYTRA);
// combine the lists
validItems.addAll(armorItems);

View File

@@ -18,6 +18,8 @@
package lol.hyper.toolstats.tools;
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.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
@@ -34,49 +36,48 @@ public class ItemLore {
}
/**
* Adds/updates lore for an item.
* Updates existing lore on an item.
*
* @param placeholder The placeholder from the config. ex: {kills}
* @param placeholderValue The value to replace the placeholder.
* @param configLorePath The path to the config message.
* @param itemMeta The item's meta.
* @param oldLine The old line to replace.
* @param newLine The new line to replace oldLine.
* @return The item's new lore.
*/
public List<String> addItemLore(ItemMeta itemMeta, String placeholder, String placeholderValue, String configLorePath) {
String configLore = toolStats.configTools.getLoreFromConfig(configLorePath, false);
String configLoreRaw = toolStats.configTools.getLoreFromConfig(configLorePath, true);
if (configLore == null || configLoreRaw == null) {
toolStats.logger.warning("There is no lore message for messages." + configLorePath + "!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
}
List<String> newLore;
// replace the placeholder with the value
// ex: {kills} -> a number
String newLine = configLoreRaw.replace(placeholder, placeholderValue);
public List<Component> updateItemLore(ItemMeta itemMeta, Component oldLine, Component newLine) {
List<Component> itemLore;
if (itemMeta.hasLore()) {
newLore = itemMeta.getLore();
itemLore = itemMeta.lore();
// keep track of line index
// this doesn't mess the lore of existing items
for (int x = 0; x < newLore.size(); x++) {
// check to see if the line matches the config value
for (int x = 0; x < itemLore.size(); x++) {
Component line = itemLore.get(x);
// find the old line to update, keeping index
// this means we update this line only!
String line = newLore.get(x);
if (line.contains(configLore)) {
newLore.set(x, newLine);
return newLore;
if (line.equals(oldLine)) {
itemLore.set(x, newLine);
return itemLore;
}
}
// if the item has lore, but we didn't find the line
newLore.add(newLine);
itemLore.add(newLine);
} else {
// if the item has no lore, create a new list and add the line
newLore = new ArrayList<>();
newLore.add(newLine);
itemLore = new ArrayList<>();
itemLore.add(newLine);
}
return newLore;
return itemLore;
}
public List<Component> addItemLore(ItemMeta itemMeta, Component newLine) {
List<Component> itemLore;
if (itemMeta.hasLore()) {
itemLore = itemMeta.lore();
itemLore.add(newLine);
} else {
itemLore = new ArrayList<>();
itemLore.add(newLine);
}
return itemLore;
}
/**
@@ -87,9 +88,9 @@ public class ItemLore {
* @param formattedDate The date of the ownership.
* @return The item's new lore.
*/
public List<String> addNewOwner(ItemMeta itemMeta, String playerName, String formattedDate) {
String dateCreatedLore;
String itemOwnerLore;
public List<Component> addNewOwner(ItemMeta itemMeta, String playerName, String formattedDate) {
Component dateCreatedLore;
Component itemOwnerLore;
Integer origin = null;
PersistentDataContainer container = itemMeta.getPersistentDataContainer();
if (container.has(toolStats.originType, PersistentDataType.INTEGER)) {
@@ -100,166 +101,107 @@ public class ItemLore {
if (origin == null) {
toolStats.logger.info("Unable to determine origin for item " + itemMeta.getAsString());
toolStats.logger.info("This IS a bug, please report this to the GitHub.");
return itemMeta.getLore();
return itemMeta.lore();
}
// set the lore based on the origin
switch (origin) {
case 2: {
dateCreatedLore = toolStats.configTools.getLoreFromConfig("looted.looted-on", true);
itemOwnerLore = toolStats.configTools.getLoreFromConfig("looted.looted-by", true);
dateCreatedLore = toolStats.configTools.formatLore("looted.looted-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("looted.looted-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.looted.looted-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.looted.looted-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
break;
}
case 3: {
dateCreatedLore = toolStats.configTools.getLoreFromConfig("traded.traded-on", true);
itemOwnerLore = toolStats.configTools.getLoreFromConfig("traded.traded-by", true);
dateCreatedLore = toolStats.configTools.formatLore("traded.traded-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("traded.traded-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.traded.traded-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.traded.traded-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
break;
}
case 4: {
dateCreatedLore = toolStats.configTools.getLoreFromConfig("looted.found-on", true);
itemOwnerLore = toolStats.configTools.getLoreFromConfig("looted.found-by", true);
dateCreatedLore = toolStats.configTools.formatLore("looted.found-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("looted.found-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.looted.found-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.looted.found-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
break;
}
case 5: {
dateCreatedLore = toolStats.configTools.getLoreFromConfig("fished.caught-on", true);
itemOwnerLore = toolStats.configTools.getLoreFromConfig("fished.caught-by", true);
dateCreatedLore = toolStats.configTools.formatLore("fished.caught-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("fished.caught-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.fished.caught-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.fished.caught-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
break;
}
case 6: {
dateCreatedLore = toolStats.configTools.getLoreFromConfig("spawned-in.spawned-on", true);
itemOwnerLore = toolStats.configTools.getLoreFromConfig("spawned-in.spawned-by", true);
dateCreatedLore = toolStats.configTools.formatLore("spawned-in.spawned-on", "{date}", formattedDate);
itemOwnerLore = toolStats.configTools.formatLore("spawned-in.spawned-by", "{player}", playerName);
if (dateCreatedLore == null) {
toolStats.logger.warning("messages.spawned-in.spawned-on is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
if (itemOwnerLore == null) {
toolStats.logger.warning("messages.spawned-in.spawned-by is not set in your config!");
toolStats.logger.warning("Unable to update lore for item.");
return itemMeta.getLore();
return itemMeta.lore();
}
break;
}
default: {
toolStats.logger.warning("Origin " + origin + " was found. Data was modified OR something REALLY broke.");
toolStats.logger.warning(itemMeta.getAsString());
return itemMeta.getLore();
return itemMeta.lore();
}
}
List<String> newLore;
List<Component> newLore;
if (itemMeta.hasLore()) {
newLore = itemMeta.getLore();
newLore = itemMeta.lore();
} else {
newLore = new ArrayList<>();
}
newLore.add(dateCreatedLore.replace("{date}", formattedDate));
newLore.add(itemOwnerLore.replace("{player}", playerName));
newLore.add(dateCreatedLore);
newLore.add(itemOwnerLore);
return newLore;
}
/**
* Determine an item's origin based on lore.
*
* @param itemMeta The item's meta.
* @param elytra If they item is an elytra.
* @return The new item meta with the new origin tag. Returns null if origin cannot be determined.
*/
public ItemMeta getOrigin(ItemMeta itemMeta, boolean elytra) {
List<String> lore;
if (!itemMeta.hasLore()) {
return null;
}
lore = itemMeta.getLore();
Integer origin = null;
String createdBy = toolStats.configTools.getLoreFromConfig("created.created-by", false);
String createdOn = toolStats.configTools.getLoreFromConfig("created.created-on", false);
String caughtBy = toolStats.configTools.getLoreFromConfig("fished.caught-by", false);
String lootedBy = toolStats.configTools.getLoreFromConfig("looted.looted-by", false);
String foundBy = toolStats.configTools.getLoreFromConfig("looted.found-by", false);
String tradedBy = toolStats.configTools.getLoreFromConfig("traded.traded-by", false);
for (String line : lore) {
// this is the worst code I have ever written
if (createdBy != null && line.contains(createdBy)) {
origin = 0;
}
if (createdOn != null && line.contains(createdOn)) {
origin = 0;
}
if (caughtBy != null && line.contains(caughtBy)) {
origin = 5;
}
if (lootedBy != null && line.contains(lootedBy)) {
origin = 2;
}
// because the config changed, "found-by" was being used for ALL looted items
// this includes elytras, so we have to check for this mistake
if (foundBy != null && line.contains(foundBy)) {
if (elytra) {
origin = 4;
} else {
origin = 5;
}
}
if (tradedBy != null && line.contains(tradedBy)) {
origin = 3;
}
}
if (origin == null) {
return null;
}
PersistentDataContainer container = itemMeta.getPersistentDataContainer();
container.set(toolStats.originType, PersistentDataType.INTEGER, origin);
return itemMeta;
}
}

View File

@@ -18,15 +18,20 @@
package lol.hyper.toolstats.tools.config;
import lol.hyper.toolstats.ToolStats;
import org.bukkit.ChatColor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Material;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ConfigTools {
private final ToolStats toolStats;
private final Pattern COLOR_CODES = Pattern.compile("(?i)&[0-9A-FK-ORX]");
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) {
this.toolStats = toolStats;
@@ -67,96 +72,74 @@ public class ConfigTools {
itemType = itemName.substring(itemName.indexOf('_') + 1);
}
switch (itemType) {
case "pickaxe": {
return toolStats.config.getBoolean("enabled." + configName + ".pickaxe");
}
case "sword": {
return toolStats.config.getBoolean("enabled." + configName + ".sword");
}
case "shovel": {
return toolStats.config.getBoolean("enabled." + configName + ".shovel");
}
case "axe": {
return toolStats.config.getBoolean("enabled." + configName + ".axe");
}
case "hoe": {
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;
return switch (itemType) {
case "pickaxe" -> toolStats.config.getBoolean("enabled." + configName + ".pickaxe");
case "sword" -> toolStats.config.getBoolean("enabled." + configName + ".sword");
case "shovel" -> toolStats.config.getBoolean("enabled." + configName + ".shovel");
case "axe" -> toolStats.config.getBoolean("enabled." + configName + ".axe");
case "hoe" -> toolStats.config.getBoolean("enabled." + configName + ".hoe");
case "shears" -> toolStats.config.getBoolean("enabled." + configName + ".shears");
case "crossbow", "bow" -> toolStats.config.getBoolean("enabled." + configName + ".bow");
case "trident" -> toolStats.config.getBoolean("enabled." + configName + ".trident");
case "fishing-rod" -> toolStats.config.getBoolean("enabled." + configName + ".fishing-rod");
case "mace" -> toolStats.config.getBoolean("enabled." + configName + ".mace");
case "helmet", "chestplate", "leggings", "boots" ->
toolStats.config.getBoolean("enabled." + configName + ".armor");
default -> false;
};
}
/**
* Gets the lore message from the config.
* Format a string to be ready for lore usage.
*
* @param configName The config name, "messages." is already in front.
* @param raw If you want the raw message with the formatting codes and placeholders.
* @return The lore message.
* @param configName The message to use.
* @param placeHolder The placeholder text in the message.
* @param value The value to set the placeholder.
* @return Formatted string, null if the configName doesn't exist.
*/
public String getLoreFromConfig(String configName, boolean raw) {
public Component formatLore(String configName, String placeHolder, Object value) {
String lore = toolStats.config.getString("messages." + configName);
if (lore == null) {
toolStats.logger.warning("Unable to find config message for: messages." + configName);
return null;
}
if (raw) {
return ChatColor.translateAlternateColorCodes('&', lore);
} else {
// remove all color codes
// this is used to compare the current lore on the item
// Example: [§7Arrows shot: §8] is on the lore
// this will return [Arrows shot: ] so we can match it
lore = COLOR_CODES.matcher(lore).replaceAll("");
if (lore.contains("{player}")) {
lore = lore.replace("{player}", "");
}
if (lore.contains("{date}")) {
lore = lore.replace("{date}", "");
}
if (lore.contains("{name}")) {
lore = lore.replace("{name}", "");
}
if (lore.contains("{kills}")) {
lore = lore.replace("{kills}", "");
}
if (lore.contains("{blocks}")) {
lore = lore.replace("{blocks}", "");
}
if (lore.contains("{sheep}")) {
lore = lore.replace("{sheep}", "");
}
if (lore.contains("{damage}")) {
lore = lore.replace("{damage}", "");
}
if (lore.contains("{fish}")) {
lore = lore.replace("{fish}", "");
}
if (lore.contains("{crops}")) {
lore = lore.replace("{crops}", "");
}
if (lore.contains("{arrows}")) {
lore = lore.replace("{arrows}", "");
}
// if the config message is empty, don't send it
if (lore.isEmpty()) {
return null;
}
return lore;
// the final component for this lore
Component component;
// set the placeholder to the value
if (placeHolder != null && value != null) {
lore = lore.replace(placeHolder, String.valueOf(value));
}
// if we match the old color codes, then format them as so
Matcher hexMatcher = CONFIG_HEX_PATTERN.matcher(lore);
Matcher colorMatcher = COLOR_CODES.matcher(lore);
if (hexMatcher.find() || colorMatcher.find()) {
component = LegacyComponentSerializer.legacyAmpersand().deserialize(lore);
} else {
// otherwise format them normally
component = Component.text(lore);
}
return component.decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE);
}
/**
* Remove all color codes from a message.
*
* @param message The message.
* @return The message without color codes.
*/
public String removeColor(String message) {
message = MINECRAFT_HEX_PATTERN.matcher(message).replaceAll("");
message = COLOR_CODES.matcher(message).replaceAll("");
message = CONFIG_HEX_PATTERN.matcher(message).replaceAll("");
return message;
}
}

View File

@@ -36,6 +36,8 @@ package lol.hyper.toolstats.tools.config;
import lol.hyper.toolstats.ToolStats;
import lol.hyper.toolstats.tools.config.versions.Version6;
import lol.hyper.toolstats.tools.config.versions.Version7;
import lol.hyper.toolstats.tools.config.versions.Version8;
public class ConfigUpdater {
@@ -48,10 +50,25 @@ public class ConfigUpdater {
public void updateConfig() {
int version = toolStats.config.getInt("config-version");
// this will be a switch in the future
if (version == 5) {
Version6 version6 = new Version6(toolStats);
version6.update();
switch(version) {
case 5: {
// Version 5 to 6
Version6 version6 = new Version6(toolStats);
version6.update();
break;
}
case 6: {
// Version 6 to 7
Version7 version7 = new Version7(toolStats);
version7.update();
break;
}
case 7: {
// Version 7 to 8
Version8 version8 = new Version8(toolStats);
version8.update();
break;
}
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* This file is part of ToolStats.
*
* ToolStats is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ToolStats is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ToolStats. If not, see <https://www.gnu.org/licenses/>.
*/
package lol.hyper.toolstats.tools.config.versions;
import lol.hyper.toolstats.ToolStats;
import java.io.File;
import java.io.IOException;
public class Version7 {
private final ToolStats toolStats;
/**
* Used for updating from version 6 to 7.
*
* @param toolStats ToolStats instance.
*/
public Version7(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-6.yml");
} catch (IOException exception) {
toolStats.logger.severe("Unable to save config-6.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 7.");
toolStats.config.set("config-version", 7);
toolStats.logger.info("Adding messages.flight-time to config.yml.");
toolStats.config.set("messages.flight-time", "&7Flight time: &8{time}");
toolStats.logger.info("Adding enabled.flight-time to config.yml.");
toolStats.config.set("enabled.flight-time", true);
// 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 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
bow: true
armor: true
mace: true
# Will show time the item is created
created-date:
pickaxe: true
@@ -19,6 +20,7 @@ enabled:
shears: true
bow: true
armor: true
mace: true
# Will show "Fished by <player>"
fished-tag:
pickaxe: true
@@ -54,11 +56,13 @@ enabled:
axe: true
trident: true
bow: true
mace: true
mob-kills:
sword: true
axe: true
trident: true
bow: true
mace: true
blocks-mined:
pickaxe: true
shovel: true
@@ -75,12 +79,14 @@ enabled:
shears: true
bow: true
armor: true
mace: true
fish-caught: true
sheep-sheared: true
armor-damage: true
dropped-by: true
elytra-tag: true
arrows-shot: true
flight-time: true
messages:
created:
@@ -110,11 +116,15 @@ messages:
dropped-by: "&7Dropped by: &8{name}" # name will be player/mob name
damage-taken: "&7Damage taken: &8{damage}"
arrows-shot: "&7Arrows shot: &8{arrows}"
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
# that is crafted. The tag will only be added to the first item. If you don't want this message, simply replace them both with ""
shift-click-warning:
crafting: "&cCrafting items via shift clicking does not fully apply tags to each item. This is a limitation with the Bukkit API."
trading: "&cTrading items via shift clicking does not fully apply tags to each item. This is a limitation with the Bukkit API."
# Set display name for mobs. See: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html
mobs:
ZOMBIE: "Zombie"
# Change the default formatting for dates.
# See: https://www.digitalocean.com/community/tutorials/java-simpledateformat-java-date-format
@@ -134,4 +144,4 @@ number-formats:
# This has no use currently, but can be used for future features for dupe detection.
generate-hash-for-items: true
config-version: 6
config-version: 7

View File

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