Compare commits

..
145 Commits
Author SHA1 Message Date
tr7zw ae98859524 Tag 2.14.1 2024-12-16 17:11:16 +01:00
tr7zw 70f0bb62f9 Add Util to get ItemStacks in Json Format for hover components 2024-12-14 21:58:53 +01:00
tr7zw e2e8aad70a Merge pull request #310 from ArmyFury/patch-1
Update Plugins.md
2024-12-07 13:17:51 +00:00
ArmyFury 4874366e30 Update Plugins.md
added SummonFriendlyMobs to plugins list
2024-12-07 12:47:39 +05:30
tr7zw d2de90ee25 Add 1.21.4 support 2024-12-03 23:28:21 +01:00
tr7zw b339c9e9c2 Merge pull request #306 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.11.1
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.1 to 3.11.1
2024-11-13 23:54:08 +01:00
tr7zw 3425a6672d Merge pull request #308 from SoSeDiK/wiki-changes
Update wiki
2024-11-13 23:53:54 +01:00
tr7zw 67616266da Start snapshots 2.14.1 2024-11-13 23:53:07 +01:00
SoSeDiK b08e4aa12f Update wiki to reflect some 2.14.0 changes
ItemMeta usage clarifications
2024-11-12 14:28:06 +02:00
dependabot[bot] 27411e90da Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.1 to 3.11.1
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.1 to 3.11.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 23:48:38 +00:00
tr7zw 73776cfec4 Sneak quick fix into release 2024-11-02 15:18:16 +01:00
tr7zw bd674e31c0 Tag 2.14.0 2024-11-02 15:07:50 +01:00
tr7zw 3405ffe0a3 Fix javadoc deploy 2024-11-02 13:24:22 +01:00
tr7zw f1317bcb04 Fix BlockEntity test. Fix #304 2024-11-02 13:06:19 +01:00
tr7zw 4a32343b95 Add 1.21.3 2024-10-28 18:56:04 +01:00
tr7zw 3de6ed83eb Hide NBTFile/NBTContainer fully behind NBT. Update tests to new format. Add missing addCompound(ReadableNBT comp) to ReadWriteNBTCompoundList 2024-10-22 23:45:16 +02:00
tr7zw e5bdce73ea Merge pull request #300 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.10.1
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.0 to 3.10.1
2024-10-22 22:42:25 +02:00
tr7zw 410e88a35b Add getComponents methods 2024-10-22 22:39:35 +02:00
tr7zw e3142b4869 Add 1.21.2 support 2024-10-22 22:24:59 +02:00
tr7zw 243a5c2bcd Fix really stupid edge case of writeCompound 2024-10-22 22:08:04 +02:00
dependabot[bot] 045c710366 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.0 to 3.10.1
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.0 to 3.10.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.0...maven-javadoc-plugin-3.10.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-01 23:20:24 +00:00
tr7zw 4cd118671f Merge pull request #297 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.10.0
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.8.0 to 3.10.0
2024-08-27 23:03:05 +02:00
dependabot[bot] d86c91f2e6 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.8.0 to 3.10.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.8.0 to 3.10.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.8.0...maven-javadoc-plugin-3.10.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-27 16:08:01 +00:00
tr7zw f8736c8188 Also update old items with "Count" tags 2024-08-27 18:07:27 +02:00
tr7zw b3aec54205 Start 2.13.3-SNAPSHOT 2024-08-27 18:06:56 +02:00
tr7zw 0f926998f6 Tag 2.13.2 2024-08-10 20:28:54 +02:00
tr7zw 3a44a5e989 Add 1.21.1 Paper support 2024-08-10 20:21:32 +02:00
tr7zw 30b931945c Merge pull request #288 from SoSeDiK/chunkload
Prevent chunk loading during tile entity tests
2024-08-10 20:20:58 +02:00
tr7zw 88d8629541 Merge pull request #290 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.8.0
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0
2024-07-21 20:56:57 +02:00
dependabot[bot] 00ae0448f4 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.7.0...maven-javadoc-plugin-3.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-21 18:53:26 +00:00
tr7zw ce26e180e6 Merge branch 'master' of https://github.com/tr7zw/Item-NBT-API 2024-07-21 20:51:52 +02:00
tr7zw c939105e45 Start 2.13.2-SNAPSHOT 2024-07-21 20:51:48 +02:00
tr7zw 2079123a42 Merge pull request #287 from SoSeDiK/wiki
Small wiki changes
2024-07-21 20:48:08 +02:00
SoSeDiK 31b17fe9c9 Update wiki
- Fix broken (block-)entities link in sidebar
- Change "(block)-entities" to "entities and block entities" in titles to better reflect title in links
- Move repository above artifact in Maven/Gradle usage
- Add info about preloadApi
- Add title for ItemMeta usage
- Small text changes
2024-07-01 15:53:10 +03:00
SoSeDiK b565902006 Prevent chunk loading during tile entity tests 2024-07-01 15:20:52 +03:00
tr7zw 5280ba82a2 Tag 2.13.1 2024-06-20 22:37:58 +02:00
tr7zw 522f732ed1 Fix wiki and update the datafixer 2024-06-20 22:34:21 +02:00
tr7zw ac84a4d69a Fix another dead link 2024-06-20 22:20:04 +02:00
tr7zw d7e18c1cb6 Fix dead link 2024-06-20 22:18:41 +02:00
tr7zw ffa612634a Merge pull request #282 from SoSeDiK/wiki
Update wiki
2024-06-20 22:13:01 +02:00
tr7zw 739682122b Remove the usage of the word "tile" entity 2024-06-20 22:07:38 +02:00
tr7zw 2e20af40e5 Add NBT.preloadApi 2024-06-20 21:39:39 +02:00
SoSeDiK e6527515be Update Maven/Gradle usage 2024-06-17 01:05:07 +03:00
SoSeDiK e6f33a35ae Small clarifications/grammar 2024-06-17 01:05:07 +03:00
SoSeDiK 39801ada18 Update saving entity nbt example 2024-06-17 01:05:07 +03:00
SoSeDiK 75fab7622a Update examples 2024-06-17 01:05:07 +03:00
tr7zw 33eef1bcf1 Update FAQ.md 2024-06-17 01:05:07 +03:00
SoSeDiK 877a42fd06 Even more TODOs 2024-06-17 01:05:07 +03:00
SoSeDiK 0a7e560e2e Fill out some TODOs 2024-06-17 01:05:07 +03:00
SoSeDiK 174728a681 mvn spottless:apply 2024-06-17 01:05:07 +03:00
SoSeDiK 79ba1dd275 [WIP] Started updating wiki 2024-06-17 01:05:07 +03:00
tr7zw 25c59b0eae Fix build 2024-06-16 22:51:48 +02:00
tr7zw 0057d3f2e8 Remove nbtinjector/dataapi from the build 2024-06-16 00:35:20 +02:00
tr7zw 59c67a3f0b Remove unused code/private some methods/classes 2024-06-16 00:31:36 +02:00
tr7zw 3ec606ae21 Disable old method mappings 2024-06-15 23:39:40 +02:00
tr7zw ff0a94f279 Add nullable flag 2024-06-15 23:27:41 +02:00
tr7zw 53216d3b7d Overwrite resolveCompound to be ReadWriteNBT 2024-06-15 23:06:38 +02:00
tr7zw 7cf23201ce Hotfix Paper 1.21 2024-06-14 21:30:01 +02:00
tr7zw fe1d586f44 Start 2.13.1 snapshots 2024-06-14 12:33:35 +02:00
tr7zw 956ef15a1d Bump version 2024-06-13 21:15:01 +02:00
tr7zw ed867749f8 Delete data api/injector logic 2024-06-13 20:56:49 +02:00
tr7zw 88fbc0140e Remove nbt-injector and nbt-data-api 2024-06-13 20:48:36 +02:00
tr7zw 82e52267b8 More deprecation, use the NBT class 2024-06-13 20:27:23 +02:00
tr7zw c16548ff4e New "modifyComponents" api 2024-06-13 20:26:39 +02:00
tr7zw cf30cf996e Update to 1.21 2024-06-13 19:56:59 +02:00
tr7zw 633433d6d0 Merge pull request #278 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.6.0
Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.3 to 3.6.0
2024-06-08 21:02:14 +02:00
tr7zw 153c72818a Merge pull request #279 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.7.0
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.3 to 3.7.0
2024-06-08 21:02:06 +02:00
dependabot[bot] 4798880a53 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.3 to 3.7.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.3 to 3.7.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-31 23:20:47 +00:00
dependabot[bot] 1f149dbae4 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.3 to 3.6.0
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.3 to 3.6.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.3...maven-shade-plugin-3.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-31 23:20:38 +00:00
tr7zw 8570c6f77e Improve error when trying to get NBT from non BlockEntity BlockStates. Fix #276 2024-05-19 01:07:24 +02:00
tr7zw 30f75e0714 Deprecate usage of NBTItem/NBTEntity/NBTTileEntity 2024-05-19 00:55:15 +02:00
tr7zw af7a6b0a1c Start 2.12.5-SNAPSHOT 2024-05-19 00:47:46 +02:00
tr7zw c0a9197113 Tag 2.12.4 2024-04-30 15:27:10 +02:00
tr7zw e14dd4f82a Add 1.20.6 2024-04-30 00:13:20 +02:00
tr7zw 198dbfabae Fix wiki page 2024-04-29 19:46:11 +02:00
tr7zw 8bd49db49b Fix incorrect MojangMapping, breaking on mojmapped servers like paper 1.20.5 2024-04-28 19:30:10 +02:00
tr7zw caf1d7cd98 Add utility method to get the current versions DataFixer id 2024-04-25 18:57:12 +02:00
tr7zw 027f2a2edd Add more version ids, test loading 1.12.2 items in 1.20.5 2024-04-25 18:39:40 +02:00
tr7zw b74b0b852e Pull down the 1.20.4 id 2024-04-25 18:04:39 +02:00
tr7zw 6ea6ab7e13 Bump the datafixer id to the actual 1.20.5 id 2024-04-25 18:03:59 +02:00
tr7zw 372225626c Use an older datafixerupper for compiling 2024-04-24 16:04:03 +02:00
tr7zw 2483f9b947 Add Datafixer. Auto update 1.20.4 items to 1.20.5 2024-04-24 15:59:20 +02:00
tr7zw fdc16aad69 Fix issues on older versions 2024-04-24 01:47:21 +02:00
tr7zw c723eef68b Merge pull request #277 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.5.3
Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.5.3
2024-04-24 01:41:02 +02:00
tr7zw 03299012ac Fix BlockEntities for 1.20.5 2024-04-24 01:40:33 +02:00
dependabot[bot] eabf0a9696 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.5.3
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.2...maven-shade-plugin-3.5.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-23 23:17:03 +00:00
tr7zw 9367942b54 Re-implement gameprofile methods for 1.20.5+ 2024-04-24 00:08:48 +02:00
tr7zw 167487e6ab Deprecate/disable more stuff not applying to 1.20.5 2024-04-23 23:47:49 +02:00
tr7zw 6395dd1964 Disable invalid tests for 1.20.5+ 2024-04-23 23:04:15 +02:00
tr7zw d3ef690f2e Fix version mapping 2024-04-23 22:56:44 +02:00
tr7zw 012f32dca9 Start update to 1.20.5 2024-04-23 22:55:50 +02:00
tr7zw 0b8d5b153c Merge pull request #273 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-source-plugin-3.3.1
Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1
2024-04-06 18:54:51 +02:00
tr7zw 246e3fa38e Start 2.12.4-SNAPSHOT 2024-04-06 18:54:26 +02:00
dependabot[bot] 19777de6d4 Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1
Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-04 23:45:13 +00:00
tr7zw 3afd9df2ae Tag 2.12.3 2024-03-24 17:27:30 +01:00
tr7zw 2cb16ed0c4 Merge pull request #270 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.13.0
Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.1 to 3.13.0
2024-03-21 21:38:09 +01:00
dependabot[bot] ac64acf271 Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.1 to 3.13.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 23:52:09 +00:00
tr7zw 85cc13a817 Update wiki code 2024-03-18 19:45:36 +01:00
tr7zw 75c8575b5b Merge pull request #267 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.5.2
Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.1 to 3.5.2
2024-02-22 19:56:42 +01:00
dependabot[bot] 67557d5f94 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.1 to 3.5.2
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.1...maven-shade-plugin-3.5.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-20 23:24:58 +00:00
tr7zw 330fb7711c Turns out Map.of is Java 9... 2024-02-13 00:22:48 +01:00
tr7zw e7f48c72bd Add marker that paper doesn't need to remap the nbtapi 2024-02-12 17:48:59 +01:00
tr7zw 3eefb1d315 Add support for un-remapped Paper 1.20+ 2024-02-12 16:55:16 +01:00
tr7zw a37a2c6729 Merge pull request #265 from tr7zw/dependabot/maven/org.codehaus.mojo-license-maven-plugin-2.4.0
Bump org.codehaus.mojo:license-maven-plugin from 2.3.0 to 2.4.0
2024-01-24 00:43:02 +01:00
dependabot[bot] e42fad0761 Bump org.codehaus.mojo:license-maven-plugin from 2.3.0 to 2.4.0
Bumps [org.codehaus.mojo:license-maven-plugin](https://github.com/mojohaus/license-maven-plugin) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/mojohaus/license-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/license-maven-plugin/compare/2.3.0...2.4.0)

---
updated-dependencies:
- dependency-name: org.codehaus.mojo:license-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-23 23:42:13 +00:00
tr7zw eee2dfa181 Merge pull request #264 from SmartGecko44/master
Update LICENSE copyright to 2024
2024-01-01 16:10:25 +01:00
Gecko! 4728449294 Update LICENSE copyright to 2024 2024-01-01 15:07:02 +01:00
tr7zw ccd78d1b00 Merge pull request #263 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.12.1
Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.0 to 3.12.1
2023-12-27 22:17:53 +01:00
dependabot[bot] 83bea69710 Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.0 to 3.12.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.0...maven-compiler-plugin-3.12.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 23:36:12 +00:00
tr7zw 87fd1ee8ee Merge pull request #261 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.12.0
Bump org.apache.maven.plugins:maven-compiler-plugin from 3.11.0 to 3.12.0
2023-12-19 19:50:31 +01:00
tr7zw af0528328f Start 2.12.3-SNAPSHOT 2023-12-19 19:50:04 +01:00
dependabot[bot] 86c802e2db Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 23:26:00 +00:00
tr7zw 7bf91d0510 2.12.2 release 2023-12-10 14:27:42 +01:00
tr7zw aed5af12a2 Add 1.20.4 support 2023-12-08 21:41:03 +01:00
tr7zw dd6e9e8312 Merge pull request #258 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.6.3
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3
2023-12-05 16:23:22 +01:00
dependabot[bot] 42871b6c06 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.2 to 3.6.3.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.2...maven-javadoc-plugin-3.6.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 23:53:19 +00:00
tr7zw 4ad7a172a0 Merge pull request #256 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.6.2
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2
2023-11-11 17:26:34 +01:00
tr7zw 6f112c0130 Start 2.12.2-SNAPSHOT 2023-11-11 17:26:02 +01:00
dependabot[bot] 5a948f017a Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.0 to 3.6.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.0...maven-javadoc-plugin-3.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 23:25:24 +00:00
tr7zw f5a1b21761 Tag 2.12.1 2023-11-04 17:49:07 +01:00
tr7zw 4af722752e Use the correct mappings for 1.19.4. Fix #254 2023-11-03 21:21:47 +01:00
tr7zw af3b7a49d0 Fix Version Id of 1.20R2 2023-10-26 21:11:57 +02:00
tr7zw 189ff2f369 Merge pull request #253 from tr7zw/dependabot/maven/org.codehaus.mojo-license-maven-plugin-2.3.0
Bump org.codehaus.mojo:license-maven-plugin from 2.2.0 to 2.3.0
2023-10-25 01:04:49 +02:00
dependabot[bot] ddf8ab3c9b Bump org.codehaus.mojo:license-maven-plugin from 2.2.0 to 2.3.0
Bumps [org.codehaus.mojo:license-maven-plugin](https://github.com/mojohaus/license-maven-plugin) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/mojohaus/license-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/license-maven-plugin/compare/2.2.0...2.3.0)

---
updated-dependencies:
- dependency-name: org.codehaus.mojo:license-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 23:03:14 +00:00
tr7zw a8a81eee83 Merge pull request #250 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.5.1
Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.0 to 3.5.1
2023-10-22 17:44:19 +02:00
tr7zw fb384784f0 Start 2.12.1 snapshots 2023-10-22 17:43:27 +02:00
dependabot[bot] 256abbc500 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.0 to 3.5.1
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-25 23:45:49 +00:00
tr7zw dc333ae25a Release 2.12.0 2023-09-21 23:20:21 +02:00
tr7zw d18adb459d Try to disable jitpack 2023-09-21 23:00:13 +02:00
tr7zw bc914b73bc oops, remove debug code 2023-09-21 20:50:01 +02:00
tr7zw 60172ea2a7 Correct copy paste fail 2023-09-21 20:24:39 +02:00
tr7zw 7b30c1533e Add 1.20.2 support 2023-09-21 20:16:11 +02:00
tr7zw a1c90658f3 Merge pull request #248 from tr7zw/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.6.0
Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.5.0 to 3.6.0
2023-09-19 22:26:41 +02:00
dependabot[bot] 0b0fdeaa60 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.5.0 to 3.6.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.5.0 to 3.6.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.5.0...maven-javadoc-plugin-3.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-15 23:09:02 +00:00
tr7zw d989797453 Add support for ProxyLists 2023-09-15 01:15:11 +02:00
tr7zw c70aefe670 Allow using "[123]" and "[-1]" to navigate lists/arrays for resolve methods
Also god, some of this code needs heavy refactoring
2023-09-14 23:56:45 +02:00
tr7zw 7d0fc09470 Fix formatting 2023-09-13 18:54:02 +02:00
tr7zw 427113e6f0 Add YourKit 2023-09-13 18:50:33 +02:00
tr7zw 20ae1cb178 Document inconsistency of hasNBTData() 2023-09-13 00:20:53 +02:00
tr7zw 83b011fafa Allow passing null into NBTContainer 2023-09-13 00:03:44 +02:00
tr7zw 3affeee151 Remove dead code, simplify remove handling for empty items 2023-09-13 00:01:09 +02:00
tr7zw 06da2114ad Fix getKeys with empty ItemsStacks 2023-09-12 23:52:31 +02:00
tr7zw a3efdc622b Return to snapshots to fix issues with items without nbt 2023-09-12 23:45:59 +02:00
tr7zw 9b60978af6 Tag 2.12.0-RC1 2023-09-08 20:06:14 +02:00
tr7zw 598db19d8d Merge pull request #244 from tr7zw/proxyPrototype
Add Proxy system (Preview)
2023-09-08 19:32:05 +02:00
82 changed files with 2371 additions and 847 deletions

No files matched your search

+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 -1
View File
@@ -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
+11 -2
View File
@@ -1,6 +1,6 @@
# 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
@@ -15,7 +15,7 @@ Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it
## 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
@@ -24,3 +24,12 @@ Import the API [using Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Ma
### Github Stargazers
<img src="https://starchart.cc/tr7zw/Item-NBT-API.svg" alt="stargazers" width="800"/>
### Supported by YourKit
![](https://www.yourkit.com/images/yklogo.png)
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>.
+2 -2
View File
@@ -1,6 +1,6 @@
# (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
@@ -14,7 +14,7 @@ Discord:[![Discord](https://img.shields.io/discord/342814924310970398?color=%237
## 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
+11 -2
View File
@@ -5,12 +5,21 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
</parent>
<artifactId>item-nbt-api</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>datafixerupper</artifactId>
<version>4.0.26</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install javadoc:javadoc</defaultGoal>
<resources>
@@ -23,7 +32,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
@@ -1,7 +1,11 @@
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;
@@ -11,6 +15,7 @@ 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;
@@ -18,6 +23,9 @@ 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.
@@ -25,12 +33,52 @@ import de.tr7zw.changeme.nbtapi.iface.ReadableNBTList;
* @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
@@ -156,9 +204,9 @@ public class NBT {
}
/**
* 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
* 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
@@ -226,6 +274,77 @@ public class NBT {
return ret;
}
/**
* It takes an ItemStack and a Consumer&lt;ReadWriteNBT&gt;, 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&lt;ReadWriteNBT&gt;, 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&lt;ReadWriteNBT&gt;, 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&lt;ReadWriteNBT&gt;, 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
@@ -410,12 +529,70 @@ 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.
*
@@ -19,6 +19,7 @@ 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.PathUtil.PathSegment;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.Forge1710Mappings;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
@@ -102,7 +103,7 @@ public class NBTCompound implements ReadWriteNBT {
}
if (!NBTReflectionUtil.valideCompound(this))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = NBTReflectionUtil.gettoCompount(rootnbttag, this);
Object workingtag = NBTReflectionUtil.getToCompount(rootnbttag, this);
if (readOnly) {
this.readOnlyCache = workingtag;
}
@@ -195,10 +196,6 @@ public class NBTCompound implements ReadWriteNBT {
}
}
protected String getContent(String key) {
return NBTReflectionUtil.getContent(this, key);
}
/**
* Setter
*
@@ -1063,38 +1060,205 @@ public class NBTCompound implements ReadWriteNBT {
@Override
public <T> T resolveOrNull(String key, Class<?> type) {
List<String> keys = PathUtil.splitPath(key);
List<PathSegment> keys = PathUtil.splitPath(key);
NBTCompound tag = this;
for (int i = 0; i < keys.size() - 1; i++) {
tag = tag.getCompound(keys.get(i));
if (tag == null) {
return null;
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.getOrNull(keys.get(keys.size() - 1), type);
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<String> keys = PathUtil.splitPath(key);
List<PathSegment> keys = PathUtil.splitPath(key);
NBTCompound tag = this;
for (int i = 0; i < keys.size() - 1; i++) {
tag = tag.getCompound(keys.get(i));
if (tag == null) {
return defaultValue;
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());
}
}
}
}
return tag.getOrDefault(keys.get(keys.size() - 1), defaultValue);
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<String> keys = PathUtil.splitPath(key);
List<PathSegment> keys = PathUtil.splitPath(key);
NBTCompound tag = this;
for (int i = 0; i < keys.size(); i++) {
tag = tag.getCompound(keys.get(i));
if (tag == null) {
return null;
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;
@@ -1102,12 +1266,25 @@ public class NBTCompound implements ReadWriteNBT {
@Override
public ReadWriteNBT resolveOrCreateCompound(String key) {
List<String> keys = PathUtil.splitPath(key);
List<PathSegment> keys = PathUtil.splitPath(key);
NBTCompound tag = this;
for (int i = 0; i < keys.size(); i++) {
tag = tag.getOrCreateCompound(keys.get(i));
if (tag == null) {
return null;
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;
@@ -1283,7 +1460,7 @@ public class NBTCompound implements ReadWriteNBT {
return false;
}
protected static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
private static boolean isEqual(NBTCompound compA, NBTCompound compB, String key) {
if (compA.getType(key) != compB.getType(key))
return false;
switch (compA.getType(key)) {
@@ -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;
@@ -56,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);
}
@@ -22,6 +22,7 @@ public class NBTContainer extends NBTCompound {
/**
* Creates an empty, standalone NBTCompound
*/
@Deprecated
public NBTContainer() {
super(null, null);
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
@@ -31,11 +32,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!");
@@ -47,7 +50,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);
@@ -58,7 +63,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) {
@@ -40,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) {
@@ -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,7 +13,7 @@ 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;
@@ -23,7 +24,9 @@ public class NBTFile extends NBTCompound {
*
* @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,7 +99,9 @@ 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();
@@ -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));
}
}
@@ -12,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;
@@ -32,10 +33,13 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
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);
}
@@ -130,11 +134,11 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
}
if (ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(originalSrcStack.getClass())) {
Object nmsStack = NBTReflectionUtil.getCraftItemHandle(originalSrcStack);
ReflectionMethod.ITEMSTACK_SET_TAG.run(nmsStack, cachedCompound);
NBTReflectionUtil.setItemStackCompound(nmsStack, cachedCompound);
bukkitItem = originalSrcStack;
} else {
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, cachedCompound);
NBTReflectionUtil.setItemStackCompound(stack, cachedCompound);
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
originalSrcStack.setItemMeta(bukkitItem.getItemMeta());
}
@@ -168,10 +172,10 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
}
if (ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(bukkitItem.getClass())) {
Object nmsStack = NBTReflectionUtil.getCraftItemHandle(bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(nmsStack, compound);
NBTReflectionUtil.setItemStackCompound(nmsStack, compound);
} else {
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound);
NBTReflectionUtil.setItemStackCompound(stack, compound);
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
}
}
@@ -185,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!");
@@ -199,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);
@@ -210,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()));
@@ -225,7 +239,12 @@ 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();
@@ -234,8 +253,14 @@ 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);
@@ -254,7 +279,8 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
}
/**
* Returns true if the item has NBT data.
* 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.
*/
@@ -279,6 +305,10 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
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);
}
}
@@ -312,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));
}
@@ -324,6 +355,7 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
* @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));
@@ -337,6 +369,7 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
* @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);
@@ -365,6 +398,7 @@ public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
* @return ItemStack[] using the {@link NBTCompound}'s data
*/
@Nullable
@Deprecated
public static ItemStack[] convertNBTtoItemArray(NBTCompound comp) {
if (!comp.hasTag("size")) {
return null;
@@ -6,21 +6,23 @@ 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.Set;
import java.util.UUID;
import javax.annotation.Nonnull;
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 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.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.MojangToMapping;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
@@ -36,6 +38,8 @@ 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;
static {
try {
@@ -50,6 +54,21 @@ public class NBTReflectionUtil {
} catch (NoSuchFieldException e) {
}
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
try {
Field typeField = ClassWrapper.NMS_DATACOMPONENTS.getClazz().getDeclaredField(
MojangToMapping.getMapping().get("net.minecraft.core.component.DataComponents#CUSTOM_DATA"));
type_custom_data = typeField.get(null);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
}
try {
Object nmsServer = ReflectionMethod.NMSSERVER_GETSERVER.run(Bukkit.getServer());
registry_access = ReflectionMethod.NMSSERVER_GETREGISTRYACCESS.run(nmsServer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
@@ -81,7 +100,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();
@@ -130,6 +154,9 @@ public class NBTReflectionUtil {
public static void writeApiNBT(NBTCompound comp, OutputStream stream) {
try {
Object workingtag = comp.getResolvedObject();
if(workingtag == null) {
workingtag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
}
ReflectionMethod.NBTFILE_WRITE.run(null, workingtag, stream);
} catch (Exception e) {
throw new NbtApiException("Exception while writing NBT!", e);
@@ -145,13 +172,40 @@ public class NBTReflectionUtil {
*/
public static Object getItemRootNBTTagCompound(Object nmsitem) {
try {
Object answer = ReflectionMethod.NMSITEM_GETTAG.run(nmsitem);
return answer;
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
*
@@ -160,8 +214,14 @@ public class NBTReflectionUtil {
*/
public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) {
try {
Object nmsComp = gettoCompount(nbtcompound.getCompound(), nbtcompound);
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) {
Object nmsComp = getToCompount(nbtcompound.getCompound(), nbtcompound);
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
if (nbtcompound.hasTag("tag") || nbtcompound.hasTag("Count")) {
nmsComp = DataFixerUtil.fixUpRawItemData(nmsComp, DataFixerUtil.VERSION1_20_4,
DataFixerUtil.getCurrentVersion());
}
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);
@@ -179,8 +239,13 @@ 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);
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
return new NBTContainer(ReflectionMethod.NMSITEM_SAVE_MODERN.run(nmsitem, registry_access));
} else {
Object answer = ReflectionMethod.NMSITEM_SAVE.run(nmsitem,
ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance());
return new NBTContainer(answer);
}
} catch (Exception e) {
throw new NbtApiException("Exception while converting NMS ItemStack to NBTCompound!", e);
}
@@ -193,6 +258,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);
@@ -254,8 +320,15 @@ 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_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();
@@ -288,7 +361,9 @@ 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_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);
@@ -338,7 +413,7 @@ public class NBTReflectionUtil {
if (!valideCompound(comp)) {
return;
}
Object workingtag = gettoCompount(nbttag, comp);
Object workingtag = getToCompount(nbttag, comp);
try {
ReflectionMethod.COMPOUND_SET.run(workingtag, name,
ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance());
@@ -359,12 +434,12 @@ public class NBTReflectionUtil {
if (root == null) {
root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
Object tmp = gettoCompount(root, comp);
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());
@@ -397,7 +472,7 @@ public class NBTReflectionUtil {
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
Object workingtag = getToCompount(rootnbttag, comp);
try {
ReflectionMethod.COMPOUND_MERGE.run(workingtag, workingtagSrc);
comp.setCompound(rootnbttag);
@@ -406,22 +481,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 workingtag = comp.getResolvedObject();
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
*
@@ -441,7 +500,7 @@ public class NBTReflectionUtil {
if (!valideCompound(comp)) {
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
}
Object workingtag = gettoCompount(rootnbttag, comp);
Object workingtag = getToCompount(rootnbttag, comp);
try {
ReflectionMethod.COMPOUND_SET.run(workingtag, key, val);
comp.setCompound(rootnbttag);
@@ -570,11 +629,11 @@ public class NBTReflectionUtil {
public static void remove(NBTCompound comp, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
return;
}
if (!valideCompound(comp))
return;
Object workingtag = gettoCompount(rootnbttag, comp);
Object workingtag = getToCompount(rootnbttag, comp);
ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key);
comp.setCompound(rootnbttag);
}
@@ -588,6 +647,9 @@ public class NBTReflectionUtil {
@SuppressWarnings("unchecked")
public static Set<String> getKeys(NBTCompound comp) {
Object workingtag = comp.getResolvedObject();
if (workingtag == null) {
return Collections.emptySet();
}
return (Set<String>) ReflectionMethod.COMPOUND_GET_KEYS.run(workingtag);
}
@@ -610,7 +672,7 @@ public class NBTReflectionUtil {
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
Object workingtag = getToCompount(rootnbttag, comp);
type.run(workingtag, key, data);
comp.setCompound(rootnbttag);
}
@@ -26,7 +26,7 @@ public class NBTTileEntity extends NBTCompound {
* @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!");
@@ -41,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())) {
@@ -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
@@ -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();
}
@@ -203,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
@@ -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,96 @@
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.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTContainer;
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.MojangToMapping;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
public class DataFixerUtil {
// these values can be found in DetectedVersion inside mc
// Finding pre 1.12.2 values is left as an exercise for the reader,
// as DetectedVersion is not a thing there
public static final int VERSION1_12_2 = 1343;
public static final int VERSION1_16_5 = 2586;
public static final int VERSION1_17_1 = 2730;
public static final int VERSION1_18_2 = 2975;
public static final int VERSION1_19_2 = 3120;
public static final int VERSION1_19_4 = 3337;
public static final int VERSION1_20_1 = 3465;
public static final int VERSION1_20_2 = 3578;
public static final int VERSION1_20_4 = 3700;
public static final int VERSION1_20_5 = 3837;
public static final int VERSION1_21 = 3953;
public static final int VERSION1_21_2 = 4080;
public static final int VERSION1_21_3 = 4189;
@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) ClassWrapper.NMS_REFERENCES.getClazz()
.getField(MojangToMapping.getMapping().get("net.minecraft.util.datafix.fixes.References#ITEM_STACK"))
.get(null);
DynamicOps<Object> nbtOps = (DynamicOps<Object>) ClassWrapper.NMS_NBTOPS.getClazz()
.getField(MojangToMapping.getMapping().get("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 {
return new NBTContainer(fixUpRawItemData(
NBTReflectionUtil.getToCompount(((NBTCompound) nbt).getCompound(), ((NBTCompound) nbt)), fromVersion,
toVersion));
}
/**
* 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.MC1_21_R3)) {
return VERSION1_21_3;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R2)) {
return VERSION1_21_2;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_21_R1)) {
return VERSION1_21;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
return VERSION1_20_5;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R3)) {
return VERSION1_20_4;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R1)) {
return VERSION1_20_1;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_19_R3)) {
return VERSION1_19_4;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_19_R1)) {
return VERSION1_19_2;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1)) {
return VERSION1_18_2;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
return VERSION1_17_1;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
return VERSION1_16_5;
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_12_R1)) {
return VERSION1_12_2;
}
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,76 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.util.UUID;
import javax.annotation.Nullable;
import com.mojang.authlib.GameProfile;
import de.tr7zw.changeme.nbtapi.NBTType;
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 {
@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");
}
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));
}
}
}
}
return gameProfile;
} catch (Throwable var11) {
return null;
}
}
public static ReadWriteNBT writeGameProfile(ReadWriteNBT arg, GameProfile gameProfile) {
if (!(gameProfile.getName() == null || gameProfile.getName().isEmpty())) {
arg.setString("Name", gameProfile.getName());
}
if (gameProfile.getId() != null) {
arg.setUUID("Id", gameProfile.getId());
}
if (!gameProfile.getProperties().isEmpty()) {
ReadWriteNBT compoundTag = arg.getOrCreateCompound("Properties");
for (String string : gameProfile.getProperties().keySet()) {
ReadWriteNBTCompoundList list = compoundTag.getCompoundList(string);
for (com.mojang.authlib.properties.Property property : gameProfile.getProperties().get(string)) {
ReadWriteNBT tag = list.addCompound();
tag.setString("Value", property.getValue());
if (property.hasSignature()) {
tag.setString("Signature", property.getSignature());
}
}
}
}
return arg;
}
}
@@ -1,5 +1,7 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -21,7 +23,8 @@ 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);
private static MinecraftVersion version;
private static Boolean hasGsonSupport;
@@ -36,11 +39,30 @@ 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.14.1";
private final int versionId;
private final boolean mojangMapping;
// TODO: not nice
@SuppressWarnings("serial")
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);
}
};
MinecraftVersion(int versionId) {
this(versionId, false);
}
@@ -73,7 +95,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");
}
@@ -108,18 +134,22 @@ 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.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0],
MinecraftVersion.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();
@@ -245,8 +275,7 @@ public enum MinecraftVersion {
return isFoliaPresent;
}
try {
logger.info("[NBTAPI] Found Folia: "
+ Class.forName("io.papermc.paper.threadedregions.RegionizedServer"));
logger.info("[NBTAPI] Found Folia: " + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"));
isFoliaPresent = true;
} catch (Exception ex) {
isFoliaPresent = false;
@@ -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+ 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);
}
}
}
@@ -8,17 +8,53 @@ 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<String> splitPath(String path) {
List<String> list = new ArrayList<>();
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(path.substring(startIndex, matcher.end() - 1).replace("\\.", "."));
list.add(new PathSegment(path.substring(startIndex, matcher.end() - 1).replace("\\.", ".")));
startIndex = matcher.end();
}
list.add(path.substring(startIndex).replace("\\.", "."));
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 + "]";
}
}
}
@@ -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,6 +20,7 @@ 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"),
@@ -62,6 +65,26 @@ 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"),
GAMEPROFILE(PackageWrapper.NONE, "com.mojang.authlib.GameProfile", MinecraftVersion.MC1_8_R3, null);
private Class<?> clazz;
@@ -99,7 +122,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);
}
@@ -3,10 +3,12 @@ package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
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
*
@@ -72,7 +74,7 @@ public class MojangToMapping {
put("net.minecraft.world.level.block.entity.BlockEntity#saveWithId()", "n");
put("net.minecraft.world.level.block.entity.BlockEntity#getBlockState()", "q");
put("net.minecraft.world.level.block.entity.BlockEntity#load(net.minecraft.nbt.CompoundTag)", "a");
put("net.minecraft.server.level.ServerLevel#getBlockState(net.minecraft.core.BlockPos)", "c_");
put("net.minecraft.server.level.ServerLevel#getBlockEntity(net.minecraft.core.BlockPos)", "c_");
}
};
@@ -120,11 +122,113 @@ 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");
}
};
public static Map<String, String> getMapping() {
switch (MinecraftVersion.getVersion()) {
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:
@@ -133,9 +237,11 @@ public class MojangToMapping {
return MC1_18R2;
case MC1_18_R1:
return MC1_18R1;
case UNKNOWN:
return MC1_20R2; // 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!");
}
}
@@ -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;
@@ -5,7 +5,6 @@ import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.UUID;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.NbtApiException;
@@ -113,10 +112,10 @@ public enum ReflectionMethod {
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")),
@@ -162,7 +161,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")),
@@ -173,11 +172,7 @@ public enum ReflectionMethod {
new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
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, "getBlockState(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")),
new Since(MinecraftVersion.MC1_18_R1, "getBlockEntity(net.minecraft.core.BlockPos)")),
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"),
@@ -186,11 +181,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")),
@@ -207,7 +200,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,
@@ -217,7 +210,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"),
@@ -237,8 +230,19 @@ public enum ReflectionMethod {
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"),
@@ -252,10 +256,8 @@ public enum ReflectionMethod {
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,
@@ -266,12 +268,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)")),
@@ -281,7 +283,29 @@ 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, 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, new Since(MinecraftVersion.MC1_20_R4, "parseOptional(net.minecraft.core.HolderLookup$Provider,net.minecraft.nbt.CompoundTag)")),
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,
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, 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()")),
;
private MinecraftVersion removedAfter;
private Since targetVersion;
@@ -372,7 +396,7 @@ 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)), ex);
}
}
@@ -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();
}
}
}
}
@@ -2,6 +2,7 @@ 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;
@@ -64,7 +65,7 @@ public class ProxyBuilder<T extends NBTProxy> implements InvocationHandler {
}
}
@SuppressWarnings("unchecked")
@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) {
@@ -98,13 +99,24 @@ public class ProxyBuilder<T extends NBTProxy> implements InvocationHandler {
(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) {
if (action == Type.HAS) {
String fieldName = getNBTName(proxy.getCasing(), method);
return (arguments) -> arguments.nbt.hasTag(fieldName);
}
@@ -116,7 +128,8 @@ public class ProxyBuilder<T extends NBTProxy> implements InvocationHandler {
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) {
if (target.type() == Type.HAS && method.getParameterCount() == 0
&& method.getReturnType() == boolean.class) {
return Type.HAS;
}
if (target.type() == Type.GET && method.getParameterCount() == 0) {
@@ -132,7 +145,8 @@ public class ProxyBuilder<T extends NBTProxy> implements InvocationHandler {
if (method.getName().startsWith("get") && method.getParameterCount() == 0) {
return Type.GET;
}
if (method.getName().startsWith("has") && method.getParameterCount() == 0 && method.getReturnType() == boolean.class) {
if (method.getName().startsWith("has") && method.getParameterCount() == 0
&& method.getReturnType() == boolean.class) {
return Type.HAS;
}
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);
}
+8 -14
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
</parent>
<artifactId>item-nbt-api-plugin</artifactId>
<packaging>jar</packaging>
@@ -12,21 +12,15 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</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>
</dependencies>
<build>
<resources>
@@ -39,7 +33,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<relocations>
@@ -34,27 +34,23 @@ 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.proxy.DataItemProxyTest;
import de.tr7zw.nbtapi.plugin.tests.proxy.SimpleProxyTest;
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 {
@@ -71,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);
@@ -89,19 +84,6 @@ 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());
@@ -128,9 +110,13 @@ public class NBTAPI extends JavaPlugin {
apiTests.add(new ItemConversionTest());
apiTests.add(new ItemStackConversionTest());
}
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R4)) {
apiTests.add(new LegacyItemTest());
apiTests.add(new ItemJsonTest());
}
apiTests.add(new ComponentsTest());
apiTests.add(new EmptyItemTest());
apiTests.add(new SmuggleTest());
apiTests.add(new DataItemProxyTest());
apiTests.add(new MetaTest());
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) { // 1.7.10 not a thing
apiTests.add(new ItemMergingTest());
@@ -158,15 +144,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());
@@ -181,8 +158,6 @@ public class NBTAPI extends JavaPlugin {
VersionChecker.hideOk = true;
return;
}
getLogger().info("Adding listeners...");
Bukkit.getPluginManager().registerEvents(new ReloadListener(), this);
MinecraftVersion.hasGsonSupport(); // init gson(if it hasn't already)
getLogger().info("Checking bindings...");
MinecraftVersion.getVersion();
@@ -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,9 +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);
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
profile = null;
profile = NBTGameProfile.fromNBT(nbt);
profile = NBT.gameProfileFromNBT(nbt);
if (profile == null || !profile.getId().equals(uuid)) {
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,18 +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();
@@ -35,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!");
}
@@ -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);
@@ -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)) {
@@ -3,24 +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");
@@ -32,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);
@@ -77,7 +75,7 @@ public class ListTest implements Test {
}
// 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) {
@@ -91,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) {
@@ -106,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) {
@@ -120,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) {
@@ -134,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))
@@ -149,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))
@@ -1,8 +1,12 @@
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 {
@@ -22,6 +26,33 @@ public class ResolveTest implements Test {
.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!");
}
}
}
@@ -3,6 +3,10 @@ package de.tr7zw.nbtapi.plugin.tests.compounds;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.NBT;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
@@ -21,6 +25,11 @@ public class StreamTest implements Test {
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);
});
}
}
@@ -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");
}
}
}
@@ -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) {
@@ -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);
}
}
}
}
@@ -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);
}
}
}
}
@@ -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);
}
}
}
}
@@ -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,37 @@
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 -> {
nbt.setString("minecraft:custom_name", "{\"extra\":[\"foobar\"],\"text\":\"\"}");
});
if(!item.getItemMeta().getDisplayName().equals("foobar")) {
throw new NbtApiException("ModifyComponent didn't work!");
}
}
}
@@ -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));
}
}
@@ -20,6 +20,13 @@ public class EmptyItemTest implements Test {
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");
@@ -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");
@@ -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,8 +14,8 @@ 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);
ReadWriteNBT comp = NBT.itemStackArrayToNBT(src);
ItemStack[] recreated = NBT.itemStackArrayFromNBT(comp);
if (recreated == null || src.length != recreated.length) {
throw new NbtApiException("Size did not match!");
}
@@ -0,0 +1,34 @@
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);
}
}
}
@@ -6,12 +6,16 @@ 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);
@@ -1,48 +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 {
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!");
}
}
}
}
//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!");
// }
// }
// }
//
//}
@@ -9,6 +9,7 @@ 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;
@@ -18,12 +19,12 @@ public class SimpleProxyTest implements Test {
public void test() throws Exception {
ItemStack item = new ItemStack(Material.STONE);
NBT.modify(item, TestInterface.class, ti -> {
if(ti.hasKills()) {
if (ti.hasKills()) {
throw new NbtApiException("Item reported to have kills before setting data!");
}
ti.setKills(42);
ti.addKill();
if(!ti.hasKills()) {
if (!ti.hasKills()) {
throw new NbtApiException("Item reported to not have kills after setting data!");
}
if (!"{Kills:43}".equals(ti.toString())) {
@@ -49,6 +50,23 @@ public class SimpleProxyTest implements Test {
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 {
@@ -59,7 +77,7 @@ public class SimpleProxyTest implements Test {
}
public boolean hasKills();
public void setKills(int amount);
public int getKills();
@@ -77,6 +95,8 @@ public class SimpleProxyTest implements Test {
public void setItem(ItemStack item);
public ProxyList<Statistic> getStatistics();
}
public interface Statistic extends NBTProxy {
@@ -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;
@@ -22,8 +23,16 @@ public class TileTest implements Test {
try {
Block block = world.getBlockAt(world.getSpawnLocation().getBlockX(), 254,
world.getSpawnLocation().getBlockZ());
if (block.getChunk().isLoaded() && 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) {
@@ -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;
@@ -25,16 +24,18 @@ public class TilesCustomNBTPersistentTest implements Test {
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.
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</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.14.1</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.4.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);
@@ -81,6 +84,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");
}
+2 -2
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
</parent>
<artifactId>nbt-data-api</artifactId>
@@ -14,7 +14,7 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
</parent>
<artifactId>nbt-injector</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.14.1</version>
<scope>compile</scope>
</dependency>
<dependency>
+18 -7
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
<packaging>pom</packaging>
<inceptionYear>2015</inceptionYear>
<organization>
@@ -19,8 +19,6 @@
</licenses>
<modules>
<module>item-nbt-api</module>
<module>nbt-injector</module>
<module>nbt-data-api</module>
<module>item-nbt-plugin</module>
<module>mappings-parser</module>
</modules>
@@ -90,7 +88,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.13.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
@@ -99,7 +97,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<version>3.3.1</version>
<executions>
<execution>
<id>attach-sources</id>
@@ -112,7 +110,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<version>3.11.1</version>
<configuration>
<source>8</source>
</configuration>
@@ -141,13 +139,26 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.2.0</version>
<version>2.4.0</version>
<configuration>
<licenseName>mit</licenseName>
<licenseFile>LICENSE</licenseFile>
<force>true</force>
</configuration>
</plugin>
<plugin>
<groupId>dev.tr7zw.nojitpack.maven</groupId>
<artifactId>no-jitpack-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<id>antijitpack</id>
<goals>
<goal>antijitpack</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
+2 -2
View File
@@ -112,7 +112,7 @@ Just use the Plugin as Maven dependency and remember to add "NBTAPI" as dependen
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api-plugin</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
</dependency>
[/CODE]
[/SPOILER]
@@ -122,7 +122,7 @@ Using this method the API gets copied into your plugin. Server owners don't have
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.12.0-SNAPSHOT</version>
<version>2.14.1</version>
</dependency>
...
<plugins>
@@ -1,42 +0,0 @@
# Converting Minecraft Objects to NBT and Strings
The basic idea is that you can convert data into different representations:
Minecraft Objects <-> NBT <-> String(Mojang-Json)
## Converting Minecraft Objects into NBT
```java
// Items
ReadWriteNBT nbt = NBT.itemStackToNBT(itemStack);
ReadWriteNBT nbt = NBT.itemStackArrayToNBT(itemStacks);
// Entity
NBTEntity nbte = new NBTEntity(entity);
// Tiles
NBTTileEntity nbtt= new NBTTileEntity(block.getState());
// Gameprofiles
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
// NBT Files
NBTFile file = new NBTFile(testFile);
```
## Converting NBT to a String and the String back to NBT
```java
// to String(works with any NBT object)
String str = nbt.toString();
// String back to NBT
ReadWriteNBT nbt = NBT.parseNBT(json);
```
## Recreating the Minecraft Objects from NBT
```java
// Items
ItemStack itemStack = NBT.nbtToItemStack(nbt);
ItemStack[] itemStacks = NBT.nbtToItemStackArray(nbt);
// Entity/Tiles
In general "new NBTEntity(entity).mergeCompound(nbt)", but you might want to remove some data from the nbt first like the Location, uuid and entityId
// Gameprofile
GameProfile profile = NBT.nbtToGameProfile(nbt);
```
+125
View File
@@ -0,0 +1,125 @@
## Set a skull's skin
#### We will be using [this head](https://minecraft-heads.com/custom-heads/head/28194-cup-of-soda) as example.
```java
// This is the base64 texture value from the bottom of the previously mentioned website.
final String textureValue = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQyY2M5MjAzYzkwYjg5YmRhYzFkZjI4NDE2NzI2NmI5NTNkZmViZjNjNDY5MGE3Y2QwYjE1NzkxYTYyZTU4MiJ9fX0=";
// Creating ItemStack
// For Minecraft 1.12.2 and below
final ItemStack item = new ItemStack(Material.SKULL_ITEM);
item.setDurability((short) 3);
// For Minecraft 1.13 and newer
final ItemStack item = new ItemStack(Material.PLAYER_HEAD);
// Applying nbt
// For Minecraft 1.20.4 and below
NBT.modify(item, nbt -> {
ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner");
// The owner UUID. Note that skulls with the same UUID but different textures will misbehave and only one texture will load.
// They will share the texture. To avoid this limitation, it is recommended to use a random UUID.
skullOwnerCompound.setUUID("Id", UUID.randomUUID());
skullOwnerCompound.getOrCreateCompound("Properties")
.getCompoundList("textures")
.addCompound()
.setString("Value", textureValue);
});
// Workaround for Minecraft 1.20.5+
NBT.modifyComponents(item, nbt -> {
ReadWriteNBT profileNbt = nbt.getOrCreateCompound("minecraft:profile");
profileNbt.setUUID("id", uuid);
ReadWriteNBT propertiesNbt = profileNbt.getCompoundList("properties").addCompound();
propertiesNbt.setString("name", "textures");
propertiesNbt.setString("value", textureValue);
});
```
> [!TIP]
> If you are using Paper API on 1.12.2+, you may use the following code to create textured skulls
```java
SkullMeta meta = (SkullMeta) item.getItemMeta();
PlayerProfile playerProfile = Bukkit.createProfile(uuid);
playerProfile.setProperty(new ProfileProperty("textures", textureValue));
meta.setPlayerProfile(playerProfile);
// You can also use item.editMeta(SkullMeta.class, meta -> {}); on 1.17+
item.setItemMeta(meta);
```
## Zombie that can pick up loot and does 0.5 hearts of damage
This code should serve only as a reference, the nbt structure might change between versions.
```java
Zombie zombie = location.getWorld().spawn(location, Zombie.class);
String attributeName = "minecraft:generic.attack_damage"; // Or generic.attackDamage prior to 1.16
double damageValue = 0.5;
// Modify vanilla data
NBT.modify(zombie, nbt -> {
nbt.setBoolean("CanPickUpLoot", true);
ReadWriteNBTCompoundList list = nbt.getCompoundList("Attributes");
// Check if zombie already has attribute set. If so, modify it
for (ReadWriteNBT listEntryNbt : list) {
if (!listEntryNbt.getString("Name").equals(attributeName)) continue;
listEntryNbt.setDouble("Base", damageValue);
return;
}
// Attribute is missing, add it instead
ReadWriteNBT listEntryNbt = list.addCompound();
listEntryNbt.setString("Name", attributeName);
listEntryNbt.setDouble("Base", damageValue);
});
// Modify custom data
NBT.modifyPersistentData(zombie, nbt -> {
// Let's mark our zombie as a custom one
nbt.setBoolean("custom_zombie", true);
});
```
## Reading world data
```java
// Get main world's folder
File worldDataFolder = Bukkit.getWorlds().getFirst().getWorldFolder();
// Read level data
NBTFile levelNbtFile = new NBTFile(new File(worldDataFolder, "level.dat"));
// Obtain world name
String worldName = levelNbtFile.resolveOrNull("Data.LevelName", String.class);
// Read some player's data
UUID playerUuid;
File playerFile = new File(worldDataFolder, "playerdata/" + playerUuid + ".dat");
if (!playerFile.exists()) {
// No offline player data for provided uuid
return;
}
NBTFile playerNbtFile = new NBTFile(playerFile);
// Change player's health
float health = playerNbtFile.getFloat("Health");
playerNbtFile.setFloat("Health", health + 5);
// Once finished, save the file
playerNbtFile.save();
```
+26
View File
@@ -0,0 +1,26 @@
## Frequently Asked Questions
### I've updated NBT-API, but it keeps saying that it's outdated
Some other plugin on your server has a shaded version of NBT-API. Try looking at the logs to find out which plugin is it, or add/remove your plugins until you find a culprit.
### I've installed NBT-API, but the plugin keeps asking for ItemNBTAPI
The plugin uses a very outdated version of NBT-API. In this case, download the version 1.8.3 from the versions tab. The outdated "ItemNBTAPI" and "NBTAPI" can be used both at the same time.
### 1.7 support
- Use 1.7.10.
- NBTLists may not work.
- NBTTypes don't work as 1.7.x is missing this feature.
- TLDR: 1.7.10 is a bit broken and not everything will work! Also, it's not supported anymore!
### Where did NBTInjector go?
The experimental NBTInjector became unsupported since Minecraft 1.14 and was removed in 2.13.0 with Minecraft 1.21 release.
NBTInjector is incompatible with reloads and may break things, and thus is not recommended.
If you're using Minecraft 1.14+, you should switch to the persistent storage API instead.
In versions prior to 1.14, you may use a workaround like storing data inside an item's nbt that the entity is wearing (e.g. having a button in mob's helmet, and storing data on that button).
+8 -17
View File
@@ -1,26 +1,17 @@
# Welcome to the NBT API wiki
# Welcome to the NBT-API wiki
NBT API has been tested on Spigot
1.7.10-1.19+
NBT-API supports Spigot and Paper versions starting at 1.8. It runs on 1.7.10 too, but some features might not work (see [1.7 support](https://github.com/tr7zw/Item-NBT-API/wiki/FAQ#17-support)).
Full JavaDoc can be found [here](https://tr7zw.github.io/Item-NBT-API/v2-api/)!
Feel free to seek for support in [![Discord](https://img.shields.io/discord/342814924310970398?color=%237289DA&label=Discord&logo=discord&logoColor=white)](https://discordapp.com/invite/yk4caxM).
### What do I have to do as a server owner?
Just download the jar and drop it in the plugins folder. Done.
Note that outdated plugins may ask for "ItemNBTAPI". In this case, download version 1.8.3 from the versions tab. The outdated "ItemNBTAPI" and "NBTAPI" can be used at the same time.
Just download the jar and drop it in the plugins folder. Done!
### 1.7 Notes
* Use 1.7.10
* NBTLists may not work
* NBTTypes don't work as 1.7.x is missing this feature.
* TLDR: 1.7.10 is a bit broken and not everything will work! Also it's not supported anymore!
### Don't reload the NBT-Injector
Reloading in general is a horrible thing and it will break the NBTInjector in horrible ways! When updating plugins/changing configs always restart the server normally!
You might also want to check out some [plugins that use NBT-API](https://github.com/tr7zw/Item-NBT-API/wiki/Plugins).
### How can I use the API as a developer?
See [Using the NBT API](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-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 see 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) to familiarize yourself with the API.
Full Javadoc can be found [here](https://tr7zw.github.io/Item-NBT-API/v2-api/)!
@@ -1,24 +0,0 @@
# Merging Compounds
You can "merge" the data from any given Compound onto some other Compound. This will overwrite tags with the same name.
Example:
`Tag1: {Num1:1, Num2:2} Tag2: {Num1:7, Num3:3}`
After merging Tag2 on Tag1:
```java
tag1.mergeCompound(tag2);
```
`Tag1: {Num1:7, Num2:2, Num3:3} Tag2: {Num1:7, Num3:3}`
## Simulate the "/data merge" command
```java
NBT.modify(zombie, nbt -> {
nbt.mergeCompound(NBT.parseNBT("{Silent:1b,Invulnerable:1b,Glowing:1b,IsBaby:1b}"));
});
```
+5 -3
View File
@@ -1,10 +1,12 @@
## List of some plugins on Github that utilize NBTAPI
Want your plugin added to this list? Submit a PR editing this file located in `~/wiki/Plugins.md`!
## List of some plugins on GitHub that utilize NBT-API
- [IllegalStack](https://github.com/dniym/IllegalStack)
- [Prison](https://github.com/PrisonTeam/Prison)
- [CommandAPI](https://github.com/JorelAli/CommandAPI)
- [SkBee](https://github.com/ShaneBeee/SkBee/)
- [Monumenta](https://github.com/TeamMonumenta/monumenta-plugins-public/)
- [SummonFriendlyMobs](https://github.com/ArmyFury/SummonFriendlyMobs)
___
Want your plugin added to this list? Submit a PR editing this file located in `~/wiki/Plugins.md`!
-29
View File
@@ -1,29 +0,0 @@
### We will be using [this head](https://minecraft-heads.com/custom-heads/food%20&%20drinks/28194-cup-of-soda) as example.
```java
// This is the base64 texture value from the bottom of the previously mentioned website.
final String textureValue = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQyY2M5MjAzYzkwYjg5YmRhYzFkZjI4NDE2NzI2NmI5NTNkZmViZjNjNDY5MGE3Y2QwYjE1NzkxYTYyZTU4MiJ9fX0=";
// Creating ItemStack
// For Minecraft 1.12 and above
final ItemStack item = new ItemStack(Material.SKULL_ITEM);
item.setDurability((short) 3);
// For Minecraft 1.13 and newer
final ItemStack item = new ItemStack(Material.PLAYER_HEAD);
NBT.modify(item, nbt -> {
final ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner");
// The owner UUID. Note that skulls with the same UUID but different textures will misbehave and only one texture will load.
// They will share the texture. To avoid this limitation, it is recommended to use a random UUID.
skullOwnerCompound.setUUID("Id", UUID.randomUUID());
skullOwnerCompound.getOrCreateCompound("Properties")
.getCompoundList("textures")
.addCompound()
.setString("Value", textureValue);
});
```
+40 -17
View File
@@ -1,12 +1,11 @@
To start using NB-API, you either need to depend on its plugin version, or shade (include) it inside your plugin.
> [!IMPORTANT]
> Plugin and shaded versions have different ``artifactId``. Make sure to correctly choose the one you need!
# Option 1) NBT-API as a dependency
Add the following Entries to your Gradle build at the correct location:
```groovy
compileOnly("de.tr7zw:item-nbt-api-plugin:VERSION")
```
(Get the current Version from [here](https://www.spigotmc.org/resources/nbt-api.7939/))
Add the following entries to your Gradle build at the correct locations:
```groovy
repositories {
@@ -19,7 +18,13 @@ repositories {
}
```
Finally, add the API as dependency to your ``plugin.yml``
```groovy
compileOnly("de.tr7zw:item-nbt-api-plugin:VERSION")
```
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
Add the API as dependency to your ``plugin.yml``:
```yml
depend: [NBTAPI]
@@ -38,16 +43,9 @@ plugins {
```
The latest version of the shadow plugin can be found [here](https://github.com/johnrengelman/shadow/releases).
<br/>
Add NBT-API to your dependencies:
```groovy
implementation("de.tr7zw:item-nbt-api:VERSION")
```
(Get the current Version from [here](https://www.spigotmc.org/resources/nbt-api.7939/))
```groovy
repositories {
...
@@ -59,7 +57,16 @@ repositories {
}
```
After this you can add the shadowjar configuration to relocate the api package:
```groovy
implementation("de.tr7zw:item-nbt-api:VERSION")
```
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
> [!WARNING]
> Make sure you're using ``item-nbt-api`` as ``artifactId``, never shade the ``-plugin`` artifact!
After this you can add the shadowJar configuration to relocate the API package:
```groovy
shadowJar {
@@ -67,7 +74,7 @@ shadowJar {
}
```
If you want to run the shadowJar task when the build task is executed, you can write like this:
If you want to run the shadowJar task when the build task is executed, you can use this:
```groovy
build {
@@ -75,3 +82,19 @@ build {
}
```
###### Initializing NBT-API early
If you are shading NBT-API, you may call ``NBT.preloadApi()`` during ``onEnable`` to initialize NBT-API early and check whether everything works. If you omit this step, NBT-API will be initialized on the first call to the API.
```java
@Override
public void onEnable() {
if (!NBT.preloadApi()) {
getLogger().warning("NBT-API wasn't initialized properly, disabling the plugin");
getPluginLoader().disablePlugin(this);
return;
}
// Load other things
}
```
+71 -43
View File
@@ -1,6 +1,24 @@
To start using NB-API, you either need to depend on its plugin version, or shade (include) it inside your plugin.
> [!IMPORTANT]
> Plugin and shaded versions have different ``artifactId``. Make sure to correctly choose the one you need!
# Option 1) NBT-API as a dependency
Add the following Entries to your pom at the correct location:
Add the following entries to your pom at the correct locations:
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
```xml
<dependency>
@@ -11,22 +29,9 @@ Add the following Entries to your pom at the correct location:
</dependency>
```
(Get the current Version from [here](https://modrinth.com/plugin/nbtapi/versions))
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
Add the API as dependency to your plugin.yml
Add the API as dependency to your ``plugin.yml``:
```yaml
depend: [NBTAPI]
@@ -34,39 +39,16 @@ depend: [NBTAPI]
# Option 2) Shading the NBT-API into your plugin
Add the following Entries to your pom at the correct location:
To include NBT-API directly in your plugin, you can use the maven shade plugin.
```xml
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>VERSION</version>
</dependency>
```
(Get the current Version from [here](https://modrinth.com/plugin/nbtapi/versions))
**IMPORTANT: This is not the same ``artifactId`` as using it as dependency! Never shade the ``-plugin`` artifact!**
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
Add the plugin to the build configuration, as shown here:
```xml
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.6.0</version>
<executions>
<execution>
<id>shade</id>
@@ -88,7 +70,9 @@ Add the following Entries to your pom at the correct location:
</plugins>
```
Example:
The latest version of the shade plugin can be found [here](https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin).
Replace ``YOUR PACKAGE WHERE THE API SHOULD END UP`` with your own unique package. For example:
```xml
<relocation>
@@ -97,3 +81,47 @@ Example:
</relocation>
```
Then, add NBT-API to your dependencies by including the following entries to your pom at the correct locations:
```xml
<repositories>
...
<!-- CodeMC -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
<layout>default</layout>
</repository>
...
</repositories>
```
```xml
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>VERSION</version>
</dependency>
```
(Get the current ``VERSION`` from [here](https://modrinth.com/plugin/nbtapi/versions))
> [!WARNING]
> Make sure you're using ``item-nbt-api`` as ``artifactId``, never shade the ``-plugin`` artifact!
###### Initializing NBT-API early
If you are shading NBT-API, you may call ``NBT.preloadApi()`` during ``onEnable`` to initialize NBT-API early and check whether everything works. If you omit this step, NBT-API will be initialized on the first call to the API.
```java
@Override
public void onEnable() {
if (!NBT.preloadApi()) {
getLogger().warning("NBT-API wasn't initialized properly, disabling the plugin");
getPluginLoader().disablePlugin(this);
return;
}
// Load other things
}
```
+444 -60
View File
@@ -1,88 +1,472 @@
## Using the ``NBT`` class (prefered)
## General usage
### Basics overview
Most of the things are exposed inside the [NBT](https://tr7zw.github.io/Item-NBT-API/v2-api/de/tr7zw/changeme/nbtapi/NBT.html) class. Your specific use-case might not yet be covered by the wiki, so make sure to explore the [Javadoc](https://tr7zw.github.io/Item-NBT-API/v2-api/), or ask your IDE for suggestions!
#### Basic getting and setting of data
[ReadableNBT](https://tr7zw.github.io/Item-NBT-API/v2-api/de/tr7zw/changeme/nbtapi/iface/ReadableNBT.html) and [ReadWriteNBT](https://tr7zw.github.io/Item-NBT-API/v2-api/de/tr7zw/changeme/nbtapi/iface/ReadWriteNBT.html) are used to read/write nbt:
```java
// Setting data on ItemStacks/Entities/BlockEntities
// Creating a new empty NBT tag
ReadWriteNBT nbt = NBT.createNBTObject();
// Setting nbt
nbt.setString("Stringtest", "Teststring");
nbt.setInteger("Inttest", 42);
nbt.setDouble("Doubletest", 1.5);
nbt.setBoolean("Booleantest", true);
// More are available! Ask your IDE, or see Javadoc for suggestions!
// Getting nbt
String s1 = nbt.getString("Stringtest");
int i1 = nbt.getInteger("Inttest");
double d = nbt.getDouble("Doubletest");
boolean b = nbt.getBoolean("Booleantest");
// Or, alternatively
String s2 = nbt.getOrDefault("Stringtest", "fallback_value");
Integer i2 = nbt.getOrNull("Inttest", Integer.class);
// Keys manipulation
nbt.getKeys(); // Get all Tags
nbt.hasTag("key"); // Check whether the Tag exists
nbt.hasTag("key", NbtType.NBTTagString); // Check whether the Tag exists and matches the type
nbt.removeKey("key"); // Remove the Tag
NBTType nbtType = nbt.getType("key"); // Get the type of the Tag
// Subtag compounds
nbt.getCompound("subtag"); // Get a subtag, or null
nbt.getOrCreateCompound("subtag"); // Get or create a subtag
```
#### Converting NBT to String and the String back to NBT
```java
// Parse Mojang-Json string to nbt
ReadWriteNBT nbt = NBT.parseNBT("{Health:20.0f,Motion:[0.0d,10.0d,0.0d],Silent:1b}");
// Get the NBT back as a Mojang-Json string (works with any NBT object)
String json = nbt.toString();
// Turn back into nbt again
ReadWriteNBT nbt2 = NBT.parseNBT(json);
```
#### Merging Compounds
You can "merge" the data from any given Compound onto some other Compound. This will overwrite the tags with the same name.
Example:
`Tag1: {Num1:1, Num2:2} Tag2: {Num1:7, Num3:3}`
After merging Tag2 on Tag1:
```java
tag1.mergeCompound(tag2);
```
`Tag1: {Num1:7, Num2:2, Num3:3} Tag2: {Num1:7, Num3:3}`
#### Resolving data
To simplify working with deeply nested NBT, resolve methods allow directly getting or working with these nested tags.
Compounds are separated by dots ``.`` In case you need a ``.`` inside a key, it can be escaped with a backslash ``\``.
```java
// For example, the following code:
nbt.resolveOrCreateCompound("foo.bar.baz");
// Will get/create the same subtag compound as:
nbt.getOrCreateCompound("foo").getOrCreateCompound("bar").getOrCreateCompound("baz");
// Get compound if exists, or null otherwise
nbt.resolveCompound("foo.some.key.baz");
// Sets foo/bar/baz/test to 42
nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// Example of a key with a . in it. Sets the key foo/some.key/baz/other to 123
nbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123);
// Similarly, you may also fetch values from nested compounds
String s = nbt.resolveOrDefault("foo.bar.Stringtest", "fallback_value");
Integer i = nbt.resolveOrNull("foo\\.bar.baz.Inttest", Integer.class);
```
#### Accessing/creating lists and their data
> [!NOTE]
> The lists will be created if they do not exist, there are no setters for lists!
```java
// Get or create a string list
ReadWriteNBTList<String> stringList = nbt.getStringList("list_key");
stringList.add("value");
// Get the list type, NBTTagString in this case
NBTType type = nbt.getListType("list_key");
// You can obtain the value back just like with normal Lists
nbt.getStringList("list_key").get(0);
// Or by fetching it
nbt.resolveOrNull("list_key[0]", String.class); // Get the first value in list
// You can also use negative number to get the value from the end of the list/array
nbt.resolveOrDefault("list_key[-1]", "fallback_value"); // Get the last value in list, or use the default
// NBT compound lists
// Get the list (will create it if needed)
ReadWriteNBTCompoundList nbtList = nbt.getOrCreateCompound("foo").getCompoundList("other_key");
// Add new compound to the list
ReadWriteNBT nbtListEntry = nbtList.addCompound();
nbtListEntry.setBoolean("bar", true);
// Add existing nbt compound to the list
ReadWriteNBT otherNbtListEntry = nbtList.addCompound(NBT.parseNBT("{foo_bar:1b}"));
// You can fetch compounds in lists
nbt.resolveCompound("foo.other_key[0]"); // Get the first compound in list, or null
nbt.resolveOrCreateCompound("foo.other_key[1]"); // Get the second compound in list, or create it
// Or fetch data from them
boolean bar = nbt.resolveOrDefault("foo.other_key[0].bar", false);
```
### Working with items
You can read/write nbt data on items using ``NBT.get``/``NBT.modify`` methods.
```java
// Setting data
NBT.modify(itemStack, nbt -> {
nbt.setString("Stringtest", "Teststring");
nbt.setInteger("Inttest", 42);
nbt.setDouble("Doubletest", 1.5d);
nbt.setBoolean("Booleantest", true);
//More are available! Ask your IDE/Javadocs for suggestions!
// More are available! Ask your IDE, or see Javadoc for suggestions!
});
// Getting data from ItemStacks
String string = NBT.get(itemStack, nbt -> nbt.getString("Stringtest"));
// Reading data
NBT.get(itemStack, nbt -> {
String stringTest = nbt.getString("Stringtest");
int intTest = nbt.getOrDefault("Inttest", 0);
// Do more stuff
});
// Getting data
String string = NBT.get(itemStack, nbt -> (String) nbt.getString("Stringtest"));
// Modifying and getting data
int someValue = NBT.modify(itemStack, nbt -> {
int i = nbt.getOrDefault("key", 0) + 1;
nbt.setInteger(i);
return i;
});
```
###### ItemMeta usage
> [!WARNING]
> Never mix the usage of ItemMeta and NBT.
> Setting ItemMeta will override any changes made to item's nbt.
```java
// WRONG, do not do this!
ItemMeta meta = itemStack.getItemMeta();
meta.setDisplayName("Modified!");
NBT.modify(itemStack, nbt -> nbt.setBoolean("modified", true));
itemStack.setItemMeta(meta); // Will undo all changes to nbt!
// Correct, both ItemMeta and NBT will be applied
NBT.modify(itemStack, nbt -> nbt.setBoolean("modified", true));
// Taking ItemMeta snapshot after changes to nbt
ItemMeta meta = itemStack.getItemMeta();
meta.setDisplayName("Modified!");
itemStack.setItemMeta(meta);
// If making any further changes with NBT & ItemMeta,
// re-take the item's ItemMeta after changing the nbt!
```
Alternatively, you may safely modify ItemMeta inside the NBT scope:
```java
// Updating ItemMeta using NBT
NBT.modify(itemStack, nbt -> {
nbt.setInteger("kills", nbt.getOrDefault("kills", 0) + 1);
nbt.modifyMeta((meta, readOnlyNbt) -> { // do not modify the nbt while modifying the meta!
nbt.modifyMeta((meta, readOnlyNbt) -> { // Do not modify the nbt while modifying the meta!
meta.setDisplayName("Kills: " + readOnlyNbt.getOrDefault("kills", 0));
});
//Do more stuff
// Do more stuff
});
```
###### Changing vanilla item nbt on 1.20.5+
> [!IMPORTANT]
> Since Minecraft 1.20.5 ItemStacks no longer have vanilla nbt during runtime.
> Any calls like ``NBT.get`` or ``NBT.modify`` will access only the item's ``custom_data`` component.
>
> As a workaround, you may use the following code:
```java
// NOTE: This code is only for 1.20.5+!
// Only reading vanilla data
NBT.getComponents(item, nbt -> {
if (nbt.hasTag("minecraft:custom_name")) {
String customName = nbt.getString("minecraft:custom_name");
}
});
// Gameprofile to NBT
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
// NBT to Gameprofile
GameProfile profile = NBT.nbtToGameProfile(nbt);
// ItemStack to NBT
// Modifying vanilla data
NBT.modifyComponents(item, nbt -> {
nbt.setString("minecraft:custom_name", "{\"extra\":[\"foobar\"],\"text\":\"\"}");
});
```
### Working with entities and block entities
Working with entities and block entities is similar to working with items.
#### Accessing vanilla nbt
The example code for entities is applicable for block entities too.
```java
// Obtain data
boolean silent = NBT.get(entity, nbt -> (boolean) nbt.getBoolean("Silent"));
// Modify data
NBT.modify(entity, nbt -> {
nbt.setBoolean("Silent", true);
nbt.setByte("CanPickUpLoot", (byte) 1);
});
```
#### Accessing custom data
For reading/storing custom data on (block-)entities, you should use methods that end with PersistentData.
> [!IMPORTANT]
> When working with block entities, make sure that the block entity exists in the world.
>
> For example, you may not be able to add data to a chest in `BlockPlaceEvent` because the chest hasn't been placed yet. In such case, you can delay your actions by one tick or set the block to chest manually.
```java
// Obtain data
boolean test = NBT.getPersistentData(entity, nbt -> (boolean) nbt.getBoolean("custom_key"));
// Modify data
NBT.modifyPersistentData(entity, nbt -> {
nbt.setBoolean("custom_key", true);
nbt.setByte("custom_byte", (byte) 1);
});
```
> [!NOTE]
> If you plan to store some data for players, you might also consider using an external storage instead to not clutter the players' data files inside the world folder. Since any data written to the persistent storage is there forever, you can leave redundant data behind when your plugin is removed, but it's perfectly fine to store data in there otherwise.
>
> Storage solutions like per-player [NBT files](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#nbt-files) might be more than enough (and is basically what vanilla does, but you'll have your own file instead of using the one inside the world). Cache the file's data on join and save on quit/server shutdown, optionally adding auto saving.
#### Simulate the "/data merge" command
Applicable for items/block entities/entities/etc.
```java
NBT.modify(zombie, nbt -> {
nbt.mergeCompound(NBT.parseNBT("{Silent:1b,Invulnerable:1b,Glowing:1b,IsBaby:1b}"));
});
```
### Working with blocks
You can store data in block entities (block entities like chest, furnace, etc.) using the examples from the section above, but normal blocks do not have the nbt data.
Thus, you have to use your own block data storage to store custom block data.
You can store data inside Chunks since 1.16.4, and NBT-API allows you to do so by using ``NBTChunk``:
```java
ReadWriteNBT nbt = new NBTChunk(chunk).getPersistentDataContainer();
```
Similarly, there is ``NBTBlock``, which allows you to store block data inside chunk's data.
```java
// Block's data will be stored in Chunk's data in "blocks.x_y_z" subtag
ReadWriteNBT nbt = new NBTBlock(block).getData();
```
**However**, keep in mind that this data is linked only to the location, and if the block gets broken/changed/exploded/moved/etc., the data will still be on that location unless manually cleared/moved!
Moreover, since the data is stored inside a Chunk, this will increase the chunk's size on the disk.
## Extras
> [!TIP]
> Besides this page, you may also take a look at some code examples at [example usages](https://github.com/tr7zw/Item-NBT-API/wiki/Example-Usages).
### NBT files
NBTFileHandle allows working with nbt files.
```java
// Will automatically create the file if it does not exist
NBTFileHandle nbtFile = NBT.getFileHandle(new File("directory", "test.nbt"));
// Setting data
nbtFile.setString("foo", "bar");
// Saving the file after applying changes
nbtFile.save();
```
Alternatively, you may read the nbt file without maintaining the link to it.
Unlike NBTFileHandle, the file won't be automatically created if it does not exist.
```java
File file = new File("directory", "test.nbt");
// Reading data from file (will return an empty compound if the file does not exist)
ReadWriteNBT nbt = NBT.readFile(file);
// Saving nbt to file
NBT.writeFile(file, nbt);
```
### Converting Minecraft Objects to NBT and Strings
The basic idea is that you can convert data into different representations:
Minecraft Objects <-> NBT <-> String (Mojang-Json)
#### Items
While ``NBT.get/modify`` allows you to modify item's direct nbt (or only the ``custom_data`` container since 1.20.5), the ItemStack object nbt represents the item's serialized data. It includes item type, amount and all extra item tags.
For example, when ``NBT.get`` looks like this:
`{foo:"bar",points:12,test:1b}`
The ItemStack object nbt from ``NBT.itemStackToNBT`` may look like this:
`{components:{"minecraft:custom_data":{foo:"bar",points:12,test:1b}},count:2,id:"minecraft:stone"}`
Or like this in versions prior to 1.20.5:
`{Count:2b,id:"minecraft:stone",tag:{foo:"bar",points:12,test:1b}}`
###### Serializing/deserializing items
```java
// Saving
ReadWriteNBT nbt = NBT.itemStackToNBT(itemStack);
// NBT to ItemStack
ItemStack itemStack = NBT.nbtToItemStack(nbt);
// ItemStack Array to NBT
ReadWriteNBT nbt = NBT.itemStackArrayToNBT(itemStacks);
// NBT to ItemStack Array
ItemStack[] itemStacks = NBT.nbtToItemStackArray(nbt);
// Creating a new NBT tag
ReadWriteNBT nbt = NBT.createNBTObject();
// Parsing a Mojang-Json String to NBT
// Restoring
ItemStack itemStack = NBT.itemStackFromNBT(nbt);
ItemStack[] itemStacks = NBT.itemStackArrayFromNBT(nbt);
// Reminder (NBT <-> String)
String json = nbt.toString();
ReadWriteNBT nbt = NBT.parseNBT(json);
```
## Old style of creating a NBT Wrapper
#### Entities and block entities
```java
NBTItem nbti = new NBTItem(ItemStack);
NBTEntity nbtent = new NBTEntity(Entity); // Vanilla tags only!
NBTTileEntity tent = new NBTTileEntity(block.getState()); // Vanilla tags only!
NBTFile file = new NBTFile(new File("directory"), "test.nbt")); // Will be created at ./directory/test.nbt
NBTContainer container = new NBTContainer(json); // Parse in json
NBTContainer container = new NBTContainer(); // Empty NBTCompound
// Saving
ReadWriteNBT entityNbt = NBT.createNBTObject();
NBT.get(entity, entityNbt::mergeCompound);
// Restoring
NBT.modify(entity, nbt -> {
// You might also want to filter out entityNbt first,
// e.g. remove some data like location, uuid, entityId, etc.
nbt.mergeCompound(entityNbt);
});
```
## Using the wrapper(NBTCompound/)
#### Game profiles
```java
//Set
nbti.setString("Stringtest", "Teststring");
nbti.setInteger("Inttest", 42);
nbti.setDouble("Doubletest", 1.5d);
nbti.setBoolean("Booleantest", true);
//More are available! Ask your IDE for suggestions! Don't use deprecated methods!
//Access/create lists
nbtent.getCompoundList("Attributes");
nbtent.getStringList("Attributes");
//The list will be created if it doesn't exist, there is no setter for lists!
//Get
nbti.getString("Stringtest");
nbti.getInteger("Inttest");
nbti.getDouble("Doubletest");
nbti.getBoolean("Booleantest");
nbti.getKeys(); //Get all Tags
nbti.hasTag("Key");
nbti.removeKey("Key");
nbti.getOrCreateCompound("subtag"); // Get or create a subtag
NBTCompound comp = nbti.getCompound("subtag"); // Get the tag or null
B.mergeCompound(A); // Merge the data from compound A into B (Like the /data merge command)
comp.toString(); // Get the nbt as a Mojang-Json string
// Saving
ReadWriteNBT nbt = NBT.gameProfileToNBT(profile);
// Restoring
GameProfile profile = NBT.gameProfileFromNBT(nbt);
```
### Interface proxies
You may define your own interfaces extending ``NBTProxy`` to create wrappers around nbt.
Methods starting with ``has``/``get``/``set`` will be interpreted as their respective calls.
```java
interface TestInterface extends NBTProxy {
// Runs: return nbt.hasTag("kills");
boolean hasKills();
// Runs: nbt.setInteger("kills", amount);
void setKills(int amount);
// Runs: return nbt.getInteger("kills");
int getKills();
// Also supported
default void addKill() {
setKills(getKills() + 1);
}
}
```
Getters are also allowed to return other interfaces extending ``NBTProxy``.
And by using ``@NBTTarget`` annotation you may have a more gradual control over data. It allows setting the type of the method (``has``/``get``/``set``) and the data key.
```java
interface TestInterface extends NBTProxy {
// Will get PointsInterface from data in "other" key
@NBTTarget(type = Type.GET, value = "other")
PointsInterface getOtherInterface();
}
interface PointsInterface extends NBTProxy {
int getPoints();
void setPoints(int points);
}
```
To support other data types like ItemStacks, you need to override the init method and register appropriate handlers.
```java
interface TestInterface extends NBTProxy {
@Override
default void init() {
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
registerHandler(ReadableNBT.class, NBTHandlers.STORE_READABLE_TAG);
registerHandler(ReadWriteNBT.class, NBTHandlers.STORE_READWRITE_TAG);
}
ItemStack getItem();
void setItem(ItemStack item);
ReadWriteNBT getBlockStateTag();
void setBlockStateTag(ReadableNBT blockState);
}
```
``NBTHandlers`` class contains some pre-defined handlers.
###### Custom handlers
If you need to support custom data types that aren't available in ``NBTHandlers``, you can write your own by creating a new ``NBTHandler``.
You can refer to [NBTHandlers](https://github.com/tr7zw/Item-NBT-API/blob/master/item-nbt-api/src/main/java/de/tr7zw/changeme/nbtapi/handler/NBTHandlers.java) class to see how the default implementations are done.
### Data fixer utils
``DataFixerUtil`` allows updating nbt from older versions to more recent ones.
For example, given the input from 1.12.2:
`{Count:42,id:"cobblestone",tag:{display:{Name:"test"},ench:[{id:34,lvl:3}]}}`
You can update it to 1.20.6:
`{components:{"minecraft:custom_name":'{"text":"test"}',"minecraft:enchantments":{levels:{"minecraft:unbreaking":3}}},count:42,id:"minecraft:cobblestone"}`
By using the following code:
```java
DataFixerUtil.fixUpItemData(nbt, DataFixerUtil.VERSION1_12_2, DataFixerUtil.VERSION1_20_6);
```
You can also use ``DataFixerUtil.getCurrentVersion()`` to update the data to whatever version the server is running.
@@ -1,14 +0,0 @@
```java
Zombie zombie = (Zombie) b.getWorld().spawnEntity(b.getLocation().add(0, 1, 0), EntityType.ZOMBIE);
NBT.modify(zombie, nbt -> {
nbt.setByte("CanPickUpLoot", (byte) 1);
ReadWriteNBTCompoundList list = nbt.getCompoundList("Attributes");
for(int i = 0; i < list.size(); i++){
ReadWriteNBT lc = list.get(i);
if(lc.getString("Name").equals("generic.attackDamage")){
lc.setDouble("Base", 0.5d);
}
}
});
```
+2 -2
View File
@@ -1,5 +1,5 @@
[tr7zw](https://github.com/tr7zw)
[SpigotMC](https://www.spigotmc.org/resources/nbt-api.7939/)
[Modrinth](https://modrinth.com/plugin/nbtapi)
[Bukkit](https://dev.bukkit.org/projects/nbt-api)
[Hangar](https://hangar.papermc.io/tr7zw/NBTAPI)
[SpigotMC](https://www.spigotmc.org/resources/nbt-api.7939/)
[Bukkit](https://dev.bukkit.org/projects/nbt-api)
+12 -9
View File
@@ -1,21 +1,24 @@
[Home](https://github.com/tr7zw/Item-NBT-API/wiki)
[Using the NBT API](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API)
[Using Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven) /
[Using Gradle](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle)
[FAQ](https://github.com/tr7zw/Item-NBT-API/wiki/FAQ)
## Code Examples
### General
* [Converting Minecraft Objects to NBT and Strings](https://github.com/tr7zw/Item-NBT-API/wiki/Converting-Minecraft-Objects-to-NBT-and-Strings)
* [Merging Compounds](https://github.com/tr7zw/Item-NBT-API/wiki/Merging-Compounds-(Copy-the-data-from-one-onto-another-compound))
* [Basics](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API)
* [Items](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#working-with-items)
* [Block-Entities/Entities](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#working-with-entities-and-block-entities)
* [Blocks](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#working-with-blocks)
### Items
### Extras
* [Set a skull's skin using NBT API](https://github.com/tr7zw/Item-NBT-API/wiki/Set-a-skull's-skin-using-NBT-API)
### Entities
* [Zombie that can pick up loot and does 0.5 hearths of damage](https://github.com/tr7zw/Item-NBT-API/wiki/Zombie-that-can-pick-up-loot-and-does-0.5-hearths-of-damage)
* [Example usages](https://github.com/tr7zw/Item-NBT-API/wiki/Example-Usages)
* [NBT files](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#nbt-files)
* [NBT objects](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#converting-minecraft-objects-to-nbt-and-strings)
* [Interface proxies](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#interface-proxies)
* [Data fixer utils](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API#data-fixer-utils)