Compare commits

..
227 Commits
Author SHA1 Message Date
tr7zw 4dde60c0a6 Deploying to gh-pages from @ tr7zw/Item-NBT-API@da6be72d29 🚀 2024-12-28 19:13:19 +00:00
tr7zw 5d4c8392cc Deploying to gh-pages from @ tr7zw/Item-NBT-API@f3af749b11 🚀 2024-12-21 23:45:50 +00:00
tr7zw 3211d5c4ff Deploying to gh-pages from @ tr7zw/Item-NBT-API@d81c2b4e8e 🚀 2024-12-21 23:45:48 +00:00
tr7zw 5c39b36226 Deploying to gh-pages from @ tr7zw/Item-NBT-API@94192feb8f 🚀 2024-12-21 23:45:18 +00:00
tr7zw 48b7932568 Deploying to gh-pages from @ tr7zw/Item-NBT-API@af3d9c8502 🚀 2024-12-21 23:44:01 +00:00
tr7zw 51b0296e50 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ae98859524 🚀 2024-12-16 16:14:28 +00:00
tr7zw e5cfd36350 Deploying to gh-pages from @ tr7zw/Item-NBT-API@70f0bb62f9 🚀 2024-12-14 21:01:19 +00:00
tr7zw d9634fc4a9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@e2e8aad70a 🚀 2024-12-07 13:19:48 +00:00
tr7zw 27eda51ba5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d2de90ee25 🚀 2024-12-03 22:30:50 +00:00
tr7zw 4f4f02f3a9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@3425a6672d 🚀 2024-11-13 22:56:47 +00:00
tr7zw 38b4d5ca2d Deploying to gh-pages from @ tr7zw/Item-NBT-API@b339c9e9c2 🚀 2024-11-13 22:56:24 +00:00
tr7zw bfebe76c0a Deploying to gh-pages from @ tr7zw/Item-NBT-API@67616266da 🚀 2024-11-13 22:55:56 +00:00
tr7zw 39a983c3a5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@73776cfec4 🚀 2024-11-02 14:20:11 +00:00
tr7zw b1caeb7365 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bd674e31c0 🚀 2024-11-02 14:10:03 +00:00
tr7zw 027298235f Deploying to gh-pages from @ tr7zw/Item-NBT-API@42db79706c 🚀 2024-11-02 14:08:05 +00:00
tr7zw 6974cd5a2b Deploying to gh-pages from @ tr7zw/Item-NBT-API@3405ffe0a3 🚀 2024-11-02 12:26:29 +00:00
tr7zw 8143e3d3b2 Deploying to gh-pages from @ tr7zw/Item-NBT-API@f8736c8188 🚀 2024-08-27 16:09:29 +00:00
tr7zw d7386ec4d1 Deploying to gh-pages from @ tr7zw/Item-NBT-API@0f926998f6 🚀 2024-08-10 18:31:35 +00:00
tr7zw 956f3ff7c9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@3a44a5e989 🚀 2024-08-10 18:24:19 +00:00
tr7zw e958d7c097 Deploying to gh-pages from @ tr7zw/Item-NBT-API@30b931945c 🚀 2024-08-10 18:22:54 +00:00
tr7zw 493cbb321c Deploying to gh-pages from @ tr7zw/Item-NBT-API@88d8629541 🚀 2024-07-21 18:58:30 +00:00
tr7zw 998ce3a958 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ce26e180e6 🚀 2024-07-21 18:54:12 +00:00
tr7zw cadc79f304 Deploying to gh-pages from @ tr7zw/Item-NBT-API@2079123a42 🚀 2024-07-21 18:50:47 +00:00
tr7zw f8af76faf4 Deploying to gh-pages from @ tr7zw/Item-NBT-API@5280ba82a2 🚀 2024-06-20 20:40:08 +00:00
tr7zw be2c91057e Deploying to gh-pages from @ tr7zw/Item-NBT-API@522f732ed1 🚀 2024-06-20 20:36:33 +00:00
tr7zw f499253590 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ac84a4d69a 🚀 2024-06-20 20:22:12 +00:00
tr7zw 745df6bfe2 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d7e18c1cb6 🚀 2024-06-20 20:21:44 +00:00
tr7zw 2d5d03b1e7 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ffa612634a 🚀 2024-06-20 20:14:42 +00:00
tr7zw e4cfbbd26e Deploying to gh-pages from @ tr7zw/Item-NBT-API@2e20af40e5 🚀 2024-06-20 19:42:02 +00:00
tr7zw 3fb66aad40 Deploying to gh-pages from @ tr7zw/Item-NBT-API@25c59b0eae 🚀 2024-06-16 20:53:48 +00:00
tr7zw 50c7257373 Deploying to gh-pages from @ tr7zw/Item-NBT-API@3ec606ae21 🚀 2024-06-15 21:41:46 +00:00
tr7zw e3058d4ce5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@53216d3b7d 🚀 2024-06-15 21:08:30 +00:00
tr7zw c489158f29 Deploying to gh-pages from @ tr7zw/Item-NBT-API@7cf23201ce 🚀 2024-06-14 19:31:58 +00:00
tr7zw 37c6bc9e6c Deploying to gh-pages from @ tr7zw/Item-NBT-API@fe1d586f44 🚀 2024-06-14 10:35:54 +00:00
tr7zw 053e0e51e4 Deploying to gh-pages from @ tr7zw/Item-NBT-API@956ef15a1d 🚀 2024-06-13 19:17:45 +00:00
tr7zw 7ccafb3ac9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ed867749f8 🚀 2024-06-13 18:59:36 +00:00
tr7zw 0f9c04c659 Deploying to gh-pages from @ tr7zw/Item-NBT-API@82e52267b8 🚀 2024-06-13 18:30:19 +00:00
tr7zw 38ec6b5146 Deploying to gh-pages from @ tr7zw/Item-NBT-API@cf30cf996e 🚀 2024-06-13 17:59:01 +00:00
tr7zw 29edbbd010 Deploying to gh-pages from @ tr7zw/Item-NBT-API@153c72818a 🚀 2024-06-08 19:04:46 +00:00
tr7zw 37050144a8 Deploying to gh-pages from @ tr7zw/Item-NBT-API@633433d6d0 🚀 2024-06-08 19:04:17 +00:00
tr7zw 50fd7149ab Deploying to gh-pages from @ tr7zw/Item-NBT-API@8570c6f77e 🚀 2024-05-18 23:09:25 +00:00
tr7zw 58bbea97e3 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c0a9197113 🚀 2024-04-30 13:29:22 +00:00
tr7zw 34ab19662f Deploying to gh-pages from @ tr7zw/Item-NBT-API@e14dd4f82a 🚀 2024-04-29 22:16:03 +00:00
tr7zw 718ebc7f06 Deploying to gh-pages from @ tr7zw/Item-NBT-API@198dbfabae 🚀 2024-04-29 17:48:35 +00:00
tr7zw 4e6763a15e Deploying to gh-pages from @ tr7zw/Item-NBT-API@8bd49db49b 🚀 2024-04-28 17:33:24 +00:00
tr7zw 77628b42ff Deploying to gh-pages from @ tr7zw/Item-NBT-API@caf1d7cd98 🚀 2024-04-25 16:59:59 +00:00
tr7zw 2bddf68b8a Deploying to gh-pages from @ tr7zw/Item-NBT-API@027f2a2edd 🚀 2024-04-25 16:41:50 +00:00
tr7zw 8e390856d1 Deploying to gh-pages from @ tr7zw/Item-NBT-API@b74b0b852e 🚀 2024-04-25 16:06:31 +00:00
tr7zw 31b518f64d Deploying to gh-pages from @ tr7zw/Item-NBT-API@6ea6ab7e13 🚀 2024-04-25 16:06:20 +00:00
tr7zw e20ba82bd4 Deploying to gh-pages from @ tr7zw/Item-NBT-API@372225626c 🚀 2024-04-24 14:06:21 +00:00
tr7zw fee2c02d5f Deploying to gh-pages from @ tr7zw/Item-NBT-API@fdc16aad69 🚀 2024-04-23 23:49:59 +00:00
tr7zw cff69b50a3 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c723eef68b 🚀 2024-04-23 23:43:38 +00:00
tr7zw 37f7642a87 Deploying to gh-pages from @ tr7zw/Item-NBT-API@03299012ac 🚀 2024-04-23 23:42:29 +00:00
tr7zw 8d5184f6d2 Deploying to gh-pages from @ tr7zw/Item-NBT-API@9367942b54 🚀 2024-04-23 22:11:04 +00:00
tr7zw c4010866bc Deploying to gh-pages from @ tr7zw/Item-NBT-API@0b8d5b153c 🚀 2024-04-06 16:56:50 +00:00
tr7zw 7ca99e7109 Deploying to gh-pages from @ tr7zw/Item-NBT-API@246e3fa38e 🚀 2024-04-06 16:56:34 +00:00
tr7zw 0b71af4de5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@3afd9df2ae 🚀 2024-03-24 16:30:10 +00:00
tr7zw ff3fd6872b Deploying to gh-pages from @ tr7zw/Item-NBT-API@2cb16ed0c4 🚀 2024-03-21 20:40:12 +00:00
tr7zw 08a3027f26 Deploying to gh-pages from @ tr7zw/Item-NBT-API@85cc13a817 🚀 2024-03-18 18:49:11 +00:00
tr7zw 4a4d26a9ec Deploying to gh-pages from @ tr7zw/Item-NBT-API@75c8575b5b 🚀 2024-02-22 19:00:21 +00:00
tr7zw b8c0ac7e9c Deploying to gh-pages from @ tr7zw/Item-NBT-API@330fb7711c 🚀 2024-02-12 23:24:35 +00:00
tr7zw 525c02b243 Deploying to gh-pages from @ tr7zw/Item-NBT-API@a37a2c6729 🚀 2024-01-23 23:44:47 +00:00
tr7zw 5524852918 Deploying to gh-pages from @ tr7zw/Item-NBT-API@eee2dfa181 🚀 2024-01-01 15:12:09 +00:00
tr7zw 92f4d8f6a9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ccd78d1b00 🚀 2023-12-27 21:19:42 +00:00
tr7zw 4ef7fe2896 Deploying to gh-pages from @ tr7zw/Item-NBT-API@87fd1ee8ee 🚀 2023-12-19 18:52:20 +00:00
tr7zw 6d3a2f8c70 Deploying to gh-pages from @ tr7zw/Item-NBT-API@af0528328f 🚀 2023-12-19 18:52:09 +00:00
tr7zw f991efdfed Deploying to gh-pages from @ tr7zw/Item-NBT-API@7bf91d0510 🚀 2023-12-10 13:30:17 +00:00
tr7zw c2b61dd2d4 Deploying to gh-pages from @ tr7zw/Item-NBT-API@aed5af12a2 🚀 2023-12-08 20:43:39 +00:00
tr7zw 68ce82f878 Deploying to gh-pages from @ tr7zw/Item-NBT-API@dd6e9e8312 🚀 2023-12-05 15:25:17 +00:00
tr7zw e58782c4f8 Deploying to gh-pages from @ tr7zw/Item-NBT-API@4ad7a172a0 🚀 2023-11-11 16:28:21 +00:00
tr7zw 21201dc06f Deploying to gh-pages from @ tr7zw/Item-NBT-API@6f112c0130 🚀 2023-11-11 16:28:02 +00:00
tr7zw 3b28393b81 Deploying to gh-pages from @ tr7zw/Item-NBT-API@f5a1b21761 🚀 2023-11-04 16:51:23 +00:00
tr7zw fcdc150900 Deploying to gh-pages from @ tr7zw/Item-NBT-API@4af722752e 🚀 2023-11-03 20:23:51 +00:00
tr7zw 2e56777e13 Deploying to gh-pages from @ tr7zw/Item-NBT-API@af3b7a49d0 🚀 2023-10-26 19:15:06 +00:00
tr7zw 2dba049bcb Deploying to gh-pages from @ tr7zw/Item-NBT-API@189ff2f369 🚀 2023-10-24 23:07:18 +00:00
tr7zw e1321862ac Deploying to gh-pages from @ tr7zw/Item-NBT-API@a8a81eee83 🚀 2023-10-22 15:47:04 +00:00
tr7zw a62b6329b1 Deploying to gh-pages from @ tr7zw/Item-NBT-API@fb384784f0 🚀 2023-10-22 15:46:17 +00:00
tr7zw 2a97e723fb Deploying to gh-pages from @ tr7zw/Item-NBT-API@dc333ae25a 🚀 2023-09-21 21:23:14 +00:00
tr7zw 8499c91783 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d18adb459d 🚀 2023-09-21 21:02:45 +00:00
tr7zw b916396ea6 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bc914b73bc 🚀 2023-09-21 18:53:04 +00:00
tr7zw 56ae63007e Deploying to gh-pages from @ tr7zw/Item-NBT-API@60172ea2a7 🚀 2023-09-21 18:27:39 +00:00
tr7zw 2382aec144 Deploying to gh-pages from @ tr7zw/Item-NBT-API@7b30c1533e 🚀 2023-09-21 18:18:03 +00:00
tr7zw 248084ebe3 Deploying to gh-pages from @ tr7zw/Item-NBT-API@a1c90658f3 🚀 2023-09-19 20:29:38 +00:00
tr7zw e745f49bb8 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d989797453 🚀 2023-09-14 23:17:53 +00:00
tr7zw 25e505c9a5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c70aefe670 🚀 2023-09-14 22:00:32 +00:00
tr7zw f55772dec6 Deploying to gh-pages from @ tr7zw/Item-NBT-API@7d0fc09470 🚀 2023-09-13 16:56:38 +00:00
tr7zw 0c2394084e Deploying to gh-pages from @ tr7zw/Item-NBT-API@427113e6f0 🚀 2023-09-13 16:53:30 +00:00
tr7zw 2978b942b8 Deploying to gh-pages from @ tr7zw/Item-NBT-API@20ae1cb178 🚀 2023-09-12 22:23:30 +00:00
tr7zw e9dfe70e06 Deploying to gh-pages from @ tr7zw/Item-NBT-API@9b60978af6 🚀 2023-09-08 18:08:22 +00:00
tr7zw 83dbce0908 Deploying to gh-pages from @ tr7zw/Item-NBT-API@598db19d8d 🚀 2023-09-08 17:34:40 +00:00
tr7zw 8452c6b7e0 Deploying to gh-pages from @ tr7zw/Item-NBT-API@7141c56319 🚀 2023-09-04 11:03:40 +00:00
tr7zw ffd55d160c Deploying to gh-pages from @ tr7zw/Item-NBT-API@3bb4d7b449 🚀 2023-08-10 23:09:21 +00:00
tr7zw 79f529c694 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d3d7a3138c 🚀 2023-08-08 18:12:53 +00:00
tr7zw 08f1197e0d Deploying to gh-pages from @ tr7zw/Item-NBT-API@6b1d4e28ed 🚀 2023-08-06 14:18:49 +00:00
tr7zw d951c83466 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bde0bf7c8d 🚀 2023-08-06 14:05:38 +00:00
tr7zw 73cef7c2c3 Deploying to gh-pages from @ tr7zw/Item-NBT-API@6e8b8f3565 🚀 2023-08-05 22:09:18 +00:00
tr7zw 75bfea1871 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d653bc67d8 🚀 2023-08-04 19:03:11 +00:00
tr7zw 4c69189e60 Deploying to gh-pages from @ tr7zw/Item-NBT-API@533765ba74 🚀 2023-08-02 22:52:05 +00:00
tr7zw b94ad1c2d6 Deploying to gh-pages from @ tr7zw/Item-NBT-API@0232f720cb 🚀 2023-08-02 22:32:02 +00:00
tr7zw 437bd7ee92 Deploying to gh-pages from @ tr7zw/Item-NBT-API@fa62c9825d 🚀 2023-08-02 21:00:19 +00:00
tr7zw 2164d63086 Deploying to gh-pages from @ tr7zw/Item-NBT-API@5051bc834d 🚀 2023-08-02 20:35:30 +00:00
tr7zw fa6eeb29ee Deploying to gh-pages from @ tr7zw/Item-NBT-API@10ea4b1767 🚀 2023-08-02 20:26:11 +00:00
tr7zw cde6529905 Deploying to gh-pages from @ tr7zw/Item-NBT-API@b801b46bce 🚀 2023-08-02 17:35:20 +00:00
tr7zw bc20db1003 Deploying to gh-pages from @ tr7zw/Item-NBT-API@fc94dac05b 🚀 2023-07-28 15:31:00 +00:00
tr7zw 814205b332 Deploying to gh-pages from @ tr7zw/Item-NBT-API@1ab5f70c88 🚀 2023-07-26 13:38:11 +00:00
tr7zw a00ab7440e Deploying to gh-pages from @ tr7zw/Item-NBT-API@c90636970a 🚀 2023-07-25 22:20:01 +00:00
tr7zw 7ba193ce47 Deploying to gh-pages from @ tr7zw/Item-NBT-API@f3b1cc27e7 🚀 2023-07-25 21:16:29 +00:00
tr7zw 179b142803 Deploying to gh-pages from @ tr7zw/Item-NBT-API@33eddbaece 🚀 2023-07-25 19:19:24 +00:00
tr7zw bf59db7e11 Deploying to gh-pages from @ tr7zw/Item-NBT-API@20f9b2f1ce 🚀 2023-07-24 01:01:53 +00:00
tr7zw f68c0b0357 Deploying to gh-pages from @ tr7zw/Item-NBT-API@affad0d92c 🚀 2023-07-23 22:09:09 +00:00
tr7zw 46515c8724 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ba169438ba 🚀 2023-07-17 17:55:41 +00:00
tr7zw 485bfb13e7 Deploying to gh-pages from @ tr7zw/Item-NBT-API@9ff2e38d07 🚀 2023-07-05 22:31:10 +00:00
tr7zw a17b792b08 Deploying to gh-pages from @ tr7zw/Item-NBT-API@8b76359143 🚀 2023-07-05 22:22:06 +00:00
tr7zw 47670787f0 Deploying to gh-pages from @ tr7zw/Item-NBT-API@a341c6a81e 🚀 2023-07-04 22:43:53 +00:00
tr7zw 0385106a77 Deploying to gh-pages from @ tr7zw/Item-NBT-API@23b9f9128f 🚀 2023-07-04 22:21:53 +00:00
tr7zw 9c93319247 Deploying to gh-pages from @ tr7zw/Item-NBT-API@81c3b75dc9 🚀 2023-07-04 22:18:37 +00:00
tr7zw e3ac4d0da5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d3b1d00e15 🚀 2023-07-04 22:09:27 +00:00
tr7zw f5bffca69c Deploying to gh-pages from @ tr7zw/Item-NBT-API@177d1fe5b7 🚀 2023-07-04 21:36:35 +00:00
tr7zw c7c25b7f37 Deploying to gh-pages from @ tr7zw/Item-NBT-API@f1682205d8 🚀 2023-07-04 21:21:29 +00:00
tr7zw 4eae5f3e1c Deploying to gh-pages from @ tr7zw/Item-NBT-API@1bfdb93622 🚀 2023-07-04 21:07:44 +00:00
tr7zw 1c8411ee54 Deploying to gh-pages from @ tr7zw/Item-NBT-API@09af2df542 🚀 2023-07-04 21:06:39 +00:00
tr7zw 40d23fb0f5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@cd1bdc0436 🚀 2023-07-04 20:58:14 +00:00
tr7zw 538fe3e974 Deploying to gh-pages from @ tr7zw/Item-NBT-API@b2ea170f9e 🚀 2023-07-04 20:04:58 +00:00
tr7zw f2b516c7de Deploying to gh-pages from @ tr7zw/Item-NBT-API@9bdd79ef7d 🚀 2023-06-27 12:44:37 +00:00
tr7zw db2d032ab8 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bfe627658e 🚀 2023-06-21 12:13:07 +00:00
tr7zw a1a62666c3 Deploying to gh-pages from @ tr7zw/Item-NBT-API@a929bd2ddc 🚀 2023-06-17 00:00:07 +00:00
tr7zw 07c433fd15 Deploying to gh-pages from @ tr7zw/Item-NBT-API@62105ead48 🚀 2023-06-15 14:54:38 +00:00
tr7zw d21f091230 Deploying to gh-pages from @ tr7zw/Item-NBT-API@f7bceec594 🚀 2023-06-15 14:53:38 +00:00
tr7zw 2c7d14e448 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c377927ee6 🚀 2023-06-07 18:29:52 +00:00
tr7zw 8fdf10207b Deploying to gh-pages from @ tr7zw/Item-NBT-API@0653f47bc1 🚀 2023-06-07 18:26:06 +00:00
tr7zw 04dd24ba07 Deploying to gh-pages from @ tr7zw/Item-NBT-API@5588fc60b4 🚀 2023-05-23 08:11:17 +00:00
tr7zw 42a9e31532 Deploying to gh-pages from @ tr7zw/Item-NBT-API@45dd70afad 🚀 2023-05-10 19:52:16 +00:00
tr7zw 74ba9fcc15 Deploying to gh-pages from @ tr7zw/Item-NBT-API@175065dac4 🚀 2023-05-07 22:18:36 +00:00
tr7zw d6fb2f494c Deploying to gh-pages from @ tr7zw/Item-NBT-API@91b1e64e85 🚀 2023-05-07 22:12:26 +00:00
tr7zw 3cc10ade03 Deploying to gh-pages from @ tr7zw/Item-NBT-API@243d17a71e 🚀 2023-05-07 21:54:43 +00:00
tr7zw f709d204d6 Deploying to gh-pages from @ tr7zw/Item-NBT-API@f4bfca8ba8 🚀 2023-05-07 18:17:14 +00:00
tr7zw 740fc32332 Deploying to gh-pages from @ tr7zw/Item-NBT-API@37378b4ee1 🚀 2023-05-06 14:18:41 +00:00
tr7zw f9e71ef82d Deploying to gh-pages from @ tr7zw/Item-NBT-API@662c0bb92d 🚀 2023-05-06 14:17:46 +00:00
tr7zw 1ddc9955e6 Deploying to gh-pages from @ tr7zw/Item-NBT-API@5759b68d89 🚀 2023-05-06 13:53:04 +00:00
tr7zw 73adc850ad Deploying to gh-pages from @ tr7zw/Item-NBT-API@c22cbaaaf0 🚀 2023-05-06 13:52:57 +00:00
tr7zw bd9d71b8bf Deploying to gh-pages from @ tr7zw/Item-NBT-API@6f25881eda 🚀 2023-03-16 18:18:12 +00:00
tr7zw 9633a44785 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bd69504f54 🚀 2023-03-09 20:10:11 +00:00
tr7zw fda4eaf341 Deploying to gh-pages from @ tr7zw/Item-NBT-API@8dc51a3d30 🚀 2023-02-16 09:05:05 +00:00
tr7zw 2d4e5db3b9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@4a93fdc869 🚀 2023-02-15 21:09:03 +00:00
tr7zw cf8ae46b8a Deploying to gh-pages from @ tr7zw/Item-NBT-API@c905de852d 🚀 2023-01-31 11:18:52 +00:00
tr7zw 4e494b6457 Deploying to gh-pages from @ tr7zw/Item-NBT-API@1123e27b10 🚀 2023-01-31 10:44:44 +00:00
tr7zw 4368af872f Deploying to gh-pages from @ tr7zw/Item-NBT-API@05b4249bb4 🚀 2023-01-25 19:35:13 +00:00
tr7zw 021994ed1f Deploying to gh-pages from @ tr7zw/Item-NBT-API@e399590d1d 🚀 2023-01-25 19:34:43 +00:00
tr7zw 18082e610b Deploying to gh-pages from @ tr7zw/Item-NBT-API@310682ea25 🚀 2023-01-24 10:04:11 +00:00
tr7zw 2eed0e5591 Deploying to gh-pages from @ tr7zw/Item-NBT-API@79e1e62862 🚀 2023-01-03 22:54:39 +00:00
tr7zw 7645fbb4bb Deploying to gh-pages from @ tr7zw/Item-NBT-API@f648aca74b 🚀 2022-12-14 16:11:56 +00:00
tr7zw aee4f5f513 Deploying to gh-pages from @ tr7zw/Item-NBT-API@9e79a604d3 🚀 2022-12-14 16:00:09 +00:00
tr7zw 0e90dd17d7 Deploying to gh-pages from @ tr7zw/Item-NBT-API@54d9ac614e 🚀 2022-12-11 18:52:13 +00:00
tr7zw d58480a8ed Deploying to gh-pages from @ tr7zw/Item-NBT-API@306812264f 🚀 2022-12-10 23:06:57 +00:00
tr7zw 850ddd852d Deploying to gh-pages from @ tr7zw/Item-NBT-API@38c42ed577 🚀 2022-12-07 20:51:10 +00:00
tr7zw 5026b5b887 Deploying to gh-pages from @ tr7zw/Item-NBT-API@3c20b5db32 🚀 2022-12-01 19:03:36 +00:00
tr7zw d4b810bd75 Deploying to gh-pages from @ tr7zw/Item-NBT-API@f10ba986ba 🚀 2022-11-25 22:57:38 +00:00
tr7zw 4f06f53541 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c5c96e6d17 🚀 2022-11-24 19:02:43 +00:00
tr7zw 1493f32caa Deploying to gh-pages from @ tr7zw/Item-NBT-API@22ded53d31 🚀 2022-11-24 19:01:08 +00:00
tr7zw 136ec1d5fc Deploying to gh-pages from @ tr7zw/Item-NBT-API@49fd713c63 🚀 2022-11-10 22:47:36 +00:00
tr7zw 35bfd9cbf9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@58f2fda332 🚀 2022-11-10 22:41:45 +00:00
tr7zw 58804323ef Deploying to gh-pages from @ tr7zw/Item-NBT-API@c06f8f8145 🚀 2022-11-10 22:16:50 +00:00
tr7zw fa93851bec Deploying to gh-pages from @ tr7zw/Item-NBT-API@45504d09f0 🚀 2022-11-10 22:08:52 +00:00
tr7zw e584023026 Deploying to gh-pages from @ tr7zw/Item-NBT-API@88fb62677d 🚀 2022-11-10 18:31:37 +00:00
tr7zw 17e0349cdd Deploying to gh-pages from @ tr7zw/Item-NBT-API@9aad17aa0d 🚀 2022-11-10 16:30:09 +00:00
tr7zw 15128bb852 Deploying to gh-pages from @ tr7zw/Item-NBT-API@fc2c944bb7 🚀 2022-11-10 16:18:29 +00:00
tr7zw 27bfeb9c47 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c6f8f4163a 🚀 2022-11-10 15:13:50 +00:00
tr7zw bbdc9152ac Deploying to gh-pages from @ tr7zw/Item-NBT-API@c6f8f4163a 🚀 2022-11-10 15:13:48 +00:00
tr7zw eaa041d7b7 Deploying to gh-pages from @ tr7zw/Item-NBT-API@793540f282 🚀 2022-11-09 19:30:35 +00:00
tr7zw fca9e78b1b Deploying to gh-pages from @ tr7zw/Item-NBT-API@793540f282 🚀 2022-11-09 19:30:33 +00:00
tr7zw e277c67629 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d30f984376 🚀 2022-11-07 00:56:48 +00:00
tr7zw cf9a983231 Deploying to gh-pages from @ tr7zw/Item-NBT-API@d30f984376 🚀 2022-11-07 00:56:47 +00:00
tr7zw 01066f990b Deploying to gh-pages from @ tr7zw/Item-NBT-API@3a987af139 🚀 2022-11-07 00:37:45 +00:00
tr7zw 6a68f7f219 Deploying to gh-pages from @ tr7zw/Item-NBT-API@3a987af139 🚀 2022-11-07 00:37:43 +00:00
tr7zw fe1605d944 Deploying to gh-pages from @ tr7zw/Item-NBT-API@783d4548ab 🚀 2022-10-27 23:37:22 +00:00
tr7zw 70b593e338 Deploying to gh-pages from @ tr7zw/Item-NBT-API@783d4548ab 🚀 2022-10-27 23:37:19 +00:00
tr7zw 1c8135f29a Deploying to gh-pages from @ tr7zw/Item-NBT-API@766d57a085 🚀 2022-10-11 18:16:57 +00:00
tr7zw 6c79f5ac7a Deploying to gh-pages from @ tr7zw/Item-NBT-API@766d57a085 🚀 2022-10-11 18:16:55 +00:00
tr7zw 12eda26763 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bf65c7ce68 🚀 2022-10-03 00:25:09 +00:00
tr7zw ebd6e44729 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bf65c7ce68 🚀 2022-10-03 00:25:07 +00:00
tr7zw bd6b3dc22b Deploying to gh-pages from @ tr7zw/Item-NBT-API@42f4af52bc 🚀 2022-10-03 00:23:54 +00:00
tr7zw 689c66f6a7 Deploying to gh-pages from @ tr7zw/Item-NBT-API@42f4af52bc 🚀 2022-10-03 00:23:53 +00:00
tr7zw 654c0f4c31 Deploying to gh-pages from @ tr7zw/Item-NBT-API@8e8285b36d 🚀 2022-09-27 20:24:18 +00:00
tr7zw c80de011a0 Deploying to gh-pages from @ tr7zw/Item-NBT-API@8e8285b36d 🚀 2022-09-27 20:24:14 +00:00
tr7zw 2096cab041 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ca76df589b 🚀 2022-09-15 12:23:33 +00:00
tr7zw 4c7bf37103 Deploying to gh-pages from @ tr7zw/Item-NBT-API@ca76df589b 🚀 2022-09-15 12:23:32 +00:00
tr7zw 4bb5a7ebee Deploying to gh-pages from @ tr7zw/Item-NBT-API@9e6ae13711 🚀 2022-09-15 12:23:30 +00:00
tr7zw 91198208fd Deploying to gh-pages from @ tr7zw/Item-NBT-API@9e6ae13711 🚀 2022-09-15 12:23:28 +00:00
tr7zw 1ec52ec80a Deploying to gh-pages from @ tr7zw/Item-NBT-API@7263b5a12f 🚀 2022-09-04 14:52:42 +00:00
tr7zw 95e47e41bd Deploying to gh-pages from @ tr7zw/Item-NBT-API@7263b5a12f 🚀 2022-09-04 14:52:38 +00:00
tr7zw 5a855939e9 Deploying to gh-pages from @ tr7zw/Item-NBT-API@e500a443a1 🚀 2022-09-03 19:25:21 +00:00
tr7zw 87277ed801 Deploying to gh-pages from @ tr7zw/Item-NBT-API@e500a443a1 🚀 2022-09-03 19:25:18 +00:00
tr7zw 16fd0c3934 Deploying to gh-pages from @ tr7zw/Item-NBT-API@332f9e4b42 🚀 2022-09-03 19:15:08 +00:00
tr7zw ae4817ff86 Deploying to gh-pages from @ tr7zw/Item-NBT-API@332f9e4b42 🚀 2022-09-03 19:15:07 +00:00
tr7zw f65fdf8950 Deploying to gh-pages from @ tr7zw/Item-NBT-API@42e37f0838 🚀 2022-09-03 18:32:50 +00:00
tr7zw a9438a4e31 Deploying to gh-pages from @ tr7zw/Item-NBT-API@42e37f0838 🚀 2022-09-03 18:32:48 +00:00
tr7zw 0271807b5f Deploying to gh-pages from @ tr7zw/Item-NBT-API@efd22f2bd1 🚀 2022-09-03 18:31:02 +00:00
tr7zw 574efc59e8 Deploying to gh-pages from @ tr7zw/Item-NBT-API@efd22f2bd1 🚀 2022-09-03 18:31:00 +00:00
tr7zw fac549cb0a Deploying to gh-pages from @ tr7zw/Item-NBT-API@4dace8749d 🚀 2022-09-03 18:30:21 +00:00
tr7zw b3456026ca Deploying to gh-pages from @ tr7zw/Item-NBT-API@4dace8749d 🚀 2022-09-03 18:30:20 +00:00
tr7zw 9861724ee5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@82dbb4b7d1 🚀 2022-09-03 18:29:57 +00:00
tr7zw 9d62f6923b Deploying to gh-pages from @ tr7zw/Item-NBT-API@82dbb4b7d1 🚀 2022-09-03 18:29:56 +00:00
tr7zw 2a4d34ef62 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bb85fd092d 🚀 2022-09-03 18:17:17 +00:00
tr7zw ff7f234184 Deploying to gh-pages from @ tr7zw/Item-NBT-API@bb85fd092d 🚀 2022-09-03 18:17:15 +00:00
tr7zw cc40b199c5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c9d4ec6cc1 🚀 2022-09-03 18:06:47 +00:00
tr7zw b0bfe7cfc5 Deploying to gh-pages from @ tr7zw/Item-NBT-API@c9d4ec6cc1 🚀 2022-09-03 18:06:45 +00:00
tr7zw 4445488ab2 Deploying to gh-pages from @ tr7zw/Item-NBT-API@0a033f1fc9 🚀 2022-07-27 23:14:20 +00:00
tr7zw 883369db62 Deploying to gh-pages from @ tr7zw/Item-NBT-API@0a033f1fc9 🚀 2022-07-27 23:14:18 +00:00
tr7zw 58a7f1b853 Deploying to gh-pages from @ tr7zw/Item-NBT-API@0954eaa294 🚀 2022-07-27 22:31:59 +00:00
tr7zw 286062c2d7 Deploying to gh-pages from @ tr7zw/Item-NBT-API@0954eaa294 🚀 2022-07-27 22:31:57 +00:00
tr7zw 535243d424 Deploying to gh-pages from @ tr7zw/Item-NBT-API@1b7465b990 🚀 2022-07-27 22:29:48 +00:00
tr7zw 4694412eb3 Deploying to gh-pages from @ tr7zw/Item-NBT-API@1b7465b990 🚀 2022-07-27 22:29:46 +00:00
tr7zw 931a811064 Deploying to gh-pages from @ tr7zw/Item-NBT-API@854524062e 🚀 2022-07-27 22:26:22 +00:00
tr7zw 324aba64ee Deploying to gh-pages from @ tr7zw/Item-NBT-API@854524062e 🚀 2022-07-27 22:26:18 +00:00
tr7zw 0f6ee075eb Deploying to gh-pages from @ tr7zw/Item-NBT-API@4e498e3247 🚀 2022-07-27 21:42:20 +00:00
tr7zw cacfaece2c Deploying to gh-pages from @ tr7zw/Item-NBT-API@4e498e3247 🚀 2022-07-27 21:42:18 +00:00
tr7zw 970fa482be Deploying to gh-pages from @ tr7zw/Item-NBT-API@54d3d4a83f 🚀 2022-06-26 21:38:59 +00:00
tr7zw 05b982d769 Deploying to gh-pages from @ tr7zw/Item-NBT-API@54d3d4a83f 🚀 2022-06-26 21:38:58 +00:00
tr7zw 57ef0ac41d Deploying to gh-pages from @ tr7zw/Item-NBT-API@7ae34cc78c 🚀 2022-06-26 21:37:28 +00:00
tr7zw c2ce0f49eb Deploying to gh-pages from @ tr7zw/Item-NBT-API@7ae34cc78c 🚀 2022-06-26 21:37:25 +00:00
tr7zw dc3ce01a7f Update index.html 2022-06-15 19:43:07 +02:00
tr7zw c2fef6a5da Remove other data, add redirect 2022-06-15 19:37:54 +02:00
tr7zw 8cacee954b Deploying to gh-pages from @ tr7zw/Item-NBT-API@80facd8d8b 🚀 2022-06-15 17:26:47 +00:00
tr7zw 669ac3eec0 Deploying to gh-pages from @ tr7zw/Item-NBT-API@80facd8d8b 🚀 2022-06-15 17:26:44 +00:00
tr7zw c5e4d21a00 Deploying to gh-pages from @ tr7zw/Item-NBT-API@8e4e674443 🚀 2022-06-15 17:17:24 +00:00
tr7zw 2e1574faab Deploying to gh-pages from @ 9d1448f96e 🚀 2022-06-15 17:08:08 +00:00
tr7zw c056b40b66 Initial gh-pages commit 2022-06-15 17:08:06 +00:00
661 changed files with 136955 additions and 13650 deletions

No files matched your search

-1
View File
@@ -1 +0,0 @@
text eol=lf
-3
View File
@@ -1,3 +0,0 @@
# These are supported funding model platforms
ko_fi: tr7zw
-14
View File
@@ -1,14 +0,0 @@
version: 2
updates:
- package-ecosystem: maven
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
ignore:
- dependency-name: com.github.ekryd.sortpom:sortpom-maven-plugin
versions:
- 2.13.1
- 2.14.0
- 2.14.1
- 2.15.0
-36
View File
@@ -1,36 +0,0 @@
name: Javadoc CI
on:
push:
branches:
- master
permissions:
contents: write
jobs:
javadoc:
if: ${{ github.repository_owner == 'tr7zw' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
uses: actions/setup-java@v3
with:
distribution: zulu
java-version: 8
- name: Build with Maven
run: mvn package
- 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-plugin && cp -r item-nbt-plugin/target/apidocs/* artifacts/v2-plugin
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages
clean: false
folder: artifacts
-18
View File
@@ -1,18 +0,0 @@
name: Java CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
uses: actions/setup-java@v3
with:
distribution: zulu
java-version: 8
- name: Build with Maven
run: mvn install --file pom.xml
-34
View File
@@ -1,34 +0,0 @@
name: Wiki CI
on:
push:
branches:
- master
permissions:
contents: write
jobs:
wiki:
if: ${{ github.repository_owner == 'tr7zw' }}
runs-on: ubuntu-latest
steps:
- name: Checkout base code
uses: actions/checkout@v3
with:
path: base-code
- name: Checkout wiki code
uses: actions/checkout@v3
with:
repository: ${{github.repository}}.wiki
path: wiki
- name: Push to wiki
run: |
cd wiki
rm *.md
cp ../base-code/wiki/* ./
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .
git diff-index --quiet HEAD || (git commit -m "Add changes" && git push)
-106
View File
@@ -1,106 +0,0 @@
### Java files ###
*.class
# Package Files
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
# Ignore project files
*.iml
# Ignore IDEA directory
.idea/
# File-based project format:
*.ipr
*.iws
### Plugin-specific files: ###
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.factorypath
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### Git ###
# Don't exclude the .gitignore itself
!.gitignore
.vscode/settings.json
View File
Whitespace-only changes.
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 - 2021, tr7zw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-26
View File
@@ -1,26 +0,0 @@
# 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.
[Server Owner/Developer Wiki](https://github.com/tr7zw/Item-NBT-API/wiki)
### Build/Maven/Sonar Status
[![Build Status](https://ci.codemc.org/buildStatus/icon?job=Tr7zw%2FItem-NBT-API)](https://ci.codemc.org/job/Tr7zw/job/Item-NBT-API/)[![](https://sonarcloud.io/api/project_badges/measure?project=tr7zw_Item-NBT-API&metric=ncloc)](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)[![](https://sonarcloud.io/api/project_badges/measure?project=tr7zw_Item-NBT-API&metric=duplicated_lines_density)](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)[![](https://sonarcloud.io/api/project_badges/measure?project=tr7zw_Item-NBT-API&metric=sqale_rating)](https://sonarcloud.io/summary/overall?id=tr7zw_Item-NBT-API)
[![Discord](https://img.shields.io/discord/342814924310970398?color=%237289DA&label=Discord&logo=discord&logoColor=white)](https://discordapp.com/invite/yk4caxM)
[![Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dtr7zw%26type%3Dpatrons&style=for-the-badge)](https://www.patreon.com/tr7zw)
### SpigotMC Status
[![Version](https://badges.spiget.org/resources/version/Version-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/rating/Rating-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/downloads/SpigotDownloads-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![bStats Servers](https://img.shields.io/bstats/servers/1058.svg?color=green&label=OnlineServers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)[![bStats Players](https://img.shields.io/bstats/players/1058.svg?color=green&label=OnlinePlayers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)[![All Contributors](https://img.shields.io/badge/all_contributors-13-green.svg?style=plastic)](#contributors-%e2%9c%a8)
## Getting started
Import the API [using Maven](https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven), then check out the [basic usage](https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API) or code examples like [working with Skulls](https://github.com/tr7zw/Item-NBT-API/wiki/Set-a-skull's-skin-using-NBT-API).
### bStats
[![bStats Stats](https://bstats.org/signatures/bukkit/ItemNBTAPI.svg)](https://bstats.org/plugin/bukkit/ItemNBTAPI)
### Github Stargazers
<img src="https://starchart.cc/tr7zw/Item-NBT-API.svg" alt="stargazers" width="800"/>
-21
View File
@@ -1,21 +0,0 @@
# (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.
[Server Owner/Developer Wiki](https://github.com/tr7zw/Item-NBT-API/wiki)
### Build/Maven/Sonar Status
[![Build Status](https://github.com/tr7zw/Item-NBT-API/workflows/Java%20CI/badge.svg)](https://ci.codemc.org/job/Tr7zw/job/Item-NBT-API/)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=alert_status)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=ncloc)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)[![](https://sonarcloud.io/api/project_badges/measure?project=de.tr7zw%3Aitem-nbt-parent&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=de.tr7zw%3Aitem-nbt-parent)
Discord:[![Discord](https://img.shields.io/discord/342814924310970398?color=%237289DA&label=Discord&logo=discord&logoColor=white)](https://discordapp.com/invite/yk4caxM)
### SpigotMC Status
[![Version](https://badges.spiget.org/resources/version/Version-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/rating/Rating-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![Rating](https://badges.spiget.org/resources/downloads/SpigotDownloads-yellow-7939.svg)](https://www.spigotmc.org/resources/item-entity-tile-nbt-api.7939/)[![bStats Servers](https://img.shields.io/bstats/servers/1058.svg?color=green&label=OnlineServers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)[![bStats Players](https://img.shields.io/bstats/players/1058.svg?color=green&label=OnlinePlayers&style=plastic)](https://bstats.org/plugin/bukkit/ItemNBTAPI)
## 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).
### bStats
[![bStats Stats](https://bstats.org/signatures/bukkit/ItemNBTAPI.svg)](https://bstats.org/plugin/bukkit/ItemNBTAPI)
-390
View File
@@ -1,390 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="21">
<profile kind="CodeFormatterProfile" name="Java Conventions Spaces" version="21">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="8"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>
+9
View File
@@ -0,0 +1,9 @@
<meta property="og:type" content="website">
<meta property="og:url" content="https://tr7zw.github.io/project/nbtapi/">
<meta property="og:title" content="NBTAPI">
<meta property="og:description" content="Add custom NBT tags to Items/Tiles/Entities without NMS!">
<meta property="og:image" content="https://tr7zw.github.io/images/nbtapi-logo.png">
<meta http-equiv="Refresh" content="0; url='https://tr7zw.github.io/project/nbtapi/'" />
<script>
window.location.href = "https://tr7zw.github.io/project/nbtapi/";
</script>
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 - 2021, tr7zw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-48
View File
@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
</parent>
<artifactId>item-nbt-api</artifactId>
<packaging>jar</packaging>
<build>
<defaultGoal>clean install javadoc:javadoc</defaultGoal>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>LICENSE</resource>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>shade</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -1,553 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.annotation.Nullable;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.inventory.ItemStack;
import com.mojang.authlib.GameProfile;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteItemNBT;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.changeme.nbtapi.iface.ReadableItemNBT;
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
import de.tr7zw.changeme.nbtapi.wrapper.NBTProxy;
import de.tr7zw.changeme.nbtapi.wrapper.ProxyBuilder;
import de.tr7zw.changeme.nbtapi.iface.ReadableNBTList;
/**
* General utility class for a clean and simple nbt access.
*
* @author tr7zw
*
*/
public class NBT {
private NBT() {
// No instances of NBT. Utility class
}
/**
* Get a read only instance of the items NBT. This method is slightly slower
* than calling NBT.get due to having to create a copy of the ItemStack, but
* allows context free access to the data.
*
* @param item
* @return
*/
public static ReadableNBT readNbt(ItemStack item) {
return new NBTItem(item.clone(), false, true, false);
}
/**
* It takes an ItemStack, and a function that takes a ReadableNBT and returns a
* generic type T. It then returns the result of the function applied to a new
* NBTItem
*
* @param item The itemstack you want to get the NBT from
* @param getter A function that takes a ReadableNBT and returns a value of type
* T.
* @return The function is being returned.
*/
public static <T> T get(ItemStack item, Function<ReadableItemNBT, T> getter) {
NBTItem nbt = new NBTItem(item, false, true, false);
T ret = getter.apply(nbt);
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
nbt.setClosed();
return ret;
}
/**
* It takes an ItemStack, and a Consumer that takes a ReadableNBT. Applies the
* Consumer on the NBT of the item
*
* @param item The itemstack you want to get the NBT from
*/
public static void get(ItemStack item, Consumer<ReadableItemNBT> getter) {
NBTItem nbt = new NBTItem(item, false, true, false);
getter.accept(nbt);
nbt.setClosed();
}
/**
* It takes an entity and a function that takes a ReadableNBT and returns a
* generic type T, and returns the result of the function
*
* @param entity The entity to get the NBT from
* @param getter A function that takes a ReadableNBT and returns a value.
* @return The NBTEntity class is being returned.
*/
public static <T> T get(Entity entity, Function<ReadableNBT, T> getter) {
NBTEntity nbt = new NBTEntity(entity, true);
T ret = getter.apply(nbt);
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
nbt.setClosed();
return ret;
}
/**
* It takes an Entity, and a Consumer that takes a ReadableNBT. Applies the
* Consumer on the NBT of the Entity
*
* @param entity The entity to get the NBT from
*/
public static void get(Entity entity, Consumer<ReadableNBT> getter) {
NBTEntity nbt = new NBTEntity(entity, true);
getter.accept(nbt);
nbt.setClosed();
}
/**
* It takes a block state and a function that takes a readable NBT and returns a
* value of type T. It then returns the value of the function applied to a new
* NBTTileEntity created from the block state
*
* @param blockState The block state of the block you want to get the NBT from.
* @param getter A function that takes a ReadableNBT and returns a value of
* type T.
* @return The return type is the same as the type of the getter function.
*/
public static <T> T get(BlockState blockState, Function<ReadableNBT, T> getter) {
NBTTileEntity nbt = new NBTTileEntity(blockState, true);
T ret = getter.apply(nbt);
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
nbt.setClosed();
return ret;
}
/**
* It takes an BlockEntity, and a Consumer that takes a ReadableNBT. Applies the
* Consumer on the NBT of the BlockEntity
*
* @param blockState The block state of the block you want to get the NBT from.
*/
public static void get(BlockState blockState, Consumer<ReadableNBT> getter) {
NBTTileEntity nbt = new NBTTileEntity(blockState, true);
getter.accept(nbt);
nbt.setClosed();
}
/**
* It takes an entity and a function that takes a ReadableNBT and returns a
* generic type T, and returns the result of the function, applied to the
* entities persistent data container
*
* @param entity The entity to get the data from
* @param getter A function that takes a ReadableNBT and returns a value of type
* T.
* @return The return type is T, which is a generic type.
*/
public static <T> T getPersistentData(Entity entity, Function<ReadableNBT, T> getter) {
T ret = getter.apply(new NBTEntity(entity).getPersistentDataContainer());
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
return ret;
}
/**
* It takes 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
* type T.
* @return The value of the NBT tag.
*/
public static <T> T getPersistentData(BlockState blockState, Function<ReadableNBT, T> getter) {
T ret = getter.apply(new NBTTileEntity(blockState).getPersistentDataContainer());
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
return ret;
}
/**
* It takes an ItemStack, applies a function to its NBT, and returns the result
* of the function
*
* @param item The item you want to modify
* @param function The function that will be applied to the item.
* @return The return value of the function.
*/
public static <T> T modify(ItemStack item, Function<ReadWriteItemNBT, T> function) {
NBTItem nbti = new NBTItem(item, false, false, true);
T val = function.apply(nbti);
nbti.finalizeChanges();
if (val instanceof ReadableNBT || val instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
nbti.setClosed();
return val;
}
/**
* It takes an ItemStack and a Consumer&lt;ReadWriteNBT&gt;, and then applies
* the Consumer to the ItemStacks NBT
*
* @param item The item you want to modify
* @param consumer The consumer that will be used to modify the NBT.
*/
public static void modify(ItemStack item, Consumer<ReadWriteItemNBT> consumer) {
NBTItem nbti = new NBTItem(item, false, false, true);
consumer.accept(nbti);
nbti.finalizeChanges();
nbti.setClosed();
}
/**
* It takes an entity and a function that takes a ReadWriteNBT and returns a
* generic type T. It then returns the result of the function
*
* @param entity The entity to modify
* @param function The function that will be called.
* @return The return type is the same as the return type of the function.
*/
public static <T> T modify(Entity entity, Function<ReadWriteNBT, T> function) {
NBTEntity nbtEnt = new NBTEntity(entity);
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
T ret = function.apply(cont);
nbtEnt.setCompound(cont.getCompound());
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
nbtEnt.setClosed();
return ret;
}
/**
* It takes an entity and a function that takes a ReadWriteNBT and applies the
* function to the entity
*
* @param entity The entity to modify
* @param consumer The consumer that will be called with the NBTEntity.
*/
public static void modify(Entity entity, Consumer<ReadWriteNBT> consumer) {
NBTEntity nbtEnt = new NBTEntity(entity);
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
consumer.accept(cont);
nbtEnt.setCompound(cont.getCompound());
nbtEnt.setClosed();
}
/**
* It takes an entity and a function that takes a ReadWriteNBT from the entities
* persistent data and returns a generic type T. It then returns the result of
* the function
*
* @param entity The entity to modify the data of.
* @param function The function that will be called.
* @return The return type is the same as the return type of the function.
*/
public static <T> T modifyPersistentData(Entity entity, Function<ReadWriteNBT, T> function) {
T ret = function.apply(new NBTEntity(entity).getPersistentDataContainer());
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
return ret;
}
/**
* It allows you to modify the persistent data of an entity without any return
* value
*
* @param entity The entity to modify
* @param consumer The consumer that will be used to modify the persistent data.
*/
public static void modifyPersistentData(Entity entity, Consumer<ReadWriteNBT> consumer) {
consumer.accept(new NBTEntity(entity).getPersistentDataContainer());
}
/**
* It takes a block state and a function that takes a ReadWriteNBT and returns a
* generic type T. It then returns the result of the function
*
* @param blockState The blockstate you want to modify
* @param function The function that will be called.
* @return The return type is the same as the return type of the function.
*/
public static <T> T modify(BlockState blockState, Function<ReadWriteNBT, T> function) {
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
T ret = function.apply(cont);
blockEnt.setCompound(cont.getCompound());
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
blockEnt.setClosed();
return ret;
}
/**
* It takes a block state and a consumer, and then it creates a new
* NBTTileEntity object with the block state, and then it passes that
* NBTTileEntity object to the consumer
*
* @param blockState The blockstate you want to modify
* @param consumer A Consumer&lt;ReadWriteNBT&gt;. This is a function that
* takes a ReadWriteNBT and does something with it.
*/
public static void modify(BlockState blockState, Consumer<ReadWriteNBT> consumer) {
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
consumer.accept(cont);
blockEnt.setCompound(cont.getCompound());
blockEnt.setClosed();
}
/**
* It takes a block state and a function that takes a ReadWriteNBT of the block
* entities persistent data and returns a generic type T. It then returns the
* result of the function
*
* @param blockState The block state of the block you want to modify.
* @param function The function that will be called to modify the NBT data.
* @return The return type is the same as the return type of the function.
*/
public static <T> T modifyPersistentData(BlockState blockState, Function<ReadWriteNBT, T> function) {
T ret = function.apply(new NBTTileEntity(blockState).getPersistentDataContainer());
if (ret instanceof ReadableNBT || ret instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
return ret;
}
/**
* It takes a block state and a consumer, and then it calls the consumer with
* the persistent data container of the block entity
*
* @param blockState The block state of the block you want to modify.
* @param consumer A Consumer&lt;ReadWriteNBT&gt;. This is a function that
* takes a ReadWriteNBT and does something with it.
*/
public static void modifyPersistentData(BlockState blockState, Consumer<ReadWriteNBT> consumer) {
consumer.accept(new NBTTileEntity(blockState).getPersistentDataContainer());
}
/**
* It converts a GameProfile object to a ReadWriteNBT object
*
* @param profile The GameProfile to convert to NBT
* @return A ReadWriteNBT object.
*/
public static ReadWriteNBT gameProfileToNBT(GameProfile profile) {
return NBTGameProfile.toNBT(profile);
}
/**
* It takes a NBT compound and returns a GameProfile
*
* @param compound The NBT tag to read the GameProfile from.
* @return A GameProfile object.
*/
public static GameProfile gameProfileFromNBT(ReadableNBT compound) {
return NBTGameProfile.fromNBT((NBTCompound) compound);
}
/**
* It converts an ItemStack to a ReadWriteNBT object
*
* @param itemStack The item stack you want to convert to NBT.
* @return A ReadWriteNBT object.
*/
public static ReadWriteNBT itemStackToNBT(ItemStack itemStack) {
return NBTItem.convertItemtoNBT(itemStack);
}
/**
* It converts a ReadableNBT object into an ItemStack
*
* @param compound The NBT tag to convert to an ItemStack
* @return An ItemStack
*/
@Nullable
public static ItemStack itemStackFromNBT(ReadableNBT compound) {
return NBTItem.convertNBTtoItem((NBTCompound) compound);
}
/**
* It converts an array of ItemStacks into a ReadWriteNBT object
*
* @param itemStacks The ItemStack[] you want to convert to NBT
* @return An NBTItem object.
*/
public static ReadWriteNBT itemStackArrayToNBT(ItemStack[] itemStacks) {
return NBTItem.convertItemArraytoNBT(itemStacks);
}
/**
* It converts a ReadableNBT object into an array of ItemStacks
*
* @param compound The NBT tag to convert to an ItemStack array.
* @return An array of ItemStacks.
*/
@Nullable
public static ItemStack[] itemStackArrayFromNBT(ReadableNBT compound) {
return NBTItem.convertNBTtoItemArray((NBTCompound) compound);
}
/**
* Create a new NBTContainer object and return it.
*
* @return A new instance of the NBTContainer class.
*/
public static ReadWriteNBT createNBTObject() {
return new NBTContainer();
}
/**
* It takes a nbt json string, and returns a ReadWriteNBT object
*
* @param nbtString The NBT string to parse.
* @return A new NBTContainer object.
*/
public static ReadWriteNBT parseNBT(String nbtString) {
return new NBTContainer(nbtString);
}
/**
* Create a read only proxy class for NBT, given an annotated interface.
*
* @param <T>
* @param item
* @param wrapper
* @return
*/
public static <T extends NBTProxy> T readNbt(ItemStack item, Class<T> wrapper) {
return new ProxyBuilder<>(new NBTItem(item, false, true, false), wrapper).readOnly().build();
}
/**
* Create a read only proxy class for NBT, given an annotated interface.
*
* @param <T>
* @param entity
* @param wrapper
* @return
*/
public static <T extends NBTProxy> T readNbt(Entity entity, Class<T> wrapper) {
return new ProxyBuilder<>(new NBTEntity(entity, true), wrapper).readOnly().build();
}
/**
* Create a read only proxy class for NBT, given an annotated interface.
*
* @param <T>
* @param blockState
* @param wrapper
* @return
*/
public static <T extends NBTProxy> T readNbt(BlockState blockState, Class<T> wrapper) {
return new ProxyBuilder<>(new NBTTileEntity(blockState, true), wrapper).readOnly().build();
}
/**
* It takes an ItemStack, applies a function to its NBT wrapped in a proxy, and
* returns the result of the function
*
* @param item The item you want to
* @param wrapper The target Proxy class
* @param function The function that will be applied to the item.
* @return The return value of the function.
*/
public static <T, X extends NBTProxy> T modify(ItemStack item, Class<X> wrapper, Function<X, T> function) {
NBTItem nbti = new NBTItem(item, false, false, true);
T val = function.apply(new ProxyBuilder<>(nbti, wrapper).build());
nbti.finalizeChanges();
if (val instanceof ReadableNBT || val instanceof ReadableNBTList<?>) {
throw new NbtApiException("Tried returning part of the NBT to outside of the NBT scope!");
}
nbti.setClosed();
return val;
}
/**
* It takes an ItemStack, applies a function to its NBT wrapped in a proxy.
*
* @param item The item you want to modify
* @param wrapper The target Proxy class
* @param consumer The consumer that will be used to modify the NBT.
*/
public static <X extends NBTProxy> void modify(ItemStack item, Class<X> wrapper, Consumer<X> consumer) {
NBTItem nbti = new NBTItem(item, false, false, true);
consumer.accept(new ProxyBuilder<>(nbti, wrapper).build());
nbti.finalizeChanges();
nbti.setClosed();
}
/**
* It takes an entity and a function to modify the entity via the proxy
*
* @param entity The entity to modify
* @param wrapper The target Proxy class
* @param consumer The consumer that will be called with the proxy.
*/
public static <X extends NBTProxy> void modify(Entity entity, Class<X> wrapper, Consumer<X> consumer) {
NBTEntity nbtEnt = new NBTEntity(entity);
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
consumer.accept(new ProxyBuilder<>(cont, wrapper).build());
nbtEnt.setCompound(cont.getCompound());
cont.setClosed();
}
/**
* It takes an entity and a function to modify the entity via the proxy
*
* @param entity The entity to modify
* @param wrapper The target Proxy class
* @param function The Function that will be called with the proxy.
* @return The return value of the function.
*/
public static <T, X extends NBTProxy> T modify(Entity entity, Class<X> wrapper, Function<X, T> function) {
NBTEntity nbtEnt = new NBTEntity(entity);
NBTContainer cont = new NBTContainer(nbtEnt.getCompound());
T val = function.apply(new ProxyBuilder<>(cont, wrapper).build());
nbtEnt.setCompound(cont.getCompound());
cont.setClosed();
return val;
}
/**
* It takes an block entity and a function to modify the entity via the proxy
*
* @param blockState The blockstate you want to modify
* @param wrapper The target Proxy class
* @param consumer The Consumer that will be called.
*/
public static <X extends NBTProxy> void modify(BlockState blockState, Class<X> wrapper, Consumer<X> consumer) {
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
consumer.accept(new ProxyBuilder<>(cont, wrapper).build());
blockEnt.setCompound(cont);
cont.setClosed();
}
/**
* It takes an block entity and a function to modify the entity via the proxy
*
* @param blockState The blockstate you want to modify
* @param wrapper The target Proxy class
* @param function The function that will be called.
* @return The return value of the function.
*/
public static <T, X extends NBTProxy> T modify(BlockState blockState, Class<X> wrapper, Function<X, T> function) {
NBTTileEntity blockEnt = new NBTTileEntity(blockState);
NBTContainer cont = new NBTContainer(blockEnt.getCompound());
T val = function.apply(new ProxyBuilder<>(cont, wrapper).build());
blockEnt.setCompound(cont);
cont.setClosed();
return val;
}
}
@@ -1,38 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import org.bukkit.block.Block;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
/**
* Helper class to store NBT data to Block Locations. Use getData() to get the
* NBT instance. Important notes:
*
* - Non BlockEntities can not have NBT data. This stores the data to the chunk
* instead!
*
* - The data is really just on the location. If the block gets
* broken/changed/exploded/moved etc., the data is still on that location!
*
* @author tr7zw
*
*/
public class NBTBlock {
private final Block block;
private final NBTChunk nbtChunk;
public NBTBlock(Block block) {
this.block = block;
if (!MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R3)) {
throw new NbtApiException("NBTBlock is only working for 1.16.4+!");
}
nbtChunk = new NBTChunk(block.getChunk());
}
public NBTCompound getData() {
return nbtChunk.getPersistentDataContainer().getOrCreateCompound("blocks")
.getOrCreateCompound(block.getX() + "_" + block.getY() + "_" + block.getZ());
}
}
@@ -1,27 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import org.bukkit.Chunk;
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
public class NBTChunk {
private final Chunk chunk;
public NBTChunk(Chunk chunk) {
this.chunk = chunk;
}
/**
* Gets the NBTCompound used by spigots PersistentDataAPI. This method is only
* available for 1.16.4+!
*
* @return NBTCompound containing the data of the PersistentDataAPI
*/
public NBTCompound getPersistentDataContainer() {
CheckUtil.assertAvailable(MinecraftVersion.MC1_16_R3);
return new NBTPersistentDataContainer(chunk.getPersistentDataContainer());
}
}
File diff suppressed because it is too large. Load diff
@@ -1,121 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* {@link NBTListCompound} implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTCompoundList extends NBTList<ReadWriteNBT> implements ReadWriteNBTCompoundList {
protected NBTCompoundList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
/**
* Adds a new Compound to the end of the List and returns it.
*
* @return The added {@link NBTListCompound}
*/
public NBTListCompound addCompound() {
return (NBTListCompound) addCompound(null);
}
/**
* Adds a copy of the Compound to the end of the List and returns it. When null
* is given, a new Compound will be created
*
* @param comp
* @return
*/
public NBTCompound addCompound(NBTCompound comp) {
if (getParent().isReadOnly()) {
throw new NbtApiException("Tried setting data in read only mode!");
}
try {
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, size(), compound);
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
getParent().saveCompound();
NBTListCompound listcomp = new NBTListCompound(this, compound);
if (comp != null) {
listcomp.mergeCompound(comp);
}
return listcomp;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
public NBTCompound addCompound(ReadWriteNBT comp) {
if (comp instanceof NBTCompound) {
return addCompound((NBTCompound) comp);
}
return null;
}
/**
* Adds a new Compound to the end of the List.
*
*
* @deprecated Please use addCompound!
* @param empty
* @return True, if compound was added
*/
@Override
@Deprecated
public boolean add(ReadWriteNBT empty) {
return addCompound(empty) != null;
}
@Override
public void add(int index, ReadWriteNBT element) {
if (element != null) {
throw new NbtApiException("You need to pass null! ListCompounds from other lists won't work.");
}
if (getParent().isReadOnly()) {
throw new NbtApiException("Tried setting data in read only mode!");
}
try {
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, index, compound);
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
super.getParent().saveCompound();
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
@Override
public NBTListCompound get(int index) {
try {
Object compound = ReflectionMethod.LIST_GET_COMPOUND.run(listObject, index);
return new NBTListCompound(this, compound);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
@Override
public NBTListCompound set(int index, ReadWriteNBT element) {
throw new NbtApiException("This method doesn't work in the ListCompound context.");
}
@Override
protected Object asTag(ReadWriteNBT object) {
return null;
}
}
@@ -1,103 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.io.InputStream;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* A Standalone {@link NBTCompound} implementation. All data is just kept inside
* this Object.
*
* @author tr7zw
*
*/
public class NBTContainer extends NBTCompound {
private Object nbt;
private boolean closed;
private boolean readOnly;
/**
* Creates an empty, standalone NBTCompound
*/
public NBTContainer() {
super(null, null);
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
/**
* Takes in any NMS Compound to wrap it
*
* @param nbt
*/
public NBTContainer(Object nbt) {
super(null, null);
if (nbt == null) {
throw new NullPointerException("The NBT-Object can't be null!");
}
if (!ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().isAssignableFrom(nbt.getClass())) {
throw new NbtApiException("The object '" + nbt.getClass() + "' is not a valid NBT-Object!");
}
this.nbt = nbt;
}
/**
* Reads in a NBT InputStream
*
* @param inputsteam
*/
public NBTContainer(InputStream inputsteam) {
super(null, null);
this.nbt = NBTReflectionUtil.readNBT(inputsteam);
}
/**
* Parses in a NBT String to a standalone {@link NBTCompound}. Can throw a
* {@link NbtApiException} in case something goes wrong.
*
* @param nbtString
*/
public NBTContainer(String nbtString) {
super(null, null);
if (nbtString == null) {
throw new NullPointerException("The String can't be null!");
}
try {
nbt = ReflectionMethod.PARSE_NBT.run(null, nbtString);
} catch (Exception ex) {
throw new NbtApiException("Unable to parse Malformed Json!", ex);
}
}
@Override
public Object getCompound() {
return nbt;
}
@Override
public void setCompound(Object tag) {
nbt = tag;
}
@Override
protected void setClosed() {
this.closed = true;
}
@Override
protected boolean isClosed() {
return closed;
}
protected boolean isReadOnly() {
return readOnly;
}
protected NBTContainer setReadOnly(boolean readOnly) {
this.readOnly = true;
return this;
}
}
@@ -1,45 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Double implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTDoubleList extends NBTList<Double> {
protected NBTDoubleList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Double object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGDOUBLE.getClazz().getDeclaredConstructor(double.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Double get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Double.valueOf(obj.toString());
} catch (NumberFormatException nf) {
return 0d;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -1,102 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
/**
* NBT class to access vanilla tags from Entities. Entities don't support custom
* tags. Use the NBTInjector for custom tags. Changes will be instantly applied
* to the Entity, use the merge method to do many things at once.
*
* @author tr7zw
*
*/
public class NBTEntity extends NBTCompound {
private final Entity ent;
private final boolean readonly;
private final Object compound;
private boolean closed = false;
/**
* @param entity Any valid Bukkit Entity
* @param readonly Readonly makes a copy at init, only reading from that copy
*/
protected NBTEntity(Entity entity, boolean readonly) {
super(null, null);
if (entity == null) {
throw new NullPointerException("Entity can't be null!");
}
this.readonly = readonly;
ent = entity;
if (readonly) {
this.compound = getCompound();
} else {
this.compound = null;
}
}
/**
* @param entity Any valid Bukkit Entity
*/
public NBTEntity(Entity entity) {
super(null, null);
if (entity == null) {
throw new NullPointerException("Entity can't be null!");
}
this.readonly = false;
this.compound = null;
ent = entity;
}
@Override
protected void setClosed() {
this.closed = true;
}
@Override
protected boolean isClosed() {
return closed;
}
@Override
protected boolean isReadOnly() {
return readonly;
}
@Override
public Object getCompound() {
// this runs before async check, since it's just a copy
if (readonly && compound != null) {
return compound;
}
if (!Bukkit.isPrimaryThread())
throw new NbtApiException("Entity NBT needs to be accessed sync!");
return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent));
}
@Override
protected void setCompound(Object compound) {
if (readonly) {
throw new NbtApiException("Tried setting data in read only mode!");
}
if (!Bukkit.isPrimaryThread())
throw new NbtApiException("Entity NBT needs to be accessed sync!");
NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent));
}
/**
* Gets the NBTCompound used by spigots PersistentDataAPI. This method is only
* available for 1.14+!
*
* @return NBTCompound containing the data of the PersistentDataAPI
*/
public NBTCompound getPersistentDataContainer() {
CheckUtil.assertAvailable(MinecraftVersion.MC1_14_R1);
return new NBTPersistentDataContainer(ent.getPersistentDataContainer());
}
}
@@ -1,105 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
/**
* {@link NBTCompound} implementation backed by a {@link File}
*
* @author tr7zw
*
*/
public class NBTFile extends NBTCompound {
private final File file;
private Object nbt;
/**
* Creates a NBTFile that uses @param file to store its data. If this file
* exists, the data will be loaded.
*
* @param file
* @throws IOException
*/
public NBTFile(File file) throws IOException {
super(null, null);
if (file == null) {
throw new NullPointerException("File can't be null!");
}
this.file = file;
if (file.exists()) {
nbt = NBTReflectionUtil.readNBT(Files.newInputStream(file.toPath()));
} else {
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
save();
}
}
/**
* Saves the data to the file
*
* @throws IOException
*/
public void save() throws IOException {
try {
getWriteLock().lock();
saveTo(file, this);
} finally {
getWriteLock().unlock();
}
}
/**
* @return The File used to store the data
*/
public File getFile() {
return file;
}
@Override
public Object getCompound() {
return nbt;
}
@Override
protected void setCompound(Object compound) {
nbt = compound;
}
/**
* Reads NBT data from the provided file.
* <p>
* Returns empty NBTContainer if file does not exist.
*
* @param file file to read
* @return NBTCompound holding file's nbt data
* @throws IOException exception
*/
public static NBTCompound readFrom(File file) throws IOException {
if (!file.exists())
return new NBTContainer();
return new NBTContainer(NBTReflectionUtil.readNBT(Files.newInputStream(file.toPath())));
}
/**
* 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 saveTo(File file, NBTCompound nbt) throws IOException {
if (!file.exists()) {
file.getParentFile().mkdirs();
if (!file.createNewFile())
throw new IOException("Unable to create file at " + file.getAbsolutePath());
}
nbt.writeCompound(Files.newOutputStream(file.toPath()));
}
}
@@ -1,45 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Float implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTFloatList extends NBTList<Float> {
protected NBTFloatList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Float object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGFLOAT.getClazz().getDeclaredConstructor(float.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Float get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Float.valueOf(obj.toString());
} catch (NumberFormatException nf) {
return 0f;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -1,32 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import com.mojang.authlib.GameProfile;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
public class NBTGameProfile {
/**
* Convert a GameProfile to NBT. The NBT then can be modified or be stored
*
* @param profile
* @return A NBTContainer with all the GameProfile data
*/
public static NBTCompound toNBT(GameProfile profile) {
return new NBTContainer(ReflectionMethod.GAMEPROFILE_SERIALIZE.run(null,
ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(), profile));
}
/**
* Reconstructs a GameProfile from a NBTCompound
*
* @param compound Has to contain GameProfile data
* @return The reconstructed GameProfile
*/
public static GameProfile fromNBT(NBTCompound compound) {
return (GameProfile) ReflectionMethod.GAMEPROFILE_DESERIALIZE.run(null,
NBTReflectionUtil.gettoCompount(compound.getCompound(), compound));
}
}
@@ -1,51 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Integer implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTIntArrayList extends NBTList<int[]> {
private final NBTContainer tmpContainer;
protected NBTIntArrayList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
this.tmpContainer = new NBTContainer();
}
@Override
protected Object asTag(int[] object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGINTARRAY.getClazz().getDeclaredConstructor(int[].class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public int[] get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
ReflectionMethod.COMPOUND_SET.run(tmpContainer.getCompound(), "tmp", obj);
int[] val = tmpContainer.getIntArray("tmp");
tmpContainer.removeKey("tmp");
return val;
} catch (NumberFormatException nf) {
return null;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -1,45 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Integer implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTIntegerList extends NBTList<Integer> {
protected NBTIntegerList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Integer object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGINT.getClazz().getDeclaredConstructor(int.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Integer get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Integer.valueOf(obj.toString());
} catch (NumberFormatException nf) {
return 0;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -1,396 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.util.Set;
import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
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.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* NBT class to access vanilla/custom tags on ItemStacks. This class doesn't
* autosave to the Itemstack, use getItem to get the changed ItemStack
*
* @author tr7zw
*
*/
public class NBTItem extends NBTCompound implements ReadWriteItemNBT {
private ItemStack bukkitItem;
private final boolean directApply;
private final boolean finalizer;
private ItemStack originalSrcStack = null;
private Object cachedCompound = null;
private boolean closed = false;
/**
* Constructor for NBTItems. The ItemStack will be cloned!
*
* @param item
*/
public NBTItem(ItemStack item) {
this(item, false);
}
/**
* @param item
* @param directApply
* @param readOnly When turned on, no copy of the source item is created.
* Modifying the stack in that case is not valid! Also
* overwrites directApply
*/
protected NBTItem(ItemStack item, boolean directApply, boolean readOnly, boolean finalizer) {
super(null, null, readOnly);
if (item == null || item.getType() == Material.AIR || item.getAmount() <= 0) {
throw new NullPointerException("ItemStack can't be null/air/amount of 0! This is not a NBTAPI bug!");
}
this.finalizer = finalizer;
if (finalizer) {
this.bukkitItem = item;
this.originalSrcStack = item;
this.directApply = false;
} else if (readOnly) {
bukkitItem = item;
this.directApply = false;
} else {
this.directApply = directApply;
bukkitItem = item.clone();
if (directApply) {
this.originalSrcStack = item;
}
}
}
/**
* Constructor for NBTItems. The ItemStack will be cloned! If directApply is
* true, all changed will be mapped to the original item. Changes to the NBTItem
* will overwrite changes done to the original item in that case.
*
* @param item
* @param directApply
*/
@Deprecated
public NBTItem(ItemStack item, boolean directApply) {
super(null, null);
if (item == null || item.getType() == Material.AIR || item.getAmount() <= 0) {
throw new NullPointerException("ItemStack can't be null/air/amount of 0! This is not a NBTAPI bug!");
}
this.finalizer = false;
this.directApply = directApply;
bukkitItem = item.clone();
if (directApply) {
this.originalSrcStack = item;
}
}
@Override
public Object getCompound() {
if (closed) {
throw new NbtApiException("Tried using closed NBT data!");
}
if (isReadOnly() && (cachedCompound != null
|| ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(bukkitItem.getClass()))) {
if (cachedCompound == null) {
cachedCompound = NBTReflectionUtil
.getItemRootNBTTagCompound(NBTReflectionUtil.getCraftItemHandle(bukkitItem));
}
return cachedCompound;
}
if (finalizer) {
if (cachedCompound == null) {
updateCachedCompound();
}
return cachedCompound;
}
return NBTReflectionUtil.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem));
}
private void updateCachedCompound() {
if (finalizer) {
cachedCompound = NBTReflectionUtil
.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem));
}
}
protected void finalizeChanges() {
if (!finalizer || cachedCompound == null) {
return;
}
// There was data, but not anymore, delete the tag from the itemstack
if (NBTReflectionUtil.getKeys(this).isEmpty()) {
cachedCompound = null;
}
if (ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(originalSrcStack.getClass())) {
Object nmsStack = NBTReflectionUtil.getCraftItemHandle(originalSrcStack);
ReflectionMethod.ITEMSTACK_SET_TAG.run(nmsStack, cachedCompound);
bukkitItem = originalSrcStack;
} else {
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, cachedCompound);
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
originalSrcStack.setItemMeta(bukkitItem.getItemMeta());
}
}
@Override
protected void setClosed() {
this.closed = true;
}
@Override
protected boolean isClosed() {
return closed;
}
@SuppressWarnings("unchecked")
@Override
protected void setCompound(Object compound) {
if (isReadOnly()) {
throw new NbtApiException("Tried setting data in read only mode!");
}
if (closed) {
throw new NbtApiException("Tried using closed NBT data!");
}
if (finalizer) {
cachedCompound = compound;
return;
}
if (compound != null && ((Set<String>) ReflectionMethod.COMPOUND_GET_KEYS.run(compound)).isEmpty()) {
compound = null;
}
if (ClassWrapper.CRAFT_ITEMSTACK.getClazz().isAssignableFrom(bukkitItem.getClass())) {
Object nmsStack = NBTReflectionUtil.getCraftItemHandle(bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(nmsStack, compound);
} else {
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound);
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
}
}
/**
* Apply stored NBT tags to the provided ItemStack.
* <p>
* Note: This will completely override current item's {@link ItemMeta}. If you
* still want to keep the original item's NBT tags, see
* {@link #mergeNBT(ItemStack)} and {@link #mergeCustomNBT(ItemStack)}.
*
* @param item ItemStack that should get the new NBT data
*/
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!");
}
NBTItem nbti = new NBTItem(new ItemStack(item.getType()));
nbti.mergeCompound(this);
item.setItemMeta(nbti.getItem().getItemMeta());
}
/**
* Merge all NBT tags to the provided ItemStack.
*
* @param item ItemStack that should get the new NBT data
*/
public void mergeNBT(ItemStack item) {
NBTItem nbti = new NBTItem(item);
nbti.mergeCompound(this);
item.setItemMeta(nbti.getItem().getItemMeta());
}
/**
* Merge only custom (non-vanilla) NBT tags to the provided ItemStack.
*
* @param item ItemStack that should get the new NBT data
*/
public void mergeCustomNBT(ItemStack item) {
if (item == null || item.getType() == Material.AIR) {
throw new NullPointerException("ItemStack can't be null/Air!");
}
ItemMeta meta = item.getItemMeta();
NBTReflectionUtil.getUnhandledNBTTags(meta)
.putAll(NBTReflectionUtil.getUnhandledNBTTags(bukkitItem.getItemMeta()));
item.setItemMeta(meta);
}
/**
* True, if the item has any tags now known for this item type.
*
* @return true when custom tags are present
*/
public boolean hasCustomNbtData() {
finalizeChanges();
ItemMeta meta = bukkitItem.getItemMeta();
return !NBTReflectionUtil.getUnhandledNBTTags(meta).isEmpty();
}
/**
* Remove all custom (non-vanilla) NBT tags from the NBTItem.
*/
public void clearCustomNBT() {
finalizeChanges();
ItemMeta meta = bukkitItem.getItemMeta();
NBTReflectionUtil.getUnhandledNBTTags(meta).clear();
bukkitItem.setItemMeta(meta);
updateCachedCompound();
}
/**
* @return The modified ItemStack
*/
public ItemStack getItem() {
return bukkitItem;
}
protected void setItem(ItemStack item) {
bukkitItem = item;
}
/**
* Returns true if the item has NBT data.
*
* @return Does the ItemStack have a NBTCompound.
*/
public boolean hasNBTData() {
return getCompound() != null;
}
/**
* Gives save access to the {@link ItemMeta} of the internal {@link ItemStack}.
* Supported operations while inside this scope: - any get/set method of
* {@link ItemMeta} - any getter on {@link NBTItem}
*
* All changes made to the {@link NBTItem} during this scope will be reverted at
* the end.
*
* @param handler
*/
public void modifyMeta(BiConsumer<ReadableNBT, ItemMeta> handler) {
finalizeChanges();
ItemMeta meta = bukkitItem.getItemMeta();
handler.accept(new NBTContainer(getResolvedObject()).setReadOnly(true), meta);
bukkitItem.setItemMeta(meta);
updateCachedCompound();
if (directApply) {
applyNBT(originalSrcStack);
}
}
/**
* Gives save access to the {@link ItemMeta} of the internal {@link ItemStack}.
* Supported operations while inside this scope: - any get/set method of
* {@link ItemMeta} - any getter on {@link NBTItem}
*
* All changes made to the {@link NBTItem} during this scope will be reverted at
* the end.
*
* @param handler
*/
public <T extends ItemMeta> void modifyMeta(Class<T> type, BiConsumer<ReadableNBT, T> handler) {
finalizeChanges();
@SuppressWarnings("unchecked")
T meta = (T) bukkitItem.getItemMeta();
handler.accept(new NBTContainer(getResolvedObject()).setReadOnly(true), meta);
bukkitItem.setItemMeta(meta);
updateCachedCompound();
if (directApply) {
applyNBT(originalSrcStack);
}
}
/**
* Helper method that converts {@link ItemStack} to {@link NBTContainer} with
* all it's data like Material, Damage, Amount and Tags.
*
* @param item
* @return Standalone {@link NBTContainer} with the Item's data
*/
public static NBTContainer convertItemtoNBT(ItemStack item) {
return NBTReflectionUtil.convertNMSItemtoNBTCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, item));
}
/**
* Helper method to do the inverse of "convertItemtoNBT". Creates an
* {@link ItemStack} using the {@link NBTCompound}
*
* @param comp
* @return ItemStack using the {@link NBTCompound}'s data
*/
@Nullable
public static ItemStack convertNBTtoItem(NBTCompound comp) {
return (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null,
NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp));
}
/**
* Helper method that converts {@link ItemStack}[] to {@link NBTContainer} with
* all its data like Material, Damage, Amount and Tags. This is a custom
* implementation and won't work with vanilla code(Shulker content etc).
*
* @param items
* @return Standalone {@link NBTContainer} with the Item's data
*/
public static NBTContainer convertItemArraytoNBT(ItemStack[] items) {
NBTContainer container = new NBTContainer();
container.setInteger("size", items.length);
NBTCompoundList list = container.getCompoundList("items");
for (int i = 0; i < items.length; i++) {
ItemStack item = items[i];
if (item == null || item.getType() == Material.AIR) {
continue;
}
NBTListCompound entry = list.addCompound();
entry.setInteger("Slot", i);
entry.mergeCompound(convertItemtoNBT(item));
}
return container;
}
/**
* Helper method to do the inverse of "convertItemArraytoNBT". Creates an
* {@link ItemStack}[] using the {@link NBTCompound}. This is a custom
* implementation and won't work with vanilla code (Shulker content, etc.).
*
* Will return null for invalid data. Empty slots in the array are filled with
* AIR Stacks!
*
* @param comp
* @return ItemStack[] using the {@link NBTCompound}'s data
*/
@Nullable
public static ItemStack[] convertNBTtoItemArray(NBTCompound comp) {
if (!comp.hasTag("size")) {
return null;
}
ItemStack[] rebuild = new ItemStack[comp.getInteger("size")];
for (int i = 0; i < rebuild.length; i++) { // not using Arrays.fill, since then it's all the same instance
rebuild[i] = new ItemStack(Material.AIR);
}
if (!comp.hasTag("items")) {
return rebuild;
}
NBTCompoundList list = comp.getCompoundList("items");
for (ReadWriteNBT lcomp : list) {
if (lcomp instanceof NBTCompound) {
int slot = lcomp.getInteger("Slot");
rebuild[slot] = convertNBTtoItem((NBTCompound) lcomp);
}
}
return rebuild;
}
@Override
protected void saveCompound() {
if (directApply) {
applyNBT(originalSrcStack);
}
}
}
@@ -1,474 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.function.Predicate;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTList;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Abstract List implementation for ListCompounds
*
* @author tr7zw
*
* @param <T>
*/
public abstract class NBTList<T> implements List<T>, ReadWriteNBTList<T> {
private String listName;
private NBTCompound parent;
private NBTType type;
protected Object listObject;
protected NBTList(NBTCompound owner, String name, NBTType type, Object list) {
parent = owner;
listName = name;
this.type = type;
this.listObject = list;
}
/**
* @return Name of this list-compound
*/
public String getName() {
return listName;
}
/**
* @return The Compound's parent Object
*/
public NBTCompound getParent() {
return parent;
}
private void validateClosed() {
if (parent.isClosed()) {
throw new NbtApiException("Tried using closed NBT data!");
}
}
private void validateWritable() {
if (getParent().isReadOnly()) {
throw new NbtApiException("Tried setting data in read only mode!");
}
}
protected void save() {
validateClosed();
parent.set(listName, listObject);
}
protected abstract Object asTag(T object);
@Override
public boolean add(T element) {
validateClosed();
validateWritable();
try {
parent.getWriteLock().lock();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, size(), asTag(element));
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, asTag(element));
}
save();
return true;
} catch (Exception ex) {
throw new NbtApiException(ex);
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public void add(int index, T element) {
validateClosed();
validateWritable();
try {
parent.getWriteLock().lock();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, index, asTag(element));
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, asTag(element));
}
save();
} catch (Exception ex) {
throw new NbtApiException(ex);
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public T set(int index, T element) {
validateClosed();
validateWritable();
try {
parent.getWriteLock().lock();
T prev = get(index);
ReflectionMethod.LIST_SET.run(listObject, index, asTag(element));
save();
return prev;
} catch (Exception ex) {
throw new NbtApiException(ex);
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public T remove(int i) {
validateClosed();
validateWritable();
try {
parent.getWriteLock().lock();
T old = get(i);
ReflectionMethod.LIST_REMOVE_KEY.run(listObject, i);
save();
return old;
} catch (Exception ex) {
throw new NbtApiException(ex);
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public int size() {
validateClosed();
try {
parent.getReadLock().lock();
return (int) ReflectionMethod.LIST_SIZE.run(listObject);
} catch (Exception ex) {
throw new NbtApiException(ex);
} finally {
parent.getReadLock().unlock();
}
}
/**
* @return The type that this list contains
*/
@Override
public NBTType getType() {
return type;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public void clear() {
while (!isEmpty()) {
remove(0);
}
}
@Override
public boolean contains(Object o) {
validateClosed();
try {
parent.getReadLock().lock();
for (int i = 0; i < size(); i++) {
if (o.equals(get(i)))
return true;
}
return false;
} finally {
parent.getReadLock().unlock();
}
}
@Override
public int indexOf(Object o) {
validateClosed();
try {
parent.getReadLock().lock();
for (int i = 0; i < size(); i++) {
if (o.equals(get(i)))
return i;
}
return -1;
} finally {
parent.getReadLock().unlock();
}
}
@Override
public boolean addAll(Collection<? extends T> c) {
validateClosed();
try {
parent.getWriteLock().lock();
int size = size();
for (T ele : c) {
add(ele);
}
return size != size();
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
validateClosed();
try {
parent.getWriteLock().lock();
int size = size();
for (T ele : c) {
add(index++, ele);
}
return size != size();
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public boolean containsAll(Collection<?> c) {
validateClosed();
try {
parent.getReadLock().lock();
for (Object ele : c) {
if (!contains(ele))
return false;
}
return true;
} finally {
parent.getReadLock().unlock();
}
}
@Override
public int lastIndexOf(Object o) {
validateClosed();
try {
parent.getReadLock().lock();
int index = -1;
for (int i = 0; i < size(); i++) {
if (o.equals(get(i)))
index = i;
}
return index;
} finally {
parent.getReadLock().unlock();
}
}
@Override
public boolean removeAll(Collection<?> c) {
validateClosed();
try {
parent.getWriteLock().lock();
int size = size();
for (Object obj : c) {
remove(obj);
}
return size != size();
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public boolean retainAll(Collection<?> c) {
validateClosed();
try {
parent.getWriteLock().lock();
int size = size();
for (Object obj : c) {
for (int i = 0; i < size(); i++) {
if (!obj.equals(get(i))) {
remove(i--);
}
}
}
return size != size();
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public boolean remove(Object o) {
validateClosed();
try {
parent.getWriteLock().lock();
int size = size();
int id = -1;
while ((id = indexOf(o)) != -1) {
remove(id);
}
return size != size();
} finally {
parent.getWriteLock().unlock();
}
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = -1;
@Override
public boolean hasNext() {
return size() > index + 1;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
return get(++index);
}
@Override
public void remove() {
NBTList.this.remove(index);
index--;
}
};
}
@Override
public ListIterator<T> listIterator() {
return listIterator(0);
}
@Override
public ListIterator<T> listIterator(int startIndex) {
final NBTList<T> list = this;
return new ListIterator<T>() {
int index = startIndex - 1;
@Override
public void add(T e) {
list.add(index, e);
}
@Override
public boolean hasNext() {
return size() > index + 1;
}
@Override
public boolean hasPrevious() {
return index >= 0 && index <= size();
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
return get(++index);
}
@Override
public int nextIndex() {
return index + 1;
}
@Override
public T previous() {
if (!hasPrevious())
throw new NoSuchElementException("Id: " + (index - 1));
return get(index--);
}
@Override
public int previousIndex() {
return index - 1;
}
@Override
public void remove() {
list.remove(index);
index--;
}
@Override
public void set(T e) {
list.set(index, e);
}
};
}
@Override
public Object[] toArray() {
validateClosed();
try {
parent.getReadLock().lock();
Object[] ar = new Object[size()];
for (int i = 0; i < size(); i++)
ar[i] = get(i);
return ar;
} finally {
parent.getReadLock().unlock();
}
}
@SuppressWarnings("unchecked")
@Override
public <E> E[] toArray(E[] a) {
validateClosed();
try {
parent.getReadLock().lock();
E[] ar = Arrays.copyOf(a, size());
Arrays.fill(ar, null);
Class<?> arrayclass = a.getClass().getComponentType();
for (int i = 0; i < size(); i++) {
T obj = get(i);
if (arrayclass.isInstance(obj)) {
ar[i] = (E) get(i);
} else {
throw new ArrayStoreException("The array does not match the objects stored in the List.");
}
}
return ar;
} finally {
parent.getReadLock().unlock();
}
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
validateClosed();
try {
parent.getReadLock().lock();
ArrayList<T> list = new ArrayList<>();
for (int i = fromIndex; i < toIndex; i++)
list.add(get(i));
return list;
} finally {
parent.getReadLock().unlock();
}
}
@Override
public boolean removeIf(Predicate<? super T> filter) {
return List.super.removeIf(filter);
}
@Override
public String toString() {
validateClosed();
try {
parent.getReadLock().lock();
return listObject.toString();
} finally {
parent.getReadLock().unlock();
}
}
}
@@ -1,61 +0,0 @@
package de.tr7zw.changeme.nbtapi;
/**
* Cut down version of the {@link NBTCompound} for inside
* {@link NBTCompoundList} This Compound implementation is missing the ability
* for further subCompounds and Lists. This class probably will change in the
* future
*
* @author tr7zw
*
*/
public class NBTListCompound extends NBTCompound {
private NBTList<?> owner;
private Object compound;
protected NBTListCompound(NBTList<?> parent, Object obj) {
super(null, null);
owner = parent;
compound = obj;
}
public NBTList<?> getListParent() {
return owner;
}
@Override
protected boolean isClosed() {
return owner.getParent().isClosed();
}
@Override
protected boolean isReadOnly() {
return owner.getParent().isReadOnly();
}
@Override
public Object getCompound() {
if (isClosed()) {
throw new NbtApiException("Tried using closed NBT data!");
}
return compound;
}
@Override
protected void setCompound(Object compound) {
if (isClosed()) {
throw new NbtApiException("Tried using closed NBT data!");
}
if (isReadOnly()) {
throw new NbtApiException("Tried setting data in read only mode!");
}
this.compound = compound;
}
@Override
protected void saveCompound() {
owner.save();
}
}
@@ -1,45 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Long implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTLongList extends NBTList<Long> {
protected NBTLongList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Long object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGLONG.getClazz().getDeclaredConstructor(long.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Long get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Long.valueOf(obj.toString().replace("L", ""));
} catch (NumberFormatException nf) {
return 0l;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -1,32 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.util.Map;
import org.bukkit.persistence.PersistentDataContainer;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
public class NBTPersistentDataContainer extends NBTCompound {
private final PersistentDataContainer container;
public NBTPersistentDataContainer(PersistentDataContainer container) {
super(null, null);
this.container = container;
}
@Override
public Object getCompound() {
return ReflectionMethod.CRAFT_PERSISTENT_DATA_CONTAINER_TO_TAG.run(container);
}
@Override
protected void setCompound(Object compound) {
@SuppressWarnings("unchecked")
Map<Object, Object> map = (Map<Object, Object>) ReflectionMethod.CRAFT_PERSISTENT_DATA_CONTAINER_GET_MAP
.run(container);
map.clear();
ReflectionMethod.CRAFT_PERSISTENT_DATA_CONTAINER_PUT_ALL.run(container, compound);
}
}
@@ -1,637 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nonnull;
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.GsonWrapper;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ObjectCreator;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Utility class for translating NBTApi calls to reflections into NMS code All
* methods are allowed to throw {@link NbtApiException}
*
* @author tr7zw
*
*/
@SuppressWarnings("deprecation")
public class NBTReflectionUtil {
private static Field field_unhandledTags = null;
private static Field field_handle = null;
static {
try {
field_unhandledTags = ClassWrapper.CRAFT_METAITEM.getClazz().getDeclaredField("unhandledTags");
field_unhandledTags.setAccessible(true);
} catch (NoSuchFieldException e) {
}
try {
field_handle = ClassWrapper.CRAFT_ITEMSTACK.getClazz().getDeclaredField("handle");
field_handle.setAccessible(true);
} catch (NoSuchFieldException e) {
}
}
/**
* Hidden constructor
*/
private NBTReflectionUtil() {
}
/**
* Gets the NMS Entity for a given Bukkit Entity
*
* @param entity Bukkit Entity
* @return NMS Entity
*/
public static Object getNMSEntity(Entity entity) {
try {
return ReflectionMethod.CRAFT_ENTITY_GET_HANDLE.run(ClassWrapper.CRAFT_ENTITY.getClazz().cast(entity));
} catch (Exception e) {
throw new NbtApiException("Exception while getting the NMS Entity from a Bukkit Entity!", e);
}
}
/**
* Reads in a InputStream as NMS Compound
*
* @param stream InputStream of any NBT file
* @return NMS Compound
*/
public static Object readNBT(InputStream stream) {
try {
return ReflectionMethod.NBTFILE_READ.run(null, stream);
} catch (Exception e) {
try {
stream.close();
} catch (IOException ignore) {
}
throw new NbtApiException("Exception while reading a NBT File!", e);
}
}
/**
* Writes a NMS Compound to an OutputStream
*
* @param nbt NMS Compound
* @param stream Stream to write to
* @return ???
*/
public static Object writeNBT(Object nbt, OutputStream stream) {
try {
return ReflectionMethod.NBTFILE_WRITE.run(null, nbt, stream);
} catch (Exception e) {
throw new NbtApiException("Exception while writing NBT!", e);
}
}
/**
* Gets the nms handle ItemStack from a CraftItemStack. Passing Spigot
* ItemStacks will cause an error!
*
* @param item
* @return
*/
public static Object getCraftItemHandle(ItemStack item) {
try {
return field_handle.get(item);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new NbtApiException("Error getting handle from " + item.getClass(), e);
}
}
/**
* Writes a Compound to an OutputStream
*
* @param comp Compound
* @param stream Stream to write to
*/
public static void writeApiNBT(NBTCompound comp, OutputStream stream) {
try {
Object workingtag = comp.getResolvedObject();
ReflectionMethod.NBTFILE_WRITE.run(null, workingtag, stream);
} catch (Exception e) {
throw new NbtApiException("Exception while writing NBT!", e);
}
}
/**
* Simulates getOrCreateTag. If an Item doesn't yet have a Tag, it will return a
* new empty tag.
*
* @param nmsitem
* @return NMS Compound
*/
public static Object getItemRootNBTTagCompound(Object nmsitem) {
try {
Object answer = ReflectionMethod.NMSITEM_GETTAG.run(nmsitem);
return answer;
} catch (Exception e) {
throw new NbtApiException("Exception while getting an Itemstack's NBTCompound!", e);
}
}
/**
* Converts {@link NBTCompound} to NMS ItemStacks
*
* @param nbtcompound Any valid {@link NBTCompound}
* @return NMS ItemStack
*/
public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) {
try {
Object nmsComp = gettoCompount(nbtcompound.getCompound(), nbtcompound);
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) {
return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nmsComp);
} else {
return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nmsComp);
}
} catch (Exception e) {
throw new NbtApiException("Exception while converting NBTCompound to NMS ItemStack!", e);
}
}
/**
* Converts NMS ItemStacks to {@link NBTContainer}
*
* @param nmsitem NMS ItemStack
* @return {@link NBTContainer} with all the data
*/
public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) {
try {
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);
}
}
/**
* Gets a live copy of non-vanilla NBT tags.
*
* @param meta ItemMeta from which tags should be retrieved
* @return Map containing unhandled (custom) NBT tags
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> getUnhandledNBTTags(ItemMeta meta) {
try {
return (Map<String, Object>) field_unhandledTags.get(meta);
} catch (Exception e) {
throw new NbtApiException("Exception while getting unhandled tags from ItemMeta!", e);
}
}
/**
* Gets the Vanilla NBT Compound from a given NMS Entity
*
* @param nmsEntity
* @return NMS NBT Compound
*/
public static Object getEntityNBTTagCompound(Object nmsEntity) {
try {
Object nbt = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
Object answer = ReflectionMethod.NMS_ENTITY_GET_NBT.run(nmsEntity, nbt);
if (answer == null)
answer = nbt;
return answer;
} catch (Exception e) {
throw new NbtApiException("Exception while getting NBTCompound from NMS Entity!", e);
}
}
/**
* Loads all Vanilla tags from a NMS Compound into a NMS Entity
*
* @param nbtTag
* @param nmsEntity
* @return The NMS Entity
*/
public static Object setEntityNBTTag(Object nbtTag, Object nmsEntity) {
try {
ReflectionMethod.NMS_ENTITY_SET_NBT.run(nmsEntity, nbtTag);
return nmsEntity;
} catch (Exception ex) {
throw new NbtApiException("Exception while setting the NBTCompound of an Entity", ex);
}
}
/**
* Gets the NMS Compound from a given TileEntity
*
* @param tile
* @return NMS Compound with the Vanilla data
*/
public static Object getTileEntityNBTTagCompound(BlockState tile) {
try {
Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld());
Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld);
Object o = null;
if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) {
o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY_1_7_10.run(nmsworld, tile.getX(), tile.getY(),
tile.getZ());
} else {
Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ());
o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos);
}
Object answer = null;
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1)) {
answer = ReflectionMethod.TILEENTITY_GET_NBT_1181.run(o);
} else {
answer = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
ReflectionMethod.TILEENTITY_GET_NBT.run(o, answer);
}
if (answer == null) {
throw new NbtApiException("Unable to get NBTCompound from TileEntity! " + tile + " " + o);
}
return answer;
} catch (Exception e) {
throw new NbtApiException("Exception while getting NBTCompound from TileEntity!", e);
}
}
/**
* Sets Vanilla tags from a NMS Compound to a TileEntity
*
* @param tile
* @param comp
*/
public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) {
try {
Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld());
Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld);
Object o = null;
if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) {
o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY_1_7_10.run(nmsworld, tile.getX(), tile.getY(),
tile.getZ());
} else {
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)) {
ReflectionMethod.TILEENTITY_SET_NBT.run(o, comp);
} else if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1)) {
Object blockData = ReflectionMethod.TILEENTITY_GET_BLOCKDATA.run(o);
ReflectionMethod.TILEENTITY_SET_NBT_LEGACY1161.run(o, blockData, comp);
} else {
ReflectionMethod.TILEENTITY_SET_NBT_LEGACY1151.run(o, comp);
}
} catch (Exception e) {
throw new NbtApiException("Exception while setting NBTData for a TileEntity!", e);
}
}
/**
* Gets the subCompound with a given name from a NMS Compound
*
* @param compound
* @param name
* @return NMS Compound or null
*/
public static Object getSubNBTTagCompound(Object compound, String name) {
try {
if ((boolean) ReflectionMethod.COMPOUND_HAS_KEY.run(compound, name)) {
return ReflectionMethod.COMPOUND_GET_COMPOUND.run(compound, name);
} else {
throw new NbtApiException("Tried getting invalid compound '" + name + "' from '" + compound + "'!");
}
} catch (Exception e) {
throw new NbtApiException("Exception while getting NBT subcompounds!", e);
}
}
/**
* Creates a subCompound with a given name in the given NMS Compound
*
* @param comp
* @param name
*/
public static void addNBTTagCompound(NBTCompound comp, String name) {
if (name == null) {
remove(comp, name);
return;
}
Object nbttag = comp.getCompound();
if (nbttag == null) {
nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) {
return;
}
Object workingtag = gettoCompount(nbttag, comp);
try {
ReflectionMethod.COMPOUND_SET.run(workingtag, name,
ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance());
comp.setCompound(nbttag);
} catch (Exception e) {
throw new NbtApiException("Exception while adding a Compound!", e);
}
}
/**
* Checks if the Compound is correctly linked to it's roots
*
* @param comp
* @return true if this is a valide Compound, else false
*/
public static boolean valideCompound(NBTCompound comp) {
Object root = comp.getCompound();
if (root == null) {
root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
Object tmp = gettoCompount(root, comp);
comp.setResolvedObject(tmp);
return tmp != null;
}
protected static Object gettoCompount(Object nbttag, NBTCompound comp) {
Deque<String> structure = new ArrayDeque<>();
while (comp.getParent() != null) {
structure.add(comp.getName());
comp = comp.getParent();
}
while (!structure.isEmpty()) {
String target = structure.pollLast();
nbttag = getSubNBTTagCompound(nbttag, target);
if (nbttag == null) {
throw new NbtApiException("Unable to find tag '" + target + "' in " + nbttag);
}
}
return nbttag;
}
/**
* Merges the second {@link NBTCompound} into the first one
*
* @param comp Target for the merge
* @param nbtcompoundSrc Data to merge
*/
public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompoundSrc) {
Object workingtagSrc = nbtcompoundSrc.getResolvedObject();
if (workingtagSrc == null) {
return;
}
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
try {
ReflectionMethod.COMPOUND_MERGE.run(workingtag, workingtagSrc);
comp.setCompound(rootnbttag);
} catch (Exception e) {
throw new NbtApiException("Exception while merging two NBTCompounds!", e);
}
}
/**
* 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
*
* @param comp
* @param key
* @param val
*/
public static void set(NBTCompound comp, String key, Object val) {
if (val == null) {
remove(comp, key);
return;
}
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) {
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
}
Object workingtag = gettoCompount(rootnbttag, comp);
try {
ReflectionMethod.COMPOUND_SET.run(workingtag, key, val);
comp.setCompound(rootnbttag);
} catch (Exception e) {
throw new NbtApiException("Exception while setting key '" + key + "' to '" + val + "'!", e);
}
}
/**
* Returns the List saved with a given key.
*
* @param comp
* @param key
* @param type
* @param clazz
* @return The list at that key. Null if it's an invalid type
*/
@SuppressWarnings("unchecked")
public static <T> NBTList<T> getList(NBTCompound comp, String key, NBTType type, Class<T> clazz) {
Object workingtag = comp.getResolvedObject();
if (workingtag == null) {
workingtag = dummyNBT.getCompound(); // it creates a new ListTag if needed, but its unlinked
}
try {
Object nbt = ReflectionMethod.COMPOUND_GET_LIST.run(workingtag, key, type.getId());
if (clazz == String.class) {
return (NBTList<T>) new NBTStringList(comp, key, type, nbt);
} else if (clazz == NBTListCompound.class) {
return (NBTList<T>) new NBTCompoundList(comp, key, type, nbt);
} else if (clazz == Integer.class) {
return (NBTList<T>) new NBTIntegerList(comp, key, type, nbt);
} else if (clazz == Float.class) {
return (NBTList<T>) new NBTFloatList(comp, key, type, nbt);
} else if (clazz == Double.class) {
return (NBTList<T>) new NBTDoubleList(comp, key, type, nbt);
} else if (clazz == Long.class) {
return (NBTList<T>) new NBTLongList(comp, key, type, nbt);
} else if (clazz == int[].class) {
return (NBTList<T>) new NBTIntArrayList(comp, key, type, nbt);
} else if (clazz == UUID.class) {
return (NBTList<T>) new NBTUUIDList(comp, key, type, nbt);
} else {
return null;
}
} catch (Exception ex) {
throw new NbtApiException("Exception while getting a list with the type '" + type + "'!", ex);
}
}
public static NBTType getListType(NBTCompound comp, String key) {
Object workingtag = comp.getResolvedObject();
if (workingtag == null) {
workingtag = dummyNBT.getCompound(); // it creates a new ListTag if needed, but its unlinked
}
try {
Object nbt = ReflectionMethod.COMPOUND_GET.run(workingtag, key);
String fieldname = "type";
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1)) {
fieldname = "w";
}
Field f;
try {
f = nbt.getClass().getDeclaredField(fieldname);
} catch (NoSuchFieldException ignore) {
// fallback try mojang mapped/legacy
f = nbt.getClass().getDeclaredField("type");
}
f.setAccessible(true);
return NBTType.valueOf(f.getByte(nbt));
} catch (Exception ex) {
throw new NbtApiException("Exception while getting the list type!", ex);
}
}
public static Object getEntry(NBTCompound comp, String key) {
Object workingtag = comp.getResolvedObject();
try {
return ReflectionMethod.COMPOUND_GET.run(workingtag, key);
} catch (Exception ex) {
throw new NbtApiException("Exception while getting an Entry!", ex);
}
}
/**
* Uses Gson to set a {@link Serializable} value in a Compound
*
* @param comp
* @param key
* @param value
*/
public static void setObject(NBTCompound comp, String key, Object value) {
if (!MinecraftVersion.hasGsonSupport())
return;
try {
String json = GsonWrapper.getString(value);
setData(comp, ReflectionMethod.COMPOUND_SET_STRING, key, json);
} catch (Exception e) {
throw new NbtApiException("Exception while setting the Object '" + value + "'!", e);
}
}
/**
* Uses Gson to load back a {@link Serializable} object from the Compound
*
* @param comp
* @param key
* @param type
* @return The loaded Object or null, if not found
*/
public static <T> T getObject(NBTCompound comp, String key, Class<T> type) {
if (!MinecraftVersion.hasGsonSupport())
return null;
String json = (String) getData(comp, ReflectionMethod.COMPOUND_GET_STRING, key);
if (json == null) {
return null;
}
return GsonWrapper.deserializeJson(json, type);
}
/**
* Deletes the given key
*
* @param comp
* @param key
*/
public static void remove(NBTCompound comp, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
return;
Object workingtag = gettoCompount(rootnbttag, comp);
ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key);
comp.setCompound(rootnbttag);
}
/**
* Gets the Keyset inside this Compound
*
* @param comp
* @return Set of all keys
*/
@SuppressWarnings("unchecked")
public static Set<String> getKeys(NBTCompound comp) {
Object workingtag = comp.getResolvedObject();
return (Set<String>) ReflectionMethod.COMPOUND_GET_KEYS.run(workingtag);
}
/**
* Sets data inside the Compound
*
* @param comp
* @param type
* @param key
* @param data
*/
public static void setData(NBTCompound comp, ReflectionMethod type, String key, Object data) {
if (data == null) {
remove(comp, key);
return;
}
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
type.run(workingtag, key, data);
comp.setCompound(rootnbttag);
}
private final static NBTContainer dummyNBT = new NBTContainer();
/**
* Gets data from the Compound
*
* @param comp
* @param type
* @param key
* @return The value or default fallback from NMS
*/
public static Object getData(NBTCompound comp, ReflectionMethod type, String key) {
Object workingtag = comp.getResolvedObject();
// return default behavior data as if there was a compound
if (workingtag == null) {
workingtag = dummyNBT.getCompound();
}
return type.run(workingtag, key);
}
}
@@ -1,42 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* String implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTStringList extends NBTList<String> {
protected NBTStringList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
public String get(int index) {
try {
return (String) ReflectionMethod.LIST_GET_STRING.run(listObject, index);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
@Override
protected Object asTag(String object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGSTRING.getClazz().getDeclaredConstructor(String.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
}
@@ -1,111 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import org.bukkit.Bukkit;
import org.bukkit.block.BlockState;
import de.tr7zw.changeme.nbtapi.utils.CheckUtil;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
/**
* NBT class to access vanilla tags from TileEntities. TileEntities don't
* support custom tags. Use the NBTInjector for custom tags. Changes will be
* instantly applied to the Tile, use the merge method to do many things at
* once.
*
* @author tr7zw
*
*/
public class NBTTileEntity extends NBTCompound {
private final BlockState tile;
private final boolean readonly;
private final Object compound;
private boolean closed = false;
/**
* @param tile BlockState from any TileEntity
* @param readonly Readonly makes a copy at init, only reading from that copy
*/
public NBTTileEntity(BlockState tile, boolean readonly) {
super(null, null);
if (tile == null || (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3) && !tile.isPlaced())) {
throw new NullPointerException("Tile can't be null/not placed!");
}
this.tile = tile;
this.readonly = readonly;
if (readonly) {
this.compound = getCompound();
} else {
this.compound = null;
}
}
/**
* @param tile BlockState from any TileEntity
*/
public NBTTileEntity(BlockState tile) {
super(null, null);
if (tile == null || (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3) && !tile.isPlaced())) {
throw new NullPointerException("Tile can't be null/not placed!");
}
this.readonly = false;
this.compound = null;
this.tile = tile;
}
@Override
protected void setClosed() {
this.closed = true;
}
@Override
protected boolean isClosed() {
return closed;
}
@Override
protected boolean isReadOnly() {
return readonly;
}
@Override
public Object getCompound() {
// this runs before async check, since it's just a copy
if (readonly && compound != null) {
return compound;
}
if (!Bukkit.isPrimaryThread())
throw new NbtApiException("BlockEntity NBT needs to be accessed sync!");
return NBTReflectionUtil.getTileEntityNBTTagCompound(tile);
}
@Override
protected void setCompound(Object compound) {
if (readonly) {
throw new NbtApiException("Tried setting data in read only mode!");
}
if (!Bukkit.isPrimaryThread())
throw new NbtApiException("BlockEntity NBT needs to be accessed sync!");
NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound);
}
/**
* Gets the NBTCompound used by spigots PersistentDataAPI. This method is only
* available for 1.14+!
*
* @return NBTCompound containing the data of the PersistentDataAPI
*/
public NBTCompound getPersistentDataContainer() {
CheckUtil.assertAvailable(MinecraftVersion.MC1_14_R1);
if (hasTag("PublicBukkitValues")) {
return getCompound("PublicBukkitValues");
} else {
NBTContainer container = new NBTContainer();
container.addCompound("PublicBukkitValues").setString("__nbtapi",
"Marker to make the PersistentDataContainer have content");
mergeCompound(container);
return getCompound("PublicBukkitValues");
}
}
}
@@ -1,38 +0,0 @@
package de.tr7zw.changeme.nbtapi;
/**
* Enum of all NBT Types Minecraft contains
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum NBTType {
NBTTagEnd(0), NBTTagByte(1), NBTTagShort(2), NBTTagInt(3), NBTTagLong(4), NBTTagFloat(5), NBTTagDouble(6),
NBTTagByteArray(7), NBTTagString(8), NBTTagList(9), NBTTagCompound(10), NBTTagIntArray(11), NBTTagLongArray(12);
NBTType(int i) {
id = i;
}
private final int id;
/**
* @return Id used by Minecraft internally
*/
public int getId() {
return id;
}
/**
* @param id Internal Minecraft id
* @return Enum representing the id, NBTTagEnd for invalide ids
*/
public static NBTType valueOf(int id) {
for (NBTType t : values())
if (t.getId() == id)
return t;
return NBTType.NBTTagEnd;
}
}
@@ -1,53 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.UUID;
import de.tr7zw.changeme.nbtapi.utils.UUIDUtil;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Integer implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTUUIDList extends NBTList<UUID> {
private final NBTContainer tmpContainer;
protected NBTUUIDList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
this.tmpContainer = new NBTContainer();
}
@Override
protected Object asTag(UUID object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGINTARRAY.getClazz().getDeclaredConstructor(int[].class);
con.setAccessible(true);
return con.newInstance(UUIDUtil.uuidToIntArray(object));
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public UUID get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
ReflectionMethod.COMPOUND_SET.run(tmpContainer.getCompound(), "tmp", obj);
int[] val = tmpContainer.getIntArray("tmp");
tmpContainer.removeKey("tmp");
return UUIDUtil.uuidFromIntArray(val);
} catch (NumberFormatException nf) {
return null;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}
@@ -1,78 +0,0 @@
package de.tr7zw.changeme.nbtapi;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
/**
* A generic {@link RuntimeException} that can be thrown by most methods in the
* NBTAPI.
*
* @author tr7zw
*
*/
public class NbtApiException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = -993309714559452334L;
/**
* Keep track of the plugin selfcheck. Null = not
* checked(silentquickstart/shaded) true = selfcheck failed false = everything
* should be fine, but apparently wasn't?
*/
public static Boolean confirmedBroken = null;
/**
*
*/
public NbtApiException() {
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
*/
public NbtApiException(String message, Throwable cause) {
super(generateMessage(message), cause);
}
/**
* @param message
*/
public NbtApiException(String message) {
super(generateMessage(message));
}
/**
* @param cause
*/
public NbtApiException(Throwable cause) {
super(generateMessage(cause == null ? null : cause.toString()), cause);
}
private static String generateMessage(String message) {
if (message == null)
return null;
if (confirmedBroken == null) {
return "[?][" + MinecraftVersion.getNBTAPIVersion() + "]" + message;
} else if (confirmedBroken == false) {
return "[Selfchecked][" + MinecraftVersion.getNBTAPIVersion() + "]" + message;
}
return "[" + MinecraftVersion.getVersion() + "][" + MinecraftVersion.getNBTAPIVersion()
+ "]There were errors detected during the server self-check! Please, make sure that NBT-API is up to date. Error message: "
+ message;
}
}
@@ -1,89 +0,0 @@
package de.tr7zw.changeme.nbtapi.handler;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.NBT;
import de.tr7zw.changeme.nbtapi.iface.NBTHandler;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
public class NBTHandlers {
public static final NBTHandler<ItemStack> ITEM_STACK = new NBTHandler<ItemStack>() {
@Override
public boolean fuzzyMatch(Object obj) {
return obj instanceof ItemStack;
}
@Override
public void set(ReadWriteNBT nbt, String key, ItemStack value) {
nbt.removeKey(key);
ReadWriteNBT tag = nbt.getOrCreateCompound(key);
tag.mergeCompound(NBT.itemStackToNBT(value));
}
@Override
public ItemStack get(ReadableNBT nbt, String key) {
ReadableNBT tag = nbt.getCompound(key);
if (tag != null) {
return NBT.itemStackFromNBT(tag);
}
return null;
}
};
public static final NBTHandler<ReadableNBT> STORE_READABLE_TAG = new NBTHandler<ReadableNBT>() {
@Override
public boolean fuzzyMatch(Object obj) {
return obj instanceof ReadableNBT;
}
@Override
public void set(ReadWriteNBT nbt, String key, ReadableNBT value) {
nbt.removeKey(key);
nbt.getOrCreateCompound(key).mergeCompound(value);
}
@Override
public ReadableNBT get(ReadableNBT nbt, String key) {
ReadableNBT tag = nbt.getCompound(key);
if (tag != null) {
ReadWriteNBT value = NBT.createNBTObject();
value.mergeCompound(tag);
return value;
}
return null;
}
};
public static final NBTHandler<ReadWriteNBT> STORE_READWRITE_TAG = new NBTHandler<ReadWriteNBT>() {
@Override
public boolean fuzzyMatch(Object obj) {
return obj instanceof ReadWriteNBT;
}
@Override
public void set(ReadWriteNBT nbt, String key, ReadWriteNBT value) {
nbt.removeKey(key);
nbt.getOrCreateCompound(key).mergeCompound(value);
}
@Override
public ReadWriteNBT get(ReadableNBT nbt, String key) {
ReadableNBT tag = nbt.getCompound(key);
if (tag != null) {
ReadWriteNBT value = NBT.createNBTObject();
value.mergeCompound(tag);
return value;
}
return null;
}
};
}
@@ -1,15 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
import javax.annotation.Nonnull;
public interface NBTHandler<T> {
public default boolean fuzzyMatch(Object obj) {
return false;
}
public void set(@Nonnull ReadWriteNBT nbt, @Nonnull String key, @Nonnull T value);
public T get(@Nonnull ReadableNBT nbt, @Nonnull String key);
}
@@ -1,48 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
import java.util.function.BiConsumer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import de.tr7zw.changeme.nbtapi.NBTItem;
public interface ReadWriteItemNBT extends ReadWriteNBT, ReadableItemNBT {
/**
* True, if the item has any tags now known for this item type.
*
* @return true when custom tags are present
*/
public boolean hasCustomNbtData();
/**
* Remove all custom (non-vanilla) NBT tags from the NBTItem.
*/
public void clearCustomNBT();
/**
* Gives save access to the {@link ItemMeta} of the internal {@link ItemStack}.
* Supported operations while inside this scope: - any get/set method of
* {@link ItemMeta} - any getter on {@link NBTItem}
*
* All changes made to the {@link NBTItem} during this scope will be reverted at
* the end.
*
* @param handler
*/
public void modifyMeta(BiConsumer<ReadableNBT, ItemMeta> handler);
/**
* Gives save access to the {@link ItemMeta} of the internal {@link ItemStack}.
* Supported operations while inside this scope: - any get/set method of
* {@link ItemMeta} - any getter on {@link NBTItem}
*
* All changes made to the {@link NBTItem} during this scope will be reverted at
* the end.
*
* @param handler
*/
public <T extends ItemMeta> void modifyMeta(Class<T> type, BiConsumer<ReadableNBT, T> handler);
}
@@ -1,212 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
import java.util.UUID;
import javax.annotation.Nullable;
import org.bukkit.inventory.ItemStack;
public interface ReadWriteNBT extends ReadableNBT {
/**
* Merges all data from comp into this compound. This is done in one action, so
* it also works with Tiles/Entities
*
* @param comp
*/
void mergeCompound(ReadableNBT comp);
/**
* Setter
*
* @param key
* @param value
*/
void setString(String key, String value);
/**
* Setter
*
* @param key
* @param value
*/
void setInteger(String key, Integer value);
/**
* Setter
*
* @param key
* @param value
*/
void setDouble(String key, Double value);
/**
* Setter
*
* @param key
* @param value
*/
void setByte(String key, Byte value);
/**
* Setter
*
* @param key
* @param value
*/
void setShort(String key, Short value);
/**
* Setter
*
* @param key
* @param value
*/
void setLong(String key, Long value);
/**
* Setter
*
* @param key
* @param value
*/
void setFloat(String key, Float value);
/**
* Setter
*
* @param key
* @param value
*/
void setByteArray(String key, byte[] value);
/**
* Setter
*
* @param key
* @param value
*/
void setIntArray(String key, int[] value);
/**
* Setter
*
* Requires 1.16+
*
* @param key
* @param value
*/
void setLongArray(String key, long[] value);
/**
* Setter
*
* @param key
* @param value
*/
void setBoolean(String key, Boolean value);
/**
* Save an ItemStack as a compound under a given key
*
* @param key
* @param item
*/
void setItemStack(String key, ItemStack item);
/**
* Save an ItemStack Array as a compound under a given key
*
* @param key
* @param items
*/
void setItemStackArray(String key, ItemStack[] items);
/**
* Setter
*
* @param key
* @param value
*/
void setUUID(String key, UUID value);
/**
* @param key Deletes the given Key
*/
void removeKey(String key);
/**
* The same as addCompound, just with a name that better reflects what it does
*
* @param name
* @return
*/
ReadWriteNBT getOrCreateCompound(String name);
/**
* @param name
* @return The Compound instance or null
*/
@Nullable
ReadWriteNBT getCompound(String name);
/**
* Returns the resolved and creates compounds as required.
* <p>
*
* @param key Path key, seperated by '.'. For example: "foo.bar.baz". Dots can
* be escaped with a backslash.
* @return The resolved compound.
*/
ReadWriteNBT resolveOrCreateCompound(String key);
/**
* Set an Object to a key via the provided handler.
*
* @param <T>
* @param key
* @param value
* @param handler
*/
<T> void set(String key, T value, NBTHandler<T> handler);
/**
* Set a key to the given Enum value. It gets stored as a String. Passing null
* as value will call removeKey(key) instead.
*
* @param <E>
* @param key
* @param value
*/
<E extends Enum<?>> void setEnum(String key, E value);
@Override
ReadWriteNBTList<String> getStringList(String name);
@Override
ReadWriteNBTList<Integer> getIntegerList(String name);
@Override
ReadWriteNBTList<int[]> getIntArrayList(String name);
@Override
ReadWriteNBTList<UUID> getUUIDList(String name);
@Override
ReadWriteNBTList<Float> getFloatList(String name);
@Override
ReadWriteNBTList<Double> getDoubleList(String name);
@Override
ReadWriteNBTList<Long> getLongList(String name);
@Override
ReadWriteNBTCompoundList getCompoundList(String name);
/**
* Remove all keys from this compound
*/
void clearNBT();
}
@@ -1,35 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
import java.util.function.Predicate;
public interface ReadWriteNBTCompoundList extends ReadableNBTList<ReadWriteNBT> {
/**
* Adds a new compound tag to the current compound tag
*
* @return A new instance of the class.
*/
ReadWriteNBT addCompound();
/**
* Removes the element at the specified position in this list
*
* @param i The index of the element to remove.
* @return A new instance of the class.
*/
ReadWriteNBT remove(int i);
/**
* Clears the contents of the list
*/
void clear();
/**
* Removes all elements of this list that satisfy the given predicate
*
* @param pred The predicate to use to test elements.
* @return A boolean value.
*/
boolean removeIf(Predicate<? super ReadWriteNBT> pred);
}
@@ -1,116 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
import java.util.Collection;
import java.util.ListIterator;
import java.util.function.Predicate;
public interface ReadWriteNBTList<T> extends ReadableNBTList<T> {
/**
* Adds the specified element to this set if it is not already present.
*
* @param element The element to be added to the list.
* @return A boolean value.
*/
boolean add(T element);
/**
* Adds the specified element at the specified position in this list.
*
* @param index The index at which the specified element is to be inserted
* @param element The element to be added to the list.
*/
void add(int index, T element);
/**
* Replaces the element at the specified position in this list with the
* specified element.
*
* @param index The index of the element to replace
* @param element The element to be stored at the specified position
* @return The element that was previously at the specified position.
*/
T set(int index, T element);
/**
* Remove the element at index i and return it.
*
* @param i the index of the element to be removed
* @return The element that was removed.
*/
T remove(int i);
/**
* Clears the contents of the list
*/
void clear();
/**
* Adds all of the elements in the specified collection to this collection.
*
* @param c The collection to be added to the list.
* @return A boolean value.
*/
boolean addAll(Collection<? extends T> c);
/**
* Inserts all of the elements in the specified collection into this list,
* starting at the specified position.
*
* @param index The index at which the elements of the specified collection are
* to be inserted.
* @param c The collection to be added to the list.
* @return A boolean value.
*/
boolean addAll(int index, Collection<? extends T> c);
/**
* Removes from this collection all of its elements that are contained in the
* specified collection
*
* @param c The collection to be removed from this list.
* @return A boolean value.
*/
boolean removeAll(Collection<?> c);
/**
* Removes all of this collection's elements that are not contained in the
* specified collection.
*
* @param c The collection to be retained in this list
* @return A boolean value.
*/
boolean retainAll(Collection<?> c);
/**
* "Remove all elements from the list that match the given predicate."
*
* The Predicate interface is a functional interface that takes a single
* argument and returns a boolean
*
* @param pred The predicate to apply to each element to determine if it should
* be removed.
* @return A boolean value.
*/
boolean removeIf(Predicate<? super T> pred);
/**
* Removes the first occurrence of the specified element from this list, if it
* is present.
*
* @param o The object to be removed from the list.
* @return A boolean value.
*/
boolean remove(Object o);
/**
* Returns a list iterator over the elements in this list (in proper sequence),
* starting at the specified position in the list
*
* @param startIndex The index of the first element to be returned from the list
* iterator (by a call to the next method).
* @return A list iterator of the list starting at the specified index.
*/
ListIterator<T> listIterator(int startIndex);
}
@@ -1,12 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
public interface ReadableItemNBT extends ReadableNBT {
/**
* Returns true if the item has NBT data.
*
* @return Does the ItemStack have a NBTCompound.
*/
public boolean hasNBTData();
}
@@ -1,352 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
import org.bukkit.inventory.ItemStack;
import de.tr7zw.changeme.nbtapi.NBTType;
/**
* This interface only exposes methods that get data without any changes to the
* underlying object.
*
* @author tr7zw
*
*/
public interface ReadableNBT {
/**
* Given a key, return the value associated with that key.
*
* @param key The key to get the value for.
* @return The value of the key.
*/
String getString(String key);
/**
* Given a key, return the value associated with that key as an Integer, or 0 if
* the key is not found.
*
* @param key The key to look up in the properties file.
* @return The value of the key.
*/
Integer getInteger(String key);
/**
* Returns the value associated with the given key as a double, or false of not
* found.
*
* @param key The key of the preference to retrieve.
* @return A double value
*/
Double getDouble(String key);
/**
* Get the value of the given key as a byte, or 0 if the key is not found.
*
* @param key The key to get the value for.
* @return A byte
*/
Byte getByte(String key);
/**
* Returns the value of the key as a Short, or 0 if the key is not found.
*
* @param key The key of the value you want to get.
* @return A short value
*/
Short getShort(String key);
/**
* Returns the value associated with the given key as a Long, or 0 if the key is
* not found.
*
* @param key The key of the value you want to get.
* @return A Long object
*/
Long getLong(String key);
/**
* Returns the value of the given key as a Float, or 0 if the key does not
* exist.
*
* @param key The key of the preference to retrieve.
* @return A float value
*/
Float getFloat(String key);
/**
* Returns the value associated with the given key as a byte array, or null if
* the key is not found.
*
* @param key The key to use to retrieve the value.
* @return A byte array.
*/
@Nullable
byte[] getByteArray(String key);
/**
* Returns the value associated with the given key as an array of integers, or
* null if the key does not exist.
*
* @param key The key of the value you want to get.
* @return An array of integers.
*/
@Nullable
int[] getIntArray(String key);
/**
* Returns the value associated with the given key as an array of longs, or null
* if the key does not exist.
*
* Requires 1.16+
*
* @param key The key of the value you want to get.
* @return An array of integers.
*/
@Nullable
long[] getLongArray(String key);
/**
* Returns the value associated with the given key, or false if the key is not
* found.
*
* @param key The key of the preference to retrieve.
* @return A boolean value.
*/
Boolean getBoolean(String key);
/**
* It returns an ItemStack associated with the given key, or null if the key
* does not exist.
*
* @param key The key of the itemstack you want to get.
* @return An ItemStack
*/
@Nullable
ItemStack getItemStack(String key);
/**
* Get an {@link ItemStack} array that was saved at the given key, or null if no
* stored data was found
*
* @param key key
* @return The stored {@link ItemStack} array, or null if stored data wasn't
* found
*/
@Nullable
ItemStack[] getItemStackArray(String key);
/**
* Given a key, return the UUID of the key.
*
* @param key The key to get the value from
* @return A UUID object.
*/
@Nullable
UUID getUUID(String key);
/**
* Checks whether the provided key exists
*
* @param key String key
* @return true, if the key is set
*/
boolean hasTag(String key);
/**
* Checks whether the provided key exists and has the specified type
*
* @param key String key
* @param type nbt tag type
* @return whether the key is set and has the specified type
*/
default boolean hasTag(String key, NBTType type) {
return hasTag(key) && getType(key) == type;
}
/**
* @return Set of all stored Keys
*/
Set<String> getKeys();
/**
* @param name
* @return The Compound instance or null
*/
@Nullable
ReadableNBT getCompound(String name);
/**
* @param name
* @return The retrieved String List
*/
ReadableNBTList<String> getStringList(String name);
/**
* @param name
* @return The retrieved Integer List
*/
ReadableNBTList<Integer> getIntegerList(String name);
/**
* @param name
* @return The retrieved Integer List
*/
ReadableNBTList<int[]> getIntArrayList(String name);
/**
* @param name
* @return The retrieved Integer List
*/
ReadableNBTList<UUID> getUUIDList(String name);
/**
* @param name
* @return The retrieved Float List
*/
ReadableNBTList<Float> getFloatList(String name);
/**
* @param name
* @return The retrieved Double List
*/
ReadableNBTList<Double> getDoubleList(String name);
/**
* @param name
* @return The retrieved Long List
*/
ReadableNBTList<Long> getLongList(String name);
/**
* Returns the type of the list, null if not a list
*
* @param name
* @return
*/
@Nullable
NBTType getListType(String name);
/**
* @param name
* @return The retrieved Compound List
*/
ReadableNBTList<ReadWriteNBT> getCompoundList(String name);
/**
* Returns the stored value if exists, or provided value otherwise.
* <p>
* Supported types:
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
* {@link String}, {@link UUID}, and {@link Enum}
*
* @param key key
* @param defaultValue default non-null value
* @param <T> value type
* @return Stored or provided value
*/
<T> T getOrDefault(String key, T defaultValue);
/**
* Returns the stored value if exists, or null.
* <p>
* Supported types:
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
* {@link String}, {@link UUID}, and {@link Enum}
*
* @param key key
* @param type data type
* @param <T> value type
* @return Stored or provided value
*/
@Nullable
<T> T getOrNull(String key, Class<?> type);
/**
* Returns the resolved value if exists, or null.
* <p>
* Supported types:
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
* {@link String}, {@link UUID}, and {@link Enum}
*
* @param key Path key, seperated by '.'. For example: "foo.bar.baz". Dots can
* be escaped with a backslash.
* @param type data type
* @param <T> value type
* @return resolved or provided value
*/
@Nullable
<T> T resolveOrNull(String key, Class<?> type);
/**
* Returns the resolved value if exists, or provided value otherwise.
* <p>
* Supported types:
* {@code Boolean, Byte, Short, Integer, Long, Float, Double, byte[], int[], long[]},
* {@link String}, {@link UUID}, and {@link Enum}
*
* @param key Path key, seperated by '.'. For example: "foo.bar.baz".
* Dots can be escaped with a backslash.
* @param defaultValue default non-null value
* @param <T> value type
* @return resolved or provided value
*/
<T> T resolveOrDefault(String key, T defaultValue);
/**
* Returns the resolved Compound if exists, or null.
* <p>
*
* @param key Path key, seperated by '.'. For example: "foo.bar.baz". Dots can
* be escaped with a backslash.
* @return The resolved value if exists, or null.
*/
@Nullable
ReadableNBT resolveCompound(String key);
/**
* Get the object at the specified key via the handler.
*
* @param <T>
* @param key
* @param handler
* @return
*/
<T> T get(String key, NBTHandler<T> handler);
/**
* Get an Enum value that has been set via setEnum or setString(key,
* value.name()). Passing null/invalid keys will return null.
*
* @param <E>
* @param key
* @param type
* @return
*/
@Nullable
<E extends Enum<E>> E getEnum(String key, Class<E> type);
/**
* @param name
* @return The type of the given stored key or null
*/
NBTType getType(String name);
/**
* Write the content of this Compound into the provided stream.
*
* @param stream
*/
void writeCompound(OutputStream stream);
/**
* @return The NBT as printable NBT-Json.
*/
String toString();
}
@@ -1,117 +0,0 @@
package de.tr7zw.changeme.nbtapi.iface;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import de.tr7zw.changeme.nbtapi.NBTType;
public interface ReadableNBTList<T> extends Iterable<T> {
/**
* 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);
/**
* Returns the number of elements in this list.
*
* @return The size of the list.
*/
int size();
/**
* Returns the type of this tag
*
* @return The type of the tag.
*/
NBTType getType();
/**
* Returns true if the list is empty, false otherwise.
*
* @return A boolean value.
*/
boolean isEmpty();
/**
* Returns true if this list contains the specified element.
*
* @param o The object to be searched for in the list.
* @return A boolean value.
*/
boolean contains(Object o);
/**
* Returns the index of the first occurrence of the specified element in this
* list, or -1 if this list does not contain the element.
*
* @param o The object to search for.
* @return The index of the first occurrence of the specified element in this
* list, or -1 if this list does not contain the element.
*/
int indexOf(Object o);
/**
* Returns true if this collection contains all of the elements in the specified
* collection
*
* @param c The collection to be checked for containment in this list
* @return A boolean value.
*/
boolean containsAll(Collection<?> c);
/**
* Returns the index of the last occurrence of the specified element in this
* list, or -1 if this list does not contain the element
*
* @param o The object to search for.
* @return The index of the last occurrence of the specified element in this
* list, or -1 if this list does not contain the element.
*/
int lastIndexOf(Object o);
/**
* Returns an array containing all of the elements in this list in proper
* sequence (from first to last element).
*
* @return An array of objects.
*/
Object[] toArray();
/**
* Returns an array containing all of the elements in this list in proper
* sequence (from first to last element).
*
* @param a The array into which the elements of the list are to be stored, if
* it is big enough; otherwise, a new array of the same runtime type is
* allocated for this purpose.
* @return An array of the elements in the list.
*/
<E> E[] toArray(E[] a);
/**
* Returns a view of the portion of this list between the specified fromIndex,
* inclusive, and toIndex, exclusive
*
* @param fromIndex The starting index of the sublist (inclusive).
* @param toIndex The index of the last element in the sublist.
* @return A view of the specified range within this list.
*/
List<T> subList(int fromIndex, int toIndex);
/**
* Create a new list containing all entries of this list.
*
* @return A list of the elements in the stream.
*/
default List<T> toListCopy() {
List<T> list = new ArrayList<>();
iterator().forEachRemaining(list::add);
return list;
}
}
@@ -1,17 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public class CheckUtil {
private CheckUtil() {
// util
}
public static void assertAvailable(MinecraftVersion version) {
if (!MinecraftVersion.isAtLeastVersion(version))
throw new NbtApiException(
"This Method is only avaliable for the version " + version.name() + " and above!");
}
}
@@ -1,62 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils;
import com.google.gson.Gson;
import de.tr7zw.changeme.nbtapi.NbtApiException;
/**
* Helper class for 1.7 servers without Gson
*
* Please consider your own Gson/Jackson instance instead of the built in
* methods.
*
* @author tr7zw
*
*/
@Deprecated
public class GsonWrapper {
/**
* Private constructor
*/
private GsonWrapper() {
}
private static Gson gson = new Gson();
/**
* Turns Objects into Json Strings
*
* @param obj
* @return Json, representing the Object
*/
public static String getString(Object obj) {
return gson.toJson(obj);
}
public static void overwriteGsonInstance(Gson replacement) {
gson = replacement;
}
/**
* Creates an Object of the given type using the Json String
*
* @param json
* @param type
* @return Object that got created, or null if the json is null
*/
public static <T> T deserializeJson(String json, Class<T> type) {
try {
if (json == null) {
return null;
}
T obj = gson.fromJson(json, type);
return type.cast(obj);
} catch (Exception ex) {
throw new NbtApiException("Error while converting json to " + type.getName(), ex);
}
}
}
@@ -1,881 +0,0 @@
/*
* This Metrics class was auto-generated and can be copied into your project if you are
* not using a build tool like Gradle or Maven for dependency management.
*
* IMPORTANT: You are not allowed to modify this class, except changing the package.
*
* Disallowed modifications include but are not limited to:
* - Remove the option for users to opt-out
* - Change the frequency for data submission
* - Obfuscate the code (every obfuscator should allow you to make an exception for specific files)
* - Reformat the code (if you use a linter, add an exception)
*
* Violations will result in a ban of your plugin and account from bStats.
*/
package de.tr7zw.changeme.nbtapi.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
import javax.net.ssl.HttpsURLConnection;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
public class Metrics {
private final Plugin plugin;
private final MetricsBase metricsBase;
/**
* Creates a new Metrics instance.
*
* @param plugin Your plugin instance.
* @param serviceId The id of the service. It can be found at <a
* href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
*/
public Metrics(JavaPlugin plugin, int serviceId) {
this.plugin = plugin;
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
if (!config.isSet("serverUuid")) {
config.addDefault("enabled", true);
config.addDefault("serverUuid", UUID.randomUUID().toString());
config.addDefault("logFailedRequests", false);
config.addDefault("logSentData", false);
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config
.options()
.header(
"bStats (https://bStats.org) collects some basic information for plugin authors, like how\n"
+ "many people use their plugin and their total player count. It's recommended to keep bStats\n"
+ "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n"
+ "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n"
+ "anonymous.")
.copyDefaults(true);
try {
config.save(configFile);
} catch (IOException ignored) {
}
}
// Load the data
boolean enabled = config.getBoolean("enabled", true);
String serverUUID = config.getString("serverUuid");
boolean logErrors = config.getBoolean("logFailedRequests", false);
boolean logSentData = config.getBoolean("logSentData", false);
boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false);
metricsBase =
new MetricsBase(
"bukkit",
serverUUID,
serviceId,
enabled,
this::appendPlatformData,
this::appendServiceData,
submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask),
plugin::isEnabled,
(message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error),
(message) -> this.plugin.getLogger().log(Level.INFO, message),
logErrors,
logSentData,
logResponseStatusText);
}
/** Shuts down the underlying scheduler service. */
public void shutdown() {
metricsBase.shutdown();
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public void addCustomChart(CustomChart chart) {
metricsBase.addCustomChart(chart);
}
private void appendPlatformData(JsonObjectBuilder builder) {
builder.appendField("playerAmount", getPlayerAmount());
builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0);
builder.appendField("bukkitVersion", Bukkit.getVersion());
builder.appendField("bukkitName", Bukkit.getName());
builder.appendField("javaVersion", System.getProperty("java.version"));
builder.appendField("osName", System.getProperty("os.name"));
builder.appendField("osArch", System.getProperty("os.arch"));
builder.appendField("osVersion", System.getProperty("os.version"));
builder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
}
private void appendServiceData(JsonObjectBuilder builder) {
builder.appendField("pluginVersion", plugin.getDescription().getVersion());
}
private int getPlayerAmount() {
try {
// Around MC 1.8 the return type was changed from an array to a collection,
// This fixes java.lang.NoSuchMethodError:
// org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
return onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
} catch (Exception e) {
// Just use the new method if the reflection failed
return Bukkit.getOnlinePlayers().size();
}
}
public static class MetricsBase {
/** The version of the Metrics class. */
public static final String METRICS_VERSION = "3.0.2";
private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";
private final ScheduledExecutorService scheduler;
private final String platform;
private final String serverUuid;
private final int serviceId;
private final Consumer<JsonObjectBuilder> appendPlatformDataConsumer;
private final Consumer<JsonObjectBuilder> appendServiceDataConsumer;
private final Consumer<Runnable> submitTaskConsumer;
private final Supplier<Boolean> checkServiceEnabledSupplier;
private final BiConsumer<String, Throwable> errorLogger;
private final Consumer<String> infoLogger;
private final boolean logErrors;
private final boolean logSentData;
private final boolean logResponseStatusText;
private final Set<CustomChart> customCharts = new HashSet<>();
private final boolean enabled;
/**
* Creates a new MetricsBase class instance.
*
* @param platform The platform of the service.
* @param serviceId The id of the service.
* @param serverUuid The server uuid.
* @param enabled Whether or not data sending is enabled.
* @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all platform-specific data.
* @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all service-specific data.
* @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be
* used to delegate the data collection to a another thread to prevent errors caused by
* concurrency. Can be {@code null}.
* @param checkServiceEnabledSupplier A supplier to check if the service is still enabled.
* @param errorLogger A consumer that accepts log message and an error.
* @param infoLogger A consumer that accepts info log messages.
* @param logErrors Whether or not errors should be logged.
* @param logSentData Whether or not the sent data should be logged.
* @param logResponseStatusText Whether or not the response status text should be logged.
*/
public MetricsBase(
String platform,
String serverUuid,
int serviceId,
boolean enabled,
Consumer<JsonObjectBuilder> appendPlatformDataConsumer,
Consumer<JsonObjectBuilder> appendServiceDataConsumer,
Consumer<Runnable> submitTaskConsumer,
Supplier<Boolean> checkServiceEnabledSupplier,
BiConsumer<String, Throwable> errorLogger,
Consumer<String> infoLogger,
boolean logErrors,
boolean logSentData,
boolean logResponseStatusText) {
ScheduledThreadPoolExecutor scheduler =
new ScheduledThreadPoolExecutor(1, task -> new Thread(task, "bStats-Metrics"));
// We want delayed tasks (non-periodic) that will execute in the future to be
// cancelled when the scheduler is shutdown.
// Otherwise, we risk preventing the server from shutting down even when
// MetricsBase#shutdown() is called
scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
this.scheduler = scheduler;
this.platform = platform;
this.serverUuid = serverUuid;
this.serviceId = serviceId;
this.enabled = enabled;
this.appendPlatformDataConsumer = appendPlatformDataConsumer;
this.appendServiceDataConsumer = appendServiceDataConsumer;
this.submitTaskConsumer = submitTaskConsumer;
this.checkServiceEnabledSupplier = checkServiceEnabledSupplier;
this.errorLogger = errorLogger;
this.infoLogger = infoLogger;
this.logErrors = logErrors;
this.logSentData = logSentData;
this.logResponseStatusText = logResponseStatusText;
checkRelocation();
if (enabled) {
// WARNING: Removing the option to opt-out will get your plugin banned from
// bStats
startSubmitting();
}
}
public void addCustomChart(CustomChart chart) {
this.customCharts.add(chart);
}
public void shutdown() {
scheduler.shutdown();
}
private void startSubmitting() {
final Runnable submitTask =
() -> {
if (!enabled || !checkServiceEnabledSupplier.get()) {
// Submitting data or service is disabled
scheduler.shutdown();
return;
}
if (submitTaskConsumer != null) {
submitTaskConsumer.accept(this::submitData);
} else {
this.submitData();
}
};
// Many servers tend to restart at a fixed time at xx:00 which causes an uneven
// distribution of requests on the
// bStats backend. To circumvent this problem, we introduce some randomness into
// the initial and second delay.
// WARNING: You must not modify and part of this Metrics class, including the
// submit delay or frequency!
// WARNING: Modifying this code will get your plugin banned on bStats. Just
// don't do it!
long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
scheduler.scheduleAtFixedRate(
submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
}
private void submitData() {
final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
appendPlatformDataConsumer.accept(baseJsonBuilder);
final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
appendServiceDataConsumer.accept(serviceJsonBuilder);
JsonObjectBuilder.JsonObject[] chartData =
customCharts.stream()
.map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors))
.filter(Objects::nonNull)
.toArray(JsonObjectBuilder.JsonObject[]::new);
serviceJsonBuilder.appendField("id", serviceId);
serviceJsonBuilder.appendField("customCharts", chartData);
baseJsonBuilder.appendField("service", serviceJsonBuilder.build());
baseJsonBuilder.appendField("serverUUID", serverUuid);
baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION);
JsonObjectBuilder.JsonObject data = baseJsonBuilder.build();
scheduler.execute(
() -> {
try {
// Send the data
sendData(data);
} catch (Exception e) {
// Something went wrong! :(
if (logErrors) {
errorLogger.accept("Could not submit bStats metrics data", e);
}
}
});
}
private void sendData(JsonObjectBuilder.JsonObject data) throws Exception {
if (logSentData) {
infoLogger.accept("Sent bStats metrics data: " + data.toString());
}
String url = String.format(REPORT_URL, platform);
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip");
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("User-Agent", "Metrics-Service/1");
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(compressedData);
}
StringBuilder builder = new StringBuilder();
try (BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
}
if (logResponseStatusText) {
infoLogger.accept("Sent data to bStats and received response: " + builder);
}
}
/** Checks that the class was properly relocated. */
private void checkRelocation() {
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null
|| !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this
// little "trick" ... :D
final String defaultPackage =
new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
final String examplePackage =
new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure no one just copy & pastes the example and uses the wrong
// package names
if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage)
|| MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
/**
* Gzips the given string.
*
* @param str The string to gzip.
* @return The gzipped string.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
}
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimplePie(String chartId, Callable<String> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
String value = callable.call();
if (value == null || value.isEmpty()) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class AdvancedPie extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
}
}
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public abstract static class CustomChart {
private final String chartId;
protected CustomChart(String chartId) {
if (chartId == null) {
throw new IllegalArgumentException("chartId must not be null");
}
this.chartId = chartId;
}
public JsonObjectBuilder.JsonObject getRequestJsonObject(
BiConsumer<String, Throwable> errorLogger, boolean logErrors) {
JsonObjectBuilder builder = new JsonObjectBuilder();
builder.appendField("chartId", chartId);
try {
JsonObjectBuilder.JsonObject data = getChartData();
if (data == null) {
// If the data is null we don't send the chart.
return null;
}
builder.appendField("data", data);
} catch (Throwable t) {
if (logErrors) {
errorLogger.accept("Failed to get data for custom chart with id " + chartId, t);
}
return null;
}
return builder.build();
}
protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
/**
* An extremely simple JSON builder.
*
* <p>While this class is neither feature-rich nor the most performant one, it's sufficient enough
* for its use-case.
*/
public static class JsonObjectBuilder {
private StringBuilder builder = new StringBuilder();
private boolean hasAtLeastOneField = false;
public JsonObjectBuilder() {
builder.append("{");
}
/**
* Appends a null field to the JSON.
*
* @param key The key of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendNull(String key) {
appendFieldUnescaped(key, "null");
return this;
}
/**
* Appends a string field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String value) {
if (value == null) {
throw new IllegalArgumentException("JSON value must not be null");
}
appendFieldUnescaped(key, "\"" + escape(value) + "\"");
return this;
}
/**
* Appends an integer field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int value) {
appendFieldUnescaped(key, String.valueOf(value));
return this;
}
/**
* Appends an object to the JSON.
*
* @param key The key of the field.
* @param object The object.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject object) {
if (object == null) {
throw new IllegalArgumentException("JSON object must not be null");
}
appendFieldUnescaped(key, object.toString());
return this;
}
/**
* Appends a string array to the JSON.
*
* @param key The key of the field.
* @param values The string array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values)
.map(value -> "\"" + escape(value) + "\"")
.collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an integer array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an object array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends a field to the object.
*
* @param key The key of the field.
* @param escapedValue The escaped value of the field.
*/
private void appendFieldUnescaped(String key, String escapedValue) {
if (builder == null) {
throw new IllegalStateException("JSON has already been built");
}
if (key == null) {
throw new IllegalArgumentException("JSON key must not be null");
}
if (hasAtLeastOneField) {
builder.append(",");
}
builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
hasAtLeastOneField = true;
}
/**
* Builds the JSON string and invalidates this builder.
*
* @return The built JSON string.
*/
public JsonObject build() {
if (builder == null) {
throw new IllegalStateException("JSON has already been built");
}
JsonObject object = new JsonObject(builder.append("}").toString());
builder = null;
return object;
}
/**
* Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
*
* <p>This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
* Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
*
* @param value The value to escape.
* @return The escaped value.
*/
private static String escape(String value) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '"') {
builder.append("\\\"");
} else if (c == '\\') {
builder.append("\\\\");
} else if (c <= '\u000F') {
builder.append("\\u000").append(Integer.toHexString(c));
} else if (c <= '\u001F') {
builder.append("\\u00").append(Integer.toHexString(c));
} else {
builder.append(c);
}
}
return builder.toString();
}
/**
* A super simple representation of a JSON object.
*
* <p>This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
* allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
* JsonObject)}.
*/
public static class JsonObject {
private final String value;
private JsonObject(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}
}
}
@@ -1,310 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
/**
* This class acts as the "Brain" of the NBTApi. It contains the main logger for
* other classes,registers bStats and checks rather Maven shading was done
* correctly.
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum MinecraftVersion {
UNKNOWN(Integer.MAX_VALUE), // Use the newest known mappings
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);
private static MinecraftVersion version;
private static Boolean hasGsonSupport;
private static Boolean isForgePresent;
private static Boolean isFoliaPresent;
private static boolean bStatsDisabled = false;
private static boolean disablePackageWarning = false;
private static boolean updateCheckDisabled = true;
/**
* Logger used by the api
*/
private static Logger logger = Logger.getLogger("NBTAPI");
// NBT-API Version
protected static final String VERSION = "2.12.0-SNAPSHOT";
private final int versionId;
private final boolean mojangMapping;
MinecraftVersion(int versionId) {
this(versionId, false);
}
MinecraftVersion(int versionId, boolean mojangMapping) {
this.versionId = versionId;
this.mojangMapping = mojangMapping;
}
/**
* @return A simple comparable Integer, representing the version.
*/
public int getVersionId() {
return versionId;
}
/**
* @return True if method names are in Mojang format and need to be remapped
* internally
*/
public boolean isMojangMapping() {
return mojangMapping;
}
/**
* This method is required to hot-wire the plugin during mappings generation for
* newer mc versions thanks to md_5 not used mojmap.
*
* @return
*/
public String getPackageName() {
if (this == UNKNOWN) {
return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
}
return this.name().replace("MC", "v");
}
/**
* Returns true if the current versions is at least the given Version
*
* @param version The minimum version
* @return
*/
public static boolean isAtLeastVersion(MinecraftVersion version) {
return getVersion().getVersionId() >= version.getVersionId();
}
/**
* Returns true if the current versions newer (not equal) than the given version
*
* @param version The minimum version
* @return
*/
public static boolean isNewerThan(MinecraftVersion version) {
return getVersion().getVersionId() > version.getVersionId();
}
/**
* Getter for this servers MinecraftVersion. Also init's bStats and checks the
* shading.
*
* @return The enum for the MinecraftVersion this server is running
*/
public static MinecraftVersion getVersion() {
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 {
version = MinecraftVersion.valueOf(ver.replace("v", "MC"));
} catch (IllegalArgumentException ex) {
version = 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()
+ ". The NBT-API will try to work as good as it can! Some functions may not work!");
}
init();
return version;
}
public static String getNBTAPIVersion() {
return VERSION;
}
private static void init() {
try {
if (hasGsonSupport() && !bStatsDisabled) {
Plugin plugin = Bukkit.getPluginManager().getPlugin(VersionChecker.getPlugin());
if (plugin != null && plugin instanceof JavaPlugin) {
getLogger()
.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
new Metrics((JavaPlugin) plugin, 1058);
} else if (plugin == null) {
getLogger().info("[NBTAPI] Unable to create a bStats instance!!");
}
}
} catch (Exception ex) {
logger.log(Level.WARNING, "[NBTAPI] Error enabling Metrics!", ex);
}
if (hasGsonSupport() && !updateCheckDisabled)
new Thread(() -> {
try {
VersionChecker.checkForUpdates();
} catch (Exception ex) {
logger.log(Level.WARNING, "[NBTAPI] Error while checking for updates! Error: " + ex.getMessage());
}
}).start();
// Maven's Relocate is clever and changes strings, too. So we have to use this
// little "trick" ... :D (from bStats)
final String defaultPackage = new String(new byte[] { 'd', 'e', '.', 't', 'r', '7', 'z', 'w', '.', 'c', 'h',
'a', 'n', 'g', 'e', 'm', 'e', '.', 'n', 'b', 't', 'a', 'p', 'i', '.', 'u', 't', 'i', 'l', 's' });
final String reservedPackage = new String(new byte[] { 'd', 'e', '.', 't', 'r', '7', 'z', 'w', '.', 'n', 'b',
't', 'a', 'p', 'i', '.', 'u', 't', 'i', 'l', 's' });
if (!disablePackageWarning && MinecraftVersion.class.getPackage().getName().equals(defaultPackage)) {
logger.warning(
"#########################################- NBTAPI -#########################################");
logger.warning(
"The NBT-API package has not been moved! This *will* cause problems with other plugins containing");
logger.warning(
"a different version of the api! Please read the guide on the plugin page on how to get the");
logger.warning(
"Maven Shade plugin to relocate the api to your personal location! If you are not the developer,");
logger.warning("please check your plugins and contact their developer, so they can fix this issue.");
logger.warning(
"#########################################- NBTAPI -#########################################");
}
if (!disablePackageWarning && !"NBTAPI".equals(VersionChecker.getPlugin())) { // we are not the nbtapi, check
// for common shading errors
if (!"de.tr7zw.nbtapi.utils".equals(reservedPackage)) {
logger.warning(
"#########################################- NBTAPI -#########################################");
logger.warning(
"The NBT-API inside " + VersionChecker.getPlugin() + " is the plugin version, not the API!");
logger.warning(
"The plugin itself should never be shaded! Remove the `-plugin` from the dependency and fix your shading setup.");
logger.warning(
"For more info check: https://github.com/tr7zw/Item-NBT-API/wiki/Using-Maven#option-2-shading-the-nbt-api-into-your-plugin");
logger.warning(
"#########################################- NBTAPI -#########################################");
return; // don't also print the second error
}
if (MinecraftVersion.class.getPackage().getName().equals("de.tr7zw.nbtapi.utils")) {
logger.warning(
"#########################################- NBTAPI -#########################################");
logger.warning(
"The NBT-API inside " + VersionChecker.getPlugin() + " is located at 'de.tr7zw.nbtapi.utils'!");
logger.warning(
"This package name is reserved for the official NBTAPI plugin, and not intended to be used for shading!");
logger.warning("Please change the relocate to something else. For example: com.example.util.nbtapi");
logger.warning(
"#########################################- NBTAPI -#########################################");
}
}
}
/**
* @return True, if Gson is usable
*/
public static boolean hasGsonSupport() {
if (hasGsonSupport != null) {
return hasGsonSupport;
}
try {
Class.forName("com.google.gson.Gson");
hasGsonSupport = true;
} catch (Exception ex) {
logger.info("[NBTAPI] Gson not found! This will not allow the usage of some methods!");
hasGsonSupport = false;
}
return hasGsonSupport;
}
/**
* @return True, if Forge is present
*/
public static boolean isForgePresent() {
if (isForgePresent != null) {
return isForgePresent;
}
try {
logger.info("[NBTAPI] Found Forge: "
+ (getVersion() == MinecraftVersion.MC1_7_R4 ? Class.forName("cpw.mods.fml.common.Loader")
: Class.forName("net.minecraftforge.fml.common.Loader")));
isForgePresent = true;
} catch (Exception ex) {
isForgePresent = false;
}
return isForgePresent;
}
/**
* @return True, if Folia is present
*/
public static boolean isFoliaPresent() {
if (isFoliaPresent != null) {
return isFoliaPresent;
}
try {
logger.info("[NBTAPI] Found Folia: "
+ Class.forName("io.papermc.paper.threadedregions.RegionizedServer"));
isFoliaPresent = true;
} catch (Exception ex) {
isFoliaPresent = false;
}
return isFoliaPresent;
}
/**
* Calling this function before the NBT-Api is used will disable bStats stats
* collection. Please consider not to do that, since it won't affect your plugin
* and helps the NBT-Api developer to see api's demand.
*/
public static void disableBStats() {
bStatsDisabled = true;
}
/**
* Disables the update check. Uses Spiget to get the current version and prints
* a warning when outdated.
*/
public static void disableUpdateCheck() {
updateCheckDisabled = true;
}
/**
* Enables the update check. Uses Spiget to get the current version and prints a
* warning when outdated.
*/
public static void enableUpdateCheck() {
updateCheckDisabled = false;
}
/**
* Forcefully disables the log message for plugins not shading the API to
* another location. This may be helpful for networks or development
* environments, but please don't use it for plugins that are uploaded to
* Spigotmc.
*/
public static void disablePackageWarning() {
disablePackageWarning = true;
}
/**
* @return Logger used by the NBT-API
*/
public static Logger getLogger() {
return logger;
}
/**
* Replaces the NBT-API logger with a custom implementation.
*
* @param logger The new logger(can not be null!)
*/
public static void replaceLogger(Logger logger) {
if (logger == null)
throw new NullPointerException("Logger can not be null!");
MinecraftVersion.logger = logger;
}
}
@@ -1,24 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class PathUtil {
private static final Pattern pattern = Pattern.compile("[^\\\\](\\.)");
public static List<String> splitPath(String path) {
List<String> list = new ArrayList<>();
Matcher matcher = pattern.matcher(path);
int startIndex = 0;
while (matcher.find(startIndex)) {
list.add(path.substring(startIndex, matcher.end() - 1).replace("\\.", "."));
startIndex = matcher.end();
}
list.add(path.substring(startIndex).replace("\\.", "."));
return list;
}
}
@@ -1,53 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public final class ReflectionUtil {
private static Field field_modifiers;
static {
try {
field_modifiers = Field.class.getDeclaredField("modifiers");
field_modifiers.setAccessible(true);
} catch (NoSuchFieldException ex) {
try {
// This hacky workaround is for newer jdk versions 11+?
Method fieldGetter = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
fieldGetter.setAccessible(true);
Field[] fields = (Field[]) fieldGetter.invoke(Field.class, false);
for (Field f : fields)
if (f.getName().equals("modifiers")) {
field_modifiers = f;
field_modifiers.setAccessible(true);
break;
}
} catch (Exception e) {
throw new NbtApiException(e);
}
}
if (field_modifiers == null) {
throw new NbtApiException("Unable to init the modifiers Field.");
}
}
public static Field makeNonFinal(Field field) throws IllegalArgumentException, IllegalAccessException {
int mods = field.getModifiers();
if (Modifier.isFinal(mods)) {
field_modifiers.set(field, mods & ~Modifier.FINAL);
}
return field;
}
public static void setFinal(Object obj, Field field, Object newValue)
throws IllegalArgumentException, IllegalAccessException {
field.setAccessible(true);
field = makeNonFinal(field);
field.set(obj, newValue);
}
}
@@ -1,22 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.util.UUID;
public class UUIDUtil {
public static UUID uuidFromIntArray(int[] is) {
return new UUID((long) is[0] << 32 | (long) is[1] & 4294967295L,
(long) is[2] << 32 | (long) is[3] & 4294967295L);
}
public static int[] uuidToIntArray(UUID uUID) {
long l = uUID.getMostSignificantBits();
long m = uUID.getLeastSignificantBits();
return leastMostToIntArray(l, m);
}
private static int[] leastMostToIntArray(long l, long m) {
return new int[] { (int) (l >> 32), (int) l, (int) (m >> 32), (int) m };
}
}
@@ -1,125 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Level;
import org.bukkit.configuration.file.YamlConfiguration;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import de.tr7zw.changeme.nbtapi.NBTItem;
/**
* This class uses the Spiget API to check for updates
*
*/
public class VersionChecker {
private static final String USER_AGENT = "nbt-api Version check";
private static final String REQUEST_URL = "https://api.spiget.org/v2/resources/7939/versions?size=100";
public static boolean hideOk = false;
protected static void checkForUpdates() throws Exception {
URL url = new URL(REQUEST_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("User-Agent", USER_AGENT);// Set
// User-Agent
// If you're not sure if the request will be successful,
// you need to check the response code and use #getErrorStream if it
// returned an error code
InputStream inputStream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
// This could be either a JsonArray or JsonObject
JsonElement element = new JsonParser().parse(reader);
if (element.isJsonArray()) {
// Is JsonArray
JsonArray updates = (JsonArray) element;
JsonObject latest = (JsonObject) updates.get(updates.size() - 1);
int versionDifference = getVersionDifference(latest.get("name").getAsString());
if (versionDifference == -1) { // Outdated
MinecraftVersion.getLogger().log(Level.WARNING,
"[NBTAPI] The NBT-API in '" + getPlugin() + "' seems to be outdated!");
MinecraftVersion.getLogger().log(Level.WARNING, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION
+ "' Newest Version: " + latest.get("name").getAsString() + "'");
MinecraftVersion.getLogger().log(Level.WARNING,
"[NBTAPI] Please update the NBTAPI or the plugin that contains the api(nag the mod author when the newest release has an old version, not the NBTAPI dev)!");
} else if (versionDifference == 0) {
if (!hideOk)
MinecraftVersion.getLogger().log(Level.INFO, "[NBTAPI] The NBT-API seems to be up-to-date!");
} else if (versionDifference == 1) {
MinecraftVersion.getLogger().log(Level.INFO, "[NBTAPI] The NBT-API in '" + getPlugin()
+ "' seems to be a future Version, not yet released on Spigot/CurseForge! This is not an error!");
MinecraftVersion.getLogger().log(Level.INFO, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION
+ "' Newest Version: " + latest.get("name").getAsString() + "'");
}
} else {
// wut?!
MinecraftVersion.getLogger().log(Level.WARNING,
"[NBTAPI] Error when looking for Updates! Got non Json Array: '" + element.toString() + "'");
}
}
// -1 = we are outdated
// 0 = up to date
// 1 = using a future version
// This method is only able to compare the Format 0.0.0(-SNAPSHOT)
private static int getVersionDifference(String version) {
String current = MinecraftVersion.VERSION;
if (current.equals(version))
return 0;
String pattern = "\\.";
if (current.split(pattern).length != 3 || version.split(pattern).length != 3)
return -1;
int curMaj = Integer.parseInt(current.split(pattern)[0]);
int curMin = Integer.parseInt(current.split(pattern)[1]);
String curPatch = current.split(pattern)[2];
int relMaj = Integer.parseInt(version.split(pattern)[0]);
int relMin = Integer.parseInt(version.split(pattern)[1]);
String relPatch = version.split(pattern)[2];
if (curMaj < relMaj)
return -1;
if (curMaj > relMaj)
return 1;
if (curMin < relMin)
return -1;
if (curMin > relMin)
return 1;
int curPatchN = Integer.parseInt(curPatch.split("-")[0]);
int relPatchN = Integer.parseInt(relPatch.split("-")[0]);
if (curPatchN < relPatchN)
return -1;
if (curPatchN > relPatchN)
return 1;
if (!relPatch.contains("-") && curPatch.contains("-"))
return -1; // Release has no - but we do = We use a Snapshot of the
// release
if (relPatch.contains("-") && curPatch.contains("-"))
return 0; // Release and cur are Snapshots/alpha/beta
return 1;
}
protected static String getPlugin() {
ClassLoader classLoader = VersionChecker.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("plugin.yml");
if (inputStream != null) {
try (InputStreamReader reader = new InputStreamReader(inputStream)) {
YamlConfiguration pluginYml = YamlConfiguration.loadConfiguration(reader);
return pluginYml.getString("name");
} catch (IOException e) {
// ignored
}
}
return NBTItem.class.getPackage().getName();
}
}
@@ -1,132 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
import static de.tr7zw.changeme.nbtapi.utils.MinecraftVersion.getLogger;
import java.util.logging.Level;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
/**
* Wraps NMS and CRAFT classes
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum ClassWrapper {
CRAFT_ITEMSTACK(PackageWrapper.CRAFTBUKKIT, "inventory.CraftItemStack", null, null),
CRAFT_METAITEM(PackageWrapper.CRAFTBUKKIT, "inventory.CraftMetaItem", null, null),
CRAFT_ENTITY(PackageWrapper.CRAFTBUKKIT, "entity.CraftEntity", null, null),
CRAFT_WORLD(PackageWrapper.CRAFTBUKKIT, "CraftWorld", null, null),
CRAFT_PERSISTENTDATACONTAINER(PackageWrapper.CRAFTBUKKIT, "persistence.CraftPersistentDataContainer",
MinecraftVersion.MC1_14_R1, null),
NMS_NBTBASE(PackageWrapper.NMS, "NBTBase", null, null, "net.minecraft.nbt", "net.minecraft.nbt.Tag"),
NMS_NBTTAGSTRING(PackageWrapper.NMS, "NBTTagString", null, null, "net.minecraft.nbt",
"net.minecraft.nbt.StringTag"),
NMS_NBTTAGINT(PackageWrapper.NMS, "NBTTagInt", null, null, "net.minecraft.nbt", "net.minecraft.nbt.IntTag"),
NMS_NBTTAGINTARRAY(PackageWrapper.NMS, "NBTTagIntArray", null, null, "net.minecraft.nbt",
"net.minecraft.nbt.IntArrayTag"),
NMS_NBTTAGFLOAT(PackageWrapper.NMS, "NBTTagFloat", null, null, "net.minecraft.nbt", "net.minecraft.nbt.FloatTag"),
NMS_NBTTAGDOUBLE(PackageWrapper.NMS, "NBTTagDouble", null, null, "net.minecraft.nbt",
"net.minecraft.nbt.DoubleTag"),
NMS_NBTTAGLONG(PackageWrapper.NMS, "NBTTagLong", null, null, "net.minecraft.nbt", "net.minecraft.nbt.LongTag"),
NMS_ITEMSTACK(PackageWrapper.NMS, "ItemStack", null, null, "net.minecraft.world.item",
"net.minecraft.world.item.ItemStack"),
NMS_NBTTAGCOMPOUND(PackageWrapper.NMS, "NBTTagCompound", null, null, "net.minecraft.nbt",
"net.minecraft.nbt.CompoundTag"),
NMS_NBTTAGLIST(PackageWrapper.NMS, "NBTTagList", null, null, "net.minecraft.nbt", "net.minecraft.nbt.ListTag"),
NMS_NBTCOMPRESSEDSTREAMTOOLS(PackageWrapper.NMS, "NBTCompressedStreamTools", null, null, "net.minecraft.nbt",
"net.minecraft.nbt.NbtIo"),
NMS_MOJANGSONPARSER(PackageWrapper.NMS, "MojangsonParser", null, null, "net.minecraft.nbt",
"net.minecraft.nbt.TagParser"),
NMS_TILEENTITY(PackageWrapper.NMS, "TileEntity", null, null, "net.minecraft.world.level.block.entity",
"net.minecraft.world.level.block.entity.BlockEntity"),
NMS_BLOCKPOSITION(PackageWrapper.NMS, "BlockPosition", MinecraftVersion.MC1_8_R3, null, "net.minecraft.core",
"net.minecraft.core.BlockPos"),
NMS_WORLDSERVER(PackageWrapper.NMS, "WorldServer", null, null, "net.minecraft.server.level",
"net.minecraft.server.level.ServerLevel"),
NMS_MINECRAFTSERVER(PackageWrapper.NMS, "MinecraftServer", null, null, "net.minecraft.server",
"net.minecraft.server.MinecraftServer"),
NMS_WORLD(PackageWrapper.NMS, "World", null, null, "net.minecraft.world.level", "net.minecraft.world.level.Level"),
NMS_ENTITY(PackageWrapper.NMS, "Entity", null, null, "net.minecraft.world.entity",
"net.minecraft.world.entity.Entity"),
NMS_ENTITYTYPES(PackageWrapper.NMS, "EntityTypes", null, null, "net.minecraft.world.entity",
"net.minecraft.world.entity.EntityType"),
NMS_REGISTRYSIMPLE(PackageWrapper.NMS, "RegistrySimple", MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_12_R1),
NMS_REGISTRYMATERIALS(PackageWrapper.NMS, "RegistryMaterials", null, null, "net.minecraft.core",
"net.minecraft.core.MappedRegistry"),
NMS_IREGISTRY(PackageWrapper.NMS, "IRegistry", null, null, "net.minecraft.core", "net.minecraft.core.Registry"),
NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey", MinecraftVersion.MC1_8_R3, null, "net.minecraft.resources",
"net.minecraft.resources.ResourceKey"),
NMS_GAMEPROFILESERIALIZER(PackageWrapper.NMS, "GameProfileSerializer", null, null, "net.minecraft.nbt",
"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"),
GAMEPROFILE(PackageWrapper.NONE, "com.mojang.authlib.GameProfile", MinecraftVersion.MC1_8_R3, null);
private Class<?> clazz;
private boolean enabled = false;
private final String mojangName;
ClassWrapper(PackageWrapper packageId, String clazzName, MinecraftVersion from, MinecraftVersion to) {
this(packageId, clazzName, from, to, null, null);
}
ClassWrapper(PackageWrapper packageId, String clazzName, MinecraftVersion from, MinecraftVersion to,
String mojangMap, String mojangName) {
this.mojangName = mojangName;
if (from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId()) {
return;
}
if (to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId()) {
return;
}
enabled = true;
try {
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_18_R1) && mojangName != null) {
// check for Mojmapped enviroment
try {
clazz = Class.forName(mojangName);
return;
} catch (ClassNotFoundException ex) {
// ignored, not mojang mapped
}
}
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_17_R1) && mojangMap != null) {
clazz = Class.forName(mojangMap + "." + clazzName);
} else if (packageId == PackageWrapper.NONE) {
clazz = Class.forName(clazzName);
} 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 {
String version = MinecraftVersion.getVersion().getPackageName();
clazz = Class.forName(packageId.getUri() + "." + version + "." + clazzName);
}
} catch (Throwable ex) {
getLogger().log(Level.WARNING, "[NBTAPI] Error while trying to resolve the class '" + clazzName + "'!", ex);
}
}
/**
* @return The wrapped class
*/
public Class<?> getClazz() {
return clazz;
}
/**
* @return Is this class available in this Version
*/
public boolean isEnabled() {
return enabled;
}
/**
* @return Package+Class name used by Mojang
*/
public String getMojangName() {
return mojangName;
}
}
@@ -1,126 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* Temporary solution to hold Forge1710 mappings.
*
* @author EverNife
*
*/
public class Forge1710Mappings {
private static Map<String, String> classMap = new HashMap<>();
private static Map<String, String> methodMap = new HashMap<>();
private static Method crucible_toString;
static {
// Fields
classMap.put("NMS_NBTBASE", "net.minecraft.nbt.NBTBase");
classMap.put("NMS_NBTTAGSTRING", "net.minecraft.nbt.NBTTagString");
classMap.put("NMS_NBTTAGINT", "net.minecraft.nbt.NBTTagInt");
classMap.put("NMS_NBTTAGINTARRAY", "net.minecraft.nbt.NBTTagIntArray");
classMap.put("NMS_NBTTAGFLOAT", "net.minecraft.nbt.NBTTagFloat");
classMap.put("NMS_NBTTAGDOUBLE", "net.minecraft.nbt.NBTTagDouble");
classMap.put("NMS_NBTTAGLONG", "net.minecraft.nbt.NBTTagLong");
classMap.put("NMS_ITEMSTACK", "net.minecraft.item.ItemStack");
classMap.put("NMS_NBTTAGCOMPOUND", "net.minecraft.nbt.NBTTagCompound");
classMap.put("NMS_NBTTAGLIST", "net.minecraft.nbt.NBTTagList");
classMap.put("NMS_NBTCOMPRESSEDSTREAMTOOLS", "net.minecraft.nbt.CompressedStreamTools");
classMap.put("NMS_MOJANGSONPARSER", "io.github.crucible.nbt.Crucible_JsonToNBT");
classMap.put("NMS_TILEENTITY", "net.minecraft.tileentity.TileEntity");
classMap.put("NMS_WORLDSERVER", "net.minecraft.world.WorldServer");
classMap.put("NMS_MINECRAFTSERVER", "net.minecraft.server.MinecraftServer");
classMap.put("NMS_WORLD", "net.minecraft.world.World");
classMap.put("NMS_ENTITY", "net.minecraft.entity.Entity");
classMap.put("NMS_ENTITYTYPES", "net.minecraft.entity.EntityList");
classMap.put("NMS_REGISTRYMATERIALS", "net.minecraft.util.RegistryNamespaced");
classMap.put("NMS_GAMEPROFILESERIALIZER", "net.minecraft.nbt.NBTUtil");
classMap.put("NMS_IREGISTRY", "net.minecraft.util.IRegistry");
// Methods
methodMap.put("COMPOUND_SET_FLOAT", "func_74776_a");
methodMap.put("COMPOUND_SET_STRING", "func_74778_a");
methodMap.put("COMPOUND_SET_INT", "func_74768_a");
methodMap.put("COMPOUND_SET_BYTEARRAY", "func_74773_a");
methodMap.put("COMPOUND_SET_INTARRAY", "func_74783_a");
methodMap.put("COMPOUND_SET_LONG", "func_74772_a");
methodMap.put("COMPOUND_SET_SHORT", "func_74777_a");
methodMap.put("COMPOUND_SET_BYTE", "func_74774_a");
methodMap.put("COMPOUND_SET_DOUBLE", "func_74780_a");
methodMap.put("COMPOUND_SET_BOOLEAN", "func_74757_a");
methodMap.put("COMPOUND_MERGE", "merge");// Only present on Crucible
methodMap.put("COMPOUND_SET", "func_74782_a");
methodMap.put("COMPOUND_GET", "func_74781_a");
methodMap.put("COMPOUND_GET_LIST", "func_150295_c");
methodMap.put("COMPOUND_OWN_TYPE", "func_74732_a");
methodMap.put("COMPOUND_GET_FLOAT", "func_74760_g");
methodMap.put("COMPOUND_GET_STRING", "func_74779_i");
methodMap.put("COMPOUND_GET_INT", "func_74762_e");
methodMap.put("COMPOUND_GET_BYTEARRAY", "func_74770_j");
methodMap.put("COMPOUND_GET_INTARRAY", "func_74759_k");
methodMap.put("COMPOUND_GET_LONG", "func_74763_f");
methodMap.put("COMPOUND_GET_SHORT", "func_74765_d");
methodMap.put("COMPOUND_GET_BYTE", "func_74771_c");
methodMap.put("COMPOUND_GET_DOUBLE", "func_74769_h");
methodMap.put("COMPOUND_GET_BOOLEAN", "func_74767_n");
methodMap.put("COMPOUND_GET_COMPOUND", "func_74775_l");
methodMap.put("COMPOUND_REMOVE_KEY", "func_82580_o");
methodMap.put("COMPOUND_HAS_KEY", "func_74764_b");
methodMap.put("COMPOUND_GET_KEYS", "func_150296_c");
methodMap.put("LISTCOMPOUND_GET_KEYS", "func_150296_c");
methodMap.put("NMSITEM_GETTAG", "func_77978_p");
methodMap.put("NMSITEM_SAVE", "func_77955_b");
methodMap.put("NMSITEM_CREATESTACK", "func_77949_a");
methodMap.put("ITEMSTACK_SET_TAG", "func_77982_d");
methodMap.put("LIST_SIZE", "func_74745_c");
methodMap.put("LEGACY_LIST_ADD", "func_74742_a");
methodMap.put("LIST_GET_STRING", "func_150307_f");
methodMap.put("LIST_GET_COMPOUND", "func_150305_b");
methodMap.put("LIST_GET", "func_150305_b");
methodMap.put("NMS_WORLD_GET_TILEENTITY_1_7_10", "func_147438_o");
methodMap.put("TILEENTITY_GET_NBT", "func_145841_b");
methodMap.put("TILEENTITY_SET_NBT", "func_145839_a");
methodMap.put("TILEENTITY_SET_NBT_LEGACY1151", "func_145839_a");
methodMap.put("NMS_ENTITY_GET_NBT", "func_70109_d");
methodMap.put("NMS_ENTITY_SET_NBT", "func_70020_e");
methodMap.put("NBTFILE_READ", "func_74796_a");
methodMap.put("NBTFILE_WRITE", "func_74799_a");
methodMap.put("PARSE_NBT", "getTagFromJson");
methodMap.put("GAMEPROFILE_DESERIALIZE", "func_152459_a");
// Crucible
try {
crucible_toString = Class.forName("net.minecraft.nbt.NBTTagCompound")
.getDeclaredMethod("crucible_toString");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Map<String, String> getClassMappings() {
return classMap;
}
public static Map<String, String> getMethodMapping() {
return methodMap;
}
public static String toString(Object nbtTagCompound) {
if (crucible_toString == null)
throw new NbtApiException("Method not loaded! 'Forge1710Mappings.crucible_toString' ");
try {
return (String) crucible_toString.invoke(nbtTagCompound);
} catch (Exception ex) {
throw new NbtApiException(
"Error while calling the method 'crucible_toString', from Forge1710Mappings. Passed Class: "
+ Forge1710Mappings.class,
ex);
}
}
}
@@ -1,142 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
import java.util.HashMap;
import java.util.Map;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
/**
* Temporary solution to hold Mojang to unmapped Spigot mappings.
*
* @author tr7zw
*
*/
public class MojangToMapping {
@SuppressWarnings("serial")
private static Map<String, String> MC1_18R1 = new HashMap<String, String>() {
{
put("net.minecraft.nbt.CompoundTag#contains(java.lang.String)", "e");
put("net.minecraft.nbt.CompoundTag#getCompound(java.lang.String)", "p");
put("net.minecraft.nbt.CompoundTag#getList(java.lang.String,int)", "c");
put("net.minecraft.nbt.CompoundTag#putByteArray(java.lang.String,byte[])", "a");
put("net.minecraft.nbt.CompoundTag#getDouble(java.lang.String)", "k");
put("net.minecraft.nbt.CompoundTag#putDouble(java.lang.String,double)", "a");
put("net.minecraft.nbt.CompoundTag#getByteArray(java.lang.String)", "m");
put("net.minecraft.nbt.CompoundTag#putInt(java.lang.String,int)", "a");
put("net.minecraft.nbt.CompoundTag#getIntArray(java.lang.String)", "n");
put("net.minecraft.nbt.CompoundTag#remove(java.lang.String)", "r");
put("net.minecraft.nbt.CompoundTag#get(java.lang.String)", "c");
put("net.minecraft.nbt.CompoundTag#merge(net.minecraft.nbt.CompoundTag)", "a");
put("net.minecraft.nbt.CompoundTag#putBoolean(java.lang.String,boolean)", "a");
put("net.minecraft.nbt.CompoundTag#getTagType(java.lang.String)", "d");
put("net.minecraft.nbt.CompoundTag#putLong(java.lang.String,long)", "a");
put("net.minecraft.nbt.CompoundTag#putLongArray(java.lang.String,long[])", "a");
put("net.minecraft.nbt.CompoundTag#getLongArray(java.lang.String)", "o");
put("net.minecraft.nbt.CompoundTag#getString(java.lang.String)", "l");
put("net.minecraft.nbt.CompoundTag#getInt(java.lang.String)", "h");
put("net.minecraft.nbt.CompoundTag#putString(java.lang.String,java.lang.String)", "a");
put("net.minecraft.nbt.CompoundTag#put(java.lang.String,net.minecraft.nbt.Tag)", "a");
put("net.minecraft.nbt.CompoundTag#getByte(java.lang.String)", "f");
put("net.minecraft.nbt.CompoundTag#putIntArray(java.lang.String,int[])", "a");
put("net.minecraft.nbt.CompoundTag#getShort(java.lang.String)", "g");
put("net.minecraft.nbt.CompoundTag#putByte(java.lang.String,byte)", "a");
put("net.minecraft.nbt.CompoundTag#getAllKeys()", "d");
put("net.minecraft.nbt.CompoundTag#putUUID(java.lang.String,java.util.UUID)", "a");
put("net.minecraft.nbt.CompoundTag#putShort(java.lang.String,short)", "a");
put("net.minecraft.nbt.CompoundTag#getLong(java.lang.String)", "i");
put("net.minecraft.nbt.CompoundTag#putFloat(java.lang.String,float)", "a");
put("net.minecraft.nbt.CompoundTag#getBoolean(java.lang.String)", "q");
put("net.minecraft.nbt.CompoundTag#getUUID(java.lang.String)", "a");
put("net.minecraft.nbt.CompoundTag#getFloat(java.lang.String)", "j");
put("net.minecraft.nbt.ListTag#addTag(int,net.minecraft.nbt.Tag)", "b");
put("net.minecraft.nbt.ListTag#setTag(int,net.minecraft.nbt.Tag)", "a");
put("net.minecraft.nbt.ListTag#getString(int)", "j");
put("net.minecraft.nbt.ListTag#remove(int)", "remove");
put("net.minecraft.nbt.ListTag#getCompound(int)", "a");
put("net.minecraft.nbt.ListTag#size()", "size");
put("net.minecraft.nbt.ListTag#get(int)", "get");
put("net.minecraft.nbt.NbtIo#readCompressed(java.io.InputStream)", "a");
put("net.minecraft.nbt.NbtIo#writeCompressed(net.minecraft.nbt.CompoundTag,java.io.OutputStream)", "a");
put("net.minecraft.nbt.NbtUtils#readGameProfile(net.minecraft.nbt.CompoundTag)", "a");
put("net.minecraft.nbt.NbtUtils#writeGameProfile(net.minecraft.nbt.CompoundTag,com.mojang.authlib.GameProfile)",
"a");
put("net.minecraft.nbt.TagParser#parseTag(java.lang.String)", "a");
put("net.minecraft.world.entity.Entity#getEncodeId()", "bk");
put("net.minecraft.world.entity.Entity#load(net.minecraft.nbt.CompoundTag)", "g");
put("net.minecraft.world.entity.Entity#saveWithoutId(net.minecraft.nbt.CompoundTag)", "f");
put("net.minecraft.world.item.ItemStack#setTag(net.minecraft.nbt.CompoundTag)", "c");
put("net.minecraft.world.item.ItemStack#getTag()", "s");
put("net.minecraft.world.item.ItemStack#save(net.minecraft.nbt.CompoundTag)", "b");
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_");
}
};
@SuppressWarnings("serial")
private static Map<String, String> MC1_18R2 = new HashMap<String, String>() {
{
putAll(MC1_18R1);
put("net.minecraft.world.item.ItemStack#getTag()", "t");
}
};
@SuppressWarnings("serial")
private static Map<String, String> MC1_19R1 = new HashMap<String, String>() {
{
putAll(MC1_18R2);
put("net.minecraft.world.item.ItemStack#getTag()", "u");
}
};
@SuppressWarnings("serial")
private static Map<String, String> MC1_19R2 = new HashMap<String, String>() {
{
putAll(MC1_19R1);
put("net.minecraft.nbt.CompoundTag#getAllKeys()", "e");
}
};
@SuppressWarnings("serial")
private static Map<String, String> MC1_20R1 = new HashMap<String, String>() {
{
putAll(MC1_19R2);
put("net.minecraft.world.entity.Entity#getEncodeId()", "br");
put("net.minecraft.world.item.ItemStack#getTag()", "v");
}
};
public static Map<String, String> getMapping() {
switch (MinecraftVersion.getVersion()) {
case MC1_20_R1:
return MC1_20R1;
case MC1_19_R2:
return MC1_19R2;
case MC1_19_R1:
return MC1_19R1;
case MC1_18_R2:
return MC1_18R2;
case MC1_18_R1:
return MC1_18R1;
default:
return MC1_19R2;// throw new NbtApiException("This version of the NBTAPI is not compatible with
// this server version!");
}
}
}
@@ -1,57 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
import java.lang.reflect.Constructor;
import java.util.logging.Level;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import static de.tr7zw.changeme.nbtapi.utils.MinecraftVersion.getLogger;
/**
* This Enum wraps Constructors for NMS classes
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum ObjectCreator {
NMS_NBTTAGCOMPOUND(null, null, 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(),
ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),;
private Constructor<?> construct;
private Class<?> targetClass;
ObjectCreator(MinecraftVersion from, MinecraftVersion to, Class<?> clazz, Class<?>... args) {
if (clazz == null)
return;
if (from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId())
return;
if (to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId())
return;
try {
this.targetClass = clazz;
construct = clazz.getDeclaredConstructor(args);
construct.setAccessible(true);
} catch (Exception ex) {
getLogger().log(Level.SEVERE, "Unable to find the constructor for the class '" + clazz.getName() + "'", ex);
}
}
/**
* Creates an Object instance with given args
*
* @param args
* @return Object created
*/
public Object getInstance(Object... args) {
try {
return construct.newInstance(args);
} catch (Exception ex) {
throw new NbtApiException("Exception while creating a new instance of '" + targetClass + "'", ex);
}
}
}
@@ -1,30 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
/**
* Package enum
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum PackageWrapper {
NMS(new String(new byte[] { 'n', 'e', 't', '.', 'm', 'i', 'n', 'e', 'c', 'r', 'a', 'f', 't', '.', 's', 'e', 'r',
'v', 'e', 'r' })),
CRAFTBUKKIT(new String(new byte[] { 'o', 'r', 'g', '.', 'b', 'u', 'k', 'k', 'i', 't', '.', 'c', 'r', 'a', 'f', 't',
'b', 'u', 'k', 'k', 'i', 't' })),
NONE("");
private final String uri;
private PackageWrapper(String uri) {
this.uri = uri;
}
/**
* @return The Uri for that package
*/
public String getUri() {
return uri;
}
}
@@ -1,421 +0,0 @@
package de.tr7zw.changeme.nbtapi.utils.nmsmappings;
import java.io.InputStream;
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;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
/**
* This class caches method reflections, keeps track of method name changes
* between versions and allows early checking for problems
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum ReflectionMethod {
COMPOUND_SET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, float.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setFloat"),
new Since(MinecraftVersion.MC1_18_R1, "putFloat(java.lang.String,float)")),
COMPOUND_SET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, String.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setString"),
new Since(MinecraftVersion.MC1_18_R1, "putString(java.lang.String,java.lang.String)")),
COMPOUND_SET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setInt"),
new Since(MinecraftVersion.MC1_18_R1, "putInt(java.lang.String,int)")),
COMPOUND_SET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, byte[].class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByteArray"),
new Since(MinecraftVersion.MC1_18_R1, "putByteArray(java.lang.String,byte[])")),
COMPOUND_SET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int[].class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setIntArray"),
new Since(MinecraftVersion.MC1_18_R1, "putIntArray(java.lang.String,int[])")),
COMPOUND_SET_LONGARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, long[].class },
MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a"),
new Since(MinecraftVersion.MC1_18_R1, "putLongArray(java.lang.String,long[])")),
COMPOUND_SET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, long.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setLong"),
new Since(MinecraftVersion.MC1_18_R1, "putLong(java.lang.String,long)")),
COMPOUND_SET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, short.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setShort"),
new Since(MinecraftVersion.MC1_18_R1, "putShort(java.lang.String,short)")),
COMPOUND_SET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, byte.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByte"),
new Since(MinecraftVersion.MC1_18_R1, "putByte(java.lang.String,byte)")),
COMPOUND_SET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, double.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setDouble"),
new Since(MinecraftVersion.MC1_18_R1, "putDouble(java.lang.String,double)")),
COMPOUND_SET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, boolean.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean"),
new Since(MinecraftVersion.MC1_18_R1, "putBoolean(java.lang.String,boolean)")),
COMPOUND_SET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, UUID.class },
MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a"),
new Since(MinecraftVersion.MC1_18_R1, "putUUID(java.lang.String,java.util.UUID)")),
COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"),
new Since(MinecraftVersion.MC1_18_R1, "merge(net.minecraft.nbt.CompoundTag)")),
COMPOUND_SET(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, ClassWrapper.NMS_NBTBASE.getClazz() },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "set"),
new Since(MinecraftVersion.MC1_18_R1, "put(java.lang.String,net.minecraft.nbt.Tag)")),
COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "get"),
new Since(MinecraftVersion.MC1_18_R1, "get(java.lang.String)")),
COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class, int.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList"),
new Since(MinecraftVersion.MC1_18_R1, "getList(java.lang.String,int)")),
// Only needed for 1.7.10 getType
COMPOUND_OWN_TYPE(ClassWrapper.NMS_NBTBASE, new Class[] {}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getTypeId")),
COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getFloat"),
new Since(MinecraftVersion.MC1_18_R1, "getFloat(java.lang.String)")),
COMPOUND_GET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getString"),
new Since(MinecraftVersion.MC1_18_R1, "getString(java.lang.String)")),
COMPOUND_GET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getInt"),
new Since(MinecraftVersion.MC1_18_R1, "getInt(java.lang.String)")),
COMPOUND_GET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getByteArray"),
new Since(MinecraftVersion.MC1_18_R1, "getByteArray(java.lang.String)")),
COMPOUND_GET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getIntArray"),
new Since(MinecraftVersion.MC1_18_R1, "getIntArray(java.lang.String)")),
COMPOUND_GET_LONGARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_16_R1,
new Since(MinecraftVersion.MC1_16_R1, "getLongArray"),
new Since(MinecraftVersion.MC1_18_R1, "getLongArray(java.lang.String)")),
COMPOUND_GET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getLong"),
new Since(MinecraftVersion.MC1_18_R1, "getLong(java.lang.String)")),
COMPOUND_GET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getShort"),
new Since(MinecraftVersion.MC1_18_R1, "getShort(java.lang.String)")),
COMPOUND_GET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getByte"),
new Since(MinecraftVersion.MC1_18_R1, "getByte(java.lang.String)")),
COMPOUND_GET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getDouble"),
new Since(MinecraftVersion.MC1_18_R1, "getDouble(java.lang.String)")),
COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getBoolean"),
new Since(MinecraftVersion.MC1_18_R1, "getBoolean(java.lang.String)")),
COMPOUND_GET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_16_R1,
new Since(MinecraftVersion.MC1_16_R1, "a"),
new Since(MinecraftVersion.MC1_18_R1, "getUUID(java.lang.String)")),
COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getCompound"),
new Since(MinecraftVersion.MC1_18_R1, "getCompound(java.lang.String)")),
NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK, new Class[] {}, MinecraftVersion.MC1_7_R4,
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"),
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")),
COMPOUND_REMOVE_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "remove"),
new Since(MinecraftVersion.MC1_18_R1, "remove(java.lang.String)")),
COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "hasKey"),
new Since(MinecraftVersion.MC1_18_R1, "contains(java.lang.String)")),
COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] { String.class }, MinecraftVersion.MC1_8_R3,
new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"),
new Since(MinecraftVersion.MC1_15_R1, "e"), new Since(MinecraftVersion.MC1_16_R1, "d"),
new Since(MinecraftVersion.MC1_18_R1, "getTagType(java.lang.String)")),
COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] {}, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys"),
new Since(MinecraftVersion.MC1_18_R1, "getAllKeys()")),
// FIXME ?!?
LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND, new Class[] {}, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys"),
new Since(MinecraftVersion.MC1_18_R1, "getAllKeys()")),
LIST_REMOVE_KEY(ClassWrapper.NMS_NBTTAGLIST, new Class[] { int.class }, MinecraftVersion.MC1_8_R3,
new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_9_R1, "remove"),
new Since(MinecraftVersion.MC1_18_R1, "remove(int)")),
LIST_SIZE(ClassWrapper.NMS_NBTTAGLIST, new Class[] {}, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "size"), new Since(MinecraftVersion.MC1_18_R1, "size()")),
LIST_SET(ClassWrapper.NMS_NBTTAGLIST, new Class[] { int.class, ClassWrapper.NMS_NBTBASE.getClazz() },
MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"),
new Since(MinecraftVersion.MC1_13_R1, "set"),
new Since(MinecraftVersion.MC1_18_R1, "setTag(int,net.minecraft.nbt.Tag)")),
LEGACY_LIST_ADD(ClassWrapper.NMS_NBTTAGLIST, new Class[] { ClassWrapper.NMS_NBTBASE.getClazz() },
MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_7_R4, "add")),
LIST_ADD(ClassWrapper.NMS_NBTTAGLIST, new Class[] { int.class, ClassWrapper.NMS_NBTBASE.getClazz() },
MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "add"),
new Since(MinecraftVersion.MC1_18_R1, "addTag(int,net.minecraft.nbt.Tag)")),
LIST_GET_STRING(ClassWrapper.NMS_NBTTAGLIST, new Class[] { int.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getString"), new Since(MinecraftVersion.MC1_18_R1, "getString(int)")),
LIST_GET_COMPOUND(ClassWrapper.NMS_NBTTAGLIST, new Class[] { int.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "get"), new Since(MinecraftVersion.MC1_18_R1, "getCompound(int)")),
LIST_GET(ClassWrapper.NMS_NBTTAGLIST, new Class[] { int.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "get"), new Since(MinecraftVersion.MC1_8_R3, "g"),
new Since(MinecraftVersion.MC1_9_R1, "h"), new Since(MinecraftVersion.MC1_12_R1, "i"),
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"),
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")),
ITEMSTACK_BUKKITMIRROR(ClassWrapper.CRAFT_ITEMSTACK, new Class[] { ClassWrapper.NMS_ITEMSTACK.getClazz() },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asCraftMirror")),
CRAFT_WORLD_GET_HANDLE(ClassWrapper.CRAFT_WORLD, new Class[] {}, MinecraftVersion.MC1_7_R4,
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")),
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"),
new Since(MinecraftVersion.MC1_14_R1, "removeTileEntity")),
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")),
TILEENTITY_LOAD_LEGACY1121(ClassWrapper.NMS_TILEENTITY,
new Class[] { ClassWrapper.NMS_WORLD.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_10_R1, MinecraftVersion.MC1_12_R1, new Since(MinecraftVersion.MC1_10_R1, "a"),
new Since(MinecraftVersion.MC1_12_R1, "create")),
TILEENTITY_LOAD_LEGACY1151(ClassWrapper.NMS_TILEENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_13_R1, MinecraftVersion.MC1_15_R1, new Since(MinecraftVersion.MC1_12_R1, "create")),
TILEENTITY_LOAD(ClassWrapper.NMS_TILEENTITY,
new Class[] { ClassWrapper.NMS_IBLOCKDATA.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_16_R1, MinecraftVersion.MC1_16_R3, new Since(MinecraftVersion.MC1_16_R1, "create")),
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,
new Since(MinecraftVersion.MC1_18_R1, "saveWithId()")),
TILEENTITY_SET_NBT_LEGACY1151(ClassWrapper.NMS_TILEENTITY,
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() }, MinecraftVersion.MC1_7_R4,
MinecraftVersion.MC1_15_R1, new Since(MinecraftVersion.MC1_7_R4, "a"),
new Since(MinecraftVersion.MC1_12_R1, "load")),
TILEENTITY_SET_NBT_LEGACY1161(ClassWrapper.NMS_TILEENTITY,
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"),
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"),
new Since(MinecraftVersion.MC1_18_R1, "getBlockState()")),
CRAFT_ENTITY_GET_HANDLE(ClassWrapper.CRAFT_ENTITY, new Class[] {}, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
NMS_ENTITY_SET_NBT(ClassWrapper.NMS_ENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "f"),
new Since(MinecraftVersion.MC1_16_R1, "load"),
new Since(MinecraftVersion.MC1_18_R1, "load(net.minecraft.nbt.CompoundTag)")),
NMS_ENTITY_GET_NBT(ClassWrapper.NMS_ENTITY, new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz() },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "e"),
new Since(MinecraftVersion.MC1_12_R1, "save"),
new Since(MinecraftVersion.MC1_18_R1, "saveWithoutId(net.minecraft.nbt.CompoundTag)")),
NMS_ENTITY_GETSAVEID(ClassWrapper.NMS_ENTITY, new Class[] {}, MinecraftVersion.MC1_14_R1,
new Since(MinecraftVersion.MC1_14_R1, "getSaveID"), new Since(MinecraftVersion.MC1_18_R1, "getEncodeId()")),
NBTFILE_READ(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS, new Class[] { InputStream.class },
MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a"),
new Since(MinecraftVersion.MC1_18_R1, "readCompressed(java.io.InputStream)")),
NBTFILE_WRITE(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS,
new Class[] { ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), OutputStream.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "a"),
new Since(MinecraftVersion.MC1_18_R1,
"writeCompressed(net.minecraft.nbt.CompoundTag,java.io.OutputStream)")),
PARSE_NBT(ClassWrapper.NMS_MOJANGSONPARSER, new Class[] { String.class }, MinecraftVersion.MC1_7_R4,
new Since(MinecraftVersion.MC1_7_R4, "parse"),
new Since(MinecraftVersion.MC1_18_R1, "parseTag(java.lang.String)")),
REGISTRY_KEYSET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] {}, MinecraftVersion.MC1_11_R1,
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")),
REGISTRY_GET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] { Object.class }, MinecraftVersion.MC1_11_R1,
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")),
// FIXME: No Spigot mapping!
REGISTRY_SET(ClassWrapper.NMS_REGISTRYSIMPLE, new Class[] { Object.class, Object.class },
MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")),
// FIXME: No Spigot mapping!
REGISTRY_GET_INVERSE(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] { Object.class }, MinecraftVersion.MC1_11_R1,
MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")),
REGISTRYMATERIALS_KEYSET(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] {}, MinecraftVersion.MC1_13_R1,
MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_13_R1, "keySet")),
REGISTRYMATERIALS_GET(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] { ClassWrapper.NMS_MINECRAFTKEY.getClazz() },
MinecraftVersion.MC1_13_R1, MinecraftVersion.MC1_17_R1, new Since(MinecraftVersion.MC1_13_R1, "get")),
REGISTRYMATERIALS_GETKEY(ClassWrapper.NMS_REGISTRYMATERIALS, new Class[] { Object.class },
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 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"),
new Since(MinecraftVersion.MC1_18_R1,
"writeGameProfile(net.minecraft.nbt.CompoundTag,com.mojang.authlib.GameProfile)")),
CRAFT_PERSISTENT_DATA_CONTAINER_TO_TAG(ClassWrapper.CRAFT_PERSISTENTDATACONTAINER, new Class[] {},
MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "toTagCompound")),
CRAFT_PERSISTENT_DATA_CONTAINER_GET_MAP(ClassWrapper.CRAFT_PERSISTENTDATACONTAINER, new Class[] {},
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")),;
private MinecraftVersion removedAfter;
private Since targetVersion;
private Method method;
private boolean loaded = false;
private boolean compatible = false;
private String methodName = null;
private ClassWrapper parentClassWrapper;
ReflectionMethod(ClassWrapper targetClass, Class<?>[] args, MinecraftVersion addedSince,
MinecraftVersion removedAfter, Since... methodnames) {
this.removedAfter = removedAfter;
this.parentClassWrapper = targetClass;
// Special Case for Modded 1.7.10
boolean specialCase = (MinecraftVersion.isForgePresent() && this.name().equals("COMPOUND_MERGE")
&& MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4); // COMPOUND_MERGE is only present on
// Crucible, not on vanilla 1.7.10
if (!specialCase && (!MinecraftVersion.isAtLeastVersion(addedSince)
|| (this.removedAfter != null && MinecraftVersion.isNewerThan(removedAfter))))
return;
compatible = true;
MinecraftVersion server = MinecraftVersion.getVersion();
Since target = methodnames[0];
for (Since s : methodnames) {
if (s.version.getVersionId() <= server.getVersionId()
&& target.version.getVersionId() < s.version.getVersionId())
target = s;
}
targetVersion = target;
String targetMethodName = targetVersion.name;
try {
if (MinecraftVersion.isForgePresent() && MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) {
targetMethodName = Forge1710Mappings.getMethodMapping().getOrDefault(this.name(), targetMethodName);
} else if (targetVersion.version.isMojangMapping()) {
try {
// check for mojang mapped method
String name = targetVersion.name.split("\\(")[0];
method = targetClass.getClazz().getMethod(name, args);
method.setAccessible(true);
loaded = true;
methodName = name;
return;
} catch (NoSuchMethodException ignore) {
// not mojang mapped
}
targetMethodName = MojangToMapping.getMapping().getOrDefault(
targetClass.getMojangName() + "#" + targetVersion.name, "Unmapped" + targetVersion.name);
}
method = targetClass.getClazz().getDeclaredMethod(targetMethodName, args);
method.setAccessible(true);
loaded = true;
methodName = targetVersion.name;
} catch (NullPointerException | NoSuchMethodException | SecurityException ex) {
try {
if (targetVersion.version.isMojangMapping())
targetMethodName = MojangToMapping.getMapping().getOrDefault(
targetClass.getMojangName() + "#" + targetVersion.name, "Unmapped" + targetVersion.name);
method = targetClass.getClazz().getMethod(targetMethodName, args);
method.setAccessible(true);
loaded = true;
methodName = targetVersion.name;
} catch (NullPointerException | NoSuchMethodException | SecurityException ex2) {
MinecraftVersion.getLogger()
.warning("[NBTAPI] Unable to find the method '" + targetMethodName + "' in '"
+ (targetClass.getClazz() == null ? targetClass.getMojangName()
: targetClass.getClazz().getSimpleName())
+ "' Args: " + Arrays.toString(args) + " Enum: " + this); // NOSONAR This gets loaded
// before the logger is loaded
}
}
}
ReflectionMethod(ClassWrapper targetClass, Class<?>[] args, MinecraftVersion addedSince, Since... methodnames) {
this(targetClass, args, addedSince, null, methodnames);
}
/**
* Runs the method on a given target object using the given args.
*
* @param target
* @param args
* @return Value returned by the method
*/
public Object run(Object target, Object... args) {
if (method == null)
throw new NbtApiException("Method not loaded! '" + this + "'");
try {
return method.invoke(target, args);
} catch (Exception ex) {
throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded
+ ", Enum: " + this + ", Passed Class: " + (target == null ? "null" : target.getClass()), ex);
}
}
/**
* @return The MethodName, used in this Minecraft Version
*/
public String getMethodName() {
return methodName;
}
/**
* @return Has this method been linked
*/
public boolean isLoaded() {
return loaded;
}
/**
* @return Is this method available in this Minecraft Version
*/
public boolean isCompatible() {
return compatible;
}
public Since getSelectedVersionInfo() {
return targetVersion;
}
/**
* @return Get Wrapper of the parent class
*/
public ClassWrapper getParentClassWrapper() {
return parentClassWrapper;
}
public static class Since {
public final MinecraftVersion version;
public final String name;
public Since(MinecraftVersion version, String name) {
this.version = version;
this.name = name;
}
}
}
@@ -1,42 +0,0 @@
package de.tr7zw.changeme.nbtapi.wrapper;
import java.util.function.UnaryOperator;
public enum Casing {
camelCase(s -> {
if (s.length() < 2) {
return s.toLowerCase();
}
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}), snake_case(s -> {
StringBuilder result = new StringBuilder();
// Convert the first letter to lowercase
result.append(Character.toLowerCase(s.charAt(0)));
// Iterate through the rest of the string
for (int i = 1; i < s.length(); i++) {
char currentChar = s.charAt(i);
// Convert uppercase letters to lowercase and add underscore
if (Character.isUpperCase(currentChar)) {
result.append('_').append(Character.toLowerCase(currentChar));
} else {
result.append(currentChar);
}
}
return result.toString();
}), PascalCase(s -> {
if (s.length() < 2) {
return s.toUpperCase();
}
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}), lowercase(String::toLowerCase), UPPERCASE(String::toUpperCase);
private UnaryOperator<String> convert;
Casing(UnaryOperator<String> function) {
this.convert = function;
}
public String convertString(String str) {
return convert.apply(str);
}
}
@@ -1,55 +0,0 @@
package de.tr7zw.changeme.nbtapi.wrapper;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import de.tr7zw.changeme.nbtapi.NbtApiException;
class DefaultMethodInvoker {
private static Method invokeDefaultMethod;
static {
try {
invokeDefaultMethod = InvocationHandler.class.getDeclaredMethod("invokeDefault",
new Class[] { Object.class, Method.class, Object[].class });
invokeDefaultMethod.setAccessible(true);
} catch (NoSuchMethodException | SecurityException e) {
// we are in java 8, use the fallback
}
}
/**
* Using reflections to access reflections, since some are still on java 8.
*
* @param target
* @param method
* @param args
* @return
*/
public static Object invokeDefault(Class<?> srcInt, Object target, Method method, Object[] args) {
if (invokeDefaultMethod != null) { // java 9+
try {
return invokeDefaultMethod.invoke(null, target, method, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new NbtApiException("Error while trying to invoke a default method for Java 9+. " + target + " "
+ method + " " + Arrays.toString(args), e);
}
} else {
try {
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class);
constructor.setAccessible(true);
return constructor.newInstance(srcInt).in(srcInt).unreflectSpecial(method, srcInt).bindTo(target)
.invokeWithArguments(args);
} catch (Throwable e) {
throw new NbtApiException("Error while trying to invoke a default method for Java 8. " + target + " "
+ method + " " + Arrays.toString(args), e);
}
}
}
}
@@ -1,35 +0,0 @@
package de.tr7zw.changeme.nbtapi.wrapper;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import de.tr7zw.changeme.nbtapi.iface.NBTHandler;
public interface NBTProxy {
final Map<Class<?>, NBTHandler<Object>> handlers = new HashMap<>();
public default void init() {
}
public default Casing getCasing() {
return Casing.PascalCase;
}
@SuppressWarnings("unchecked")
public default <T> NBTHandler<T> getHandler(Class<T> clazz) {
return (NBTHandler<T>) handlers.get(clazz);
}
public default Collection<NBTHandler<Object>> getHandlers() {
return handlers.values();
}
@SuppressWarnings("unchecked")
public default <T> void registerHandler(Class<T> clazz, NBTHandler<T> handler) {
handlers.put(clazz, (NBTHandler<Object>) handler);
}
}
@@ -1,19 +0,0 @@
package de.tr7zw.changeme.nbtapi.wrapper;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(METHOD)
public @interface NBTTarget {
public String value();
public Type type() default Type.AUTOMATIC;
public enum Type {
AUTOMATIC, GET, SET, HAS
}
}
@@ -1,199 +0,0 @@
package de.tr7zw.changeme.nbtapi.wrapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import de.tr7zw.changeme.nbtapi.NBTType;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.NBTHandler;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.changeme.nbtapi.wrapper.NBTTarget.Type;
public class ProxyBuilder<T extends NBTProxy> implements InvocationHandler {
private static final Map<Method, Function<Arguments, Object>> METHOD_CACHE = new ConcurrentHashMap<>();
private final Class<T> target;
private final ReadWriteNBT nbt;
private boolean readOnly;
public ProxyBuilder(ReadWriteNBT nbt, Class<T> target) {
if (!target.isInterface()) {
throw new NbtApiException("A proxy can only be built from an interface! Check the wiki for examples.");
}
this.target = target;
this.nbt = nbt;
}
public ProxyBuilder<T> readOnly() {
this.readOnly = true;
return this;
}
@SuppressWarnings("unchecked")
public T build() {
T inst = (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { target }, this);
inst.init();
return inst;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
METHOD_CACHE.computeIfAbsent(method, m -> ProxyBuilder.createFunction((NBTProxy) proxy, m));
return METHOD_CACHE.get(method).apply(new Arguments(target, (NBTProxy) proxy, readOnly, nbt, args));
}
private static class Arguments {
Class<?> target;
NBTProxy proxy;
ReadWriteNBT nbt;
Object[] args;
boolean readOnly;
public Arguments(Class<?> target, NBTProxy proxy, boolean readOnly, ReadWriteNBT nbt, Object[] args) {
this.target = target;
this.proxy = proxy;
this.nbt = nbt;
this.args = args;
this.readOnly = readOnly;
}
}
@SuppressWarnings("unchecked")
private static Function<Arguments, Object> createFunction(NBTProxy proxy, Method method) {
if ("toString".equals(method.getName()) && method.getParameterCount() == 0
&& method.getReturnType() == String.class) {
return (arguments) -> arguments.nbt.toString();
}
if (method.isDefault()) {
return (arguments) -> DefaultMethodInvoker.invokeDefault(arguments.target, arguments.proxy, method,
arguments.args);
}
Type action = getAction(method);
if (action == Type.SET) {
String fieldName = getNBTName(proxy.getCasing(), method);
return (arguments) -> {
if (arguments.readOnly) {
throw new NbtApiException("Tried calling a set method on a read only object.");
}
return setNBT(arguments.nbt, arguments.proxy, fieldName, arguments.args[0]);
};
}
if (action == Type.GET) {
Class<?> retType = method.getReturnType();
String fieldName = getNBTName(proxy.getCasing(), method);
// Allow stacking of proxies
if (retType.isInterface() && NBTProxy.class.isAssignableFrom(retType)) {
return (arguments) -> {
if (arguments.nbt.hasTag(fieldName) && arguments.nbt.getType(fieldName) != NBTType.NBTTagCompound) {
throw new NbtApiException("Tried getting a '" + retType + "' proxy from the field '" + fieldName
+ "', but it's not a TagCompound!");
}
return new ProxyBuilder<NBTProxy>(arguments.nbt.getOrCreateCompound(fieldName),
(Class<NBTProxy>) retType).build();
};
}
NBTHandler<Object> handler = (NBTHandler<Object>) proxy.getHandler(retType);
if (handler != null) {
return (arguments) -> handler.get(arguments.nbt, fieldName);
}
return (arguments) -> arguments.nbt.getOrNull(fieldName, retType);
}
if(action == Type.HAS) {
String fieldName = getNBTName(proxy.getCasing(), method);
return (arguments) -> arguments.nbt.hasTag(fieldName);
}
throw new IllegalArgumentException(
"The method '" + method.getName() + "' in '" + method.getDeclaringClass().getName()
+ "' can not be handled by the NBT-API. Please check the Wiki for examples!");
}
private static Type getAction(Method method) {
NBTTarget target = method.getAnnotation(NBTTarget.class);
if (target != null) {
if (target.type() == Type.HAS && method.getParameterCount() == 0 && method.getReturnType() == boolean.class) {
return Type.HAS;
}
if (target.type() == Type.GET && method.getParameterCount() == 0) {
return Type.GET;
}
if (target.type() == Type.SET && method.getParameterCount() == 1) {
return Type.SET;
}
}
if (method.getName().startsWith("set") && method.getParameterCount() == 1) {
return Type.SET;
}
if (method.getName().startsWith("get") && method.getParameterCount() == 0) {
return Type.GET;
}
if (method.getName().startsWith("has") && method.getParameterCount() == 0 && method.getReturnType() == boolean.class) {
return Type.HAS;
}
return null;
}
private static String getNBTName(Casing casing, Method method) {
NBTTarget target = method.getAnnotation(NBTTarget.class);
if (target != null) {
return target.value();
}
return casing.convertString(method.getName().substring(3));
}
private static Object setNBT(ReadWriteNBT nbt, NBTProxy proxy, String key, Object value) {
// welcome to the "I wish we all could use java 17" method. Thanks, legacy mc
// versions
if (value == null) {
nbt.removeKey(key);
} else if (value instanceof Boolean) {
nbt.setBoolean(key, (Boolean) value);
} else if (value instanceof Byte) {
nbt.setByte(key, (Byte) value);
} else if (value instanceof Short) {
nbt.setShort(key, (Short) value);
} else if (value instanceof Integer) {
nbt.setInteger(key, (Integer) value);
} else if (value instanceof Long) {
nbt.setLong(key, (Long) value);
} else if (value instanceof Float) {
nbt.setFloat(key, (Float) value);
} else if (value instanceof Double) {
nbt.setDouble(key, (Double) value);
} else if (value instanceof byte[]) {
nbt.setByteArray(key, (byte[]) value);
} else if (value instanceof int[]) {
nbt.setIntArray(key, (int[]) value);
} else if (value instanceof long[]) {
nbt.setLongArray(key, (long[]) value);
} else if (value instanceof String) {
nbt.setString(key, (String) value);
} else if (value instanceof UUID) {
nbt.setUUID(key, (UUID) value);
} else if (value.getClass().isEnum()) {
nbt.setEnum(key, (Enum<?>) value);
} else {
@SuppressWarnings("unchecked")
NBTHandler<Object> handler = (NBTHandler<Object>) proxy.getHandler(value.getClass());
if (handler != null) {
handler.set(nbt, key, value);
} else {
for (NBTHandler<Object> nbth : proxy.getHandlers()) {
if (nbth.fuzzyMatch(value)) {
nbth.set(nbt, key, value);
return null;
}
}
throw new IllegalArgumentException("Tried setting an object of type '" + value.getClass().getName()
+ "'. This is not a supported NBT value. Please check the Wiki for examples!");
}
}
return null;
}
}
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 - 2021, tr7zw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-133
View File
@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-parent</artifactId>
<version>2.12.0-SNAPSHOT</version>
</parent>
<artifactId>item-nbt-api-plugin</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.12.0-SNAPSHOT</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>
</dependencies>
<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>de.tr7zw.changeme.nbtapi</pattern>
<shadedPattern>de.tr7zw.nbtapi</shadedPattern>
</relocation>
<relocation>
<pattern>javassist</pattern>
<shadedPattern>de.tr7zw.nbtinjector.javassist</shadedPattern>
</relocation>
<relocation>
<pattern>de.tr7zw.annotations</pattern>
<shadedPattern>de.tr7zw.nbtapi.utils.annotations</shadedPattern>
</relocation>
</relocations>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>LICENSE</resource>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>shade</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
<!-- Start and Stop a SpigotMC server automatically before and after the integration-test phase. -->
<plugin>
<groupId>de.tr7zw.spigotmc.maven</groupId>
<artifactId>tr-spigotmc-maven-plugin</artifactId>
<version>0.0.3-SNAPSHOT</version>
<configuration>
<!-- 1.8.8-R0.1-SNAPSHOT-latest, 1.9.2-R0.1-SNAPSHOT-latest, 1.9.4-R0.1-SNAPSHOT-latest, 1.10.2-R0.1-SNAPSHOT-latest,1.11.2,1.12.2,1.13.2,1.14.4,1.15.1,1.16.1,1.16.2 -->
<versions>
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.8.8-R0.1-SNAPSHOT/spigot-1.8.8-R0.1-20190527.160303-7.jar,
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.9.4-R0.1-SNAPSHOT/spigot-1.9.4-R0.1-20190527.160755-2.jar,
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.10.2-R0.1-SNAPSHOT/spigot-1.10.2-R0.1-20190527.154910-2.jar,
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.11.2-R0.1-SNAPSHOT/spigot-1.11.2-R0.1-20191216.091129-1.jar,
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.12.2-R0.1-SNAPSHOT/spigot-1.12.2-R0.1-20190527.155359-34.jar,
<!--https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.13.2-R0.1-SNAPSHOT/spigot-1.13.2-R0.1-20191113.201242-53.jar,-->
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.14.4-R0.1-SNAPSHOT/spigot-1.14.4-R0.1-20191224.232152-15.jar,
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.15.2-R0.1-SNAPSHOT/spigot-1.15.2-R0.1-20200625.172449-18.jar,
https://repo.codemc.io/repository/nms/org/spigotmc/spigot/1.16.5-R0.1-SNAPSHOT/spigot-1.16.5-R0.1-20210611.090701-17.jar
</versions>
<works>Success! This version of NBT-API</works>
<error>WARNING! This version of NBT-API</error>
<filename>item-nbt-api-plugin-${project.version}.jar</filename>
<foldername>item-nbt-plugin</foldername>
</configuration>
<executions>
<execution>
<id>start-server</id>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>nbtapi-javadoc-plugin</artifactId>
<version>3.4.2-SNAPSHOT</version>
<executions>
<execution>
<id>bundle-javadoc</id>
<goals>
<goal>aggregate-jar</goal>
</goals>
<phase>package</phase>
<configuration>
<detectOfflineLinks>false</detectOfflineLinks>
<includeDependencySources>true</includeDependencySources>
<sourcepath>src/main/java;${project.parent.basedir}/item-nbt-api/src/main/java;${project.build.directory}/javadoc-relocate;${defines.dir}</sourcepath>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -1,263 +0,0 @@
package de.tr7zw.nbtapi.plugin;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.changeme.nbtapi.utils.VersionChecker;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper;
import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod;
import de.tr7zw.nbtapi.plugin.tests.GameprofileTest;
import de.tr7zw.nbtapi.plugin.tests.NBTFileTest;
import de.tr7zw.nbtapi.plugin.tests.blocks.BlockNBTTest;
import de.tr7zw.nbtapi.plugin.tests.chunks.ChunkNBTPersistentTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.EnumTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.EqualsTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.ForEachTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.GetterSetterTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.InterfaceTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.IteratorTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.ListTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.LongArrayTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.MergeTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.ModernSubCompoundsTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.RemovingKeys;
import de.tr7zw.nbtapi.plugin.tests.compounds.ResolveTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.StreamTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.SubCompoundsTest;
import de.tr7zw.nbtapi.plugin.tests.compounds.TypeTest;
import de.tr7zw.nbtapi.plugin.tests.data.WorldDataTest;
import de.tr7zw.nbtapi.plugin.tests.entities.EntityCustomNbtPersistentTest;
import de.tr7zw.nbtapi.plugin.tests.entities.EntityTest;
import de.tr7zw.nbtapi.plugin.tests.injector.EntityCustomNbtInjectorTest;
import de.tr7zw.nbtapi.plugin.tests.injector.MergeTileSubCompoundTest;
import de.tr7zw.nbtapi.plugin.tests.injector.SpawnEntityCustomNbtInjectorTest;
import de.tr7zw.nbtapi.plugin.tests.injector.TilesCustomNBTInjectorTest;
import de.tr7zw.nbtapi.plugin.tests.items.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.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.MetaTest;
import de.tr7zw.nbtapi.plugin.tests.items.NBTModifyItemTest;
import de.tr7zw.nbtapi.plugin.tests.items.SmuggleTest;
public class NBTAPI extends JavaPlugin {
private boolean compatible = true;
private List<de.tr7zw.nbtapi.plugin.tests.Test> apiTests = new ArrayList<>();
private static NBTAPI instance;
public static NBTAPI getInstance() {
return instance;
}
@Override
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);
saveConfig();
if (!getConfig().getBoolean("bStats.enabled")) {
getLogger().info("bStats disabled");
MinecraftVersion.disableBStats();
}
if (!getConfig().getBoolean("updateCheck.enabled")) {
getLogger().info("Update check disabled");
MinecraftVersion.disableUpdateCheck();
} else {
MinecraftVersion.enableUpdateCheck();
}
// Disabled by default since 2.1. Enable it yourself by calling
// NBTInjector.inject(); during onLoad/config
if (getConfig().getBoolean("nbtInjector.enabled")) {
getLogger().info("Injecting custom NBT");
try {
NBTInjector.inject();
getLogger().info("Injected!");
} catch (Throwable ex) { // NOSONAR
getLogger().log(Level.SEVERE, "Error while Injecting custom Tile/Entity classes!", ex);
compatible = false;
}
}
// NBTCompounds
apiTests.add(new GetterSetterTest());
apiTests.add(new TypeTest());
apiTests.add(new RemovingKeys());
apiTests.add(new EnumTest());
apiTests.add(new InterfaceTest());
apiTests.add(new ResolveTest());
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) // 1.7.10 list support is not complete at all
apiTests.add(new ListTest());
apiTests.add(new SubCompoundsTest());
apiTests.add(new ModernSubCompoundsTest());
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) // 1.7.10 not a thing
apiTests.add(new MergeTest());
apiTests.add(new ForEachTest());
apiTests.add(new StreamTest());
apiTests.add(new EqualsTest());
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) // 1.7.10 list support is not complete at all
apiTests.add(new IteratorTest());
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R1))
apiTests.add(new LongArrayTest());
// Items
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3)) { // 1.7.10 not a thing
apiTests.add(new ItemConversionTest());
apiTests.add(new ItemStackConversionTest());
}
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());
apiTests.add(new DirectApplyTest());
apiTests.add(new DirectApplyMetaTest());
apiTests.add(new NBTModifyItemTest());
}
// Proxies
apiTests.add(new SimpleProxyTest());
// Entity
apiTests.add(new EntityTest());
apiTests.add(new EntityCustomNbtPersistentTest());
// Tiles
apiTests.add(new TileTest());
apiTests.add(new TilesCustomNBTPersistentTest());
// Chunks
apiTests.add(new ChunkNBTPersistentTest());
// Blocks
apiTests.add(new BlockNBTTest());
// 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());
}
@Override
public void onEnable() {
instance = this; // NOSONAR
// new MetricsLite(this); The metrics moved into the API
if (getConfig().getBoolean("silentquickstart")) {
// we are silent, won't check anything or pre-init
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();
boolean classUnlinked = false;
for (ClassWrapper c : ClassWrapper.values()) {
if (c.isEnabled() && c.getClazz() == null) {
if (!classUnlinked)
getLogger().info("Classes:");
getLogger().warning(c.name() + " did not find it's class!");
compatible = false;
classUnlinked = true;
}
}
if (!classUnlinked)
getLogger().info("All Classes were able to link!");
boolean methodUnlinked = false;
for (ReflectionMethod method : ReflectionMethod.values()) {
if (method.isCompatible() && !method.isLoaded()) {
if (!methodUnlinked)
getLogger().info("Methods:");
getLogger().warning(method.name() + " did not find the method!");
compatible = false;
methodUnlinked = true;
}
}
if (!methodUnlinked)
getLogger().info("All Methods were able to link!");
getLogger().info("Running NBT reflection test...");
Map<de.tr7zw.nbtapi.plugin.tests.Test, Exception> results = new HashMap<>();
for (de.tr7zw.nbtapi.plugin.tests.Test test : apiTests) {
try {
test.test();
results.put(test, null);
} catch (Exception ex) {
results.put(test, ex);
getLogger().log(Level.WARNING, "Error during '" + test.getClass().getSimpleName() + "' test!", ex);
} catch (NoSuchFieldError th) { // NOSONAR
getLogger().log(Level.SEVERE, "Servere error during '" + test.getClass().getSimpleName() + "' test!");
getLogger().warning(
"WARNING! This version of Item-NBT-API seems to be broken with your Spigot version! Canceled the other tests!");
throw th;
}
}
for (Entry<de.tr7zw.nbtapi.plugin.tests.Test, Exception> entry : results.entrySet()) {
if (entry.getValue() != null) {
compatible = false;
getLogger().info(entry.getKey().getClass().getSimpleName() + ": " + entry.getValue().getMessage());
}
}
String checkMessage = "Plugins that don't check properly may throw Exeptions, crash or have unexpected behaviors!";
if (compatible) {
NbtApiException.confirmedBroken = false;
getLogger().info("Success! This version of NBT-API is compatible with your server.");
} else {
NbtApiException.confirmedBroken = true;
getLogger().warning(
"WARNING! This version of NBT-API seems to be broken with your Spigot version! " + checkMessage);
if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) {
getLogger().warning(
"1.7.10 is only partally supported! Some thing will not work/are not yet avaliable in 1.7.10!");
}
}
}
/**
* @return True if all selfchecks succeeded
*/
public boolean isCompatible() {
return compatible;
}
}
@@ -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!");
}
}
}
@@ -1,25 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests;
import java.util.UUID;
import com.mojang.authlib.GameProfile;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTGameProfile;
import de.tr7zw.changeme.nbtapi.NbtApiException;
public class GameprofileTest implements Test {
@Override
public void test() throws Exception {
UUID uuid = UUID.randomUUID();
GameProfile profile = new GameProfile(uuid, "random");
NBTCompound nbt = NBTGameProfile.toNBT(profile);
profile = null;
profile = NBTGameProfile.fromNBT(nbt);
if (profile == null || !profile.getId().equals(uuid)) {
throw new NbtApiException("Error when converting a GameProfile from/to NBT!");
}
}
}
@@ -1,63 +0,0 @@
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.NbtApiException;
import de.tr7zw.nbtapi.plugin.NBTAPI;
public class NBTFileTest implements Test {
@Override
public void test() throws Exception {
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");
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");
block.setString("type", "wool");
file.save();
if (!"wool".equals(block.getString("type"))) {
throw new NbtApiException("SubCompounds did not work!");
}
NBTFile fileLoaded = new NBTFile(testFile);
if (!fileLoaded.getString("test").equals("test")) {
throw new NbtApiException("Wasn't able to load NBT File with the correct content!");
}
Files.deleteIfExists(fileLoaded.getFile().toPath());
// String
String str = fileLoaded.toString();
NBTContainer rebuild = new NBTContainer(str);
if (!str.equals(rebuild.toString())) {
throw new NbtApiException("Wasn't able to parse NBT from a String!");
}
NBTCompound dummy = new NBTContainer();
dummy.setString("test1", "key1");
NBTFile.saveTo(testFile, dummy);
dummy = new NBTContainer();
dummy.setString("test2", "key2");
NBTFile.saveTo(testFile, dummy);
dummy = NBTFile.readFrom(testFile);
if (dummy.hasTag("test1") || !dummy.getString("test2").equals("key2")) {
throw new NbtApiException("Wasn't able to save NBT File with the correct content!");
}
Files.deleteIfExists(fileLoaded.getFile().toPath());
}
}
@@ -1,7 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests;
public interface Test {
public void test() throws Exception; // NOSONAR
}
@@ -1,41 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.blocks;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
import de.tr7zw.changeme.nbtapi.NBTBlock;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class BlockNBTTest implements Test {
@Override
public void test() throws Exception {
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_16_R3.getVersionId())
return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
if (world.getLoadedChunks().length > 1) {
Chunk chunk = world.getLoadedChunks()[0];
Block block = chunk.getBlock(0, 254, 0);
NBTBlock comp = new NBTBlock(block);
comp.getData().removeKey("Too");
if (comp.getData().hasTag("Too")) {
throw new NbtApiException("Unable to remove key from Block!");
}
comp.getData().setString("Too", "Bar");
if (!new NBTBlock(block).getData().getString("Too").equals("Bar")) {
throw new NbtApiException("Custom Data did not save to a Block!");
}
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTBlocks!", ex);
}
}
}
}
@@ -1,41 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.chunks;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import de.tr7zw.changeme.nbtapi.NBTChunk;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class ChunkNBTPersistentTest implements Test {
@Override
public void test() throws Exception {
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_16_R3.getVersionId())
return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
if (world.getLoadedChunks().length > 1) {
Chunk chunk = world.getLoadedChunks()[0];
NBTChunk comp = new NBTChunk(chunk);
NBTCompound persistentData = comp.getPersistentDataContainer();
persistentData.removeKey("Foo");
if (persistentData.hasTag("Foo")) {
throw new NbtApiException("Unable to remove key from Chunk!");
}
persistentData.setString("Foo", "Bar");
if (!new NBTChunk(chunk).getPersistentDataContainer().getString("Foo").equals("Bar")) {
throw new NbtApiException("Custom Data did not save to the Chunk!");
}
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTChunks!", ex);
}
}
}
}
@@ -1,24 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NBTType;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class EnumTest implements Test {
@Override
public void test() throws Exception {
NBTCompound comp = new NBTContainer();
comp.setEnum("test", NBTType.NBTTagEnd);
NBTType type = comp.getEnum("test", NBTType.class);
NBTType typeNonNull = comp.getOrNull("test", NBTType.class);
NBTType typeDefault = comp.getOrDefault("invalid", NBTType.NBTTagByte);
NBTType typeDefaultFound = comp.getOrDefault("test", NBTType.NBTTagByte);
if (type != NBTType.NBTTagEnd || typeNonNull != NBTType.NBTTagEnd || typeDefaultFound != NBTType.NBTTagEnd
|| typeDefault != NBTType.NBTTagByte)
throw new NbtApiException("One enum did not match what it should have been!");
}
}
@@ -1,53 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
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.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class EqualsTest implements Test {
@Override
public void test() throws Exception {
NBTContainer cont = new NBTContainer();
cont.setString("hello", "world");
cont.setInteger("theAnswer", 42);
cont.addCompound("sub").setString("me", "too");
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);
}
// empty test
if (!new NBTContainer().equals(new NBTContainer())) {
throw new NbtApiException("Two empty tags did not match!");
}
// not equal test
NBTContainer part1 = new NBTContainer();
part1.setString("a", "a");
part1.setString("b", "b");
NBTContainer part2 = new NBTContainer();
part2.setString("a", "a");
part2.setString("b", "a");
if (part1.equals(part2)) {
throw new NbtApiException("Missmatched nbt did match!");
}
}
}
@@ -1,50 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import java.util.ListIterator;
import de.tr7zw.changeme.nbtapi.NBTCompoundList;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.nbtapi.plugin.tests.Test;
/**
* Test requested by TAU on Discord
*
*/
public class ForEachTest implements Test {
@SuppressWarnings("unused")
@Override
public void test() throws Exception {
NBTContainer comp = new NBTContainer();
NBTCompoundList compList = comp.getCompoundList("testkey");
if (compList != null) {
compList.addCompound().setInteger("id", 1);
compList.addCompound().setInteger("id", 2);
compList.addCompound().setInteger("id", 3);
int count = 0;
for (ReadWriteNBT listComp : compList) {
count++;
}
if (count != compList.size())
throw new NbtApiException("For loop did not get all Entries!");
count = 0;
ListIterator<ReadWriteNBT> lit = compList.listIterator();
while (lit.hasNext()) {
lit.next();
count++;
}
if (count != compList.size())
throw new NbtApiException("ListIterator did not get all Entries!");
count = 0;
while (lit.hasPrevious()) {
lit.previous();
count++;
}
if (count != compList.size())
throw new NbtApiException("ListIterator previous did not get all Entries!");
}
}
}
@@ -1,64 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBT;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class GetterSetterTest implements Test {
private static final String STRING_TEST_KEY = "stringTest";
private static final String INT_TEST_KEY = "intTest";
private static final String DOUBLE_TEST_KEY = "doubleTest";
private static final String BOOLEAN_TEST_KEY = "booleanTest";
private static final String SHORT_TEST_KEY = "shortTest";
private static final String BYTE_TEST_KEY = "byteTest";
private static final String FLOAT_TEST_KEY = "floatTest";
private static final String LONG_TEST_KEY = "longTest";
private static final String INTARRAY_TEST_KEY = "intarrayTest";
private static final String BYTEARRAY_TEST_KEY = "bytearrayTest";
private static final String STRING_TEST_VALUE = "TestString";
private static final int INT_TEST_VALUE = 42;
private static final double DOUBLE_TEST_VALUE = 1.5d;
private static final boolean BOOLEAN_TEST_VALUE = true;
private static final short SHORT_TEST_VALUE = 64;
private static final byte BYTE_TEST_VALUE = 7;
private static final float FLOAT_TEST_VALUE = 13.37f;
private static final long LONG_TEST_VALUE = (long) Integer.MAX_VALUE + 42L;
private static final int[] INTARRAY_TEST_VALUE = new int[] { 1337, 42, 69 };
private static final byte[] BYTEARRAY_TEST_VALUE = new byte[] { 8, 7, 3, 2 };
@Override
public void test() throws Exception {
ReadWriteNBT comp = NBT.createNBTObject();
comp.setString(STRING_TEST_KEY, STRING_TEST_VALUE);
comp.setInteger(INT_TEST_KEY, INT_TEST_VALUE);
comp.setDouble(DOUBLE_TEST_KEY, DOUBLE_TEST_VALUE);
comp.setBoolean(BOOLEAN_TEST_KEY, BOOLEAN_TEST_VALUE);
comp.setByte(BYTE_TEST_KEY, BYTE_TEST_VALUE);
comp.setShort(SHORT_TEST_KEY, SHORT_TEST_VALUE);
comp.setLong(LONG_TEST_KEY, LONG_TEST_VALUE);
comp.setFloat(FLOAT_TEST_KEY, FLOAT_TEST_VALUE);
comp.setIntArray(INTARRAY_TEST_KEY, INTARRAY_TEST_VALUE);
comp.setByteArray(BYTEARRAY_TEST_KEY, BYTEARRAY_TEST_VALUE);
if (!comp.hasTag(STRING_TEST_KEY)) {
throw new NbtApiException("Wasn't able to check a key! The Item-NBT-API may not work!");
}
int[] intArray = comp.getIntArray(INTARRAY_TEST_KEY);
byte[] byteArray = comp.getByteArray(BYTEARRAY_TEST_KEY);
if (!(STRING_TEST_VALUE).equals(comp.getString(STRING_TEST_KEY))
|| comp.getInteger(INT_TEST_KEY) != INT_TEST_VALUE
|| comp.getDouble(DOUBLE_TEST_KEY) != DOUBLE_TEST_VALUE
|| comp.getByte(BYTE_TEST_KEY) != BYTE_TEST_VALUE || comp.getShort(SHORT_TEST_KEY) != SHORT_TEST_VALUE
|| comp.getFloat(FLOAT_TEST_KEY) != FLOAT_TEST_VALUE || comp.getLong(LONG_TEST_KEY) != LONG_TEST_VALUE
|| (intArray != null && intArray.length != (INTARRAY_TEST_VALUE).length)
|| (byteArray != null && byteArray.length != (BYTEARRAY_TEST_VALUE).length)
|| !comp.getBoolean(BOOLEAN_TEST_KEY).equals(BOOLEAN_TEST_VALUE)) {
throw new NbtApiException("One key does not equal the original value! The Item-NBT-API may not work!");
}
}
}
@@ -1,95 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
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 GsonTest implements Test {
@SuppressWarnings("deprecation")
@Override
public void test() throws Exception {
if (!MinecraftVersion.hasGsonSupport()) {
return;
}
try {
ItemStack item = new ItemStack(Material.STONE, 1);
NBTItem nbtItem = new NBTItem(item);
nbtItem.setObject(JSON_TEST_KEY, new SimpleJsonTestObject());
if (!nbtItem.hasTag(JSON_TEST_KEY)) {
throw new NbtApiException(
"Wasn't able to find JSON key! The Item-NBT-API may not work with Json serialization/deserialization!");
} else {
SimpleJsonTestObject simpleObject = nbtItem.getObject(JSON_TEST_KEY, SimpleJsonTestObject.class);
if (simpleObject == null) {
throw new NbtApiException(
"Wasn't able to check JSON key! The Item-NBT-API may not work with Json serialization/deserialization!");
} else if (!(STRING_TEST_VALUE).equals(simpleObject.getTestString())
|| simpleObject.getTestInteger() != INT_TEST_VALUE
|| simpleObject.getTestDouble() != DOUBLE_TEST_VALUE
|| !simpleObject.isTestBoolean() == BOOLEAN_TEST_VALUE) {
throw new NbtApiException(
"One key does not equal the original value in JSON! The Item-NBT-API may not work with Json serialization/deserialization!");
}
}
} catch (Exception ex) {
throw new NbtApiException("Exception during Gson check!", ex);
}
}
// region STATIC FINAL VARIABLES
private static final String JSON_TEST_KEY = "jsonTest";
private static final String STRING_TEST_VALUE = "TestString";
private static final int INT_TEST_VALUE = 42;
private static final double DOUBLE_TEST_VALUE = 1.5d;
private static final boolean BOOLEAN_TEST_VALUE = true;
// end region STATIC FINAL VARIABLES
public static class SimpleJsonTestObject {
private String testString = STRING_TEST_VALUE;
private int testInteger = INT_TEST_VALUE;
private double testDouble = DOUBLE_TEST_VALUE;
private boolean testBoolean = BOOLEAN_TEST_VALUE;
public String getTestString() {
return testString;
}
public void setTestString(String testString) {
this.testString = testString;
}
public int getTestInteger() {
return testInteger;
}
public void setTestInteger(int testInteger) {
this.testInteger = testInteger;
}
public double getTestDouble() {
return testDouble;
}
public void setTestDouble(double testDouble) {
this.testDouble = testDouble;
}
public boolean isTestBoolean() {
return testBoolean;
}
public void setTestBoolean(boolean testBoolean) {
this.testBoolean = testBoolean;
}
}
}
@@ -1,21 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBT;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class InterfaceTest implements Test {
@Override
public void test() throws Exception {
ReadWriteNBT src = NBT.createNBTObject();
src.setString("foo", "bar");
ReadWriteNBT target = NBT.createNBTObject();
target.mergeCompound(src);
if (!"bar".equals(target.getString("foo"))) {
throw new NbtApiException("Wasn't able to check the key! The Item-NBT-API may not work!");
}
}
}
@@ -1,65 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NBTList;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class IteratorTest implements Test {
@Override
public void test() throws Exception {
NBTList<Integer> testList;
testList = initIntegerList();
testIterator(testList.iterator());
testList = initIntegerList();
testIterator(testList.listIterator());
}
private NBTList<Integer> initIntegerList() {
NBTContainer comp = new NBTContainer();
NBTList<Integer> list = comp.getIntegerList("test");
list.add(1);
list.add(2);
list.add(3);
list.add(4);
return list;
}
private static void testIterator(Iterator<Integer> iterator) {
assertTrue(iterator.hasNext());
assertTrue(iterator.next() == 1);
assertTrue(iterator.hasNext());
assertTrue(iterator.next() == 2);
iterator.remove();
assertTrue(iterator.hasNext());
assertTrue(iterator.next() == 3);
assertTrue(iterator.hasNext());
assertTrue(iterator.next() == 4);
testNoMoreElements(iterator);
}
private static void testNoMoreElements(Iterator<Integer> iterator) {
assertTrue(!iterator.hasNext());
try {
iterator.next();
} catch (NoSuchElementException expected) {
return;
} catch (Exception e) {
throw new NbtApiException("iterator threw wrong exception: " + e.toString());
}
throw new NbtApiException("iterator did not throw exception");
}
private static void assertTrue(boolean condition) {
if (!condition) {
throw new NbtApiException("iterator test failed");
}
}
}
@@ -1,168 +0,0 @@
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.NBTType;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class ListTest implements Test {
@Override
public void test() throws Exception {
NBTContainer comp = new NBTContainer();
// Strings
NBTList<String> list = comp.getStringList("testlist");
list.add("test1");
list.add("test2");
list.add("test3");
list.add("test4");
list.set(2, "test42");
list.remove(1);
if (!list.get(1).equals("test42") || list.size() != 3) {
throw new NbtApiException("The String-list did not match what it should have looked like.");
}
// Compound
NBTCompoundList taglist = comp.getCompoundList("complist");
NBTListCompound 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");
subsubcomp.setString("deep", "String");
subsubcomp.getCompoundList("deeplist").addCompound().setString("test", "test");
subsubcomp.getCompoundList("clonelist").addCompound(comp);
taglist = null;
lcomp = null;
subsubcomp = null;
taglist = comp.getCompoundList("complist");
if (taglist.size() == 1) {
lcomp = taglist.get(0);
ReadWriteNBT sublist = lcomp.getCompound("listsubkey");
if (lcomp.getKeys().size() != 4) {
throw new NbtApiException("Wrong key amount in Taglist (" + lcomp.getKeys().size() + ")!");
} else if (sublist == null) {
throw new NbtApiException("The sublist is null! The Item-NBT-API may not work!");
} else if (!(lcomp.getDouble("double1") == 0.3333 && lcomp.getInteger("int1") == 42
&& lcomp.getString("test2").equals("test2") && !lcomp.hasTag("test1"))) {
throw new NbtApiException("One key in the Taglist changed! The Item-NBT-API may not work!");
} else if (!"String".equals(sublist.getString("deep"))) {
throw new NbtApiException(
"The Compound nested in the listcompound was not correct! The Item-NBT-API may not work!");
} else if (sublist.getType("deep") != NBTType.NBTTagString) {
throw new NbtApiException("The nested key's type wasn't correct! The Item-NBT-API may not work!");
} else if (sublist.getType("deeplist") != NBTType.NBTTagList) {
throw new NbtApiException("The nested list's type wasn't correct '" + sublist.getType("deeplist")
+ "'! The Item-NBT-API may not work!");
}
} else {
throw new NbtApiException("Taglist is empty! The Item-NBT-API may not work!");
}
if (comp.getListType("complist") != NBTType.NBTTagCompound) {
throw new NbtApiException("complist had the wrong type! The Item-NBT-API may not work!");
}
// Integer
NBTList<Integer> intlist = comp.getIntegerList("inttest");
intlist.add(42);
intlist.add(69);
if (intlist.size() == 2 && intlist.get(0) == 42 && intlist.get(1) == 69) {
// ok
} else {
throw new NbtApiException("IntList is not correct! " + Arrays.toString(intlist.toArray(new Integer[0])));
}
if (comp.getListType("inttest") != NBTType.NBTTagInt) {
throw new NbtApiException("inttest had the wrong type! The Item-NBT-API may not work!");
}
// Double
NBTList<Double> doublelist = comp.getDoubleList("doubletest");
doublelist.add(42.23d);
doublelist.add(69.69d);
if (doublelist.size() == 2 && doublelist.get(0) == 42.23d && doublelist.get(1) == 69.69d) {
// ok
} else {
throw new NbtApiException(
"DoubleList is not correct! " + Arrays.toString(doublelist.toArray(new Double[0])));
}
if (comp.getListType("doubletest") != NBTType.NBTTagDouble) {
throw new NbtApiException("doubletest had the wrong type! The Item-NBT-API may not work!");
}
// Float
NBTList<Float> floatlist = comp.getFloatList("floattest");
floatlist.add(42.23f);
floatlist.add(69.69f);
if (floatlist.size() == 2 && floatlist.get(0) == 42.23f && floatlist.get(1) == 69.69f) {
// ok
} else {
throw new NbtApiException("FloatList is not correct! " + Arrays.toString(floatlist.toArray(new Float[0])));
}
if (comp.getListType("floattest") != NBTType.NBTTagFloat) {
throw new NbtApiException("floattest had the wrong type! The Item-NBT-API may not work!");
}
// Long
NBTList<Long> longlist = comp.getLongList("longtest");
longlist.add(1241234124124l);
longlist.add(1231454321312l);
if (longlist.size() == 2 && longlist.get(0) == 1241234124124l && longlist.get(1) == 1231454321312l) {
// ok
} else {
throw new NbtApiException("LongList is not correct! " + Arrays.toString(longlist.toArray(new Long[0])));
}
if (comp.getListType("longtest") != NBTType.NBTTagLong) {
throw new NbtApiException("longtest had the wrong type! The Item-NBT-API may not work!");
}
// int[]
NBTList<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))
&& Arrays.equals(new int[] { 4, 2, 0 }, intArrayList.get(1))) {
// ok
} else {
throw new NbtApiException("IntArrayList is not correct! " + intArrayList);
}
if (comp.getListType("intatest") != NBTType.NBTTagIntArray) {
throw new NbtApiException("intatest had the wrong type! The Item-NBT-API may not work!");
}
// UUID
NBTList<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))
&& UUID.fromString("853c80ef-3c37-49fd-aa49-938b674adae6").equals(uuidList.get(1))) {
// ok
} else {
throw new NbtApiException("UUIDList is not correct! " + uuidList);
}
if (comp.getListType("uuidtest") != NBTType.NBTTagIntArray) {
throw new NbtApiException("uuidtest had the wrong type! The Item-NBT-API may not work!");
}
}
}
@@ -1,25 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import java.util.Arrays;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class LongArrayTest implements Test {
@Override
public void test() throws Exception {
NBTContainer comp = new NBTContainer();
comp.setLongArray("test", new long[] { 1, 2, 3, 4, Long.MAX_VALUE });
if (!comp.hasTag("test")) {
throw new NbtApiException("Wasn't able to check a key! The Item-NBT-API may not work!");
}
if (!Arrays.equals(comp.getLongArray("test"), new long[] { 1, 2, 3, 4, Long.MAX_VALUE })) {
throw new NbtApiException("The long key does not equal the original value! The Item-NBT-API may not work!");
}
}
}
@@ -1,22 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class MergeTest implements Test {
@Override
public void test() throws Exception {
NBTContainer test1 = new NBTContainer();
test1.setString("test1", "test");
NBTContainer test2 = new NBTContainer();
test2.setString("test2", "test");
test2.addCompound("test").setLong("time", System.currentTimeMillis());
test1.mergeCompound(test2);
if (!test1.getString("test1").equals(test1.getString("test2"))) {
throw new NbtApiException("Wasn't able to merge Compounds!");
}
}
}
@@ -1,56 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBT;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class ModernSubCompoundsTest implements Test {
private static final String COMP_TEST_KEY = "componentTest";
private static final String STRING_TEST_KEY = "stringTest";
private static final String INT_TEST_KEY = "intTest";
private static final String DOUBLE_TEST_KEY = "doubleTest";
private static final String BOOLEAN_TEST_KEY = "booleanTest";
private static final String STRING_TEST_VALUE = "TestString";
private static final int INT_TEST_VALUE = 42;
private static final double DOUBLE_TEST_VALUE = 1.5d;
private static final boolean BOOLEAN_TEST_VALUE = true;
@Override
public void test() throws Exception {
ReadWriteNBT cont = NBT.createNBTObject();
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);
if (cont.getCompound("invalide") != null) {
throw new NbtApiException("An invalide compound did not return null!");
}
comp = null;
comp = cont.getCompound(COMP_TEST_KEY);
if (comp == null) {
throw new NbtApiException("Wasn't able to get the NBTCompound!");
}
if (!comp.hasTag(STRING_TEST_KEY)) {
throw new NbtApiException("Wasn't able to check a compound key!");
}
if (!(STRING_TEST_VALUE + "2").equals(comp.getString(STRING_TEST_KEY))
|| comp.getInteger(INT_TEST_KEY) != INT_TEST_VALUE * 2
|| comp.getDouble(DOUBLE_TEST_KEY) != DOUBLE_TEST_VALUE * 2
|| comp.getBoolean(BOOLEAN_TEST_KEY) == BOOLEAN_TEST_VALUE) {
throw new NbtApiException("One key does not equal the original compound value!");
}
// Using getOrCreateCompound twice
comp.getOrCreateCompound("someName").setString("test", "abc");
if (!comp.getOrCreateCompound("someName").getString("test").equals("abc")) {
throw new NbtApiException("getOrCreateCompound did not return the same compound!");
}
}
}
@@ -1,67 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class RemovingKeys implements Test {
private static final String STRING_TEST_KEY = "stringTest";
private static final String INT_TEST_KEY = "intTest";
private static final String DOUBLE_TEST_KEY = "doubleTest";
private static final String BOOLEAN_TEST_KEY = "booleanTest";
private static final String SHORT_TEST_KEY = "shortTest";
private static final String BYTE_TEST_KEY = "byteTest";
private static final String FLOAT_TEST_KEY = "floatTest";
private static final String LONG_TEST_KEY = "longTest";
private static final String INTARRAY_TEST_KEY = "intarrayTest";
private static final String BYTEARRAY_TEST_KEY = "bytearrayTest";
private static final String STRING_TEST_VALUE = "TestString";
private static final int INT_TEST_VALUE = 42;
private static final double DOUBLE_TEST_VALUE = 1.5d;
private static final boolean BOOLEAN_TEST_VALUE = true;
private static final short SHORT_TEST_VALUE = 64;
private static final byte BYTE_TEST_VALUE = 7;
private static final float FLOAT_TEST_VALUE = 13.37f;
private static final long LONG_TEST_VALUE = (long) Integer.MAX_VALUE + 42L;
private static final int[] INTARRAY_TEST_VALUE = new int[] { 1337, 42, 69 };
private static final byte[] BYTEARRAY_TEST_VALUE = new byte[] { 8, 7, 3, 2 };
@Override
public void test() throws Exception {
NBTContainer comp = new NBTContainer();
comp.setString(STRING_TEST_KEY, STRING_TEST_VALUE);
comp.setInteger(INT_TEST_KEY, INT_TEST_VALUE);
comp.setDouble(DOUBLE_TEST_KEY, DOUBLE_TEST_VALUE);
comp.setBoolean(BOOLEAN_TEST_KEY, BOOLEAN_TEST_VALUE);
comp.setByte(BYTE_TEST_KEY, BYTE_TEST_VALUE);
comp.setShort(SHORT_TEST_KEY, SHORT_TEST_VALUE);
comp.setLong(LONG_TEST_KEY, LONG_TEST_VALUE);
comp.setFloat(FLOAT_TEST_KEY, FLOAT_TEST_VALUE);
comp.setIntArray(INTARRAY_TEST_KEY, INTARRAY_TEST_VALUE);
comp.setByteArray(BYTEARRAY_TEST_KEY, BYTEARRAY_TEST_VALUE);
if (comp.getKeys().size() != 10) {
throw new NbtApiException("Key amount did not match after setting keys!");
}
comp.setString(STRING_TEST_KEY, null);
comp.setInteger(INT_TEST_KEY, null);
comp.setDouble(DOUBLE_TEST_KEY, null);
comp.setBoolean(BOOLEAN_TEST_KEY, null);
comp.setByte(BYTE_TEST_KEY, null);
comp.setShort(SHORT_TEST_KEY, null);
comp.setLong(LONG_TEST_KEY, null);
comp.setFloat(FLOAT_TEST_KEY, null);
comp.setIntArray(INTARRAY_TEST_KEY, null);
comp.setByteArray(BYTEARRAY_TEST_KEY, null);
if (comp.getKeys().size() != 0) {
throw new NbtApiException("Keys where not removed using the setter with null!");
}
}
}
@@ -1,27 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBT;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class ResolveTest implements Test {
@Override
public void test() throws Exception {
ReadWriteNBT src = NBT.createNBTObject();
src.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
if (src.resolveOrDefault("foo.bar.baz.test", 0) != 42) {
throw new NbtApiException("Wasn't able to check the value! The Item-NBT-API may not work!");
}
if (!Integer.valueOf(42).equals(src.resolveOrNull("foo.bar.baz.test", Integer.class))) {
throw new NbtApiException("Wasn't able to check the value! The Item-NBT-API may not work!");
}
src.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123);
if (src.getOrCreateCompound("foo").getOrCreateCompound("some.key").getOrCreateCompound("baz")
.getInteger("other") != 123) {
throw new NbtApiException("Wasn't able to check the value! The Item-NBT-API may not work!");
}
}
}
@@ -1,26 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class StreamTest implements Test {
@Override
public void test() throws Exception {
NBTContainer base = new NBTContainer();
base.getOrCreateCompound("sub").setString("hello", "world");
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
base.getOrCreateCompound("sub").writeCompound(outStream);
byte[] data = outStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
NBTContainer container = new NBTContainer(inputStream);
if (!container.toString().equals(base.getOrCreateCompound("sub").toString())) {
throw new NbtApiException("Component content did not match! " + base.getCompound("sub") + " " + container);
}
}
}
@@ -1,56 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
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;
public class SubCompoundsTest implements Test {
private static final String COMP_TEST_KEY = "componentTest";
private static final String STRING_TEST_KEY = "stringTest";
private static final String INT_TEST_KEY = "intTest";
private static final String DOUBLE_TEST_KEY = "doubleTest";
private static final String BOOLEAN_TEST_KEY = "booleanTest";
private static final String STRING_TEST_VALUE = "TestString";
private static final int INT_TEST_VALUE = 42;
private static final double DOUBLE_TEST_VALUE = 1.5d;
private static final boolean BOOLEAN_TEST_VALUE = true;
@Override
public void test() throws Exception {
NBTContainer cont = new NBTContainer();
NBTCompound comp = cont.addCompound(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);
if (cont.getCompound("invalide") != null) {
throw new NbtApiException("An invalide compound did not return null!");
}
comp = null;
comp = cont.getCompound(COMP_TEST_KEY);
if (comp == null) {
throw new NbtApiException("Wasn't able to get the NBTCompound!");
}
if (!comp.hasTag(STRING_TEST_KEY)) {
throw new NbtApiException("Wasn't able to check a compound key!");
}
if (!(STRING_TEST_VALUE + "2").equals(comp.getString(STRING_TEST_KEY))
|| comp.getInteger(INT_TEST_KEY) != INT_TEST_VALUE * 2
|| comp.getDouble(DOUBLE_TEST_KEY) != DOUBLE_TEST_VALUE * 2
|| comp.getBoolean(BOOLEAN_TEST_KEY) == BOOLEAN_TEST_VALUE) {
throw new NbtApiException("One key does not equal the original compound value!");
}
// Using getOrCreateCompound twice
comp.getOrCreateCompound("someName").setString("test", "abc");
if (!comp.getOrCreateCompound("someName").getString("test").equals("abc")) {
throw new NbtApiException("getOrCreateCompound did not return the same compound!");
}
}
}
@@ -1,22 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.compounds;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NBTType;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class TypeTest implements Test {
@Override
public void test() throws Exception {
NBTCompound comp = new NBTContainer();
comp.setString("s", "test");
comp.setInteger("i", 42);
comp.addCompound("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");
}
}
}
@@ -1,42 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.entities;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class EntityCustomNbtPersistentTest implements Test {
@Override
public void test() throws Exception {
if (MinecraftVersion.getVersion().getVersionId() < MinecraftVersion.MC1_14_R1.getVersionId())
return;
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
if (!world.getEntitiesByClasses(Animals.class, Monster.class).isEmpty()) {
Entity ent = world.getEntitiesByClasses(Animals.class, Monster.class).iterator().next();
NBTEntity nbtEnt = new NBTEntity(ent);
NBTCompound comp = nbtEnt.getPersistentDataContainer();
comp.setString("Hello", "World");
NBTEntity nbtent = new NBTEntity(ent);
if (!nbtent.toString().contains("Hello:\"World\"")) {
throw new NbtApiException("Custom Data did not save to the Entity!");
}
comp.removeKey("Hello");
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTEntities!", ex);
}
}
}
}
@@ -1,30 +0,0 @@
package de.tr7zw.nbtapi.plugin.tests.entities;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Monster;
import de.tr7zw.changeme.nbtapi.NBTEntity;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class EntityTest implements Test {
@Override
public void test() throws Exception {
if (!Bukkit.getWorlds().isEmpty()) {
World world = Bukkit.getWorlds().get(0);
try {
if (!world.getEntitiesByClasses(Animals.class, Monster.class).isEmpty()) {
NBTEntity nbte = new NBTEntity(
world.getEntitiesByClasses(Animals.class, Monster.class).iterator().next());
nbte.setString("INVALIDEKEY", "test");
}
} catch (Exception ex) {
throw new NbtApiException("Wasn't able to use NBTEntities!", 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);
}
}
}
}
@@ -1,31 +0,0 @@
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.NBTItem;
import de.tr7zw.changeme.nbtapi.NbtApiException;
import de.tr7zw.changeme.nbtapi.iface.ReadableNBT;
import de.tr7zw.nbtapi.plugin.tests.Test;
public class DirectApplyMetaTest implements Test {
@Override
public void test() throws Exception {
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!");
}
}
private void modifyMeta(ReadableNBT nbt, ItemMeta meta) {
meta.setDisplayName(nbt.getString("SomeKey"));
}
}
Loaded 100 of 661 files, more files were not shown because too many files have changed in this diff. Show more