mirror of
https://github.com/tr7zw/Item-NBT-API.git
synced 2026-11-05 09:10:23 -05:00
Compare commits
318
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d6aa142de | ||
|
|
cc1436cd09 | ||
|
|
4506dd37da | ||
|
|
bbc02e1299 | ||
|
|
ca9d5ad140 | ||
|
|
25c82a5ad0 | ||
|
|
17d40445d2 | ||
|
|
47ad3591df | ||
|
|
b3652ecf7d | ||
|
|
46a9116613 | ||
|
|
5776be4a35 | ||
|
|
9fbee68966 | ||
|
|
b277f0b01d | ||
|
|
e4793a0d46 | ||
|
|
7c34542b86 | ||
|
|
856bf5ed6d | ||
|
|
123da87a3a | ||
|
|
f3d7545c6b | ||
|
|
3b29fe399e | ||
|
|
c368318bb6 | ||
|
|
c1473dfa97 | ||
|
|
a360ca50f4 | ||
|
|
8b1ca8447e | ||
|
|
b66353d0d0 | ||
|
|
5bec1371d2 | ||
|
|
8cbb6af964 | ||
|
|
309455ecfc | ||
|
|
22c0b0385b | ||
|
|
bc6bd56ce9 | ||
|
|
fcdf0929f9 | ||
|
|
e1c6ce2575 | ||
|
|
2fcc1d82ab | ||
|
|
eec2c0980e | ||
|
|
3ddf3e53dc | ||
|
|
70d5ab12eb | ||
|
|
a63e9ba8f4 | ||
|
|
d8a59d6383 | ||
|
|
943c7d23d6 | ||
|
|
6c70ce2ccc | ||
|
|
c1b7854fbb | ||
|
|
f9f1c204b6 | ||
|
|
789f1fea96 | ||
|
|
0e40144f09 | ||
|
|
1c6315e014 | ||
|
|
91f345adf2 | ||
|
|
71783a8dc9 | ||
|
|
5d06ae9275 | ||
|
|
835fdf48cd | ||
|
|
31d77d25f9 | ||
|
|
6cb08ac919 | ||
|
|
08a92ac06c | ||
|
|
6bcd00d114 | ||
|
|
bc93986392 | ||
|
|
aa646e35ae | ||
|
|
1054d16996 | ||
|
|
9351a86774 | ||
|
|
56a43d246b | ||
|
|
2b895fd4ef | ||
|
|
8f8bbfd034 | ||
|
|
df231c2324 | ||
|
|
b068284b6e | ||
|
|
9e9b85f46a | ||
|
|
3baed4b1e7 | ||
|
|
432b40b3bc | ||
|
|
fdf3638948 | ||
|
|
b240e888cd | ||
|
|
ccc096e2d4 | ||
|
|
35f541d3db | ||
|
|
d4ee3b998c | ||
|
|
2902dca5a5 | ||
|
|
1c1e3c8664 | ||
|
|
7f8f021ced | ||
|
|
98ed1850f6 | ||
|
|
764e01503d | ||
|
|
43d8e2a351 | ||
|
|
689cd4fa3b | ||
|
|
c8f68f8b3b | ||
|
|
e52ba209e6 | ||
|
|
418f5bea07 | ||
|
|
1392e72a8a | ||
|
|
dc39d1d8ef | ||
|
|
a974142a55 | ||
|
|
f014e71020 | ||
|
|
da6be72d29 | ||
|
|
d9a93e9306 | ||
|
|
ba374fe69c | ||
|
|
aa35ee8333 | ||
|
|
3bb0bdd74c | ||
|
|
f3af749b11 | ||
|
|
d81c2b4e8e | ||
|
|
94192feb8f | ||
|
|
af3d9c8502 | ||
|
|
ae98859524 | ||
|
|
70f0bb62f9 | ||
|
|
505e172955 | ||
|
|
d2b2b6a506 | ||
|
|
e2e8aad70a | ||
|
|
4874366e30 | ||
|
|
d2de90ee25 | ||
|
|
a0f93e575e | ||
|
|
b339c9e9c2 | ||
|
|
3425a6672d | ||
|
|
67616266da | ||
|
|
b08e4aa12f | ||
|
|
27411e90da | ||
|
|
73776cfec4 | ||
|
|
bd674e31c0 | ||
|
|
3405ffe0a3 | ||
|
|
f1317bcb04 | ||
|
|
4a32343b95 | ||
|
|
3de6ed83eb | ||
|
|
e5bdce73ea | ||
|
|
410e88a35b | ||
|
|
e3142b4869 | ||
|
|
243a5c2bcd | ||
|
|
045c710366 | ||
|
|
4cd118671f | ||
|
|
d86c91f2e6 | ||
|
|
f8736c8188 | ||
|
|
b3aec54205 | ||
|
|
0f926998f6 | ||
|
|
3a44a5e989 | ||
|
|
30b931945c | ||
|
|
88d8629541 | ||
|
|
00ae0448f4 | ||
|
|
ce26e180e6 | ||
|
|
c939105e45 | ||
|
|
2079123a42 | ||
|
|
31b17fe9c9 | ||
|
|
b565902006 | ||
|
|
5280ba82a2 | ||
|
|
522f732ed1 | ||
|
|
ac84a4d69a | ||
|
|
d7e18c1cb6 | ||
|
|
ffa612634a | ||
|
|
739682122b | ||
|
|
2e20af40e5 | ||
|
|
e6527515be | ||
|
|
e6f33a35ae | ||
|
|
39801ada18 | ||
|
|
75fab7622a | ||
|
|
33eef1bcf1 | ||
|
|
877a42fd06 | ||
|
|
0a7e560e2e | ||
|
|
174728a681 | ||
|
|
79ba1dd275 | ||
|
|
25c59b0eae | ||
|
|
0057d3f2e8 | ||
|
|
59c67a3f0b | ||
|
|
3ec606ae21 | ||
|
|
ff0a94f279 | ||
|
|
53216d3b7d | ||
|
|
7cf23201ce | ||
|
|
fe1d586f44 | ||
|
|
956ef15a1d | ||
|
|
ed867749f8 | ||
|
|
88fbc0140e | ||
|
|
82e52267b8 | ||
|
|
c16548ff4e | ||
|
|
cf30cf996e | ||
|
|
633433d6d0 | ||
|
|
153c72818a | ||
|
|
4798880a53 | ||
|
|
1f149dbae4 | ||
|
|
8570c6f77e | ||
|
|
30f75e0714 | ||
|
|
af7a6b0a1c | ||
|
|
c0a9197113 | ||
|
|
e14dd4f82a | ||
|
|
198dbfabae | ||
|
|
8bd49db49b | ||
|
|
caf1d7cd98 | ||
|
|
027f2a2edd | ||
|
|
b74b0b852e | ||
|
|
6ea6ab7e13 | ||
|
|
372225626c | ||
|
|
2483f9b947 | ||
|
|
fdc16aad69 | ||
|
|
c723eef68b | ||
|
|
03299012ac | ||
|
|
eabf0a9696 | ||
|
|
9367942b54 | ||
|
|
167487e6ab | ||
|
|
6395dd1964 | ||
|
|
d3ef690f2e | ||
|
|
012f32dca9 | ||
|
|
0b8d5b153c | ||
|
|
246e3fa38e | ||
|
|
19777de6d4 | ||
|
|
3afd9df2ae | ||
|
|
2cb16ed0c4 | ||
|
|
ac64acf271 | ||
|
|
85cc13a817 | ||
|
|
75c8575b5b | ||
|
|
67557d5f94 | ||
|
|
330fb7711c | ||
|
|
e7f48c72bd | ||
|
|
3eefb1d315 | ||
|
|
a37a2c6729 | ||
|
|
e42fad0761 | ||
|
|
eee2dfa181 | ||
|
|
4728449294 | ||
|
|
ccd78d1b00 | ||
|
|
83bea69710 | ||
|
|
87fd1ee8ee | ||
|
|
af0528328f | ||
|
|
86c802e2db | ||
|
|
7bf91d0510 | ||
|
|
aed5af12a2 | ||
|
|
dd6e9e8312 | ||
|
|
42871b6c06 | ||
|
|
4ad7a172a0 | ||
|
|
6f112c0130 | ||
|
|
5a948f017a | ||
|
|
f5a1b21761 | ||
|
|
4af722752e | ||
|
|
af3b7a49d0 | ||
|
|
189ff2f369 | ||
|
|
ddf8ab3c9b | ||
|
|
a8a81eee83 | ||
|
|
fb384784f0 | ||
|
|
256abbc500 | ||
|
|
dc333ae25a | ||
|
|
d18adb459d | ||
|
|
bc914b73bc | ||
|
|
60172ea2a7 | ||
|
|
7b30c1533e | ||
|
|
a1c90658f3 | ||
|
|
0b0fdeaa60 | ||
|
|
d989797453 | ||
|
|
c70aefe670 | ||
|
|
7d0fc09470 | ||
|
|
427113e6f0 | ||
|
|
20ae1cb178 | ||
|
|
83b011fafa | ||
|
|
3affeee151 | ||
|
|
06da2114ad | ||
|
|
a3efdc622b | ||
|
|
9b60978af6 | ||
|
|
598db19d8d | ||
|
|
7a914d00e7 | ||
|
|
7141c56319 | ||
|
|
992d9717ec | ||
|
|
c5c2652d42 | ||
|
|
fb8e2272b3 | ||
|
|
120d087edc | ||
|
|
12c98d7d94 | ||
|
|
51d06817bc | ||
|
|
3bb4d7b449 | ||
|
|
f562994d18 | ||
|
|
f86d234c9c | ||
|
|
cb8e24428b | ||
|
|
30bd0bcbaf | ||
|
|
bb4d3bb9b0 | ||
|
|
523ce8cf60 | ||
|
|
d3d7a3138c | ||
|
|
e71bf88d12 | ||
|
|
1ba6fc8706 | ||
|
|
a341034de0 | ||
|
|
b45b25c255 | ||
|
|
c7eaa51bdb | ||
|
|
6b1d4e28ed | ||
|
|
4341cb33ea | ||
|
|
bde0bf7c8d | ||
|
|
55ab9a2918 | ||
|
|
7f4d134bd0 | ||
|
|
6e8b8f3565 | ||
|
|
a009b521c0 | ||
|
|
54d0db8189 | ||
|
|
66ffcf2866 | ||
|
|
d653bc67d8 | ||
|
|
533765ba74 | ||
|
|
0232f720cb | ||
|
|
205ca93977 | ||
|
|
fa62c9825d | ||
|
|
5051bc834d | ||
|
|
10ea4b1767 | ||
|
|
b801b46bce | ||
|
|
fc94dac05b | ||
|
|
1ab5f70c88 | ||
|
|
af6a11d649 | ||
|
|
c90636970a | ||
|
|
f3b1cc27e7 | ||
|
|
33eddbaece | ||
|
|
20f9b2f1ce | ||
|
|
e8c24c6bc5 | ||
|
|
affad0d92c | ||
|
|
ba169438ba | ||
|
|
c2e23af84f | ||
|
|
9ff2e38d07 | ||
|
|
5b12aa70e7 | ||
|
|
5424282fe6 | ||
|
|
8b76359143 | ||
|
|
2c6d54b32c | ||
|
|
a341c6a81e | ||
|
|
23b9f9128f | ||
|
|
81c3b75dc9 | ||
|
|
d3b1d00e15 | ||
|
|
177d1fe5b7 | ||
|
|
f1682205d8 | ||
|
|
ced5b15023 | ||
|
|
f6a150d5be | ||
|
|
1bfdb93622 | ||
|
|
09af2df542 | ||
|
|
cd1bdc0436 | ||
|
|
b2ea170f9e | ||
|
|
769ba78aa1 | ||
|
|
9bdd79ef7d | ||
|
|
55893bac8a | ||
|
|
bfe627658e | ||
|
|
a929bd2ddc | ||
|
|
3a966e0478 | ||
|
|
62105ead48 | ||
|
|
84e096d8b4 | ||
|
|
8bc066872c | ||
|
|
4491f6780a | ||
|
|
af19868289 | ||
|
|
4c538aad7b |
No files matched your search
@@ -1,176 +0,0 @@
|
||||
{
|
||||
"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": [
|
||||
"code",
|
||||
"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/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"login": "Peaches_MLG",
|
||||
"name": "Peaches_MLG",
|
||||
"avatar_url": "https://www.spigotmc.org/data/avatars/l/194/194338.jpg?1561235996",
|
||||
"profile": "https://www.spigotmc.org/members/peaches_mlg100.194338/",
|
||||
"contributions": [
|
||||
"financial"
|
||||
],
|
||||
"links": {
|
||||
"financial": "https://tr7zw.dev/donate/"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8,7 +8,7 @@ updates:
|
||||
ignore:
|
||||
- dependency-name: com.github.ekryd.sortpom:sortpom-maven-plugin
|
||||
versions:
|
||||
- 2.13.1
|
||||
- 2.13.3-SNAPSHOT
|
||||
- 2.14.0
|
||||
- 2.14.1
|
||||
- 2.15.0
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: Copy artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p artifacts/v2-api && cp -r item-nbt-api/target/apidocs/* artifacts/v2-api
|
||||
mkdir -p artifacts/v2-api && cp -r item-nbt-api/target/reports/apidocs/* artifacts/v2-api
|
||||
mkdir -p artifacts/v2-plugin && cp -r item-nbt-plugin/target/apidocs/* artifacts/v2-plugin
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 - 2021, tr7zw
|
||||
Copyright (c) 2015 - 2024, 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
|
||||
|
||||
@@ -1,54 +1,36 @@
|
||||
# Item-NBT-API
|
||||
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.
|
||||
|
||||
[](https://modrinth.com/plugin/nbtapi)
|
||||
[](https://discordapp.com/invite/yk4caxM)
|
||||
|
||||
Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it in 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
|
||||
[](https://ci.codemc.org/job/Tr7zw/job/Item-NBT-API/)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)
|
||||
[](https://discordapp.com/invite/yk4caxM)
|
||||
[](https://www.patreon.com/tr7zw)
|
||||
|
||||
[](https://ci.codemc.org/job/Tr7zw/job/Item-NBT-API/)[](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)[](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)[](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)
|
||||
|
||||
### SpigotMC Status
|
||||
|
||||
[](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[](https://bstats.org/plugin/bukkit/ItemNBTAPI)[](https://bstats.org/plugin/bukkit/ItemNBTAPI)[](#contributors-%e2%9c%a8)
|
||||
|
||||
## 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).
|
||||
|
||||
Import the API using [Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven) or [Gradle](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle), 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/Example-Usages#set-a-skulls-skin).
|
||||
|
||||
### bStats
|
||||
|
||||
[](https://bstats.org/plugin/bukkit/ItemNBTAPI)
|
||||
|
||||
### Github Stargazers
|
||||
|
||||
<img src="https://starchart.cc/tr7zw/Item-NBT-API.svg" alt="stargazers" width="800"/>
|
||||
|
||||
## Contributors ✨
|
||||
### Supported by YourKit
|
||||
|
||||
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://github.com/tr7zw/Item-NBT-API/commits?author=LoneDev" title="Code">💻</a> <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>
|
||||
<td align="center"><a href="https://www.spigotmc.org/members/peaches_mlg100.194338/"><img src="https://www.spigotmc.org/data/avatars/l/194/194338.jpg?1561235996" width="100px;" alt=""/><br /><sub><b>Peaches_MLG</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!
|
||||

|
||||
YourKit supports open source projects with innovative and intelligent tools
|
||||
for monitoring and profiling Java and .NET applications.
|
||||
YourKit is the creator of <a href="https://www.yourkit.com/java/profiler/">YourKit Java Profiler</a>,
|
||||
<a href="https://www.yourkit.com/.net/profiler/">YourKit .NET Profiler</a>,
|
||||
and <a href="https://www.yourkit.com/youmonitor/">YourKit YouMonitor</a>.
|
||||
+7
-2
@@ -1,16 +1,21 @@
|
||||
# (Item-)NBT-API
|
||||
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.
|
||||
|
||||
Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it in 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
|
||||
|
||||
[](https://ci.codemc.org/job/Tr7zw/job/Item-NBT-API/)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)
|
||||
Discord:[](https://discordapp.com/invite/yk4caxM)
|
||||
|
||||
### SpigotMC Status
|
||||
|
||||
[](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[](https://bstats.org/plugin/bukkit/ItemNBTAPI)[](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).
|
||||
|
||||
Import the API using [Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven) or [Gradle](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle), 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/Example-Usages#set-a-skulls-skin).
|
||||
|
||||
### bStats
|
||||
|
||||
[](https://bstats.org/plugin/bukkit/ItemNBTAPI)
|
||||
+21
-15
@@ -5,19 +5,25 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<version>2.16.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>item-nbt-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>functional-annotations</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>datafixerupper</artifactId>
|
||||
<version>4.0.26</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -32,15 +38,15 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.6.2</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>de.tr7zw.annotations</pattern>
|
||||
<shadedPattern>de.tr7zw.changeme.nbtapi.utils.annotations</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>de.tr7zw.changeme.nbtapi.utils.metrics</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>LICENSE</resource>
|
||||
|
||||
@@ -1,17 +1,34 @@
|
||||
package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTFileHandle;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteItemNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableItemNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.wrapper.NBTProxy;
|
||||
import de.tr7zw.changeme.nbtapi.wrapper.ProxyBuilder;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBTList;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
/**
|
||||
* General utility class for a clean and simple nbt access.
|
||||
@@ -19,12 +36,64 @@ import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
* @author tr7zw
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class NBT {
|
||||
|
||||
private NBT() {
|
||||
// No instances of NBT. Utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for shaded versions to preload and check the API during
|
||||
* onEnable. This method does not throw an exception and instead logs them. Will
|
||||
* return false if something fundamentally is wrong and the NBTAPI is in a non
|
||||
* functioning state. The shading plugin then needs to handle this. Note:
|
||||
* Calling this method during onLoad will cause an failure, so please wait till
|
||||
* onEnable.
|
||||
*
|
||||
* @return true if everything went fine
|
||||
*/
|
||||
public static boolean preloadApi() {
|
||||
try {
|
||||
// boiled down version of the plugin selfcheck without tests
|
||||
if (MinecraftVersion.getVersion() == MinecraftVersion.UNKNOWN) {
|
||||
NbtApiException.confirmedBroken = true;
|
||||
return false;
|
||||
}
|
||||
for (ClassWrapper c : ClassWrapper.values()) {
|
||||
if (c.isEnabled() && c.getClazz() == null) {
|
||||
NbtApiException.confirmedBroken = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (ReflectionMethod method : ReflectionMethod.values()) {
|
||||
if (method.isCompatible() && !method.isLoaded()) {
|
||||
NbtApiException.confirmedBroken = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// not settings NbtApiException.confirmedBroken = false, as no actual tests were done.
|
||||
// This just means the version was found, and all reflections seem to work.
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
NbtApiException.confirmedBroken = true;
|
||||
MinecraftVersion.getLogger().log(Level.WARNING, "[NBTAPI] Error during the selfcheck!", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a read only instance of the items NBT. This method is slightly slower
|
||||
* than calling NBT.get due to having to create a copy of the ItemStack, but
|
||||
* allows context free access to the data.
|
||||
*
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public static ReadableNBT readNbt(ItemStack item) {
|
||||
return new NBTItem(item.clone(), false, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack, and a function that takes a ReadableNBT and returns a
|
||||
* generic type T. It then returns the result of the function applied to a new
|
||||
@@ -35,8 +104,26 @@ public class NBT {
|
||||
* T.
|
||||
* @return The function is being returned.
|
||||
*/
|
||||
public static <T> T get(ItemStack item, Function<ReadableNBT, T> getter) {
|
||||
return getter.apply(new NBTItem(item, false, true));
|
||||
public static <T> T get(ItemStack item, Function<ReadableItemNBT, T> getter) {
|
||||
NBTItem nbt = new NBTItem(item, false, true, false);
|
||||
T ret = getter.apply(nbt);
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
nbt.setClosed();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack, and a Consumer that takes a ReadableNBT. Applies the
|
||||
* Consumer on the NBT of the item
|
||||
*
|
||||
* @param item The itemstack you want to get the NBT from
|
||||
*/
|
||||
public static void get(ItemStack item, Consumer<ReadableItemNBT> getter) {
|
||||
NBTItem nbt = new NBTItem(item, false, true, false);
|
||||
getter.accept(nbt);
|
||||
nbt.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +135,25 @@ public class NBT {
|
||||
* @return The NBTEntity class is being returned.
|
||||
*/
|
||||
public static <T> T get(Entity entity, Function<ReadableNBT, T> getter) {
|
||||
return getter.apply(new NBTEntity(entity, true));
|
||||
NBTEntity nbt = new NBTEntity(entity, true);
|
||||
T ret = getter.apply(nbt);
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
nbt.setClosed();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an Entity, and a Consumer that takes a ReadableNBT. Applies the
|
||||
* Consumer on the NBT of the Entity
|
||||
*
|
||||
* @param entity The entity to get the NBT from
|
||||
*/
|
||||
public static void get(Entity entity, Consumer<ReadableNBT> getter) {
|
||||
NBTEntity nbt = new NBTEntity(entity, true);
|
||||
getter.accept(nbt);
|
||||
nbt.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +167,25 @@ public class NBT {
|
||||
* @return The return type is the same as the type of the getter function.
|
||||
*/
|
||||
public static <T> T get(BlockState blockState, Function<ReadableNBT, T> getter) {
|
||||
return getter.apply(new NBTTileEntity(blockState, true));
|
||||
NBTTileEntity nbt = new NBTTileEntity(blockState, true);
|
||||
T ret = getter.apply(nbt);
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
nbt.setClosed();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an BlockEntity, and a Consumer that takes a ReadableNBT. Applies the
|
||||
* Consumer on the NBT of the BlockEntity
|
||||
*
|
||||
* @param blockState The block state of the block you want to get the NBT from.
|
||||
*/
|
||||
public static void get(BlockState blockState, Consumer<ReadableNBT> getter) {
|
||||
NBTTileEntity nbt = new NBTTileEntity(blockState, true);
|
||||
getter.accept(nbt);
|
||||
nbt.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,13 +199,17 @@ public class NBT {
|
||||
* @return The return type is T, which is a generic type.
|
||||
*/
|
||||
public static <T> T getPersistentData(Entity entity, Function<ReadableNBT, T> getter) {
|
||||
return getter.apply(new NBTEntity(entity).getPersistentDataContainer());
|
||||
T ret = getter.apply(new NBTEntity(entity).getPersistentDataContainer());
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an block entity and a function that takes a ReadableNBT and returns
|
||||
* a generic type T, and returns the result of the function, applied to the
|
||||
* block entities persistent data container
|
||||
* It takes a block entity and a function that takes a ReadableNBT and returns a
|
||||
* generic type T, and returns the result of the function, applied to the block
|
||||
* entities persistent data container
|
||||
*
|
||||
* @param blockState The block state of the block you want to get the data from.
|
||||
* @param getter A function that takes a ReadableNBT and returns a value of
|
||||
@@ -90,7 +217,11 @@ public class NBT {
|
||||
* @return The value of the NBT tag.
|
||||
*/
|
||||
public static <T> T getPersistentData(BlockState blockState, Function<ReadableNBT, T> getter) {
|
||||
return getter.apply(new NBTTileEntity(blockState).getPersistentDataContainer());
|
||||
T ret = getter.apply(new NBTTileEntity(blockState).getPersistentDataContainer());
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,9 +233,13 @@ public class NBT {
|
||||
* @return The return value of the function.
|
||||
*/
|
||||
public static <T> T modify(ItemStack item, Function<ReadWriteItemNBT, T> function) {
|
||||
NBTItem nbti = new NBTItem(item, true);
|
||||
NBTItem nbti = new NBTItem(item, false, false, true);
|
||||
T val = function.apply(nbti);
|
||||
nbti.applyNBT(item);
|
||||
nbti.finalizeChanges();
|
||||
if (val instanceof ReadableNBT || val instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
nbti.setClosed();
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -116,9 +251,10 @@ public class NBT {
|
||||
* @param consumer The consumer that will be used to modify the NBT.
|
||||
*/
|
||||
public static void modify(ItemStack item, Consumer<ReadWriteItemNBT> consumer) {
|
||||
NBTItem nbti = new NBTItem(item, true);
|
||||
NBTItem nbti = new NBTItem(item, false, false, true);
|
||||
consumer.accept(nbti);
|
||||
nbti.applyNBT(item);
|
||||
nbti.finalizeChanges();
|
||||
nbti.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,9 +270,84 @@ public class NBT {
|
||||
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
|
||||
T ret = function.apply(cont);
|
||||
nbtEnt.setCompound(cont.getCompound());
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
nbtEnt.setClosed();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quite expensive, so don't overuse it.
|
||||
*
|
||||
* @param item The item you want to modify the components of
|
||||
* @param consumer The consumer that will be used to modify the components.
|
||||
*/
|
||||
public static void modifyComponents(ItemStack item, Consumer<ReadWriteNBT> consumer) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
consumer.accept(nbti.getOrCreateCompound("components"));
|
||||
ItemStack tmp = NBT.itemStackFromNBT(nbti);
|
||||
item.setItemMeta(tmp.getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quite expensive, so don't overuse it.
|
||||
*
|
||||
* @param item The item you want to modify the components of
|
||||
* @param function The consumer that will be used to modify the components.
|
||||
* @return The return type is the same as the return type of the function.
|
||||
*/
|
||||
public static <T> T modifyComponents(ItemStack item, Function<ReadWriteNBT, T> function) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
T ret = function.apply(nbti.getOrCreateCompound("components"));
|
||||
ItemStack tmp = NBT.itemStackFromNBT(nbti);
|
||||
item.setItemMeta(tmp.getItemMeta());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quite expensive, try to cache the results/use it smartly.
|
||||
*
|
||||
* @param item The item you want to read the components of
|
||||
* @param consumer The consumer that will be used to read the components.
|
||||
*/
|
||||
public static void getComponents(ItemStack item, Consumer<ReadableNBT> consumer) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
consumer.accept(nbti.getOrCreateCompound("components"));
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack and a Consumer<ReadWriteNBT>, and then applies
|
||||
* the Consumer to the ItemStacks Components as NBT. This is for 1.20.5+ only.
|
||||
* This method is quite expensive, try to cache the results/use it smartly.
|
||||
*
|
||||
* @param item The item you want to read the components of
|
||||
* @param function The consumer that will be used to read the components.
|
||||
* @return The return type is the same as the return type of the function.
|
||||
*/
|
||||
public static <T> T getComponents(ItemStack item, Function<ReadableNBT, T> function) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException("This method only works for 1.20.5+!");
|
||||
}
|
||||
ReadWriteNBT nbti = NBT.itemStackToNBT(item);
|
||||
return function.apply(nbti.getOrCreateCompound("components"));
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an entity and a function that takes a ReadWriteNBT and applies the
|
||||
* function to the entity
|
||||
@@ -149,6 +360,7 @@ public class NBT {
|
||||
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
|
||||
consumer.accept(cont);
|
||||
nbtEnt.setCompound(cont.getCompound());
|
||||
nbtEnt.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +373,11 @@ public class NBT {
|
||||
* @return The return type is the same as the return type of the function.
|
||||
*/
|
||||
public static <T> T modifyPersistentData(Entity entity, Function<ReadWriteNBT, T> function) {
|
||||
return function.apply(new NBTEntity(entity).getPersistentDataContainer());
|
||||
T ret = function.apply(new NBTEntity(entity).getPersistentDataContainer());
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,7 +403,11 @@ public class NBT {
|
||||
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
|
||||
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
|
||||
T ret = function.apply(cont);
|
||||
blockEnt.setCompound(cont);
|
||||
blockEnt.setCompound(cont.getCompound());
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
blockEnt.setClosed();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -204,7 +424,8 @@ public class NBT {
|
||||
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
|
||||
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
|
||||
consumer.accept(cont);
|
||||
blockEnt.setCompound(cont);
|
||||
blockEnt.setCompound(cont.getCompound());
|
||||
blockEnt.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,7 +438,11 @@ public class NBT {
|
||||
* @return The return type is the same as the return type of the function.
|
||||
*/
|
||||
public static <T> T modifyPersistentData(BlockState blockState, Function<ReadWriteNBT, T> function) {
|
||||
return function.apply(new NBTTileEntity(blockState).getPersistentDataContainer());
|
||||
T ret = function.apply(new NBTTileEntity(blockState).getPersistentDataContainer());
|
||||
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,6 +493,7 @@ public class NBT {
|
||||
* @param compound The NBT tag to convert to an ItemStack
|
||||
* @return An ItemStack
|
||||
*/
|
||||
@Nullable
|
||||
public static ItemStack itemStackFromNBT(ReadableNBT compound) {
|
||||
return NBTItem.convertNBTtoItem((NBTCompound) compound);
|
||||
}
|
||||
@@ -288,6 +514,7 @@ public class NBT {
|
||||
* @param compound The NBT tag to convert to an ItemStack array.
|
||||
* @return An array of ItemStacks.
|
||||
*/
|
||||
@Nullable
|
||||
public static ItemStack[] itemStackArrayFromNBT(ReadableNBT compound) {
|
||||
return NBTItem.convertNBTtoItemArray((NBTCompound) compound);
|
||||
}
|
||||
@@ -305,10 +532,402 @@ public class NBT {
|
||||
* It takes a nbt json string, and returns a ReadWriteNBT object
|
||||
*
|
||||
* @param nbtString The NBT string to parse.
|
||||
* @return A new NBTContainer object.
|
||||
* @return A new ReadWriteNBT object.
|
||||
*/
|
||||
public static ReadWriteNBT parseNBT(String nbtString) {
|
||||
return new NBTContainer(nbtString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads in an NBT stream and returns a ReadWriteNBT object
|
||||
*
|
||||
* @param stream The NBT stream to read.
|
||||
* @return A new ReadWriteNBT object.
|
||||
*/
|
||||
public static ReadWriteNBT readNBT(InputStream stream) {
|
||||
return new NBTContainer(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for other developers using NMS. Allows to wrap any
|
||||
* net.minecraft.nbt.CompoundTag to a NBTAPI ReadWriteNBT object.
|
||||
*
|
||||
* @param nmsNbtTag Needs to be a valid net.minecraft.nbt.CompoundTag
|
||||
* @return A new ReadWriteNBT object.
|
||||
*/
|
||||
public static ReadWriteNBT wrapNMSTag(Object nmsNbtTag) {
|
||||
return new NBTContainer(nmsNbtTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a NBTFileHandle that uses @param file to store its data. If this file
|
||||
* exists, the data will be loaded, otherwise a new file gets created.
|
||||
*
|
||||
* @param file
|
||||
* @throws IOException
|
||||
*/
|
||||
public static NBTFileHandle getFileHandle(File file) throws IOException {
|
||||
return new NBTFile(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads NBT data from the provided file.
|
||||
* <p>
|
||||
* Returns an empty tag if the file does not exist.
|
||||
*
|
||||
* @param file file to read
|
||||
* @return ReadWriteNBT of the files data
|
||||
* @throws IOException exception
|
||||
*/
|
||||
public static ReadWriteNBT readFile(File file) throws IOException {
|
||||
return NBTFile.readFrom(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves NBT data to the provided file.
|
||||
* <p>
|
||||
* Will fully override the file if it already exists.
|
||||
*
|
||||
* @param file file
|
||||
* @param nbt NBT data
|
||||
* @throws IOException exception
|
||||
*/
|
||||
public static void writeFile(File file, ReadWriteNBT nbt) throws IOException {
|
||||
NBTFile.saveTo(file, (NBTCompound) nbt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a read only proxy class for NBT, given an annotated interface.
|
||||
*
|
||||
* @param <T>
|
||||
* @param item
|
||||
* @param wrapper
|
||||
* @return
|
||||
*/
|
||||
public static <T extends NBTProxy> T readNbt(ItemStack item, Class<T> wrapper) {
|
||||
return new ProxyBuilder<>(new NBTItem(item, false, true, false), wrapper).readOnly().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a read only proxy class for NBT, given an annotated interface.
|
||||
*
|
||||
* @param <T>
|
||||
* @param entity
|
||||
* @param wrapper
|
||||
* @return
|
||||
*/
|
||||
public static <T extends NBTProxy> T readNbt(Entity entity, Class<T> wrapper) {
|
||||
return new ProxyBuilder<>(new NBTEntity(entity, true), wrapper).readOnly().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a read only proxy class for NBT, given an annotated interface.
|
||||
*
|
||||
* @param <T>
|
||||
* @param blockState
|
||||
* @param wrapper
|
||||
* @return
|
||||
*/
|
||||
public static <T extends NBTProxy> T readNbt(BlockState blockState, Class<T> wrapper) {
|
||||
return new ProxyBuilder<>(new NBTTileEntity(blockState, true), wrapper).readOnly().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack, applies a function to its NBT wrapped in a proxy, and
|
||||
* returns the result of the function
|
||||
*
|
||||
* @param item The item you want to
|
||||
* @param wrapper The target Proxy class
|
||||
* @param function The function that will be applied to the item.
|
||||
* @return The return value of the function.
|
||||
*/
|
||||
public static <T, X extends NBTProxy> T modify(ItemStack item, Class<X> wrapper, Function<X, T> function) {
|
||||
NBTItem nbti = new NBTItem(item, false, false, true);
|
||||
T val = function.apply(new ProxyBuilder<>(nbti, wrapper).build());
|
||||
nbti.finalizeChanges();
|
||||
if (val instanceof ReadableNBT || val instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
nbti.setClosed();
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an ItemStack, applies a function to its NBT wrapped in a proxy.
|
||||
*
|
||||
* @param item The item you want to modify
|
||||
* @param wrapper The target Proxy class
|
||||
* @param consumer The consumer that will be used to modify the NBT.
|
||||
*/
|
||||
public static <X extends NBTProxy> void modify(ItemStack item, Class<X> wrapper, Consumer<X> consumer) {
|
||||
NBTItem nbti = new NBTItem(item, false, false, true);
|
||||
consumer.accept(new ProxyBuilder<>(nbti, wrapper).build());
|
||||
nbti.finalizeChanges();
|
||||
nbti.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an entity and a function to modify the entity via the proxy
|
||||
*
|
||||
* @param entity The entity to modify
|
||||
* @param wrapper The target Proxy class
|
||||
* @param consumer The consumer that will be called with the proxy.
|
||||
*/
|
||||
public static <X extends NBTProxy> void modify(Entity entity, Class<X> wrapper, Consumer<X> consumer) {
|
||||
NBTEntity nbtEnt = new NBTEntity(entity);
|
||||
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
|
||||
consumer.accept(new ProxyBuilder<>(cont, wrapper).build());
|
||||
nbtEnt.setCompound(cont.getCompound());
|
||||
cont.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an entity and a function to modify the entity via the proxy
|
||||
*
|
||||
* @param entity The entity to modify
|
||||
* @param wrapper The target Proxy class
|
||||
* @param function The Function that will be called with the proxy.
|
||||
* @return The return value of the function.
|
||||
*/
|
||||
public static <T, X extends NBTProxy> T modify(Entity entity, Class<X> wrapper, Function<X, T> function) {
|
||||
NBTEntity nbtEnt = new NBTEntity(entity);
|
||||
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
|
||||
T val = function.apply(new ProxyBuilder<>(cont, wrapper).build());
|
||||
nbtEnt.setCompound(cont.getCompound());
|
||||
cont.setClosed();
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an block entity and a function to modify the entity via the proxy
|
||||
*
|
||||
* @param blockState The blockstate you want to modify
|
||||
* @param wrapper The target Proxy class
|
||||
* @param consumer The Consumer that will be called.
|
||||
*/
|
||||
public static <X extends NBTProxy> void modify(BlockState blockState, Class<X> wrapper, Consumer<X> consumer) {
|
||||
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
|
||||
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
|
||||
consumer.accept(new ProxyBuilder<>(cont, wrapper).build());
|
||||
blockEnt.setCompound(cont);
|
||||
cont.setClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an block entity and a function to modify the entity via the proxy
|
||||
*
|
||||
* @param blockState The blockstate you want to modify
|
||||
* @param wrapper The target Proxy class
|
||||
* @param function The function that will be called.
|
||||
* @return The return value of the function.
|
||||
*/
|
||||
public static <T, X extends NBTProxy> T modify(BlockState blockState, Class<X> wrapper, Function<X, T> function) {
|
||||
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
|
||||
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
|
||||
T val = function.apply(new ProxyBuilder<>(cont, wrapper).build());
|
||||
blockEnt.setCompound(cont);
|
||||
cont.setClosed();
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads block‑specific data that was previously stored in the chunk's
|
||||
* persistent data container.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose stored data is to be read
|
||||
* @param consumer the consumer that receives a {@link ReadableNBT} view of the data
|
||||
*/
|
||||
public static void readChunkPDC(Block block, Consumer<ReadableNBT> consumer) {
|
||||
processBlockChunkPDC(block, false, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads block‑specific data from the chunk's persistent data container and
|
||||
* applies a function to produce a result.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose stored data is to be read
|
||||
* @param function the function that processes the {@link ReadableNBT} and
|
||||
* returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function applied to the data
|
||||
*/
|
||||
public static <T> T readAndGetChunkPDC(Block block, Function<ReadableNBT, T> function) {
|
||||
return processBlockChunkPDC(block, false, function::apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies block‑specific data stored in the chunk's persistent data container.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Caution:</b> the data remains even if the block is broken, replaced, moved,
|
||||
* or exploded, etc. You should manually remove the data when it is no longer needed.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose data is to be modified
|
||||
* @param consumer the consumer that receives the {@link ReadWriteNBT} and
|
||||
* applies modifications
|
||||
*/
|
||||
public static void modifyChunkPDC(Block block, Consumer<ReadWriteNBT> consumer) {
|
||||
processBlockChunkPDC(block, true, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies block‑specific data in the chunk's persistent data container and
|
||||
* returns a result computed from the modified data.
|
||||
* <p>
|
||||
* The data is stored inside the {@code blocks} compound of the chunk's
|
||||
* persistent data container, using a key formed as {@code X_Y_Z} where
|
||||
* X, Y, Z are the block's coordinates.
|
||||
* <p>
|
||||
* <b>Caution:</b> the data remains even if the block is broken, replaced, moved,
|
||||
* or exploded, etc. You should manually remove the data when it is no longer needed.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param block the block whose data is to be modified
|
||||
* @param function the function that receives the {@link ReadWriteNBT}, modifies
|
||||
* it, and returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function after modification
|
||||
*/
|
||||
public static <T> T modifyAndGetChunkPDC(Block block, Function<ReadWriteNBT, T> function) {
|
||||
return processBlockChunkPDC(block, true, function::apply);
|
||||
}
|
||||
|
||||
private static <T> T processBlockChunkPDC(Block block, boolean createIfAbsent, Function<NBTCompound, T> action) {
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R3);
|
||||
|
||||
String blockKey = block.getX() + "_" + block.getY() + "_" + block.getZ();
|
||||
|
||||
NBTCompound chunkData = new NBTPersistentDataContainer(block.getChunk().getPersistentDataContainer(), !createIfAbsent);
|
||||
|
||||
NBTCompound blocksData = createIfAbsent
|
||||
? chunkData.getOrCreateCompound("blocks")
|
||||
: chunkData.getCompound("blocks");
|
||||
|
||||
NBTCompound blockData;
|
||||
if (createIfAbsent) {
|
||||
blockData = blocksData.getOrCreateCompound(blockKey);
|
||||
} else {
|
||||
blockData = blocksData == null ? null : blocksData.getCompound(blockKey);
|
||||
if (blockData == null) {
|
||||
blockData = new NBTContainer().setReadOnly(true);
|
||||
}
|
||||
}
|
||||
|
||||
T result = action.apply(blockData);
|
||||
|
||||
if (createIfAbsent) {
|
||||
if (blockData.isEmpty()) {
|
||||
blocksData.removeKey(blockKey);
|
||||
}
|
||||
if (blocksData.isEmpty()) {
|
||||
chunkData.removeKey("blocks");
|
||||
}
|
||||
}
|
||||
|
||||
if (result instanceof ReadableNBT || result instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the chunk's persistent data container.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be read
|
||||
* @param consumer the consumer that receives a {@link ReadableNBT} view of the data
|
||||
*/
|
||||
public static void readChunkPDC(Chunk chunk, Consumer<ReadableNBT> consumer) {
|
||||
processChunkPDC(chunk, false, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the chunk's persistent data container and applies a function to produce a result.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be read
|
||||
* @param function the function that processes the {@link ReadableNBT} and
|
||||
* returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function applied to the data
|
||||
*/
|
||||
public static <T> T readAndGetChunkPDC(Chunk chunk, Function<ReadableNBT, T> function) {
|
||||
return processChunkPDC(chunk, false, function::apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the chunk's persistent data container.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be modified
|
||||
* @param consumer the consumer that receives the {@link ReadWriteNBT} and
|
||||
* applies modifications
|
||||
*/
|
||||
public static void modifyChunkPDC(Chunk chunk, Consumer<ReadWriteNBT> consumer) {
|
||||
processChunkPDC(chunk, true, nbt -> {
|
||||
consumer.accept(nbt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the chunk's persistent data container and returns a result computed from the modified data.
|
||||
* <p>
|
||||
* <b>Minecraft version:</b> this method requires <b>1.16.4 or newer</b>.
|
||||
*
|
||||
* @param chunk the chunk whose persistent data is to be modified
|
||||
* @param function the function that receives the {@link ReadWriteNBT}, modifies
|
||||
* it, and returns a value
|
||||
* @param <T> the type of the returned value
|
||||
* @return the result of the function after modification
|
||||
*/
|
||||
public static <T> T modifyAndGetChunkPDC(Chunk chunk, Function<ReadWriteNBT, T> function) {
|
||||
return processChunkPDC(chunk, true, function::apply);
|
||||
}
|
||||
|
||||
private static <T> T processChunkPDC(Chunk chunk, boolean createIfAbsent, Function<NBTCompound, T> action) {
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R3);
|
||||
|
||||
NBTCompound chunkData = new NBTPersistentDataContainer(chunk.getPersistentDataContainer(), !createIfAbsent);
|
||||
|
||||
T result = action.apply(chunkData);
|
||||
|
||||
if (result instanceof ReadableNBT || result instanceof ReadableNBTList<?>) {
|
||||
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,16 +7,17 @@ import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
/**
|
||||
* Helper class to store NBT data to Block Locations. Use getData() to get the
|
||||
* NBT instance. Important notes:
|
||||
*
|
||||
* <p>
|
||||
* - Non BlockEntities can not have NBT data. This stores the data to the chunk
|
||||
* instead!
|
||||
*
|
||||
* <p>
|
||||
* - The data is really just on the location. If the block gets
|
||||
* broken/changed/explodes/moved etc, the data is still on that location!
|
||||
* broken/changed/exploded/moved etc., the data is still on that location!
|
||||
*
|
||||
* @author tr7zw
|
||||
*
|
||||
* @deprecated use methods in {@link NBT} class to read/modify block's NBT
|
||||
*/
|
||||
@Deprecated
|
||||
public class NBTBlock {
|
||||
|
||||
private final Block block;
|
||||
@@ -30,6 +31,13 @@ public class NBTBlock {
|
||||
nbtChunk = new NBTChunk(block.getChunk());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block NBT data stored within the chunk's PDC.
|
||||
*
|
||||
* @return block NBT data
|
||||
* @deprecated use methods in {@link NBT} class to read/modify block's NBT
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTCompound getData() {
|
||||
return nbtChunk.getPersistentDataContainer().getOrCreateCompound("blocks")
|
||||
.getOrCreateCompound(block.getX() + "_" + block.getY() + "_" + block.getZ());
|
||||
|
||||
@@ -2,11 +2,15 @@ package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
import de.tr7zw.annotations.FAUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.annotations.AvailableSince;
|
||||
import de.tr7zw.changeme.nbtapi.utils.annotations.CheckUtil;
|
||||
|
||||
/**
|
||||
* Helper class to store NBT data to {@link Chunk}'s PDC (persistent data container).
|
||||
*
|
||||
* @deprecated use methods in {@link NBT} class to read/modify chunk's nbt
|
||||
*/
|
||||
@Deprecated
|
||||
public class NBTChunk {
|
||||
|
||||
private final Chunk chunk;
|
||||
@@ -21,9 +25,8 @@ public class NBTChunk {
|
||||
*
|
||||
* @return NBTCompound containing the data of the PersistentDataAPI
|
||||
*/
|
||||
@AvailableSince(version = MinecraftVersion.MC1_16_R3)
|
||||
public NBTCompound getPersistentDataContainer() {
|
||||
FAUtil.check(this::getPersistentDataContainer, CheckUtil::isAvaliable);
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R3);
|
||||
return new NBTPersistentDataContainer(chunk.getPersistentDataContainer());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -12,9 +14,14 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTHandler;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.PathUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.UUIDUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.PathUtil.PathSegment;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.Forge1710Mappings;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
@@ -33,10 +40,17 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
|
||||
private String compundName;
|
||||
private NBTCompound parent;
|
||||
private final boolean readOnly;
|
||||
private Object readOnlyCache;
|
||||
|
||||
protected NBTCompound(NBTCompound owner, String name) {
|
||||
this(owner, name, false);
|
||||
}
|
||||
|
||||
protected NBTCompound(NBTCompound owner, String name, boolean readOnly) {
|
||||
this.compundName = name;
|
||||
this.parent = owner;
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
protected Lock getReadLock() {
|
||||
@@ -52,6 +66,55 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
parent.saveCompound();
|
||||
}
|
||||
|
||||
protected void setResolvedObject(Object object) {
|
||||
if (isClosed()) {
|
||||
throw new NbtApiException("Tried using closed NBT data!");
|
||||
}
|
||||
if (readOnly) {
|
||||
this.readOnlyCache = object;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setClosed() {
|
||||
if (parent != null) {
|
||||
parent.setClosed();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isClosed() {
|
||||
if (parent != null) {
|
||||
return parent.isClosed();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
protected Object getResolvedObject() {
|
||||
if (isClosed()) {
|
||||
throw new NbtApiException("Tried using closed NBT data!");
|
||||
}
|
||||
if (readOnlyCache != null) {
|
||||
return readOnlyCache;
|
||||
}
|
||||
Object rootnbttag = getCompound();
|
||||
if (rootnbttag instanceof Optional<?>) {
|
||||
rootnbttag = ((Optional<Object>) rootnbttag).orElse(null);
|
||||
}
|
||||
if (rootnbttag == null) {
|
||||
return null;
|
||||
}
|
||||
if (!NBTReflectionUtil.validCompound(this))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = NBTReflectionUtil.getToCompount(rootnbttag, this);
|
||||
if (readOnly) {
|
||||
this.readOnlyCache = workingtag;
|
||||
}
|
||||
return workingtag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Compound name
|
||||
*/
|
||||
@@ -84,6 +147,9 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
* @param comp
|
||||
*/
|
||||
public void mergeCompound(NBTCompound comp) {
|
||||
if (comp == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
writeLock.lock();
|
||||
NBTReflectionUtil.mergeOtherNBTCompound(this, comp);
|
||||
@@ -135,10 +201,6 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
}
|
||||
}
|
||||
|
||||
protected String getContent(String key) {
|
||||
return NBTReflectionUtil.getContent(this, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter
|
||||
*
|
||||
@@ -403,6 +465,45 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter
|
||||
*
|
||||
* Requires at least 1.16
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
@Override
|
||||
public void setLongArray(String key, long[] value) {
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R1);
|
||||
try {
|
||||
writeLock.lock();
|
||||
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_LONGARRAY, key, value);
|
||||
saveCompound();
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter
|
||||
*
|
||||
* Requires at least 1.16
|
||||
*
|
||||
* @param key
|
||||
* @return The stored value or NMS fallback
|
||||
*/
|
||||
@Override
|
||||
public long[] getLongArray(String key) {
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R1);
|
||||
try {
|
||||
readLock.lock();
|
||||
return (long[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_LONGARRAY, key);
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter
|
||||
*
|
||||
@@ -561,7 +662,9 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
public void setUUID(String key, UUID value) {
|
||||
try {
|
||||
writeLock.lock();
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
setIntArray(key, UUIDUtil.uuidToIntArray(value));
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_UUID, key, value);
|
||||
} else {
|
||||
setString(key, value.toString());
|
||||
@@ -582,10 +685,13 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
public UUID getUUID(String key) {
|
||||
try {
|
||||
readLock.lock();
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)
|
||||
&& getType(key) == NBTType.NBTTagIntArray) {
|
||||
NBTType type = getType(key);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4) && type == NBTType.NBTTagIntArray) {
|
||||
return UUIDUtil.uuidFromIntArray(getIntArray(key));
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)
|
||||
&& type == NBTType.NBTTagIntArray) {
|
||||
return (UUID) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_UUID, key);
|
||||
} else if (getType(key) == NBTType.NBTTagString) {
|
||||
} else if (type == NBTType.NBTTagString) {
|
||||
try {
|
||||
return UUID.fromString(getString(key));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
@@ -689,8 +795,8 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
readLock.lock();
|
||||
if (getType(name) != NBTType.NBTTagCompound)
|
||||
return null;
|
||||
NBTCompound next = new NBTCompound(this, name);
|
||||
if (NBTReflectionUtil.valideCompound(next))
|
||||
NBTCompound next = new NBTCompound(this, name, readOnly);
|
||||
if (NBTReflectionUtil.validCompound(next))
|
||||
return next;
|
||||
return null;
|
||||
} finally {
|
||||
@@ -860,7 +966,7 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
* Returns the stored value if exists, or provided value otherwise.
|
||||
* <p>
|
||||
* Supported types:
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[]},
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key key
|
||||
@@ -877,24 +983,26 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
return defaultValue;
|
||||
|
||||
Class<?> clazz = defaultValue.getClass();
|
||||
if (clazz == Boolean.class)
|
||||
if (clazz == Boolean.class || clazz == boolean.class)
|
||||
return (T) getBoolean(key);
|
||||
if (clazz == Byte.class)
|
||||
if (clazz == Byte.class || clazz == byte.class)
|
||||
return (T) getByte(key);
|
||||
if (clazz == Short.class)
|
||||
if (clazz == Short.class || clazz == short.class)
|
||||
return (T) getShort(key);
|
||||
if (clazz == Integer.class)
|
||||
if (clazz == Integer.class || clazz == int.class)
|
||||
return (T) getInteger(key);
|
||||
if (clazz == Long.class)
|
||||
if (clazz == Long.class || clazz == long.class)
|
||||
return (T) getLong(key);
|
||||
if (clazz == Float.class)
|
||||
if (clazz == Float.class || clazz == float.class)
|
||||
return (T) getFloat(key);
|
||||
if (clazz == Double.class)
|
||||
if (clazz == Double.class || clazz == double.class)
|
||||
return (T) getDouble(key);
|
||||
if (clazz == byte[].class)
|
||||
return (T) getByteArray(key);
|
||||
if (clazz == int[].class)
|
||||
return (T) getIntArray(key);
|
||||
if (clazz == long[].class)
|
||||
return (T) getLongArray(key);
|
||||
if (clazz == String.class)
|
||||
return (T) getString(key);
|
||||
if (clazz == UUID.class) {
|
||||
@@ -914,7 +1022,7 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
* Returns the stored value if exists, or null.
|
||||
* <p>
|
||||
* Supported types:
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[]},
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key key
|
||||
@@ -930,24 +1038,26 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
if (!hasTag(key))
|
||||
return null;
|
||||
|
||||
if (type == Boolean.class)
|
||||
if (type == Boolean.class || type == boolean.class)
|
||||
return (T) getBoolean(key);
|
||||
if (type == Byte.class)
|
||||
if (type == Byte.class || type == byte.class)
|
||||
return (T) getByte(key);
|
||||
if (type == Short.class)
|
||||
if (type == Short.class || type == short.class)
|
||||
return (T) getShort(key);
|
||||
if (type == Integer.class)
|
||||
if (type == Integer.class || type == int.class)
|
||||
return (T) getInteger(key);
|
||||
if (type == Long.class)
|
||||
if (type == Long.class || type == long.class)
|
||||
return (T) getLong(key);
|
||||
if (type == Float.class)
|
||||
if (type == Float.class || type == float.class)
|
||||
return (T) getFloat(key);
|
||||
if (type == Double.class)
|
||||
if (type == Double.class || type == double.class)
|
||||
return (T) getDouble(key);
|
||||
if (type == byte[].class)
|
||||
return (T) getByteArray(key);
|
||||
if (type == int[].class)
|
||||
return (T) getIntArray(key);
|
||||
if (type == long[].class)
|
||||
return (T) getLongArray(key);
|
||||
if (type == String.class)
|
||||
return (T) getString(key);
|
||||
if (type == UUID.class)
|
||||
@@ -958,6 +1068,238 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
throw new NbtApiException("Unsupported type for getOrNull: " + type.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T resolveOrNull(String key, Class<?> type) {
|
||||
List<PathSegment> keys = PathUtil.splitPath(key);
|
||||
NBTCompound tag = this;
|
||||
for (int i = 0; i < keys.size() - 1; i++) {
|
||||
PathSegment segment = keys.get(i);
|
||||
if (!segment.hasIndex()) {
|
||||
tag = tag.getCompound(segment.getPath());
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (tag.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& tag.getListType(segment.getPath()) == NBTType.NBTTagCompound) {
|
||||
NBTCompoundList list = tag.getCompoundList(segment.getPath());
|
||||
if (segment.getIndex() >= 0) {
|
||||
tag = list.get(segment.getIndex());
|
||||
} else {
|
||||
tag = list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PathSegment segment = keys.get(keys.size() - 1);
|
||||
if (!segment.hasIndex()) {
|
||||
return tag.getOrNull(segment.getPath(), type);
|
||||
} else {
|
||||
return getIndexedValue(tag, segment, (Class<T>)type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T resolveOrDefault(String key, T defaultValue) {
|
||||
List<PathSegment> keys = PathUtil.splitPath(key);
|
||||
NBTCompound tag = this;
|
||||
for (int i = 0; i < keys.size() - 1; i++) {
|
||||
PathSegment segment = keys.get(i);
|
||||
if (!segment.hasIndex()) {
|
||||
tag = tag.getCompound(segment.getPath());
|
||||
if (tag == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
} else {
|
||||
if (tag.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& tag.getListType(segment.getPath()) == NBTType.NBTTagCompound) {
|
||||
NBTCompoundList list = tag.getCompoundList(segment.getPath());
|
||||
if (segment.getIndex() >= 0) {
|
||||
tag = list.get(segment.getIndex());
|
||||
} else {
|
||||
tag = list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PathSegment segment = keys.get(keys.size() - 1);
|
||||
if (!segment.hasIndex()) {
|
||||
return tag.getOrDefault(segment.getPath(), defaultValue);
|
||||
} else {
|
||||
return getIndexedValue(tag, segment, (Class<T>)defaultValue.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: before I'm even done writing this method, this sucks. Needs refactoring at some point
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T getIndexedValue(NBTCompound comp, PathSegment segment, Class<T> type) {
|
||||
if (type == String.class) {
|
||||
if (comp.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& comp.getListType(segment.getPath()) == NBTType.NBTTagString) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
return (T) comp.getStringList(segment.getPath()).get(segment.getIndex());
|
||||
} else {
|
||||
List<String> list = comp.getStringList(segment.getPath());
|
||||
return (T) list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
throw new NbtApiException("No fitting list/array found for " + segment.getPath() + " of type " + type);
|
||||
}
|
||||
if (type == int.class || type == Integer.class) {
|
||||
if (comp.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& comp.getListType(segment.getPath()) == NBTType.NBTTagInt) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
return (T) comp.getIntegerList(segment.getPath()).get(segment.getIndex());
|
||||
} else {
|
||||
List<Integer> list = comp.getIntegerList(segment.getPath());
|
||||
return (T) list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
} else if(comp.getType(segment.getPath()) == NBTType.NBTTagIntArray) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
int[] array = comp.getIntArray(segment.getPath());
|
||||
if(array != null) {
|
||||
return (T)(Integer) array[segment.getIndex()];
|
||||
}
|
||||
} else {
|
||||
int[] array = comp.getIntArray(segment.getPath());
|
||||
if(array != null) {
|
||||
return (T)(Integer) array[array.length + segment.getIndex()];
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NbtApiException("No fitting list/array found for " + segment.getPath() + " of type " + type);
|
||||
}
|
||||
if (type == long.class || type == Long.class) {
|
||||
if (comp.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& comp.getListType(segment.getPath()) == NBTType.NBTTagLong) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
return (T) comp.getLongList(segment.getPath()).get(segment.getIndex());
|
||||
} else {
|
||||
List<Long> list = comp.getLongList(segment.getPath());
|
||||
return (T) list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
} else if(comp.getType(segment.getPath()) == NBTType.NBTTagLongArray) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
long[] array = comp.getLongArray(segment.getPath());
|
||||
if(array != null) {
|
||||
return (T)(Long) array[segment.getIndex()];
|
||||
}
|
||||
} else {
|
||||
long[] array = comp.getLongArray(segment.getPath());
|
||||
if(array != null) {
|
||||
return (T)(Long) array[array.length + segment.getIndex()];
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NbtApiException("No fitting list/array found for " + segment.getPath() + " of type " + type);
|
||||
}
|
||||
if (type == float.class || type == Float.class) {
|
||||
if (comp.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& comp.getListType(segment.getPath()) == NBTType.NBTTagFloat) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
return (T) comp.getFloatList(segment.getPath()).get(segment.getIndex());
|
||||
} else {
|
||||
List<Float> list = comp.getFloatList(segment.getPath());
|
||||
return (T) list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
throw new NbtApiException("No fitting list/array found for " + segment.getPath() + " of type " + type);
|
||||
}
|
||||
if (type == double.class || type == Double.class) {
|
||||
if (comp.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& comp.getListType(segment.getPath()) == NBTType.NBTTagDouble) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
return (T) comp.getDoubleList(segment.getPath()).get(segment.getIndex());
|
||||
} else {
|
||||
List<Double> list = comp.getDoubleList(segment.getPath());
|
||||
return (T) list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
throw new NbtApiException("No fitting list/array found for " + segment.getPath() + " of type " + type);
|
||||
}
|
||||
if (type == int[].class) {
|
||||
if (comp.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& comp.getListType(segment.getPath()) == NBTType.NBTTagIntArray) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
return (T) comp.getIntArrayList(segment.getPath()).get(segment.getIndex());
|
||||
} else {
|
||||
List<int[]> list = comp.getIntArrayList(segment.getPath());
|
||||
return (T) list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
throw new NbtApiException("No fitting list/array found for " + segment.getPath() + " of type " + type);
|
||||
}
|
||||
if (type == byte.class || type == Byte.class) {
|
||||
if(comp.getType(segment.getPath()) == NBTType.NBTTagByteArray) {
|
||||
if (segment.getIndex() >= 0) {
|
||||
byte[] array = comp.getByteArray(segment.getPath());
|
||||
if(array != null) {
|
||||
return (T)(Byte) array[segment.getIndex()];
|
||||
}
|
||||
} else {
|
||||
byte[] array = comp.getByteArray(segment.getPath());
|
||||
if(array != null) {
|
||||
return (T)(Byte) array[array.length + segment.getIndex()];
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NbtApiException("No fitting list/array found for " + segment.getPath() + " of type " + type);
|
||||
}
|
||||
throw new NbtApiException("Unable to get indexed value for type " + type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadWriteNBT resolveCompound(String key) {
|
||||
List<PathSegment> keys = PathUtil.splitPath(key);
|
||||
NBTCompound tag = this;
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
PathSegment segment = keys.get(i);
|
||||
if (!segment.hasIndex()) {
|
||||
tag = tag.getCompound(segment.getPath());
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (tag.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& tag.getListType(segment.getPath()) == NBTType.NBTTagCompound) {
|
||||
NBTCompoundList list = tag.getCompoundList(segment.getPath());
|
||||
if (segment.getIndex() >= 0) {
|
||||
tag = list.get(segment.getIndex());
|
||||
} else {
|
||||
tag = list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadWriteNBT resolveOrCreateCompound(String key) {
|
||||
List<PathSegment> keys = PathUtil.splitPath(key);
|
||||
NBTCompound tag = this;
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
PathSegment segment = keys.get(i);
|
||||
if (!segment.hasIndex()) {
|
||||
tag = tag.getOrCreateCompound(segment.getPath());
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (tag.getType(segment.getPath()) == NBTType.NBTTagList
|
||||
&& tag.getListType(segment.getPath()) == NBTType.NBTTagCompound) {
|
||||
NBTCompoundList list = tag.getCompoundList(segment.getPath());
|
||||
if (segment.getIndex() >= 0) {
|
||||
tag = list.get(segment.getIndex());
|
||||
} else {
|
||||
tag = list.get(list.size() + segment.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a key to the given Enum value. It gets stored as a String. Passing null
|
||||
* as value will call removeKey(key) instead.
|
||||
@@ -1011,7 +1353,13 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
Object nbtbase = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET, name);
|
||||
if (nbtbase == null)
|
||||
return null;
|
||||
return NBTType.valueOf((byte) ReflectionMethod.COMPOUND_OWN_TYPE.run(nbtbase));
|
||||
return NBTType.valueOf((byte) ReflectionMethod.COMPOUND_OWN_TYPE_LEGACY.run(nbtbase));
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET, name);
|
||||
if (o == null)
|
||||
return null;
|
||||
return NBTType.fromName((String)ReflectionMethod.TAGTYPE_GET_NAME.run(ReflectionMethod.TAGTYPE_OWN_TYPE.run(o)));
|
||||
}
|
||||
Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_TYPE, name);
|
||||
if (o == null)
|
||||
@@ -1032,6 +1380,16 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(String key, NBTHandler<T> handler) {
|
||||
return handler.get(this, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void set(String key, T value, NBTHandler<T> handler) {
|
||||
handler.set(this, key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
/*
|
||||
@@ -1077,7 +1435,7 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
public String asNBTString() {
|
||||
try {
|
||||
readLock.lock();
|
||||
Object comp = NBTReflectionUtil.gettoCompount(getCompound(), this);
|
||||
Object comp = getResolvedObject();
|
||||
if (comp == null)
|
||||
return "{}";
|
||||
if (MinecraftVersion.isForgePresent() && MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) {
|
||||
@@ -1118,7 +1476,107 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
|
||||
@Override
|
||||
public NBTCompound extractDifference(ReadableNBT other) {
|
||||
if (this == other)
|
||||
return new NBTContainer();
|
||||
|
||||
if (other instanceof NBTCompound) {
|
||||
return saveDiff(new NBTContainer(), this, (NBTCompound) other);
|
||||
} else {
|
||||
throw new NbtApiException("Unknown NBT object: " + other);
|
||||
}
|
||||
}
|
||||
|
||||
private static NBTCompound saveDiff(NBTCompound saveTo, NBTCompound compA, NBTCompound compB) {
|
||||
for (String key : compA.getKeys()) {
|
||||
saveDiff(saveTo, compA, compB, key);
|
||||
}
|
||||
return saveTo;
|
||||
}
|
||||
|
||||
private static void saveDiff(NBTCompound saveTo, NBTCompound compA, NBTCompound compB, String key) {
|
||||
boolean typeMismatch = compA.getType(key) != compB.getType(key);
|
||||
switch (compA.getType(key)) {
|
||||
case NBTTagByte:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setByte(key, compA.getByte(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagByteArray:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setByteArray(key, compA.getByteArray(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagCompound: {
|
||||
NBTCompound tmp1 = compA.getCompound(key);
|
||||
if (tmp1 == null) return;
|
||||
if (typeMismatch) {
|
||||
saveTo.addCompound(key).mergeCompound(tmp1);
|
||||
} else {
|
||||
NBTCompound tmp2 = compB.getCompound(key);
|
||||
if (tmp2 == null) {
|
||||
saveTo.addCompound(key).mergeCompound(tmp1);
|
||||
return;
|
||||
}
|
||||
NBTCompound tmpDiff = tmp1.extractDifference(tmp2);
|
||||
if (!tmpDiff.getKeys().isEmpty()) {
|
||||
saveTo.addCompound(key).mergeCompound(tmpDiff);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case NBTTagDouble:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setDouble(key, compA.getDouble(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagEnd:
|
||||
return; // ??
|
||||
case NBTTagFloat:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setFloat(key, compA.getFloat(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagInt:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setInteger(key, compA.getInteger(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagIntArray:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setIntArray(key, compA.getIntArray(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagList:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.set(key, NBTReflectionUtil.getEntry(compA, key));
|
||||
}
|
||||
return;
|
||||
case NBTTagLong:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setLong(key, compA.getLong(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagShort:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setShort(key, compA.getShort(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagString:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setString(key, compA.getString(key));
|
||||
}
|
||||
return;
|
||||
case NBTTagLongArray:
|
||||
if (typeMismatch || !isEqual(compA, compB, key)) {
|
||||
saveTo.setLongArray(key, compA.getLongArray(key));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
|
||||
if (compA.getType(key) != compB.getType(key))
|
||||
return false;
|
||||
switch (compA.getType(key)) {
|
||||
@@ -1126,8 +1584,10 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
return compA.getByte(key).equals(compB.getByte(key));
|
||||
case NBTTagByteArray:
|
||||
return Arrays.equals(compA.getByteArray(key), compB.getByteArray(key));
|
||||
case NBTTagCompound:
|
||||
return compA.getCompound(key).equals(compB.getCompound(key));
|
||||
case NBTTagCompound: {
|
||||
NBTCompound tmp = compA.getCompound(key);
|
||||
return tmp != null && tmp.equals(compB.getCompound(key));
|
||||
}
|
||||
case NBTTagDouble:
|
||||
return compA.getDouble(key).equals(compB.getDouble(key));
|
||||
case NBTTagEnd:
|
||||
@@ -1147,6 +1607,8 @@ public class NBTCompound implements ReadWriteNBT {
|
||||
return compA.getShort(key).equals(compB.getShort(key));
|
||||
case NBTTagString:
|
||||
return compA.getString(key).equals(compB.getString(key));
|
||||
case NBTTagLongArray:
|
||||
return Arrays.equals(compA.getLongArray(key), compB.getLongArray(key));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
@@ -35,6 +36,9 @@ public class NBTCompoundList extends NBTList<ReadWriteNBT> implements ReadWriteN
|
||||
* @return
|
||||
*/
|
||||
public NBTCompound addCompound(NBTCompound comp) {
|
||||
if (getParent().isReadOnly()) {
|
||||
throw new NbtApiException("Tried setting data in read only mode!");
|
||||
}
|
||||
try {
|
||||
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
|
||||
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
|
||||
@@ -53,7 +57,8 @@ public class NBTCompoundList extends NBTList<ReadWriteNBT> implements ReadWriteN
|
||||
}
|
||||
}
|
||||
|
||||
public NBTCompound addCompound(ReadWriteNBT comp) {
|
||||
@Override
|
||||
public ReadWriteNBT addCompound(ReadableNBT comp) {
|
||||
if (comp instanceof NBTCompound) {
|
||||
return addCompound((NBTCompound) comp);
|
||||
}
|
||||
@@ -79,6 +84,9 @@ public class NBTCompoundList extends NBTList<ReadWriteNBT> implements ReadWriteN
|
||||
if (element != null) {
|
||||
throw new NbtApiException("You need to pass null! ListCompounds from other lists won't work.");
|
||||
}
|
||||
if (getParent().isReadOnly()) {
|
||||
throw new NbtApiException("Tried setting data in read only mode!");
|
||||
}
|
||||
try {
|
||||
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
|
||||
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
|
||||
|
||||
@@ -16,10 +16,15 @@ import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
public class NBTContainer extends NBTCompound {
|
||||
|
||||
private Object nbt;
|
||||
private boolean closed;
|
||||
private boolean readOnly;
|
||||
|
||||
/**
|
||||
* Creates an empty, standalone NBTCompound
|
||||
*
|
||||
* @deprecated use {@link NBT#createNBTObject()}
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer() {
|
||||
super(null, null);
|
||||
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
@@ -29,11 +34,13 @@ public class NBTContainer extends NBTCompound {
|
||||
* Takes in any NMS Compound to wrap it
|
||||
*
|
||||
* @param nbt
|
||||
* @deprecated Use NBT.wrapNMSTag
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer(Object nbt) {
|
||||
super(null, null);
|
||||
if (nbt == null) {
|
||||
throw new NullPointerException("The NBT-Object can't be null!");
|
||||
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().isAssignableFrom(nbt.getClass())) {
|
||||
throw new NbtApiException("The object '" + nbt.getClass() + "' is not a valid NBT-Object!");
|
||||
@@ -45,7 +52,9 @@ public class NBTContainer extends NBTCompound {
|
||||
* Reads in a NBT InputStream
|
||||
*
|
||||
* @param inputsteam
|
||||
* @deprecated Use NBT.readNBT
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer(InputStream inputsteam) {
|
||||
super(null, null);
|
||||
this.nbt = NBTReflectionUtil.readNBT(inputsteam);
|
||||
@@ -56,7 +65,9 @@ public class NBTContainer extends NBTCompound {
|
||||
* {@link NbtApiException} in case something goes wrong.
|
||||
*
|
||||
* @param nbtString
|
||||
* @deprecated Use NBT.parseNBT
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTContainer(String nbtString) {
|
||||
super(null, null);
|
||||
if (nbtString == null) {
|
||||
@@ -79,4 +90,23 @@ public class NBTContainer extends NBTCompound {
|
||||
nbt = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setClosed() {
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
protected boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
protected NBTContainer setReadOnly(boolean readOnly) {
|
||||
this.readOnly = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,10 +3,8 @@ package de.tr7zw.changeme.nbtapi;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import de.tr7zw.annotations.FAUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.annotations.AvailableSince;
|
||||
import de.tr7zw.changeme.nbtapi.utils.annotations.CheckUtil;
|
||||
|
||||
/**
|
||||
* NBT class to access vanilla tags from Entities. Entities don't support custom
|
||||
@@ -21,6 +19,7 @@ public class NBTEntity extends NBTCompound {
|
||||
private final Entity ent;
|
||||
private final boolean readonly;
|
||||
private final Object compound;
|
||||
private boolean closed = false;
|
||||
|
||||
/**
|
||||
* @param entity Any valid Bukkit Entity
|
||||
@@ -41,8 +40,11 @@ public class NBTEntity extends NBTCompound {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated: Please use the NBT class
|
||||
*
|
||||
* @param entity Any valid Bukkit Entity
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTEntity(Entity entity) {
|
||||
super(null, null);
|
||||
if (entity == null) {
|
||||
@@ -53,6 +55,21 @@ public class NBTEntity extends NBTCompound {
|
||||
ent = entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setClosed() {
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReadOnly() {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCompound() {
|
||||
// this runs before async check, since it's just a copy
|
||||
@@ -80,9 +97,8 @@ public class NBTEntity extends NBTCompound {
|
||||
*
|
||||
* @return NBTCompound containing the data of the PersistentDataAPI
|
||||
*/
|
||||
@AvailableSince(version = MinecraftVersion.MC1_14_R1)
|
||||
public NBTCompound getPersistentDataContainer() {
|
||||
FAUtil.check(this::getPersistentDataContainer, CheckUtil::isAvaliable);
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_14_R1);
|
||||
return new NBTPersistentDataContainer(ent.getPersistentDataContainer());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTFileHandle;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
|
||||
|
||||
/**
|
||||
@@ -12,18 +13,20 @@ import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
|
||||
* @author tr7zw
|
||||
*
|
||||
*/
|
||||
public class NBTFile extends NBTCompound {
|
||||
public class NBTFile extends NBTCompound implements NBTFileHandle {
|
||||
|
||||
private final File file;
|
||||
private Object nbt;
|
||||
|
||||
/**
|
||||
* Creates a NBTFile that uses @param file to store it's data. If this file
|
||||
* Creates a NBTFile that uses @param file to store its data. If this file
|
||||
* exists, the data will be loaded.
|
||||
*
|
||||
* @param file
|
||||
* @throws IOException
|
||||
* @deprecated Use NBT.getFileHandle(file)
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTFile(File file) throws IOException {
|
||||
super(null, null);
|
||||
if (file == null) {
|
||||
@@ -43,6 +46,7 @@ public class NBTFile extends NBTCompound {
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
try {
|
||||
getWriteLock().lock();
|
||||
@@ -55,6 +59,7 @@ public class NBTFile extends NBTCompound {
|
||||
/**
|
||||
* @return The File used to store the data
|
||||
*/
|
||||
@Override
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
@@ -77,7 +82,9 @@ public class NBTFile extends NBTCompound {
|
||||
* @param file file to read
|
||||
* @return NBTCompound holding file's nbt data
|
||||
* @throws IOException exception
|
||||
* @deprecated Use NBT.readFile(file)
|
||||
*/
|
||||
@Deprecated
|
||||
public static NBTCompound readFrom(File file) throws IOException {
|
||||
if (!file.exists())
|
||||
return new NBTContainer();
|
||||
@@ -92,14 +99,16 @@ public class NBTFile extends NBTCompound {
|
||||
* @param file file
|
||||
* @param nbt NBT data
|
||||
* @throws IOException exception
|
||||
* @deprecated Use NBT.writeFile(file, nbt)
|
||||
*/
|
||||
@Deprecated
|
||||
public static void saveTo(File file, NBTCompound nbt) throws IOException {
|
||||
if (!file.exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
if (!file.createNewFile())
|
||||
throw new IOException("Unable to create file at " + file.getAbsolutePath());
|
||||
}
|
||||
NBTReflectionUtil.writeNBT(nbt.getCompound(), Files.newOutputStream(file.toPath()));
|
||||
nbt.writeCompound(Files.newOutputStream(file.toPath()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.GameprofileUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
@@ -13,7 +15,11 @@ public class NBTGameProfile {
|
||||
* @param profile
|
||||
* @return A NBTContainer with all the GameProfile data
|
||||
*/
|
||||
@Deprecated
|
||||
public static NBTCompound toNBT(GameProfile profile) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return (NBTCompound) GameprofileUtil.writeGameProfile(NBT.createNBTObject(), profile);
|
||||
}
|
||||
return new NBTContainer(ReflectionMethod.GAMEPROFILE_SERIALIZE.run(null,
|
||||
ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(), profile));
|
||||
}
|
||||
@@ -24,9 +30,13 @@ public class NBTGameProfile {
|
||||
* @param compound Has to contain GameProfile data
|
||||
* @return The reconstructed GameProfile
|
||||
*/
|
||||
@Deprecated
|
||||
public static GameProfile fromNBT(NBTCompound compound) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return GameprofileUtil.readGameProfile(compound);
|
||||
}
|
||||
return (GameProfile) ReflectionMethod.GAMEPROFILE_DESERIALIZE.run(null,
|
||||
NBTReflectionUtil.gettoCompount(compound.getCompound(), compound));
|
||||
NBTReflectionUtil.getToCompount(compound.getCompound(), compound));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
@@ -9,6 +12,7 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteItemNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
@@ -22,15 +26,20 @@ import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
|
||||
private ItemStack bukkitItem;
|
||||
private boolean directApply;
|
||||
private boolean readOnly;
|
||||
private final boolean directApply;
|
||||
private final boolean finalizer;
|
||||
private ItemStack originalSrcStack = null;
|
||||
private Object cachedCompound = null;
|
||||
private boolean closed = false;
|
||||
|
||||
/**
|
||||
* Constructor for NBTItems. The ItemStack will be cloned!
|
||||
* Constructor for NBTItems. The ItemStack will be cloned! Deprecated: Please
|
||||
* use the NBT class to work with items. It's up to 400% faster and provides
|
||||
* less ways to mess up code.
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTItem(ItemStack item) {
|
||||
this(item, false);
|
||||
}
|
||||
@@ -42,14 +51,19 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
* Modifying the stack in that case is not valid! Also
|
||||
* overwrites directApply
|
||||
*/
|
||||
protected NBTItem(ItemStack item, boolean directApply, boolean readOnly) {
|
||||
super(null, null);
|
||||
protected NBTItem(ItemStack item, boolean directApply, boolean readOnly, boolean finalizer) {
|
||||
super(null, null, readOnly);
|
||||
if (item == null || item.getType() == Material.AIR || item.getAmount() <= 0) {
|
||||
throw new NullPointerException("ItemStack can't be null/air/amount of 0! This is not a NBTAPI bug!");
|
||||
}
|
||||
if (readOnly) {
|
||||
this.finalizer = finalizer;
|
||||
if (finalizer) {
|
||||
this.bukkitItem = item;
|
||||
this.originalSrcStack = item;
|
||||
this.directApply = false;
|
||||
} else if (readOnly) {
|
||||
bukkitItem = item;
|
||||
this.readOnly = true;
|
||||
this.directApply = false;
|
||||
} else {
|
||||
this.directApply = directApply;
|
||||
bukkitItem = item.clone();
|
||||
@@ -67,11 +81,13 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
* @param item
|
||||
* @param directApply
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTItem(ItemStack item, boolean directApply) {
|
||||
super(null, null);
|
||||
if (item == null || item.getType() == Material.AIR || item.getAmount() <= 0) {
|
||||
throw new NullPointerException("ItemStack can't be null/air/amount of 0! This is not a NBTAPI bug!");
|
||||
}
|
||||
this.finalizer = false;
|
||||
this.directApply = directApply;
|
||||
bukkitItem = item.clone();
|
||||
if (directApply) {
|
||||
@@ -81,20 +97,87 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
|
||||
@Override
|
||||
public Object getCompound() {
|
||||
if (readOnly && ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(bukkitItem.getClass())) {
|
||||
return NBTReflectionUtil.getItemRootNBTTagCompound(NBTReflectionUtil.getCraftItemHandle(bukkitItem));
|
||||
if (closed) {
|
||||
throw new NbtApiException("Tried using closed NBT data!");
|
||||
}
|
||||
if (isReadOnly() && (cachedCompound != null
|
||||
|| ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(bukkitItem.getClass()))) {
|
||||
if (cachedCompound == null) {
|
||||
cachedCompound = NBTReflectionUtil
|
||||
.getItemRootNBTTagCompound(NBTReflectionUtil.getCraftItemHandle(bukkitItem));
|
||||
}
|
||||
return cachedCompound;
|
||||
}
|
||||
if (finalizer) {
|
||||
if (cachedCompound == null) {
|
||||
updateCachedCompound();
|
||||
}
|
||||
return cachedCompound;
|
||||
}
|
||||
return NBTReflectionUtil.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem));
|
||||
}
|
||||
|
||||
private void updateCachedCompound() {
|
||||
if (finalizer) {
|
||||
cachedCompound = NBTReflectionUtil
|
||||
.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem));
|
||||
}
|
||||
}
|
||||
|
||||
protected void finalizeChanges() {
|
||||
if (!finalizer || cachedCompound == null) {
|
||||
return;
|
||||
}
|
||||
// There was data, but not anymore, delete the tag from the itemstack
|
||||
if (NBTReflectionUtil.getKeys(this).isEmpty()) {
|
||||
cachedCompound = null;
|
||||
}
|
||||
if (ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(originalSrcStack.getClass())) {
|
||||
Object nmsStack = NBTReflectionUtil.getCraftItemHandle(originalSrcStack);
|
||||
NBTReflectionUtil.setItemStackCompound(nmsStack, cachedCompound);
|
||||
bukkitItem = originalSrcStack;
|
||||
} else {
|
||||
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
|
||||
NBTReflectionUtil.setItemStackCompound(stack, cachedCompound);
|
||||
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
|
||||
originalSrcStack.setItemMeta(bukkitItem.getItemMeta());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setClosed() {
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void setCompound(Object compound) {
|
||||
if (readOnly) {
|
||||
if (isReadOnly()) {
|
||||
throw new NbtApiException("Tried setting data in read only mode!");
|
||||
}
|
||||
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
|
||||
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound);
|
||||
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
|
||||
if (closed) {
|
||||
throw new NbtApiException("Tried using closed NBT data!");
|
||||
}
|
||||
if (finalizer) {
|
||||
cachedCompound = compound;
|
||||
return;
|
||||
}
|
||||
if (compound != null && ((Set<String>) ReflectionMethod.COMPOUND_GET_KEYS.run(compound)).isEmpty()) {
|
||||
compound = null;
|
||||
}
|
||||
if (ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(bukkitItem.getClass())) {
|
||||
Object nmsStack = NBTReflectionUtil.getCraftItemHandle(bukkitItem);
|
||||
NBTReflectionUtil.setItemStackCompound(nmsStack, compound);
|
||||
} else {
|
||||
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
|
||||
NBTReflectionUtil.setItemStackCompound(stack, compound);
|
||||
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,6 +189,7 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
*
|
||||
* @param item ItemStack that should get the new NBT data
|
||||
*/
|
||||
@Deprecated
|
||||
public void applyNBT(ItemStack item) {
|
||||
if (item == null || item.getType() == Material.AIR) {
|
||||
throw new NullPointerException("ItemStack can't be null/Air! This is not a NBTAPI bug!");
|
||||
@@ -120,6 +204,7 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
*
|
||||
* @param item ItemStack that should get the new NBT data
|
||||
*/
|
||||
@Deprecated
|
||||
public void mergeNBT(ItemStack item) {
|
||||
NBTItem nbti = new NBTItem(item);
|
||||
nbti.mergeCompound(this);
|
||||
@@ -131,10 +216,18 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
*
|
||||
* @param item ItemStack that should get the new NBT data
|
||||
*/
|
||||
@Deprecated
|
||||
public void mergeCustomNBT(ItemStack item) {
|
||||
if (item == null || item.getType() == Material.AIR) {
|
||||
throw new NullPointerException("ItemStack can't be null/Air!");
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
// 1.20.5+ doesn't have any vanilla tags
|
||||
NBT.modify(item, nbt -> {
|
||||
nbt.mergeCompound(this);
|
||||
});
|
||||
return;
|
||||
}
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
NBTReflectionUtil.getUnhandledNBTTags(meta)
|
||||
.putAll(NBTReflectionUtil.getUnhandledNBTTags(bukkitItem.getItemMeta()));
|
||||
@@ -146,7 +239,13 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
*
|
||||
* @return true when custom tags are present
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean hasCustomNbtData() {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
// 1.20.5+ doesn't have any vanilla tags
|
||||
return hasNBTData();
|
||||
}
|
||||
finalizeChanges();
|
||||
ItemMeta meta = bukkitItem.getItemMeta();
|
||||
return !NBTReflectionUtil.getUnhandledNBTTags(meta).isEmpty();
|
||||
}
|
||||
@@ -154,10 +253,18 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
/**
|
||||
* Remove all custom (non-vanilla) NBT tags from the NBTItem.
|
||||
*/
|
||||
@Deprecated
|
||||
public void clearCustomNBT() {
|
||||
finalizeChanges();
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
// 1.20.5+ doesn't have any vanilla tags
|
||||
setCompound(null);
|
||||
return;
|
||||
}
|
||||
ItemMeta meta = bukkitItem.getItemMeta();
|
||||
NBTReflectionUtil.getUnhandledNBTTags(meta).clear();
|
||||
bukkitItem.setItemMeta(meta);
|
||||
updateCachedCompound();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,7 +279,8 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
}
|
||||
|
||||
/**
|
||||
* This may return true even when the NBT is empty.
|
||||
* Returns true if the item has NBT data. This needs to be checked before
|
||||
* calling methods like remove, otherwise the value might be wrong!
|
||||
*
|
||||
* @return Does the ItemStack have a NBTCompound.
|
||||
*/
|
||||
@@ -191,10 +299,16 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
* @param handler
|
||||
*/
|
||||
public void modifyMeta(BiConsumer<ReadableNBT, ItemMeta> handler) {
|
||||
finalizeChanges();
|
||||
ItemMeta meta = bukkitItem.getItemMeta();
|
||||
handler.accept(this, meta);
|
||||
handler.accept(new NBTContainer(getResolvedObject()).setReadOnly(true), meta);
|
||||
bukkitItem.setItemMeta(meta);
|
||||
updateCachedCompound();
|
||||
if (directApply) {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
throw new NbtApiException(
|
||||
"Direct apply mode meta changes don't work anymore in 1.20.5+. Please switch to the modern NBT.modify sytnax!");
|
||||
}
|
||||
applyNBT(originalSrcStack);
|
||||
}
|
||||
}
|
||||
@@ -210,10 +324,12 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
* @param handler
|
||||
*/
|
||||
public <T extends ItemMeta> void modifyMeta(Class<T> type, BiConsumer<ReadableNBT, T> handler) {
|
||||
finalizeChanges();
|
||||
@SuppressWarnings("unchecked")
|
||||
T meta = (T) bukkitItem.getItemMeta();
|
||||
handler.accept(this, meta);
|
||||
handler.accept(new NBTContainer(getResolvedObject()).setReadOnly(true), meta);
|
||||
bukkitItem.setItemMeta(meta);
|
||||
updateCachedCompound();
|
||||
if (directApply) {
|
||||
applyNBT(originalSrcStack);
|
||||
}
|
||||
@@ -226,6 +342,7 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
* @param item
|
||||
* @return Standalone {@link NBTContainer} with the Item's data
|
||||
*/
|
||||
@Deprecated
|
||||
public static NBTContainer convertItemtoNBT(ItemStack item) {
|
||||
return NBTReflectionUtil.convertNMSItemtoNBTCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, item));
|
||||
}
|
||||
@@ -237,6 +354,8 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
* @param comp
|
||||
* @return ItemStack using the {@link NBTCompound}'s data
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public static ItemStack convertNBTtoItem(NBTCompound comp) {
|
||||
return (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null,
|
||||
NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp));
|
||||
@@ -244,12 +363,13 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
|
||||
/**
|
||||
* Helper method that converts {@link ItemStack}[] to {@link NBTContainer} with
|
||||
* all it data like Material, Damage, Amount and Tags. This is a custom
|
||||
* all its data like Material, Damage, Amount and Tags. This is a custom
|
||||
* implementation and won't work with vanilla code(Shulker content etc).
|
||||
*
|
||||
* @param items
|
||||
* @return Standalone {@link NBTContainer} with the Item's data
|
||||
*/
|
||||
@Deprecated
|
||||
public static NBTContainer convertItemArraytoNBT(ItemStack[] items) {
|
||||
NBTContainer container = new NBTContainer();
|
||||
container.setInteger("size", items.length);
|
||||
@@ -269,7 +389,7 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
/**
|
||||
* Helper method to do the inverse of "convertItemArraytoNBT". Creates an
|
||||
* {@link ItemStack}[] using the {@link NBTCompound}. This is a custom
|
||||
* implementation and won't work with vanilla code(Shulker content etc).
|
||||
* implementation and won't work with vanilla code (Shulker content, etc.).
|
||||
*
|
||||
* Will return null for invalid data. Empty slots in the array are filled with
|
||||
* AIR Stacks!
|
||||
@@ -277,6 +397,8 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
|
||||
* @param comp
|
||||
* @return ItemStack[] using the {@link NBTCompound}'s data
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public static ItemStack[] convertNBTtoItemArray(NBTCompound comp) {
|
||||
if (!comp.hasTag("size")) {
|
||||
return null;
|
||||
|
||||
@@ -48,7 +48,20 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
return parent;
|
||||
}
|
||||
|
||||
private void validateClosed() {
|
||||
if (parent.isClosed()) {
|
||||
throw new NbtApiException("Tried using closed NBT data!");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateWritable() {
|
||||
if (getParent().isReadOnly()) {
|
||||
throw new NbtApiException("Tried setting data in read only mode!");
|
||||
}
|
||||
}
|
||||
|
||||
protected void save() {
|
||||
validateClosed();
|
||||
parent.set(listName, listObject);
|
||||
}
|
||||
|
||||
@@ -56,6 +69,8 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean add(T element) {
|
||||
validateClosed();
|
||||
validateWritable();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
|
||||
@@ -74,6 +89,8 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
validateClosed();
|
||||
validateWritable();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
|
||||
@@ -91,6 +108,8 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public T set(int index, T element) {
|
||||
validateClosed();
|
||||
validateWritable();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
T prev = get(index);
|
||||
@@ -106,6 +125,8 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public T remove(int i) {
|
||||
validateClosed();
|
||||
validateWritable();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
T old = get(i);
|
||||
@@ -121,6 +142,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
return (int) ReflectionMethod.LIST_SIZE.run(listObject);
|
||||
@@ -153,6 +175,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
@@ -167,6 +190,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
@@ -181,6 +205,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
int size = size();
|
||||
@@ -195,6 +220,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends T> c) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
int size = size();
|
||||
@@ -209,6 +235,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
for (Object ele : c) {
|
||||
@@ -223,6 +250,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
int index = -1;
|
||||
@@ -238,6 +266,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
int size = size();
|
||||
@@ -252,6 +281,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
int size = size();
|
||||
@@ -270,11 +300,12 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getWriteLock().lock();
|
||||
int size = size();
|
||||
int id = -1;
|
||||
while ((id = indexOf(o)) != -1) {
|
||||
int id = indexOf(o);
|
||||
if (id != -1) {
|
||||
remove(id);
|
||||
}
|
||||
return size != size();
|
||||
@@ -375,6 +406,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
Object[] ar = new Object[size()];
|
||||
@@ -389,6 +421,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <E> E[] toArray(E[] a) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
E[] ar = Arrays.copyOf(a, size());
|
||||
@@ -410,6 +443,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public List<T> subList(int fromIndex, int toIndex) {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
ArrayList<T> list = new ArrayList<>();
|
||||
@@ -428,6 +462,7 @@ public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
validateClosed();
|
||||
try {
|
||||
parent.getReadLock().lock();
|
||||
return listObject.toString();
|
||||
|
||||
@@ -24,13 +24,32 @@ public class NBTListCompound extends NBTCompound {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClosed() {
|
||||
return owner.getParent().isClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReadOnly() {
|
||||
return owner.getParent().isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCompound() {
|
||||
if (isClosed()) {
|
||||
throw new NbtApiException("Tried using closed NBT data!");
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCompound(Object compound) {
|
||||
if (isClosed()) {
|
||||
throw new NbtApiException("Tried using closed NBT data!");
|
||||
}
|
||||
if (isReadOnly()) {
|
||||
throw new NbtApiException("Tried setting data in read only mode!");
|
||||
}
|
||||
this.compound = compound;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,11 @@ public class NBTPersistentDataContainer extends NBTCompound {
|
||||
private final PersistentDataContainer container;
|
||||
|
||||
public NBTPersistentDataContainer(PersistentDataContainer container) {
|
||||
super(null, null);
|
||||
this(container, false);
|
||||
}
|
||||
|
||||
protected NBTPersistentDataContainer(PersistentDataContainer container, boolean readOnly) {
|
||||
super(null, null, readOnly);
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,19 +6,29 @@ import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.DataFixerUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.GsonWrapper;
|
||||
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.CodecHelper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
@@ -34,6 +44,12 @@ public class NBTReflectionUtil {
|
||||
|
||||
private static Field field_unhandledTags = null;
|
||||
private static Field field_handle = null;
|
||||
private static Object type_custom_data = null;
|
||||
private static Object registry_access = null;
|
||||
public static Codec<Object> itemstack_codec = null;
|
||||
public static DynamicOps<Object> nbtOps = null;
|
||||
public static DynamicOps<Object> nbtRegistryOps = null;
|
||||
public static Object problemReporter = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -48,6 +64,28 @@ public class NBTReflectionUtil {
|
||||
} catch (NoSuchFieldException e) {
|
||||
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
try {
|
||||
Field typeField = ReflectionUtil.getMappedField(ClassWrapper.NMS_DATACOMPONENTS.getClazz(), "net.minecraft.core.component.DataComponents#CUSTOM_DATA");
|
||||
type_custom_data = typeField.get(null);
|
||||
} catch (Exception e) {
|
||||
MinecraftVersion.getLogger().log(Level.WARNING,
|
||||
"Unable to find DataComponents#CUSTOM_DATA, NBTApi will not be able to read/write custom data on 1.20+",
|
||||
e);
|
||||
}
|
||||
try {
|
||||
Object nmsServer = ReflectionMethod.NMSSERVER_GETSERVER.run(Bukkit.getServer());
|
||||
registry_access = ReflectionMethod.NMSSERVER_GETREGISTRYACCESS.run(nmsServer);
|
||||
itemstack_codec = (Codec<Object>) ReflectionUtil.getMappedField(ClassWrapper.NMS_ITEMSTACK.getClazz(), "net.minecraft.world.item.ItemStack#CODEC").get(null);
|
||||
nbtOps = (DynamicOps<Object>) ReflectionUtil.getMappedField(ClassWrapper.NMS_NBTOPS.getClazz(), "net.minecraft.nbt.NbtOps#INSTANCE").get(null);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
nbtRegistryOps = (DynamicOps<Object>) ReflectionMethod.GET_SERIALIZATION_CONTEXT.run(registry_access, nbtOps);
|
||||
problemReporter = ReflectionUtil.getMappedField(ClassWrapper.NMS_PROBLEM_REPORTER.getClazz(), "net.minecraft.util.ProblemReporter#DISCARDING").get(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +117,12 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
public static Object readNBT(InputStream stream) {
|
||||
try {
|
||||
return ReflectionMethod.NBTFILE_READ.run(null, stream);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R3)) {
|
||||
return ReflectionMethod.NBTFILE_READV2.run(null, stream,
|
||||
ReflectionMethod.NBTACCOUNTER_CREATE_UNLIMITED.run(null));
|
||||
} else {
|
||||
return ReflectionMethod.NBTFILE_READ.run(null, stream);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
stream.close();
|
||||
@@ -127,13 +170,10 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
public static void writeApiNBT(NBTCompound comp, OutputStream stream) {
|
||||
try {
|
||||
Object nbttag = comp.getCompound();
|
||||
if (nbttag == null) {
|
||||
nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
Object workingtag = comp.getResolvedObject();
|
||||
if (workingtag == null) {
|
||||
workingtag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
|
||||
}
|
||||
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);
|
||||
@@ -149,13 +189,40 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
public static Object getItemRootNBTTagCompound(Object nmsitem) {
|
||||
try {
|
||||
Object answer = ReflectionMethod.NMSITEM_GETTAG.run(nmsitem);
|
||||
return answer != null ? answer : ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
Object customData = ReflectionMethod.NMSDATACOMPONENTHOLDER_GET.run(nmsitem, type_custom_data);
|
||||
if (customData == null) {
|
||||
return null;
|
||||
}
|
||||
return ReflectionMethod.NMSCUSTOMDATA_GETCOPY.run(customData);
|
||||
} else {
|
||||
Object answer = ReflectionMethod.NMSITEM_GETTAG.run(nmsitem);
|
||||
return answer;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Exception while getting an Itemstack's NBTCompound!", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Compound as the Items NBT or CustomData
|
||||
*
|
||||
* @param nmsItem
|
||||
* @param compound
|
||||
*/
|
||||
public static void setItemStackCompound(Object nmsItem, Object compound) {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
if (compound == null) {
|
||||
ReflectionMethod.NMSITEM_SET.run(nmsItem, new Object[] { type_custom_data, null });
|
||||
} else {
|
||||
ReflectionMethod.NMSITEM_SET.run(nmsItem, type_custom_data,
|
||||
ObjectCreator.NMS_CUSTOMDATA.getInstance(compound));
|
||||
}
|
||||
} else {
|
||||
ReflectionMethod.ITEMSTACK_SET_TAG.run(nmsItem, compound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts {@link NBTCompound} to NMS ItemStacks
|
||||
*
|
||||
@@ -163,15 +230,35 @@ public class NBTReflectionUtil {
|
||||
* @return NMS ItemStack
|
||||
*/
|
||||
public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) {
|
||||
Object nmsComp = null;
|
||||
try {
|
||||
Object nmsComp = gettoCompount(nbtcompound.getCompound(), nbtcompound);
|
||||
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) {
|
||||
nmsComp = getToCompount(nbtcompound.getCompound(), nbtcompound);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
if (nbtcompound.hasTag("DataVersion", NBTType.NBTTagInt)) {
|
||||
int dataVersion = nbtcompound.getInteger("DataVersion");
|
||||
int currentVersion = DataFixerUtil.getCurrentVersion();
|
||||
if (dataVersion < currentVersion) {
|
||||
nmsComp = DataFixerUtil.fixUpRawItemData(nmsComp, dataVersion, currentVersion);
|
||||
}
|
||||
} else if (nbtcompound.hasTag("tag") || nbtcompound.hasTag("Count")) {
|
||||
nmsComp = DataFixerUtil.fixUpRawItemData(nmsComp, DataFixerUtil.VERSION1_20_4, DataFixerUtil.getCurrentVersion());
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
return CodecHelper.convertNbtToItemStack(nmsComp);
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
Optional<Object> opt = (Optional<Object>) ReflectionMethod.NMSITEM_LOAD_MODERN.run(null,
|
||||
registry_access, nmsComp);
|
||||
return opt.orElse(null);
|
||||
} else {
|
||||
return ReflectionMethod.NMSITEM_LOAD.run(null, registry_access, nmsComp);
|
||||
}
|
||||
} else if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) {
|
||||
return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nmsComp);
|
||||
} else {
|
||||
return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nmsComp);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Exception while converting NBTCompound to NMS ItemStack!", e);
|
||||
throw new NbtApiException("Exception while converting NBTCompound to NMS ItemStack! " + nmsComp, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,8 +270,20 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) {
|
||||
try {
|
||||
Object answer = ReflectionMethod.NMSITEM_SAVE.run(nmsitem, ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance());
|
||||
return new NBTContainer(answer);
|
||||
NBTContainer container;
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
container = new NBTContainer(CodecHelper.convertItemStackToNbt(nmsitem));
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
container = new NBTContainer(ReflectionMethod.NMSITEM_SAVE_MODERN.run(nmsitem, registry_access));
|
||||
} else {
|
||||
Object answer = ReflectionMethod.NMSITEM_SAVE.run(nmsitem,
|
||||
ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance());
|
||||
container = new NBTContainer(answer);
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_12_R1)) {
|
||||
container.setInteger("DataVersion", DataFixerUtil.getCurrentVersion());
|
||||
}
|
||||
return container;
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Exception while converting NMS ItemStack to NBTCompound!", e);
|
||||
}
|
||||
@@ -197,6 +296,7 @@ public class NBTReflectionUtil {
|
||||
* @return Map containing unhandled (custom) NBT tags
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Deprecated
|
||||
public static Map<String, Object> getUnhandledNBTTags(ItemMeta meta) {
|
||||
try {
|
||||
return (Map<String, Object>) field_unhandledTags.get(meta);
|
||||
@@ -214,7 +314,16 @@ public class NBTReflectionUtil {
|
||||
public static Object getEntityNBTTagCompound(Object nmsEntity) {
|
||||
try {
|
||||
Object nbt = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
|
||||
Object answer = ReflectionMethod.NMS_ENTITY_GET_NBT.run(nmsEntity, nbt);
|
||||
Object answer;
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
Object output = ReflectionMethod.NMS_GET_TAG_VALUE_OUTPUT.run(null, problemReporter, registry_access);
|
||||
|
||||
ReflectionMethod.NMS_ENTITY_GET_NBT_1216.run(nmsEntity, output);
|
||||
|
||||
answer = ReflectionMethod.NMS_TAG_VALUE_OUTPUT_TO_TAG_COMPOUND.run(output);
|
||||
} else {
|
||||
answer = ReflectionMethod.NMS_ENTITY_GET_NBT.run(nmsEntity, nbt);
|
||||
}
|
||||
if (answer == null)
|
||||
answer = nbt;
|
||||
return answer;
|
||||
@@ -232,7 +341,14 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
public static Object setEntityNBTTag(Object nbtTag, Object nmsEntity) {
|
||||
try {
|
||||
ReflectionMethod.NMS_ENTITY_SET_NBT.run(nmsEntity, nbtTag);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
Object valueInputTag = ReflectionMethod.NMS_GET_TAG_VALUE_INPUT.run(null, problemReporter, registry_access, nbtTag);
|
||||
|
||||
ReflectionMethod.NMS_ENTITY_SET_NBT_1216.run(nmsEntity, valueInputTag);
|
||||
} else {
|
||||
ReflectionMethod.NMS_ENTITY_SET_NBT.run(nmsEntity, nbtTag);
|
||||
}
|
||||
|
||||
return nmsEntity;
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Exception while setting the NBTCompound of an Entity", ex);
|
||||
@@ -258,8 +374,21 @@ public class NBTReflectionUtil {
|
||||
o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos);
|
||||
}
|
||||
|
||||
if (o == null) {
|
||||
throw new NbtApiException("The passed BlockState(" + tile.getType()
|
||||
+ ") doesn't point to a BlockEntity. Only BlockEntities like Chest/Signs/Furnance/etc have NBT.");
|
||||
}
|
||||
|
||||
Object answer = null;
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1)) {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
Object output = ReflectionMethod.NMS_GET_TAG_VALUE_OUTPUT.run(null, problemReporter, registry_access);
|
||||
|
||||
ReflectionMethod.TILEENTITY_GET_NBT_1216.run(o, output);
|
||||
|
||||
answer = ReflectionMethod.NMS_TAG_VALUE_OUTPUT_TO_TAG_COMPOUND.run(output);
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
answer = ReflectionMethod.TILEENTITY_GET_NBT_1205.run(o, registry_access);
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1)) {
|
||||
answer = ReflectionMethod.TILEENTITY_GET_NBT_1181.run(o);
|
||||
} else {
|
||||
answer = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
|
||||
@@ -292,7 +421,13 @@ public class NBTReflectionUtil {
|
||||
Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ());
|
||||
o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos);
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
Object valueInput = ReflectionMethod.NMS_GET_TAG_VALUE_INPUT.run(null, problemReporter, registry_access, comp);
|
||||
|
||||
ReflectionMethod.TILEENTITY_SET_NBT_1216.run(o, valueInput);
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
ReflectionMethod.TILEENTITY_SET_NBT_1205.run(o, comp, registry_access);
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
|
||||
ReflectionMethod.TILEENTITY_SET_NBT.run(o, comp);
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
Object blockData = ReflectionMethod.TILEENTITY_GET_BLOCKDATA.run(o);
|
||||
@@ -315,7 +450,11 @@ public class NBTReflectionUtil {
|
||||
public static Object getSubNBTTagCompound(Object compound, String name) {
|
||||
try {
|
||||
if ((boolean) ReflectionMethod.COMPOUND_HAS_KEY.run(compound, name)) {
|
||||
return ReflectionMethod.COMPOUND_GET_COMPOUND.run(compound, name);
|
||||
Object comp = ReflectionMethod.COMPOUND_GET_COMPOUND.run(compound, name);
|
||||
if (comp instanceof Optional) {
|
||||
return ((Optional<?>) comp).orElse(null);
|
||||
}
|
||||
return comp;
|
||||
} else {
|
||||
throw new NbtApiException("Tried getting invalid compound '" + name + "' from '" + compound + "'!");
|
||||
}
|
||||
@@ -339,10 +478,10 @@ public class NBTReflectionUtil {
|
||||
if (nbttag == null) {
|
||||
nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp)) {
|
||||
if (!validCompound(comp)) {
|
||||
return;
|
||||
}
|
||||
Object workingtag = gettoCompount(nbttag, comp);
|
||||
Object workingtag = getToCompount(nbttag, comp);
|
||||
try {
|
||||
ReflectionMethod.COMPOUND_SET.run(workingtag, name,
|
||||
ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance());
|
||||
@@ -356,25 +495,36 @@ public class NBTReflectionUtil {
|
||||
* Checks if the Compound is correctly linked to it's roots
|
||||
*
|
||||
* @param comp
|
||||
* @return true if this is a valide Compound, else false
|
||||
* @return true if this is a valid Compound, else false
|
||||
*/
|
||||
public static Boolean valideCompound(NBTCompound comp) {
|
||||
public static boolean validCompound(NBTCompound comp) {
|
||||
Object root = comp.getCompound();
|
||||
if (root instanceof Optional) {
|
||||
root = ((Optional<?>) root).orElse(null);
|
||||
}
|
||||
if (root == null) {
|
||||
root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
return (gettoCompount(root, comp)) != null;
|
||||
Object tmp = getToCompount(root, comp);
|
||||
comp.setResolvedObject(tmp);
|
||||
return tmp != null;
|
||||
}
|
||||
|
||||
protected static Object gettoCompount(Object nbttag, NBTCompound comp) {
|
||||
public static Object getToCompount(Object nbttag, NBTCompound comp) {
|
||||
Deque<String> structure = new ArrayDeque<>();
|
||||
while (comp.getParent() != null) {
|
||||
structure.add(comp.getName());
|
||||
comp = comp.getParent();
|
||||
}
|
||||
if (nbttag instanceof Optional) {
|
||||
nbttag = ((Optional<?>) nbttag).orElse(null);
|
||||
}
|
||||
while (!structure.isEmpty()) {
|
||||
String target = structure.pollLast();
|
||||
nbttag = getSubNBTTagCompound(nbttag, target);
|
||||
if (nbttag instanceof Optional) {
|
||||
nbttag = ((Optional<?>) nbttag).orElse(null);
|
||||
}
|
||||
if (nbttag == null) {
|
||||
throw new NbtApiException("Unable to find tag '" + target + "' in " + nbttag);
|
||||
}
|
||||
@@ -389,20 +539,17 @@ public class NBTReflectionUtil {
|
||||
* @param nbtcompoundSrc Data to merge
|
||||
*/
|
||||
public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompoundSrc) {
|
||||
Object workingtagSrc = nbtcompoundSrc.getResolvedObject();
|
||||
if (workingtagSrc == null) {
|
||||
return;
|
||||
}
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
if (!validCompound(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);
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
try {
|
||||
ReflectionMethod.COMPOUND_MERGE.run(workingtag, workingtagSrc);
|
||||
comp.setCompound(rootnbttag);
|
||||
@@ -411,28 +558,6 @@ public class NBTReflectionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content for a given key inside a Compound
|
||||
*
|
||||
* @param comp
|
||||
* @param key
|
||||
* @return Content saved under this key
|
||||
*/
|
||||
public static String getContent(NBTCompound comp, String key) {
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
try {
|
||||
return ReflectionMethod.COMPOUND_GET.run(workingtag, key).toString();
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Exception while getting the Content for key '" + key + "'!", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a key in a {@link NBTCompound} to a given value
|
||||
*
|
||||
@@ -449,10 +574,10 @@ public class NBTReflectionUtil {
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp)) {
|
||||
if (!validCompound(comp)) {
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
}
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
try {
|
||||
ReflectionMethod.COMPOUND_SET.run(workingtag, key, val);
|
||||
comp.setCompound(rootnbttag);
|
||||
@@ -472,15 +597,23 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> NBTList<T> getList(NBTCompound comp, String key, NBTType type, Class<T> clazz) {
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
Object workingtag = comp.getResolvedObject();
|
||||
if (workingtag == null) {
|
||||
workingtag = dummyNBT.getCompound(); // it creates a new ListTag if needed, but its unlinked
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
return null;
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
try {
|
||||
Object nbt = ReflectionMethod.COMPOUND_GET_LIST.run(workingtag, key, type.getId());
|
||||
Object nbt = null;
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
nbt = ReflectionMethod.COMPOUND_GET_LIST.run(workingtag, key);
|
||||
if (nbt instanceof Optional) {
|
||||
nbt = ((Optional<?>) nbt).orElse(null);
|
||||
}
|
||||
if (nbt == null) {
|
||||
nbt = ClassWrapper.NMS_NBTTAGLIST.getClazz().newInstance();
|
||||
}
|
||||
} else {
|
||||
nbt = ReflectionMethod.COMPOUND_GET_LIST_LEGACY.run(workingtag, key, type.getId());
|
||||
}
|
||||
if (clazz == String.class) {
|
||||
return (NBTList<T>) new NBTStringList(comp, key, type, nbt);
|
||||
} else if (clazz == NBTListCompound.class) {
|
||||
@@ -506,20 +639,43 @@ public class NBTReflectionUtil {
|
||||
}
|
||||
|
||||
public static NBTType getListType(NBTCompound comp, String key) {
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
Object workingtag = comp.getResolvedObject();
|
||||
if (workingtag == null) {
|
||||
workingtag = dummyNBT.getCompound(); // it creates a new ListTag if needed, but its unlinked
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
return null;
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
try {
|
||||
Object nbt = ReflectionMethod.COMPOUND_GET.run(workingtag, key);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
if (nbt instanceof Optional) {
|
||||
nbt = ((Optional<?>) nbt).orElse(null);
|
||||
}
|
||||
if (nbt == null) {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
if (new NBTStringList(comp, key, NBTType.NBTTagString, nbt).isEmpty()) {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
Object compound = ReflectionMethod.LIST_GET.run(nbt, 0);
|
||||
if (compound instanceof Optional) {
|
||||
compound = ((Optional<?>) compound).orElse(null);
|
||||
}
|
||||
if (compound == null) {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
return NBTType.fromName((String) ReflectionMethod.TAGTYPE_GET_NAME
|
||||
.run(ReflectionMethod.TAGTYPE_OWN_TYPE.run(compound)));
|
||||
}
|
||||
String fieldname = "type";
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
|
||||
fieldname = "w";
|
||||
}
|
||||
Field f = nbt.getClass().getDeclaredField(fieldname);
|
||||
Field f;
|
||||
try {
|
||||
f = nbt.getClass().getDeclaredField(fieldname);
|
||||
} catch (NoSuchFieldException ignore) {
|
||||
// fallback try mojang mapped/legacy
|
||||
f = nbt.getClass().getDeclaredField("type");
|
||||
}
|
||||
f.setAccessible(true);
|
||||
return NBTType.valueOf(f.getByte(nbt));
|
||||
} catch (Exception ex) {
|
||||
@@ -528,16 +684,9 @@ public class NBTReflectionUtil {
|
||||
}
|
||||
|
||||
public static Object getEntry(NBTCompound comp, String key) {
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
return null;
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
Object workingtag = comp.getResolvedObject();
|
||||
try {
|
||||
Object nbt = ReflectionMethod.COMPOUND_GET.run(workingtag, key);
|
||||
return nbt;
|
||||
return ReflectionMethod.COMPOUND_GET.run(workingtag, key);
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Exception while getting an Entry!", ex);
|
||||
}
|
||||
@@ -588,11 +737,11 @@ public class NBTReflectionUtil {
|
||||
public static void remove(NBTCompound comp, String key) {
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
return;
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
}
|
||||
if (!validCompound(comp))
|
||||
return;
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key);
|
||||
comp.setCompound(rootnbttag);
|
||||
}
|
||||
@@ -605,13 +754,10 @@ public class NBTReflectionUtil {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Set<String> getKeys(NBTCompound comp) {
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
Object workingtag = comp.getResolvedObject();
|
||||
if (workingtag == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
return (Set<String>) ReflectionMethod.COMPOUND_GET_KEYS.run(workingtag);
|
||||
}
|
||||
|
||||
@@ -632,13 +778,15 @@ public class NBTReflectionUtil {
|
||||
if (rootnbttag == null) {
|
||||
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
if (!validCompound(comp))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
Object workingtag = getToCompount(rootnbttag, comp);
|
||||
type.run(workingtag, key, data);
|
||||
comp.setCompound(rootnbttag);
|
||||
}
|
||||
|
||||
private final static NBTContainer dummyNBT = new NBTContainer();
|
||||
|
||||
/**
|
||||
* Gets data from the Compound
|
||||
*
|
||||
@@ -648,14 +796,46 @@ public class NBTReflectionUtil {
|
||||
* @return The value or default fallback from NMS
|
||||
*/
|
||||
public static Object getData(NBTCompound comp, ReflectionMethod type, String key) {
|
||||
Object rootnbttag = comp.getCompound();
|
||||
if (rootnbttag == null) {
|
||||
return null;
|
||||
Object workingtag = comp.getResolvedObject();
|
||||
// return default behavior data as if there was a compound
|
||||
if (workingtag == null) {
|
||||
workingtag = dummyNBT.getCompound();
|
||||
}
|
||||
if (!valideCompound(comp))
|
||||
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
|
||||
Object workingtag = gettoCompount(rootnbttag, comp);
|
||||
return type.run(workingtag, key);
|
||||
if (workingtag instanceof Optional<?>) {
|
||||
workingtag = ((Optional<Object>) workingtag).orElseGet(() -> dummyNBT.getCompound());
|
||||
}
|
||||
Object obj = type.run(workingtag, key);
|
||||
if (obj instanceof Optional<?>) {
|
||||
return ((Optional<Object>) obj).orElseGet(() -> getDefaultValue(type));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static Object getDefaultValue(ReflectionMethod type) {
|
||||
if (type == ReflectionMethod.COMPOUND_GET_STRING) {
|
||||
return "";
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_BYTE) {
|
||||
return (byte) 0;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_SHORT) {
|
||||
return (short) 0;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_BOOLEAN) {
|
||||
return false;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_INT) {
|
||||
return 0;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_LONG) {
|
||||
return 0L;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_FLOAT) {
|
||||
return 0.0f;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_DOUBLE) {
|
||||
return 0.0d;
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_BYTEARRAY) {
|
||||
return new byte[0];
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_INTARRAY) {
|
||||
return new int[0];
|
||||
} else if (type == ReflectionMethod.COMPOUND_GET_LONGARRAY) {
|
||||
return new long[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package de.tr7zw.changeme.nbtapi;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
@@ -21,7 +22,11 @@ public class NBTStringList extends NBTList<String> {
|
||||
@Override
|
||||
public String get(int index) {
|
||||
try {
|
||||
return (String) ReflectionMethod.LIST_GET_STRING.run(listObject, index);
|
||||
Object ret = ReflectionMethod.LIST_GET_STRING.run(listObject, index);
|
||||
if (ret instanceof Optional<?>) {
|
||||
return ((Optional<String>) ret).orElse("");
|
||||
}
|
||||
return (String) ret;
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException(ex);
|
||||
}
|
||||
|
||||
@@ -3,10 +3,8 @@ package de.tr7zw.changeme.nbtapi;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.BlockState;
|
||||
|
||||
import de.tr7zw.annotations.FAUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.changeme.nbtapi.utils.annotations.AvailableSince;
|
||||
import de.tr7zw.changeme.nbtapi.utils.annotations.CheckUtil;
|
||||
|
||||
/**
|
||||
* NBT class to access vanilla tags from TileEntities. TileEntities don't
|
||||
@@ -22,12 +20,13 @@ public class NBTTileEntity extends NBTCompound {
|
||||
private final BlockState tile;
|
||||
private final boolean readonly;
|
||||
private final Object compound;
|
||||
private boolean closed = false;
|
||||
|
||||
/**
|
||||
* @param tile BlockState from any TileEntity
|
||||
* @param readonly Readonly makes a copy at init, only reading from that copy
|
||||
*/
|
||||
public NBTTileEntity(BlockState tile, boolean readonly) {
|
||||
protected NBTTileEntity(BlockState tile, boolean readonly) {
|
||||
super(null, null);
|
||||
if (tile == null || (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3) && !tile.isPlaced())) {
|
||||
throw new NullPointerException("Tile can't be null/not placed!");
|
||||
@@ -42,8 +41,11 @@ public class NBTTileEntity extends NBTCompound {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated: Please use the NBT class
|
||||
*
|
||||
* @param tile BlockState from any TileEntity
|
||||
*/
|
||||
@Deprecated
|
||||
public NBTTileEntity(BlockState tile) {
|
||||
super(null, null);
|
||||
if (tile == null || (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3) && !tile.isPlaced())) {
|
||||
@@ -54,6 +56,21 @@ public class NBTTileEntity extends NBTCompound {
|
||||
this.tile = tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setClosed() {
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReadOnly() {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCompound() {
|
||||
// this runs before async check, since it's just a copy
|
||||
@@ -81,9 +98,8 @@ public class NBTTileEntity extends NBTCompound {
|
||||
*
|
||||
* @return NBTCompound containing the data of the PersistentDataAPI
|
||||
*/
|
||||
@AvailableSince(version = MinecraftVersion.MC1_14_R1)
|
||||
public NBTCompound getPersistentDataContainer() {
|
||||
FAUtil.check(this::getPersistentDataContainer, CheckUtil::isAvaliable);
|
||||
CheckUtil.assertAvailable(MinecraftVersion.MC1_14_R1);
|
||||
if (hasTag("PublicBukkitValues")) {
|
||||
return getCompound("PublicBukkitValues");
|
||||
} else {
|
||||
|
||||
@@ -8,14 +8,16 @@ package de.tr7zw.changeme.nbtapi;
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public enum NBTType {
|
||||
NBTTagEnd(0), NBTTagByte(1), NBTTagShort(2), NBTTagInt(3), NBTTagLong(4), NBTTagFloat(5), NBTTagDouble(6),
|
||||
NBTTagByteArray(7), NBTTagIntArray(11), NBTTagString(8), NBTTagList(9), NBTTagCompound(10);
|
||||
NBTTagEnd(0, ""), NBTTagByte(1, "BYTE"), NBTTagShort(2, "SHORT"), NBTTagInt(3, "INT"), NBTTagLong(4, "LONG"), NBTTagFloat(5, "FLOAT"), NBTTagDouble(6, "DOUBLE"),
|
||||
NBTTagByteArray(7, "BYTE[]"), NBTTagString(8, "STRING"), NBTTagList(9, "LIST"), NBTTagCompound(10, "COMPOUND"), NBTTagIntArray(11, "INT[]"), NBTTagLongArray(12, "LONG[]");
|
||||
|
||||
NBTType(int i) {
|
||||
NBTType(int i, String name) {
|
||||
id = i;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* @return Id used by Minecraft internally
|
||||
@@ -23,6 +25,13 @@ public enum NBTType {
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name of the NBTType
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Internal Minecraft id
|
||||
@@ -35,4 +44,11 @@ public enum NBTType {
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
|
||||
public static NBTType fromName(String name) {
|
||||
for (NBTType t : values())
|
||||
if (t.getName().equals(name))
|
||||
return t;
|
||||
return NBTType.NBTTagEnd;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,16 +29,6 @@ public class NbtApiException extends RuntimeException {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param cause
|
||||
* @param enableSuppression
|
||||
* @param writableStackTrace
|
||||
*/
|
||||
public NbtApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(generateMessage(message), cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param cause
|
||||
@@ -65,12 +55,12 @@ public class NbtApiException extends RuntimeException {
|
||||
if (message == null)
|
||||
return null;
|
||||
if (confirmedBroken == null) {
|
||||
return "[?]" + message;
|
||||
return "[?][" + MinecraftVersion.getNBTAPIVersion() + "]" + message;
|
||||
} else if (confirmedBroken == false) {
|
||||
return "[Selfchecked]" + message;
|
||||
return "[Selfchecked][" + MinecraftVersion.getNBTAPIVersion() + "]" + message;
|
||||
}
|
||||
|
||||
return "[" + MinecraftVersion.getVersion()
|
||||
return "[" + MinecraftVersion.getVersion() + "][" + MinecraftVersion.getNBTAPIVersion()
|
||||
+ "]There were errors detected during the server self-check! Please, make sure that NBT-API is up to date. Error message: "
|
||||
+ message;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package de.tr7zw.changeme.nbtapi.handler;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTHandler;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
|
||||
public class NBTHandlers {
|
||||
|
||||
public static final NBTHandler<ItemStack> ITEM_STACK = new NBTHandler<ItemStack>() {
|
||||
|
||||
@Override
|
||||
public boolean fuzzyMatch(Object obj) {
|
||||
return obj instanceof ItemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(ReadWriteNBT nbt, String key, ItemStack value) {
|
||||
nbt.removeKey(key);
|
||||
ReadWriteNBT tag = nbt.getOrCreateCompound(key);
|
||||
tag.mergeCompound(NBT.itemStackToNBT(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack get(ReadableNBT nbt, String key) {
|
||||
ReadableNBT tag = nbt.getCompound(key);
|
||||
if (tag != null) {
|
||||
return NBT.itemStackFromNBT(tag);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public static final NBTHandler<ReadableNBT> STORE_READABLE_TAG = new NBTHandler<ReadableNBT>() {
|
||||
|
||||
@Override
|
||||
public boolean fuzzyMatch(Object obj) {
|
||||
return obj instanceof ReadableNBT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(ReadWriteNBT nbt, String key, ReadableNBT value) {
|
||||
nbt.removeKey(key);
|
||||
nbt.getOrCreateCompound(key).mergeCompound(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableNBT get(ReadableNBT nbt, String key) {
|
||||
ReadableNBT tag = nbt.getCompound(key);
|
||||
if (tag != null) {
|
||||
ReadWriteNBT value = NBT.createNBTObject();
|
||||
value.mergeCompound(tag);
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public static final NBTHandler<ReadWriteNBT> STORE_READWRITE_TAG = new NBTHandler<ReadWriteNBT>() {
|
||||
|
||||
@Override
|
||||
public boolean fuzzyMatch(Object obj) {
|
||||
return obj instanceof ReadWriteNBT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(ReadWriteNBT nbt, String key, ReadWriteNBT value) {
|
||||
nbt.removeKey(key);
|
||||
nbt.getOrCreateCompound(key).mergeCompound(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadWriteNBT get(ReadableNBT nbt, String key) {
|
||||
ReadableNBT tag = nbt.getCompound(key);
|
||||
if (tag != null) {
|
||||
ReadWriteNBT value = NBT.createNBTObject();
|
||||
value.mergeCompound(tag);
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.tr7zw.changeme.nbtapi.iface;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface NBTFileHandle extends ReadWriteNBT {
|
||||
|
||||
/**
|
||||
* Saves the data to the file
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
void save() throws IOException;
|
||||
|
||||
/**
|
||||
* @return The File used to store the data
|
||||
*/
|
||||
File getFile();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package de.tr7zw.changeme.nbtapi.iface;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface NBTHandler<T> {
|
||||
|
||||
public default boolean fuzzyMatch(Object obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void set(@Nonnull ReadWriteNBT nbt, @Nonnull String key, @Nonnull T value);
|
||||
|
||||
public T get(@Nonnull ReadableNBT nbt, @Nonnull String key);
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
|
||||
public interface ReadWriteItemNBT extends ReadWriteNBT {
|
||||
public interface ReadWriteItemNBT extends ReadWriteNBT, ReadableItemNBT {
|
||||
|
||||
/**
|
||||
* True, if the item has any tags now known for this item type.
|
||||
|
||||
@@ -2,6 +2,8 @@ package de.tr7zw.changeme.nbtapi.iface;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public interface ReadWriteNBT extends ReadableNBT {
|
||||
@@ -86,6 +88,16 @@ public interface ReadWriteNBT extends ReadableNBT {
|
||||
*/
|
||||
void setIntArray(String key, int[] value);
|
||||
|
||||
/**
|
||||
* Setter
|
||||
*
|
||||
* Requires 1.16+
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
void setLongArray(String key, long[] value);
|
||||
|
||||
/**
|
||||
* Setter
|
||||
*
|
||||
@@ -135,8 +147,29 @@ public interface ReadWriteNBT extends ReadableNBT {
|
||||
* @param name
|
||||
* @return The Compound instance or null
|
||||
*/
|
||||
@Nullable
|
||||
ReadWriteNBT getCompound(String name);
|
||||
|
||||
/**
|
||||
* Returns the resolved and creates compounds as required.
|
||||
* <p>
|
||||
*
|
||||
* @param key Path key, seperated by '.'. For example: "foo.bar.baz". Dots can
|
||||
* be escaped with a backslash.
|
||||
* @return The resolved compound.
|
||||
*/
|
||||
ReadWriteNBT resolveOrCreateCompound(String key);
|
||||
|
||||
/**
|
||||
* Set an Object to a key via the provided handler.
|
||||
*
|
||||
* @param <T>
|
||||
* @param key
|
||||
* @param value
|
||||
* @param handler
|
||||
*/
|
||||
<T> void set(String key, T value, NBTHandler<T> handler);
|
||||
|
||||
/**
|
||||
* Set a key to the given Enum value. It gets stored as a String. Passing null
|
||||
* as value will call removeKey(key) instead.
|
||||
@@ -170,6 +203,10 @@ public interface ReadWriteNBT extends ReadableNBT {
|
||||
|
||||
@Override
|
||||
ReadWriteNBTCompoundList getCompoundList(String name);
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
ReadWriteNBT resolveCompound(String key);
|
||||
|
||||
/**
|
||||
* Remove all keys from this compound
|
||||
|
||||
+9
@@ -10,6 +10,15 @@ public interface ReadWriteNBTCompoundList extends ReadableNBTList<ReadWriteNBT>
|
||||
* @return A new instance of the class.
|
||||
*/
|
||||
ReadWriteNBT addCompound();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
ReadWriteNBT addCompound(ReadableNBT comp);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this list
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.tr7zw.changeme.nbtapi.iface;
|
||||
|
||||
public interface ReadableItemNBT extends ReadableNBT {
|
||||
|
||||
/**
|
||||
* Returns true if the item has NBT data.
|
||||
*
|
||||
* @return Does the ItemStack have a NBTCompound.
|
||||
*/
|
||||
public boolean hasNBTData();
|
||||
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import java.io.OutputStream;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
@@ -84,6 +86,7 @@ public interface ReadableNBT {
|
||||
* @param key The key to use to retrieve the value.
|
||||
* @return A byte array.
|
||||
*/
|
||||
@Nullable
|
||||
byte[] getByteArray(String key);
|
||||
|
||||
/**
|
||||
@@ -93,8 +96,21 @@ public interface ReadableNBT {
|
||||
* @param key The key of the value you want to get.
|
||||
* @return An array of integers.
|
||||
*/
|
||||
@Nullable
|
||||
int[] getIntArray(String key);
|
||||
|
||||
/**
|
||||
* Returns the value associated with the given key as an array of longs, or null
|
||||
* if the key does not exist.
|
||||
*
|
||||
* Requires 1.16+
|
||||
*
|
||||
* @param key The key of the value you want to get.
|
||||
* @return An array of integers.
|
||||
*/
|
||||
@Nullable
|
||||
long[] getLongArray(String key);
|
||||
|
||||
/**
|
||||
* Returns the value associated with the given key, or false if the key is not
|
||||
* found.
|
||||
@@ -111,6 +127,7 @@ public interface ReadableNBT {
|
||||
* @param key The key of the itemstack you want to get.
|
||||
* @return An ItemStack
|
||||
*/
|
||||
@Nullable
|
||||
ItemStack getItemStack(String key);
|
||||
|
||||
/**
|
||||
@@ -121,6 +138,7 @@ public interface ReadableNBT {
|
||||
* @return The stored {@link ItemStack} array, or null if stored data wasn't
|
||||
* found
|
||||
*/
|
||||
@Nullable
|
||||
ItemStack[] getItemStackArray(String key);
|
||||
|
||||
/**
|
||||
@@ -129,6 +147,7 @@ public interface ReadableNBT {
|
||||
* @param key The key to get the value from
|
||||
* @return A UUID object.
|
||||
*/
|
||||
@Nullable
|
||||
UUID getUUID(String key);
|
||||
|
||||
/**
|
||||
@@ -155,10 +174,20 @@ public interface ReadableNBT {
|
||||
*/
|
||||
Set<String> getKeys();
|
||||
|
||||
/**
|
||||
* Checks whether this NBT is empty (has no stored data).
|
||||
*
|
||||
* @return whether this NBT is empty
|
||||
*/
|
||||
default boolean isEmpty() {
|
||||
return getKeys().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @return The Compound instance or null
|
||||
*/
|
||||
@Nullable
|
||||
ReadableNBT getCompound(String name);
|
||||
|
||||
/**
|
||||
@@ -209,6 +238,7 @@ public interface ReadableNBT {
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
NBTType getListType(String name);
|
||||
|
||||
/**
|
||||
@@ -221,8 +251,8 @@ public interface ReadableNBT {
|
||||
* Returns the stored value if exists, or provided value otherwise.
|
||||
* <p>
|
||||
* Supported types:
|
||||
* {@code byte/Byte, short/Short, int/Integer, long/Long, float/Float, double/Double, byte[], int[]},
|
||||
* {@link String}, {@link UUID}
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key key
|
||||
* @param defaultValue default non-null value
|
||||
@@ -235,16 +265,69 @@ public interface ReadableNBT {
|
||||
* Returns the stored value if exists, or null.
|
||||
* <p>
|
||||
* Supported types:
|
||||
* {@code Byte, Short, Integer, Long, Float, Double, byte[], int[]},
|
||||
* {@link String}, {@link UUID}
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key key
|
||||
* @param type data type
|
||||
* @param <T> value type
|
||||
* @return Stored or provided value
|
||||
*/
|
||||
@Nullable
|
||||
<T> T getOrNull(String key, Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns the resolved value if exists, or null.
|
||||
* <p>
|
||||
* Supported types:
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key Path key, separated by '.'. For example: "foo.bar.baz". Dots can
|
||||
* be escaped with a backslash.
|
||||
* @param type data type
|
||||
* @param <T> value type
|
||||
* @return resolved or provided value
|
||||
*/
|
||||
@Nullable
|
||||
<T> T resolveOrNull(String key, Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns the resolved value if exists, or provided value otherwise.
|
||||
* <p>
|
||||
* Supported types:
|
||||
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
|
||||
* {@link String}, {@link UUID}, and {@link Enum}
|
||||
*
|
||||
* @param key Path key, separated by '.'. For example: "foo.bar.baz".
|
||||
* Dots can be escaped with a backslash.
|
||||
* @param defaultValue default non-null value
|
||||
* @param <T> value type
|
||||
* @return resolved or provided value
|
||||
*/
|
||||
<T> T resolveOrDefault(String key, T defaultValue);
|
||||
|
||||
/**
|
||||
* Returns the resolved Compound if exists, or null.
|
||||
* <p>
|
||||
*
|
||||
* @param key Path key, separated by '.'. For example: "foo.bar.baz". Dots can
|
||||
* be escaped with a backslash.
|
||||
* @return The resolved value if exists, or null.
|
||||
*/
|
||||
@Nullable
|
||||
ReadableNBT resolveCompound(String key);
|
||||
|
||||
/**
|
||||
* Get the object at the specified key via the handler.
|
||||
*
|
||||
* @param <T>
|
||||
* @param key
|
||||
* @param handler
|
||||
* @return
|
||||
*/
|
||||
<T> T get(String key, NBTHandler<T> handler);
|
||||
|
||||
/**
|
||||
* Get an Enum value that has been set via setEnum or setString(key,
|
||||
* value.name()). Passing null/invalid keys will return null.
|
||||
@@ -254,6 +337,7 @@ public interface ReadableNBT {
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
<E extends Enum<E>> E getEnum(String key, Class<E> type);
|
||||
|
||||
/**
|
||||
@@ -269,6 +353,17 @@ public interface ReadableNBT {
|
||||
*/
|
||||
void writeCompound(OutputStream stream);
|
||||
|
||||
/**
|
||||
* Compares this readable nbt to the other one
|
||||
* and returns the difference.
|
||||
* <p>Note: the result will only contain data that is present
|
||||
* in this readable nbt and is missing/different in the provided one.
|
||||
*
|
||||
* @param other other readable nbt
|
||||
* @return difference between readable nbts
|
||||
*/
|
||||
ReadWriteNBT extractDifference(ReadableNBT other);
|
||||
|
||||
/**
|
||||
* @return The NBT as printable NBT-Json.
|
||||
*/
|
||||
|
||||
@@ -1,412 +0,0 @@
|
||||
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.getLogger;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
getLogger()
|
||||
.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) {
|
||||
getLogger().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) {
|
||||
getLogger().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) {
|
||||
getLogger().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) {
|
||||
MinecraftVersion.getLogger().info("[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) {
|
||||
getLogger().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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
|
||||
public class CheckUtil {
|
||||
|
||||
private CheckUtil() {
|
||||
// util
|
||||
}
|
||||
|
||||
public static void assertAvailable(MinecraftVersion version) {
|
||||
if (!MinecraftVersion.isAtLeastVersion(version))
|
||||
throw new NbtApiException(
|
||||
"This Method is only avaliable for the version " + version.name() + " and above!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import com.mojang.datafixers.DSL.TypeReference;
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTReflectionUtil;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
public class DataFixerUtil {
|
||||
|
||||
// https://minecraft.wiki/w/Data_version
|
||||
public static final int VERSION1_12R1 = 1343;
|
||||
public static final int VERSION1_16R1 = 2586;
|
||||
public static final int VERSION1_17R1 = 2730;
|
||||
public static final int VERSION1_18R1 = 2975;
|
||||
public static final int VERSION1_19R1 = 3120;
|
||||
public static final int VERSION1_19R3 = 3337;
|
||||
public static final int VERSION1_20R1 = 3465;
|
||||
public static final int VERSION1_20R2 = 3578;
|
||||
public static final int VERSION1_20R3 = 3700;
|
||||
public static final int VERSION1_20R4 = 3837;
|
||||
public static final int VERSION1_21R1 = 3953;
|
||||
public static final int VERSION1_21R2 = 4080;
|
||||
public static final int VERSION1_21R3 = 4189;
|
||||
public static final int VERSION1_21R4 = 4323;
|
||||
public static final int VERSION1_21R5 = 4435;
|
||||
public static final int VERSION1_21R6 = 4554;
|
||||
public static final int VERSION1_21R7 = 4671;
|
||||
public static final int VERSION_26_1 = 4786;
|
||||
public static final int VERSION_26_2 = 4903;
|
||||
// There was a mixup between version numbers and revisions, kept for compatibility, use the above revision numbers
|
||||
@Deprecated
|
||||
public static final int VERSION1_12_2 = 1343;
|
||||
@Deprecated
|
||||
public static final int VERSION1_16_5 = 2586;
|
||||
@Deprecated
|
||||
public static final int VERSION1_17_1 = 2730;
|
||||
@Deprecated
|
||||
public static final int VERSION1_18_2 = 2975;
|
||||
@Deprecated
|
||||
public static final int VERSION1_19_2 = 3120;
|
||||
@Deprecated
|
||||
public static final int VERSION1_19_4 = 3337;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_1 = 3465;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_2 = 3578;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_4 = 3700;
|
||||
@Deprecated
|
||||
public static final int VERSION1_20_5 = 3837;
|
||||
// the 1.21 versions use Revision instead of patch versions, unlike the other above. kept for compatibility
|
||||
@Deprecated
|
||||
public static final int VERSION1_21 = 3953;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_2 = 4080;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_3 = 4189;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_4 = 4323;
|
||||
@Deprecated
|
||||
public static final int VERSION1_21_5 = 4435;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object fixUpRawItemData(Object nbt, int fromVersion, int toVersion)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
DataFixer dataFixer = (DataFixer) ReflectionMethod.GET_DATAFIXER.run(null);
|
||||
TypeReference itemStackReference = (TypeReference) ReflectionUtil.getMappedField(ClassWrapper.NMS_REFERENCES.getClazz(),"net.minecraft.util.datafix.fixes.References#ITEM_STACK").get(null);
|
||||
DynamicOps<Object> nbtOps = (DynamicOps<Object>) ReflectionUtil.getMappedField(ClassWrapper.NMS_NBTOPS.getClazz(), "net.minecraft.nbt.NbtOps#INSTANCE").get(null);
|
||||
Dynamic<Object> fixed = dataFixer.update(itemStackReference, new Dynamic<Object>(nbtOps, nbt), fromVersion,
|
||||
toVersion);
|
||||
return fixed.getValue();
|
||||
}
|
||||
|
||||
public static ReadWriteNBT fixUpItemData(ReadWriteNBT nbt, int fromVersion, int toVersion)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
ReadWriteNBT tag = NBT.wrapNMSTag(fixUpRawItemData(
|
||||
NBTReflectionUtil.getToCompount(((NBTCompound) nbt).getCompound(), ((NBTCompound) nbt)), fromVersion,
|
||||
toVersion));
|
||||
tag.setInteger("DataVersion", toVersion);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static ReadWriteNBT fixUpItemData(ReadWriteNBT nbt, int fromVersion)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
return fixUpItemData(nbt, fromVersion, getCurrentVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will return the closest or exact version number of the current
|
||||
* server. Only contains versions people will reasonably use and will fail with
|
||||
* an exception, when the target version is before 1.12.2. (Assuming no one will
|
||||
* update 1.8 items to 1.11, if so, provide the version numbers to the converter
|
||||
* method directly)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static int getCurrentVersion() {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC26_2)) {
|
||||
return VERSION_26_2;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC26_1)) {
|
||||
return VERSION_26_1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R7)) {
|
||||
return VERSION1_21R7;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
return VERSION1_21R6;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R5)) {
|
||||
return VERSION1_21R5;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
return VERSION1_21R4;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R3)) {
|
||||
return VERSION1_21R3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R2)) {
|
||||
return VERSION1_21R2;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R1)) {
|
||||
return VERSION1_21R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return VERSION1_20R4;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R3)) {
|
||||
return VERSION1_20R3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R1)) {
|
||||
return VERSION1_20R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_19_R3)) {
|
||||
return VERSION1_19R3;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_19_R1)) {
|
||||
return VERSION1_19R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1)) {
|
||||
return VERSION1_18R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
|
||||
return VERSION1_17R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
return VERSION1_16R1;
|
||||
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_12_R1)) {
|
||||
return VERSION1_12R1;
|
||||
}
|
||||
throw new NbtApiException(
|
||||
"Trying to update data *to* a version before 1.12.2? Something is probably going wrong, contact the plugin author.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBTList;
|
||||
|
||||
public class GameprofileUtil {
|
||||
|
||||
private static Method GET_NAME = null;
|
||||
private static Method GET_ID = null;
|
||||
private static Method GET_VALUE = null;
|
||||
private static Method GET_SIGNATURE = null;
|
||||
private static Method GET_PROPERTY_NAME = null;
|
||||
private static Method GET_PROPERTIES = null;
|
||||
|
||||
static {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
GET_NAME = GameProfile.class.getDeclaredMethod("name");
|
||||
GET_ID = GameProfile.class.getDeclaredMethod("id");
|
||||
GET_VALUE = com.mojang.authlib.properties.Property.class.getDeclaredMethod("value");
|
||||
GET_SIGNATURE = com.mojang.authlib.properties.Property.class.getDeclaredMethod("signature");
|
||||
GET_PROPERTY_NAME = com.mojang.authlib.properties.Property.class.getDeclaredMethod("name");
|
||||
GET_PROPERTIES = GameProfile.class.getDeclaredMethod("properties");
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GameProfile readGameProfile(ReadableNBT arg) {
|
||||
String string = null;
|
||||
UUID uUID = null;
|
||||
if (arg.hasTag("Name") && arg.getType("Name") == NBTType.NBTTagString) {
|
||||
string = arg.getString("Name");
|
||||
} else if (arg.hasTag("name") && arg.getType("name") == NBTType.NBTTagString) {
|
||||
string = arg.getString("name");
|
||||
}
|
||||
if (arg.hasTag("Id") && arg.getType("Id") == NBTType.NBTTagIntArray && arg.getIntArray("Id").length == 4) {
|
||||
uUID = arg.getUUID("Id");
|
||||
} else if (arg.hasTag("id") && arg.getType("id") == NBTType.NBTTagIntArray
|
||||
&& arg.getIntArray("id").length == 4) {
|
||||
uUID = arg.getUUID("id");
|
||||
}
|
||||
try {
|
||||
GameProfile gameProfile = new GameProfile(uUID, string);
|
||||
if (arg.hasTag("Properties") && arg.getType("Properties") == NBTType.NBTTagCompound) {
|
||||
ReadableNBT compoundTag = arg.getCompound("Properties");
|
||||
for (String string2 : compoundTag.getKeys()) {
|
||||
ReadableNBTList<ReadWriteNBT> listTag = compoundTag.getCompoundList(string);
|
||||
for (int i = 0; i < listTag.size(); ++i) {
|
||||
ReadableNBT compoundTag2 = listTag.get(i);
|
||||
String string3 = compoundTag2.getString("Value");
|
||||
if (compoundTag2.hasTag("Signature")
|
||||
&& compoundTag2.getType("Signature") == NBTType.NBTTagString) {
|
||||
gameProfile.getProperties().put(string2, new com.mojang.authlib.properties.Property(string2,
|
||||
string3, compoundTag2.getString("Signature")));
|
||||
} else {
|
||||
gameProfile.getProperties().put(string2,
|
||||
new com.mojang.authlib.properties.Property(string2, string3));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (arg.getType("properties") == NBTType.NBTTagList) { // 1.20.5+
|
||||
ReadableNBTList<ReadWriteNBT> listTag = arg.getCompoundList("properties");
|
||||
for (int i = 0; i < listTag.size(); ++i) {
|
||||
ReadableNBT compoundTag2 = listTag.get(i);
|
||||
String string2 = compoundTag2.getString("name");
|
||||
String string3 = compoundTag2.getString("value");
|
||||
if (compoundTag2.hasTag("signature")
|
||||
&& compoundTag2.getType("signature") == NBTType.NBTTagString) {
|
||||
gameProfile.getProperties().put(string2, new com.mojang.authlib.properties.Property(string2,
|
||||
string3, compoundTag2.getString("signature")));
|
||||
} else {
|
||||
gameProfile.getProperties().put(string2,
|
||||
new com.mojang.authlib.properties.Property(string2, string3));
|
||||
}
|
||||
}
|
||||
}
|
||||
return gameProfile;
|
||||
} catch (Throwable var11) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ReadWriteNBT writeGameProfile(ReadWriteNBT arg, GameProfile gameProfile) {
|
||||
String name = getName(gameProfile);
|
||||
if (!(name == null || name.isEmpty())) {
|
||||
String nameKey = MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4) ? "name" : "Name";
|
||||
arg.setString(nameKey, getName(gameProfile));
|
||||
}
|
||||
UUID id = getId(gameProfile);
|
||||
if (id != null) {
|
||||
String idKey = MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4) ? "id" : "Id";
|
||||
arg.setUUID(idKey, id);
|
||||
}
|
||||
PropertyMap properties = getProperties(gameProfile);
|
||||
if (!properties.isEmpty()) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
ReadWriteNBTCompoundList list = arg.getCompoundList("properties");
|
||||
for (com.mojang.authlib.properties.Property property : properties.values()) {
|
||||
ReadWriteNBT tag = list.addCompound();
|
||||
tag.setString("name", getPropertyName(property));
|
||||
tag.setString("value", getValue(property));
|
||||
if (property.hasSignature()) {
|
||||
tag.setString("signature", getSignature(property));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ReadWriteNBT compoundTag = arg.getOrCreateCompound("Properties");
|
||||
for (String string : gameProfile.getProperties().keySet()) {
|
||||
ReadWriteNBTCompoundList list = compoundTag.getCompoundList(string);
|
||||
for (com.mojang.authlib.properties.Property property : properties.get(string)) {
|
||||
ReadWriteNBT tag = list.addCompound();
|
||||
tag.setString("Value", getValue(property));
|
||||
if (property.hasSignature()) {
|
||||
tag.setString("Signature", getSignature(property));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
private static String getName(GameProfile profile) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_NAME.invoke(profile).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get GameProfile name via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return profile.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private static UUID getId(GameProfile profile) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return (UUID) GET_ID.invoke(profile);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get GameProfile id via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return profile.getId();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getValue(com.mojang.authlib.properties.Property property) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_VALUE.invoke(property).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get Property value via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return property.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSignature(com.mojang.authlib.properties.Property property) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_SIGNATURE.invoke(property).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get Property signature via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return property.getSignature();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPropertyName(com.mojang.authlib.properties.Property property) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return GET_PROPERTY_NAME.invoke(property).toString();
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get Property name via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return property.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private static PropertyMap getProperties(GameProfile profile) {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R6)) {
|
||||
try {
|
||||
return (PropertyMap) GET_PROPERTIES.invoke(profile);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Failed to get GameProfile properties via reflection", e);
|
||||
}
|
||||
} else {
|
||||
return profile.getProperties();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,20 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.DrilldownPie;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
/**
|
||||
* This class acts as the "Brain" of the NBTApi. It contains the main logger for
|
||||
@@ -19,11 +30,16 @@ public enum MinecraftVersion {
|
||||
MC1_7_R4(174), MC1_8_R3(183), MC1_9_R1(191), MC1_9_R2(192), MC1_10_R1(1101), MC1_11_R1(1111), MC1_12_R1(1121),
|
||||
MC1_13_R1(1131), MC1_13_R2(1132), MC1_14_R1(1141), MC1_15_R1(1151), MC1_16_R1(1161), MC1_16_R2(1162),
|
||||
MC1_16_R3(1163), MC1_17_R1(1171), MC1_18_R1(1181, true), MC1_18_R2(1182, true), MC1_19_R1(1191, true),
|
||||
MC1_19_R2(1192, true), MC1_19_R3(1193, true), MC1_20_R1(1201, true);
|
||||
MC1_19_R2(1192, true), MC1_19_R3(1193, true), MC1_20_R1(1201, true), MC1_20_R2(1202, true), MC1_20_R3(1203, true),
|
||||
MC1_20_R4(1204, true), MC1_21_R1(1211, true), MC1_21_R2(1212, true), MC1_21_R3(1213, true), MC1_21_R4(1214, true),
|
||||
MC1_21_R5(1215, true), MC1_21_R6(1216, true), MC1_21_R7(1217, true), MC26_1(260100, true), MC26_2(260200, true);
|
||||
|
||||
private static MinecraftVersion version;
|
||||
private static Boolean hasGsonSupport;
|
||||
private static Boolean isForgePresent;
|
||||
private static Boolean isNeoForgePresent;
|
||||
private static Boolean isFabricPresent;
|
||||
private static Boolean isFoliaPresent;
|
||||
private static boolean bStatsDisabled = false;
|
||||
private static boolean disablePackageWarning = false;
|
||||
private static boolean updateCheckDisabled = true;
|
||||
@@ -33,11 +49,38 @@ public enum MinecraftVersion {
|
||||
private static Logger logger = Logger.getLogger("NBTAPI");
|
||||
|
||||
// NBT-API Version
|
||||
protected static final String VERSION = "2.12.0-SNAPSHOT";
|
||||
protected static final String VERSION = "2.16.0";
|
||||
|
||||
private final int versionId;
|
||||
private final boolean mojangMapping;
|
||||
|
||||
// TODO: not nice
|
||||
private static final Map<String, MinecraftVersion> VERSION_TO_REVISION = new HashMap<String, MinecraftVersion>() {
|
||||
{
|
||||
this.put("1.20", MC1_20_R1);
|
||||
this.put("1.20.1", MC1_20_R1);
|
||||
this.put("1.20.2", MC1_20_R2);
|
||||
this.put("1.20.3", MC1_20_R3);
|
||||
this.put("1.20.4", MC1_20_R3);
|
||||
this.put("1.20.5", MC1_20_R4);
|
||||
this.put("1.20.6", MC1_20_R4);
|
||||
this.put("1.21", MC1_21_R1);
|
||||
this.put("1.21.1", MC1_21_R1);
|
||||
this.put("1.21.2", MC1_21_R2);
|
||||
this.put("1.21.3", MC1_21_R2);
|
||||
this.put("1.21.4", MC1_21_R3);
|
||||
this.put("1.21.5", MC1_21_R4);
|
||||
this.put("1.21.6", MC1_21_R5);
|
||||
this.put("1.21.7", MC1_21_R5);
|
||||
this.put("1.21.8", MC1_21_R5);
|
||||
this.put("1.21.9", MC1_21_R6);
|
||||
this.put("1.21.10", MC1_21_R6);
|
||||
this.put("1.21.11", MC1_21_R7);
|
||||
this.put("26.1", MC26_1);
|
||||
this.put("26.2", MC26_2);
|
||||
}
|
||||
};
|
||||
|
||||
MinecraftVersion(int versionId) {
|
||||
this(versionId, false);
|
||||
}
|
||||
@@ -70,7 +113,11 @@ public enum MinecraftVersion {
|
||||
*/
|
||||
public String getPackageName() {
|
||||
if (this == UNKNOWN) {
|
||||
return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
try {
|
||||
return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
} catch (Exception ex) {
|
||||
// ignore, paper without remap, will fail
|
||||
}
|
||||
}
|
||||
return this.name().replace("MC", "v");
|
||||
}
|
||||
@@ -105,28 +152,115 @@ public enum MinecraftVersion {
|
||||
if (version != null) {
|
||||
return version;
|
||||
}
|
||||
final String ver = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
logger.info("[NBTAPI] Found Spigot: " + ver + "! Trying to find NMS support");
|
||||
try {
|
||||
final String ver = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
logger.info("[NBTAPI] Found Minecraft: " + ver + "! Trying to find NMS support");
|
||||
version = MinecraftVersion.valueOf(ver.replace("v", "MC"));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
version = MinecraftVersion.UNKNOWN;
|
||||
} catch (Exception ex) {
|
||||
logger.info("[NBTAPI] Found Minecraft: " + Bukkit.getServer().getBukkitVersion().split("-")[0]
|
||||
+ "! Trying to find NMS support");
|
||||
version = VERSION_TO_REVISION.get(Bukkit.getServer().getBukkitVersion().split("-")[0]);
|
||||
if (version == null) {
|
||||
// check for modern versions with the new versioning scheme, also the new paper version format
|
||||
String versionString = Bukkit.getServer().getBukkitVersion().split("-")[0].split(".build")[0];
|
||||
for (Entry<String, MinecraftVersion> entry : VERSION_TO_REVISION.entrySet()) {
|
||||
if (versionString.startsWith(entry.getKey()) && version == null) {
|
||||
version = entry.getValue();
|
||||
// pick the highest revision that matches the version string, in case 26.1.3 is somehow different to 26.1
|
||||
} else if (versionString.startsWith(entry.getKey()) && entry.getValue().getVersionId() > version.getVersionId()) {
|
||||
version = entry.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (version == null) {
|
||||
version = UNKNOWN;
|
||||
}
|
||||
}
|
||||
if (version != UNKNOWN) {
|
||||
logger.info("[NBTAPI] NMS support '" + version.name() + "' loaded!");
|
||||
} else {
|
||||
logger.warning("[NBTAPI] This Server-Version(" + ver + ") is not supported by this NBT-API Version("
|
||||
+ VERSION + ") located in " + VersionChecker.getPlugin()
|
||||
logger.warning("[NBTAPI] This Server-Version(" + Bukkit.getServer().getBukkitVersion()
|
||||
+ ") is not supported by this NBT-API Version(" + VERSION + ") located in "
|
||||
+ VersionChecker.getPlugin()
|
||||
+ ". The NBT-API will try to work as good as it can! Some functions may not work!");
|
||||
}
|
||||
init();
|
||||
return version;
|
||||
}
|
||||
|
||||
public static String getNBTAPIVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
private static void init() {
|
||||
// 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',
|
||||
'a', 'n', 'g', 'e', 'm', 'e', '.', 'n', 'b', 't', 'a', 'p', 'i', '.', 'u', 't', 'i', 'l', 's' });
|
||||
final String reservedPackage = new String(new byte[] { 'd', 'e', '.', 't', 'r', '7', 'z', 'w', '.', 'n', 'b',
|
||||
't', 'a', 'p', 'i', '.', 'u', 't', 'i', 'l', 's' });
|
||||
try {
|
||||
if (hasGsonSupport() && !bStatsDisabled)
|
||||
new ApiMetricsLite();
|
||||
if (hasGsonSupport() && !bStatsDisabled) {
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin(VersionChecker.getPlugin());
|
||||
if (plugin != null && plugin instanceof JavaPlugin) {
|
||||
getLogger()
|
||||
.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
|
||||
Metrics metrics = new Metrics((JavaPlugin) plugin, 1058);
|
||||
metrics.addCustomChart(new SimplePie("nbtapi_version", () -> {
|
||||
return VERSION;
|
||||
}));
|
||||
metrics.addCustomChart(new DrilldownPie("nms_version", () -> {
|
||||
Map<String, Map<String, Integer>> map = new HashMap<>();
|
||||
Map<String, Integer> entry = new HashMap<>();
|
||||
entry.put(Bukkit.getName(), 1);
|
||||
map.put(getVersion().name(), entry);
|
||||
return map;
|
||||
}));
|
||||
metrics.addCustomChart(new SimplePie("shaded", () -> {
|
||||
return Boolean.toString(!"NBTAPI".equals(VersionChecker.getPlugin()));
|
||||
}));
|
||||
metrics.addCustomChart(new SimplePie("server_software", () -> {
|
||||
return Bukkit.getName();
|
||||
}));
|
||||
metrics.addCustomChart(new SimplePie("parent_plugin", () -> {
|
||||
return VersionChecker.getPluginforBStats();
|
||||
}));
|
||||
metrics.addCustomChart(new SimplePie("parent_plugin_type", () -> {
|
||||
return VersionChecker.getPluginType();
|
||||
}));
|
||||
metrics.addCustomChart(new SimplePie("special_environment", () -> {
|
||||
if (isFoliaPresent()) {
|
||||
return "Folia";
|
||||
} else if (isForgePresent()) {
|
||||
return "Forge";
|
||||
} else if (isFabricPresent()) {
|
||||
return "Fabric";
|
||||
} else if (isNeoForgePresent()) {
|
||||
return "NeoForge";
|
||||
} else {
|
||||
return "None";
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new SimplePie("bindings_check", () -> {
|
||||
|
||||
boolean failedBinding = false;
|
||||
for (ClassWrapper c : ClassWrapper.values()) {
|
||||
if (c.isEnabled() && c.getClazz() == null) {
|
||||
failedBinding = true;
|
||||
}
|
||||
}
|
||||
for (ReflectionMethod method : ReflectionMethod.values()) {
|
||||
if (method.isCompatible() && !method.isLoaded()) {
|
||||
failedBinding = true;
|
||||
}
|
||||
}
|
||||
|
||||
return failedBinding ? "Failed" : "Pass";
|
||||
}));
|
||||
} else if (plugin == null) {
|
||||
getLogger().info("[NBTAPI] Unable to create a bStats instance!!");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.WARNING, "[NBTAPI] Error enabling Metrics!", ex);
|
||||
}
|
||||
@@ -139,10 +273,6 @@ public enum MinecraftVersion {
|
||||
logger.log(Level.WARNING, "[NBTAPI] Error while checking for updates! Error: " + ex.getMessage());
|
||||
}
|
||||
}).start();
|
||||
// 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',
|
||||
'a', 'n', 'g', 'e', 'm', 'e', '.', 'n', 'b', 't', 'a', 'p', 'i', '.', 'u', 't', 'i', 'l', 's' });
|
||||
if (!disablePackageWarning && MinecraftVersion.class.getPackage().getName().equals(defaultPackage)) {
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
@@ -156,17 +286,32 @@ public enum MinecraftVersion {
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
}
|
||||
if (!disablePackageWarning && !"NBTAPI".equals(VersionChecker.getPlugin())
|
||||
&& MinecraftVersion.class.getPackage().getName().equals("de.tr7zw.nbtapi.utils")) {
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
logger.warning(
|
||||
"The NBT-API inside " + VersionChecker.getPlugin() + " is located at 'de.tr7zw.nbtapi.utils'!");
|
||||
logger.warning(
|
||||
"This package name is reserved for the official NBTAPI plugin, and not intended to be used for shading!");
|
||||
logger.warning("Please change the relocate to something else. For example: com.example.util.nbtapi");
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
if (!disablePackageWarning && !"NBTAPI".equals(VersionChecker.getPlugin())) { // we are not the nbtapi, check
|
||||
// for common shading errors
|
||||
if (!"de.tr7zw.nbtapi.utils".equals(reservedPackage)) {
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
logger.warning(
|
||||
"The NBT-API inside " + VersionChecker.getPlugin() + " is the plugin version, not the API!");
|
||||
logger.warning(
|
||||
"The plugin itself should never be shaded! Remove the `-plugin` from the dependency and fix your shading setup.");
|
||||
logger.warning(
|
||||
"For more info check: https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven#option-2-shading-the-nbt-api-into-your-plugin");
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
return; // don't also print the second error
|
||||
}
|
||||
if (MinecraftVersion.class.getPackage().getName().equals("de.tr7zw.nbtapi.utils")) {
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
logger.warning(
|
||||
"The NBT-API inside " + VersionChecker.getPlugin() + " is located at 'de.tr7zw.nbtapi.utils'!");
|
||||
logger.warning(
|
||||
"This package name is reserved for the official NBTAPI plugin, and not intended to be used for shading!");
|
||||
logger.warning("Please change the relocate to something else. For example: com.example.util.nbtapi");
|
||||
logger.warning(
|
||||
"#########################################- NBTAPI -#########################################");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +323,7 @@ public enum MinecraftVersion {
|
||||
return hasGsonSupport;
|
||||
}
|
||||
try {
|
||||
logger.info("[NBTAPI] Found Gson: " + Class.forName("com.google.gson.Gson"));
|
||||
Class.forName("com.google.gson.Gson");
|
||||
hasGsonSupport = true;
|
||||
} catch (Exception ex) {
|
||||
logger.info("[NBTAPI] Gson not found! This will not allow the usage of some methods!");
|
||||
@@ -187,6 +332,22 @@ public enum MinecraftVersion {
|
||||
return hasGsonSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True, if Fabric is present
|
||||
*/
|
||||
public static boolean isFabricPresent() {
|
||||
if (isFabricPresent != null) {
|
||||
return isFabricPresent;
|
||||
}
|
||||
try {
|
||||
logger.info("[NBTAPI] Found Fabric: " + Class.forName("net.fabricmc.api.ModInitializer"));
|
||||
isFabricPresent = true;
|
||||
} catch (Exception ex) {
|
||||
isFabricPresent = false;
|
||||
}
|
||||
return isFabricPresent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True, if Forge is present
|
||||
*/
|
||||
@@ -204,6 +365,38 @@ public enum MinecraftVersion {
|
||||
}
|
||||
return isForgePresent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True, if NeoForge is present
|
||||
*/
|
||||
public static boolean isNeoForgePresent() {
|
||||
if (isNeoForgePresent != null) {
|
||||
return isNeoForgePresent;
|
||||
}
|
||||
try {
|
||||
logger.info("[NBTAPI] Found NeoForge: " + Class.forName("net.neoforged.neoforge.common.NeoForge"));
|
||||
isNeoForgePresent = true;
|
||||
} catch (Exception ex) {
|
||||
isNeoForgePresent = false;
|
||||
}
|
||||
return isNeoForgePresent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True, if Folia is present
|
||||
*/
|
||||
public static boolean isFoliaPresent() {
|
||||
if (isFoliaPresent != null) {
|
||||
return isFoliaPresent;
|
||||
}
|
||||
try {
|
||||
logger.info("[NBTAPI] Found Folia: " + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"));
|
||||
isFoliaPresent = true;
|
||||
} catch (Exception ex) {
|
||||
isFoliaPresent = false;
|
||||
}
|
||||
return isFoliaPresent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling this function before the NBT-Api is used will disable bStats stats
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.MojangToMapping;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
public class NBTJsonUtil {
|
||||
|
||||
/**
|
||||
* 1.20.3-1.21.4 only. Used to convert items into Json, used in Chat Hover Components.
|
||||
*
|
||||
* @param itemStack
|
||||
* @return
|
||||
* @throws NbtApiException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static JsonElement itemStackToJson(ItemStack itemStack) {
|
||||
try {
|
||||
Codec<Object> itemStackCodec = (Codec<Object>) ClassWrapper.NMS_ITEMSTACK.getClazz()
|
||||
.getField(MojangToMapping.getMapping().get("net.minecraft.world.item.ItemStack#CODEC")).get(null);
|
||||
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, itemStack);
|
||||
DataResult<JsonElement> result = itemStackCodec.encode(stack, JsonOps.INSTANCE,
|
||||
JsonOps.INSTANCE.emptyMap());
|
||||
Optional<JsonElement> opt = (Optional<JsonElement>) result.getClass().getMethod("result").invoke(result);
|
||||
return opt.orElse(null);
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Error trying to get Json of an ItemStack.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class PathUtil {
|
||||
|
||||
private static final Pattern pattern = Pattern.compile("[^\\\\](\\.)");
|
||||
private static final Pattern indexPattern = Pattern.compile(".*\\[(-?[0-9]+)\\]");
|
||||
|
||||
public static List<PathSegment> splitPath(String path) {
|
||||
List<PathSegment> list = new ArrayList<>();
|
||||
Matcher matcher = pattern.matcher(path);
|
||||
int startIndex = 0;
|
||||
while (matcher.find(startIndex)) {
|
||||
list.add(new PathSegment(path.substring(startIndex, matcher.end() - 1).replace("\\.", ".")));
|
||||
startIndex = matcher.end();
|
||||
}
|
||||
list.add(new PathSegment(path.substring(startIndex).replace("\\.", ".")));
|
||||
return list;
|
||||
}
|
||||
|
||||
public static class PathSegment {
|
||||
|
||||
private final String path;
|
||||
private final Integer index;
|
||||
|
||||
private PathSegment(String path) {
|
||||
Matcher matcher = indexPattern.matcher(path);
|
||||
if (matcher.find()) {
|
||||
this.path = path.substring(0, path.indexOf("["));
|
||||
this.index = Integer.parseInt(matcher.group(1));
|
||||
} else {
|
||||
this.path = path;
|
||||
this.index = null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public boolean hasIndex() {
|
||||
return index != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PathSegment [path=" + path + ", index=" + index + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +1,24 @@
|
||||
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;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.MojangToMapping;
|
||||
|
||||
public final class ReflectionUtil {
|
||||
|
||||
private static Field field_modifiers;
|
||||
|
||||
static {
|
||||
|
||||
public static Field getMappedField(Class<?> clazz, String mapping) {
|
||||
String mojmapName = mapping.split("#")[1];
|
||||
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);
|
||||
}
|
||||
return clazz.getField(mojmapName);
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
// not Mojamp, try remapped
|
||||
}
|
||||
if (field_modifiers == null) {
|
||||
throw new NbtApiException("Unable to init the modifiers Field.");
|
||||
try {
|
||||
return clazz.getDeclaredField(MojangToMapping.getMapping().get(mapping));
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Unable to find field " + mapping + " in class " + clazz.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -109,7 +109,20 @@ public class VersionChecker {
|
||||
|
||||
protected static String getPlugin() {
|
||||
ClassLoader classLoader = VersionChecker.class.getClassLoader();
|
||||
InputStream inputStream = classLoader.getResourceAsStream("plugin.yml");
|
||||
InputStream inputStream = classLoader.getResourceAsStream("paper-plugin.yml");
|
||||
if (inputStream != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(inputStream)) {
|
||||
YamlConfiguration pluginYml = YamlConfiguration.loadConfiguration(reader);
|
||||
return pluginYml.getString("name");
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This can happen if the paper-plugin.yml is not formatted correctly
|
||||
MinecraftVersion.getLogger().log(Level.WARNING, "[NBTAPI] Error reading paper-plugin.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
inputStream = classLoader.getResourceAsStream("plugin.yml");
|
||||
|
||||
if (inputStream != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(inputStream)) {
|
||||
@@ -117,9 +130,67 @@ public class VersionChecker {
|
||||
return pluginYml.getString("name");
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This can happen if the plugin.yml is not formatted correctly
|
||||
MinecraftVersion.getLogger().log(Level.WARNING, "[NBTAPI] Error reading plugin.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
return NBTItem.class.getPackage().getName();
|
||||
}
|
||||
|
||||
protected static String getPluginforBStats() {
|
||||
ClassLoader classLoader = VersionChecker.class.getClassLoader();
|
||||
InputStream inputStream = classLoader.getResourceAsStream("paper-plugin.yml");
|
||||
if (inputStream != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(inputStream)) {
|
||||
YamlConfiguration pluginYml = YamlConfiguration.loadConfiguration(reader);
|
||||
return pluginYml.getString("name");
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This can happen if the paper-plugin.yml is not formatted correctly
|
||||
MinecraftVersion.getLogger().log(Level.WARNING, "[NBTAPI] Error reading paper-plugin.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
inputStream = classLoader.getResourceAsStream("plugin.yml");
|
||||
|
||||
if (inputStream != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(inputStream)) {
|
||||
YamlConfiguration pluginYml = YamlConfiguration.loadConfiguration(reader);
|
||||
return pluginYml.getString("name");
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This can happen if the plugin.yml is not formatted correctly
|
||||
MinecraftVersion.getLogger().log(Level.WARNING, "[NBTAPI] Error reading plugin.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
return "UnknownPlugin";
|
||||
}
|
||||
|
||||
protected static String getPluginType() {
|
||||
ClassLoader classLoader = VersionChecker.class.getClassLoader();
|
||||
InputStream inputStream = classLoader.getResourceAsStream("paper-plugin.yml");
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
}
|
||||
return "PaperPlugin";
|
||||
}
|
||||
|
||||
inputStream = classLoader.getResourceAsStream("plugin.yml");
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
}
|
||||
return "SpigotPlugin";
|
||||
}
|
||||
return "UnknownPlugin";
|
||||
}
|
||||
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
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 AvailableSince {
|
||||
|
||||
MinecraftVersion version();
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
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(AvailableSince.class).version()
|
||||
.getVersionId())
|
||||
throw new NbtApiException("The Method '" + method.getName() + "' is only avaliable for the Versions "
|
||||
+ method.getAnnotation(AvailableSince.class).version() + "+, but still got called!");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+49
@@ -4,6 +4,8 @@ import static de.tr7zw.changeme.nbtapi.utils.MinecraftVersion.getLogger;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
|
||||
/**
|
||||
@@ -18,9 +20,11 @@ public enum ClassWrapper {
|
||||
CRAFT_METAITEM(PackageWrapper.CRAFTBUKKIT, "inventory.CraftMetaItem", null, null),
|
||||
CRAFT_ENTITY(PackageWrapper.CRAFTBUKKIT, "entity.CraftEntity", null, null),
|
||||
CRAFT_WORLD(PackageWrapper.CRAFTBUKKIT, "CraftWorld", null, null),
|
||||
CRAFT_SERVER(PackageWrapper.CRAFTBUKKIT, "CraftServer", null, null),
|
||||
CRAFT_PERSISTENTDATACONTAINER(PackageWrapper.CRAFTBUKKIT, "persistence.CraftPersistentDataContainer",
|
||||
MinecraftVersion.MC1_14_R1, null),
|
||||
NMS_NBTBASE(PackageWrapper.NMS, "NBTBase", null, null, "net.minecraft.nbt", "net.minecraft.nbt.Tag"),
|
||||
NMS_TAGTYPE(PackageWrapper.NMS, "NBTTagType", MinecraftVersion.MC1_21_R4, null, "net.minecraft.nbt", "net.minecraft.nbt.TagType"),
|
||||
NMS_NBTTAGSTRING(PackageWrapper.NMS, "NBTTagString", null, null, "net.minecraft.nbt",
|
||||
"net.minecraft.nbt.StringTag"),
|
||||
NMS_NBTTAGINT(PackageWrapper.NMS, "NBTTagInt", null, null, "net.minecraft.nbt", "net.minecraft.nbt.IntTag"),
|
||||
@@ -62,6 +66,38 @@ public enum ClassWrapper {
|
||||
"net.minecraft.nbt.NbtUtils"),
|
||||
NMS_IBLOCKDATA(PackageWrapper.NMS, "IBlockData", MinecraftVersion.MC1_8_R3, null,
|
||||
"net.minecraft.world.level.block.state", "net.minecraft.world.level.block.state.BlockState"),
|
||||
NMS_NBTACCOUNTER(PackageWrapper.NMS, "NBTReadLimiter", MinecraftVersion.MC1_20_R3, null, "net.minecraft.nbt",
|
||||
"net.minecraft.nbt.NbtAccounter"),
|
||||
NMS_CUSTOMDATA(PackageWrapper.NMS, "CustomData", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.world.item.component", "net.minecraft.world.item.component.CustomData"),
|
||||
NMS_DATACOMPONENTTYPE(PackageWrapper.NMS, "DataComponentType", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.core.component", "net.minecraft.core.component.DataComponentType"),
|
||||
NMS_DATACOMPONENTS(PackageWrapper.NMS, "DataComponents", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.core.component", "net.minecraft.core.component.DataComponents"),
|
||||
NMS_DATACOMPONENTHOLDER(PackageWrapper.NMS, "DataComponentHolder", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.core.component", "net.minecraft.core.component.DataComponentHolder"),
|
||||
NMS_PROVIDER(PackageWrapper.NMS, "HolderLookup$a", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.core", "net.minecraft.core.HolderLookup$Provider"),
|
||||
NMS_SERVER(PackageWrapper.NMS, "MinecraftServer", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.server", "net.minecraft.server.MinecraftServer"),
|
||||
NMS_DATAFIXERS(PackageWrapper.NMS, "DataConverterRegistry", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.util.datafix", "net.minecraft.util.datafix.DataFixers"),
|
||||
NMS_REFERENCES(PackageWrapper.NMS, "DataConverterTypes", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.util.datafix.fixes", "net.minecraft.util.datafix.fixes.References"),
|
||||
NMS_NBTOPS(PackageWrapper.NMS, "DynamicOpsNBT", MinecraftVersion.MC1_20_R4, null,
|
||||
"net.minecraft.nbt", "net.minecraft.nbt.NbtOps"),
|
||||
NMS_PROBLEM_REPORTER(PackageWrapper.NMS, "ProblemReporter", MinecraftVersion.MC1_21_R5, null,
|
||||
"net.minecraft.util", "net.minecraft.util.ProblemReporter"),
|
||||
NMS_TAG_VALUE_INPUT(PackageWrapper.NMS, "TagValueInput", MinecraftVersion.MC1_21_R5, null,
|
||||
"net.minecraft.world.level.storage", "net.minecraft.world.level.storage.TagValueInput"),
|
||||
NMS_VALUE_INPUT(PackageWrapper.NMS, "ValueInput", MinecraftVersion.MC1_21_R5, null,
|
||||
"net.minecraft.world.level.storage", "net.minecraft.world.level.storage.ValueInput"),
|
||||
NMS_TAG_VALUE_OUTPUT(PackageWrapper.NMS, "TagValueOutput", MinecraftVersion.MC1_21_R5, null,
|
||||
"net.minecraft.world.level.storage", "net.minecraft.world.level.storage.TagValueOutput"),
|
||||
NMS_VALUE_OUTPUT(PackageWrapper.NMS, "ValueOutput", MinecraftVersion.MC1_21_R5, null,
|
||||
"net.minecraft.world.level.storage", "net.minecraft.world.level.storage.ValueOutput"),
|
||||
NMS_DYNAMICOPS(PackageWrapper.NONE, "DynamicOps", MinecraftVersion.MC1_21_R5, null,
|
||||
"com.mojang.serialization", "com.mojang.serialization.DynamicOps"),
|
||||
GAMEPROFILE(PackageWrapper.NONE, "com.mojang.authlib.GameProfile", MinecraftVersion.MC1_8_R3, null);
|
||||
|
||||
private Class<?> clazz;
|
||||
@@ -83,6 +119,15 @@ public enum ClassWrapper {
|
||||
}
|
||||
enabled = true;
|
||||
try {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1) && mojangName != null) {
|
||||
// check for Mojmapped enviroment
|
||||
try {
|
||||
clazz = Class.forName(mojangName);
|
||||
return;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
// ignored, not mojang mapped
|
||||
}
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1) && mojangMap != null) {
|
||||
clazz = Class.forName(mojangMap + "." + clazzName);
|
||||
} else if (packageId == PackageWrapper.NONE) {
|
||||
@@ -90,7 +135,11 @@ public enum ClassWrapper {
|
||||
} else if (MinecraftVersion.isForgePresent() && MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4
|
||||
&& Forge1710Mappings.getClassMappings().get(this.name()) != null) {
|
||||
clazz = Class.forName(clazzName = Forge1710Mappings.getClassMappings().get(this.name()));
|
||||
} else if (packageId == PackageWrapper.CRAFTBUKKIT) {
|
||||
// this also works for un-remapped Paper 1.20+
|
||||
clazz = Class.forName(Bukkit.getServer().getClass().getPackage().getName() + "." + clazzName);
|
||||
} else {
|
||||
// fallback for old versions pre mojmap and in the nms package
|
||||
String version = MinecraftVersion.getVersion().getPackageName();
|
||||
clazz = Class.forName(packageId.getUri() + "." + version + "." + clazzName);
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTReflectionUtil;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
|
||||
public class CodecHelper {
|
||||
|
||||
public static Object convertItemStackToNbt(Object itemStack) {
|
||||
Object result = null;
|
||||
try {
|
||||
// FIXME caching, this has 0 exception handling
|
||||
result = NBTReflectionUtil.itemstack_codec.encodeStart(NBTReflectionUtil.nbtRegistryOps, itemStack);
|
||||
Objects.requireNonNull(result);
|
||||
return ((Optional<Object>)result.getClass().getMethod("result").invoke(result)).get();
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Failed to convert ItemStack to NBT. " + result + " " + itemStack, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object convertNbtToItemStack(Object nbt) {
|
||||
Object result = null;
|
||||
try {
|
||||
// FIXME caching, this has 0 exception handling
|
||||
result = NBTReflectionUtil.itemstack_codec.parse(NBTReflectionUtil.nbtRegistryOps, nbt);
|
||||
Objects.requireNonNull(result);
|
||||
return ((Optional<Object>)result.getClass().getMethod("result").invoke(result)).get();
|
||||
} catch (Exception e) {
|
||||
throw new NbtApiException("Failed to convert NBT to ItemStack. " + result + " " + nbt, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -56,8 +56,8 @@ public class Forge1710Mappings {
|
||||
methodMap.put("COMPOUND_MERGE", "merge");// Only present on Crucible
|
||||
methodMap.put("COMPOUND_SET", "func_74782_a");
|
||||
methodMap.put("COMPOUND_GET", "func_74781_a");
|
||||
methodMap.put("COMPOUND_GET_LIST", "func_150295_c");
|
||||
methodMap.put("COMPOUND_OWN_TYPE", "func_74732_a");
|
||||
methodMap.put("COMPOUND_GET_LIST_LEGACY", "func_150295_c");
|
||||
methodMap.put("COMPOUND_OWN_TYPE_LEGACY", "func_74732_a");
|
||||
methodMap.put("COMPOUND_GET_FLOAT", "func_74760_g");
|
||||
methodMap.put("COMPOUND_GET_STRING", "func_74779_i");
|
||||
methodMap.put("COMPOUND_GET_INT", "func_74762_e");
|
||||
|
||||
+230
-3
@@ -1,12 +1,15 @@
|
||||
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
|
||||
/**
|
||||
* Temporary solution to hold Mojang to unmapped Spigot mappings.
|
||||
* Note years later: nothing is more permanent than a temporary solution.
|
||||
*
|
||||
* @author tr7zw
|
||||
*
|
||||
@@ -28,10 +31,12 @@ public class MojangToMapping {
|
||||
put("net.minecraft.nbt.CompoundTag#getIntArray(java.lang.String)", "n");
|
||||
put("net.minecraft.nbt.CompoundTag#remove(java.lang.String)", "r");
|
||||
put("net.minecraft.nbt.CompoundTag#get(java.lang.String)", "c");
|
||||
put("net.minecraft.nbt.CompoundTag#put(java.lang.String,net.minecraft.nbt.Tag)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#merge(net.minecraft.nbt.CompoundTag)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#putBoolean(java.lang.String,boolean)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getTagType(java.lang.String)", "d");
|
||||
put("net.minecraft.nbt.CompoundTag#putLong(java.lang.String,long)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#putLongArray(java.lang.String,long[])", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getLongArray(java.lang.String)", "o");
|
||||
put("net.minecraft.nbt.CompoundTag#getString(java.lang.String)", "l");
|
||||
put("net.minecraft.nbt.CompoundTag#getInt(java.lang.String)", "h");
|
||||
put("net.minecraft.nbt.CompoundTag#putString(java.lang.String,java.lang.String)", "a");
|
||||
@@ -118,11 +123,231 @@ public class MojangToMapping {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_20R2 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_20R1);
|
||||
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bu");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_20R3 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_20R2);
|
||||
|
||||
put("net.minecraft.nbt.NbtIo#readCompressed(java.io.InputStream,net.minecraft.nbt.NbtAccounter)", "a");
|
||||
put("net.minecraft.nbt.NbtAccounter#unlimitedHeap()", "a");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bw");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#saveWithId()", "p");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "r");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "a");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_20R4 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_20R3);
|
||||
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bC");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "n");
|
||||
put("net.minecraft.core.component.DataComponents#CUSTOM_DATA", "b");
|
||||
put("net.minecraft.core.component.DataComponentHolder#get(net.minecraft.core.component.DataComponentType)", "a");
|
||||
put("net.minecraft.world.item.component.CustomData#copyTag()", "c");
|
||||
put("net.minecraft.world.item.ItemStack#set(net.minecraft.core.component.DataComponentType,java.lang.Object)", "b");
|
||||
put("net.minecraft.world.item.ItemStack#save(net.minecraft.core.HolderLookup$Provider)", "a");
|
||||
put("net.minecraft.server.MinecraftServer#registryAccess()", "bc");
|
||||
put("net.minecraft.world.item.ItemStack#parseOptional(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.CompoundTag)", "a");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#saveWithId(net.minecraft.core.HolderLookup$Provider)", "c");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#loadWithComponents(net.minecraft.nbt.CompoundTag,net.minecraft.core.HolderLookup$Provider)", "c");
|
||||
put("net.minecraft.util.datafix.DataFixers#getDataFixer()", "a");
|
||||
put("net.minecraft.util.datafix.fixes.References#ITEM_STACK", "t");
|
||||
put("net.minecraft.nbt.NbtOps#INSTANCE", "a");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "b");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R1 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_20R4);
|
||||
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bD");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R2 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R1);
|
||||
|
||||
put("net.minecraft.server.MinecraftServer#registryAccess()", "ba");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bK");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "m");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "a");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R3 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R2);
|
||||
|
||||
put("net.minecraft.world.item.component.CustomData#copyTag()", "d");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R4 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R3);
|
||||
|
||||
put("net.minecraft.nbt.CompoundTag#getShort(java.lang.String)", "d");
|
||||
put("net.minecraft.nbt.CompoundTag#getString(java.lang.String)", "i");
|
||||
put("net.minecraft.nbt.CompoundTag#contains(java.lang.String)", "b");
|
||||
put("net.minecraft.nbt.CompoundTag#getDouble(java.lang.String)", "h");
|
||||
put("net.minecraft.nbt.CompoundTag#getByteArray(java.lang.String)", "j");
|
||||
put("net.minecraft.nbt.CompoundTag#getFloat(java.lang.String)", "g");
|
||||
put("net.minecraft.nbt.CompoundTag#get(java.lang.String)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getLong(java.lang.String)", "f");
|
||||
put("net.minecraft.nbt.CompoundTag#getLongArray(java.lang.String)", "l");
|
||||
put("net.minecraft.nbt.CompoundTag#getInt(java.lang.String)", "e");
|
||||
put("net.minecraft.nbt.CompoundTag#getIntArray(java.lang.String)", "k");
|
||||
put("net.minecraft.nbt.CompoundTag#getCompound(java.lang.String)", "m");
|
||||
put("net.minecraft.nbt.CompoundTag#getByte(java.lang.String)", "c");
|
||||
put("net.minecraft.nbt.ListTag#getString(int)", "m");
|
||||
put("net.minecraft.world.entity.Entity#saveWithoutId(net.minecraft.nbt.CompoundTag)", "h");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bI");
|
||||
put("net.minecraft.world.entity.Entity#load(net.minecraft.nbt.CompoundTag)", "i");
|
||||
put("net.minecraft.nbt.Tag#getType()", "c");
|
||||
put("net.minecraft.nbt.TagType#getName()", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getList(java.lang.String)", "o");
|
||||
put("net.minecraft.world.item.ItemStack#parse(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.Tag)", "a");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "b");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R5 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R3);
|
||||
put("net.minecraft.core.HolderLookup$Provider#createSerializationContext(com.mojang.serialization.DynamicOps)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getByteArray(java.lang.String)", "j");
|
||||
put("net.minecraft.nbt.CompoundTag#getDouble(java.lang.String)", "h");
|
||||
put("net.minecraft.nbt.CompoundTag#keySet()", "e");
|
||||
put("net.minecraft.nbt.CompoundTag#getLong(java.lang.String)", "f");
|
||||
put("net.minecraft.nbt.CompoundTag#getList(java.lang.String)", "o");
|
||||
put("net.minecraft.nbt.CompoundTag#getInt(java.lang.String)", "e");
|
||||
put("net.minecraft.nbt.CompoundTag#getCompound(java.lang.String)", "m");
|
||||
put("net.minecraft.nbt.CompoundTag#getByte(java.lang.String)", "c");
|
||||
put("net.minecraft.nbt.CompoundTag#getShort(java.lang.String)", "d");
|
||||
put("net.minecraft.nbt.CompoundTag#getIntArray(java.lang.String)", "k");
|
||||
put("net.minecraft.nbt.CompoundTag#get(java.lang.String)", "a");
|
||||
put("net.minecraft.nbt.CompoundTag#getString(java.lang.String)", "i");
|
||||
put("net.minecraft.nbt.CompoundTag#getFloat(java.lang.String)", "g");
|
||||
put("net.minecraft.nbt.CompoundTag#getLongArray(java.lang.String)", "l");
|
||||
put("net.minecraft.nbt.CompoundTag#contains(java.lang.String)", "b");
|
||||
put("net.minecraft.nbt.ListTag#getString(int)", "m");
|
||||
put("net.minecraft.nbt.Tag#getType()", "c");
|
||||
put("net.minecraft.nbt.TagParser#parseCompoundFully(java.lang.String)", "a");
|
||||
put("net.minecraft.nbt.TagType#getName()", "a");
|
||||
put("net.minecraft.world.entity.Entity#load(net.minecraft.world.level.storage.ValueInput)", "e");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bN");
|
||||
put("net.minecraft.world.entity.Entity#saveWithoutId(net.minecraft.world.level.storage.ValueOutput)", "d");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#saveWithId(net.minecraft.world.level.storage.ValueOutput)", "d");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#loadWithComponents(net.minecraft.world.level.storage.ValueInput)", "b");
|
||||
put("net.minecraft.world.level.storage.TagValueInput#create(net.minecraft.util.ProblemReporter,net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.CompoundTag)", "a");
|
||||
put("net.minecraft.world.level.storage.TagValueOutput#createWithContext(net.minecraft.util.ProblemReporter,net.minecraft.core.HolderLookup$Provider)", "a");
|
||||
put("net.minecraft.world.level.storage.TagValueOutput#buildResult()", "b");
|
||||
put("net.minecraft.world.item.ItemStack#CODEC", "b");
|
||||
put("net.minecraft.util.ProblemReporter#DISCARDING", "a");
|
||||
put("net.minecraft.util.datafix.fixes.References#ITEM_STACK", "u");
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R6 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R5);
|
||||
|
||||
put("net.minecraft.server.MinecraftServer#registryAccess()", "bg");
|
||||
put("net.minecraft.world.entity.Entity#load(net.minecraft.world.level.storage.ValueInput)", "d");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "bW");
|
||||
put("net.minecraft.world.item.component.CustomData#copyTag()", "b");
|
||||
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "o");
|
||||
put("net.minecraft.util.datafix.fixes.References#ITEM_STACK", "v");
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static Map<String, String> MC1_21R7 = new HashMap<String, String>() {
|
||||
|
||||
{
|
||||
putAll(MC1_21R6);
|
||||
|
||||
put("net.minecraft.nbt.NbtAccounter#unlimitedHeap()", "c");
|
||||
put("net.minecraft.server.MinecraftServer#registryAccess()", "bc");
|
||||
put("net.minecraft.world.entity.Entity#getEncodeId()", "ca");
|
||||
put("net.minecraft.util.datafix.fixes.References#ITEM_STACK", "x");
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
public static Map<String, String> getMapping() {
|
||||
// No mappings after 26.1
|
||||
if(MinecraftVersion.getVersion() != MinecraftVersion.UNKNOWN && MinecraftVersion.getVersion().isAtLeastVersion(MinecraftVersion.MC26_1)) {
|
||||
return Collections.EMPTY_MAP;
|
||||
}
|
||||
switch (MinecraftVersion.getVersion()) {
|
||||
case MC1_21_R7:
|
||||
return MC1_21R7;
|
||||
case MC1_21_R6:
|
||||
return MC1_21R6;
|
||||
case MC1_21_R5:
|
||||
return MC1_21R5;
|
||||
case MC1_21_R4:
|
||||
return MC1_21R4;
|
||||
case MC1_21_R3:
|
||||
return MC1_21R3;
|
||||
case MC1_21_R2:
|
||||
return MC1_21R2;
|
||||
case MC1_21_R1:
|
||||
return MC1_21R1;
|
||||
case MC1_20_R4:
|
||||
return MC1_20R4;
|
||||
case MC1_20_R3:
|
||||
return MC1_20R3;
|
||||
case MC1_20_R2:
|
||||
return MC1_20R2;
|
||||
case MC1_20_R1:
|
||||
return MC1_20R1;
|
||||
case MC1_19_R3:
|
||||
return MC1_19R2;
|
||||
case MC1_19_R2:
|
||||
return MC1_19R2;
|
||||
case MC1_19_R1:
|
||||
@@ -131,9 +356,11 @@ public class MojangToMapping {
|
||||
return MC1_18R2;
|
||||
case MC1_18_R1:
|
||||
return MC1_18R1;
|
||||
case UNKNOWN:
|
||||
return MC1_21R7; // assume it's a future version, so try the latest known mappings
|
||||
default:
|
||||
return MC1_19R2;// throw new NbtApiException("This version of the NBTAPI is not compatible with
|
||||
// this server version!");
|
||||
// this should never happen, unless a version is forgotten here(like 1.19R3 which uses the 1.19R2 mappings)
|
||||
throw new NbtApiException("No fitting mapping found for version " + MinecraftVersion.getVersion() + ". This is a bug!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -17,8 +17,9 @@ import static de.tr7zw.changeme.nbtapi.utils.MinecraftVersion.getLogger;
|
||||
@SuppressWarnings("javadoc")
|
||||
public enum ObjectCreator {
|
||||
NMS_NBTTAGCOMPOUND(null, null, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
|
||||
NMS_CUSTOMDATA(MinecraftVersion.MC1_20_R4, null, ClassWrapper.NMS_CUSTOMDATA.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
|
||||
NMS_BLOCKPOSITION(null, null, ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class),
|
||||
NMS_COMPOUNDFROMITEM(MinecraftVersion.MC1_11_R1, null, ClassWrapper.NMS_ITEMSTACK.getClazz(),
|
||||
NMS_COMPOUNDFROMITEM(MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_20_R3, ClassWrapper.NMS_ITEMSTACK.getClazz(),
|
||||
ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),;
|
||||
|
||||
private Constructor<?> construct;
|
||||
|
||||
+106
-33
@@ -5,6 +5,7 @@ import java.io.OutputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@@ -36,6 +37,9 @@ public enum ReflectionMethod {
|
||||
COMPOUND_SET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int[].class },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setIntArray"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "putIntArray(java.lang.String,int[])")),
|
||||
COMPOUND_SET_LONGARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, long[].class },
|
||||
MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "putLongArray(java.lang.String,long[])")),
|
||||
COMPOUND_SET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, long.class },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setLong"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "putLong(java.lang.String,long)")),
|
||||
@@ -52,23 +56,29 @@ public enum ReflectionMethod {
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "putBoolean(java.lang.String,boolean)")),
|
||||
COMPOUND_SET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, UUID.class },
|
||||
MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a"),
|
||||
MinecraftVersion.MC1_16_R1, MinecraftVersion.MC1_21_R3, new Since(MinecraftVersion.MC1_16_R1, "a"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "putUUID(java.lang.String,java.util.UUID)")),
|
||||
COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "put(java.lang.String,net.minecraft.nbt.Tag)")),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "merge(net.minecraft.nbt.CompoundTag)")),
|
||||
COMPOUND_SET(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, ClassWrapper.NMS_NBTBASE.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "set"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "put(java.lang.String,net.minecraft.nbt.Tag)")),
|
||||
COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "get"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "get(java.lang.String)")),
|
||||
COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int.class },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList"),
|
||||
COMPOUND_GET_LIST_LEGACY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int.class },
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_21_R3, new Since(MinecraftVersion.MC1_7_R4, "getList"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getList(java.lang.String,int)")),
|
||||
COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_21_R4,
|
||||
new Since(MinecraftVersion.MC1_21_R4, "getList(java.lang.String)")),
|
||||
// Only needed for 1.7.10 getType
|
||||
COMPOUND_OWN_TYPE(ClassWrapper.NMS_NBTBASE, new Class[] {}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4,
|
||||
COMPOUND_OWN_TYPE_LEGACY(ClassWrapper.NMS_NBTBASE, new Class[] {}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getTypeId")),
|
||||
TAGTYPE_OWN_TYPE(ClassWrapper.NMS_NBTBASE, new Class[] {}, MinecraftVersion.MC1_21_R4,
|
||||
new Since(MinecraftVersion.MC1_21_R4, "getType()")),
|
||||
TAGTYPE_GET_NAME(ClassWrapper.NMS_TAGTYPE, new Class[] {}, MinecraftVersion.MC1_21_R4,
|
||||
new Since(MinecraftVersion.MC1_21_R4, "getName()")),
|
||||
|
||||
COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getFloat"),
|
||||
@@ -85,6 +95,9 @@ public enum ReflectionMethod {
|
||||
COMPOUND_GET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getIntArray"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getIntArray(java.lang.String)")),
|
||||
COMPOUND_GET_LONGARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_16_R1,
|
||||
new Since(MinecraftVersion.MC1_16_R1, "getLongArray"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getLongArray(java.lang.String)")),
|
||||
COMPOUND_GET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getLong"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getLong(java.lang.String)")),
|
||||
@@ -100,17 +113,18 @@ public enum ReflectionMethod {
|
||||
COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getBoolean"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getBoolean(java.lang.String)")),
|
||||
COMPOUND_GET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_16_R1,
|
||||
COMPOUND_GET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_16_R1, MinecraftVersion.MC1_21_R3,
|
||||
new Since(MinecraftVersion.MC1_16_R1, "a"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getUUID(java.lang.String)")),
|
||||
COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getCompound"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getCompound(java.lang.String)")),
|
||||
|
||||
NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK, new Class[] {}, MinecraftVersion.MC1_7_R4,
|
||||
|
||||
|
||||
NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK, new Class[] {}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R3,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getTag"), new Since(MinecraftVersion.MC1_18_R1, "getTag()")),
|
||||
NMSITEM_SAVE(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "save"),
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R3, new Since(MinecraftVersion.MC1_7_R4, "save"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "save(net.minecraft.nbt.CompoundTag)")),
|
||||
NMSITEM_CREATESTACK(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_10_R1, new Since(MinecraftVersion.MC1_7_R4, "createStack")),
|
||||
@@ -121,17 +135,17 @@ public enum ReflectionMethod {
|
||||
COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "hasKey"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "contains(java.lang.String)")),
|
||||
COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_8_R3,
|
||||
COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_21_R4,
|
||||
new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"),
|
||||
new Since(MinecraftVersion.MC1_15_R1, "e"), new Since(MinecraftVersion.MC1_16_R1, "d"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getTagType(java.lang.String)")),
|
||||
COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] {}, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getAllKeys()")),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getAllKeys()"), new Since(MinecraftVersion.MC1_21_R5, "keySet()")),
|
||||
// FIXME ?!?
|
||||
LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] {}, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getAllKeys()")),
|
||||
// LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] {}, MinecraftVersion.MC1_7_R4,
|
||||
// new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys"),
|
||||
// new Since(MinecraftVersion.MC1_18_R1, "getAllKeys()")),
|
||||
LIST_REMOVE_KEY(ClassWrapper.NMS_NBTTAGLIST, new Class[] { int.class }, MinecraftVersion.MC1_8_R3,
|
||||
new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_9_R1, "remove"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "remove(int)")),
|
||||
@@ -156,7 +170,7 @@ public enum ReflectionMethod {
|
||||
new Since(MinecraftVersion.MC1_13_R1, "get"), new Since(MinecraftVersion.MC1_18_R1, "get(int)")),
|
||||
|
||||
ITEMSTACK_SET_TAG(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTag"),
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R3, new Since(MinecraftVersion.MC1_7_R4, "setTag"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "setTag(net.minecraft.nbt.CompoundTag)")),
|
||||
ITEMSTACK_NMSCOPY(ClassWrapper.CRAFT_ITEMSTACK, new Class[] { ItemStack.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "asNMSCopy")),
|
||||
@@ -168,10 +182,6 @@ public enum ReflectionMethod {
|
||||
NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER, new Class[] { ClassWrapper.NMS_BLOCKPOSITION.getClazz() },
|
||||
MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "getTileEntity"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "getBlockEntity(net.minecraft.core.BlockPos)")),
|
||||
NMS_WORLD_SET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER,
|
||||
new Class[] { ClassWrapper.NMS_BLOCKPOSITION.getClazz(), ClassWrapper.NMS_TILEENTITY.getClazz() },
|
||||
MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_16_R3,
|
||||
new Since(MinecraftVersion.MC1_8_R3, "setTileEntity")),
|
||||
NMS_WORLD_REMOVE_TILEENTITY(ClassWrapper.NMS_WORLDSERVER, new Class[] { ClassWrapper.NMS_BLOCKPOSITION.getClazz() },
|
||||
MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_8_R3, "t"),
|
||||
new Since(MinecraftVersion.MC1_9_R1, "s"), new Since(MinecraftVersion.MC1_13_R1, "n"),
|
||||
@@ -180,11 +190,9 @@ public enum ReflectionMethod {
|
||||
NMS_WORLD_GET_TILEENTITY_1_7_10(ClassWrapper.NMS_WORLDSERVER, new Class[] { int.class, int.class, int.class },
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")),
|
||||
// FIXME: No Spigot mapping!
|
||||
TILEENTITY_LOAD_LEGACY191(ClassWrapper.NMS_TILEENTITY,
|
||||
new Class[] { ClassWrapper.NMS_MINECRAFTSERVER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_9_R1, MinecraftVersion.MC1_9_R1, new Since(MinecraftVersion.MC1_9_R1, "a")),
|
||||
// FIXME: No Spigot mapping!
|
||||
TILEENTITY_LOAD_LEGACY183(ClassWrapper.NMS_TILEENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_9_R2, new Since(MinecraftVersion.MC1_8_R3, "c"),
|
||||
new Since(MinecraftVersion.MC1_9_R1, "a"), new Since(MinecraftVersion.MC1_9_R2, "c")),
|
||||
@@ -201,7 +209,7 @@ public enum ReflectionMethod {
|
||||
TILEENTITY_GET_NBT(ClassWrapper.NMS_TILEENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_7_R4, "b"),
|
||||
new Since(MinecraftVersion.MC1_9_R1, "save")),
|
||||
TILEENTITY_GET_NBT_1181(ClassWrapper.NMS_TILEENTITY, new Class[] {}, MinecraftVersion.MC1_18_R1,
|
||||
TILEENTITY_GET_NBT_1181(ClassWrapper.NMS_TILEENTITY, new Class[] {}, MinecraftVersion.MC1_18_R1, MinecraftVersion.MC1_20_R3,
|
||||
new Since(MinecraftVersion.MC1_18_R1, "saveWithId()")),
|
||||
TILEENTITY_SET_NBT_LEGACY1151(ClassWrapper.NMS_TILEENTITY,
|
||||
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() }, MinecraftVersion.MC1_7_R4,
|
||||
@@ -211,7 +219,7 @@ public enum ReflectionMethod {
|
||||
new Class[] { ClassWrapper.NMS_IBLOCKDATA.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_16_R1, MinecraftVersion.MC1_16_R3, new Since(MinecraftVersion.MC1_16_R1, "load")),
|
||||
TILEENTITY_SET_NBT(ClassWrapper.NMS_TILEENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_16_R1, "load"),
|
||||
MinecraftVersion.MC1_17_R1, MinecraftVersion.MC1_20_R4, new Since(MinecraftVersion.MC1_16_R1, "load"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "load(net.minecraft.nbt.CompoundTag)")),
|
||||
TILEENTITY_GET_BLOCKDATA(ClassWrapper.NMS_TILEENTITY, new Class[] {}, MinecraftVersion.MC1_16_R1,
|
||||
new Since(MinecraftVersion.MC1_16_R1, "getBlock"),
|
||||
@@ -220,19 +228,30 @@ public enum ReflectionMethod {
|
||||
CRAFT_ENTITY_GET_HANDLE(ClassWrapper.CRAFT_ENTITY, new Class[] {}, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
|
||||
NMS_ENTITY_SET_NBT(ClassWrapper.NMS_ENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "f"),
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_21_R4, new Since(MinecraftVersion.MC1_7_R4, "f"),
|
||||
new Since(MinecraftVersion.MC1_16_R1, "load"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "load(net.minecraft.nbt.CompoundTag)")),
|
||||
NMS_ENTITY_GET_NBT(ClassWrapper.NMS_ENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "e"),
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_21_R4, new Since(MinecraftVersion.MC1_7_R4, "e"),
|
||||
new Since(MinecraftVersion.MC1_12_R1, "save"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "saveWithoutId(net.minecraft.nbt.CompoundTag)")),
|
||||
NMS_ENTITY_GETSAVEID(ClassWrapper.NMS_ENTITY, new Class[] {}, MinecraftVersion.MC1_14_R1,
|
||||
new Since(MinecraftVersion.MC1_14_R1, "getSaveID"), new Since(MinecraftVersion.MC1_18_R1, "getEncodeId()")),
|
||||
|
||||
NBTFILE_READ(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS, new Class[] { InputStream.class },
|
||||
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a"),
|
||||
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R2, new Since(MinecraftVersion.MC1_7_R4, "a"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "readCompressed(java.io.InputStream)")),
|
||||
|
||||
NBTFILE_READV2(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS,
|
||||
new Class[] { InputStream.class, ClassWrapper.NMS_NBTACCOUNTER.getClazz() }, MinecraftVersion.MC1_20_R3,
|
||||
new Since(MinecraftVersion.MC1_20_R3,
|
||||
"readCompressed(java.io.InputStream,net.minecraft.nbt.NbtAccounter)")),
|
||||
|
||||
NBTACCOUNTER_CREATE_UNLIMITED(ClassWrapper.NMS_NBTACCOUNTER,
|
||||
new Class[] {}, MinecraftVersion.MC1_20_R3,
|
||||
new Since(MinecraftVersion.MC1_20_R3,
|
||||
"unlimitedHeap()")),
|
||||
|
||||
NBTFILE_WRITE(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS,
|
||||
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), OutputStream.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "a"),
|
||||
@@ -241,15 +260,13 @@ public enum ReflectionMethod {
|
||||
|
||||
PARSE_NBT(ClassWrapper.NMS_MOJANGSONPARSER, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "parse"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "parseTag(java.lang.String)")),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "parseTag(java.lang.String)"), new Since(MinecraftVersion.MC1_21_R5, "parseCompoundFully(java.lang.String)")),
|
||||
REGISTRY_KEYSET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] {}, MinecraftVersion.MC1_11_R1,
|
||||
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")),
|
||||
REGISTRY_GET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] { Object.class }, MinecraftVersion.MC1_11_R1,
|
||||
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")),
|
||||
// FIXME: No Spigot mapping!
|
||||
REGISTRY_SET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] { Object.class, Object.class },
|
||||
MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")),
|
||||
// FIXME: No Spigot mapping!
|
||||
REGISTRY_GET_INVERSE(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] { Object.class }, MinecraftVersion.MC1_11_R1,
|
||||
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")),
|
||||
REGISTRYMATERIALS_KEYSET(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] {}, MinecraftVersion.MC1_13_R1,
|
||||
@@ -260,12 +277,12 @@ public enum ReflectionMethod {
|
||||
MinecraftVersion.MC1_13_R2, MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_13_R2, "getKey")),
|
||||
|
||||
GAMEPROFILE_DESERIALIZE(ClassWrapper.NMS_GAMEPROFILESERIALIZER,
|
||||
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() }, MinecraftVersion.MC1_7_R4,
|
||||
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() }, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_20_R3,
|
||||
new Since(MinecraftVersion.MC1_7_R4, "deserialize"),
|
||||
new Since(MinecraftVersion.MC1_18_R1, "readGameProfile(net.minecraft.nbt.CompoundTag)")),
|
||||
GAMEPROFILE_SERIALIZE(ClassWrapper.NMS_GAMEPROFILESERIALIZER,
|
||||
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), ClassWrapper.GAMEPROFILE.getClazz() },
|
||||
MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "serialize"),
|
||||
MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_20_R3, new Since(MinecraftVersion.MC1_8_R3, "serialize"),
|
||||
new Since(MinecraftVersion.MC1_18_R1,
|
||||
"writeGameProfile(net.minecraft.nbt.CompoundTag,com.mojang.authlib.GameProfile)")),
|
||||
|
||||
@@ -275,7 +292,51 @@ public enum ReflectionMethod {
|
||||
MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "getRaw")),
|
||||
CRAFT_PERSISTENT_DATA_CONTAINER_PUT_ALL(ClassWrapper.CRAFT_PERSISTENTDATACONTAINER,
|
||||
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() }, MinecraftVersion.MC1_14_R1,
|
||||
new Since(MinecraftVersion.MC1_14_R1, "putAll")),;
|
||||
new Since(MinecraftVersion.MC1_14_R1, "putAll")),
|
||||
// 1.20.5+ Stuff
|
||||
NMSDATACOMPONENTHOLDER_GET(ClassWrapper.NMS_DATACOMPONENTHOLDER, new Class[] {ClassWrapper.NMS_DATACOMPONENTTYPE.getClazz()}, MinecraftVersion.MC1_20_R4,
|
||||
new Since(MinecraftVersion.MC1_20_R4, "get(net.minecraft.core.component.DataComponentType)")),
|
||||
NMSCUSTOMDATA_GETCOPY(ClassWrapper.NMS_CUSTOMDATA, new Class[] {}, MinecraftVersion.MC1_20_R4,
|
||||
new Since(MinecraftVersion.MC1_20_R4, "copyTag()")),
|
||||
NMSITEM_SET(ClassWrapper.NMS_ITEMSTACK, new Class[] {ClassWrapper.NMS_DATACOMPONENTTYPE.getClazz(), Object.class}, MinecraftVersion.MC1_20_R4,
|
||||
new Since(MinecraftVersion.MC1_20_R4, "set(net.minecraft.core.component.DataComponentType,java.lang.Object)")),
|
||||
NMSITEM_SAVE_MODERN(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_PROVIDER.getClazz() },
|
||||
MinecraftVersion.MC1_20_R4, MinecraftVersion.MC1_21_R4, new Since(MinecraftVersion.MC1_20_R4, "save(net.minecraft.core.HolderLookup$Provider)")),
|
||||
NMSITEM_LOAD(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_PROVIDER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
|
||||
MinecraftVersion.MC1_20_R4, MinecraftVersion.MC1_21_R3, new Since(MinecraftVersion.MC1_20_R4, "parseOptional(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.CompoundTag)")),
|
||||
NMSITEM_LOAD_MODERN(ClassWrapper.NMS_ITEMSTACK, new Class[] { ClassWrapper.NMS_PROVIDER.getClazz(), ClassWrapper.NMS_NBTBASE.getClazz() },
|
||||
MinecraftVersion.MC1_21_R4, MinecraftVersion.MC1_21_R4, new Since(MinecraftVersion.MC1_20_R4, "parse(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.Tag)")),
|
||||
NMSSERVER_GETREGISTRYACCESS(ClassWrapper.NMS_SERVER, new Class[] {},
|
||||
MinecraftVersion.MC1_20_R4, new Since(MinecraftVersion.MC1_20_R4, "registryAccess()")),
|
||||
NMSSERVER_GETSERVER(ClassWrapper.CRAFT_SERVER, new Class[] {},
|
||||
MinecraftVersion.MC1_20_R4, new Since(MinecraftVersion.MC1_20_R4, "getServer()")),
|
||||
TILEENTITY_GET_NBT_1205(ClassWrapper.NMS_TILEENTITY, new Class[] {ClassWrapper.NMS_PROVIDER.getClazz()}, MinecraftVersion.MC1_20_R4, MinecraftVersion.MC1_21_R4,
|
||||
new Since(MinecraftVersion.MC1_20_R4, "saveWithId(net.minecraft.core.HolderLookup$Provider)")),
|
||||
TILEENTITY_SET_NBT_1205(ClassWrapper.NMS_TILEENTITY, new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), ClassWrapper.NMS_PROVIDER.getClazz() },
|
||||
MinecraftVersion.MC1_20_R4, MinecraftVersion.MC1_21_R4, new Since(MinecraftVersion.MC1_20_R4, "loadWithComponents(net.minecraft.nbt.CompoundTag,net.minecraft.core.HolderLookup$Provider)")),
|
||||
GET_DATAFIXER(ClassWrapper.NMS_DATAFIXERS, new Class[] {}, MinecraftVersion.MC1_20_R4,
|
||||
new Since(MinecraftVersion.MC1_20_R4, "getDataFixer()")),
|
||||
// 1.21.6 Stuff
|
||||
GET_SERIALIZATION_CONTEXT(ClassWrapper.NMS_PROVIDER, new Class[] {ClassWrapper.NMS_DYNAMICOPS.getClazz()}, MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "createSerializationContext(com.mojang.serialization.DynamicOps)")),
|
||||
NMS_GET_TAG_VALUE_INPUT(ClassWrapper.NMS_TAG_VALUE_INPUT, new Class[] {ClassWrapper.NMS_PROBLEM_REPORTER.getClazz(), ClassWrapper.NMS_PROVIDER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "create(net.minecraft.util.ProblemReporter,net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.CompoundTag)")),
|
||||
NMS_GET_TAG_VALUE_OUTPUT(ClassWrapper.NMS_TAG_VALUE_OUTPUT, new Class[] {ClassWrapper.NMS_PROBLEM_REPORTER.getClazz(), ClassWrapper.NMS_PROVIDER.getClazz()}, MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "createWithContext(net.minecraft.util.ProblemReporter,net.minecraft.core.HolderLookup$Provider)")),
|
||||
NMS_TAG_VALUE_OUTPUT_TO_TAG_COMPOUND(ClassWrapper.NMS_TAG_VALUE_OUTPUT, new Class[] {}, MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "buildResult()")),
|
||||
NMS_ENTITY_SET_NBT_1216(ClassWrapper.NMS_ENTITY, new Class[] { ClassWrapper.NMS_VALUE_INPUT.getClazz() }, MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "load(net.minecraft.world.level.storage.ValueInput)")
|
||||
),
|
||||
NMS_ENTITY_GET_NBT_1216(ClassWrapper.NMS_ENTITY, new Class[] { ClassWrapper.NMS_VALUE_OUTPUT.getClazz() }, MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "saveWithoutId(net.minecraft.world.level.storage.ValueOutput)")),
|
||||
|
||||
TILEENTITY_GET_NBT_1216(ClassWrapper.NMS_TILEENTITY, new Class[] {ClassWrapper.NMS_VALUE_OUTPUT.getClazz()}, MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "saveWithId(net.minecraft.world.level.storage.ValueOutput)")),
|
||||
TILEENTITY_SET_NBT_1216(ClassWrapper.NMS_TILEENTITY, new Class[] {ClassWrapper.NMS_VALUE_INPUT.getClazz() },
|
||||
MinecraftVersion.MC1_21_R5,
|
||||
new Since(MinecraftVersion.MC1_21_R5, "loadWithComponents(net.minecraft.world.level.storage.ValueInput)")),
|
||||
;
|
||||
|
||||
private MinecraftVersion removedAfter;
|
||||
private Since targetVersion;
|
||||
@@ -310,6 +371,17 @@ public enum ReflectionMethod {
|
||||
if (MinecraftVersion.isForgePresent() && MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) {
|
||||
targetMethodName = Forge1710Mappings.getMethodMapping().getOrDefault(this.name(), targetMethodName);
|
||||
} else if (targetVersion.version.isMojangMapping()) {
|
||||
try {
|
||||
// check for mojang mapped method
|
||||
String name = targetVersion.name.split("\\(")[0];
|
||||
method = targetClass.getClazz().getMethod(name, args);
|
||||
method.setAccessible(true);
|
||||
loaded = true;
|
||||
methodName = name;
|
||||
return;
|
||||
} catch (NoSuchMethodException ignore) {
|
||||
// not mojang mapped
|
||||
}
|
||||
targetMethodName = MojangToMapping.getMapping().getOrDefault(
|
||||
targetClass.getMojangName() + "#" + targetVersion.name, "Unmapped" + targetVersion.name);
|
||||
}
|
||||
@@ -355,7 +427,8 @@ public enum ReflectionMethod {
|
||||
return method.invoke(target, args);
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded
|
||||
+ ", Enum: " + this + ", Passed Class: " + (target == null ? "null" : target.getClass()), ex);
|
||||
+ ", Enum: " + this + ", Passed Class: " + (target == null ? "null" : target.getClass()) + " Args: " + (args == null ? "null" : Arrays.toString(args)) +
|
||||
" Classes: " + (args == null ? "null" : Arrays.asList(args).stream().map(a -> a == null ? "NULL" : a.getClass().getName()).collect(Collectors.toList())), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.tr7zw.changeme.nbtapi.wrapper;
|
||||
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public enum Casing {
|
||||
camelCase(s -> {
|
||||
if (s.length() < 2) {
|
||||
return s.toLowerCase();
|
||||
}
|
||||
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
|
||||
}), snake_case(s -> {
|
||||
StringBuilder result = new StringBuilder();
|
||||
// Convert the first letter to lowercase
|
||||
result.append(Character.toLowerCase(s.charAt(0)));
|
||||
// Iterate through the rest of the string
|
||||
for (int i = 1; i < s.length(); i++) {
|
||||
char currentChar = s.charAt(i);
|
||||
// Convert uppercase letters to lowercase and add underscore
|
||||
if (Character.isUpperCase(currentChar)) {
|
||||
result.append('_').append(Character.toLowerCase(currentChar));
|
||||
} else {
|
||||
result.append(currentChar);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}), PascalCase(s -> {
|
||||
if (s.length() < 2) {
|
||||
return s.toUpperCase();
|
||||
}
|
||||
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
|
||||
}), lowercase(String::toLowerCase), UPPERCASE(String::toUpperCase);
|
||||
|
||||
private UnaryOperator<String> convert;
|
||||
|
||||
Casing(UnaryOperator<String> function) {
|
||||
this.convert = function;
|
||||
}
|
||||
|
||||
public String convertString(String str) {
|
||||
return convert.apply(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package de.tr7zw.changeme.nbtapi.wrapper;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
|
||||
class DefaultMethodInvoker {
|
||||
|
||||
private static Method invokeDefaultMethod;
|
||||
|
||||
static {
|
||||
try {
|
||||
invokeDefaultMethod = InvocationHandler.class.getDeclaredMethod("invokeDefault",
|
||||
new Class[] { Object.class, Method.class, Object[].class });
|
||||
invokeDefaultMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
// we are in java 8, use the fallback
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using reflections to access reflections, since some are still on java 8.
|
||||
*
|
||||
* @param target
|
||||
* @param method
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
public static Object invokeDefault(Class<?> srcInt, Object target, Method method, Object[] args) {
|
||||
if (invokeDefaultMethod != null) { // java 9+
|
||||
try {
|
||||
return invokeDefaultMethod.invoke(null, target, method, args);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new NbtApiException("Error while trying to invoke a default method for Java 9+. " + target + " "
|
||||
+ method + " " + Arrays.toString(args), e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class);
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance(srcInt).in(srcInt).unreflectSpecial(method, srcInt).bindTo(target)
|
||||
.invokeWithArguments(args);
|
||||
} catch (Throwable e) {
|
||||
throw new NbtApiException("Error while trying to invoke a default method for Java 8. " + target + " "
|
||||
+ method + " " + Arrays.toString(args), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.tr7zw.changeme.nbtapi.wrapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTHandler;
|
||||
|
||||
public interface NBTProxy {
|
||||
|
||||
final Map<Class<?>, NBTHandler<Object>> handlers = new HashMap<>();
|
||||
|
||||
public default void init() {
|
||||
|
||||
}
|
||||
|
||||
public default Casing getCasing() {
|
||||
return Casing.PascalCase;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public default <T> NBTHandler<T> getHandler(Class<T> clazz) {
|
||||
return (NBTHandler<T>) handlers.get(clazz);
|
||||
}
|
||||
|
||||
public default Collection<NBTHandler<Object>> getHandlers() {
|
||||
return handlers.values();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public default <T> void registerHandler(Class<T> clazz, NBTHandler<T> handler) {
|
||||
handlers.put(clazz, (NBTHandler<Object>) handler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.tr7zw.changeme.nbtapi.wrapper;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target(METHOD)
|
||||
public @interface NBTTarget {
|
||||
public String value();
|
||||
|
||||
public Type type() default Type.AUTOMATIC;
|
||||
|
||||
public enum Type {
|
||||
AUTOMATIC, GET, SET, HAS
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package de.tr7zw.changeme.nbtapi.wrapper;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
|
||||
|
||||
class ProxiedList<E extends NBTProxy> implements ProxyList<E> {
|
||||
|
||||
private final ReadWriteNBTCompoundList nbt;
|
||||
private final Class<E> proxy;
|
||||
|
||||
public ProxiedList(ReadWriteNBTCompoundList nbt, Class<E> proxyClass) {
|
||||
this.nbt = nbt;
|
||||
this.proxy = proxyClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int index) {
|
||||
ReadWriteNBT tag = nbt.get(index);
|
||||
return new ProxyBuilder<E>(tag,proxy).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return nbt.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(int index) {
|
||||
nbt.remove(index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new Itr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E addCompound() {
|
||||
ReadWriteNBT tag = nbt.addCompound();
|
||||
return new ProxyBuilder<E>(tag,proxy).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return nbt.isEmpty();
|
||||
}
|
||||
|
||||
private class Itr implements Iterator<E> {
|
||||
/**
|
||||
* Index of element to be returned by subsequent call to next.
|
||||
*/
|
||||
int cursor = 0;
|
||||
|
||||
/**
|
||||
* Index of element returned by most recent call to next or
|
||||
* previous. Reset to -1 if this element is deleted by a call
|
||||
* to remove.
|
||||
*/
|
||||
int lastRet = -1;
|
||||
|
||||
public boolean hasNext() {
|
||||
return cursor != size();
|
||||
}
|
||||
|
||||
public E next() {
|
||||
try {
|
||||
int i = cursor;
|
||||
E next = get(i);
|
||||
lastRet = i;
|
||||
cursor = i + 1;
|
||||
return next;
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (lastRet < 0)
|
||||
throw new IllegalStateException();
|
||||
|
||||
try {
|
||||
ProxiedList.this.remove(lastRet);
|
||||
if (lastRet < cursor)
|
||||
cursor--;
|
||||
lastRet = -1;
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
throw new ConcurrentModificationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
package de.tr7zw.changeme.nbtapi.wrapper;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTHandler;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.wrapper.NBTTarget.Type;
|
||||
|
||||
public class ProxyBuilder<T extends NBTProxy> implements InvocationHandler {
|
||||
|
||||
private static final Map<Method, Function<Arguments, Object>> METHOD_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
private final Class<T> target;
|
||||
private final ReadWriteNBT nbt;
|
||||
private boolean readOnly;
|
||||
|
||||
public ProxyBuilder(ReadWriteNBT nbt, Class<T> target) {
|
||||
if (!target.isInterface()) {
|
||||
throw new NbtApiException("A proxy can only be built from an interface! Check the wiki for examples.");
|
||||
}
|
||||
this.target = target;
|
||||
this.nbt = nbt;
|
||||
}
|
||||
|
||||
public ProxyBuilder<T> readOnly() {
|
||||
this.readOnly = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T build() {
|
||||
T inst = (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { target }, this);
|
||||
inst.init();
|
||||
return inst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
METHOD_CACHE.computeIfAbsent(method, m -> ProxyBuilder.createFunction((NBTProxy) proxy, m));
|
||||
return METHOD_CACHE.get(method).apply(new Arguments(target, (NBTProxy) proxy, readOnly, nbt, args));
|
||||
}
|
||||
|
||||
private static class Arguments {
|
||||
Class<?> target;
|
||||
NBTProxy proxy;
|
||||
ReadWriteNBT nbt;
|
||||
Object[] args;
|
||||
boolean readOnly;
|
||||
|
||||
public Arguments(Class<?> target, NBTProxy proxy, boolean readOnly, ReadWriteNBT nbt, Object[] args) {
|
||||
this.target = target;
|
||||
this.proxy = proxy;
|
||||
this.nbt = nbt;
|
||||
this.args = args;
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private static Function<Arguments, Object> createFunction(NBTProxy proxy, Method method) {
|
||||
if ("toString".equals(method.getName()) && method.getParameterCount() == 0
|
||||
&& method.getReturnType() == String.class) {
|
||||
return (arguments) -> arguments.nbt.toString();
|
||||
}
|
||||
if (method.isDefault()) {
|
||||
return (arguments) -> DefaultMethodInvoker.invokeDefault(arguments.target, arguments.proxy, method,
|
||||
arguments.args);
|
||||
}
|
||||
Type action = getAction(method);
|
||||
if (action == Type.SET) {
|
||||
String fieldName = getNBTName(proxy.getCasing(), method);
|
||||
return (arguments) -> {
|
||||
if (arguments.readOnly) {
|
||||
throw new NbtApiException("Tried calling a set method on a read only object.");
|
||||
}
|
||||
return setNBT(arguments.nbt, arguments.proxy, fieldName, arguments.args[0]);
|
||||
};
|
||||
}
|
||||
if (action == Type.GET) {
|
||||
Class<?> retType = method.getReturnType();
|
||||
String fieldName = getNBTName(proxy.getCasing(), method);
|
||||
// Allow stacking of proxies
|
||||
if (retType.isInterface() && NBTProxy.class.isAssignableFrom(retType)) {
|
||||
return (arguments) -> {
|
||||
if (arguments.nbt.hasTag(fieldName) && arguments.nbt.getType(fieldName) != NBTType.NBTTagCompound) {
|
||||
throw new NbtApiException("Tried getting a '" + retType + "' proxy from the field '" + fieldName
|
||||
+ "', but it's not a TagCompound!");
|
||||
}
|
||||
return new ProxyBuilder<NBTProxy>(arguments.nbt.getOrCreateCompound(fieldName),
|
||||
(Class<NBTProxy>) retType).build();
|
||||
};
|
||||
}
|
||||
if (retType == ProxyList.class) {
|
||||
|
||||
Class<?> parameterType = (Class<?>) ((ParameterizedType) method.getGenericReturnType())
|
||||
.getActualTypeArguments()[0];
|
||||
if (parameterType != null && parameterType.isInterface()
|
||||
&& NBTProxy.class.isAssignableFrom(parameterType)) {
|
||||
return (arguments) -> {
|
||||
return new ProxiedList(arguments.nbt.getCompoundList(fieldName), parameterType);
|
||||
};
|
||||
}
|
||||
}
|
||||
NBTHandler<Object> handler = (NBTHandler<Object>) proxy.getHandler(retType);
|
||||
if (handler != null) {
|
||||
return (arguments) -> handler.get(arguments.nbt, fieldName);
|
||||
}
|
||||
return (arguments) -> arguments.nbt.getOrNull(fieldName, retType);
|
||||
}
|
||||
if (action == Type.HAS) {
|
||||
String fieldName = getNBTName(proxy.getCasing(), method);
|
||||
return (arguments) -> arguments.nbt.hasTag(fieldName);
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"The method '" + method.getName() + "' in '" + method.getDeclaringClass().getName()
|
||||
+ "' can not be handled by the NBT-API. Please check the Wiki for examples!");
|
||||
}
|
||||
|
||||
private static Type getAction(Method method) {
|
||||
NBTTarget target = method.getAnnotation(NBTTarget.class);
|
||||
if (target != null) {
|
||||
if (target.type() == Type.HAS && method.getParameterCount() == 0
|
||||
&& method.getReturnType() == boolean.class) {
|
||||
return Type.HAS;
|
||||
}
|
||||
if (target.type() == Type.GET && method.getParameterCount() == 0) {
|
||||
return Type.GET;
|
||||
}
|
||||
if (target.type() == Type.SET && method.getParameterCount() == 1) {
|
||||
return Type.SET;
|
||||
}
|
||||
}
|
||||
if (method.getName().startsWith("set") && method.getParameterCount() == 1) {
|
||||
return Type.SET;
|
||||
}
|
||||
if (method.getName().startsWith("get") && method.getParameterCount() == 0) {
|
||||
return Type.GET;
|
||||
}
|
||||
if (method.getName().startsWith("has") && method.getParameterCount() == 0
|
||||
&& method.getReturnType() == boolean.class) {
|
||||
return Type.HAS;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getNBTName(Casing casing, Method method) {
|
||||
NBTTarget target = method.getAnnotation(NBTTarget.class);
|
||||
if (target != null) {
|
||||
return target.value();
|
||||
}
|
||||
return casing.convertString(method.getName().substring(3));
|
||||
}
|
||||
|
||||
private static Object setNBT(ReadWriteNBT nbt, NBTProxy proxy, String key, Object value) {
|
||||
// welcome to the "I wish we all could use java 17" method. Thanks, legacy mc
|
||||
// versions
|
||||
if (value == null) {
|
||||
nbt.removeKey(key);
|
||||
} else if (value instanceof Boolean) {
|
||||
nbt.setBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Byte) {
|
||||
nbt.setByte(key, (Byte) value);
|
||||
} else if (value instanceof Short) {
|
||||
nbt.setShort(key, (Short) value);
|
||||
} else if (value instanceof Integer) {
|
||||
nbt.setInteger(key, (Integer) value);
|
||||
} else if (value instanceof Long) {
|
||||
nbt.setLong(key, (Long) value);
|
||||
} else if (value instanceof Float) {
|
||||
nbt.setFloat(key, (Float) value);
|
||||
} else if (value instanceof Double) {
|
||||
nbt.setDouble(key, (Double) value);
|
||||
} else if (value instanceof byte[]) {
|
||||
nbt.setByteArray(key, (byte[]) value);
|
||||
} else if (value instanceof int[]) {
|
||||
nbt.setIntArray(key, (int[]) value);
|
||||
} else if (value instanceof long[]) {
|
||||
nbt.setLongArray(key, (long[]) value);
|
||||
} else if (value instanceof String) {
|
||||
nbt.setString(key, (String) value);
|
||||
} else if (value instanceof UUID) {
|
||||
nbt.setUUID(key, (UUID) value);
|
||||
} else if (value.getClass().isEnum()) {
|
||||
nbt.setEnum(key, (Enum<?>) value);
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
NBTHandler<Object> handler = (NBTHandler<Object>) proxy.getHandler(value.getClass());
|
||||
if (handler != null) {
|
||||
handler.set(nbt, key, value);
|
||||
} else {
|
||||
for (NBTHandler<Object> nbth : proxy.getHandlers()) {
|
||||
if (nbth.fuzzyMatch(value)) {
|
||||
nbth.set(nbt, key, value);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Tried setting an object of type '" + value.getClass().getName()
|
||||
+ "'. This is not a supported NBT value. Please check the Wiki for examples!");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.tr7zw.changeme.nbtapi.wrapper;
|
||||
|
||||
public interface ProxyList<T extends NBTProxy> extends Iterable<T> {
|
||||
|
||||
/**
|
||||
* Adds a new compound tag to the current compound tag
|
||||
*
|
||||
* @return A new instance of the class.
|
||||
*/
|
||||
T addCompound();
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this collection. If this collection
|
||||
* contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.
|
||||
*
|
||||
* @return the number of elements in this collection
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Returns true if this collection contains no elements.
|
||||
*
|
||||
* @return true if this collection contains no elements
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Get the object with the given id.
|
||||
*
|
||||
* @param id The id of the object to get.
|
||||
* @return The object with the given id.
|
||||
*/
|
||||
T get(int id);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this list
|
||||
*
|
||||
* @param i The index of the element to remove.
|
||||
*/
|
||||
void remove(int i);
|
||||
|
||||
}
|
||||
+15
-22
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<version>2.16.0</version>
|
||||
</parent>
|
||||
<artifactId>item-nbt-api-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -12,21 +12,22 @@
|
||||
<dependency>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-api</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<version>2.16.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>nbt-injector</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>nbt-data-api</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>datafixerupper</artifactId>
|
||||
<version>4.0.26</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<!-- Overwrite to provided -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
@@ -39,7 +40,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.6.2</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<relocations>
|
||||
@@ -47,14 +48,6 @@
|
||||
<pattern>de.tr7zw.changeme.nbtapi</pattern>
|
||||
<shadedPattern>de.tr7zw.nbtapi</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>javassist</pattern>
|
||||
<shadedPattern>de.tr7zw.nbtinjector.javassist</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>de.tr7zw.annotations</pattern>
|
||||
<shadedPattern>de.tr7zw.nbtapi.utils.annotations</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
@@ -19,6 +18,7 @@ import de.tr7zw.nbtapi.plugin.tests.GameprofileTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.NBTFileTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.blocks.BlockNBTTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.chunks.ChunkNBTPersistentTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.CompoundDifferenceTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.EnumTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.EqualsTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.ForEachTest;
|
||||
@@ -26,28 +26,31 @@ import de.tr7zw.nbtapi.plugin.tests.compounds.GetterSetterTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.InterfaceTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.IteratorTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.ListTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.LongArrayTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.MergeTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.ModernSubCompoundsTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.RemovingKeys;
|
||||
import de.tr7zw.nbtapi.plugin.tests.compounds.ResolveTest;
|
||||
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.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.ComponentsTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.DirectApplyMetaTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.DirectApplyTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.EmptyItemTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemConversionTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.tiles.TileTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.tiles.TilesCustomNBTPersistentTest;
|
||||
import de.tr7zw.nbtinjector.NBTInjector;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemJsonTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemMergingTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.ItemStackConversionTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.LegacyItemTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.MetaTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.NBTModifyItemTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.items.SmuggleTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.proxy.SimpleProxyTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.tiles.TileTest;
|
||||
import de.tr7zw.nbtapi.plugin.tests.tiles.TilesCustomNBTPersistentTest;
|
||||
|
||||
public class NBTAPI extends JavaPlugin {
|
||||
|
||||
@@ -64,7 +67,6 @@ public class NBTAPI extends JavaPlugin {
|
||||
public void onLoad() {
|
||||
|
||||
getConfig().options().copyDefaults(true);
|
||||
getConfig().addDefault("nbtInjector.enabled", false);
|
||||
getConfig().addDefault("bStats.enabled", true);
|
||||
getConfig().addDefault("updateCheck.enabled", true);
|
||||
getConfig().addDefault("silentquickstart", false);
|
||||
@@ -82,25 +84,13 @@ public class NBTAPI extends JavaPlugin {
|
||||
MinecraftVersion.enableUpdateCheck();
|
||||
}
|
||||
|
||||
// Disabled by default since 2.1. Enable it yourself by calling
|
||||
// NBTInjector.inject(); during onLoad/config
|
||||
if (getConfig().getBoolean("nbtInjector.enabled")) {
|
||||
getLogger().info("Injecting custom NBT");
|
||||
try {
|
||||
NBTInjector.inject();
|
||||
getLogger().info("Injected!");
|
||||
} catch (Throwable ex) { // NOSONAR
|
||||
getLogger().log(Level.SEVERE, "Error while Injecting custom Tile/Entity classes!", ex);
|
||||
compatible = false;
|
||||
}
|
||||
}
|
||||
|
||||
// NBTCompounds
|
||||
apiTests.add(new GetterSetterTest());
|
||||
apiTests.add(new TypeTest());
|
||||
apiTests.add(new RemovingKeys());
|
||||
apiTests.add(new EnumTest());
|
||||
apiTests.add(new InterfaceTest());
|
||||
apiTests.add(new ResolveTest());
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) // 1.7.10 list support is not complete at all
|
||||
apiTests.add(new ListTest());
|
||||
apiTests.add(new SubCompoundsTest());
|
||||
@@ -110,20 +100,35 @@ public class NBTAPI extends JavaPlugin {
|
||||
apiTests.add(new ForEachTest());
|
||||
apiTests.add(new StreamTest());
|
||||
apiTests.add(new EqualsTest());
|
||||
apiTests.add(new CompoundDifferenceTest());
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) // 1.7.10 list support is not complete at all
|
||||
apiTests.add(new IteratorTest());
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1))
|
||||
apiTests.add(new LongArrayTest());
|
||||
|
||||
// Items
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) { // 1.7.10 not a thing
|
||||
apiTests.add(new ItemConversionTest());
|
||||
apiTests.add(new ItemStackConversionTest());
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
apiTests.add(new LegacyItemTest());
|
||||
}
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4) && !MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
apiTests.add(new ItemJsonTest());
|
||||
}
|
||||
apiTests.add(new ComponentsTest());
|
||||
apiTests.add(new EmptyItemTest());
|
||||
apiTests.add(new SmuggleTest());
|
||||
apiTests.add(new MetaTest());
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) { // 1.7.10 not a thing
|
||||
apiTests.add(new ItemMergingTest());
|
||||
apiTests.add(new DirectApplyTest());
|
||||
apiTests.add(new DirectApplyMetaTest());
|
||||
apiTests.add(new NBTModifyItemTest());
|
||||
}
|
||||
// Proxies
|
||||
apiTests.add(new SimpleProxyTest());
|
||||
|
||||
// Entity
|
||||
apiTests.add(new EntityTest());
|
||||
@@ -142,15 +147,6 @@ public class NBTAPI extends JavaPlugin {
|
||||
// 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());
|
||||
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3))
|
||||
apiTests.add(new GameprofileTest());
|
||||
|
||||
@@ -165,10 +161,7 @@ public class NBTAPI extends JavaPlugin {
|
||||
VersionChecker.hideOk = true;
|
||||
return;
|
||||
}
|
||||
getLogger().info("Adding listeners...");
|
||||
Bukkit.getPluginManager().registerEvents(new ReloadListener(), this);
|
||||
getLogger().info("Gson:");
|
||||
MinecraftVersion.hasGsonSupport();
|
||||
MinecraftVersion.hasGsonSupport(); // init gson(if it hasn't already)
|
||||
getLogger().info("Checking bindings...");
|
||||
MinecraftVersion.getVersion();
|
||||
|
||||
@@ -207,7 +200,7 @@ public class NBTAPI extends JavaPlugin {
|
||||
} catch (Exception ex) {
|
||||
results.put(test, ex);
|
||||
getLogger().log(Level.WARNING, "Error during '" + test.getClass().getSimpleName() + "' test!", ex);
|
||||
} catch (NoSuchFieldError th) { // NOSONAR
|
||||
} catch (Throwable th) { // NOSONAR
|
||||
getLogger().log(Level.SEVERE, "Servere error during '" + test.getClass().getSimpleName() + "' test!");
|
||||
getLogger().warning(
|
||||
"WARNING! This version of Item-NBT-API seems to be broken with your Spigot version! Canceled the other tests!");
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package de.tr7zw.nbtapi.plugin;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import de.tr7zw.nbtinjector.NBTInjector;
|
||||
|
||||
/**
|
||||
* This listener class tries to prevent people from reloading while the
|
||||
* NBTInjector is enabled.
|
||||
*
|
||||
* @author tr7zw
|
||||
*
|
||||
*/
|
||||
public class ReloadListener implements Listener {
|
||||
|
||||
/**
|
||||
* Console handler
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onCommand(org.bukkit.event.server.ServerCommandEvent event) {
|
||||
if (event.getCommand().toLowerCase().startsWith("reload") && NBTInjector.isInjected()) {
|
||||
event.setCancelled(true);
|
||||
event.getSender().sendMessage(
|
||||
"[NBTAPI] The NBTInjector is currently enabled. Reloading will turn the server into an unstable state and data-loss may accure. Please do a clean restart. Canceled reload!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Player handler
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onCommand(org.bukkit.event.player.PlayerCommandPreprocessEvent event) {
|
||||
if (event.getMessage().toLowerCase().startsWith("/reload") && NBTInjector.isInjected()) {
|
||||
event.setCancelled(true);
|
||||
event.getPlayer().sendMessage(
|
||||
"[NBTAPI] The NBTInjector is currently enabled. Reloading will turn the server into an unstable state and data-loss may accure. Please do a clean restart. Canceled reload!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,9 +4,9 @@ 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.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
|
||||
public class GameprofileTest implements Test {
|
||||
|
||||
@@ -14,10 +14,9 @@ public class GameprofileTest implements Test {
|
||||
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)) {
|
||||
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
|
||||
GameProfile profile2 = NBT.gameProfileFromNBT(nbt);
|
||||
if (profile == null || !profile.equals(profile2)) {
|
||||
throw new NbtApiException("Error when converting a GameProfile from/to NBT!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package de.tr7zw.nbtapi.plugin.tests;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBTFile;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.NBTFileHandle;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.NBTAPI;
|
||||
|
||||
public class NBTFileTest implements Test {
|
||||
@@ -16,15 +16,18 @@ public class NBTFileTest implements Test {
|
||||
NBTAPI.getInstance().getDataFolder().mkdirs();
|
||||
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");
|
||||
NBTFileHandle file = NBT.getFileHandle(testFile);
|
||||
file.getOrCreateCompound("testcomp").setString("test1", "ok");
|
||||
ReadWriteNBT comp = file.getOrCreateCompound("testcomp");
|
||||
if (comp == null) {
|
||||
throw new NbtApiException("Error getting compound!");
|
||||
}
|
||||
comp.setString("test2", "ok");
|
||||
file.setLong("time", System.currentTimeMillis());
|
||||
file.setString("test", "test");
|
||||
NBTCompound chunks = file.addCompound("chunks");
|
||||
NBTCompound chunk = chunks.addCompound("somechunk");
|
||||
NBTCompound block = chunk.addCompound("someblock");
|
||||
ReadWriteNBT chunks = file.getOrCreateCompound("chunks");
|
||||
ReadWriteNBT chunk = chunks.getOrCreateCompound("somechunk");
|
||||
ReadWriteNBT block = chunk.getOrCreateCompound("someblock");
|
||||
block.setString("type", "wool");
|
||||
file.save();
|
||||
|
||||
@@ -32,25 +35,25 @@ public class NBTFileTest implements Test {
|
||||
throw new NbtApiException("SubCompounds did not work!");
|
||||
}
|
||||
|
||||
NBTFile fileLoaded = new NBTFile(testFile);
|
||||
NBTFileHandle fileLoaded = NBT.getFileHandle(testFile);
|
||||
if (!fileLoaded.getString("test").equals("test")) {
|
||||
throw new NbtApiException("Wasn't able to load NBT File with the correct content!");
|
||||
}
|
||||
Files.deleteIfExists(fileLoaded.getFile().toPath());
|
||||
// String
|
||||
String str = fileLoaded.toString();
|
||||
NBTContainer rebuild = new NBTContainer(str);
|
||||
ReadWriteNBT rebuild = NBT.parseNBT(str);
|
||||
if (!str.equals(rebuild.toString())) {
|
||||
throw new NbtApiException("Wasn't able to parse NBT from a String!");
|
||||
}
|
||||
|
||||
NBTCompound dummy = new NBTContainer();
|
||||
ReadWriteNBT dummy = NBT.createNBTObject();
|
||||
dummy.setString("test1", "key1");
|
||||
NBTFile.saveTo(testFile, dummy);
|
||||
dummy = new NBTContainer();
|
||||
NBT.writeFile(testFile, dummy);
|
||||
dummy = NBT.createNBTObject();
|
||||
dummy.setString("test2", "key2");
|
||||
NBTFile.saveTo(testFile, dummy);
|
||||
dummy = NBTFile.readFrom(testFile);
|
||||
NBT.writeFile(testFile, dummy);
|
||||
dummy = NBT.readFile(testFile);
|
||||
if (dummy.hasTag("test1") || !dummy.getString("test2").equals("key2")) {
|
||||
throw new NbtApiException("Wasn't able to save NBT File with the correct content!");
|
||||
}
|
||||
|
||||
+56
-19
@@ -1,40 +1,77 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.blocks;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTBlock;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockNBTTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_16_R3.getVersionId())
|
||||
return;
|
||||
if (!Bukkit.getWorlds().isEmpty()) {
|
||||
World world = Bukkit.getWorlds().get(0);
|
||||
try {
|
||||
if (world.getLoadedChunks().length > 1) {
|
||||
Chunk chunk = world.getLoadedChunks()[0];
|
||||
Block block = chunk.getBlock(0, 254, 0);
|
||||
NBTBlock comp = new NBTBlock(block);
|
||||
comp.getData().removeKey("Too");
|
||||
if (comp.getData().hasTag("Too")) {
|
||||
throw new NbtApiException("Unable to remove key from Block!");
|
||||
}
|
||||
comp.getData().setString("Too", "Bar");
|
||||
if (!new NBTBlock(block).getData().getString("Too").equals("Bar")) {
|
||||
throw new NbtApiException("Custom Data did not save to a Block!");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTBlocks!", ex);
|
||||
|
||||
List<World> loadedWorlds = Bukkit.getWorlds();
|
||||
if (loadedWorlds.isEmpty())
|
||||
return;
|
||||
|
||||
World world = loadedWorlds.get(0);
|
||||
Chunk[] loadedChunks = world.getLoadedChunks();
|
||||
if (loadedChunks.length == 0)
|
||||
return;
|
||||
|
||||
try {
|
||||
Chunk chunk = loadedChunks[0];
|
||||
Block block = chunk.getBlock(0, 254, 0);
|
||||
String blockKey = block.getX() + "_" + block.getY() + "_" + block.getZ();
|
||||
|
||||
NBT.modifyChunkPDC(block, nbt -> nbt.setString("Too", "Bar"));
|
||||
boolean storedDataPresent = NBT.readAndGetChunkPDC(chunk, nbt -> {
|
||||
if (!nbt.hasTag("blocks", NBTType.NBTTagCompound)) return false;
|
||||
|
||||
ReadableNBT blocksNbt = nbt.getCompound("blocks");
|
||||
if (blocksNbt == null || !blocksNbt.hasTag(blockKey, NBTType.NBTTagCompound)) return false;
|
||||
|
||||
ReadableNBT blockNbt = blocksNbt.getCompound(blockKey);
|
||||
return blockNbt != null && blockNbt.hasTag("Too", NBTType.NBTTagString) && "Bar".equals(blockNbt.getString("Too"));
|
||||
});
|
||||
if (!storedDataPresent) {
|
||||
throw new NbtApiException("Custom Data did not save to a Block!");
|
||||
}
|
||||
if (!NBT.readAndGetChunkPDC(block, nbt -> nbt.hasTag("Too"))) {
|
||||
throw new NbtApiException("Custom Data did not save to a Block!");
|
||||
}
|
||||
|
||||
boolean blockHadOnlyTestKey = NBT.readAndGetChunkPDC(block, nbt -> nbt.getKeys().size() == 1);
|
||||
boolean chunkHadOnlyOneBlock = NBT.readAndGetChunkPDC(chunk, nbt -> nbt.getCompound("blocks").getKeys().size() == 1);
|
||||
|
||||
NBT.modifyChunkPDC(block, nbt -> nbt.removeKey("Too"));
|
||||
|
||||
if (NBT.readAndGetChunkPDC(block, nbt -> nbt.hasTag("Too"))) {
|
||||
throw new NbtApiException("Unable to remove key from Block!");
|
||||
}
|
||||
|
||||
if (chunkHadOnlyOneBlock) {
|
||||
if (NBT.readAndGetChunkPDC(chunk, nbt -> nbt.hasTag("blocks"))) {
|
||||
throw new NbtApiException("Chunk data wasn't cleaned up (hanging \"blocks\" compound)!");
|
||||
}
|
||||
} else if (blockHadOnlyTestKey) {
|
||||
if (NBT.readAndGetChunkPDC(chunk, nbt -> nbt.getCompound("blocks").hasTag(blockKey))) {
|
||||
throw new NbtApiException("Chunk data wasn't cleaned up (hanging block location compound)!");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTBlocks!", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-20
@@ -1,40 +1,46 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.chunks;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTChunk;
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ChunkNBTPersistentTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_16_R3.getVersionId())
|
||||
return;
|
||||
if (!Bukkit.getWorlds().isEmpty()) {
|
||||
World world = Bukkit.getWorlds().get(0);
|
||||
try {
|
||||
if (world.getLoadedChunks().length > 1) {
|
||||
Chunk chunk = world.getLoadedChunks()[0];
|
||||
NBTChunk comp = new NBTChunk(chunk);
|
||||
NBTCompound persistentData = comp.getPersistentDataContainer();
|
||||
persistentData.removeKey("Foo");
|
||||
if (persistentData.hasTag("Foo")) {
|
||||
throw new NbtApiException("Unable to remove key from Chunk!");
|
||||
}
|
||||
persistentData.setString("Foo", "Bar");
|
||||
if (!new NBTChunk(chunk).getPersistentDataContainer().getString("Foo").equals("Bar")) {
|
||||
throw new NbtApiException("Custom Data did not save to the Chunk!");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTChunks!", ex);
|
||||
|
||||
List<World> loadedWorlds = Bukkit.getWorlds();
|
||||
if (loadedWorlds.isEmpty())
|
||||
return;
|
||||
|
||||
World world = loadedWorlds.get(0);
|
||||
Chunk[] loadedChunks = world.getLoadedChunks();
|
||||
if (loadedChunks.length == 0)
|
||||
return;
|
||||
|
||||
Chunk chunk = loadedChunks[0];
|
||||
try {
|
||||
NBT.modifyChunkPDC(chunk, nbt -> nbt.setString("Foo", "Bar"));
|
||||
if (!NBT.readAndGetChunkPDC(chunk, nbt -> nbt.hasTag("Foo", NBTType.NBTTagString) && "Bar".equals(nbt.getString("Foo")))) {
|
||||
throw new NbtApiException("Custom Data did not save to the Chunk!");
|
||||
}
|
||||
|
||||
NBT.modifyChunkPDC(chunk, nbt -> nbt.removeKey("Foo"));
|
||||
if (NBT.readAndGetChunkPDC(chunk, nbt -> nbt.hasTag("Foo"))) {
|
||||
throw new NbtApiException("Unable to remove key from Chunk!");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NbtApiException("Wasn't able to use NBTChunks!", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CompoundDifferenceTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ReadWriteNBT nbt1 = NBT.createNBTObject();
|
||||
nbt1.setInteger("intTag", 1);
|
||||
ReadWriteNBT tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 1);
|
||||
nbt1.getCompoundList("compoundList1").addCompound(tmp);
|
||||
nbt1.setIntArray("intArray", new int[]{1, 2, 3});
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setIntArray("foo", new int[]{1, 2, 3});
|
||||
nbt1.getCompoundList("compoundList2").addCompound(tmp);
|
||||
nbt1.getOrCreateCompound("compoundTag").setFloat("floatTag", 20F);
|
||||
nbt1.getOrCreateCompound("compoundTag").setBoolean("booleanTag", true);
|
||||
nbt1.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D));
|
||||
nbt1.getOrCreateCompound("compoundTag").getFloatList("floatList").addAll(Arrays.asList(1F, 2F));
|
||||
nbt1.getOrCreateCompound("compoundTagTwo").setString("stringTag", "string");
|
||||
ReadWriteNBT nbt2 = NBT.createNBTObject();
|
||||
nbt2.setInteger("intTag", 1);
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 1);
|
||||
nbt2.getCompoundList("compoundList1").addCompound(tmp);
|
||||
nbt2.setInteger("alsoIntTag", 2);
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 2);
|
||||
nbt2.getCompoundList("compoundList2").addCompound(tmp);
|
||||
nbt2.getOrCreateCompound("compoundTag").setFloat("floatTag", 20F);
|
||||
nbt2.getOrCreateCompound("compoundTag").setBoolean("booleanTag", false);
|
||||
nbt2.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D, 4D));
|
||||
nbt2.getOrCreateCompound("compoundTag").getFloatList("floatList").addAll(Arrays.asList(1F, 2F));
|
||||
nbt2.getOrCreateCompound("compoundTagTwo").setString("stringTag", "string");
|
||||
|
||||
ReadWriteNBT expectedDiff1 = NBT.createNBTObject();
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setIntArray("foo", new int[]{1, 2, 3});
|
||||
expectedDiff1.getCompoundList("compoundList2").addCompound(tmp);
|
||||
expectedDiff1.setIntArray("intArray", new int[]{1, 2, 3});
|
||||
expectedDiff1.getOrCreateCompound("compoundTag").setBoolean("booleanTag", true);
|
||||
expectedDiff1.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D));
|
||||
ReadWriteNBT expectedDiff2 = NBT.createNBTObject();
|
||||
tmp = NBT.createNBTObject();
|
||||
tmp.setInteger("foo", 2);
|
||||
expectedDiff2.getCompoundList("compoundList2").addCompound(tmp);
|
||||
expectedDiff2.setInteger("alsoIntTag", 2);
|
||||
expectedDiff2.getOrCreateCompound("compoundTag").setBoolean("booleanTag", false);
|
||||
expectedDiff2.getOrCreateCompound("compoundTag").getDoubleList("doubleList").addAll(Arrays.asList(1D, 2D, 3D, 4D));
|
||||
|
||||
ReadWriteNBT diff1 = nbt1.extractDifference(nbt2);
|
||||
ReadWriteNBT diff2 = nbt2.extractDifference(nbt1);
|
||||
|
||||
if (!expectedDiff1.equals(diff1)) {
|
||||
throw new NbtApiException("Diff1: Compounds did not match! " + expectedDiff1 + " " + diff1);
|
||||
}
|
||||
if (!expectedDiff2.equals(diff2)) {
|
||||
throw new NbtApiException("Diff2: Compounds did not match! " + expectedDiff2 + " " + diff2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class EnumTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTCompound comp = new NBTContainer();
|
||||
ReadWriteNBT comp = NBT.createNBTObject();
|
||||
comp.setEnum("test", NBTType.NBTTagEnd);
|
||||
NBTType type = comp.getEnum("test", NBTType.class);
|
||||
NBTType typeNonNull = comp.getOrNull("test", NBTType.class);
|
||||
|
||||
+18
-18
@@ -5,44 +5,44 @@ import java.util.Arrays;
|
||||
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.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class EqualsTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer cont = new NBTContainer();
|
||||
ReadWriteNBT cont = NBT.createNBTObject();
|
||||
cont.setString("hello", "world");
|
||||
cont.setInteger("theAnswer", 42);
|
||||
cont.addCompound("sub").setString("me", "too");
|
||||
cont.getOrCreateCompound("sub").setString("me", "too");
|
||||
cont.getStringList("somelist").addAll(Arrays.asList("a", "b", "c"));
|
||||
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");
|
||||
customData.getStringList("somelist").addAll(Arrays.asList("a", "b", "c"));
|
||||
if (!customData.equals(cont)) {
|
||||
throw new NbtApiException("Compounds did not match! " + customData + " " + cont);
|
||||
}
|
||||
NBT.modify(item, nbti -> {
|
||||
ReadWriteNBT customData = nbti.getOrCreateCompound("customData");
|
||||
// reverse order
|
||||
customData.getOrCreateCompound("sub").setString("me", "too");
|
||||
customData.setInteger("theAnswer", 42);
|
||||
customData.setString("hello", "world");
|
||||
customData.getStringList("somelist").addAll(Arrays.asList("a", "b", "c"));
|
||||
if (!customData.equals(cont)) {
|
||||
throw new NbtApiException("Compounds did not match! " + customData + " " + cont);
|
||||
}
|
||||
});
|
||||
|
||||
// empty test
|
||||
|
||||
if (!new NBTContainer().equals(new NBTContainer())) {
|
||||
if (!NBT.createNBTObject().equals(NBT.createNBTObject())) {
|
||||
throw new NbtApiException("Two empty tags did not match!");
|
||||
}
|
||||
|
||||
// not equal test
|
||||
NBTContainer part1 = new NBTContainer();
|
||||
ReadWriteNBT part1 = NBT.createNBTObject();
|
||||
part1.setString("a", "a");
|
||||
part1.setString("b", "b");
|
||||
NBTContainer part2 = new NBTContainer();
|
||||
ReadWriteNBT part2 = NBT.createNBTObject();
|
||||
part2.setString("a", "a");
|
||||
part2.setString("b", "a");
|
||||
if (part1.equals(part2)) {
|
||||
|
||||
+7
-4
@@ -1,7 +1,8 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class GetterSetterTest implements Test {
|
||||
@@ -30,7 +31,7 @@ public class GetterSetterTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer comp = new NBTContainer();
|
||||
ReadWriteNBT comp = NBT.createNBTObject();
|
||||
|
||||
comp.setString(STRING_TEST_KEY, STRING_TEST_VALUE);
|
||||
comp.setInteger(INT_TEST_KEY, INT_TEST_VALUE);
|
||||
@@ -46,13 +47,15 @@ public class GetterSetterTest implements Test {
|
||||
if (!comp.hasTag(STRING_TEST_KEY)) {
|
||||
throw new NbtApiException("Wasn't able to check a key! The Item-NBT-API may not work!");
|
||||
}
|
||||
int[] intArray = comp.getIntArray(INTARRAY_TEST_KEY);
|
||||
byte[] byteArray = comp.getByteArray(BYTEARRAY_TEST_KEY);
|
||||
if (!(STRING_TEST_VALUE).equals(comp.getString(STRING_TEST_KEY))
|
||||
|| comp.getInteger(INT_TEST_KEY) != INT_TEST_VALUE
|
||||
|| comp.getDouble(DOUBLE_TEST_KEY) != DOUBLE_TEST_VALUE
|
||||
|| comp.getByte(BYTE_TEST_KEY) != BYTE_TEST_VALUE || comp.getShort(SHORT_TEST_KEY) != SHORT_TEST_VALUE
|
||||
|| comp.getFloat(FLOAT_TEST_KEY) != FLOAT_TEST_VALUE || comp.getLong(LONG_TEST_KEY) != LONG_TEST_VALUE
|
||||
|| comp.getIntArray(INTARRAY_TEST_KEY).length != (INTARRAY_TEST_VALUE).length
|
||||
|| comp.getByteArray(BYTEARRAY_TEST_KEY).length != (BYTEARRAY_TEST_VALUE).length
|
||||
|| (intArray != null && intArray.length != (INTARRAY_TEST_VALUE).length)
|
||||
|| (byteArray != null && byteArray.length != (BYTEARRAY_TEST_VALUE).length)
|
||||
|| !comp.getBoolean(BOOLEAN_TEST_KEY).equals(BOOLEAN_TEST_VALUE)) {
|
||||
throw new NbtApiException("One key does not equal the original value! The Item-NBT-API may not work!");
|
||||
}
|
||||
|
||||
+24
-23
@@ -3,23 +3,22 @@ package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
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.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTList;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ListTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer comp = new NBTContainer();
|
||||
ReadWriteNBT comp = NBT.createNBTObject();
|
||||
|
||||
// Strings
|
||||
NBTList<String> list = comp.getStringList("testlist");
|
||||
ReadWriteNBTList<String> list = comp.getStringList("testlist");
|
||||
list.add("test1");
|
||||
list.add("test2");
|
||||
list.add("test3");
|
||||
@@ -31,14 +30,14 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Compound
|
||||
NBTCompoundList taglist = comp.getCompoundList("complist");
|
||||
NBTListCompound lcomp = taglist.addCompound();
|
||||
ReadWriteNBTCompoundList taglist = comp.getCompoundList("complist");
|
||||
ReadWriteNBT lcomp = taglist.addCompound();
|
||||
lcomp.setDouble("double1", 0.3333);
|
||||
lcomp.setInteger("int1", 42);
|
||||
lcomp.setString("test1", "test1");
|
||||
lcomp.setString("test2", "test2");
|
||||
lcomp.removeKey("test1");
|
||||
NBTCompound subsubcomp = lcomp.addCompound("listsubkey");
|
||||
ReadWriteNBT subsubcomp = lcomp.getOrCreateCompound("listsubkey");
|
||||
subsubcomp.setString("deep", "String");
|
||||
subsubcomp.getCompoundList("deeplist").addCompound().setString("test", "test");
|
||||
subsubcomp.getCompoundList("clonelist").addCompound(comp);
|
||||
@@ -50,31 +49,33 @@ public class ListTest implements Test {
|
||||
taglist = comp.getCompoundList("complist");
|
||||
if (taglist.size() == 1) {
|
||||
lcomp = taglist.get(0);
|
||||
ReadWriteNBT sublist = lcomp.getCompound("listsubkey");
|
||||
if (lcomp.getKeys().size() != 4) {
|
||||
throw new NbtApiException("Wrong key amount in Taglist (" + lcomp.getKeys().size() + ")!");
|
||||
} else if (sublist == null) {
|
||||
throw new NbtApiException("The sublist is null! The Item-NBT-API may not work!");
|
||||
} else if (!(lcomp.getDouble("double1") == 0.3333 && lcomp.getInteger("int1") == 42
|
||||
&& lcomp.getString("test2").equals("test2") && !lcomp.hasTag("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"))) {
|
||||
} else if (!"String".equals(sublist.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) {
|
||||
} else if (sublist.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 if (sublist.getType("deeplist") != NBTType.NBTTagList) {
|
||||
throw new NbtApiException("The nested list's type wasn't correct '" + sublist.getType("deeplist")
|
||||
+ "'! The Item-NBT-API may not work!");
|
||||
}
|
||||
} else {
|
||||
throw new NbtApiException("Taglist is empty! The Item-NBT-API may not work!");
|
||||
}
|
||||
|
||||
if (comp.getListType("complist") != NBTType.NBTTagCompound) {
|
||||
throw new NbtApiException("complist had the wrong type! The Item-NBT-API may not work!");
|
||||
throw new NbtApiException("complist had the wrong type(" + comp.getListType("complist") + ")! The Item-NBT-API may not work!");
|
||||
}
|
||||
|
||||
// Integer
|
||||
NBTList<Integer> intlist = comp.getIntegerList("inttest");
|
||||
ReadWriteNBTList<Integer> intlist = comp.getIntegerList("inttest");
|
||||
intlist.add(42);
|
||||
intlist.add(69);
|
||||
if (intlist.size() == 2 && intlist.get(0) == 42 && intlist.get(1) == 69) {
|
||||
@@ -88,7 +89,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Double
|
||||
NBTList<Double> doublelist = comp.getDoubleList("doubletest");
|
||||
ReadWriteNBTList<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) {
|
||||
@@ -103,7 +104,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Float
|
||||
NBTList<Float> floatlist = comp.getFloatList("floattest");
|
||||
ReadWriteNBTList<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) {
|
||||
@@ -117,7 +118,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// Long
|
||||
NBTList<Long> longlist = comp.getLongList("longtest");
|
||||
ReadWriteNBTList<Long> longlist = comp.getLongList("longtest");
|
||||
longlist.add(1241234124124l);
|
||||
longlist.add(1231454321312l);
|
||||
if (longlist.size() == 2 && longlist.get(0) == 1241234124124l && longlist.get(1) == 1231454321312l) {
|
||||
@@ -131,7 +132,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// int[]
|
||||
NBTList<int[]> intArrayList = comp.getIntArrayList("intatest");
|
||||
ReadWriteNBTList<int[]> intArrayList = comp.getIntArrayList("intatest");
|
||||
intArrayList.add(new int[] { 1, 2, 3 });
|
||||
intArrayList.add(new int[] { 4, 2, 0 });
|
||||
if (intArrayList.size() == 2 && Arrays.equals(new int[] { 1, 2, 3 }, intArrayList.get(0))
|
||||
@@ -146,7 +147,7 @@ public class ListTest implements Test {
|
||||
}
|
||||
|
||||
// UUID
|
||||
NBTList<UUID> uuidList = comp.getUUIDList("uuidtest");
|
||||
ReadWriteNBTList<UUID> uuidList = comp.getUUIDList("uuidtest");
|
||||
uuidList.add(UUID.fromString("fce0323d-7f50-4317-9720-5f6b14cf78ea"));
|
||||
uuidList.add(UUID.fromString("853c80ef-3c37-49fd-aa49-938b674adae6"));
|
||||
if (uuidList.size() == 2 && UUID.fromString("fce0323d-7f50-4317-9720-5f6b14cf78ea").equals(uuidList.get(0))
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class LongArrayTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer comp = new NBTContainer();
|
||||
|
||||
comp.setLongArray("test", new long[] { 1, 2, 3, 4, Long.MAX_VALUE });
|
||||
|
||||
if (!comp.hasTag("test")) {
|
||||
throw new NbtApiException("Wasn't able to check a key! The Item-NBT-API may not work!");
|
||||
}
|
||||
if (!Arrays.equals(comp.getLongArray("test"), new long[] { 1, 2, 3, 4, Long.MAX_VALUE })) {
|
||||
throw new NbtApiException("The long key does not equal the original value! The Item-NBT-API may not work!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ResolveTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ReadWriteNBT src = NBT.createNBTObject();
|
||||
src.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
|
||||
if (src.resolveOrDefault("foo.bar.baz.test", 0) != 42) {
|
||||
throw new NbtApiException("Wasn't able to check the value! The Item-NBT-API may not work!");
|
||||
}
|
||||
if (!Integer.valueOf(42).equals(src.resolveOrNull("foo.bar.baz.test", Integer.class))) {
|
||||
throw new NbtApiException("Wasn't able to check the value! The Item-NBT-API may not work!");
|
||||
}
|
||||
src.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123);
|
||||
if (src.getOrCreateCompound("foo").getOrCreateCompound("some.key").getOrCreateCompound("baz")
|
||||
.getInteger("other") != 123) {
|
||||
throw new NbtApiException("Wasn't able to check the value! The Item-NBT-API may not work!");
|
||||
}
|
||||
ReadWriteNBT comp = src.resolveOrCreateCompound("foo.bar.baz");
|
||||
comp.setIntArray("intarray", new int[] {1,2,3,4,5,6});
|
||||
comp.getStringList("strlist").addAll(Arrays.asList("Hello", "World!"));
|
||||
ReadWriteNBTCompoundList list = comp.getCompoundList("somelist");
|
||||
list.addCompound().setInteger("id", 1);
|
||||
list.addCompound().setInteger("id", 2);
|
||||
list.addCompound().setInteger("id", 3);
|
||||
list.addCompound().setInteger("id", 4);
|
||||
list.addCompound().setInteger("id", 5);
|
||||
list.addCompound().setInteger("id", 6);
|
||||
ReadableNBT listEntry = src.resolveCompound("foo.bar.baz.somelist[0]");
|
||||
if(listEntry == null || listEntry.getInteger("id") != 1) {
|
||||
throw new NbtApiException("The value is not what was expected! The Item-NBT-API may not work!");
|
||||
}
|
||||
ReadableNBT lastEntry = src.resolveOrCreateCompound("foo.bar.baz.somelist[-1]");
|
||||
if(lastEntry == null || lastEntry.getInteger("id") != 6) {
|
||||
throw new NbtApiException("The value is not what was expected! The Item-NBT-API may not work!");
|
||||
}
|
||||
if(src.resolveOrDefault("foo.bar.baz.intarray[1]", 0) != 2) {
|
||||
throw new NbtApiException("The value is not what was expected! The Item-NBT-API may not work!");
|
||||
}
|
||||
if(src.resolveOrNull("foo.bar.baz.intarray[2]", Integer.class) != (Integer)3) {
|
||||
throw new NbtApiException("The value is not what was expected! The Item-NBT-API may not work!");
|
||||
}
|
||||
if(!"World!".equals(src.resolveOrNull("foo.bar.baz.strlist[1]", String.class))) {
|
||||
throw new NbtApiException("The value is not what was expected! The Item-NBT-API may not work!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+15
-6
@@ -3,24 +3,33 @@ package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
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");
|
||||
ReadWriteNBT base = NBT.createNBTObject();
|
||||
base.getOrCreateCompound("sub").setString("hello", "world");
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
base.getCompound("sub").writeCompound(outStream);
|
||||
base.getOrCreateCompound("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())) {
|
||||
ReadWriteNBT container = NBT.readNBT(inputStream);
|
||||
if (!container.toString().equals(base.getOrCreateCompound("sub").toString())) {
|
||||
throw new NbtApiException("Component content did not match! " + base.getCompound("sub") + " " + container);
|
||||
}
|
||||
ItemStack item = new ItemStack(Material.STICK);
|
||||
|
||||
NBT.modify(item, nbt -> {
|
||||
nbt.writeCompound(outStream);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class SubCompoundsTest implements Test {
|
||||
@@ -19,9 +19,9 @@ public class SubCompoundsTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTContainer cont = new NBTContainer();
|
||||
ReadWriteNBT cont = NBT.createNBTObject();
|
||||
|
||||
NBTCompound comp = cont.addCompound(COMP_TEST_KEY);
|
||||
ReadWriteNBT comp = cont.getOrCreateCompound(COMP_TEST_KEY);
|
||||
comp.setString(STRING_TEST_KEY, STRING_TEST_VALUE + "2");
|
||||
comp.setInteger(INT_TEST_KEY, INT_TEST_VALUE * 2);
|
||||
comp.setDouble(DOUBLE_TEST_KEY, DOUBLE_TEST_VALUE * 2);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.compounds;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTContainer;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class TypeTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
NBTCompound comp = new NBTContainer();
|
||||
ReadWriteNBT comp = NBT.createNBTObject();
|
||||
comp.setString("s", "test");
|
||||
comp.setInteger("i", 42);
|
||||
comp.addCompound("c");
|
||||
comp.getOrCreateCompound("c");
|
||||
if (comp.getType("s") != NBTType.NBTTagString || comp.getType("i") != NBTType.NBTTagInt
|
||||
|| comp.getType("c") != NBTType.NBTTagCompound)
|
||||
throw new NbtApiException("One parsed type did not match what it should have been!");
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+11
-10
@@ -6,8 +6,7 @@ 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.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
@@ -23,14 +22,16 @@ public class EntityCustomNbtPersistentTest implements Test {
|
||||
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");
|
||||
NBT.modifyPersistentData(ent, comp -> {
|
||||
comp.setString("Hello", "World");
|
||||
});
|
||||
|
||||
NBT.modifyPersistentData(ent, comp -> {
|
||||
if (!comp.toString().contains("Hello:\"World\"")) {
|
||||
throw new NbtApiException("Custom Data did not save to the Entity!");
|
||||
}
|
||||
comp.removeKey("Hello");
|
||||
});
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
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.hasTag("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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ComponentsTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if(!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return;
|
||||
}
|
||||
ItemStack item = new ItemStack(Material.STICK);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName("test");
|
||||
item.setItemMeta(meta);
|
||||
String comp = NBT.modifyComponents(item, n -> {
|
||||
return n.toString();
|
||||
});
|
||||
if(!comp.contains("test")) {
|
||||
throw new NbtApiException("ReadComponent didn't work!");
|
||||
}
|
||||
NBT.modifyComponents(item, nbt -> {
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R4)) {
|
||||
nbt.mergeCompound(NBT.parseNBT("{\"minecraft:custom_name\":[{\"text\":\"foobar\",\"italic\":false}]}"));
|
||||
} else {
|
||||
nbt.setString("minecraft:custom_name", "{\"extra\":[\"foobar\"],\"text\":\"\"}");
|
||||
}
|
||||
});
|
||||
if(!item.getItemMeta().getDisplayName().equals("foobar")) {
|
||||
throw new NbtApiException("ModifyComponent didn't work!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+6
-1
@@ -4,22 +4,27 @@ import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class DirectApplyMetaTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return; // skip
|
||||
}
|
||||
ItemStack baseItem = new ItemStack(Material.STONE);
|
||||
NBTItem nbti = new NBTItem(baseItem, true);
|
||||
nbti.setString("SomeKey", "SomeValue");
|
||||
nbti.modifyMeta(this::modifyMeta);
|
||||
|
||||
if (!new NBTItem(baseItem).hasTag("SomeKey") || !"SomeValue".equals(baseItem.getItemMeta().getDisplayName())) {
|
||||
throw new NbtApiException("The item was not modified correctly!");
|
||||
throw new NbtApiException("The item was not modified correctly! " + NBT.itemStackToNBT(baseItem));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-1
@@ -25,7 +25,9 @@ public class DirectApplyTest implements Test {
|
||||
});
|
||||
baseItem = NBT.itemStackFromNBT(NBT.itemStackToNBT(baseItem)); // trick to force the item to be "real", not a
|
||||
// Spigot only item
|
||||
String outside = NBT.get(baseItem, nbt -> nbt.getString("SomeKey"));
|
||||
String outside = NBT.get(baseItem, nbt -> {
|
||||
return nbt.getString("SomeKey");
|
||||
});
|
||||
if (!new NBTItem(baseItem).hasTag("SomeKey")) {
|
||||
throw new NbtApiException("The data was not applied!");
|
||||
}
|
||||
|
||||
+46
-1
@@ -3,6 +3,7 @@ package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
@@ -13,8 +14,27 @@ public class EmptyItemTest implements Test {
|
||||
public void test() throws Exception {
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
NBTItem nbti = new NBTItem(item);
|
||||
if (nbti.getBoolean("test") == null || nbti.getString("test") == null)
|
||||
if (nbti.hasNBTData()) {
|
||||
throw new NbtApiException("Item reported to have data");
|
||||
}
|
||||
if (nbti.getBoolean("test") == null || nbti.getString("test") == null || nbti.getFloatList("test") == null) {
|
||||
throw new NbtApiException("Getters return null instead of the default value");
|
||||
}
|
||||
if (!nbti.getKeys().isEmpty()) {
|
||||
throw new NbtApiException("getKeys() returned keys!");
|
||||
}
|
||||
nbti.removeKey("test");
|
||||
if (nbti.hasNBTData()) {
|
||||
throw new NbtApiException("Item reported to have data after remove");
|
||||
}
|
||||
nbti.setString("test", "test");
|
||||
if (!nbti.hasNBTData()) {
|
||||
throw new NbtApiException("Item reported to have no data");
|
||||
}
|
||||
nbti.removeKey("test");
|
||||
if (nbti.hasNBTData()) {
|
||||
throw new NbtApiException("Item reported to have data after deletion");
|
||||
}
|
||||
|
||||
try {
|
||||
Material barrel = Material.valueOf("BARREL");
|
||||
@@ -23,6 +43,31 @@ public class EmptyItemTest implements Test {
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// old version
|
||||
}
|
||||
|
||||
item = new ItemStack(Material.STONE);
|
||||
NBT.modify(item, nbt -> {
|
||||
nbt.setString("test", "test");
|
||||
});
|
||||
NBT.get(item, nbt -> {
|
||||
if (!nbt.hasNBTData()) {
|
||||
throw new NbtApiException("Item reported to have no data");
|
||||
}
|
||||
return nbt.hasNBTData();
|
||||
});
|
||||
NBT.modify(item, nbt -> {
|
||||
nbt.removeKey("test");
|
||||
});
|
||||
NBT.get(item, nbt -> {
|
||||
if (nbt.hasNBTData()) {
|
||||
throw new NbtApiException("Item reported to have data after deletion");
|
||||
}
|
||||
return nbt.hasNBTData();
|
||||
});
|
||||
|
||||
ItemStack testItem = new ItemStack(Material.STONE);
|
||||
NBTItem nbt = new NBTItem(testItem, true);
|
||||
nbt.removeKey("not there");
|
||||
nbt.setBoolean("test", true);
|
||||
}
|
||||
|
||||
}
|
||||
+17
-8
@@ -1,13 +1,15 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTType;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
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;
|
||||
|
||||
@@ -19,16 +21,23 @@ public class ItemConversionTest implements Test {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setLore(Lists.newArrayList("Firest Line", "Second Line"));
|
||||
item.setItemMeta(meta);
|
||||
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));
|
||||
|
||||
ReadWriteNBT nbt = NBT.itemStackToNBT(item);
|
||||
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_12_R1)
|
||||
&& !nbt.hasTag("DataVersion", NBTType.NBTTagInt)) {
|
||||
throw new NbtApiException("The item nbt '" + nbt + "' didn't contain the data version");
|
||||
}
|
||||
|
||||
String nbtString = nbt.toString();
|
||||
if (!nbtString.contains("Firest Line") || !nbtString.contains("Second Line"))
|
||||
throw new NbtApiException("The Item nbt '" + nbtString + "' didn't contain the lore");
|
||||
ItemStack rebuild = NBT.itemStackFromNBT(NBT.parseNBT(nbtString));
|
||||
if (!item.isSimilar(rebuild))
|
||||
throw new NbtApiException("Rebuilt item did not match the original!");
|
||||
|
||||
NBTContainer cont = new NBTContainer();
|
||||
ReadWriteNBT cont = NBT.createNBTObject();
|
||||
cont.setItemStack("testItem", item);
|
||||
if (!cont.getItemStack("testItem").isSimilar(item))
|
||||
if (!item.isSimilar(cont.getItemStack("testItem")))
|
||||
throw new NbtApiException("Rebuilt item did not match the original!");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.NBTJsonUtil;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ItemJsonTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName("test");
|
||||
meta.setUnbreakable(true);
|
||||
item.setItemMeta(meta);
|
||||
JsonElement elem = NBTJsonUtil.itemStackToJson(item);
|
||||
if (elem == null) {
|
||||
throw new NbtApiException("Getting the Json didn't work correctly! " + item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,12 +6,16 @@ import org.bukkit.inventory.meta.BookMeta;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ItemMergingTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return; // skip, there is no vanilla nbt
|
||||
}
|
||||
ItemStack item = new ItemStack(Material.WRITTEN_BOOK);
|
||||
BookMeta bookMeta = (BookMeta) item.getItemMeta();
|
||||
bookMeta.setAuthor("Author");
|
||||
|
||||
+5
-5
@@ -3,9 +3,9 @@ package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class ItemStackConversionTest implements Test {
|
||||
@@ -14,9 +14,9 @@ public class ItemStackConversionTest implements Test {
|
||||
public void test() throws Exception {
|
||||
ItemStack[] src = new ItemStack[] { new ItemStack(Material.STONE), new ItemStack(Material.STICK),
|
||||
new ItemStack(Material.AIR), new ItemStack(Material.STONE) };
|
||||
NBTCompound comp = NBTItem.convertItemArraytoNBT(src);
|
||||
ItemStack[] recreated = NBTItem.convertNBTtoItemArray(comp);
|
||||
if (src.length != recreated.length) {
|
||||
ReadWriteNBT comp = NBT.itemStackArrayToNBT(src);
|
||||
ItemStack[] recreated = NBT.itemStackArrayFromNBT(comp);
|
||||
if (recreated == null || src.length != recreated.length) {
|
||||
throw new NbtApiException("Size did not match!");
|
||||
}
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
import de.tr7zw.changeme.nbtapi.utils.DataFixerUtil;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class LegacyItemTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ItemStack item = NBT
|
||||
.itemStackFromNBT(NBT.parseNBT("{id:cobblestone,Count:42,tag:{Enchantments:[{lvl:3,id:unbreaking}]}}"));
|
||||
if (item.getType() != Material.COBBLESTONE || item.getAmount() != 42
|
||||
|| item.getEnchantmentLevel(Enchantment.DURABILITY) != 3) {
|
||||
throw new NbtApiException("1.20 item didn't load correctly! " + item);
|
||||
}
|
||||
ReadWriteNBT nbt = NBT
|
||||
.parseNBT("{id:cobblestone,Count:42,tag:{display:{Name:\"test\"},ench:[{lvl:3,id:34}]}}");
|
||||
nbt = DataFixerUtil.fixUpItemData(nbt, DataFixerUtil.VERSION1_12_2, DataFixerUtil.getCurrentVersion());
|
||||
item = NBT.itemStackFromNBT(nbt);
|
||||
if (item.getType() != Material.COBBLESTONE || item.getAmount() != 42
|
||||
|| item.getEnchantmentLevel(Enchantment.DURABILITY) != 3
|
||||
|| !"test".equals(item.getItemMeta().getDisplayName())) {
|
||||
throw new NbtApiException("1.12.2 item didn't load correctly! " + item);
|
||||
}
|
||||
|
||||
ItemStack item2 = NBT.itemStackFromNBT(NBT.parseNBT("{DataVersion:" + DataFixerUtil.VERSION1_12_2 + ",id:cobblestone,Count:42,tag:{display:{Name:\"test\"},ench:[{lvl:3,id:34}]}}"));
|
||||
if (!item.equals(item2))
|
||||
throw new NbtApiException("Data-fixed 1.12.2 item didn't load correctly! " + item2);
|
||||
|
||||
ReadWriteNBT testNBT = NBT.parseNBT("{id:cobblestone,Count:42,tag:{display:{Name:\"test\"},ench:[{lvl:3,id:34}]},DataVersion:1343}");
|
||||
testNBT = DataFixerUtil.fixUpItemData(testNBT, DataFixerUtil.VERSION1_12R1);
|
||||
if (testNBT.getInteger("DataVersion") != DataFixerUtil.getCurrentVersion())
|
||||
throw new NbtApiException("DataVersion wasn't updated correctly! " + testNBT);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class MetaTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
return; // skip
|
||||
}
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
NBT.modify(item, nbt -> {
|
||||
nbt.setInteger("HideFlags", 1);
|
||||
nbt.modifyMeta((rnbt, meta) -> {
|
||||
if (!meta.hasItemFlag(ItemFlag.HIDE_ENCHANTS) || rnbt.getInteger("HideFlags") != 1) {
|
||||
throw new NbtApiException("The meta did not correctly update or read! " + rnbt);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class NBTModifyItemTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ItemStack baseItem = new ItemStack(Material.STONE);
|
||||
NBT.modify(baseItem, nbti -> {
|
||||
nbti.setString("SomeKey", "SomeValue");
|
||||
});
|
||||
if (baseItem.equals(new ItemStack(Material.STONE)) || !new NBTItem(baseItem).hasTag("SomeKey")) {
|
||||
throw new NbtApiException("The item's where not equal!");
|
||||
}
|
||||
baseItem = new ItemStack(Material.STONE);
|
||||
// test using a "real" item
|
||||
baseItem = NBT.itemStackFromNBT(NBT.itemStackToNBT(baseItem));
|
||||
String inside = NBT.modify(baseItem, nbt -> {
|
||||
nbt.setString("SomeKey", "SomeValue");
|
||||
nbt.modifyMeta((r, meta) -> {
|
||||
meta.setDisplayName("Test");
|
||||
});
|
||||
nbt.getOrCreateCompound("sub").setInteger("val", 42);
|
||||
return nbt.getString("SomeKey");
|
||||
});
|
||||
String outside = NBT.get(baseItem, nbt -> {
|
||||
return nbt.getString("SomeKey");
|
||||
});
|
||||
if (baseItem == null) {
|
||||
throw new NbtApiException("Base item was null!");
|
||||
}
|
||||
if (!new NBTItem(baseItem).hasTag("SomeKey")) {
|
||||
throw new NbtApiException("The data was not applied!");
|
||||
}
|
||||
if (new NBTItem(baseItem).getOrCreateCompound("sub").getInteger("val") != 42) {
|
||||
throw new NbtApiException("The sub value was not applied!");
|
||||
}
|
||||
if (!"SomeValue".equals(inside)) {
|
||||
throw new NbtApiException("Inside returned the wrong value!");
|
||||
}
|
||||
if (!"SomeValue".equals(outside)) {
|
||||
throw new NbtApiException("Outside returned the wrong value!");
|
||||
}
|
||||
if (!"Test".equals(baseItem.getItemMeta().getDisplayName())) {
|
||||
throw new NbtApiException("The display name was not applied!");
|
||||
}
|
||||
baseItem = new ItemStack(Material.STONE);
|
||||
// test using a "fake" item
|
||||
inside = NBT.modify(baseItem, nbt -> {
|
||||
nbt.setString("SomeKey", "SomeValue");
|
||||
nbt.modifyMeta((r, meta) -> {
|
||||
meta.setDisplayName("Test");
|
||||
});
|
||||
nbt.getOrCreateCompound("sub").setInteger("val", 42);
|
||||
return nbt.getString("SomeKey");
|
||||
});
|
||||
outside = NBT.get(baseItem, nbt -> (String) nbt.getString("SomeKey"));
|
||||
if (!new NBTItem(baseItem).hasTag("SomeKey")) {
|
||||
throw new NbtApiException("The data was not applied!");
|
||||
}
|
||||
if (new NBTItem(baseItem).getOrCreateCompound("sub").getInteger("val") != 42) {
|
||||
throw new NbtApiException("The sub value was not applied!");
|
||||
}
|
||||
if (!"SomeValue".equals(inside)) {
|
||||
throw new NbtApiException("Inside returned the wrong value!");
|
||||
}
|
||||
if (!"SomeValue".equals(outside)) {
|
||||
throw new NbtApiException("Outside returned the wrong value!");
|
||||
}
|
||||
if (!"Test".equals(baseItem.getItemMeta().getDisplayName())) {
|
||||
throw new NbtApiException("The display name was not applied!");
|
||||
}
|
||||
// other ordering
|
||||
baseItem = new ItemStack(Material.STONE);
|
||||
NBT.modify(baseItem, nbti -> {
|
||||
nbti.setString("a", "SomeValue");
|
||||
});
|
||||
NBT.modify(baseItem, nbt -> {
|
||||
nbt.modifyMeta((r, meta) -> {
|
||||
meta.setDisplayName("Test");
|
||||
});
|
||||
nbt.setInteger("b", 12);
|
||||
});
|
||||
if (!new NBTItem(baseItem).hasTag("a") || !new NBTItem(baseItem).hasTag("b")
|
||||
|| !"Test".equals(baseItem.getItemMeta().getDisplayName())) {
|
||||
throw new NbtApiException("The data was not applied: " + new NBTItem(baseItem).toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.items;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTList;
|
||||
import de.tr7zw.changeme.nbtapi.iface.ReadableNBTList;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class SmuggleTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
Exception error = null;
|
||||
try {
|
||||
ReadWriteNBTList<Long> list = NBT.modify(item, nbt -> {
|
||||
nbt.getLongList("test").add(123l);
|
||||
return nbt.getLongList("test");
|
||||
});
|
||||
error = new NbtApiException("Managed to smuggle nbt out of the context: " + list);
|
||||
} catch (Exception e) {
|
||||
// this is the excpected behavior
|
||||
}
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
try {
|
||||
ReadableNBTList<Long> list = NBT.get(item, nbt -> {
|
||||
return nbt.getLongList("test");
|
||||
});
|
||||
error = new NbtApiException("Managed to smuggle nbt out of the context: " + list);
|
||||
} catch (Exception e) {
|
||||
// this is the excpected behavior
|
||||
}
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
AtomicReference<ReadableNBTList<Long>> list = new AtomicReference<>();
|
||||
try {
|
||||
NBT.get(item, nbt -> {
|
||||
list.set(nbt.getLongList("test")); // smuggling the nbt out of the context
|
||||
return null;
|
||||
});
|
||||
if (list.get().size() == 1) {
|
||||
error = new NbtApiException("Managed to smuggle nbt out of the context: " + list);
|
||||
}
|
||||
error = new NbtApiException("Managed to smuggle nbt out of the context: " + list);
|
||||
} catch (Exception e) {
|
||||
// this is the excpected behavior
|
||||
}
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
//package de.tr7zw.nbtapi.plugin.tests.proxy;
|
||||
//
|
||||
//import org.bukkit.Material;
|
||||
//import org.bukkit.inventory.ItemStack;
|
||||
//import org.bukkit.inventory.meta.ItemMeta;
|
||||
//
|
||||
//import de.tr7zw.changeme.nbtapi.NBT;
|
||||
//import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
//import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
//import de.tr7zw.changeme.nbtapi.data.proxy.NBTItemMeta;
|
||||
//import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
|
||||
//import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
//import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
//
|
||||
//public class DataItemProxyTest implements Test {
|
||||
//
|
||||
// @Override
|
||||
// public void test() throws Exception {
|
||||
// if(MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
|
||||
// return; // skip
|
||||
// }
|
||||
// ItemStack item = new ItemStack(Material.STONE);
|
||||
// ItemMeta meta = item.getItemMeta();
|
||||
// meta.setDisplayName("Test");
|
||||
// item.setItemMeta(meta);
|
||||
// NBT.modify(item, NBTItemMeta.class, nmeta -> {
|
||||
// nmeta.setCustomModelData(123);
|
||||
// nmeta.setUnbreakable(true);
|
||||
// if (!nmeta.getDisplayData().getRawName().contains("Test")) {
|
||||
// throw new NbtApiException("Raw name didn't containg the expected String: " + nmeta);
|
||||
// }
|
||||
// ReadWriteNBT container = NBT.createNBTObject();
|
||||
// container.setString("foo", "bar");
|
||||
// nmeta.setBlockStateTag(container);
|
||||
// if (!container.equals(nmeta.getBlockStateTag())) {
|
||||
// throw new NbtApiException("BlockStateTag did not match! " + nmeta);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
|
||||
// meta = item.getItemMeta();
|
||||
// if (!meta.hasCustomModelData() || meta.getCustomModelData() != 123) {
|
||||
// throw new NbtApiException("Custom Model Data did not match! " + new NBTItem(item));
|
||||
// }
|
||||
// if (!meta.isUnbreakable()) {
|
||||
// throw new NbtApiException("Unbreakable did not set!");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package de.tr7zw.nbtapi.plugin.tests.proxy;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.handler.NBTHandlers;
|
||||
import de.tr7zw.changeme.nbtapi.wrapper.NBTProxy;
|
||||
import de.tr7zw.changeme.nbtapi.wrapper.NBTTarget;
|
||||
import de.tr7zw.changeme.nbtapi.wrapper.ProxyList;
|
||||
import de.tr7zw.changeme.nbtapi.wrapper.NBTTarget.Type;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
|
||||
public class SimpleProxyTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
NBT.modify(item, TestInterface.class, ti -> {
|
||||
if (ti.hasKills()) {
|
||||
throw new NbtApiException("Item reported to have kills before setting data!");
|
||||
}
|
||||
ti.setKills(42);
|
||||
ti.addKill();
|
||||
if (!ti.hasKills()) {
|
||||
throw new NbtApiException("Item reported to not have kills after setting data!");
|
||||
}
|
||||
if (!"{Kills:43}".equals(ti.toString())) {
|
||||
throw new NbtApiException("ToString returned the wrong string. " + ti.toString());
|
||||
}
|
||||
});
|
||||
if (new NBTItem(item).getInteger("Kills") != 43) {
|
||||
throw new NbtApiException("The item was not modified correctly by the proxy!");
|
||||
}
|
||||
NBT.modify(item, TestInterface.class, ti -> {
|
||||
if (ti.theKillsWithADifferentMethodNameAndNoGet() != 43) {
|
||||
throw new NbtApiException("The annotation didn't work correctly!");
|
||||
}
|
||||
Statistic jumps = ti.getJumps();
|
||||
jumps.setPoints(9000);
|
||||
jumps.addPoint();
|
||||
if (ti.getJumps().getPoints() != 9001) {
|
||||
throw new NbtApiException("The stacked proxy didn't work correctly!");
|
||||
}
|
||||
ItemStack stack = new ItemStack(Material.STONE, 42);
|
||||
ti.setItem(stack);
|
||||
if (!stack.equals(ti.getItem())) {
|
||||
throw new NbtApiException("The handler in the proxy didn't work correctly!");
|
||||
}
|
||||
});
|
||||
NBT.modify(item, TestInterface.class, ti -> {
|
||||
Statistic a = ti.getStatistics().addCompound();
|
||||
a.setPoints(1);
|
||||
a.addPoint();
|
||||
a.addPoint();
|
||||
ti.getStatistics().addCompound();
|
||||
if (ti.getStatistics().size() != 2) {
|
||||
throw new NbtApiException("List size not as expected!");
|
||||
}
|
||||
ti.getStatistics().remove(1);
|
||||
if (ti.getStatistics().size() != 1) {
|
||||
throw new NbtApiException("List size not as expected!");
|
||||
}
|
||||
if (ti.getStatistics().iterator().next().getPoints() != 3) {
|
||||
throw new NbtApiException("Points not as expected!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface TestInterface extends NBTProxy {
|
||||
|
||||
@Override
|
||||
default void init() {
|
||||
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
|
||||
}
|
||||
|
||||
public boolean hasKills();
|
||||
|
||||
public void setKills(int amount);
|
||||
|
||||
public int getKills();
|
||||
|
||||
public default void addKill() {
|
||||
setKills(getKills() + 1);
|
||||
}
|
||||
|
||||
@NBTTarget(value = "Kills", type = Type.GET)
|
||||
public int theKillsWithADifferentMethodNameAndNoGet();
|
||||
|
||||
public Statistic getJumps();
|
||||
|
||||
public ItemStack getItem();
|
||||
|
||||
public void setItem(ItemStack item);
|
||||
|
||||
public ProxyList<Statistic> getStatistics();
|
||||
|
||||
}
|
||||
|
||||
public interface Statistic extends NBTProxy {
|
||||
public void setPoints(int amount);
|
||||
|
||||
public int getPoints();
|
||||
|
||||
public default void addPoint() {
|
||||
setPoints(getPoints() + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NBTTileEntity;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
@@ -14,13 +15,24 @@ public class TileTest implements Test {
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
if (MinecraftVersion.isFoliaPresent()) {
|
||||
return;
|
||||
}
|
||||
if (!Bukkit.getWorlds().isEmpty()) {
|
||||
World world = Bukkit.getWorlds().get(0);
|
||||
try {
|
||||
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 254,
|
||||
world.getSpawnLocation().getBlockZ());
|
||||
if (block.getType() == Material.AIR) {
|
||||
if (world.isChunkLoaded(block.getX() >> 4, block.getZ() >> 4) && block.getType() == Material.AIR) {
|
||||
block.setType(Material.CHEST);
|
||||
if (MinecraftVersion.isNewerThan(MinecraftVersion.MC1_21_R1)) {
|
||||
// 1.21 changed the lock logic. So just try to get/set data, dont check for now
|
||||
NBT.modify(block.getState(), nbt -> {
|
||||
nbt.setString("foo", "bar");
|
||||
});
|
||||
block.setType(Material.AIR);
|
||||
return;
|
||||
}
|
||||
NBTTileEntity tile = new NBTTileEntity(block.getState());
|
||||
if (!MinecraftVersion.isNewerThan(MinecraftVersion.MC1_17_R1)) {
|
||||
if (tile.getInteger("y") != 254) {
|
||||
|
||||
+15
-11
@@ -5,8 +5,7 @@ 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.NBT;
|
||||
import de.tr7zw.changeme.nbtapi.NbtApiException;
|
||||
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
|
||||
import de.tr7zw.nbtapi.plugin.tests.Test;
|
||||
@@ -17,21 +16,26 @@ public class TilesCustomNBTPersistentTest implements Test {
|
||||
public void test() throws Exception {
|
||||
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_14_R1.getVersionId())
|
||||
return;
|
||||
if (MinecraftVersion.isFoliaPresent()) {
|
||||
return;
|
||||
}
|
||||
if (!Bukkit.getWorlds().isEmpty()) {
|
||||
World world = Bukkit.getWorlds().get(0);
|
||||
try {
|
||||
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 250,
|
||||
world.getSpawnLocation().getBlockZ());
|
||||
if (block.getType() == Material.AIR) {
|
||||
if (world.isChunkLoaded(block.getX() >> 4, block.getZ() >> 4) && 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().getString("Foo")
|
||||
.equals("Bar")) {
|
||||
block.setType(Material.AIR);
|
||||
throw new NbtApiException("Custom Data did not save to the Tile!");
|
||||
}
|
||||
NBT.modifyPersistentData(block.getState(), persistentData -> {
|
||||
persistentData.setString("Foo", "Bar");
|
||||
});
|
||||
NBT.getPersistentData(block.getState(), persistentData -> {
|
||||
if (!persistentData.getString("Foo").equals("Bar")) {
|
||||
block.setType(Material.AIR);
|
||||
throw new NbtApiException("Custom Data did not save to the Tile!");
|
||||
}
|
||||
return null;
|
||||
});
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
||||
Whitespace-only changes.
@@ -3,4 +3,5 @@ name: NBTAPI
|
||||
version: ${project.version}
|
||||
author: tr7zw
|
||||
loadbefore: [ItemNBTAPI]
|
||||
api-version: 1.13
|
||||
api-version: 1.13
|
||||
folia-supported: true
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-parent</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<version>2.16.0</version>
|
||||
</parent>
|
||||
<artifactId>mappings-parser</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -12,7 +12,7 @@
|
||||
<dependency>
|
||||
<groupId>de.tr7zw</groupId>
|
||||
<artifactId>item-nbt-api</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<version>2.16.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -3,13 +3,13 @@ package dev.tr7zw.mappingsparser;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.MojangToMapping;
|
||||
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
|
||||
|
||||
/**
|
||||
@@ -24,7 +24,7 @@ public class MappingsParser {
|
||||
public static StringBuilder builder = new StringBuilder();
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
File input = new File("minecraft_server.1.20.txt");
|
||||
File input = new File("minecraft_server.1.21.9.txt");
|
||||
List<String> lines = Files.readAllLines(input.toPath());
|
||||
|
||||
Map<String, ClassWrapper> classes = new HashMap<>();
|
||||
@@ -40,6 +40,9 @@ public class MappingsParser {
|
||||
ClassWrapper nmsWrapper = null;
|
||||
Map<ReflectionMethod, String> mappedNames = null;
|
||||
for (String line : lines) {
|
||||
if (line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
if (!line.startsWith(" ")) {
|
||||
if (nmsWrapper != null && mappedNames != null) {
|
||||
proccessMapping(nmsWrapper, mappedNames);
|
||||
@@ -59,17 +62,46 @@ public class MappingsParser {
|
||||
mojangName = line.trim().split(" ")[1];
|
||||
unmappedName = line.trim().split(" ")[3];
|
||||
classes.remove(currentClass);
|
||||
for (ReflectionMethod method : mappedNames.keySet()) {
|
||||
if (method.getSelectedVersionInfo() == null)
|
||||
continue;
|
||||
if (!mojangName.contains("("))
|
||||
continue;
|
||||
if (mojangName.equals(method.getSelectedVersionInfo().name)) {
|
||||
mappedNames.put(method, unmappedName);
|
||||
if (mappedNames != null) {
|
||||
for (ReflectionMethod method : mappedNames.keySet()) {
|
||||
if (method.getSelectedVersionInfo() == null)
|
||||
continue;
|
||||
if (!mojangName.contains("("))
|
||||
continue;
|
||||
if (mojangName.equals(method.getSelectedVersionInfo().name)) {
|
||||
mappedNames.put(method, unmappedName);
|
||||
}
|
||||
}
|
||||
}
|
||||
// System.out.println(currentClass + ": " + mojangName + " -> " + unmappedName);
|
||||
}
|
||||
for(String type : MojangToMapping.getMapping().keySet()) {
|
||||
if(type.contains("(")) {
|
||||
continue;
|
||||
}
|
||||
// Field
|
||||
String clazz = type.split("#")[0];
|
||||
String fieldName = type.split("#")[1];
|
||||
for (String line : lines) {
|
||||
if (line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
if (!line.startsWith(" ")) {
|
||||
currentClass = line.split(" ")[0];
|
||||
continue;
|
||||
}
|
||||
mojangName = line.trim().split(" ")[1];
|
||||
unmappedName = line.trim().split(" ")[3];
|
||||
if (currentClass.equals(clazz) && mojangName.equals(fieldName)) {
|
||||
if (MojangToMapping.getMapping().get(type) == null) {
|
||||
System.out.println("Missing mapping for " + type);
|
||||
} else if (!MojangToMapping.getMapping().get(type)
|
||||
.equals(unmappedName)) {
|
||||
builder.append("put(\"" + type + "\", \"" + unmappedName + "\");\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(builder);
|
||||
}
|
||||
|
||||
@@ -79,6 +111,8 @@ public class MappingsParser {
|
||||
System.out.println(
|
||||
"Missing mapping in class " + nmsWrapper.getMojangName() + " method " + entry.getKey().name());
|
||||
} else {
|
||||
if(!entry.getValue().equals(MojangToMapping.getMapping().get(nmsWrapper.getMojangName() + "#"
|
||||
+ entry.getKey().getSelectedVersionInfo().name)))
|
||||
builder.append("put(\"" + nmsWrapper.getMojangName() + "#"
|
||||
+ entry.getKey().getSelectedVersionInfo().name + "\", \"" + entry.getValue() + "\");\n");
|
||||
}
|
||||
|
||||
Loaded 100 of 119 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user