Compare commits

...
76 Commits
Author SHA1 Message Date
tr7zw 05da1c6b1c Bump version for tag 2020-04-02 01:18:13 +02:00
tr7zw 8b861f6c7a Update NBTContainer.java 2020-04-01 17:01:30 +02:00
tr7zw 58c744dab7 Update NBTContainer.java 2020-04-01 16:50:54 +02:00
tr7zw 8c75990918 Add null (and other) checks for userInput 2020-04-01 04:34:25 +02:00
tr7zw e6fa7bca63 Adding the missing Lists
Float, Double and Long lists
2020-03-21 14:48:40 +01:00
tr7zw 6eff3d9cdc Merge pull request #72 from tr7zw/dependabot/maven/org.javassist-javassist-3.27.0-GA
Bump javassist from 3.26.0-GA to 3.27.0-GA
2020-03-21 13:40:13 +01:00
dependabot-preview[bot] 492372519a Bump javassist from 3.26.0-GA to 3.27.0-GA
Bumps [javassist](https://github.com/jboss-javassist/javassist) from 3.26.0-GA to 3.27.0-GA.
- [Release notes](https://github.com/jboss-javassist/javassist/releases)
- [Commits](https://github.com/jboss-javassist/javassist/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-20 05:16:29 +00:00
tr7zw 054a7f5173 Merge pull request #71 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.2.0
Bump maven-javadoc-plugin from 3.1.1 to 3.2.0
2020-03-17 00:24:21 +01:00
dependabot-preview[bot] a7b73fda9d Bump maven-javadoc-plugin from 3.1.1 to 3.2.0
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.1.1...maven-javadoc-plugin-3.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 05:26:07 +00:00
tr7zw fd9bbe093b Add Equals unittest 2020-03-12 22:12:09 +01:00
tr7zw 92108a218c Override NBTCompound equals and hashcode to use the toString result 2020-03-12 21:57:21 +01:00
tr7zw 340fd2ae63 Add Stream API 2020-03-12 21:50:32 +01:00
tr7zw 371d55cd1f Fix merge, Fix 1.13 Injector
Thanks to DefinitlyEvil, fixes #70
2020-03-12 20:49:33 +01:00
tr7zw fe8e50d788 Merge pull request #69 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.2.2
Bump maven-shade-plugin from 3.2.1 to 3.2.2
2020-02-13 10:22:30 +01:00
dependabot-preview[bot] 834d0bc6e3 Bump maven-shade-plugin from 3.2.1 to 3.2.2
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.2.1...maven-shade-plugin-3.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-13 05:13:45 +00:00
tr7zw 0a31d709e3 Merge pull request #66 from tr7zw/dependabot/maven/com.github.ekryd.sortpom-sortpom-maven-plugin-2.11.0
Bump sortpom-maven-plugin from 2.10.0 to 2.11.0
2020-02-05 16:39:36 +01:00
dependabot-preview[bot] 19254b5214 Bump sortpom-maven-plugin from 2.10.0 to 2.11.0
Bumps [sortpom-maven-plugin](https://github.com/Ekryd/sortpom) from 2.10.0 to 2.11.0.
- [Release notes](https://github.com/Ekryd/sortpom/releases)
- [Commits](https://github.com/Ekryd/sortpom/compare/sortpom-parent-2.10.0...sortpom-parent-2.11.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-04 05:14:11 +00:00
tr7zw 188942887e Add TauCubed 2020-01-26 18:24:35 +01:00
tr7zw ab1b6e5fa8 Add Gaby 2020-01-25 21:53:44 +01:00
tr7zw c684f9f288 Add all-contributors section 2020-01-25 18:42:56 +01:00
tr7zw 4a3fbf135b Update README.md 2020-01-18 15:28:02 +01:00
tr7zw 1e3e8dc5d9 Update README.md 2020-01-18 14:57:04 +01:00
tr7zw be0fc09cb3 Update README.md 2020-01-18 14:55:19 +01:00
tr7zw a9a248c7cf Small stuff and making method names clearer 2020-01-17 01:42:21 +01:00
tr7zw 26e3c5b913 Add NBTGameProfile for converting 2020-01-17 00:58:09 +01:00
tr7zw 2585ef0a50 Add the persistentDataContainer for Entities 2020-01-16 19:36:46 +01:00
tr7zw 0754250af9 Add functional-annotations
Starting to make avaliable 1.14+ PersistentDataAPI containers
2020-01-16 19:01:54 +01:00
tr7zw 922c32c91b Update FUNDING.yml 2020-01-15 11:09:32 +01:00
tr7zw c7e01f2660 Delete the selftest file first, incase it's corrupted 2020-01-06 22:36:37 +01:00
tr7zw cb67076324 Bump nbt-data-api to 2.3.0-SNAPSHOT 2020-01-06 19:56:29 +01:00
tr7zw b691c6972c Merge remote-tracking branch 'origin/NbtDataApi' 2020-01-06 19:54:53 +01:00
tr7zw cec0222114 bump to 2.3.0-SNAPSHOT 2020-01-06 19:54:47 +01:00
tr7zw 61fd8669f0 Prepare Tag 2.2.0 2019-12-31 15:23:28 +01:00
tr7zw aa54a91c40 clean pom 2019-12-31 15:18:21 +01:00
tr7zw 739b449254 Merge branch 'master' into NbtDataApi 2019-12-31 01:40:54 +01:00
tr7zw d97a050e1a Fix bug in nbtcompound to ItemStack method, added simple ItemStack getter/setter 2019-12-31 01:36:23 +01:00
tr7zw e3da9bf20e Lazy Plugin (Player) data getter 2019-12-31 00:24:12 +01:00
tr7zw 259b184829 include 2019-12-30 19:00:46 +01:00
tr7zw 58bbcbe888 Init nbt-data-api 2019-12-30 18:57:47 +01:00
tr7zw 8479479c84 Handle async bstats init
Fixes #59
2019-12-30 15:50:52 +01:00
tr7zw 6129125dd9 Add toString to lists 2019-12-30 12:00:39 +01:00
tr7zw 43baa7c2ef Detect future Versions, real version checking 2019-12-30 01:28:45 +01:00
tr7zw c6cbc3b309 Fix build 2019-12-30 00:14:02 +01:00
tr7zw 39fd158c56 Add update check 2019-12-29 20:13:11 +01:00
tr7zw 2202dc38e0 Lists fix previous, but not sure how correct it compared to how it should work 2019-12-29 19:14:17 +01:00
tr7zw 656b7caff2 Fix List's Iterator/ListIterator off-by-one Error
List Iterator's previous is probably still broken
2019-12-29 19:01:20 +01:00
tr7zw 0918f25716 Remove debug message 2019-12-26 01:49:58 +01:00
tr7zw 662ad04a5e Removed custom toString (now uses asNBTString), CompList AddCompound got a helper method for auto copy 2019-12-26 01:45:02 +01:00
tr7zw daf684931f More stacked list tests, fix java 11 javadoc 2019-12-26 01:16:32 +01:00
tr7zw 99b5775855 Merge pull request #58 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-source-plugin-3.2.1
Bump maven-source-plugin from 3.2.0 to 3.2.1
2019-12-23 13:04:57 +01:00
dependabot-preview[bot] 87a6fce52f Bump maven-source-plugin from 3.2.0 to 3.2.1
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/apache/maven-source-plugin/releases)
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.0...maven-source-plugin-3.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-23 05:20:46 +00:00
tr7zw 0a46bce99c Fix javadoc 2019-12-23 01:42:35 +01:00
tr7zw a1a3c0be33 Make CompoundLists extend NBTCompounds, so now they feature all methods
This took way to long...........
2019-12-23 00:09:19 +01:00
tr7zw bbf5064a15 fuuuu 2019-12-21 21:49:31 +01:00
tr7zw 437c69b7f4 Wups setAccessible 2019-12-21 21:23:23 +01:00
tr7zw ede8ebba6b Trying to fix Reflections for Java 11+
This is related to #50
2019-12-21 18:23:15 +01:00
tr7zw 54d1ed019f Throw exception on NBT-Injector use without enableing it
Fixes #51
2019-12-21 16:14:33 +01:00
tr7zw 4491709645 Bump version to 2.2.0-SNAPSHOT 2019-12-21 16:07:11 +01:00
tr7zw 34abb0aefb Merge pull request #57 from SoSeDiK/injector
Injector: Updated fields' names for 1.15 support
2019-12-21 15:59:00 +01:00
SoSeDiK 2522edac6b Updated fields' names for 1.15 support 2019-12-20 23:03:04 +02:00
tr7zw f64ac8e3ac 1.15 update, 2.2.1 2019-12-13 19:27:04 +01:00
tr7zw 5d3188a813 Merge branch 'master' of https://github.com/tr7zw/Item-NBT-API 2019-12-13 18:27:32 +01:00
tr7zw fc85d7f4ec Add 1.15 to testing 2019-12-13 18:26:09 +01:00
tr7zw 6063f8a27d Merge pull request #54 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-source-plugin-3.2.0
Bump maven-source-plugin from 3.1.0 to 3.2.0
2019-11-04 10:33:33 +01:00
dependabot-preview[bot] f203a0c8bc Bump maven-source-plugin from 3.1.0 to 3.2.0
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/apache/maven-source-plugin/releases)
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.1.0...maven-source-plugin-3.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-04 08:59:27 +00:00
tr7zw 0bec8d4025 Merge pull request #48 from tr7zw/e3ndr-readme-update
Update README.md
2019-10-17 20:17:09 +02:00
Ender 56abfad7a1 Update README.md 2019-10-17 12:37:15 -05:00
tr7zw e96ae3227e Merge pull request #47 from tr7zw/github-completebuild
Try full build + on pull_request
2019-10-09 15:10:47 +02:00
tr7zw b727e33227 Try full build + on pull_request 2019-10-09 14:50:06 +02:00
tr7zw be13f4bd5e Fix snapshot build 2019-10-09 11:03:02 +02:00
tr7zw 18d03036a9 Add missing Entity mappings for 1.14 2019-10-07 16:48:53 +02:00
tr7zw edeb9051e7 Fix dependency 2019-10-07 16:32:56 +02:00
tr7zw 5b17a25c23 Change to 2.1.1-SNAPSHOT 2019-10-07 16:30:44 +02:00
tr7zw 9f8208347b Merge pull request #45 from tr7zw/GithubActionsBuild
Update maven.yml
2019-10-01 10:05:52 +02:00
tr7zw 6e3ab1fb7e Update maven.yml 2019-10-01 10:02:04 +02:00
tr7zw 7587df8ef2 Forgot to increment version in MetricsLite. Sadly to late now 2019-09-24 01:44:38 +02:00
54 changed files with 2174 additions and 707 deletions

No files matched your search

+163
View File
@@ -0,0 +1,163 @@
{
"projectName": "Item-NBT-API",
"projectOwner": "tr7zw",
"imageSize": 100,
"contributorsPerLine": 7,
"repoHost": "https://github.com",
"types": {
"discord": {
"symbol": "🤝",
"description": "Discord help"
}
},
"contributors": [
{
"login": "sgdc3",
"name": "Gabriele C.",
"avatar_url": "https://avatars3.githubusercontent.com/u/8779252?s=460&v=4",
"profile": "https://github.com/sgdc3",
"contributions": [
"code",
"infra"
],
"links": {
"infra": "https://codemc.io/"
}
},
{
"login": "SoSeDiK",
"name": "SoSeDiK",
"avatar_url": "https://avatars0.githubusercontent.com/u/19875118?s=460&v=4",
"profile": "https://github.com/SoSeDiK",
"contributions": [
"code",
"userTesting"
],
"links": {
"userTesting": "https://github.com/SoSeDiK?tab=repositories"
}
},
{
"login": "e3ndr",
"name": "Ender",
"avatar_url": "https://avatars1.githubusercontent.com/u/33337309?s=460&v=4",
"profile": "https://github.com/e3ndr",
"contributions": [
"doc",
"discord"
],
"links": {
"doc": "https://github.com/tr7zw/Item-NBT-API/wiki"
}
},
{
"login": "inventivetalentdev",
"name": "Haylee Schäfer",
"avatar_url": "https://avatars3.githubusercontent.com/u/6525296?s=460&v=4",
"profile": "https://github.com/inventivetalentdev",
"contributions": [
"code",
"ideas"
],
"links": {
"code": "https://github.com/tr7zw/Item-NBT-API/tree/master/nbt-injector",
"ideas": "https://github.com/InventivetalentDev/NBTInjector"
}
},
{
"login": "SpiGet",
"name": "SpiGet",
"avatar_url": "https://avatars3.githubusercontent.com/u/15632072?s=200&v=4",
"profile": "https://spiget.org/",
"contributions": [
"plugin"
],
"links": {
"plugin": "https://github.com/tr7zw/Item-NBT-API/blob/master/item-nbt-api/src/main/java/de/tr7zw/changeme/nbtapi/utils/VersionChecker.java"
}
},
{
"login": "bStats",
"name": "bStats",
"avatar_url": "https://avatars2.githubusercontent.com/u/5033001?s=460&v=4",
"profile": "https://github.com/Bastian/bStats",
"contributions": [
"plugin"
],
"links": {
"plugin": "https://bstats.org/plugin/bukkit/ItemNBTAPI/1058"
}
},
{
"login": "MrAxeTv",
"name": "MrAxeTv",
"avatar_url": "https://avatars0.githubusercontent.com/u/17033332?s=460&v=4",
"profile": "https://github.com/MrAxeTv",
"contributions": [
"financial",
"userTesting",
"discord"
],
"links": {
"financial": "https://tr7zw.dev/donate/",
"userTesting": "https://www.spigotmc.org/resources/beastwithdraw-multy-withdraw-plugin.13896/"
}
},
{
"login": "MrDienns",
"name": "Dennis van der Veeke",
"avatar_url": "https://avatars3.githubusercontent.com/u/15938901?s=460&v=4",
"profile": "https://github.com/MrDienns",
"contributions": [
"financial"
],
"links": {
"financial": "https://tr7zw.dev/donate/"
}
},
{
"login": "iGabyTM",
"name": "Gabriel Dumitru",
"avatar_url": "https://avatars2.githubusercontent.com/u/32105478?s=460&v=4",
"profile": "https://github.com/iGabyTM",
"contributions": [
"discord"
]
},
{
"login": "TauCubed",
"name": "TauCubed",
"avatar_url": "https://avatars0.githubusercontent.com/u/35522873?s=460&v=4",
"profile": "https://github.com/TauCubed",
"contributions": [
"discord"
]
},
{
"login": "LoneDev",
"name": "LoneDev",
"avatar_url": "https://www.spigotmc.org/data/avatars/l/88/88296.jpg?1563463602",
"profile": "https://www.spigotmc.org/members/lonedev.88296",
"contributions": [
"ideas",
"financial"
],
"links": {
"ideas": "https://www.spigotmc.org/threads/nbt-api.70503/page-7#post-3652832",
"financial": "https://tr7zw.dev/donate/"
}
},
{
"login": "GC.",
"name": "GC.",
"avatar_url": "https://www.spigotmc.org/data/avatars/l/25/25090.jpg?1502396477",
"profile": "https://www.spigotmc.org/members/gc.25090",
"contributions": [
"financial"
],
"links": {
"financial": "https://tr7zw.dev/donate/"
}
}
]
}
+2 -2
View File
@@ -1,4 +1,4 @@
# These are supported funding model platforms
custom: https://paypal.me/tr7zw
patreon: tr7zw
custom: https://tr7zw.dev/donate/
+17
View File
@@ -0,0 +1,17 @@
name: Java CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Maven
run: mvn --file pom.xml
+40 -2
View File
@@ -1,8 +1,46 @@
# Item-NBT-API
Add custom NBT tags to Items without NMS!
Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it Files, other NBT or as String in yaml/json/SQL/Redis.
[Server Owner/Developer Wiki](https://github.com/tr7zw/Item-NBT-API/wiki)
### Build/Maven/Sonar Status
[![Build Status](https://ci.codemc.org/buildStatus/icon?job=Tr7zw%2FItem-NBT-API)](https://ci.codemc.org/job/Tr7zw/job/Item-NBT-API/)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=alert_status)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=ncloc)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)
### SpigotMC Status
[![Version](https://badges.spiget.org/resources/version/Version-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/rating/Rating-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/downloads/SpigotDownloads-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![bStats Servers](https://img.shields.io/bstats/servers/1058.svg?color=green&label=OnlineServers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)[![bStats Players](https://img.shields.io/bstats/players/1058.svg?color=green&label=OnlinePlayers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)
[![Version](https://badges.spiget.org/resources/version/Version-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/rating/Rating-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/downloads/SpigotDownloads-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![bStats Servers](https://img.shields.io/bstats/servers/1058.svg?color=green&label=OnlineServers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)[![bStats Players](https://img.shields.io/bstats/players/1058.svg?color=green&label=OnlinePlayers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)[![All Contributors](https://img.shields.io/badge/all_contributors-12-green.svg?style=plastic)](#contributors-%e2%9c%a8)
[![bStats Stats](https://bstats.org/signatures/bukkit/ItemNBTAPI.svg)](https://bstats.org/plugin/bukkit/ItemNBTAPI)
## Getting started
Import the API [using Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven), then check out the [basic usage](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API) or code examples like [working with Skulls](https://github.com/tr7zw/Item-NBT-API/wiki/Set-a-skull's-skin-using-NBT-API).
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://github.com/sgdc3"><img src="https://avatars3.githubusercontent.com/u/8779252?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Gabriele C.</b></sub></a><br /><a href="https://github.com/tr7zw/Item-NBT-API/commits?author=sgdc3" title="Code">💻</a> <a href="https://codemc.io/" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center"><a href="https://github.com/SoSeDiK"><img src="https://avatars0.githubusercontent.com/u/19875118?s=460&v=4" width="100px;" alt=""/><br /><sub><b>SoSeDiK</b></sub></a><br /><a href="https://github.com/tr7zw/Item-NBT-API/commits?author=SoSeDiK" title="Code">💻</a> <a href="https://github.com/SoSeDiK?tab=repositories" title="User Testing">📓</a></td>
<td align="center"><a href="https://github.com/e3ndr"><img src="https://avatars1.githubusercontent.com/u/33337309?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Ender</b></sub></a><br /><a href="https://github.com/tr7zw/Item-NBT-API/wiki" title="Documentation">📖</a> <a href="#discord-e3ndr" title="Discord help">🤝</a></td>
<td align="center"><a href="https://github.com/inventivetalentdev"><img src="https://avatars3.githubusercontent.com/u/6525296?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Haylee Schäfer</b></sub></a><br /><a href="https://github.com/tr7zw/Item-NBT-API/tree/master/nbt-injector" title="Code">💻</a> <a href="https://github.com/InventivetalentDev/NBTInjector" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://spiget.org/"><img src="https://avatars3.githubusercontent.com/u/15632072?s=200&v=4" width="100px;" alt=""/><br /><sub><b>SpiGet</b></sub></a><br /><a href="https://github.com/tr7zw/Item-NBT-API/blob/master/item-nbt-api/src/main/java/de/tr7zw/changeme/nbtapi/utils/VersionChecker.java" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="https://github.com/Bastian/bStats"><img src="https://avatars2.githubusercontent.com/u/5033001?s=460&v=4" width="100px;" alt=""/><br /><sub><b>bStats</b></sub></a><br /><a href="https://bstats.org/plugin/bukkit/ItemNBTAPI/1058" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="https://github.com/MrAxeTv"><img src="https://avatars0.githubusercontent.com/u/17033332?s=460&v=4" width="100px;" alt=""/><br /><sub><b>MrAxeTv</b></sub></a><br /><a href="https://tr7zw.dev/donate/" title="Financial Support">💵</a> <a href="https://www.spigotmc.org/resources/beastwithdraw-multy-withdraw-plugin.13896/" title="User Testing">📓</a> <a href="#discord-MrAxeTv" title="Discord help">🤝</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/MrDienns"><img src="https://avatars3.githubusercontent.com/u/15938901?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Dennis van der Veeke</b></sub></a><br /><a href="https://tr7zw.dev/donate/" title="Financial Support">💵</a></td>
<td align="center"><a href="https://github.com/iGabyTM"><img src="https://avatars2.githubusercontent.com/u/32105478?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Gabriel Dumitru</b></sub></a><br /><a href="#discord-iGabyTM" title="Discord help">🤝</a></td>
<td align="center"><a href="https://github.com/TauCubed"><img src="https://avatars0.githubusercontent.com/u/35522873?s=460&v=4" width="100px;" alt=""/><br /><sub><b>TauCubed</b></sub></a><br /><a href="#discord-TauCubed" title="Discord help">🤝</a></td>
<td align="center"><a href="https://www.spigotmc.org/members/lonedev.88296"><img src="https://www.spigotmc.org/data/avatars/l/88/88296.jpg?1563463602" width="100px;" alt=""/><br /><sub><b>LoneDev</b></sub></a><br /><a href="https://www.spigotmc.org/threads/nbt-api.70503/page-7#post-3652832" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://tr7zw.dev/donate/" title="Financial Support">💵</a></td>
<td align="center"><a href="https://www.spigotmc.org/members/gc.25090"><img src="https://www.spigotmc.org/data/avatars/l/25/25090.jpg?1502396477" width="100px;" alt=""/><br /><sub><b>GC.</b></sub></a><br /><a href="https://tr7zw.dev/donate/" title="Financial Support">💵</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://allcontributors.org) specification.
Contributions of any kind are welcome! Shoot me a message or pullrequest to be added!
+53 -13
View File
@@ -1,20 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.1.0</version>
</parent>
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.3.0</version>
</parent>
<artifactId>item-nbt-api</artifactId>
<packaging>jar</packaging>
<artifactId>item-nbt-api</artifactId>
<packaging>jar</packaging>
<build>
<defaultGoal>clean install javadoc:javadoc</defaultGoal>
</build>
<dependencies>
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>functional-annotations</artifactId>
<version>0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install javadoc:javadoc</defaultGoal>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<id>shade</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>de.tr7zw.annotations</pattern>
<shadedPattern>de.tr7zw.changeme.nbtapi.utils.annotations</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,8 +1,11 @@
package de.tr7zw.changeme.nbtapi;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Set;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
@@ -23,6 +26,11 @@ public class NBTCompound {
this.parent = owner;
}
protected void saveCompound(){
if(parent != null)
parent.saveCompound();
}
/**
* @return The Compound name
*/
@@ -56,6 +64,7 @@ public class NBTCompound {
*/
public void mergeCompound(NBTCompound comp) {
NBTReflectionUtil.mergeOtherNBTCompound(this, comp);
saveCompound();
}
/**
@@ -66,6 +75,7 @@ public class NBTCompound {
*/
public void setString(String key, String value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_STRING, key, value);
saveCompound();
}
/**
@@ -90,6 +100,7 @@ public class NBTCompound {
*/
public void setInteger(String key, Integer value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INT, key, value);
saveCompound();
}
/**
@@ -110,6 +121,7 @@ public class NBTCompound {
*/
public void setDouble(String key, Double value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_DOUBLE, key, value);
saveCompound();
}
/**
@@ -130,6 +142,7 @@ public class NBTCompound {
*/
public void setByte(String key, Byte value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTE, key, value);
saveCompound();
}
/**
@@ -150,6 +163,7 @@ public class NBTCompound {
*/
public void setShort(String key, Short value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_SHORT, key, value);
saveCompound();
}
/**
@@ -170,6 +184,7 @@ public class NBTCompound {
*/
public void setLong(String key, Long value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_LONG, key, value);
saveCompound();
}
/**
@@ -190,6 +205,7 @@ public class NBTCompound {
*/
public void setFloat(String key, Float value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_FLOAT, key, value);
saveCompound();
}
/**
@@ -210,6 +226,7 @@ public class NBTCompound {
*/
public void setByteArray(String key, byte[] value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTEARRAY, key, value);
saveCompound();
}
/**
@@ -230,6 +247,7 @@ public class NBTCompound {
*/
public void setIntArray(String key, int[] value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INTARRAY, key, value);
saveCompound();
}
/**
@@ -250,10 +268,12 @@ public class NBTCompound {
*/
public void setBoolean(String key, Boolean value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BOOLEAN, key, value);
saveCompound();
}
protected void set(String key, Object val) {
NBTReflectionUtil.set(this, key, val);
saveCompound();
}
/**
@@ -274,6 +294,7 @@ public class NBTCompound {
*/
public void setObject(String key, Object value) {
NBTReflectionUtil.setObject(this, key, value);
saveCompound();
}
/**
@@ -286,6 +307,28 @@ public class NBTCompound {
public <T> T getObject(String key, Class<T> type) {
return NBTReflectionUtil.getObject(this, key, type);
}
/**
* Save an ItemStack as a compound under a given key
*
* @param key
* @param item
*/
public void setItemStack(String key, ItemStack item){
removeKey(key);
addCompound(key).mergeCompound(NBTItem.convertItemtoNBT(item));
}
/**
* Get an ItemStack that was saved at the given key
*
* @param key
* @return
*/
public ItemStack getItemStack(String key){
NBTCompound comp = getCompound(key);
return NBTItem.convertNBTtoItem(comp);
}
/**
* @param key
@@ -303,6 +346,7 @@ public class NBTCompound {
*/
public void removeKey(String key) {
NBTReflectionUtil.remove(this, key);
saveCompound();
}
/**
@@ -325,6 +369,7 @@ public class NBTCompound {
NBTCompound comp = getCompound(name);
if(comp == null)
throw new NbtApiException("Error while adding Compound, got null!");
saveCompound();
return comp;
}
@@ -346,7 +391,9 @@ public class NBTCompound {
* @return The retrieved String List
*/
public NBTList<String> getStringList(String name) {
return NBTReflectionUtil.getList(this, name, NBTType.NBTTagString, String.class);
NBTList<String> list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagString, String.class);
saveCompound();
return list;
}
/**
@@ -354,7 +401,39 @@ public class NBTCompound {
* @return The retrieved Integer List
*/
public NBTList<Integer> getIntegerList(String name) {
return NBTReflectionUtil.getList(this, name, NBTType.NBTTagInt, Integer.class);
NBTList<Integer> list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagInt, Integer.class);
saveCompound();
return list;
}
/**
* @param name
* @return The retrieved Float List
*/
public NBTList<Float> getFloatList(String name) {
NBTList<Float> list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagFloat, Float.class);
saveCompound();
return list;
}
/**
* @param name
* @return The retrieved Double List
*/
public NBTList<Double> getDoubleList(String name) {
NBTList<Double> list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagDouble, Double.class);
saveCompound();
return list;
}
/**
* @param name
* @return The retrieved Long List
*/
public NBTList<Long> getLongList(String name) {
NBTList<Long> list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagLong, Long.class);
saveCompound();
return list;
}
/**
@@ -362,7 +441,9 @@ public class NBTCompound {
* @return The retrieved Compound List
*/
public NBTCompoundList getCompoundList(String name) {
return (NBTCompoundList) NBTReflectionUtil.getList(this, name, NBTType.NBTTagCompound, NBTListCompound.class);
NBTCompoundList list = (NBTCompoundList) NBTReflectionUtil.getList(this, name, NBTType.NBTTagCompound, NBTListCompound.class);
saveCompound();
return list;
}
/**
@@ -377,22 +458,29 @@ public class NBTCompound {
return null;
return NBTType.valueOf((byte) o);
}
public void writeCompound(OutputStream stream) {
NBTReflectionUtil.writeApiNBT(this, stream);
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
/*StringBuilder result = new StringBuilder();
for (String key : getKeys()) {
result.append(toString(key));
}
return result.toString();
return result.toString();*/
return asNBTString();
}
/**
* @deprecated Just use toString()
* @param key
* @return A string representation of the given key
*/
@Deprecated
public String toString(String key) {
StringBuilder result = new StringBuilder();
/*StringBuilder result = new StringBuilder();
NBTCompound compound = this;
while (compound.getParent() != null) {
result.append(" ");
@@ -402,12 +490,15 @@ public class NBTCompound {
return this.getCompound(key).toString();
} else {
return result + "-" + key + ": " + getContent(key) + System.lineSeparator();
}
}*/
return asNBTString();
}
/**
* @deprecated Just use toString()
* @return A json valid nbt string for this Compound
*/
@Deprecated
public String asNBTString() {
Object comp = NBTReflectionUtil.gettoCompount(getCompound(), this);
if (comp == null)
@@ -415,4 +506,22 @@ public class NBTCompound {
return comp.toString();
}
@Override
public int hashCode() {
return toString().hashCode();
}
/**
* Uses the nbt-string to match this compound with another object.
* This allows two "technically" different Compounds to match, if they have the same content
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
return toString().equals(obj.toString());
}
}
@@ -24,6 +24,17 @@ public class NBTCompoundList extends NBTList<NBTListCompound> {
* @return The added {@link NBTListCompound}
*/
public NBTListCompound addCompound() {
return (NBTListCompound) addCompound(null);
}
/**
* Adds a copy of the Compound to the end of the List and returns it.
* When null is given, a new Compound will be created
*
* @param comp
* @return
*/
public NBTCompound addCompound(NBTCompound comp) {
try {
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
@@ -31,7 +42,12 @@ public class NBTCompoundList extends NBTList<NBTListCompound> {
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
return new NBTListCompound(this, compound);
getParent().saveCompound();
NBTListCompound listcomp = new NBTListCompound(this, compound);
if(comp != null){
listcomp.mergeCompound(comp);
}
return listcomp;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
@@ -40,25 +56,15 @@ public class NBTCompoundList extends NBTList<NBTListCompound> {
/**
* Adds a new Compound to the end of the List.
*
* @param empty This has to be null!
*
* @deprecated Please use addCompound!
* @param empty
* @return True, if compound was added
*/
@Override
@Deprecated
public boolean add(NBTListCompound empty) {
if (empty != null) {
throw new NotImplementedException("You need to pass null! ListCompounds from other lists won't work.");
}
try {
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, 0, compound);
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
return true;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
return addCompound(empty) != null;
}
@Override
@@ -73,6 +79,7 @@ public class NBTCompoundList extends NBTList<NBTListCompound> {
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
super.getParent().saveCompound();
} catch (Exception ex) {
throw new NbtApiException(ex);
}
@@ -1,5 +1,8 @@
package de.tr7zw.changeme.nbtapi;
import java.io.InputStream;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
@@ -29,9 +32,25 @@ public class NBTContainer extends NBTCompound {
*/
public NBTContainer(Object nbt) {
super(null, null);
if (nbt == null) {
throw new NullPointerException("The NBT-Object can't be null!");
}
if (!ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().isAssignableFrom(nbt.getClass())) {
throw new NbtApiException("The object '" + nbt.getClass() + "' is not a valid NBT-Object!");
}
this.nbt = nbt;
}
/**
* Reads in a NBT InputStream
*
* @param inputsteam
*/
public NBTContainer(InputStream inputsteam) {
super(null, null);
this.nbt = NBTReflectionUtil.readNBT(inputsteam);
}
/**
* Parses in a NBT String to a standalone {@link NBTCompound}. Can throw a
* {@link NbtApiException} in case something goes wrong.
@@ -40,6 +59,9 @@ public class NBTContainer extends NBTCompound {
*/
public NBTContainer(String nbtString) {
super(null, null);
if (nbtString == null) {
throw new NullPointerException("The String can't be null!");
}
try {
nbt = ReflectionMethod.PARSE_NBT.run(null, nbtString);
} catch (Exception ex) {
@@ -0,0 +1,45 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Double implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTDoubleList extends NBTList<Double> {
protected NBTDoubleList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Double object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGDOUBLE.getClazz().getDeclaredConstructor(double.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Double get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Double.valueOf(obj.toString());
} catch (NumberFormatException nf) {
return 0d;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -2,6 +2,11 @@ package de.tr7zw.changeme.nbtapi;
import org.bukkit.entity.Entity;
import de.tr7zw.annotations.FAUtil;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.annotations.AvaliableSince;
import de.tr7zw.changeme.nbtapi.utils.annotations.CheckUtil;
/**
* NBT class to access vanilla tags from Entities. Entities don't support custom
* tags. Use the NBTInjector for custom tags. Changes will be instantly applied
@@ -19,6 +24,9 @@ public class NBTEntity extends NBTCompound {
*/
public NBTEntity(Entity entity) {
super(null, null);
if (entity == null || entity.isDead()) {
throw new NullPointerException("Entity can't be null/dead!");
}
ent = entity;
}
@@ -32,4 +40,24 @@ public class NBTEntity extends NBTCompound {
NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent));
}
/**
* Gets the NBTCompound used by spigots PersistentDataAPI. This method is only
* available for 1.14+!
*
* @return NBTCompound containing the data of the PersistentDataAPI
*/
@AvaliableSince(version = MinecraftVersion.MC1_14_R1)
public NBTCompound getPersistentDataContainer() {
FAUtil.check(this::getPersistentDataContainer, CheckUtil::isAvaliable);
if (hasKey("BukkitValues")) {
return getCompound("BukkitValues");
} else {
NBTContainer container = new NBTContainer();
container.addCompound("BukkitValues").setString("__nbtapi",
"Marker to make the PersistentDataContainer have content");
mergeCompound(container);
return getCompound("BukkitValues");
}
}
}
@@ -27,10 +27,13 @@ public class NBTFile extends NBTCompound {
*/
public NBTFile(File file) throws IOException {
super(null, null);
if (file == null) {
throw new NullPointerException("File can't be null!");
}
this.file = file;
if (file.exists()) {
FileInputStream inputsteam = new FileInputStream(file);
nbt = NBTReflectionUtil.readNBTFile(inputsteam);
nbt = NBTReflectionUtil.readNBT(inputsteam);
} else {
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
save();
@@ -49,7 +52,7 @@ public class NBTFile extends NBTCompound {
throw new IOException("Unable to create file at " + file.getAbsolutePath());
}
FileOutputStream outStream = new FileOutputStream(file);
NBTReflectionUtil.saveNBTFile(nbt, outStream);
NBTReflectionUtil.writeNBT(nbt, outStream);
}
/**
@@ -0,0 +1,45 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Float implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTFloatList extends NBTList<Float> {
protected NBTFloatList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Float object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGFLOAT.getClazz().getDeclaredConstructor(float.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Float get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Float.valueOf(obj.toString());
} catch (NumberFormatException nf) {
return 0f;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -0,0 +1,30 @@
package de.tr7zw.changeme.nbtapi;
import com.mojang.authlib.GameProfile;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
public class NBTGameProfile {
/**
* Convert a GameProfile to NBT. The NBT then can be modified or be stored
*
* @param profile
* @return A NBTContainer with all the GameProfile data
*/
public static NBTCompound toNBT(GameProfile profile) {
return new NBTContainer(ReflectionMethod.GAMEPROFILE_SERIALIZE.run(null, ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(), profile));
}
/**
* Reconstructs a GameProfile from a NBTCompound
*
* @param compound Has to contain GameProfile data
* @return The reconstructed GameProfile
*/
public static GameProfile fromNBT(NBTCompound compound) {
return (GameProfile) ReflectionMethod.GAMEPROFILE_DESERIALIZE.run(null, NBTReflectionUtil.gettoCompount(compound.getCompound(), compound));
}
}
@@ -1,5 +1,6 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
@@ -20,10 +21,12 @@ public class NBTIntegerList extends NBTList<Integer> {
@Override
protected Object asTag(Integer object) {
try {
return ClassWrapper.NMS_NBTTAGINT.getClazz().getConstructor(int.class).newInstance(object);
Constructor<?> con = ClassWrapper.NMS_NBTTAGINT.getClazz().getDeclaredConstructor(int.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Oject " + object + " to it's NMS object!", e);
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@@ -1,5 +1,6 @@
package de.tr7zw.changeme.nbtapi;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
@@ -22,8 +23,8 @@ public class NBTItem extends NBTCompound {
*/
public NBTItem(ItemStack item) {
super(null, null);
if (item == null) {
throw new NullPointerException("ItemStack can't be null!");
if (item == null || item.getType() == Material.AIR) {
throw new NullPointerException("ItemStack can't be null/Air!");
}
bukkitItem = item.clone();
}
@@ -31,6 +31,20 @@ public abstract class NBTList<T> implements List<T> {
this.type = type;
this.listObject = list;
}
/**
* @return Name of this list-compound
*/
public String getName(){
return listName;
}
/**
* @return The Compound's parent Object
*/
public NBTCompound getParent() {
return parent;
}
protected void save() {
parent.set(listName, listObject);
@@ -208,7 +222,7 @@ public abstract class NBTList<T> implements List<T> {
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
private int index = -1;
@Override
public boolean hasNext() {
@@ -234,7 +248,7 @@ public abstract class NBTList<T> implements List<T> {
final NBTList<T> list = this;
return new ListIterator<T>() {
int index = startIndex;
int index = startIndex - 1;
@Override
public void add(T e) {
@@ -248,7 +262,7 @@ public abstract class NBTList<T> implements List<T> {
@Override
public boolean hasPrevious() {
return index > 0;
return index >= 0 && index <= size();
}
@Override
@@ -265,7 +279,9 @@ public abstract class NBTList<T> implements List<T> {
@Override
public T previous() {
return get(--index);
if (!hasPrevious())
throw new NoSuchElementException("Id: " + (index - 1));
return get(index--);
}
@Override
@@ -318,4 +334,10 @@ public abstract class NBTList<T> implements List<T> {
return list;
}
@Override
public String toString() {
return listObject.toString();
}
}
@@ -1,9 +1,5 @@
package de.tr7zw.changeme.nbtapi;
import java.util.Set;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Cut down version of the {@link NBTCompound} for inside
* {@link NBTCompoundList} This Compound implementation is missing the ability
@@ -13,144 +9,34 @@ import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
* @author tr7zw
*
*/
public class NBTListCompound {
public class NBTListCompound extends NBTCompound {
private NBTList<?> owner;
private Object compound;
protected NBTListCompound(NBTList<?> parent, Object obj) {
super(null, null);
owner = parent;
compound = obj;
}
/**
* String setter
*
* @param key
* @param value
*/
public void setString(String key, String value) {
if (value == null) {
remove(key);
return;
}
try {
compound.getClass().getMethod("setString", String.class, String.class).invoke(compound, key, value);
owner.save();
} catch (Exception ex) {
throw new NbtApiException(ex);
}
public NBTList<?> getListParent() {
return owner;
}
/**
* int setter
*
* @param key
* @param value
*/
public void setInteger(String key, int value) {
try {
compound.getClass().getMethod("setInt", String.class, int.class).invoke(compound, key, value);
owner.save();
} catch (Exception ex) {
throw new NbtApiException(ex);
}
@Override
public Object getCompound() {
return compound;
}
/**
* int getter
*
* @param value
* @return Saved value or NMS fallback
*/
public int getInteger(String value) {
try {
return (int) compound.getClass().getMethod("getInt", String.class).invoke(compound, value);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
@Override
protected void setCompound(Object compound) {
this.compound = compound;
}
/**
* double setter
*
* @param key
* @param value
*/
public void setDouble(String key, double value) {
try {
compound.getClass().getMethod("setDouble", String.class, double.class).invoke(compound, key, value);
owner.save();
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
/**
* double getter
*
* @param key
* @return Saved value or NMS fallback
*/
public double getDouble(String key) {
try {
return (double) compound.getClass().getMethod("getDouble", String.class).invoke(compound, key);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
/**
* String getter
*
* @param key
* @return Saved value or NMS fallback
*/
public String getString(String key) {
try {
return (String) compound.getClass().getMethod("getString", String.class).invoke(compound, key);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
/**
* Checks for a given key
*
* @param key
* @return true if the Compound has this key, else false
*/
public boolean hasKey(String key) {
try {
return (boolean) compound.getClass().getMethod("hasKey", String.class).invoke(compound, key);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
/**
* @return Set containing all keys
*/
@SuppressWarnings("unchecked")
public Set<String> getKeys() {
try {
return (Set<String>) ReflectionMethod.LISTCOMPOUND_GET_KEYS.run(compound);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
/**
* Removes a key from the Compound
*
* @param key
*/
public void remove(String key) {
try {
compound.getClass().getMethod("remove", String.class).invoke(compound, key);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
@Override
protected void saveCompound() {
owner.save();
}
}
@@ -0,0 +1,45 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Long implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTLongList extends NBTList<Long> {
protected NBTLongList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Long object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGLONG.getClazz().getDeclaredConstructor(long.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Long get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Long.valueOf(obj.toString().replace("L", ""));
} catch (NumberFormatException nf) {
return 0l;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -1,7 +1,7 @@
package de.tr7zw.changeme.nbtapi;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.Deque;
@@ -47,12 +47,12 @@ public class NBTReflectionUtil {
}
/**
* Reads in a FileInputStream as NMS Compound
* Reads in a InputStream as NMS Compound
*
* @param stream InputStream of any NBT file
* @return NMS Compound
*/
public static Object readNBTFile(FileInputStream stream) {
public static Object readNBT(InputStream stream) {
try {
return ReflectionMethod.NBTFILE_READ.run(null, stream);
} catch (Exception e) {
@@ -61,17 +61,38 @@ public class NBTReflectionUtil {
}
/**
* Writes a NMS Compound to a FileOutputStream
* Writes a NMS Compound to an OutputStream
*
* @param nbt NMS Compound
* @param stream Stream to write to
* @return ???
*/
public static Object saveNBTFile(Object nbt, FileOutputStream stream) {
public static Object writeNBT(Object nbt, OutputStream stream) {
try {
return ReflectionMethod.NBTFILE_WRITE.run(null, nbt, stream);
} catch (Exception e) {
throw new NbtApiException("Exception while saving a NBT File!", e);
throw new NbtApiException("Exception while writing NBT!", e);
}
}
/**
* Writes a Compound to an OutputStream
*
* @param comp Compound
* @param stream Stream to write to
*/
public static void writeApiNBT(NBTCompound comp, OutputStream stream) {
try {
Object nbttag = comp.getCompound();
if (nbttag == null) {
nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
return;
Object workingtag = gettoCompount(nbttag, comp);
ReflectionMethod.NBTFILE_WRITE.run(null, workingtag, stream);
} catch (Exception e) {
throw new NbtApiException("Exception while writing NBT!", e);
}
}
@@ -99,10 +120,11 @@ public class NBTReflectionUtil {
*/
public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) {
try {
Object nmsComp = gettoCompount(nbtcompound.getCompound(), nbtcompound);
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) {
return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nbtcompound.getCompound());
return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nmsComp);
} else {
return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nbtcompound.getCompound());
return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nmsComp);
}
} catch (Exception e) {
throw new NbtApiException("Exception while converting NBTCompound to NMS ItemStack!", e);
@@ -277,10 +299,10 @@ public class NBTReflectionUtil {
/**
* Merges the second {@link NBTCompound} into the first one
*
* @param comp Target for the merge
* @param nbtcompound Data to merge
* @param comp Target for the merge
* @param nbtcompoundSrc Data to merge
*/
public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) {
public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompoundSrc) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
@@ -288,8 +310,15 @@ public class NBTReflectionUtil {
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
Object rootnbttagSrc = nbtcompoundSrc.getCompound();
if (rootnbttagSrc == null) {
rootnbttagSrc = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(nbtcompoundSrc))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtagSrc = gettoCompount(rootnbttagSrc, nbtcompoundSrc);
try {
ReflectionMethod.COMPOUND_MERGE.run(workingtag, nbtcompound.getCompound());
ReflectionMethod.COMPOUND_MERGE.run(workingtag, workingtagSrc);
comp.setCompound(rootnbttag);
} catch (Exception e) {
throw new NbtApiException("Exception while merging two NBTCompounds!", e);
@@ -372,6 +401,12 @@ public class NBTReflectionUtil {
return (NBTList<T>) new NBTCompoundList(comp, key, type, nbt);
} else if (clazz == Integer.class) {
return (NBTList<T>) new NBTIntegerList(comp, key, type, nbt);
} else if (clazz == Float.class) {
return (NBTList<T>) new NBTFloatList(comp, key, type, nbt);
} else if (clazz == Double.class) {
return (NBTList<T>) new NBTDoubleList(comp, key, type, nbt);
} else if (clazz == Long.class) {
return (NBTList<T>) new NBTLongList(comp, key, type, nbt);
} else {
return null;
}
@@ -1,5 +1,6 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
@@ -29,10 +30,12 @@ public class NBTStringList extends NBTList<String> {
@Override
protected Object asTag(String object) {
try {
return ClassWrapper.NMS_NBTTAGSTRING.getClazz().getConstructor(String.class).newInstance(object);
Constructor<?> con = ClassWrapper.NMS_NBTTAGSTRING.getClazz().getDeclaredConstructor(String.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Oject " + object + " to it's NMS object!", e);
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@@ -2,6 +2,11 @@ package de.tr7zw.changeme.nbtapi;
import org.bukkit.block.BlockState;
import de.tr7zw.annotations.FAUtil;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.annotations.AvaliableSince;
import de.tr7zw.changeme.nbtapi.utils.annotations.CheckUtil;
/**
* NBT class to access vanilla tags from TileEntities. TileEntities don't
* support custom tags. Use the NBTInjector for custom tags. Changes will be
@@ -20,6 +25,9 @@ public class NBTTileEntity extends NBTCompound {
*/
public NBTTileEntity(BlockState tile) {
super(null, null);
if (tile == null || !tile.isPlaced()) {
throw new NullPointerException("Tile can't be null/not placed!");
}
this.tile = tile;
}
@@ -33,4 +41,24 @@ public class NBTTileEntity extends NBTCompound {
NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound);
}
/**
* Gets the NBTCompound used by spigots PersistentDataAPI. This method is only
* available for 1.14+!
*
* @return NBTCompound containing the data of the PersistentDataAPI
*/
@AvaliableSince(version = MinecraftVersion.MC1_14_R1)
public NBTCompound getPersistentDataContainer() {
FAUtil.check(this::getPersistentDataContainer, CheckUtil::isAvaliable);
if (hasKey("PublicBukkitValues")) {
return getCompound("PublicBukkitValues");
} else {
NBTContainer container = new NBTContainer();
container.addCompound("PublicBukkitValues").setString("__nbtapi",
"Marker to make the PersistentDataContainer have content");
mergeCompound(container);
return getCompound("PublicBukkitValues");
}
}
}
@@ -1,377 +1,387 @@
package de.tr7zw.changeme.nbtapi.utils;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
import static de.tr7zw.changeme.nbtapi.utils.MinecraftVersion.logger;
/**
* bStats collects some data for plugin authors.
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*
* This class is modified by tr7zw to work when the api is shaded into other peoples plugins.
*/
public class ApiMetricsLite {
private static final String PLUGINNAME = "ItemNBTAPI"; // DO NOT CHANGE THE NAME! else it won't link the data on bStats
private static final String PLUGINVERSION = "2.0.0"; // In case you fork the nbt-api for internal use in your network, plugins and so on, you *may* add that to the version here. (2.x.x-Timolia or something like that?)
// Not sure how good of an idea that is, so maybe just leave it as is ¯\_(ツ)_/¯
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The version of the NBT-Api bStats
public static final int NBT_BSTATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/bukkit";
// Is bStats enabled on this server?
private boolean enabled;
// Should failed requests be logged?
private static boolean logFailedRequests;
// Should the sent data be logged?
private static boolean logSentData;
// Should the response text be logged?
private static boolean logResponseStatusText;
// The uuid of the server
private static String serverUUID;
// The plugin
private Plugin plugin;
/**
* Class constructor.
*
*/
public ApiMetricsLite() {
// The register method just uses any enabled plugin it can find to register. This *shouldn't* cause any problems, since the plugin isn't used any other way.
// Register our service
for(Plugin plug : Bukkit.getPluginManager().getPlugins()) {
plugin = plug;
if(plugin != null)
break;
}
if(plugin == null) {
return;// Didn't find any plugin that could work
}
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
// Check if the config file exists
if (!config.isSet("serverUuid")) {
// Add default values
config.addDefault("enabled", true);
// Every server gets it's unique random id.
config.addDefault("serverUuid", UUID.randomUUID().toString());
// Should failed request be logged?
config.addDefault("logFailedRequests", false);
// Should the sent data be logged?
config.addDefault("logSentData", false);
// Should the response text be logged?
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config.options().header(
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
"To honor their work, you should not disable it.\n" +
"This has nearly no effect on the server performance!\n" +
"Check out https://bStats.org/ to learn more :)"
).copyDefaults(true);
try {
config.save(configFile);
} catch (IOException ignored) { }
}
// Load the data
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
enabled = config.getBoolean("enabled", true);
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if (enabled) {
boolean found = false;
// Search for all other bStats Metrics classes to see if we are the first one
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("NBT_BSTATS_VERSION"); // Create only one instance of the nbt-api bstats.
return;
} catch (NoSuchFieldException ignored) { }
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
found = true; // We aren't the first
break;
} catch (NoSuchFieldException ignored) { }
}
// Register our service
Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal);
if (!found) {
logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
// We are the first!
startSubmitting();
}
}
}
/**
* Checks if bStats is enabled.
*
* @return Whether bStats is enabled or not.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Starts the Scheduler which submits our data every 30 minutes.
*/
private void startSubmitting() {
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (!plugin.isEnabled()) { // Plugin was disabled
timer.cancel();
return;
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000l * 60l * 5l, 1000l * 60l * 30l);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
}
/**
* Gets the plugin specific data.
* This method is called using Reflection.
*
* @return The plugin specific data.
*/
public JsonObject getPluginData() {
JsonObject data = new JsonObject();
data.addProperty("pluginName", PLUGINNAME); // Append the name of the plugin
data.addProperty("pluginVersion", PLUGINVERSION); // Append the version of the plugin
data.add("customCharts", new JsonArray());
return data;
}
/**
* Gets the server specific data.
*
* @return The server specific data.
*/
private JsonObject getServerData() {
// Minecraft specific data
int playerAmount;
try {
// Around MC 1.8 the return type was changed to a collection from an array,
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
} catch (Exception e) {
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = Bukkit.getVersion();
String bukkitName = Bukkit.getName();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
String osName = System.getProperty("os.name");
String osArch = System.getProperty("os.arch");
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JsonObject data = new JsonObject();
data.addProperty("serverUUID", serverUUID);
data.addProperty("playerAmount", playerAmount);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bukkitVersion", bukkitVersion);
data.addProperty("bukkitName", bukkitName);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
/**
* Collects the data and sends it afterwards.
*/
private void submitData() {
final JsonObject data = getServerData();
JsonArray pluginData = new JsonArray();
// Search for all other bStats Metrics classes to get their plugin data
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
try {
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
if (plugin instanceof JsonObject) {
pluginData.add((JsonObject) plugin);
} else { // old bstats version compatibility
try {
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
jsonStringGetter.setAccessible(true);
String jsonString = (String) jsonStringGetter.invoke(plugin);
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
pluginData.add(object);
}
} catch (ClassNotFoundException e) {
// minecraft version 1.14+
if (logFailedRequests) {
logger.log(Level.WARNING, "[NBTAPI][BSTATS] Encountered exception while posting request!", e);
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
}
continue; // continue looping since we cannot do any other thing.
}
}
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
}
}
} catch (NoSuchFieldException ignored) { }
}
data.add("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(new Runnable() {
@Override
public void run() {
try {
// Send the data
sendData(plugin, data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
logger.log(Level.WARNING, "[NBTAPI][BSTATS] Could not submit plugin stats of " + plugin.getName(), e);
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}
}).start();
}
/**
* Sends the data to the bStats server.
*
* @param plugin Any plugin. It's just used to get a logger instance.
* @param data The data to send.
* @throws Exception If the request failed.
*/
private static void sendData(Plugin plugin, JsonObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread()) {
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if (logSentData) {
System.out.println("[NBTAPI][BSTATS] Sending data to bStats: " + data.toString());
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().info("Sending data to bStats: " + data.toString());
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
bufferedReader.close();
if (logResponseStatusText) {
logger.info("[NBTAPI][BSTATS] Sent data to bStats and received response: " + builder.toString());
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
}
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return new byte[0];
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}
}
package de.tr7zw.changeme.nbtapi.utils;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
import static de.tr7zw.changeme.nbtapi.utils.MinecraftVersion.logger;
/**
* bStats collects some data for plugin authors.
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*
* This class is modified by tr7zw to work when the api is shaded into other peoples plugins.
*/
public class ApiMetricsLite {
private static final String PLUGINNAME = "ItemNBTAPI"; // DO NOT CHANGE THE NAME! else it won't link the data on bStats
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The version of the NBT-Api bStats
public static final int NBT_BSTATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/bukkit";
// Is bStats enabled on this server?
private boolean enabled;
// Should failed requests be logged?
private static boolean logFailedRequests;
// Should the sent data be logged?
private static boolean logSentData;
// Should the response text be logged?
private static boolean logResponseStatusText;
// The uuid of the server
private static String serverUUID;
// The plugin
private Plugin plugin;
/**
* Class constructor.
*
*/
public ApiMetricsLite() {
// The register method just uses any enabled plugin it can find to register. This *shouldn't* cause any problems, since the plugin isn't used any other way.
// Register our service
for(Plugin plug : Bukkit.getPluginManager().getPlugins()) {
plugin = plug;
if(plugin != null)
break;
}
if(plugin == null) {
return;// Didn't find any plugin that could work
}
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
// Check if the config file exists
if (!config.isSet("serverUuid")) {
// Add default values
config.addDefault("enabled", true);
// Every server gets it's unique random id.
config.addDefault("serverUuid", UUID.randomUUID().toString());
// Should failed request be logged?
config.addDefault("logFailedRequests", false);
// Should the sent data be logged?
config.addDefault("logSentData", false);
// Should the response text be logged?
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config.options().header(
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
"To honor their work, you should not disable it.\n" +
"This has nearly no effect on the server performance!\n" +
"Check out https://bStats.org/ to learn more :)"
).copyDefaults(true);
try {
config.save(configFile);
} catch (IOException ignored) { }
}
// Load the data
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
enabled = config.getBoolean("enabled", true);
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if (enabled) {
boolean found = false;
// Search for all other bStats Metrics classes to see if we are the first one
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("NBT_BSTATS_VERSION"); // Create only one instance of the nbt-api bstats.
return;
} catch (NoSuchFieldException ignored) { }
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
found = true; // We aren't the first
break;
} catch (NoSuchFieldException ignored) { }
}
boolean fFound = found;
// Register our service
if(Bukkit.isPrimaryThread()){
Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal);
if (!fFound) {
logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
// We are the first!
startSubmitting();
}
}else{
Bukkit.getScheduler().runTask(plugin, () -> {
Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal);
if (!fFound) {
logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
// We are the first!
startSubmitting();
}
});
}
}
}
/**
* Checks if bStats is enabled.
*
* @return Whether bStats is enabled or not.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Starts the Scheduler which submits our data every 30 minutes.
*/
private void startSubmitting() {
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (!plugin.isEnabled()) { // Plugin was disabled
timer.cancel();
return;
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000l * 60l * 5l, 1000l * 60l * 30l);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
}
/**
* Gets the plugin specific data.
* This method is called using Reflection.
*
* @return The plugin specific data.
*/
public JsonObject getPluginData() {
JsonObject data = new JsonObject();
data.addProperty("pluginName", PLUGINNAME); // Append the name of the plugin
data.addProperty("pluginVersion", MinecraftVersion.VERSION); // Append the version of the plugin
data.add("customCharts", new JsonArray());
return data;
}
/**
* Gets the server specific data.
*
* @return The server specific data.
*/
private JsonObject getServerData() {
// Minecraft specific data
int playerAmount;
try {
// Around MC 1.8 the return type was changed to a collection from an array,
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
} catch (Exception e) {
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = Bukkit.getVersion();
String bukkitName = Bukkit.getName();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
String osName = System.getProperty("os.name");
String osArch = System.getProperty("os.arch");
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JsonObject data = new JsonObject();
data.addProperty("serverUUID", serverUUID);
data.addProperty("playerAmount", playerAmount);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bukkitVersion", bukkitVersion);
data.addProperty("bukkitName", bukkitName);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
/**
* Collects the data and sends it afterwards.
*/
private void submitData() {
final JsonObject data = getServerData();
JsonArray pluginData = new JsonArray();
// Search for all other bStats Metrics classes to get their plugin data
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
try {
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
if (plugin instanceof JsonObject) {
pluginData.add((JsonObject) plugin);
} else { // old bstats version compatibility
try {
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
jsonStringGetter.setAccessible(true);
String jsonString = (String) jsonStringGetter.invoke(plugin);
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
pluginData.add(object);
}
} catch (ClassNotFoundException e) {
// minecraft version 1.14+
if (logFailedRequests) {
logger.log(Level.WARNING, "[NBTAPI][BSTATS] Encountered exception while posting request!", e);
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
}
continue; // continue looping since we cannot do any other thing.
}
}
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
}
}
} catch (NoSuchFieldException ignored) { }
}
data.add("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(new Runnable() {
@Override
public void run() {
try {
// Send the data
sendData(plugin, data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
logger.log(Level.WARNING, "[NBTAPI][BSTATS] Could not submit plugin stats of " + plugin.getName(), e);
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}
}).start();
}
/**
* Sends the data to the bStats server.
*
* @param plugin Any plugin. It's just used to get a logger instance.
* @param data The data to send.
* @throws Exception If the request failed.
*/
private static void sendData(Plugin plugin, JsonObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread()) {
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if (logSentData) {
System.out.println("[NBTAPI][BSTATS] Sending data to bStats: " + data.toString());
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().info("Sending data to bStats: " + data.toString());
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
bufferedReader.close();
if (logResponseStatusText) {
logger.info("[NBTAPI][BSTATS] Sent data to bStats and received response: " + builder.toString());
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
}
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return new byte[0];
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}
}
@@ -25,16 +25,21 @@ public enum MinecraftVersion {
MC1_12_R1(1121),
MC1_13_R1(1131),
MC1_13_R2(1132),
MC1_14_R1(1141);
MC1_14_R1(1141),
MC1_15_R1(1151);
private static MinecraftVersion version;
private static Boolean hasGsonSupport;
private static boolean bStatsDisabled = false;
private static boolean disablePackageWarning = false;
private static boolean updateCheckDisabled = false;
/**
* Logger used by the api
*/
public static final Logger logger = Logger.getLogger("NBTAPI");
// NBT-API Version
protected static final String VERSION = "2.3.0";
private final int versionId;
@@ -82,6 +87,12 @@ public enum MinecraftVersion {
} catch (Exception ex) {
logger.log(Level.WARNING, "[NBTAPI] Error enabeling Metrics!", ex);
}
try {
if(!updateCheckDisabled)
VersionChecker.checkForUpdates();
} catch (Exception ex) {
logger.log(Level.WARNING, "[NBTAPI] Error while checking for updates!", ex);
}
// Maven's Relocate is clever and changes strings, too. So we have to use this
// little "trick" ... :D (from bStats)
final String defaultPackage = new String(new byte[] { 'd', 'e', '.', 't', 'r', '7', 'z', 'w', '.', 'c', 'h',
@@ -126,6 +137,14 @@ public enum MinecraftVersion {
public static void disableBStats() {
bStatsDisabled = true;
}
/**
* Disables the update check. Uses Spiget to get the current version and
* prints a warning when outdated.
*/
public static void disableUpdateCheck() {
updateCheckDisabled = true;
}
/**
* Forcefully disables the log message for plugins not shading the API to
@@ -0,0 +1,53 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public final class ReflectionUtil {
private static Field field_modifiers;
static {
try {
field_modifiers = Field.class.getDeclaredField("modifiers");
field_modifiers.setAccessible(true);
} catch (NoSuchFieldException ex) {
try {
// This hacky workaround is for newer jdk versions 11+?
Method fieldGetter = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
fieldGetter.setAccessible(true);
Field[] fields = (Field[]) fieldGetter.invoke(Field.class, false);
for (Field f : fields)
if (f.getName().equals("modifiers")) {
field_modifiers = f;
field_modifiers.setAccessible(true);
break;
}
} catch (Exception e) {
throw new NbtApiException(e);
}
}
if (field_modifiers == null) {
throw new NbtApiException("Unable to init the modifiers Field.");
}
}
public static Field makeNonFinal(Field field) throws IllegalArgumentException, IllegalAccessException {
int mods = field.getModifiers();
if (Modifier.isFinal(mods)) {
field_modifiers.set(field, mods & ~Modifier.FINAL);
}
return field;
}
public static void setFinal(Object obj, Field field, Object newValue)
throws IllegalArgumentException, IllegalAccessException {
field.setAccessible(true);
field = makeNonFinal(field);
field.set(obj, newValue);
}
}
@@ -0,0 +1,106 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Level;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import de.tr7zw.changeme.nbtapi.NBTItem;
/**
* This class uses the Spiget API to check for updates
*
*/
public class VersionChecker {
private static final String USER_AGENT = "nbt-api Version check";
private static final String REQUEST_URL = "https://api.spiget.org/v2/resources/7939/versions?size=100";
protected static void checkForUpdates() throws Exception {
URL url = new URL(REQUEST_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("User-Agent", USER_AGENT);// Set
// User-Agent
// If you're not sure if the request will be successful,
// you need to check the response code and use #getErrorStream if it
// returned an error code
InputStream inputStream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
// This could be either a JsonArray or JsonObject
JsonElement element = new JsonParser().parse(reader);
if (element.isJsonArray()) {
// Is JsonArray
JsonArray updates = (JsonArray) element;
JsonObject latest = (JsonObject) updates.get(updates.size() - 1);
int versionDifference = getVersionDifference(latest.get("name").getAsString());
if (versionDifference == -1) { // Outdated
MinecraftVersion.logger.log(Level.WARNING,
"[NBTAPI] The NBT-API at '" + NBTItem.class.getPackage() + "' seems to be outdated!");
MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION
+ "' Newest Version: " + latest.get("name").getAsString() + "'");
MinecraftVersion.logger.log(Level.WARNING,
"[NBTAPI] Please update the nbt-api or the plugin that contains the api!");
} else if (versionDifference == 0) {
MinecraftVersion.logger.log(Level.INFO, "[NBTAPI] The NBT-API seems to be up-to-date!");
} else if (versionDifference == 1) {
MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] The NBT-API at '" + NBTItem.class.getPackage()
+ "' seems to be a future Version, not yet released on Spigot!");
MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION
+ "' Newest Version: " + latest.get("name").getAsString() + "'");
}
} else {
// wut?!
MinecraftVersion.logger.log(Level.WARNING,
"[NBTAPI] Error when looking for Updates! Got non Json Array: '" + element.toString() + "'");
}
}
// -1 = we are outdated
// 0 = up to date
// 1 = using a future version
// This method is only able to compare the Format 0.0.0(-SNAPSHOT)
private static int getVersionDifference(String version) {
String current = MinecraftVersion.VERSION;
if (current.equals(version))
return 0;
String pattern = "\\.";
if (current.split(pattern).length != 3 || version.split(pattern).length != 3)
return -1;
int curMaj = Integer.parseInt(current.split(pattern)[0]);
int curMin = Integer.parseInt(current.split(pattern)[1]);
String curPatch = current.split(pattern)[2];
int relMaj = Integer.parseInt(version.split(pattern)[0]);
int relMin = Integer.parseInt(version.split(pattern)[1]);
String relPatch = version.split(pattern)[2];
if (curMaj < relMaj)
return -1;
if (curMaj > relMaj)
return 1;
if (curMin < relMin)
return -1;
if (curMin > relMin)
return 1;
int curPatchN = Integer.parseInt(curPatch.split("-")[0]);
int relPatchN = Integer.parseInt(relPatch.split("-")[0]);
if (curPatchN < relPatchN)
return -1;
if (curPatchN > relPatchN)
return 1;
if (!relPatch.contains("-") && curPatch.contains("-"))
return -1; // Release has no - but we do = We use a Snapshot of the
// release
if (relPatch.contains("-") && curPatch.contains("-"))
return 0; // Release and cur are Snapshots/alpha/beta
return 1;
}
}
@@ -0,0 +1,17 @@
package de.tr7zw.changeme.nbtapi.utils.annotations;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
@Retention(RUNTIME)
@Target({ METHOD })
public @interface AvaliableSince {
MinecraftVersion version();
}
@@ -0,0 +1,16 @@
package de.tr7zw.changeme.nbtapi.utils.annotations;
import java.lang.reflect.Method;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
public class CheckUtil {
public static boolean isAvaliable(Method method) {
if(MinecraftVersion.getVersion().getVersionId() < method.getAnnotation(AvaliableSince.class).version().getVersionId())
throw new NbtApiException("The Method '" + method.getName() + "' is only avaliable for the Versions " + method.getAnnotation(AvaliableSince.class).version() + "+, but still got called!");
return true;
}
}
@@ -20,6 +20,9 @@ CRAFT_WORLD(PackageWrapper.CRAFTBUKKIT, "CraftWorld"),
NMS_NBTBASE(PackageWrapper.NMS, "NBTBase"),
NMS_NBTTAGSTRING(PackageWrapper.NMS, "NBTTagString"),
NMS_NBTTAGINT(PackageWrapper.NMS, "NBTTagInt"),
NMS_NBTTAGFLOAT(PackageWrapper.NMS, "NBTTagFloat"),
NMS_NBTTAGDOUBLE(PackageWrapper.NMS, "NBTTagDouble"),
NMS_NBTTAGLONG(PackageWrapper.NMS, "NBTTagLong"),
NMS_ITEMSTACK(PackageWrapper.NMS, "ItemStack"),
NMS_NBTTAGCOMPOUND(PackageWrapper.NMS, "NBTTagCompound"),
NMS_NBTTAGLIST(PackageWrapper.NMS, "NBTTagList"),
@@ -36,7 +39,7 @@ NMS_REGISTRYSIMPLE(PackageWrapper.NMS, "RegistrySimple", MinecraftVersion.MC1_11
NMS_REGISTRYMATERIALS(PackageWrapper.NMS, "RegistryMaterials"),
NMS_IREGISTRY(PackageWrapper.NMS, "IRegistry"),
NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey"),
NMS_GAMEPROFILESERIALIZER(PackageWrapper.NMS, "GameProfileSerializer")
;
private Class<?> clazz;
@@ -3,13 +3,13 @@ package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.logging.Level;
import org.bukkit.inventory.ItemStack;
import com.mojang.authlib.GameProfile;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import static de.tr7zw.changeme.nbtapi.utils.MinecraftVersion.logger;
/**
* This class caches method reflections, keeps track of method name changes between versions and allows early checking for problems
@@ -53,7 +53,7 @@ public enum ReflectionMethod {
COMPOUND_REMOVE_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "remove")),
COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "hasKey")),
COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d")), //FIXME: No Spigot mapping!
COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"), new Since(MinecraftVersion.MC1_15_R1, "e")), //FIXME: No Spigot mapping!
COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
@@ -99,8 +99,10 @@ public enum ReflectionMethod {
REGISTRY_GET_INVERSE (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")), //FIXME: No Spigot mapping!
REGISTRYMATERIALS_KEYSET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "keySet")),
REGISTRYMATERIALS_GET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTKEY.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "get")),
REGISTRYMATERIALS_GETKEY (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_13_R2, "getKey")),
GAMEPROFILE_DESERIALIZE (ClassWrapper.NMS_GAMEPROFILESERIALIZER.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "deserialize")),
GAMEPROFILE_SERIALIZE (ClassWrapper.NMS_GAMEPROFILESERIALIZER.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), GameProfile.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "serialize")),
;
private MinecraftVersion removedAfter;
@@ -127,7 +129,7 @@ public enum ReflectionMethod {
loaded = true;
methodName = targetVersion.name;
}catch(NullPointerException | NoSuchMethodException | SecurityException ex){
System.out.println("[NBTAPI] Unable to find the method '" + targetVersion.name + "' in '" + targetClass.getSimpleName() + "'"); //NOSONAR This gets loaded before the logger is loaded
System.out.println("[NBTAPI] Unable to find the method '" + targetVersion.name + "' in '" + targetClass.getSimpleName() + "' Enum: " + this); //NOSONAR This gets loaded before the logger is loaded
}
}
@@ -143,10 +145,12 @@ public enum ReflectionMethod {
* @return Value returned by the method
*/
public Object run(Object target, Object... args){
try{
if(method == null)
throw new NbtApiException("Method not loaded! '" + this + "'");
try{
return method.invoke(target, args);
}catch(Exception ex){
throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ".", ex);
throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ", Enum: " + this, ex);
}
}
+13 -7
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.1.0</version>
<version>2.3.0</version>
</parent>
<artifactId>item-nbt-api-plugin</artifactId>
<packaging>jar</packaging>
@@ -12,13 +12,19 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.1.0</version>
<version>2.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>nbt-injector</artifactId>
<version>2.1.0</version>
<version>2.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>nbt-data-api</artifactId>
<version>2.3.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -33,7 +39,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<version>3.2.2</version>
<executions>
<execution>
<id>shade</id>
@@ -73,11 +79,11 @@
</execution>
</executions>
<configuration>
<!-- 1.8.8-R0.1-SNAPSHOT-latest, 1.9.2-R0.1-SNAPSHOT-latest, 1.9.4-R0.1-SNAPSHOT-latest, 1.10.2-R0.1-SNAPSHOT-latest,1.11.2,1.12.2,1.13.2,1.14.1,1.14.2,1.14.3,1.14.4 -->
<versions>1.8.8-R0.1-SNAPSHOT-latest, 1.9.2-R0.1-SNAPSHOT-latest, 1.9.4-R0.1-SNAPSHOT-latest, 1.10.2-R0.1-SNAPSHOT-latest,1.11.2,1.12.2,1.13.2,1.14.1,1.14.2,1.14.3,1.14.4</versions>
<!-- 1.8.8-R0.1-SNAPSHOT-latest, 1.9.2-R0.1-SNAPSHOT-latest, 1.9.4-R0.1-SNAPSHOT-latest, 1.10.2-R0.1-SNAPSHOT-latest,1.11.2,1.12.2,1.13.2,1.14.4,1.15.1 -->
<versions>1.8.8-R0.1-SNAPSHOT-latest, 1.9.2-R0.1-SNAPSHOT-latest, 1.9.4-R0.1-SNAPSHOT-latest, 1.10.2-R0.1-SNAPSHOT-latest,1.11.2,1.12.2,1.13.2,1.14.4,1.15.1,1.15.2</versions>
<works>Success! This version of NBT-API</works>
<error>WARNING! This version of NBT-API</error>
<filename>item-nbt-api-plugin-2.1.0.jar</filename>
<filename>item-nbt-api-plugin-${project.version}.jar</filename>
<foldername>item-nbt-plugin</foldername>
</configuration>
</plugin>
@@ -12,18 +12,27 @@ import org.bukkit.plugin.java.JavaPlugin;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
import de.tr7zw.nbtapi.plugin.tests.GameprofileTest;
import de.tr7zw.nbtapi.plugin.tests.NBTFileTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.EqualsTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.ForEachTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.GetterSetterTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.ListTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.MergeTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.RemovingKeys;
import de.tr7zw.nbtapi.plugin.tests.compounds.StreamTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.SubCompoundsTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.TypeTest;
import de.tr7zw.nbtapi.plugin.tests.entities.EntityCustomNbtTest;
import de.tr7zw.nbtapi.plugin.tests.data.WorldDataTest;
import de.tr7zw.nbtapi.plugin.tests.entities.EntityCustomNbtPersistentTest;
import de.tr7zw.nbtapi.plugin.tests.entities.EntityTest;
import de.tr7zw.nbtapi.plugin.tests.injector.EntityCustomNbtInjectorTest;
import de.tr7zw.nbtapi.plugin.tests.injector.MergeTileSubCompoundTest;
import de.tr7zw.nbtapi.plugin.tests.injector.SpawnEntityCustomNbtInjectorTest;
import de.tr7zw.nbtapi.plugin.tests.injector.TilesCustomNBTInjectorTest;
import de.tr7zw.nbtapi.plugin.tests.items.EmptyItemTest;
import de.tr7zw.nbtapi.plugin.tests.items.ItemConvertionTest;
import de.tr7zw.nbtapi.plugin.tests.tiles.TilesCustomNBTTest;
import de.tr7zw.nbtapi.plugin.tests.tiles.TilesCustomNBTPersistentTest;
import de.tr7zw.nbtinjector.NBTInjector;
public class NBTAPI extends JavaPlugin {
@@ -57,6 +66,9 @@ public class NBTAPI extends JavaPlugin {
apiTests.add(new ListTest());
apiTests.add(new SubCompoundsTest());
apiTests.add(new MergeTest());
apiTests.add(new ForEachTest());
apiTests.add(new StreamTest());
apiTests.add(new EqualsTest());
// Items
apiTests.add(new ItemConvertionTest());
@@ -64,13 +76,24 @@ public class NBTAPI extends JavaPlugin {
// Entity
apiTests.add(new EntityTest());
apiTests.add(new EntityCustomNbtTest());
apiTests.add(new EntityCustomNbtPersistentTest());
// Tiles
apiTests.add(new TilesCustomNBTTest());
apiTests.add(new TilesCustomNBTPersistentTest());
// Files
apiTests.add(new NBTFileTest());
// Data
apiTests.add(new WorldDataTest());
// Injector
apiTests.add(new TilesCustomNBTInjectorTest());
apiTests.add(new MergeTileSubCompoundTest());
apiTests.add(new EntityCustomNbtInjectorTest());
apiTests.add(new SpawnEntityCustomNbtInjectorTest());
apiTests.add(new GameprofileTest());
}
@@ -0,0 +1,25 @@
package de.tr7zw.nbtapi.plugin.tests;
import java.util.UUID;
import com.mojang.authlib.GameProfile;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTGameProfile;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public class GameprofileTest implements Test {
@Override
public void test() throws Exception {
UUID uuid = UUID.randomUUID();
GameProfile profile = new GameProfile(uuid, "random");
NBTCompound nbt = NBTGameProfile.toNBT(profile);
profile = null;
profile = NBTGameProfile.fromNBT(nbt);
if (profile == null || !profile.getId().equals(uuid)) {
throw new NbtApiException("Error when converting a GameProfile from/to NBT!");
}
}
}
@@ -14,7 +14,9 @@ public class NBTFileTest implements Test {
@Override
public void test() throws Exception {
NBTAPI.getInstance().getDataFolder().mkdirs();
NBTFile file = new NBTFile(new File(NBTAPI.getInstance().getDataFolder(), "test.nbt"));
File testFile = new File(NBTAPI.getInstance().getDataFolder(), "test.nbt");
Files.deleteIfExists(testFile.toPath());
NBTFile file = new NBTFile(testFile);
file.addCompound("testcomp").setString("test1", "ok");
NBTCompound comp = file.getCompound("testcomp");
comp.setString("test2", "ok");
@@ -30,7 +32,7 @@ public class NBTFileTest implements Test {
throw new NbtApiException("SubCompounds did not work!");
}
NBTFile fileLoaded = new NBTFile(new File(NBTAPI.getInstance().getDataFolder(), "test.nbt"));
NBTFile fileLoaded = new NBTFile(testFile);
if (!fileLoaded.getString("test").equals("test")) {
throw new NbtApiException("Wasn't able to load NBT File with the correct content!");
}
@@ -0,0 +1,32 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NBTItem;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class EqualsTest implements Test{
@Override
public void test() throws Exception {
NBTContainer cont = new NBTContainer();
cont.setString("hello", "world");
cont.setInteger("theAnswer", 42);
cont.addCompound("sub").setString("me", "too");
ItemStack item = new ItemStack(Material.STONE);
NBTItem nbti = new NBTItem(item);
NBTCompound customData = nbti.addCompound("customData");
// reverse order
customData.addCompound("sub").setString("me", "too");
customData.setInteger("theAnswer", 42);
customData.setString("hello", "world");
if(!customData.equals(cont)) {
throw new NbtApiException("Compounds did not match! " + customData + " " + cont);
}
}
}
@@ -0,0 +1,50 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import java.util.ListIterator;
import de.tr7zw.changeme.nbtapi.NBTCompoundList;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NBTListCompound;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
/**
* Test requested by TAU on Discord
*
*/
public class ForEachTest implements Test {
@SuppressWarnings("unused")
@Override
public void test() throws Exception {
NBTContainer comp = new NBTContainer();
NBTCompoundList compList = comp.getCompoundList("testkey");
if (compList != null) {
compList.addCompound().setInteger("id", 1);
compList.addCompound().setInteger("id", 2);
compList.addCompound().setInteger("id", 3);
int count = 0;
for (NBTListCompound listComp : compList) {
count++;
}
if(count != compList.size())
throw new NbtApiException("For loop did not get all Entries!");
count = 0;
ListIterator<NBTListCompound> lit = compList.listIterator();
while(lit.hasNext()){
lit.next();
count++;
}
if(count != compList.size())
throw new NbtApiException("ListIterator did not get all Entries!");
count = 0;
while(lit.hasPrevious()){
lit.previous();
count++;
}
if(count != compList.size())
throw new NbtApiException("ListIterator previous did not get all Entries!");
}
}
}
@@ -2,10 +2,12 @@ package de.tr7zw.nbtapi.plugin.tests.compounds;
import java.util.Arrays;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTCompoundList;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NBTList;
import de.tr7zw.changeme.nbtapi.NBTListCompound;
import de.tr7zw.changeme.nbtapi.NBTType;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
@@ -34,19 +36,33 @@ public class ListTest implements Test {
lcomp.setInteger("int1", 42);
lcomp.setString("test1", "test1");
lcomp.setString("test2", "test2");
lcomp.remove("test1");
lcomp.removeKey("test1");
NBTCompound subsubcomp = lcomp.addCompound("listsubkey");
subsubcomp.setString("deep", "String");
subsubcomp.getCompoundList("deeplist").addCompound().setString("test", "test");
subsubcomp.getCompoundList("clonelist").addCompound(comp);
taglist = null;
lcomp = null;
subsubcomp = null;
taglist = comp.getCompoundList("complist");
if (taglist.size() == 1) {
lcomp = taglist.get(0);
if (lcomp.getKeys().size() != 3) {
if (lcomp.getKeys().size() != 4) {
throw new NbtApiException("Wrong key amount in Taglist (" + lcomp.getKeys().size() + ")!");
} else if (!(lcomp.getDouble("double1") == 0.3333 && lcomp.getInteger("int1") == 42
&& lcomp.getString("test2").equals("test2") && !lcomp.hasKey("test1"))) {
throw new NbtApiException("One key in the Taglist changed! The Item-NBT-API may not work!");
} else if (lcomp.getCompound("listsubkey") == null
|| !"String".equals(lcomp.getCompound("listsubkey").getString("deep"))) {
throw new NbtApiException(
"The Compound nested in the listcompound was not correct! The Item-NBT-API may not work!");
} else if (lcomp.getCompound("listsubkey").getType("deep") != NBTType.NBTTagString) {
throw new NbtApiException("The nested key's type wasn't correct! The Item-NBT-API may not work!");
} else if (lcomp.getCompound("listsubkey").getType("deeplist") != NBTType.NBTTagList) {
throw new NbtApiException("The nested list's type wasn't correct '"
+ lcomp.getCompound("listsubkey").getType("deeplist") + "'! The Item-NBT-API may not work!");
}
} else {
throw new NbtApiException("Taglist is empty! The Item-NBT-API may not work!");
@@ -62,6 +78,36 @@ public class ListTest implements Test {
throw new NbtApiException("IntList is not correct! " + Arrays.toString(intlist.toArray(new Integer[0])));
}
// Double
NBTList<Double> doublelist = comp.getDoubleList("doubletest");
doublelist.add(42.23d);
doublelist.add(69.69d);
if (doublelist.size() == 2 && doublelist.get(0) == 42.23d && doublelist.get(1) == 69.69d) {
// ok
} else {
throw new NbtApiException("DoubleList is not correct! " + Arrays.toString(doublelist.toArray(new Double[0])));
}
// Float
NBTList<Float> floatlist = comp.getFloatList("floattest");
floatlist.add(42.23f);
floatlist.add(69.69f);
if (floatlist.size() == 2 && floatlist.get(0) == 42.23f && floatlist.get(1) == 69.69f) {
// ok
} else {
throw new NbtApiException("FloatList is not correct! " + Arrays.toString(floatlist.toArray(new Float[0])));
}
// Long
NBTList<Long> longlist = comp.getLongList("longtest");
longlist.add(1241234124124l);
longlist.add(1231454321312l);
if (longlist.size() == 2 && longlist.get(0) == 1241234124124l && longlist.get(1) == 1231454321312l) {
// ok
} else {
throw new NbtApiException("LongList is not correct! " + Arrays.toString(longlist.toArray(new Long[0])));
}
}
}
@@ -0,0 +1,26 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class StreamTest implements Test{
@Override
public void test() throws Exception {
NBTContainer base = new NBTContainer();
base.addCompound("sub").setString("hello", "world");
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
base.getCompound("sub").writeCompound(outStream);
byte[] data = outStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
NBTContainer container = new NBTContainer(inputStream);
if(!container.toString().equals(base.getCompound("sub").toString())) {
throw new NbtApiException("Component content did not match! " + base.getCompound("sub") + " " + container);
}
}
}
@@ -0,0 +1,24 @@
package de.tr7zw.nbtapi.plugin.tests.data;
import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.World;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.data.NBTData;
import de.tr7zw.changeme.nbtapi.data.WorldData;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class WorldDataTest implements Test{
@Override
public void test() throws Exception {
for(World world : Bukkit.getWorlds()){
if(!new File(world.getWorldFolder(), "level.dat").exists())continue;
WorldData data = NBTData.getWorldData(world);
if(data.getWorldName() == null || data.getSpawnPosition() == null)throw new NbtApiException("Got Null");
}
}
}
@@ -0,0 +1,41 @@
package de.tr7zw.nbtapi.plugin.tests.entities;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class EntityCustomNbtPersistentTest implements Test {
@Override
public void test() throws Exception {
if(MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_14_R1.getVersionId())return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
if (!world.getEntitiesByClasses(Animals.class, Monster.class).isEmpty()) {
Entity ent = world.getEntitiesByClasses(Animals.class, Monster.class).iterator().next();
NBTEntity nbtEnt = new NBTEntity(ent);
NBTCompound comp = nbtEnt.getPersistentDataContainer();
comp.setString("Hello", "World");
NBTEntity nbtent = new NBTEntity(ent);
if (!nbtent.toString().contains("Hello:\"World\"")) {
throw new NbtApiException("Custom Data did not save to the Entity!");
}
comp.removeKey("Hello");
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTEntities!", ex);
}
}
}
}
@@ -1,41 +1,41 @@
package de.tr7zw.nbtapi.plugin.tests.entities;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
import de.tr7zw.nbtinjector.NBTInjector;
public class EntityCustomNbtTest implements Test {
@Override
public void test() throws Exception {
if(!NBTInjector.isInjected())return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
if (!world.getEntitiesByClasses(Animals.class, Monster.class).isEmpty()) {
Entity ent = world.getEntitiesByClasses(Animals.class, Monster.class).iterator().next();
ent = NBTInjector.patchEntity(ent);
NBTCompound comp = NBTInjector.getNbtData(ent);
comp.setString("Hello", "World");
NBTEntity nbtent = new NBTEntity(ent);
if (!nbtent.asNBTString().contains("__extraData:{Hello:\"World\"}")) {
throw new NbtApiException("Custom Data did not save to the Entity!");
}
comp.removeKey("Hello");
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTEntities!", ex);
}
}
}
}
package de.tr7zw.nbtapi.plugin.tests.injector;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
import de.tr7zw.nbtinjector.NBTInjector;
public class EntityCustomNbtInjectorTest implements Test {
@Override
public void test() throws Exception {
if(!NBTInjector.isInjected())return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
if (!world.getEntitiesByClasses(Animals.class, Monster.class).isEmpty()) {
Entity ent = world.getEntitiesByClasses(Animals.class, Monster.class).iterator().next();
ent = NBTInjector.patchEntity(ent);
NBTCompound comp = NBTInjector.getNbtData(ent);
comp.setString("Hello", "World");
NBTEntity nbtent = new NBTEntity(ent);
if (!nbtent.toString().contains("__extraData:{Hello:\"World\"}")) {
throw new NbtApiException("Custom Data did not save to the Entity!");
}
comp.removeKey("Hello");
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTEntities!", ex);
}
}
}
}
@@ -0,0 +1,46 @@
package de.tr7zw.nbtapi.plugin.tests.injector;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
import de.tr7zw.nbtinjector.NBTInjector;
public class MergeTileSubCompoundTest implements Test {
@Override
public void test() throws Exception {
if (!NBTInjector.isInjected())
return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
boolean failed = false;
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 255,
world.getSpawnLocation().getBlockZ());
if (block.getType() == Material.AIR) {
block.setType(Material.CHEST);
NBTCompound comp = NBTInjector.getNbtData(block.getState());
comp.addCompound("subcomp").setString("hello", "world");
NBTContainer cont = new NBTContainer();
cont.mergeCompound(comp.getCompound("subcomp"));
if (!(cont.hasKey("hello") && "world".equals(cont.getString("hello")))) {
failed = true;
}
block.setType(Material.AIR);
if(failed) {
throw new NbtApiException("Data was not correct! " + cont);
}
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTTiles!", ex);
}
}
}
}
@@ -0,0 +1,41 @@
package de.tr7zw.nbtapi.plugin.tests.injector;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
import de.tr7zw.nbtinjector.NBTInjector;
public class SpawnEntityCustomNbtInjectorTest implements Test {
@Override
public void test() throws Exception {
if (!NBTInjector.isInjected())
return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
Entity entity = world.spawnEntity(new Location(world, 0, 0, 0), EntityType.ARMOR_STAND);
entity = NBTInjector.patchEntity(entity);
NBTCompound comp = NBTInjector.getNbtData(entity);
comp.setString("Hello", "World");
NBTEntity nbtent = new NBTEntity(entity);
if (!nbtent.toString().contains("__extraData:{Hello:\"World\"}")) {
throw new NbtApiException("Custom Data did not save to the Entity!");
}
comp.removeKey("Hello");
entity.remove();
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTEntities!", ex);
}
}
}
}
@@ -1,40 +1,40 @@
package de.tr7zw.nbtapi.plugin.tests.tiles;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTTileEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
import de.tr7zw.nbtinjector.NBTInjector;
public class TilesCustomNBTTest implements Test {
@Override
public void test() throws Exception {
if(!NBTInjector.isInjected())return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 255,
world.getSpawnLocation().getBlockZ());
if (block.getType() == Material.AIR) {
block.setType(Material.CHEST);
NBTCompound comp = NBTInjector.getNbtData(block.getState());
comp.setString("Foo", "Bar");
if (!new NBTTileEntity(block.getState()).asNBTString().contains("__extraData:{Foo:\"Bar\"}")) {
block.setType(Material.AIR);
throw new NbtApiException("Custom Data did not save to the Tile!");
}
block.setType(Material.AIR);
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTTiles!", ex);
}
}
}
}
package de.tr7zw.nbtapi.plugin.tests.injector;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTTileEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
import de.tr7zw.nbtinjector.NBTInjector;
public class TilesCustomNBTInjectorTest implements Test {
@Override
public void test() throws Exception {
if(!NBTInjector.isInjected())return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 255,
world.getSpawnLocation().getBlockZ());
if (block.getType() == Material.AIR) {
block.setType(Material.CHEST);
NBTCompound comp = NBTInjector.getNbtData(block.getState());
comp.setString("Foo", "Bar");
if (!new NBTTileEntity(block.getState()).toString().contains("__extraData:{Foo:\"Bar\"}")) {
block.setType(Material.AIR);
throw new NbtApiException("Custom Data did not save to the Tile!");
}
block.setType(Material.AIR);
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTTiles!", ex);
}
}
}
}
@@ -19,12 +19,17 @@ public class ItemConvertionTest implements Test {
ItemMeta meta = item.getItemMeta();
meta.setLore(Lists.newArrayList("Firest Line", "Second Line"));
item.setItemMeta(meta);
String nbt = NBTItem.convertItemtoNBT(item).asNBTString();
String nbt = NBTItem.convertItemtoNBT(item).toString();
if (!nbt.contains("Firest Line") || !nbt.contains("Second Line"))
throw new NbtApiException("The Item nbt '" + nbt + "' didn't contain the lore");
ItemStack rebuild = NBTItem.convertNBTtoItem(new NBTContainer(nbt));
if (!item.isSimilar(rebuild))
throw new NbtApiException("Rebuilt item did not match the original!");
NBTContainer cont = new NBTContainer();
cont.setItemStack("testItem", item);
if(!cont.getItemStack("testItem").isSimilar(item))
throw new NbtApiException("Rebuilt item did not match the original!");
}
}
@@ -0,0 +1,41 @@
package de.tr7zw.nbtapi.plugin.tests.tiles;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTTileEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class TilesCustomNBTPersistentTest implements Test {
@Override
public void test() throws Exception {
if(MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_14_R1.getVersionId())return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 255,
world.getSpawnLocation().getBlockZ());
if (block.getType() == Material.AIR) {
block.setType(Material.CHEST);
NBTTileEntity comp = new NBTTileEntity(block.getState());
NBTCompound persistentData = comp.getPersistentDataContainer();
persistentData.setString("Foo", "Bar");
if (!new NBTTileEntity(block.getState()).getPersistentDataContainer().toString().contains("Foo:\"Bar\"")) {
block.setType(Material.AIR);
throw new NbtApiException("Custom Data did not save to the Tile!");
}
block.setType(Material.AIR);
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTTiles!", ex);
}
}
}
}
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 tr7zw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.3.0</version>
</parent>
<artifactId>nbt-data-api</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.3.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install javadoc:javadoc</defaultGoal>
</build>
</project>
@@ -0,0 +1,66 @@
package de.tr7zw.changeme.nbtapi.data;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.plugin.Plugin;
import de.tr7zw.changeme.nbtapi.NBTFile;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public class NBTData {
public static WorldData getWorldData(World world) {
try {
return new WorldData(world.getWorldFolder());
} catch (IOException e) {
throw new NbtApiException("Error loading World Data!", e);
}
}
public static WorldData getWorldData(File worldFolder) {
try {
return new WorldData(worldFolder);
} catch (IOException e) {
throw new NbtApiException("Error loading World Data!", e);
}
}
public static PlayerData getOfflinePlayerData(UUID uuid) {
for (World world : Bukkit.getWorlds()) {
File dataFolder = new File(world.getWorldFolder(), "playerdata");
File playerFile = new File(dataFolder, uuid.toString() + ".dat");
if (playerFile.exists()) {
try {
return new PlayerData(playerFile);
} catch (IOException e) {
throw new NbtApiException("Error loading player data!", e);
}
}
}
return null;
}
public static NBTFile getPluginPlayerData(Plugin plugin, UUID uuid) {
try {
File dataFolder = new File(plugin.getDataFolder(), "nbt-playerdata");
dataFolder.mkdirs();
return new NBTFile(new File(dataFolder, uuid.toString() + ".dat"));
} catch (IOException e) {
throw new NbtApiException("Error getting Player Plugin data!", e);
}
}
public static NBTFile getPluginData(Plugin plugin) {
try {
plugin.getDataFolder().mkdirs();
return new NBTFile(new File(plugin.getDataFolder(), "settings.dat"));
} catch (IOException e) {
throw new NbtApiException("Error getting Plugin data!", e);
}
}
}
@@ -0,0 +1,42 @@
package de.tr7zw.changeme.nbtapi.data;
import java.io.File;
import java.io.IOException;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTFile;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public class PlayerData {
private final NBTFile file;
protected PlayerData(File playerFile) throws IOException {
file = new NBTFile(playerFile);
}
public NBTFile getFile() {
return file;
}
public NBTCompound getCompound() {
return file;
}
public void saveChanges() {
try {
file.save();
} catch (IOException e) {
throw new NbtApiException("Error when saving level data!", e);
}
}
public float getHealth(){
return file.getFloat("Health");
}
public void setHealth(float health){
file.setFloat("Health", health);
}
}
@@ -0,0 +1,58 @@
package de.tr7zw.changeme.nbtapi.data;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.bukkit.util.Vector;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTFile;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public class WorldData {
private final NBTFile file;
protected WorldData(File worldFolder) throws IOException {
if(!new File(worldFolder, "level.dat").exists())throw new FileNotFoundException("Level.dat at: " + new File(worldFolder, "level.dat").getAbsolutePath());
file = new NBTFile(new File(worldFolder, "level.dat"));
}
public NBTFile getFile() {
return file;
}
public NBTCompound getCompound() {
return file;
}
public void saveChanges() {
try {
file.save();
} catch (IOException e) {
throw new NbtApiException("Error when saving level data!", e);
}
}
public String getWorldName(){
return file.getCompound("Data").getString("LevelName");
}
public void setWorldName(String name){
file.getCompound("Data").setString("LevelName", name);
}
public Vector getSpawnPosition(){
NBTCompound data = file.getCompound("Data");
return new Vector(data.getInteger("SpawnX"), data.getInteger("SpawnY"), data.getInteger("SpawnZ"));
}
public void setSpawnPosition(Vector vec){
NBTCompound data = file.getCompound("Data");
data.setInteger("SpawnX", vec.getBlockX());
data.setInteger("SpawnY", vec.getBlockY());
data.setInteger("SpawnZ", vec.getBlockZ());
}
}
+3 -3
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.1.0</version>
<version>2.3.0</version>
</parent>
<artifactId>nbt-injector</artifactId>
<packaging>jar</packaging>
@@ -12,13 +12,13 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.1.0</version>
<version>2.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.25.0-GA</version>
<version>3.27.0-GA</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -16,6 +16,7 @@ import org.bukkit.Bukkit;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.ReflectionUtil;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
import de.tr7zw.nbtinjector.NBTInjector.Entity;
@@ -36,6 +37,7 @@ public class InternalInjectors {
private static final List<String> skippingEntities = Arrays.asList("minecraft:player", "minecraft:fishing_bobber",
"minecraft:lightning_bolt"); // These are broken/won't work, used by 1.14+
private static final Map<String, String> classMappings = new HashMap<>();
protected static final Map<Class<?>, Object> classToMCKey = new HashMap<Class<?>, Object>();
static {
classMappings.put("minecraft:wandering_trader", "VillagerTrader");
@@ -64,6 +66,8 @@ public class InternalInjectors {
classMappings.put("minecraft:illusioner", "IllagerIllusioner");
classMappings.put("minecraft:pufferfish", "PufferFish");
classMappings.put("minecraft:cave_spider", "CaveSpider");
classMappings.put("minecraft:item_frame", "ItemFrame");
classMappings.put("minecraft:leash_knot", "Leash");
}
/**
@@ -110,12 +114,13 @@ public class InternalInjectors {
inverse.put(wrapped, mckey);
int id = (int) registryId.getClass().getMethod("getId", new Class[] {Object.class}).invoke(registryId, entclass);
registryId.getClass().getMethod("a", new Class[] {Object.class, int.class}).invoke(registryId, wrapped, id);
classToMCKey.put(entclass, mckey);
} catch (Exception e) {
throw new NbtApiException("Exception while injecting " + mckey, e);
}
}
Field inverseField = registry.getClass().getDeclaredField("b");
NBTInjector.setFinal(registry, inverseField, inverse);
ReflectionUtil.setFinal(registry, inverseField, inverse);
}
protected static void entity1v13Below(ClassPool classPool) throws ReflectiveOperationException {
@@ -134,8 +139,8 @@ public class InternalInjectors {
continue;
} // Already injected
Class<?> wrapped = ClassGenerator.wrapEntity(classPool, nmsclass, "__extraData");
NBTInjector.setFinal(entityTypesObj, classField, wrapped);
NBTInjector.setFinal(entityTypesObj, supplierField, new Function<Object, Object>() {
ReflectionUtil.setFinal(entityTypesObj, classField, wrapped);
ReflectionUtil.setFinal(entityTypesObj, supplierField, new Function<Object, Object>() {
@Override
public Object apply(Object t) {
@@ -147,6 +152,7 @@ public class InternalInjectors {
}
}
});
classToMCKey.put(nmsclass, mckey);
} catch (Exception e) {
throw new NbtApiException("Exception while injecting " + mckey, e);
}
@@ -162,7 +168,10 @@ public class InternalInjectors {
continue;
}
Object entityTypesObj = ReflectionMethod.REGISTRYMATERIALS_GET.run(entityRegistry, mckey);
Field creatorField = entityTypesObj.getClass().getDeclaredField("aZ");
String creatorFieldName = "aZ";
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_15_R1.getVersionId())
creatorFieldName = "ba";
Field creatorField = entityTypesObj.getClass().getDeclaredField(creatorFieldName);
creatorField.setAccessible(true);
Object creator = creatorField.get(entityTypesObj);
Method createEntityMethod = creator.getClass().getMethod("create", ClassWrapper.NMS_ENTITYTYPES.getClazz(),
@@ -193,12 +202,13 @@ public class InternalInjectors {
"Wasn't able to create an Entity instace, won't be able add NBT to '" + mckey + "' entities!");
continue;
}
classToMCKey.put(nmsclass, mckey);
try {
if (INBTWrapper.class.isAssignableFrom(nmsclass)) {
continue;
} // Already injected
Class<?> wrapped = ClassGenerator.wrapEntity(classPool, nmsclass, "__extraData");
NBTInjector.setFinal(entityTypesObj, creatorField,
ReflectionUtil.setFinal(entityTypesObj, creatorField,
ClassGenerator.createEntityTypeWrapper(classPool, wrapped).newInstance());
} catch (Exception e) {
throw new NbtApiException("Exception while injecting " + mckey, e);
@@ -240,7 +250,7 @@ public class InternalInjectors {
}
}
Field inverseField = registry.getClass().getDeclaredField("b");
NBTInjector.setFinal(registry, inverseField, inverse);
ReflectionUtil.setFinal(registry, inverseField, inverse);
}
protected static void tile1v13(ClassPool classPool) throws ReflectiveOperationException {
@@ -249,8 +259,10 @@ public class InternalInjectors {
for (Object mckey : registryentries) {
Object tileEntityTypesObj = ReflectionMethod.REGISTRYMATERIALS_GET.run(tileRegistry, mckey);
String supplierFieldName = "A";
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId())
if (MinecraftVersion.getVersion().getVersionId() == MinecraftVersion.MC1_14_R1.getVersionId())
supplierFieldName = "H";
else if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_15_R1.getVersionId())
supplierFieldName = "I";
Field supplierField = tileEntityTypesObj.getClass().getDeclaredField(supplierFieldName);
supplierField.setAccessible(true);
Supplier<Object> supplier = (Supplier<Object>) supplierField.get(tileEntityTypesObj);
@@ -260,7 +272,7 @@ public class InternalInjectors {
continue;
} // Already injected
Class<?> wrapped = ClassGenerator.wrapTileEntity(classPool, nmsclass, "__extraData");
NBTInjector.setFinal(tileEntityTypesObj, supplierField, new Supplier<Object>() {
ReflectionUtil.setFinal(tileEntityTypesObj, supplierField, new Supplier<Object>() {
@Override
public Object get() {
try {
@@ -2,7 +2,6 @@ package de.tr7zw.nbtinjector;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@@ -37,6 +36,9 @@ public class NBTInjector {
static Logger logger = Logger.getLogger("NBTInjector");
private static boolean isInjected = false;
private static final String NOT_INJECTED_MESSAGE = "The NBTInjector has not been enabled!\n"
+ "You need to call 'NBTInjector.inject()' during the Method 'onLoad' of your Plugin!"
+ " Check the Wiki/Pluginpage for more information!";
/**
* Replaces the vanilla classes with Wrapped classes that support custom NBT.
@@ -105,6 +107,7 @@ public class NBTInjector {
if (entity == null) {
return null;
}
if(!isInjected)throw new NbtApiException(NOT_INJECTED_MESSAGE);
try {
Object ent = NBTReflectionUtil.getNMSEntity(entity);
if (!(ent instanceof INBTWrapper)) {// Replace Entity with custom one
@@ -116,8 +119,10 @@ public class NBTInjector {
String id = "";
if (MinecraftVersion.getVersion().getVersionId() <= MinecraftVersion.MC1_10_R1.getVersionId()) {
id = Entity.getBackupMap().get(ent.getClass());
} else if (MinecraftVersion.getVersion().getVersionId() <= MinecraftVersion.MC1_13_R2.getVersionId()) {
} else if (MinecraftVersion.getVersion().getVersionId() <= MinecraftVersion.MC1_12_R1.getVersionId()) {
id = ReflectionMethod.REGISTRY_GET_INVERSE.run(Entity.getRegistry(), ent.getClass()).toString();
} else if (MinecraftVersion.getVersion().getVersionId() <= MinecraftVersion.MC1_13_R2.getVersionId()) {
id = InternalInjectors.classToMCKey.get(ent.getClass()).toString();
} else {
id = (String) ReflectionMethod.NMS_ENTITY_GETSAVEID.run(ent);
}
@@ -152,6 +157,7 @@ public class NBTInjector {
if (entity == null) {
return null;
}
if(!isInjected)throw new NbtApiException(NOT_INJECTED_MESSAGE);
try {
Object ent = NBTReflectionUtil.getNMSEntity(entity);
if (!(ent instanceof INBTWrapper)) {
@@ -176,6 +182,7 @@ public class NBTInjector {
if (tile == null) {
return null;
}
if(!isInjected)throw new NbtApiException(NOT_INJECTED_MESSAGE);
try {
Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ());
Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld());
@@ -212,17 +219,6 @@ public class NBTInjector {
}
}
protected static void setFinal(Object obj, Field field, Object newValue)
throws NoSuchFieldException, IllegalAccessException {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(obj, newValue);
}
private static Field getAccessable(Field field) {
field.setAccessible(true);
return field;
@@ -248,11 +244,11 @@ public class NBTInjector {
throw new NbtApiException(e);
}
}
static Object getRegistry() throws ReflectiveOperationException {
return getAccessable(ClassWrapper.NMS_ENTITYTYPES.getClazz().getDeclaredField("b")).get(null);
}
static Object getRegistryId(Object reg) throws ReflectiveOperationException {
return getAccessable(reg.getClass().getDeclaredField("a")).get(reg);
}
+42 -5
View File
@@ -3,11 +3,12 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.1.0</version>
<version>2.3.0</version>
<packaging>pom</packaging>
<modules>
<module>item-nbt-api</module>
<module>nbt-injector</module>
<module>nbt-data-api</module>
<module>item-nbt-plugin</module>
</modules>
<properties>
@@ -26,6 +27,12 @@
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>1.5.25</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<!-- CodeMC -->
@@ -34,13 +41,27 @@
<url>https://repo.codemc.org/repository/maven-public/</url>
<layout>default</layout>
</repository>
<!-- CodeMC NMS -->
<!-- CodeMC NMS -->
<repository>
<id>codemc-nms-repo</id>
<url>https://repo.codemc.org/repository/nms/</url>
<layout>default</layout>
</repository>
<!-- Mojang -->
<repository>
<id>mojang-libraries</id>
<url>https://libraries.minecraft.net/</url>
<layout>default</layout>
</repository>
</repositories>
<pluginRepositories>
<!-- CodeMC -->
<pluginRepository>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public/</url>
<layout>default</layout>
</pluginRepository>
</pluginRepositories>
<build>
<defaultGoal>clean install</defaultGoal>
<resources>
@@ -65,7 +86,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
@@ -78,7 +99,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
@@ -87,11 +108,14 @@
</goals>
</execution>
</executions>
<configuration>
<source>8</source>
</configuration>
</plugin>
<plugin>
<groupId>com.github.ekryd.sortpom</groupId>
<artifactId>sortpom-maven-plugin</artifactId>
<version>2.10.0</version>
<version>2.11.0</version>
<executions>
<execution>
<id>sortpom</id>
@@ -101,6 +125,19 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>de.tr7zw</groupId>
<artifactId>allcontributors</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<id>update-contributors</id>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>