mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-12 04:20:17 +00:00
Compare commits
2119 Commits
4.1.0-BETA
...
5.0.0-BETA
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c69116717 | |||
| 9d9c628acd | |||
| cbda24d77e | |||
| ed64eac76f | |||
| a7aebed0a0 | |||
| c66a3a8b3e | |||
| 4aba9d9725 | |||
| d2c34615f5 | |||
| 815b4e2bab | |||
| 69273f3ff7 | |||
| fdb724c646 | |||
| 3109a179db | |||
| 5afeeb8f89 | |||
| 1cb7846f7c | |||
| 097feba4d5 | |||
| 9509d7e04d | |||
| 3116fb8187 | |||
| e0630fbb25 | |||
| 8454076235 | |||
| 4a3843a881 | |||
| b8a1b32461 | |||
| edcf0f8405 | |||
| b8abe34904 | |||
| 7ac74180c9 | |||
| 6186fc0bfe | |||
| ef40934d24 | |||
| 69b668355f | |||
| ee9ce8a4f4 | |||
| 59ca7b75e1 | |||
| 9621836e36 | |||
| 0547383296 | |||
| c7dff9ea40 | |||
| 043350753b | |||
| 5ad8016b99 | |||
| 2e5b2eed6e | |||
| 5a0cde49cc | |||
| 008a022ec1 | |||
| 5c85a7c306 | |||
| 599c4284f5 | |||
| 9499e2e595 | |||
| a4fea1444a | |||
| c9bb4335a1 | |||
| 015c668885 | |||
| ccb22ceb3f | |||
| 1ba47802a8 | |||
| 9d111e13f1 | |||
| 44bc4d8c7c | |||
| 30f1d3e016 | |||
| 7b1a1e5a18 | |||
| 1b452f3a88 | |||
| fa719f37d5 | |||
| d834266635 | |||
| d317347a9b | |||
| 077fac84bf | |||
| 6f0eb019d2 | |||
| fdb3a5b121 | |||
| 8e6c1762d7 | |||
| e3bc36ab5b | |||
| 283ff28aa9 | |||
| c3ceeeace7 | |||
| aac4f6c0e1 | |||
| 926f68d8c5 | |||
| ed11fd5a83 | |||
| e0a6ec0c24 | |||
| 7cdf6b0946 | |||
| 5c7f4570b4 | |||
| bb60a9057f | |||
| 3b893961e4 | |||
| 325ffec1be | |||
| fa715a074a | |||
| 4caa2c7690 | |||
| d04da9b1d8 | |||
| 8a374df801 | |||
| 02cf5ed388 | |||
| 6cad559dbe | |||
| 84a943bcec | |||
| f2c6a75145 | |||
| 09e823e304 | |||
| 289ede669d | |||
| 4f32f5e0b7 | |||
| 633e77a34c | |||
| 092d130c96 | |||
| c09390d20f | |||
| 22f8623e17 | |||
| d8e77c1920 | |||
| 85372633eb | |||
| 2c81446e5b | |||
| 299ff5d912 | |||
| 896dd2ec9d | |||
| f1417e8dc9 | |||
| 897ba9f2d9 | |||
| d2c37d8bcf | |||
| 43fe819862 | |||
| f9d9cbd0f6 | |||
| ed021d193d | |||
| 32e6fdd95a | |||
| 01f340985a | |||
| 5e462db0f8 | |||
| 6beb80b8fe | |||
| 4d0cecbac2 | |||
| 5fcf5e0c40 | |||
| f29e2f7110 | |||
| d0d263191d | |||
| 3366e1084b | |||
| d0b9234841 | |||
| d80f65ae7c | |||
| 096daef0d0 | |||
| 29694c19af | |||
| b3e94ef1dc | |||
| f04151dbe6 | |||
| 5dcd8bf289 | |||
| 17fe894229 | |||
| 728e0bc869 | |||
| a1d44de487 | |||
| 263e1e9950 | |||
| 2121152b76 | |||
| a1cd1d7433 | |||
| 04aabaee5e | |||
| 75410a5412 | |||
| e2108557ab | |||
| ff8301b86c | |||
| 869c836e2d | |||
| b70ff32548 | |||
| 73bf5d4b29 | |||
| eb136e60c8 | |||
| 4228880509 | |||
| 709d874204 | |||
| 07dc10d6e6 | |||
| 7f6269c432 | |||
| 194714b448 | |||
| 023460db2c | |||
| 2910ffebf4 | |||
| fea820a99e | |||
| 7c19f14cf5 | |||
| 5a54d09869 | |||
| a8dec1adb1 | |||
| 0dca85af44 | |||
| 4def4d52d9 | |||
| 1d10107024 | |||
| 54ae4d0ea2 | |||
| 0d21e591d1 | |||
| 408616723c | |||
| 9bfcd39f2a | |||
| 8102616ff4 | |||
| b162d688a3 | |||
| eb130f2906 | |||
| 3b09c3a48a | |||
| 87781cff4d | |||
| db0cf4bb5a | |||
| a0346fb6d3 | |||
| eb4679fefd | |||
| a4f2b99ed5 | |||
| 3ecc980bc4 | |||
| 107b56154b | |||
| f86fde064d | |||
| edcaeef831 | |||
| d4ca566fd0 | |||
| 6c0ad9589b | |||
| 84a16ce69a | |||
| d06d3bc871 | |||
| 11e34b3e5c | |||
| f9318bf286 | |||
| 769be8e140 | |||
| c878bd8289 | |||
| 71b78b02d3 | |||
| 4147d0dc75 | |||
| 674b65f789 | |||
| a77fc8109f | |||
| 6102740ee3 | |||
| 40168a457e | |||
| d07acd0013 | |||
| 9561ae5af7 | |||
| 56fbd45dd5 | |||
| b5dc72b0ee | |||
| 4ba57f2b03 | |||
| 1026811741 | |||
| 84cb070d56 | |||
| df0d72bf61 | |||
| a534ac759a | |||
| 5ab954b7a0 | |||
| 6c6f686f8e | |||
| bf7975da57 | |||
| 7aeedd8220 | |||
| 3dd1ce2d02 | |||
| 5a29d07021 | |||
| 692e1253c6 | |||
| ab0c444823 | |||
| e48a4aaa55 | |||
| 6fc4ce0f86 | |||
| 6acabf7a1b | |||
| 10243c7b2c | |||
| b122703fd0 | |||
| e40774d62f | |||
| 027d8f7377 | |||
| 5950707267 | |||
| 6cace51a21 | |||
| 6703f46a08 | |||
| 874fdf5adb | |||
| 1c626baf1a | |||
| c3a2199f0e | |||
| 499b29b53a | |||
| 8102586ee0 | |||
| 18b528f72d | |||
| 0336394098 | |||
| 7e92da126d | |||
| b80d7a57e3 | |||
| 1569bed37a | |||
| ba62e0f9cb | |||
| a6e79c5004 | |||
| 858d4a2ed2 | |||
| 18658cb74d | |||
| dd9ea4ee02 | |||
| ed88d68fd7 | |||
| 9bddcc72f7 | |||
| 87d8c1ea11 | |||
| 89deb0fe18 | |||
| ad88490e84 | |||
| 3490e2b06a | |||
| 946c2fbacc | |||
| 1c0eed56f1 | |||
| a0dadc6e37 | |||
| 9e9b4db00f | |||
| e667b5c7db | |||
| f61f72180f | |||
| 3f82150837 | |||
| 017fcde6aa | |||
| 24374297e7 | |||
| 76ebedff6a | |||
| 3ea8d27a3b | |||
| d6c923b525 | |||
| 7b55c984bf | |||
| f5b4d64668 | |||
| 1683aa681d | |||
| bf84caa02c | |||
| 734adec90d | |||
| 4724195791 | |||
| f32a853bd4 | |||
| dbcd2b1e65 | |||
| 61b0ad3e7f | |||
| b2f755720d | |||
| 8ef2780dcd | |||
| 7e1467f3f7 | |||
| b19c7212ab | |||
| 14c1a9550d | |||
| 9037d5f16b | |||
| 8b64ea9e65 | |||
| 2936726bf8 | |||
| 9cd07f6721 | |||
| 4bb8daa1a5 | |||
| 6e8eda4ac1 | |||
| 73522d06ef | |||
| a6a360d179 | |||
| 199ef7401f | |||
| d731f5485a | |||
| f63d349be4 | |||
| 02e11b5a60 | |||
| 4a770e5801 | |||
| a2ff9649d5 | |||
| a862cf5144 | |||
| 5ac0d7ae11 | |||
| 0c47455b24 | |||
| 09bff60b04 | |||
| 821dd8885b | |||
| a78ae73119 | |||
| 17a1266056 | |||
| 217d7ab4cf | |||
| 9e8c0a6bea | |||
| dc1b5a9285 | |||
| c3a16d9b1f | |||
| 982d05affd | |||
| 10f3145af2 | |||
| bed218d1dd | |||
| 5e1f837a73 | |||
| b49a9ae81d | |||
| bea878e9e9 | |||
| 04197d6b80 | |||
| 4c60e82110 | |||
| beb0713a40 | |||
| cd603e8266 | |||
| af385668c2 | |||
| 3ee62d8440 | |||
| 811639f2cd | |||
| 58974765a6 | |||
| eca9fe50b6 | |||
| 1959d6dc9b | |||
| 9db7e5f0ca | |||
| c1cef19f84 | |||
| cebdb95265 | |||
| 006cdaf6ea | |||
| 32577354fc | |||
| acc8ae87fb | |||
| 0e8b28716a | |||
| 0220a30780 | |||
| 7c77233d12 | |||
| 6f02b83a26 | |||
| fbfdf749f2 | |||
| 0818388bd5 | |||
| 289c0b08f4 | |||
| dd37b531ad | |||
| 341a9b78b5 | |||
| 58d5126ada | |||
| 3b11191043 | |||
| f978c1e9a0 | |||
| 0b8193aeb3 | |||
| 00286e761c | |||
| db59f71130 | |||
| b11457d605 | |||
| ea386c42d3 | |||
| 043e81e737 | |||
| 66a4c4c88b | |||
| 1a9322c00a | |||
| c8d9477da1 | |||
| 08e8ef275f | |||
| e57fbff28c | |||
| f90315c4a2 | |||
| 955f7944bb | |||
| ccd288d7fa | |||
| 097632902a | |||
| a4d34be6df | |||
| e7771d76f2 | |||
| ecc830a689 | |||
| ee72e80fbb | |||
| 63310cf764 | |||
| 1992d3b6db | |||
| 035a0a4e9d | |||
| 23ea721164 | |||
| 7cdab75b05 | |||
| 2bf7941aec | |||
| 8408da8534 | |||
| 453ad997e9 | |||
| c9601ae67d | |||
| 758b5ee500 | |||
| ca6d51498f | |||
| e8085e22a0 | |||
| a83fc85f1e | |||
| 3d70a169e1 | |||
| 6ccb8f7373 | |||
| 59bae9b077 | |||
| 2751e1ec02 | |||
| c91168db66 | |||
| 4e55433ed8 | |||
| eece6c4433 | |||
| 67b7b60d18 | |||
| 804feedb67 | |||
| d57aca1367 | |||
| 7b0816e42f | |||
| 4864444440 | |||
| 52ea4feac0 | |||
| 01d557062a | |||
| a619fd2be6 | |||
| 05d9298958 | |||
| f696a5881b | |||
| 419962d3a2 | |||
| 054c06fab9 | |||
| 7bc5d8c824 | |||
| 607bdfa42f | |||
| eec53f9ae0 | |||
| 3d56bd267c | |||
| 9a969e21c7 | |||
| 195bc3b623 | |||
| 2177d8d352 | |||
| 471625e697 | |||
| 2135776c19 | |||
| 765aef0810 | |||
| bd21feffc4 | |||
| cf0e7b4213 | |||
| 5b324f695c | |||
| 9caed10488 | |||
| 83945ff0a0 | |||
| ef45180b80 | |||
| ec2b53f61a | |||
| 11ef6414b0 | |||
| abd4ef01eb | |||
| 941fd03998 | |||
| 1af8da3c1f | |||
| a5985dcf7d | |||
| 183d1f4038 | |||
| 08ee825d91 | |||
| 337a254768 | |||
| a31e3331fd | |||
| acebbeed16 | |||
| e0fdbe6eb1 | |||
| cc8660629b | |||
| e7e19abe85 | |||
| 72853677bb | |||
| 5f9e0081fd | |||
| b266f45152 | |||
| 4ba4d556ed | |||
| 6c29c3d2dd | |||
| 34ced382db | |||
| dace20ad1f | |||
| a573a279fa | |||
| 14f141fab2 | |||
| 10d22a55ec | |||
| 777b4d6ac3 | |||
| c500ccd891 | |||
| daff955bc4 | |||
| 85a64d56fb | |||
| cc69383b6f | |||
| 0022d82779 | |||
| 7cad9be0d2 | |||
| 2f862a552a | |||
| 590f6dad08 | |||
| 9564c81582 | |||
| 3de7a8c27f | |||
| d376399b7f | |||
| e2071e59c8 | |||
| a123194368 | |||
| 8e280ebb8b | |||
| f03afba10e | |||
| fa7c38276c | |||
| b13e97de3d | |||
| 328b87fc18 | |||
| f94040dead | |||
| 7c95a65ade | |||
| 2b88b215bf | |||
| 54c19fd662 | |||
| 9b1ec261c4 | |||
| 6151576baa | |||
| acaa1a9ce1 | |||
| fff8f0f815 | |||
| 867b8945e4 | |||
| 9e329d55a8 | |||
| be68c6a819 | |||
| 3aec0fa3df | |||
| fa131dab12 | |||
| bb4a82b1e7 | |||
| 93d844a281 | |||
| 616844696e | |||
| 71e3e36522 | |||
| dedd1d7fb3 | |||
| 9d442f2104 | |||
| a1b42d419f | |||
| ef942a627f | |||
| fd8c276bd2 | |||
| a49957682e | |||
| b399b2086c | |||
| 9783380d1a | |||
| a784d93bfd | |||
| a05e8b366f | |||
| 8933064cd5 | |||
| 87a2e0460c | |||
| 6db2b022fb | |||
| 4073c3fb39 | |||
| e227e6d8bf | |||
| 3aa40829ae | |||
| 035d4b7263 | |||
| 3db1492c18 | |||
| a523189149 | |||
| f8893efb94 | |||
| 70f1ee3e97 | |||
| eb2f0ed3d0 | |||
| 14e7d3e143 | |||
| 6d636fc2c7 | |||
| a39f61a33d | |||
| a42a67fc50 | |||
| 5eeb63f64b | |||
| b9d62de29d | |||
| aaec21f544 | |||
| 0edc5f8113 | |||
| a382f0fd92 | |||
| 95c18ef99a | |||
| 972f107972 | |||
| e15e53859f | |||
| 4692552fdc | |||
| cbb58d3e0d | |||
| 7c974a12e1 | |||
| f64dc01bd1 | |||
| 33140482bb | |||
| 77fe0a69ba | |||
| 948aa059c3 | |||
| 407b78de3b | |||
| 0fcd2e7894 | |||
| 369e0855a7 | |||
| a6cf39b94e | |||
| 17afd38274 | |||
| 8f024cb382 | |||
| e7209679fb | |||
| da054736b1 | |||
| d92173cded | |||
| 308cdb6863 | |||
| ae50b952f1 | |||
| 7608d5f04e | |||
| 9ae830fd54 | |||
| f44946cb49 | |||
| c82b43a586 | |||
| f704bfb63a | |||
| 9acb4d64db | |||
| 5854b1c8c2 | |||
| 8234360c8d | |||
| 6a64486f55 | |||
| 6ec778d0af | |||
| 737a63b0a3 | |||
| 75bb4f8da6 | |||
| efdd7a186d | |||
| 627c62a230 | |||
| 9a67fbf27a | |||
| 94ffef1a99 | |||
| 2feb9ca903 | |||
| 50b8d39aba | |||
| c4ecb3d128 | |||
| b574d49d36 | |||
| 47e9ecd257 | |||
| 799739fe86 | |||
| 59a04c971f | |||
| 168af31fd7 | |||
| 871bd169a8 | |||
| 4dbcd714bd | |||
| d5e92b4ae6 | |||
| 2a3288c4f9 | |||
| 9cdb641936 | |||
| 42df1a5c70 | |||
| b56b35b10d | |||
| 0e0f5e85eb | |||
| 324bc27b5a | |||
| 71aad310c6 | |||
| 38828e2b42 | |||
| 9a6d7b505c | |||
| 1e3b025916 | |||
| 55a48e0c84 | |||
| c2f6d8139a | |||
| ceff230d73 | |||
| e6f1cb69d1 | |||
| 4c3892b2d6 | |||
| 396d64c60b | |||
| d7a0f5362e | |||
| 75f74454c6 | |||
| 7611155ff9 | |||
| c0f3dbdd70 | |||
| c5dcd268ad | |||
| 910c4c4b24 | |||
| 2fd6e769e6 | |||
| aacd92bf08 | |||
| caebe14dab | |||
| cb10360c20 | |||
| 082f9e1647 | |||
| d891646d0a | |||
| 886b40a455 | |||
| 525f62e1e4 | |||
| 69155015c9 | |||
| 6854830b6e | |||
| 2d56aa50b9 | |||
| 5d0388e747 | |||
| 074e7586cb | |||
| 2c413768a5 | |||
| fbaf8e3fc8 | |||
| c62845e92a | |||
| c7930ce9ec | |||
| 475888b031 | |||
| 40b90bb722 | |||
| 5a4550a4fc | |||
| 7bbc04e6de | |||
| 3ba662f64f | |||
| 5d7b99daf4 | |||
| e47627f565 | |||
| 39207c7992 | |||
| 2f12bb9943 | |||
| 41ab698f93 | |||
| e45a6d8311 | |||
| 8912a97be7 | |||
| 8d2a9ce67c | |||
| 811352e2ef | |||
| 981385cf4a | |||
| 433b0ca6cc | |||
| da5302ca86 | |||
| 6b7a4e2c41 | |||
| e9b994cbc3 | |||
| cfa1e7486a | |||
| 3c46bf01c6 | |||
| 0e15a8698a | |||
| d3fff4e0b2 | |||
| aeb26141b2 | |||
| 4562cfb85b | |||
| cb1aac3cd4 | |||
| 3dd1a14fb7 | |||
| 63c3127248 | |||
| 2f283678c7 | |||
| 96c32d24ba | |||
| d64a9d8b52 | |||
| 92c29b8172 | |||
| 0ac9584bbb | |||
| fe12e8d944 | |||
| 7529953f0a | |||
| 00dbb6855a | |||
| 5226300b99 | |||
| 0f81b7be15 | |||
| 2b987b450b | |||
| 7eca3e8081 | |||
| 0975da57d6 | |||
| f56339c306 | |||
| b58d7fc82a | |||
| 2cd8e4d270 | |||
| 0a3ecfdae9 | |||
| 2f469ef4a0 | |||
| ceea8220a9 | |||
| cbaff1caec | |||
| 18013e9551 | |||
| 92896c78da | |||
| 5aa8b953a8 | |||
| 375ec8e00c | |||
| 002f7d6826 | |||
| bd3e9e1cad | |||
| 06ad1a2d2b | |||
| 222415859a | |||
| 6173471cca | |||
| 14b250c63f | |||
| 644881372d | |||
| a12aac71fd | |||
| 608fcd6cd7 | |||
| ce9b25e97a | |||
| f948cb0086 | |||
| 07a30ea1f9 | |||
| 6c52723d97 | |||
| d5b7bf77b0 | |||
| b1a5b02d3a | |||
| 74e052de51 | |||
| a5397d55fe | |||
| 65ef929d22 | |||
| 441919c5e3 | |||
| 448aeec780 | |||
| b8f6b66e42 | |||
| 365cce9d0c | |||
| 78aea5c34c | |||
| d7f40f75d2 | |||
| 41e60cb62c | |||
| 5d2ac214a8 | |||
| 023010370b | |||
| de3ba00684 | |||
| b47035fbab | |||
| 072a9202ef | |||
| f0925ff9dc | |||
| d9324b9951 | |||
| 1d9336ed67 | |||
| d37142af4b | |||
| 7c068101b7 | |||
| 217f9aea02 | |||
| 2f5e08067d | |||
| a8556dff02 | |||
| 664089861a | |||
| 7314151c47 | |||
| 7abfc46567 | |||
| 3a13f5cf5f | |||
| edb8f19a0c | |||
| 6c0254c1eb | |||
| 0bb9fb09cc | |||
| ab21fcdd67 | |||
| d9b8251f7b | |||
| ad6a423d12 | |||
| b03df4f1e6 | |||
| 0a2a6e2b3a | |||
| 0eb751c1c9 | |||
| b59b1e491e | |||
| 95e8c68fde | |||
| 7e16f9be8f | |||
| 768650cee0 | |||
| c2c529e2da | |||
| c55e23a2c6 | |||
| 5c2ed210fc | |||
| 289e86e899 | |||
| 7d59bafd83 | |||
| 950eddf405 | |||
| 1bbe053848 | |||
| 69967a0e55 | |||
| 0132ff47cb | |||
| 2ed48c8469 | |||
| d786ed5ebf | |||
| 8909aa6a18 | |||
| a9f06fc5f4 | |||
| a14346e98c | |||
| b76265cd37 | |||
| dff3f45d22 | |||
| 1e17d86421 | |||
| ba18a81e88 | |||
| 6dd006e730 | |||
| b57fcb52d4 | |||
| 2c20b20ad2 | |||
| 329c2a6c0f | |||
| 39218017ca | |||
| a4494a2133 | |||
| fc487b17be | |||
| ecd8f151f1 | |||
| c671d8a80b | |||
| ca1f1bf09f | |||
| 91ac47ecba | |||
| f4a1d69075 | |||
| cbeae906e1 | |||
| b25e8e26f0 | |||
| a79be994de | |||
| e26c8b9e9f | |||
| 4e9c3e101d | |||
| d295e1be54 | |||
| 2f3fcef97c | |||
| 4df1f7f502 | |||
| d74719704e | |||
| c5056e0a43 | |||
| a47aa50477 | |||
| 5021096bdd | |||
| 9c391a6809 | |||
| f7930a3a0b | |||
| bb7df60a4d | |||
| 992cb06da6 | |||
| bb3f87f862 | |||
| d2eddf9d33 | |||
| 81ca0c8fbf | |||
| fc77b14760 | |||
| 52b6f1a492 | |||
| 0233e74f4f | |||
| dd355c58d8 | |||
| 267032cff9 | |||
| 545d18eea7 | |||
| 9b4b960eb2 | |||
| d4b8c47a65 | |||
| 4a3d9f8f83 | |||
| 1c96e7936c | |||
| c5ca0857ee | |||
| 6cecd690b2 | |||
| 91e38d1f97 | |||
| 653178c1fd | |||
| eb06535ed1 | |||
| f9bcc8e862 | |||
| faaec12aaf | |||
| 1123a5aa23 | |||
| 8633804f15 | |||
| d3cea2ca7c | |||
| c2918709a3 | |||
| ece49f011c | |||
| 5d6dba96af | |||
| f43ca405d4 | |||
| d146175d27 | |||
| 3baa5ab712 | |||
| b24eb153f9 | |||
| 36525d9055 | |||
| 3d6baa8a55 | |||
| 30d3869eea | |||
| 81697111b9 | |||
| eedc943766 | |||
| e647e8c933 | |||
| c02bead12b | |||
| e9ca25c1cb | |||
| a513cca582 | |||
| c6e11a8453 | |||
| 2e9a3f9160 | |||
| 9a47c1d401 | |||
| 433f5451d7 | |||
| 85231215e7 | |||
| 64e505defb | |||
| 3d4ed5308e | |||
| 33d1755eae | |||
| 58dd4a44e3 | |||
| fc63c54116 | |||
| 5fdbb19852 | |||
| 6b2156151f | |||
| db07976aab | |||
| d8d236842f | |||
| f51717323b | |||
| 0e4b79ea77 | |||
| 588c9b114b | |||
| b095f606c1 | |||
| b312e93176 | |||
| 42db3abf5e | |||
| 172ce659b8 | |||
| 61933624d2 | |||
| 0d31b25fba | |||
| 90beaeaeb4 | |||
| 466f7e98ed | |||
| 59be901efe | |||
| 2da9b76452 | |||
| c79806eaf0 | |||
| 7ac6bd79a9 | |||
| 6b8b7311f0 | |||
| f173b91ca1 | |||
| 9796dfd4d9 | |||
| c1ba735c9e | |||
| 8fd4918429 | |||
| c89df7eb1c | |||
| 0d169b4e80 | |||
| b1c0eae1f6 | |||
| 80832ff763 | |||
| f7d0d16eb3 | |||
| 6375139d0b | |||
| a8edb92565 | |||
| 133884da72 | |||
| b4c7d33388 | |||
| d37841c214 | |||
| 2a81a421f3 | |||
| 567bd8abb5 | |||
| 3d038b28ff | |||
| 0c9b6a6797 | |||
| 639f089c55 | |||
| 9010b2743c | |||
| 4c91c4aaf1 | |||
| f8cc015c51 | |||
| 17125ce0e3 | |||
| 3987ee6cb2 | |||
| 51a684c0ea | |||
| 43e69041fc | |||
| 5d2b0acfc8 | |||
| 7d1d62042c | |||
| 2a33c9ed3b | |||
| b03733442b | |||
| 9c9929ff39 | |||
| 566a8a261f | |||
| a9e5f92958 | |||
| 17dde140a5 | |||
| b3473960b4 | |||
| 044d35956e | |||
| da4315df05 | |||
| 83bfe790fa | |||
| ee7d4728d8 | |||
| 923dcec4e7 | |||
| 1e5597f0d5 | |||
| aebcfc516f | |||
| 97ef209c5f | |||
| 16f90f4120 | |||
| ec59dc1c80 | |||
| 973b8130db | |||
| 99faeb8d05 | |||
| 1305fd5fb2 | |||
| 7a137f932f | |||
| 63e8b1cf3a | |||
| 65bce762ff | |||
| 529700bb8b | |||
| f38b15cf83 | |||
| 0efd928db6 | |||
| 9809909072 | |||
| de3af9e660 | |||
| a30c649607 | |||
| d7ebabd771 | |||
| be1087c071 | |||
| b27c47335c | |||
| 58eec637c1 | |||
| 4f86ea9933 | |||
| 6e2685cbbb | |||
| b2017c8462 | |||
| bf44edd179 | |||
| 44e288554a | |||
| ffa88aff67 | |||
| aa374083d8 | |||
| 1785cbb6b5 | |||
| 3d75094874 | |||
| 8c0d3943d8 | |||
| d02c6668b2 | |||
| 880d01daea | |||
| 50b70708fb | |||
| ba4d038972 | |||
| 437fa615b8 | |||
| 0ee6cdb058 | |||
| 97d6a79b25 | |||
| 8b5e4c1c16 | |||
| c5d716dc9d | |||
| 4d79aced07 | |||
| 95d0a3bf41 | |||
| cf707e15c2 | |||
| 1308cda5c2 | |||
| 214a5ddc15 | |||
| 9f7dfe3355 | |||
| 9b55d18393 | |||
| 84f9136b95 | |||
| 31465525e3 | |||
| 74613b9b09 | |||
| 1cefe24414 | |||
| 4357c110c8 | |||
| 8bf85d4a18 | |||
| b5e6dec0c6 | |||
| a3306914cc | |||
| 3b32ea1b0b | |||
| 7ec32f981e | |||
| b0c87e9d06 | |||
| 99996b62d6 | |||
| fed2a6d917 | |||
| 8e600b4a78 | |||
| 1d4b6dc66e | |||
| 1cb6d9f5af | |||
| 18c2e90574 | |||
| 142ccc7e87 | |||
| 174c9a48f5 | |||
| 0a9b52618d | |||
| 7ae6425d05 | |||
| b5cfab497d | |||
| ca3b5c38b7 | |||
| bc8def3be1 | |||
| 774e23137e | |||
| 3984d220bb | |||
| 43bc3c7b25 | |||
| eb62dc3294 | |||
| 28d8526d8d | |||
| 0b497654f2 | |||
| 279056fe2f | |||
| cd233b123b | |||
| 64dd5e3bf6 | |||
| 4e5cc57560 | |||
| d476a4c1aa | |||
| 95263795a8 | |||
| 2db86d151f | |||
| 8f20b9da91 | |||
| b0c6e8d8e0 | |||
| f0358b09b7 | |||
| 80a432d9ff | |||
| ec9f9a469f | |||
| d450264e1c | |||
| 5e92f55d35 | |||
| 58c1bfe5d2 | |||
| d03caafc2b | |||
| 641d35a30f | |||
| 642630a4d2 | |||
| b6982a84ef | |||
| d634b3de18 | |||
| d79e6354a0 | |||
| ff63983de4 | |||
| 588215044e | |||
| 5c1e9a35a9 | |||
| aad9f5fb45 | |||
| a8dca190c6 | |||
| fdb07cdbcd | |||
| 3b6ff3c42b | |||
| e5f5fe80f9 | |||
| 36ab34df29 | |||
| 23ae0c7cac | |||
| 1bc5e225ab | |||
| dda8ff18b1 | |||
| 6562335120 | |||
| 0c463a8721 | |||
| a66f966b08 | |||
| cca22046ab | |||
| 858d3dce8e | |||
| d19f0bf7be | |||
| ff2391e74a | |||
| 39e10da88d | |||
| 34839da757 | |||
| b3b8516661 | |||
| 90305a0b92 | |||
| 613ce251c5 | |||
| beed6efd4e | |||
| e5bc4deb12 | |||
| 2fcff13578 | |||
| b4b8ef1c6b | |||
| 9650b7f03a | |||
| a205d64732 | |||
| a3502a711d | |||
| 83ddcce987 | |||
| 732dac6fc1 | |||
| d5e3636908 | |||
| ef100b248b | |||
| d03bbb0426 | |||
| 93e661aa4e | |||
| 50efcf7424 | |||
| a7ac6070dc | |||
| 069062f122 | |||
| bf7014e0ec | |||
| 824ed0a56a | |||
| b3ccf41307 | |||
| a39938e6b6 | |||
| d5bf88acc0 | |||
| 2d0602d19f | |||
| 1a5cc8212c | |||
| 3a2a23b236 | |||
| 1a8c8af523 | |||
| 1e9d83f014 | |||
| 68e862b6fa | |||
| c915334c2b | |||
| 6153a2ac70 | |||
| ed452b9ccd | |||
| c19880e045 | |||
| 01bad344a0 | |||
| cdbdcb5d67 | |||
| 29301614e8 | |||
| 2fdc46c165 | |||
| bfd1b2c635 | |||
| d9638cef96 | |||
| 1671405cd0 | |||
| fe982c697b | |||
| 1572b31b8d | |||
| fba4895a17 | |||
| b6f6671a81 | |||
| 6da467b142 | |||
| 44af519cd6 | |||
| fb31e6085e | |||
| e4548da173 | |||
| 0d5287bf0b | |||
| a9361b3f8b | |||
| 6e4c62744e | |||
| 9a0ead6deb | |||
| d74824c8d5 | |||
| d4eb73abe9 | |||
| d1d5020c53 | |||
| 9f6c6b2b71 | |||
| bd01a919e5 | |||
| 0039af984d | |||
| 7864294336 | |||
| 2a910c1cc2 | |||
| cd04a3db2e | |||
| 572def9245 | |||
| 20f5bed926 | |||
| 14d17a9546 | |||
| b74c092d9b | |||
| 53cae8911d | |||
| 7bcc663b60 | |||
| b3bda788d9 | |||
| 2cc8a56e68 | |||
| b70f7afbd6 | |||
| 92783a6db9 | |||
| 57deb60355 | |||
| 92e47b98f8 | |||
| b84c110819 | |||
| e1b0e00c6f | |||
| 774df0fa4c | |||
| f88ae93897 | |||
| 4fadb63f67 | |||
| c83f0896ac | |||
| 0d29a138fb | |||
| 421379fc77 | |||
| 293cea7714 | |||
| 15645759e9 | |||
| 8dc0d506f4 | |||
| 8c651ce4b4 | |||
| db7cee6f22 | |||
| 6ae7cb288e | |||
| 7df2719fce | |||
| 10b8dcfdd1 | |||
| c1fbac412e | |||
| 3feaa18f6c | |||
| 1c6a2b66f7 | |||
| 41970feb57 | |||
| 0edf2ea6a4 | |||
| cd4bb91676 | |||
| 2be527060f | |||
| 6f68c6d8a0 | |||
| ac16378410 | |||
| 1f9dfa77bf | |||
| 0c7f8470b9 | |||
| fc56c041f3 | |||
| d6bbf8217d | |||
| 22486dd75e | |||
| 37ec1193ea | |||
| 1366a43c22 | |||
| 383dc2a2b9 | |||
| bda0ca23b4 | |||
| b21cd82e94 | |||
| 1c7b1e9e5d | |||
| 4b41b2f9ae | |||
| b87e4d8bd3 | |||
| a6cc611e9f | |||
| 86a2f8e360 | |||
| def2f8c145 | |||
| 6f4ea886b0 | |||
| ed7c95549d | |||
| cfb0cad7e0 | |||
| 83e5b0adb6 | |||
| 4650a3bb22 | |||
| 5e5661de75 | |||
| e2f1b10165 | |||
| 455f9fa92e | |||
| dec188d4ad | |||
| 2db3498891 | |||
| ab0202ba29 | |||
| 9295afe8b9 | |||
| a7dfa0907c | |||
| f448b2e685 | |||
| 6a0c54f850 | |||
| 77a18d0aea | |||
| 140a809c40 | |||
| cb7c136035 | |||
| 1bc8fb1851 | |||
| f6a9949942 | |||
| 18c9ccb01c | |||
| b6289e5807 | |||
| 24ac543313 | |||
| 83a136a176 | |||
| 3f7d8a3777 | |||
| 3c55db531d | |||
| 1609b11c8e | |||
| cf9610c710 | |||
| 590eb74703 | |||
| c24370b8ac | |||
| 93d4475111 | |||
| e4fc523251 | |||
| b39eaaf91f | |||
| 7804172846 | |||
| 7d29ac8293 | |||
| 481bda8cd5 | |||
| d1c75da14b | |||
| 89e29448ee | |||
| 66e70e5b0e | |||
| 785dc71256 | |||
| d459afaa54 | |||
| db586233da | |||
| 23e98a30f5 | |||
| 5bc7ca6569 | |||
| f39d2a9be3 | |||
| 2a982d48ad | |||
| 47d98af6ac | |||
| 9f97654f6f | |||
| f80ffd8de0 | |||
| 82ba7903c8 | |||
| 441b06f6c7 | |||
| 112974758e | |||
| 313850eec4 | |||
| a82923acb4 | |||
| 67887afd6b | |||
| 3d03bb1301 | |||
| c063198b89 | |||
| f3ca6de1eb | |||
| 88eafdd614 | |||
| 6dd5fec4ea | |||
| 6866c86d39 | |||
| a735a69870 | |||
| a0ea74c08f | |||
| ca4b8a5827 | |||
| f88c4d9a8c | |||
| 66cd156d80 | |||
| 222049927a | |||
| d72e947d15 | |||
| 770cca2efa | |||
| 033dac3d16 | |||
| 1ee02d7e02 | |||
| 85678aa356 | |||
| 1d253bc8c2 | |||
| 973a56ab28 | |||
| 9e0b4621be | |||
| ffb3af3e0d | |||
| b3f03d7ae6 | |||
| 2585160ca2 | |||
| 14d3e6c7d5 | |||
| 65ec318c30 | |||
| a25cb3741a | |||
| b7a15b6e01 | |||
| 456439566b | |||
| d5762d3f44 | |||
| 5c5d96d00b | |||
| 4dabac8420 | |||
| 5b89833d5c | |||
| fb25e05416 | |||
| 7fd4c12ea1 | |||
| 78b5be8dd0 | |||
| 0a92e91a30 | |||
| b3a13a2f21 | |||
| 08b9495bce | |||
| 4bd2325828 | |||
| 64ac20173b | |||
| ca3612e4ff | |||
| 6799dcff51 | |||
| 5779622235 | |||
| d4c4ae3d7a | |||
| c16893cbac | |||
| 7f175b47e6 | |||
| 0e73ffe555 | |||
| 1ffd38b37b | |||
| bd13f39156 | |||
| 0c446c276c | |||
| 0284e65f60 | |||
| b0d787b3d3 | |||
| 65e3ed43d5 | |||
| 75eba9c9ed | |||
| b5a049d1fe | |||
| bd9fcffe62 | |||
| feffbc2c5b | |||
| 53b51c99b4 | |||
| 5cb77c8365 | |||
| bf8befc40b | |||
| f75ca312cc | |||
| d144832928 | |||
| 709a869045 | |||
| ac056044ce | |||
| fc8434308b | |||
| 5426b41447 | |||
| af2babec23 | |||
| fedd541663 | |||
| 1ecb10acba | |||
| 5d5366a7c8 | |||
| 717ab1989a | |||
| 83db186b6a | |||
| 6a4e5aba8b | |||
| c13170a00b | |||
| 98778052bb | |||
| e86e8254a8 | |||
| 1b852ac290 | |||
| 10b799fadb | |||
| bc5008334a | |||
| 3235d128e5 | |||
| 2b7510945a | |||
| d6af2b12f4 | |||
| ad2d59923c | |||
| 792c1b62b7 | |||
| e90abecf38 | |||
| 575dd47db7 | |||
| e4a5defabb | |||
| 6e8f11d5e8 | |||
| c9626c610b | |||
| b65e0f64f6 | |||
| 8fb7fff6b9 | |||
| 5c8d8ff61f | |||
| 99b55f7427 | |||
| dce8bd6d21 | |||
| 8fa81242d6 | |||
| 223de3ad23 | |||
| 2f4a9469b6 | |||
| 8e97e9dcda | |||
| 304bb84af2 | |||
| cb020988d4 | |||
| eeb95872ea | |||
| 1b0d353fa3 | |||
| 4d34885b15 | |||
| c5b2488fc1 | |||
| d62df585f2 | |||
| 19d7c2b552 | |||
| d4f96a155a | |||
| 43a3151de3 | |||
| f7ab0a3b92 | |||
| bf4f6e5d53 | |||
| 036e06e889 | |||
| 9343a0b800 | |||
| 14b4644b03 | |||
| 464b65b25c | |||
| f1c571a528 | |||
| 15586ed80e | |||
| 0f8ad8ecf7 | |||
| 82b9afef77 | |||
| 2fc84f6c67 | |||
| 566f5935a3 | |||
| 44e4dabf6e | |||
| 8acc535218 | |||
| e9a1cb7ce5 | |||
| a21419d120 | |||
| c2b599166c | |||
| df7a1fcba6 | |||
| d77a95e4af | |||
| 5c72807b16 | |||
| 5c6927e16c | |||
| 9abbb85a93 | |||
| 554182b2cb | |||
| d669a6f0c7 | |||
| 723ae9eca0 | |||
| 79125b8426 | |||
| 6ba3b39541 | |||
| f4de4bd971 | |||
| c8a8e33fc1 | |||
| 16ed16722a | |||
| 42f9336f7a | |||
| 5d9f783037 | |||
| 01ca14c314 | |||
| 608c6ed6db | |||
| c26631d06d | |||
| b75bc61a64 | |||
| 3724479be3 | |||
| eb916fe43d | |||
| 5e3b3a0700 | |||
| e3640907ba | |||
| d9b050fb68 | |||
| 817591910b | |||
| 6a2315a63d | |||
| 89b784734e | |||
| b751207969 | |||
| cffa3b8a72 | |||
| 91e91b1d9f | |||
| 102406ee79 | |||
| 4419161a49 | |||
| 38e495babf | |||
| 17635e770b | |||
| b13f333b2e | |||
| a7313ed9d9 | |||
| e10a624444 | |||
| b20e04539d | |||
| 4852f8029a | |||
| bedf79e2cd | |||
| f6c9bf5cd1 | |||
| 2d2df22ee7 | |||
| 2940547026 | |||
| 24e72ec109 | |||
| 47adcf763d | |||
| 67682cbf27 | |||
| c1acf44337 | |||
| 466307a43f | |||
| 44c4118080 | |||
| c4f85e526b | |||
| 6cee428287 | |||
| bcba064d69 | |||
| 2fa92e5e02 | |||
| dbc0b9634b | |||
| 86647683bc | |||
| fa201b081c | |||
| de3bbb71fa | |||
| 040516054f | |||
| 64f0e58e60 | |||
| 62f21516d1 | |||
| c553f7cf06 | |||
| eccfb3bbe2 | |||
| 87b840ff97 | |||
| f64e306fb8 | |||
| 9a8902d1fe | |||
| b36b65927c | |||
| afaf9dbc88 | |||
| b0a492c063 | |||
| 6d4279671e | |||
| cf34f88a67 | |||
| b8d1b00985 | |||
| 8660dfe576 | |||
| 172bd9a129 | |||
| 012b668537 | |||
| fec89b7803 | |||
| 4f2f9b4352 | |||
| b3f8b5ff37 | |||
| 81edb1bed4 | |||
| d0ff6d2e36 | |||
| 4afd3dcabf | |||
| 4e3964ffce | |||
| c7f5215a51 | |||
| 66f2116e57 | |||
| c15c59ae0d | |||
| 07786dc4bc | |||
| 259f44e57c | |||
| 93254523e6 | |||
| 2b61c025c2 | |||
| e5804df24b | |||
| e00f8e3a32 | |||
| c8320fe849 | |||
| e2855aadff | |||
| 21ed5a450f | |||
| ba2baba7cc | |||
| c7133bc2e6 | |||
| d4f4fda442 | |||
| 4d6ec66270 | |||
| baf75089f5 | |||
| b4ce5ed515 | |||
| eb8fb63409 | |||
| 705df7d508 | |||
| 91719051e2 | |||
| d321094081 | |||
| 323d31005f | |||
| 0c7370e564 | |||
| 3dd4c42fd3 | |||
| f1a63098bd | |||
| 75d7adfb2d | |||
| 7dd8876515 | |||
| d0067cfac5 | |||
| eafc23c756 | |||
| 20cb67461f | |||
| 8b2d941502 | |||
| dea0207e4e | |||
| 4b1052022c | |||
| 32f9fcd4e9 | |||
| 9d535e2917 | |||
| 3ccd288afd | |||
| 06655bee78 | |||
| 2ba51567d8 | |||
| 14933a731b | |||
| a22276e679 | |||
| 260e54e4b1 | |||
| a44c089f98 | |||
| 5e70ae2066 | |||
| ad7528e3f3 | |||
| 99ff78a8a5 | |||
| 9ffee7cfc3 | |||
| ccb3c3cb05 | |||
| 151f2c3f3a | |||
| 66d655731a | |||
| 54a773be0c | |||
| d894c5e97f | |||
| 419b21281d | |||
| 56e6a55645 | |||
| c67e42a723 | |||
| 3e4f01d85e | |||
| da9937933b | |||
| 2142eb3cc9 | |||
| 690efb09e3 | |||
| e4d24e1edd | |||
| 4d6fb2b925 | |||
| 0ad2985247 | |||
| 976502e3db | |||
| b0c76f4db5 | |||
| 8886a023f1 | |||
| ae70c63798 | |||
| 986daab511 | |||
| eb404bddb4 | |||
| 30079f6fd0 | |||
| ce87424336 | |||
| 06d3fc2880 | |||
| d40e864821 | |||
| 88a5a95479 | |||
| 00db73a5b2 | |||
| 5a8983dd81 | |||
| 269b6ed16a | |||
| f031c3c602 | |||
| a377795db9 | |||
| a8728a02f6 | |||
| dc8f65c0dd | |||
| 5c4288de01 | |||
| 46b79fbe85 | |||
| 494cb580f3 | |||
| 64e93ae4e1 | |||
| f3e09dd7d5 | |||
| fe93609c8d | |||
| ebe6782295 | |||
| 638d03846c | |||
| f57cd95ad5 | |||
| d725ded7b6 | |||
| a8dae96bb0 | |||
| e5b038ebcd | |||
| a005cd6e33 | |||
| 5536672e4b | |||
| a42bb9626d | |||
| 3c017af6a0 | |||
| 412dcaa744 | |||
| 51ce358734 | |||
| d09c45e362 | |||
| 86d2ecfaff | |||
| 68cbe46600 | |||
| c5282b059b | |||
| 4e71cc7d79 | |||
| 6be92ea6f7 | |||
| 325f1cf82e | |||
| 1714e2fd35 | |||
| 0a23e91329 | |||
| a059d03b37 | |||
| bd773c2f84 | |||
| d9544b5d0e | |||
| 4909c0f257 | |||
| 56cf59355f | |||
| 9f0b32e748 | |||
| 59c5770cf2 | |||
| 45be6e19f3 | |||
| 405e552efd | |||
| e44a291697 | |||
| d9c61f0492 | |||
| 68e704bf97 | |||
| afd37ca892 | |||
| 03b8077054 | |||
| 17abd50f69 | |||
| 2c33d8429e | |||
| cbebb70af6 | |||
| 6604d22ceb | |||
| ce59228688 | |||
| 386c385a08 | |||
| dd615c775d | |||
| 6176f0d9df | |||
| 33eef99d1f | |||
| 3e7d34c8ad | |||
| e302e5a85f | |||
| 4acf7aadbd | |||
| 227a481473 | |||
| a3016abf53 | |||
| 89632f3514 | |||
| c7ba791ff8 | |||
| db9c7de35c | |||
| 017ebb9b47 | |||
| 3f937605ac | |||
| b818ed0d08 | |||
| 0e0b858b69 | |||
| 0d0296d535 | |||
| 2a0fade893 | |||
| 30149c6ed4 | |||
| c84033213f | |||
| c4fc352db1 | |||
| 172214386a | |||
| b661c94915 | |||
| 7750f9581a | |||
| 451971b866 | |||
| d49597fe5f | |||
| bcdbb09c2c | |||
| ff90c83d66 | |||
| 248eacd042 | |||
| 7430e1fbc0 | |||
| b125d4d25f | |||
| 323c563684 | |||
| 9740891a2f | |||
| b5914f4587 | |||
| 3792ef5a50 | |||
| 7994da07be | |||
| 8858b16a25 | |||
| a64adbfffe | |||
| ba079bd9aa | |||
| db2b523762 | |||
| 4bd087fc83 | |||
| af8f2c47f3 | |||
| 2a0b500010 | |||
| c22a840d27 | |||
| f8547ad57c | |||
| 9898577135 | |||
| cab56b0479 | |||
| ff96f1b93c | |||
| 09c1e161e0 | |||
| 66c09fdc3b | |||
| 4d9f2bc9b1 | |||
| 38651fde74 | |||
| de917afc6f | |||
| 5e4e5147d9 | |||
| 8831dff61b | |||
| 83c46a4b54 | |||
| ea3d5ac563 | |||
| ce6b09291a | |||
| 2cb722b674 | |||
| 784d602600 | |||
| dd63681f94 | |||
| 15c99cfe77 | |||
| d5fa0a2fc5 | |||
| 0da9260994 | |||
| 56428e8a4e | |||
| 6058032807 | |||
| c0e178c19c | |||
| 541a624d48 | |||
| 2fd9b751b6 | |||
| 7deee31502 | |||
| 0afb67be7d | |||
| bedc9cf518 | |||
| b61a934c9f | |||
| 65ed7d7794 | |||
| 55cb68e5b5 | |||
| bc5a600d59 | |||
| 3d61345543 | |||
| b56d049103 | |||
| 27d7672273 | |||
| db8bf672f0 | |||
| f57e02849a | |||
| 03fdbd9f7b | |||
| 1da4c45979 | |||
| b9542b4908 | |||
| 00b4e4016c | |||
| cac72d73fb | |||
| b268818eda | |||
| e3a9324e8d | |||
| 8e002fc1ca | |||
| 61da920db0 | |||
| 1bce583cf3 | |||
| 5f7521027e | |||
| f24f2d9ca9 | |||
| be2fe160b3 | |||
| 8b80c70b9c | |||
| 9cc24c2c39 | |||
| 63ee03a7be | |||
| df2d1fd4f9 | |||
| 04b855235a | |||
| 72d8b54188 | |||
| 088a2e478c | |||
| 9f65fb5f90 | |||
| 1c689b10b9 | |||
| 82f9a25d88 | |||
| 8822bdbefa | |||
| 21cf3813be | |||
| adf8a61814 | |||
| 6964012464 | |||
| 5ed75731f2 | |||
| d8bba6ed3d | |||
| 0da174842e | |||
| 1533fcf8f6 | |||
| caa4b78a3f | |||
| 14352a05bc | |||
| bb5b52d998 | |||
| 301b0aba82 | |||
| c8e318df8c | |||
| 4aa1a3da8b | |||
| 680615eed8 | |||
| 1da6202e6e | |||
| 5e22b70b6d | |||
| 831738b29c | |||
| e78f20391e | |||
| 0a22e4606d | |||
| 02513818a9 | |||
| d641812c52 | |||
| a851496293 | |||
| 0bb30b6201 | |||
| bd2516eded | |||
| 35fd71eddf | |||
| e956cfed1c | |||
| cf7d42b3ea | |||
| 1ff69136a3 | |||
| aa9f8781ff | |||
| be168beba0 | |||
| 01a8bce2dd | |||
| 1f8009954c | |||
| becbd562d6 | |||
| 3a9e4bc357 | |||
| 3ce1be2a23 | |||
| fe4ff3325b | |||
| 82edb20e0c | |||
| 64a8c462f9 | |||
| 4ec97d0f7a | |||
| 016a80bb70 | |||
| ce66a400a7 | |||
| 50776875bb | |||
| bcb0e2ff1f | |||
| 1584768c80 | |||
| c29e23b2f1 | |||
| 57132204ec | |||
| 860fa719b2 | |||
| c89f7f8e5e | |||
| 13bb1c26fb | |||
| 86e7ae341f | |||
| 5fd685e07d | |||
| 93124c79ea | |||
| 08fbf92d8d | |||
| f08f82edfd | |||
| b57f0a2b7e | |||
| 5c85aa6e58 | |||
| 02568bb049 | |||
| d2613039ed | |||
| f97c22c341 | |||
| 2a24982bc4 | |||
| 6ecfbd1bde | |||
| f2dc9187f0 | |||
| b661097c51 | |||
| 0771295899 | |||
| 702816458c | |||
| e040c2b281 | |||
| 5a43db1c6d | |||
| dab7686656 | |||
| 38cf9fc6e6 | |||
| 083a35f970 | |||
| e12e4e8fb8 | |||
| d15a90899e | |||
| 237c2866e0 | |||
| 38d6284671 | |||
| 7355798e77 | |||
| 01af70f671 | |||
| 23695fb900 | |||
| 4b662d65b3 | |||
| 2bb99fa677 | |||
| 7b8eeb42f6 | |||
| 2029e3be20 | |||
| 6ee551c5e1 | |||
| b7e2b3e94a | |||
| c87a3b054c | |||
| f3c9b59856 | |||
| 4b73bedd57 | |||
| 8b86e43d51 | |||
| eade2d2af0 | |||
| f2299a562f | |||
| ef15dc883a | |||
| 3fcf6372e0 | |||
| 533cb77c50 | |||
| 681a9bb0e1 | |||
| 6c080dae55 | |||
| 670fb4de74 | |||
| bf199d3a74 | |||
| bd8dd48dee | |||
| 6d7318af43 | |||
| adfabca684 | |||
| 97c0d72e28 | |||
| 4ccae2d1de | |||
| b36c6ea13b | |||
| 39b8daeeec | |||
| 776b8d2f95 | |||
| c492352d50 | |||
| 8f1452acd1 | |||
| 8a2ba584ab | |||
| 2b27b8a230 | |||
| 383be5426e | |||
| 81b51c0791 | |||
| 227f28a6d2 | |||
| d8dc32ec4b | |||
| 0fc24c94cd | |||
| 24bd403e23 | |||
| 81eafde074 | |||
| a2ea0cea86 | |||
| 5ce5e1d2b0 | |||
| 901a51a9dd | |||
| 567bd8e330 | |||
| 812d5c3f58 | |||
| 9a5a03ef83 | |||
| 38d75f3aab | |||
| 03c505aaa7 | |||
| 179cac45f5 | |||
| 1591881bf2 | |||
| 7bbb2617c8 | |||
| 2ec65ba799 | |||
| 3dd7c09351 | |||
| afc6e8878d | |||
| 7eaf1246a0 | |||
| 645c44ae9c | |||
| 331b05c681 | |||
| 3abe80184a | |||
| 7618b13c6e | |||
| 351cd4bfd7 | |||
| 1154c7c1ab | |||
| 4a3e42f82e | |||
| 8ecf9717d6 | |||
| 3ca80b353b | |||
| 7d172e2211 | |||
| e934e2bd26 | |||
| 3177d19730 | |||
| 82104a8251 | |||
| e9a17374d1 | |||
| a31bd19b5a | |||
| c82dfef9b0 | |||
| 1181b13b5d | |||
| 688be0a404 | |||
| 33e6b63fe5 | |||
| 5d92eddc82 | |||
| 0324392cd8 | |||
| 01b0742bd4 | |||
| 02cf6ae46c | |||
| fcb2ccab99 | |||
| a38a5c67f1 | |||
| a45a96b3ee | |||
| f67104c81e | |||
| 86efa0aae6 | |||
| 2b84cb7be4 | |||
| 26df37e6ef | |||
| 554f96bc24 | |||
| 6482aa7c64 | |||
| 68491be847 | |||
| 6d941640a9 | |||
| 0ea3861d43 | |||
| a323a5e56d | |||
| 79caba22a7 | |||
| 30815bc8a2 | |||
| df3a69dcb7 | |||
| d4b7f66e15 | |||
| 8e767da29e | |||
| c0b15de504 | |||
| 1d5430937f | |||
| 9de88aa734 | |||
| 9e59819f06 | |||
| c60311617d | |||
| 7bc3dcdefd | |||
| 22edca610c | |||
| 6eac2ea7a5 | |||
| cd016bedce | |||
| 95ad3f16e1 | |||
| fb4d332d1a | |||
| a06b9294df | |||
| 221c6b8570 | |||
| eb95e2a97e | |||
| ec6769a6fc | |||
| 343a12626e | |||
| d11d77d328 | |||
| 20eb80fc9a | |||
| 071067effb | |||
| 89cc449808 | |||
| 1e59679ec2 | |||
| 8b8560a701 | |||
| 161ab5af16 | |||
| ab41594da2 | |||
| 80d4c11061 | |||
| e767796986 | |||
| dea7031b86 | |||
| 7e3d099d5b | |||
| 8b1bd5b7ff | |||
| d807840d57 | |||
| 4dbac79e86 | |||
| 5abc7f866a | |||
| 9dc2a01c2e | |||
| 6f0aa360d1 | |||
| 2f2ffe0aa4 | |||
| 4430f6c5fd | |||
| a75bc5d537 | |||
| 7c3b78b0a0 | |||
| 643556a366 | |||
| 1a598bdfd8 | |||
| e27f80fd85 | |||
| d922f003f6 | |||
| d17032dd8c | |||
| 4c03aabe0f | |||
| 3ae9341c52 | |||
| d10d660a4d | |||
| 107b0e1728 | |||
| 7769857f6a | |||
| cb97f37d13 | |||
| 6c92e73b46 | |||
| c1a01e91bf | |||
| 12e4724b19 | |||
| 52e74296de | |||
| 3b7e274c34 | |||
| db6abfb227 | |||
| 2adaca2521 | |||
| b6f39035f8 | |||
| cfd550451f | |||
| 60d3bddfbc | |||
| 9ff1bf6deb | |||
| 212c94ce98 | |||
| 77530b0c24 | |||
| 3e1246acff | |||
| 4c29f98292 | |||
| 5cc0d92eff | |||
| b875b68fc7 | |||
| a5ebbf8adb | |||
| 217385efb9 | |||
| f70c36baf9 | |||
| eda4ae9181 | |||
| d2e421c424 | |||
| 6da53536ca | |||
| 1da6aa40f8 | |||
| a913736235 | |||
| 124edeacaf | |||
| a216f4d089 | |||
| 17b0e0be84 | |||
| 81d8aed2e2 | |||
| 69418084bc | |||
| 593a4b65ea | |||
| 869d340f10 | |||
| 5d64d4a1e3 | |||
| cc3c5bdb8d | |||
| e1c4150dff | |||
| 755ca1af9b | |||
| 7d78b9cb2c | |||
| 91f802ac7a | |||
| 72cfea3a63 | |||
| a353872327 | |||
| f4d71d0b48 | |||
| a6299b0927 | |||
| 6e372d9e36 | |||
| ad8132ae11 | |||
| 0326c4964b | |||
| 5d39d7a1c8 | |||
| 937bb4c6ce | |||
| cf15a0913d | |||
| 33cf085692 | |||
| 3752225ed5 | |||
| 5cf572892f | |||
| 20ff5d5a3d | |||
| b88a47929f | |||
| 159392e738 | |||
| 2f03af51dd | |||
| cb76c149e1 | |||
| 6d7bf1c5d8 | |||
| ed2a239334 | |||
| 46c504e529 | |||
| 0e7e776862 | |||
| de12b701ac | |||
| b402df8b91 | |||
| dca457b1e0 | |||
| 72cff0ee11 | |||
| 09778e3f1b | |||
| 9f5d4180c9 | |||
| c8a7a53d70 | |||
| 223893fd5c | |||
| a58551af5b | |||
| f7dce4af88 | |||
| dff5c30172 | |||
| e8994dbc17 | |||
| aaba8a2a9a | |||
| 27056b6c37 | |||
| 9930de01b9 | |||
| 37f0ccdb7e | |||
| 43e61336cf | |||
| e383f6d8f8 | |||
| 6dbfdd970f | |||
| cfea0dac76 | |||
| cd021f49cd | |||
| e4ce467c0b | |||
| 6b4687a36b | |||
| c085bf0db4 | |||
| e0d4bd985e | |||
| 3339225fe8 | |||
| df33e179e5 | |||
| 624a7dff16 | |||
| 1d314ad4ce | |||
| 5a98b08ee8 | |||
| be863015bf | |||
| 8edf2c4507 | |||
| ded7e24f67 | |||
| e73bb07da0 | |||
| d9d02d526a | |||
| f272986903 | |||
| 988da8eaab | |||
| ea7f706aed | |||
| 52e3f1e269 | |||
| 4c9d2a989e | |||
| 022db5cbe3 | |||
| 42474c14aa | |||
| 63b2e7cc4f | |||
| 3edb735850 | |||
| eafbc3a468 | |||
| c1c3475e5a | |||
| 3bbf558883 | |||
| 1d68d9f71a | |||
| f2e8824242 | |||
| a0e47b5a64 | |||
| f7465f55e7 | |||
| 453bf6d73b | |||
| 3353a00641 | |||
| e388cb1643 | |||
| 741182c55f | |||
| 2efce35331 | |||
| d1dfbd95e2 | |||
| 4fc712119f | |||
| 1aee5b1ed8 | |||
| fefd3e6b29 | |||
| 9b43be9d9c | |||
| ea677154cb | |||
| 7f2802e75f | |||
| f924208881 | |||
| 6bea2961d9 | |||
| ac3a6033b9 | |||
| d7e6b01216 | |||
| 26aee7ff73 | |||
| 319c8fe32c | |||
| ce121ccea9 | |||
| ede9e78fbd | |||
| 7f1a4185b5 | |||
| 4c433fd75b | |||
| 53c2c4939e | |||
| 7d1464f0a1 | |||
| 8cc7fb9dd9 | |||
| 194cb1fb84 | |||
| 8ea106c091 | |||
| a6cb3313b0 | |||
| c6374b79b0 | |||
| 993adc8c82 | |||
| 9f4418e01d | |||
| 8bf1fb7b1d | |||
| f25beab6cb | |||
| 3c5300556a | |||
| 334c9daa6a | |||
| b52bb5016c | |||
| 310104f786 | |||
| 901449b0b1 | |||
| ed95679953 | |||
| a9f2766a8b | |||
| 4e777572c9 | |||
| 90a8595a40 | |||
| bf71eb448a | |||
| 2c29d272ad | |||
| 98aa2b9ff9 | |||
| ea33a04d00 | |||
| 9963fcf849 | |||
| ab93135b84 | |||
| 4a94cb85a2 | |||
| b7e6854189 | |||
| 2b8a54f8ff | |||
| a5dab0f61e | |||
| 824f1f24ff | |||
| f4f5c3128f | |||
| fdd42fd15f | |||
| 05a5e5eac1 | |||
| c8e1cfcbee | |||
| 869dda9a45 | |||
| e2c647ef91 | |||
| 05fdd94754 | |||
| 4a599b58ff | |||
| 05792826bc | |||
| fbf7ad4295 | |||
| 6c1c0c867e | |||
| 5c0eb92d81 | |||
| 1e88412a8f | |||
| f97ce6afef | |||
| 879476d8e0 | |||
| 6d584cf008 | |||
| 8efa299c65 | |||
| b6e7ad187a | |||
| 5ef73ca9aa | |||
| c50518a4ca | |||
| 4c98780bdb | |||
| 856fd2a33b | |||
| 581bbfe255 | |||
| b4e1edaa64 | |||
| 025f6407e2 | |||
| 10c0d83fa5 | |||
| 9a6ec14cbf | |||
| f77fec0c3c | |||
| 5d970cf5bd | |||
| 58e186440b | |||
| 6a39caa204 | |||
| 91f81d4c8e | |||
| 2b81b53dfa | |||
| dfd8c4e4b8 | |||
| c9c50e16ec | |||
| eff856d8e5 | |||
| 90a369f0b6 | |||
| ba05b4f024 | |||
| 3e90c3072a | |||
| 12946fbe46 | |||
| 70f923714c | |||
| 7cd394b0fb | |||
| 0bca098707 | |||
| d47a7f48bd | |||
| f181c60209 | |||
| 784c34f784 | |||
| 03fa5387ac | |||
| 1ea0b8a9df | |||
| 566e4a4196 | |||
| 61265604fb | |||
| 29909e7f44 | |||
| a95749f968 | |||
| 3232a83965 | |||
| c816bbdb6e | |||
| 4f25ab10e9 | |||
| f04099c5de | |||
| fdb82f5fb8 | |||
| 75d4c47384 | |||
| bd4c2b5245 | |||
| d60dba2de0 | |||
| 51a3043dfd | |||
| 5415ca2fa9 | |||
| 7098bcec8c | |||
| 6d65512531 | |||
| 3ed336fa0e | |||
| b26b1cd32f | |||
| 54db842d16 | |||
| 31a0085efb | |||
| 715355e148 | |||
| 55dfacea8d | |||
| e98cf39b47 | |||
| dda2f42e59 | |||
| bc46e148df | |||
| 55c744cc00 | |||
| 169a3217de | |||
| 905eee3198 | |||
| 8a11ed70e3 | |||
| db9d769db6 | |||
| 45150f1a52 | |||
| 0f07b2499c | |||
| 0a0383d9bd | |||
| 7e903fde5b | |||
| 1b3e50d0a3 | |||
| dc5ddf1c1b | |||
| 03cf635adc | |||
| 77ba8b81f8 | |||
| 0ce3f763db | |||
| 0226f5466c | |||
| 166ffe430a | |||
| 1905f87942 | |||
| d702113fb5 | |||
| 4f44a067b0 | |||
| 44818e6d14 | |||
| 325131dd30 | |||
| 38eeda6e8b | |||
| 1eb59fb9b5 | |||
| 1c60aa9769 | |||
| c2d3b23449 | |||
| fe2c3d08a0 | |||
| 7a0f62ce5a | |||
| 735e4cc3bc | |||
| e9dd9df0a0 | |||
| 032b15efe0 | |||
| 256826d9c7 | |||
| c273b29dec | |||
| e58b3ba46c | |||
| dd3b79b142 | |||
| 863f9560b0 | |||
| f870568e62 | |||
| 9e03136861 | |||
| 1b48603d07 | |||
| 4e6fb4b12c | |||
| c19a038d47 | |||
| 95bc013e97 | |||
| 7ddd547190 | |||
| 38e34093cf | |||
| d55eed803d | |||
| dd1ebb5915 | |||
| df1cdbe921 | |||
| 7846ea8acc | |||
| 1dc0d5f96a | |||
| 712ffb3e31 | |||
| 8f5813b003 | |||
| 337aab4f0d | |||
| 1155f91574 | |||
| 9fbb2ef46a | |||
| 4d88f8f7f4 | |||
| f33633efcb | |||
| 324d203f4e | |||
| 0cc997f531 | |||
| 2a4111868c | |||
| 123701ed76 | |||
| 28dce8783f | |||
| 3781b62d35 | |||
| 859f062267 | |||
| f85f2cae98 | |||
| 6644fd472c | |||
| 101b71ed02 | |||
| e808b7aac4 | |||
| f4f4ea1483 | |||
| 979f6f3d57 | |||
| cab9b6c862 | |||
| 4d935aa8b6 | |||
| ccfe485c06 | |||
| 1a800cf4df | |||
| fe7d942500 | |||
| f323e3c43f | |||
| 40e46dbca2 | |||
| 7d70865db0 | |||
| dbe99e5821 | |||
| 25fdf7e442 | |||
| a91e7f7202 | |||
| cdafb1b0c4 | |||
| 69db9f8a30 | |||
| c4228edf3c | |||
| 03e3ecdbd3 | |||
| 0626edbcdd | |||
| d03f4d76a2 | |||
| 710201fd51 | |||
| ab5a7b0d04 | |||
| 15425d01bc | |||
| 0642364a44 | |||
| cfdbfa3d58 | |||
| e9a6c0ba58 | |||
| 466b018319 | |||
| d16b6fe61e | |||
| 7a75fcda44 | |||
| 8d289ab01d | |||
| 363a9689b4 | |||
| 40c7497efe | |||
| 440a48b973 | |||
| f01887fb1e | |||
| 6ccb1ff114 | |||
| 1d2593208a | |||
| a7bdef69e2 | |||
| d9ea647925 | |||
| 6673289c33 | |||
| 822af4f7f5 | |||
| 3155c90396 | |||
| 1dbfedce4c | |||
| 3ab5b5a79d | |||
| 8a4bc72b34 | |||
| 6cbc14f2b2 | |||
| 75d0fc4749 | |||
| ea161af4e5 | |||
| 0bf5f97fe9 | |||
| b9f1bcf0e4 | |||
| 32b07e0940 | |||
| 99f087e5e1 | |||
| 22a4117109 | |||
| aaf7a88de7 | |||
| e0da99a973 | |||
| b2630a0920 | |||
| 67a0ae0246 | |||
| 5ae20459dd | |||
| d6dfcb11e8 | |||
| 8a84f87879 | |||
| 57341d8a1b | |||
| 40cf66a730 |
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
@ -6,3 +6,19 @@ updates:
|
|||||||
interval: daily
|
interval: daily
|
||||||
time: "10:00"
|
time: "10:00"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
|
ignore:
|
||||||
|
#only allow patch updates for locale-data - this has to be updated manually due to codegen
|
||||||
|
- dependency-name: pocketmine/locale-data
|
||||||
|
update-types:
|
||||||
|
- "version-update:semver-major"
|
||||||
|
- "version-update:semver-minor"
|
||||||
|
|
||||||
|
- package-ecosystem: gitsubmodule
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
|||||||
BIN
.github/readme/pocketmine-dark.png
vendored
Normal file
BIN
.github/readme/pocketmine-dark.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
.github/readme/pocketmine.png
vendored
Normal file
BIN
.github/readme/pocketmine.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
104
.github/workflows/build-docker-image.yml
vendored
Normal file
104
.github/workflows/build-docker-image.yml
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
name: Update Docker Hub images
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Update Docker Hub images
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Clone pmmp/PocketMine-Docker repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: pmmp/PocketMine-Docker
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Get tag names
|
||||||
|
id: tag-name
|
||||||
|
run: |
|
||||||
|
VERSION=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
|
||||||
|
echo TAG_NAME=$VERSION >> $GITHUB_OUTPUT
|
||||||
|
echo MAJOR=$(echo $VERSION | cut -d. -f1) >> $GITHUB_OUTPUT
|
||||||
|
echo MINOR=$(echo $VERSION | cut -d. -f1-2) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Download new release information
|
||||||
|
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
||||||
|
|
||||||
|
- name: Detect channel
|
||||||
|
id: channel
|
||||||
|
run: echo CHANNEL=$(jq -r '.channel' new_build_info.json) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Get name of Docker repository name
|
||||||
|
id: docker-repo-name
|
||||||
|
run: echo NAME=$(echo "${GITHUB_REPOSITORY,,}") >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Build image for tag
|
||||||
|
uses: docker/build-push-action@v4.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
||||||
|
|
||||||
|
- name: Build image for major tag
|
||||||
|
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||||
|
uses: docker/build-push-action@v4.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||||
|
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
||||||
|
|
||||||
|
- name: Build image for minor tag
|
||||||
|
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||||
|
uses: docker/build-push-action@v4.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||||
|
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
||||||
|
|
||||||
|
- name: Build image for latest tag
|
||||||
|
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||||
|
uses: docker/build-push-action@v4.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||||
|
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
||||||
101
.github/workflows/discord-release-embed.php
vendored
Normal file
101
.github/workflows/discord-release-embed.php
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine;
|
||||||
|
|
||||||
|
use pocketmine\utils\Internet;
|
||||||
|
use function dirname;
|
||||||
|
use function fwrite;
|
||||||
|
use function is_array;
|
||||||
|
use function json_decode;
|
||||||
|
use function json_encode;
|
||||||
|
use const JSON_THROW_ON_ERROR;
|
||||||
|
use const STDERR;
|
||||||
|
|
||||||
|
require dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-return array<string, mixed>
|
||||||
|
*/
|
||||||
|
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl, string $buildLogUrl, int $newsPingRoleId) : array{
|
||||||
|
return [
|
||||||
|
"content" => "<@&$newsPingRoleId> New PocketMine-MP release: $version ($channel)",
|
||||||
|
"embeds" => [
|
||||||
|
[
|
||||||
|
"title" => "New PocketMine-MP release: $version ($channel)",
|
||||||
|
"description" => <<<DESCRIPTION
|
||||||
|
$description
|
||||||
|
|
||||||
|
[Details]($detailsUrl) | [Source Code]($sourceUrl) | [Build Log]($buildLogUrl) | [Download]($pharDownloadUrl)
|
||||||
|
DESCRIPTION,
|
||||||
|
"url" => $detailsUrl,
|
||||||
|
"color" => $channel === "stable" ? 0x57ab5a : 0xc69026
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($argv) !== 6){
|
||||||
|
fwrite(STDERR, "Required arguments: github repo, version, API token, webhook URL, ping role ID\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
[, $repo, $tagName, $token, $hookURL, $newsPingRoleId] = $argv;
|
||||||
|
|
||||||
|
$result = Internet::getURL('https://api.github.com/repos/' . $repo . '/releases/tags/' . $tagName, extraHeaders: [
|
||||||
|
'Authorization: token ' . $token
|
||||||
|
]);
|
||||||
|
if($result === null){
|
||||||
|
fwrite(STDERR, "failed to access GitHub API\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if($result->getCode() !== 200){
|
||||||
|
fwrite(STDERR, "Error accessing GitHub API: " . $result->getCode() . "\n");
|
||||||
|
fwrite(STDERR, $result->getBody() . "\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$releaseInfoJson = json_decode($result->getBody(), true, JSON_THROW_ON_ERROR);
|
||||||
|
if(!is_array($releaseInfoJson)){
|
||||||
|
fwrite(STDERR, "Invalid release JSON returned from GitHub API\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$buildInfoPath = 'https://github.com/' . $repo . '/releases/download/' . $tagName . '/build_info.json';
|
||||||
|
|
||||||
|
$buildInfoResult = Internet::getURL($buildInfoPath, extraHeaders: [
|
||||||
|
'Authorization: token ' . $token
|
||||||
|
]);
|
||||||
|
if($buildInfoResult === null){
|
||||||
|
fwrite(STDERR, "missing build_info.json\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if($buildInfoResult->getCode() !== 200){
|
||||||
|
fwrite(STDERR, "error accessing build_info.json: " . $buildInfoResult->getCode() . "\n");
|
||||||
|
fwrite(STDERR, $buildInfoResult->getBody() . "\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$buildInfoJson = json_decode($buildInfoResult->getBody(), true, JSON_THROW_ON_ERROR);
|
||||||
|
if(!is_array($buildInfoJson)){
|
||||||
|
fwrite(STDERR, "invalid build_info.json\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$detailsUrl = $buildInfoJson["details_url"];
|
||||||
|
$sourceUrl = $buildInfoJson["source_url"];
|
||||||
|
$pharDownloadUrl = $buildInfoJson["download_url"];
|
||||||
|
$buildLogUrl = $buildInfoJson["build_log_url"];
|
||||||
|
|
||||||
|
$description = $releaseInfoJson["body"];
|
||||||
|
|
||||||
|
$discordPayload = generateDiscordEmbed($buildInfoJson["base_version"], $buildInfoJson["channel"], $description, $detailsUrl, $sourceUrl, $pharDownloadUrl, $buildLogUrl, (int) $newsPingRoleId);
|
||||||
|
|
||||||
|
$response = Internet::postURL(
|
||||||
|
$hookURL,
|
||||||
|
json_encode($discordPayload, JSON_THROW_ON_ERROR),
|
||||||
|
extraHeaders: ['Content-Type: application/json']
|
||||||
|
);
|
||||||
|
if($response?->getCode() !== 204){
|
||||||
|
fwrite(STDERR, "failed to send Discord webhook\n");
|
||||||
|
fwrite(STDERR, $response?->getBody() ?? "no response body\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
38
.github/workflows/discord-release-notify.yml
vendored
Normal file
38
.github/workflows/discord-release-notify.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
name: Notify Discord webhook of release
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup PHP and tools
|
||||||
|
uses: shivammathur/setup-php@2.24.0
|
||||||
|
with:
|
||||||
|
php-version: 8.1
|
||||||
|
|
||||||
|
- name: Restore Composer package cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/composer/files
|
||||||
|
~/.cache/composer/vcs
|
||||||
|
key: "composer-v2-cache-${{ hashFiles('./composer.lock') }}"
|
||||||
|
restore-keys: |
|
||||||
|
composer-v2-cache-
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
||||||
|
|
||||||
|
- name: Get actual tag name
|
||||||
|
id: tag-name
|
||||||
|
run: echo TAG_NAME=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{') >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Run webhook post script
|
||||||
|
run: php .github/workflows/discord-release-embed.php ${{ github.repository }} ${{ steps.tag-name.outputs.TAG_NAME }} ${{ github.token }} ${{ secrets.DISCORD_RELEASE_WEBHOOK }} ${{ secrets.DISCORD_NEWS_PING_ROLE_ID }}
|
||||||
29
.github/workflows/draft-release.yml
vendored
29
.github/workflows/draft-release.yml
vendored
@ -13,17 +13,17 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@2.12.0
|
uses: shivammathur/setup-php@2.24.0
|
||||||
with:
|
with:
|
||||||
php-version: 8.0
|
php-version: 8.1
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -40,7 +40,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
BUILD_NUMBER=$((2000+$GITHUB_RUN_NUMBER)) #to stay above jenkins
|
BUILD_NUMBER=$((2000+$GITHUB_RUN_NUMBER)) #to stay above jenkins
|
||||||
echo "Build number: $BUILD_NUMBER"
|
echo "Build number: $BUILD_NUMBER"
|
||||||
echo ::set-output name=BUILD_NUMBER::$BUILD_NUMBER
|
echo BUILD_NUMBER=$BUILD_NUMBER >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Minify BedrockData JSON files
|
- name: Minify BedrockData JSON files
|
||||||
run: php vendor/pocketmine/bedrock-data/.minify_json.php
|
run: php vendor/pocketmine/bedrock-data/.minify_json.php
|
||||||
@ -51,16 +51,18 @@ jobs:
|
|||||||
- name: Get PocketMine-MP release version
|
- name: Get PocketMine-MP release version
|
||||||
id: get-pm-version
|
id: get-pm-version
|
||||||
run: |
|
run: |
|
||||||
echo ::set-output name=PM_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BASE_VERSION;')
|
echo PM_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BASE_VERSION;') >> $GITHUB_OUTPUT
|
||||||
echo ::set-output name=MCPE_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;')
|
echo MCPE_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;') >> $GITHUB_OUTPUT
|
||||||
echo ::set-output name=PM_VERSION_SHORT::$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\VersionInfo::BASE_VERSION); array_pop($v); echo implode(".", $v);')
|
echo PM_VERSION_SHORT=$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\VersionInfo::BASE_VERSION); array_pop($v); echo implode(".", $v);') >> $GITHUB_OUTPUT
|
||||||
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);')
|
echo PM_VERSION_MD=$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);') >> $GITHUB_OUTPUT
|
||||||
|
echo CHANGELOG_SUFFIX=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;') >> $GITHUB_OUTPUT
|
||||||
|
echo PRERELEASE=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "false" : "true";') >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Generate build info
|
- name: Generate build info
|
||||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} > build_info.json
|
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} ${{ github.run_id }} > build_info.json
|
||||||
|
|
||||||
- name: Upload release artifacts
|
- name: Upload release artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: release_artifacts
|
name: release_artifacts
|
||||||
path: |
|
path: |
|
||||||
@ -69,15 +71,16 @@ jobs:
|
|||||||
${{ github.workspace }}/build_info.json
|
${{ github.workspace }}/build_info.json
|
||||||
|
|
||||||
- name: Create draft release
|
- name: Create draft release
|
||||||
uses: ncipollo/release-action@v1.8.6
|
uses: ncipollo/release-action@v1.12.0
|
||||||
with:
|
with:
|
||||||
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
|
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
|
||||||
commit: ${{ github.sha }}
|
commit: ${{ github.sha }}
|
||||||
draft: true
|
draft: true
|
||||||
|
prerelease: ${{ steps.get-pm-version.outputs.PRERELEASE }}
|
||||||
name: PocketMine-MP ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
name: PocketMine-MP ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||||
tag: ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
tag: ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
body: |
|
body: |
|
||||||
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
|
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
|
||||||
|
|
||||||
Please see the [changelogs](/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||||
|
|||||||
57
.github/workflows/main.yml
vendored
57
.github/workflows/main.yml
vendored
@ -13,14 +13,15 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.14]
|
php: [8.1.19, 8.2.6]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Build and prepare PHP cache
|
- name: Build and prepare PHP cache
|
||||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: ${{ matrix.php }}
|
||||||
install-path: "./bin"
|
install-path: "./bin"
|
||||||
|
pm-version-major: "5"
|
||||||
|
|
||||||
phpstan:
|
phpstan:
|
||||||
name: PHPStan analysis
|
name: PHPStan analysis
|
||||||
@ -31,22 +32,23 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.14]
|
php: [8.1.19, 8.2.6]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: ${{ matrix.php }}
|
||||||
install-path: "./bin"
|
install-path: "./bin"
|
||||||
|
pm-version-major: "5"
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -69,22 +71,23 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.14]
|
php: [8.1.19, 8.2.6]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: ${{ matrix.php }}
|
||||||
install-path: "./bin"
|
install-path: "./bin"
|
||||||
|
pm-version-major: "5"
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -107,24 +110,25 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.14]
|
php: [8.1.19, 8.2.6]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: ${{ matrix.php }}
|
||||||
install-path: "./bin"
|
install-path: "./bin"
|
||||||
|
pm-version-major: "5"
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -147,22 +151,23 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.14]
|
php: [8.1.19, 8.2.6]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: ${{ matrix.php }}
|
||||||
install-path: "./bin"
|
install-path: "./bin"
|
||||||
|
pm-version-major: "5"
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -180,6 +185,12 @@ jobs:
|
|||||||
- name: Regenerate KnownTranslation APIs
|
- name: Regenerate KnownTranslation APIs
|
||||||
run: php build/generate-known-translation-apis.php
|
run: php build/generate-known-translation-apis.php
|
||||||
|
|
||||||
|
- name: Regenerate RuntimeEnum(De)serializer
|
||||||
|
run: php build/generate-runtime-enum-serializers.php
|
||||||
|
|
||||||
|
- name: Regenerate BedrockData available files constants
|
||||||
|
run: php build/generate-bedrockdata-path-consts.php
|
||||||
|
|
||||||
- name: Verify code is unchanged
|
- name: Verify code is unchanged
|
||||||
run: |
|
run: |
|
||||||
git diff
|
git diff
|
||||||
@ -192,13 +203,15 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup PHP and tools
|
- name: Setup PHP and tools
|
||||||
uses: shivammathur/setup-php@2.15.0
|
uses: shivammathur/setup-php@2.24.0
|
||||||
with:
|
with:
|
||||||
php-version: 8.0
|
php-version: 8.1
|
||||||
tools: php-cs-fixer:3.2
|
tools: php-cs-fixer:3.16
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Run PHP-CS-Fixer
|
- name: Run PHP-CS-Fixer
|
||||||
run: php-cs-fixer fix --dry-run --diff --ansi
|
run: php-cs-fixer fix --dry-run --diff --ansi
|
||||||
|
|||||||
11
.github/workflows/support.yml
vendored
11
.github/workflows/support.yml
vendored
@ -8,12 +8,19 @@ jobs:
|
|||||||
support:
|
support:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/support-requests@v2
|
- uses: dessant/support-requests@v3
|
||||||
with:
|
with:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
support-label: "Support request"
|
support-label: "Support request"
|
||||||
issue-comment: >
|
issue-comment: >
|
||||||
Thanks, but this issue tracker is not intended for support requests. Please read the guidelines on [submitting an issue](https://github.com/pmmp/PocketMine-MP/blob/master/CONTRIBUTING.md#creating-an-issue).
|
Hi, we only accept **bug reports** on this issue tracker, but this issue looks like a support request.
|
||||||
|
|
||||||
|
|
||||||
|
Instead of creating an issue, try the following:
|
||||||
|
|
||||||
|
- Check our [Documentation](https://doc.pmmp.io) to see if you can find answers there
|
||||||
|
|
||||||
|
- Ask the community on our [Discord server](https://discord.gg/bmSAZBG) or our [Forums](https://forums.pmmp.io)
|
||||||
|
|
||||||
|
|
||||||
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bmSAZBG) | [Forums](https://forums.pmmp.io)
|
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bmSAZBG) | [Forums](https://forums.pmmp.io)
|
||||||
|
|||||||
3
.github/workflows/update-php-versions.php
vendored
3
.github/workflows/update-php-versions.php
vendored
@ -22,7 +22,8 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const VERSIONS = [
|
const VERSIONS = [
|
||||||
"8.0"
|
"8.1",
|
||||||
|
"8.2"
|
||||||
];
|
];
|
||||||
|
|
||||||
$workflowFile = file_get_contents(__DIR__ . '/main.yml');
|
$workflowFile = file_get_contents(__DIR__ . '/main.yml');
|
||||||
|
|||||||
61
.github/workflows/update-updater-api.yml
vendored
61
.github/workflows/update-updater-api.yml
vendored
@ -13,25 +13,70 @@ jobs:
|
|||||||
- name: Install jq
|
- name: Install jq
|
||||||
run: sudo apt update && sudo apt install jq -y
|
run: sudo apt update && sudo apt install jq -y
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: pmmp/update.pmmp.io
|
repository: ${{ github.repository_owner }}/update.pmmp.io
|
||||||
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
|
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
|
||||||
|
|
||||||
- name: Get actual tag name
|
- name: Get actual tag name
|
||||||
id: tag-name
|
id: tag-name
|
||||||
run: echo ::set-output name=TAG_NAME::$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
|
run: echo TAG_NAME=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{') >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Download new release information
|
- name: Download new release information
|
||||||
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
||||||
|
|
||||||
- name: Detect channel
|
- name: Detect channels
|
||||||
id: channel
|
id: channel
|
||||||
run: echo ::set-output name=CHANNEL::$(jq -r '.channel' new_build_info.json)
|
|
||||||
|
|
||||||
- name: Copy release information
|
|
||||||
run: |
|
run: |
|
||||||
cp new_build_info.json channels/${{ steps.channel.outputs.CHANNEL }}.json
|
CHANNEL=$(jq -r '.channel' new_build_info.json)
|
||||||
|
VERSION=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
echo CHANNEL=$CHANNEL >> $GITHUB_OUTPUT
|
||||||
|
if [ "$CHANNEL" == "stable" ]; then
|
||||||
|
echo MAJOR=$(echo $VERSION | cut -d. -f1) >> $GITHUB_OUTPUT
|
||||||
|
echo MINOR=$(echo $VERSION | cut -d. -f1-2) >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo MAJOR=$(echo $VERSION | cut -d. -f1)-$CHANNEL >> $GITHUB_OUTPUT
|
||||||
|
echo MINOR=$(echo $VERSION | cut -d. -f1-2)-$CHANNEL >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Update channel info
|
||||||
|
run: |
|
||||||
|
function version_id() {
|
||||||
|
major=$(echo $1 | cut -d. -f1)
|
||||||
|
minor=$(echo $1 | cut -d. -f2)
|
||||||
|
patch=$(echo $1 | cut -d. -f3)
|
||||||
|
echo $(((major * 1000000) + (minor * 1000) + patch))
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_channel() {
|
||||||
|
local target_file_name="$1"
|
||||||
|
local new_file_name="$2"
|
||||||
|
|
||||||
|
local old_version_id
|
||||||
|
local new_version_id
|
||||||
|
|
||||||
|
if [ ! -f "$target_file_name" ]; then
|
||||||
|
echo "Creating channel file: $target_file_name"
|
||||||
|
cp "$new_file_name" "$target_file_name"
|
||||||
|
else
|
||||||
|
old_version_id=$(version_id "$(jq -r '.base_version' "$target_file_name")")
|
||||||
|
new_version_id=$(version_id "$(jq -r '.base_version' "$new_file_name")")
|
||||||
|
|
||||||
|
echo "Old version ID: $old_version_id"
|
||||||
|
echo "New version ID: $new_version_id"
|
||||||
|
|
||||||
|
if [ $new_version_id -ge $old_version_id ]; then #suffixed versions will have the same version ID - assume they'll always be newer
|
||||||
|
echo "Updating channel file: $target_file_name ($old_version_id -> $new_version_id)"
|
||||||
|
cp "$new_file_name" "$target_file_name"
|
||||||
|
else
|
||||||
|
echo "Version $new_version_id is less than $old_version_id, not updating channel file: $target_file_name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_channel "channels/${{ steps.channel.outputs.CHANNEL }}.json" "new_build_info.json"
|
||||||
|
update_channel "channels/${{ steps.channel.outputs.MAJOR }}.json" "new_build_info.json"
|
||||||
|
update_channel "channels/${{ steps.channel.outputs.MINOR }}.json" "new_build_info.json"
|
||||||
rm new_build_info.json
|
rm new_build_info.json
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
|
|||||||
5
.idea/codeStyles/Project.xml
generated
5
.idea/codeStyles/Project.xml
generated
@ -62,6 +62,11 @@
|
|||||||
<option name="USE_TAB_CHARACTER" value="true" />
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
</indentOptions>
|
</indentOptions>
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="Shell Script">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="neon">
|
<codeStyleSettings language="neon">
|
||||||
<indentOptions>
|
<indentOptions>
|
||||||
<option name="USE_TAB_CHARACTER" value="true" />
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
|||||||
2
.idea/fileTemplates/includes/PHP File Header.php
generated
2
.idea/fileTemplates/includes/PHP File Header.php
generated
@ -16,6 +16,6 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@ -42,12 +42,41 @@ return (new PhpCsFixer\Config)
|
|||||||
'import_functions' => true,
|
'import_functions' => true,
|
||||||
'import_classes' => null,
|
'import_classes' => null,
|
||||||
],
|
],
|
||||||
|
'header_comment' => [
|
||||||
|
'comment_type' => 'comment',
|
||||||
|
'header' => <<<BODY
|
||||||
|
|
||||||
|
____ _ _ __ __ _ __ __ ____
|
||||||
|
| _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
| |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
| __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
|_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
@author PocketMine Team
|
||||||
|
@link http://www.pocketmine.net/
|
||||||
|
|
||||||
|
|
||||||
|
BODY,
|
||||||
|
'location' => 'after_open'
|
||||||
|
],
|
||||||
'indentation_type' => true,
|
'indentation_type' => true,
|
||||||
'logical_operators' => true,
|
'logical_operators' => true,
|
||||||
|
'native_constant_invocation' => [
|
||||||
|
'scope' => 'namespaced'
|
||||||
|
],
|
||||||
'native_function_invocation' => [
|
'native_function_invocation' => [
|
||||||
'scope' => 'namespaced',
|
'scope' => 'namespaced',
|
||||||
'include' => ['@all'],
|
'include' => ['@all'],
|
||||||
],
|
],
|
||||||
|
'new_with_braces' => [
|
||||||
|
'named_class' => true,
|
||||||
|
'anonymous_class' => false,
|
||||||
|
],
|
||||||
'no_closing_tag' => true,
|
'no_closing_tag' => true,
|
||||||
'no_empty_phpdoc' => true,
|
'no_empty_phpdoc' => true,
|
||||||
'no_extra_blank_lines' => true,
|
'no_extra_blank_lines' => true,
|
||||||
@ -66,6 +95,12 @@ return (new PhpCsFixer\Config)
|
|||||||
],
|
],
|
||||||
'sort_algorithm' => 'alpha'
|
'sort_algorithm' => 'alpha'
|
||||||
],
|
],
|
||||||
|
'phpdoc_align' => [
|
||||||
|
'align' => 'vertical',
|
||||||
|
'tags' => [
|
||||||
|
'param',
|
||||||
|
]
|
||||||
|
],
|
||||||
'phpdoc_line_span' => [
|
'phpdoc_line_span' => [
|
||||||
'property' => 'single',
|
'property' => 'single',
|
||||||
'method' => null,
|
'method' => null,
|
||||||
|
|||||||
10
BUILDING.md
10
BUILDING.md
@ -2,13 +2,13 @@
|
|||||||
## Pre-requisites
|
## Pre-requisites
|
||||||
- A bash shell (git bash is sufficient for Windows)
|
- A bash shell (git bash is sufficient for Windows)
|
||||||
- [`git`](https://git-scm.com) available in your shell
|
- [`git`](https://git-scm.com) available in your shell
|
||||||
- PHP 8.0 or newer available in your shell
|
- PHP 8.1 or newer available in your shell
|
||||||
- [`composer`](https://getcomposer.org) available in your shell
|
- [`composer`](https://getcomposer.org) available in your shell
|
||||||
|
|
||||||
## Custom PHP binaries
|
## Custom PHP binaries
|
||||||
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
||||||
|
|
||||||
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-8.0-Aggregate)
|
- [Prebuilt binaries](https://github.com/pmmp/PHP-Binaries/releases)
|
||||||
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
||||||
|
|
||||||
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
||||||
@ -29,11 +29,5 @@ Run `composer make-server` using your preferred PHP binary. It'll drop a `Pocket
|
|||||||
|
|
||||||
You can also use the `--out` option to change the output filename.
|
You can also use the `--out` option to change the output filename.
|
||||||
|
|
||||||
There is a bug in PHP that might cause an error which looks like this:
|
|
||||||
```
|
|
||||||
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
|
|
||||||
```
|
|
||||||
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 8.0.3.
|
|
||||||
|
|
||||||
## Running PocketMine-MP from source code
|
## Running PocketMine-MP from source code
|
||||||
Run `src/PocketMine.php` using your preferred PHP binary.
|
Run `src/PocketMine.php` using your preferred PHP binary.
|
||||||
|
|||||||
@ -18,6 +18,60 @@ Larger contributions like feature additions should be preceded by a [Change Prop
|
|||||||
## Other things you'll need
|
## Other things you'll need
|
||||||
- [git](https://git-scm.com/)
|
- [git](https://git-scm.com/)
|
||||||
|
|
||||||
|
## List of `pocketmine` namespaces which are in other repos
|
||||||
|
PocketMine-MP has several dependencies which are independent from the main server code. Most of them use the `pocketmine` namespace.
|
||||||
|
Some of these add extra classes to packages which already exist in PocketMine-MP.
|
||||||
|
|
||||||
|
Take a look at the table below if you can't find the class or function you're looking for.
|
||||||
|
|
||||||
|
| Source URL | Namespace, class or function |
|
||||||
|
|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| [pmmp/BedrockProtocol](https://github.com/pmmp/BedrockProtocol) | `pocketmine\network\mcpe\protocol` |
|
||||||
|
| [pmmp/BinaryUtils](https://github.com/pmmp/BinaryUtils) | `pocketmine\utils\BinaryDataException`</br>`pocketmine\utils\BinaryStream`</br>`pocketmine\utils\Binary` |
|
||||||
|
| [pmmp/ClassLoader](https://github.com/pmmp/`ClassLoader`) | `BaseClassLoader`</br>`ClassLoader`</br>`DynamicClassLoader` |
|
||||||
|
| [pmmp/Color](https://github.com/pmmp/Color) | `pocketmine\color` |
|
||||||
|
| [pmmp/ErrorHandler](https://github.com/pmmp/ErrorHandler) | `pocketmine\errorhandler` |
|
||||||
|
| [pmmp/Log](https://github.com/pmmp/Log) | `AttachableLogger`</br>`BufferedLogger`</br>`GlobalLogger`</br>`LogLevel`</br>`Logger`</br>`PrefixedLogger`</br>`SimpleLogger` |
|
||||||
|
| [pmmp/Math](https://github.com/pmmp/Math) | `pocketmine\math` |
|
||||||
|
| [pmmp/NBT](https://github.com/pmmp/NBT) | `pocketmine\nbt` |
|
||||||
|
| [pmmp/RakLibIpc](https://github.com/pmmp/RakLibIpc) | `raklib\server\ipc` |
|
||||||
|
| [pmmp/RakLib](https://github.com/pmmp/RakLib) | `raklib` |
|
||||||
|
| [pmmp/Snooze](https://github.com/pmmp/Snooze) | `pocketmine\snooze` |
|
||||||
|
| [pmmp/ext-chunkutils2](https://github.com/pmmp/ext-chunkutils2) | `pocketmine\world\format\LightArray`</br>`pocketmine\world\format\PalettedBlockArray`</br>`pocketmine\world\format\io\SubChunkConverter` |
|
||||||
|
| [pmmp/ext-morton](https://github.com/pmmp/ext-morton) | `morton2d_decode`</br>`morton2d_encode`</br>`morton3d_decode`</br>`morton3d_encode` |
|
||||||
|
| [pmmp/ext-libdeflate](https://github.com/pmmp/ext-libdeflate) | `libdeflate_deflate_compress`</br>`libdeflate_gzip_compress`</br>`libdeflate_zlib_compress` |
|
||||||
|
|
||||||
|
## Choosing a target branch
|
||||||
|
PocketMine-MP has three primary branches of development.
|
||||||
|
|
||||||
|
| Type of change | `stable` | `minor-next` | `major-next` |
|
||||||
|
|:--------------------------------------------------------------------------------------------|:--------:|:-------------------------------:|:------------:|
|
||||||
|
| Bug fixes | ✔️ | ✔️ | ✔️ |
|
||||||
|
| Improvements to API docs | ✔️ | ✔️ | ✔️ |
|
||||||
|
| Cleaning up code | ❌ | ✔️ | ✔️ |
|
||||||
|
| Changing code formatting or style | ❌ | ✔️ | ✔️ |
|
||||||
|
| Addition of new core features | ❌ | 🟡 Only if non-disruptive | ✔️ |
|
||||||
|
| Changing core behaviour (e.g. making something use threads) | ❌ | ✔️ | ✔️ |
|
||||||
|
| Addition of new configuration options | ❌ | 🟡 Only if optional | ✔️ |
|
||||||
|
| Addition of new API classes, methods or constants | ❌ | ✔️ | ✔️ |
|
||||||
|
| Deprecating API classes, methods or constants | ❌ | ✔️ | ✔️ |
|
||||||
|
| Adding optional parameters to an API method | ❌ | ✔️ | ✔️ |
|
||||||
|
| Changing API behaviour | ❌ | 🟡 Only if backwards-compatible | ✔️ |
|
||||||
|
| Removal of API | ❌ | ❌ | ✔️ |
|
||||||
|
| Backwards-incompatible API change (e.g. renaming a method) | ❌ | ❌ | ✔️ |
|
||||||
|
| Backwards-incompatible internals change (e.g. changing things in `pocketmine\network\mcpe`) | ❌ | ✔️ | ✔️ |
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
- **Non-disruptive** means that usage should not be significantly altered by the change.
|
||||||
|
- Examples of **non-disruptive** changes include adding new commands, or gameplay features like blocks and items.
|
||||||
|
- Examples of **disruptive** changes include changing the way the server is run, world format changes (since those require downtime for the user to convert their world).
|
||||||
|
- **API** includes all public and protected classes, functions and constants (unless marked as `@internal`).
|
||||||
|
- Private members are not part of the API, **unless in a trait**.
|
||||||
|
- The `pocketmine\network\mcpe` package is considered implicitly `@internal` in its entirety (see its [README](src/network/mcpe/README.md) for more details).
|
||||||
|
- Minecraft's protocol changes are considered necessary internal changes, and are **not** subject to the same rules.
|
||||||
|
- Protocol changes must always be released in a new minor version, since they disrupt user experience by requiring a client update.
|
||||||
|
- BC-breaking changes to the internal network API are allowed, but only in new minor versions. This ensures that plugins which use the internal network API will not break (though they shouldn't use such API anyway).
|
||||||
|
|
||||||
## Making a pull request
|
## Making a pull request
|
||||||
The basic procedure to create a pull request is:
|
The basic procedure to create a pull request is:
|
||||||
1. [Fork the repository on GitHub](https://github.com/pmmp/PocketMine-MP/fork). This gives you your own copy of the repository to make changes to.
|
1. [Fork the repository on GitHub](https://github.com/pmmp/PocketMine-MP/fork). This gives you your own copy of the repository to make changes to.
|
||||||
|
|||||||
16
README.md
16
README.md
@ -1,12 +1,19 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://pmmp.io"><img src="http://cdn.pocketmine.net/img/PocketMine-MP-h.png"></img></a><br>
|
<a href="https://pmmp.io">
|
||||||
|
<!--[if IE]>
|
||||||
|
<img src="https://github.com/pmmp/PocketMine-MP/blob/stable/.github/readme/pocketmine.png" alt="The PocketMine-MP logo" title="PocketMine" loading="eager" />
|
||||||
|
<![endif]-->
|
||||||
|
<picture>
|
||||||
|
<source srcset="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine-dark.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<img src="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine.png" loading="eager" />
|
||||||
|
</picture>
|
||||||
|
</a><br>
|
||||||
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/pmmp/PocketMine-MP/actions/workflows/main.yml"><img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" /></a>
|
<a href="https://github.com/pmmp/PocketMine-MP/actions/workflows/main.yml"><img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" /></a>
|
||||||
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/pmmp/PocketMine-MP?label=release&sort=semver"></a>
|
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/pmmp/PocketMine-MP?label=release&sort=semver"></a>
|
||||||
<a href="https://hub.docker.com/r/pmmp/pocketmine-mp"><img src="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image" alt="Docker image version (latest semver)" /></a>
|
|
||||||
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
|
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
|
||||||
<br>
|
<br>
|
||||||
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img alt="GitHub all releases" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/total?label=downloads%40total"></a>
|
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img alt="GitHub all releases" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/total?label=downloads%40total"></a>
|
||||||
@ -16,7 +23,7 @@
|
|||||||
## Getting started
|
## Getting started
|
||||||
- [Documentation](http://pmmp.readthedocs.org/)
|
- [Documentation](http://pmmp.readthedocs.org/)
|
||||||
- [Installation instructions](https://pmmp.readthedocs.io/en/rtfd/installation.html)
|
- [Installation instructions](https://pmmp.readthedocs.io/en/rtfd/installation.html)
|
||||||
- [Docker image](https://hub.docker.com/r/pmmp/pocketmine-mp)
|
- [Docker image](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp)
|
||||||
- [Plugin repository](https://poggit.pmmp.io/plugins)
|
- [Plugin repository](https://poggit.pmmp.io/plugins)
|
||||||
|
|
||||||
## Discussion/Help
|
## Discussion/Help
|
||||||
@ -27,7 +34,8 @@
|
|||||||
## For developers
|
## For developers
|
||||||
* [Building and running from source](BUILDING.md)
|
* [Building and running from source](BUILDING.md)
|
||||||
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
||||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
* [Latest release API documentation](https://apidoc.pmmp.io) - Doxygen API documentation generated for each release
|
||||||
|
* [Latest bleeding-edge API documentation](https://apidoc-dev.pmmp.io) - Doxygen API documentation generated weekly from `major-next` branch
|
||||||
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
|
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
|
||||||
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||||
* [Contributing Guidelines](CONTRIBUTING.md)
|
* [Contributing Guidelines](CONTRIBUTING.md)
|
||||||
|
|||||||
@ -7,10 +7,11 @@ GitHub is public and anyone can see the issues you post on the issue tracker, in
|
|||||||
|
|
||||||
**WARNING: You may put live servers at risk by reporting a vulnerability on the GitHub issue tracker.**
|
**WARNING: You may put live servers at risk by reporting a vulnerability on the GitHub issue tracker.**
|
||||||
|
|
||||||
**Contact us** by sending an email to [**team@pmmp.io**](mailto:team@pmmp.io?subject=Security%20Vulnerability%20in%20PocketMine-MP). Include the following information:
|
**Contact us** by sending an email to [**security@pmmp.io**](mailto:security@pmmp.io). Include the following information:
|
||||||
|
|
||||||
- Version of PocketMine-MP
|
- Version of PocketMine-MP
|
||||||
- Detailed description of the vulnerability (e.g. how to exploit it, what the effects are)
|
- Detailed description of the vulnerability (e.g. how to exploit it, what the effects are)
|
||||||
|
- Your GitHub username, if you wish to be credited for reporting the problem in the security advisory
|
||||||
|
|
||||||
Please note that we can't guarantee a reply to every email.
|
Please note that we can't guarantee a reply to every email.
|
||||||
|
|
||||||
|
|||||||
128
build/generate-bedrockdata-path-consts.php
Normal file
128
build/generate-bedrockdata-path-consts.php
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\build\generate_bedrockdata_path_consts;
|
||||||
|
|
||||||
|
use Symfony\Component\Filesystem\Path;
|
||||||
|
use function dirname;
|
||||||
|
use function fclose;
|
||||||
|
use function fopen;
|
||||||
|
use function fwrite;
|
||||||
|
use function is_file;
|
||||||
|
use function scandir;
|
||||||
|
use function str_replace;
|
||||||
|
use function strtoupper;
|
||||||
|
use const PHP_EOL;
|
||||||
|
use const pocketmine\BEDROCK_DATA_PATH;
|
||||||
|
use const SCANDIR_SORT_ASCENDING;
|
||||||
|
use const STDERR;
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
function constantify(string $permissionName) : string{
|
||||||
|
return strtoupper(str_replace([".", "-"], "_", $permissionName));
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = scandir(BEDROCK_DATA_PATH, SCANDIR_SORT_ASCENDING);
|
||||||
|
if($files === false){
|
||||||
|
fwrite(STDERR, "Couldn't find any files in " . BEDROCK_DATA_PATH . PHP_EOL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$consts = [];
|
||||||
|
|
||||||
|
foreach($files as $file){
|
||||||
|
if($file === '.' || $file === '..'){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if($file[0] === '.'){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$path = Path::join(BEDROCK_DATA_PATH, $file);
|
||||||
|
if(!is_file($path)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach([
|
||||||
|
'README.md',
|
||||||
|
'LICENSE',
|
||||||
|
'composer.json',
|
||||||
|
] as $ignored){
|
||||||
|
if($file === $ignored){
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$consts[] = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = fopen(dirname(__DIR__) . '/src/data/bedrock/BedrockDataFiles.php', 'wb');
|
||||||
|
if($output === false){
|
||||||
|
fwrite(STDERR, "Couldn't open output file" . PHP_EOL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fwrite($output, <<<'HEADER'
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\data\bedrock;
|
||||||
|
|
||||||
|
use const pocketmine\BEDROCK_DATA_PATH;
|
||||||
|
|
||||||
|
final class BedrockDataFiles{
|
||||||
|
private function __construct(){
|
||||||
|
//NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HEADER
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($consts as $constName => $fileName){
|
||||||
|
fwrite($output, "\tpublic const " . constantify($fileName) . " = BEDROCK_DATA_PATH . '/$fileName';\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($output, "}\n");
|
||||||
|
fclose($output);
|
||||||
|
|
||||||
|
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
||||||
197
build/generate-block-serializer-consts.php
Normal file
197
build/generate-block-serializer-consts.php
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\build\generate_block_serializer_consts;
|
||||||
|
|
||||||
|
use pocketmine\data\bedrock\block\BlockStateData;
|
||||||
|
use pocketmine\data\bedrock\block\BlockStateNames;
|
||||||
|
use pocketmine\data\bedrock\block\BlockStateStringValues;
|
||||||
|
use pocketmine\data\bedrock\block\BlockTypeNames;
|
||||||
|
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||||
|
use pocketmine\nbt\NbtException;
|
||||||
|
use pocketmine\network\mcpe\convert\BlockStateDictionary;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
|
use pocketmine\utils\Utils;
|
||||||
|
use function array_values;
|
||||||
|
use function asort;
|
||||||
|
use function count;
|
||||||
|
use function dirname;
|
||||||
|
use function explode;
|
||||||
|
use function fclose;
|
||||||
|
use function file_get_contents;
|
||||||
|
use function fopen;
|
||||||
|
use function fwrite;
|
||||||
|
use function is_string;
|
||||||
|
use function ksort;
|
||||||
|
use function mb_strtoupper;
|
||||||
|
use function sort;
|
||||||
|
use function strrpos;
|
||||||
|
use function strtoupper;
|
||||||
|
use function substr;
|
||||||
|
use const SORT_STRING;
|
||||||
|
use const STDERR;
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
class BlockPaletteReport{
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
* @phpstan-var array<string, string>
|
||||||
|
*/
|
||||||
|
public array $seenTypes = [];
|
||||||
|
/**
|
||||||
|
* @var string[][]
|
||||||
|
* @phpstan-var array<string, array<mixed, mixed>>
|
||||||
|
*/
|
||||||
|
public array $seenStateValues = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BlockStateData[] $states
|
||||||
|
* @phpstan-param list<BlockStateData> $states
|
||||||
|
*/
|
||||||
|
function generateBlockPaletteReport(array $states) : BlockPaletteReport{
|
||||||
|
$result = new BlockPaletteReport();
|
||||||
|
|
||||||
|
foreach($states as $stateData){
|
||||||
|
$name = $stateData->getName();
|
||||||
|
$result->seenTypes[$name] = $name;
|
||||||
|
foreach(Utils::stringifyKeys($stateData->getStates()) as $k => $v){
|
||||||
|
$result->seenStateValues[$k][$v->getValue()] = $v->getValue();
|
||||||
|
asort($result->seenStateValues[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($result->seenTypes, SORT_STRING);
|
||||||
|
ksort($result->seenStateValues, SORT_STRING);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function constifyMcId(string $id) : string{
|
||||||
|
return strtoupper(explode(":", $id, 2)[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateClassHeader(string $className) : string{
|
||||||
|
$backslashPos = strrpos($className, "\\");
|
||||||
|
if($backslashPos === false){
|
||||||
|
throw new AssumptionFailedError("Expected a namespaced class FQN");
|
||||||
|
}
|
||||||
|
$namespace = substr($className, 0, $backslashPos);
|
||||||
|
$shortName = substr($className, $backslashPos + 1);
|
||||||
|
return <<<HEADER
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace $namespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is generated automatically from the block palette for the current version. Do not edit it manually.
|
||||||
|
*/
|
||||||
|
final class $shortName{
|
||||||
|
private function __construct(){
|
||||||
|
//NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-param list<string> $seenIds
|
||||||
|
*/
|
||||||
|
function generateBlockIds(array $seenIds) : void{
|
||||||
|
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockTypeNames.php', 'wb'));
|
||||||
|
|
||||||
|
fwrite($output, generateClassHeader(BlockTypeNames::class));
|
||||||
|
|
||||||
|
foreach($seenIds as $id){
|
||||||
|
fwrite($output, "\tpublic const " . constifyMcId($id) . " = \"" . $id . "\";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($output, "}\n");
|
||||||
|
fclose($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateBlockStateNames(BlockPaletteReport $data) : void{
|
||||||
|
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockStateNames.php', 'wb'));
|
||||||
|
|
||||||
|
fwrite($output, generateClassHeader(BlockStateNames::class));
|
||||||
|
foreach(Utils::stringifyKeys($data->seenStateValues) as $state => $values){
|
||||||
|
$constName = mb_strtoupper($state, 'US-ASCII');
|
||||||
|
fwrite($output, "\tpublic const $constName = \"$state\";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($output, "}\n");
|
||||||
|
fclose($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateBlockStringValues(BlockPaletteReport $data) : void{
|
||||||
|
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockStateStringValues.php', 'wb'));
|
||||||
|
|
||||||
|
fwrite($output, generateClassHeader(BlockStateStringValues::class));
|
||||||
|
foreach(Utils::stringifyKeys($data->seenStateValues) as $stateName => $values){
|
||||||
|
$anyWritten = false;
|
||||||
|
sort($values, SORT_STRING);
|
||||||
|
foreach($values as $value){
|
||||||
|
if(!is_string($value)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$anyWritten = true;
|
||||||
|
$constName = mb_strtoupper($stateName . "_" . $value, 'US-ASCII');
|
||||||
|
fwrite($output, "\tpublic const $constName = \"$value\";\n");
|
||||||
|
}
|
||||||
|
if($anyWritten){
|
||||||
|
fwrite($output, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fwrite($output, "}\n");
|
||||||
|
fclose($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($argv) !== 2){
|
||||||
|
fwrite(STDERR, "This script regenerates BlockTypeNames, BlockStateNames and BlockStateStringValues from a given palette file\n");
|
||||||
|
fwrite(STDERR, "Required arguments: path to block palette file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$palettePath = $argv[1];
|
||||||
|
$paletteRaw = file_get_contents($palettePath);
|
||||||
|
if($paletteRaw === false){
|
||||||
|
fwrite(STDERR, "Failed to read block palette file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
$states = BlockStateDictionary::loadPaletteFromString($paletteRaw);
|
||||||
|
}catch(NbtException){
|
||||||
|
fwrite(STDERR, "Invalid block palette file $argv[1]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$report = generateBlockPaletteReport($states);
|
||||||
|
generateBlockIds(array_values($report->seenTypes));
|
||||||
|
generateBlockStateNames($report);
|
||||||
|
generateBlockStringValues($report);
|
||||||
|
|
||||||
|
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
||||||
@ -17,14 +17,14 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
if(count($argv) !== 5){
|
if(count($argv) !== 6){
|
||||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number>");
|
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number> <github actions run ID>\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,4 +40,5 @@ echo json_encode([
|
|||||||
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
|
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
|
||||||
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
|
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
|
||||||
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
|
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
|
||||||
|
"build_log_url" => "https://github.com/$argv[3]/actions/runs/$argv[5]",
|
||||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n";
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n";
|
||||||
|
|||||||
97
build/generate-item-type-names.php
Normal file
97
build/generate-item-type-names.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\build\generate_item_serializer_ids;
|
||||||
|
|
||||||
|
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||||
|
use pocketmine\network\mcpe\convert\ItemTypeDictionaryFromDataHelper;
|
||||||
|
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
|
||||||
|
use pocketmine\utils\Utils;
|
||||||
|
use function asort;
|
||||||
|
use function count;
|
||||||
|
use function dirname;
|
||||||
|
use function explode;
|
||||||
|
use function fclose;
|
||||||
|
use function file_get_contents;
|
||||||
|
use function fopen;
|
||||||
|
use function fwrite;
|
||||||
|
use function strtoupper;
|
||||||
|
use const SORT_STRING;
|
||||||
|
use const STDERR;
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
function constifyMcId(string $id) : string{
|
||||||
|
return strtoupper(explode(":", $id, 2)[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateItemIds(ItemTypeDictionary $dictionary) : void{
|
||||||
|
$ids = [];
|
||||||
|
foreach($dictionary->getEntries() as $entry){
|
||||||
|
if($entry->getNumericId() < 256){ //blockitems are serialized via BlockStateSerializer
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$ids[$entry->getStringId()] = $entry->getStringId();
|
||||||
|
}
|
||||||
|
asort($ids, SORT_STRING);
|
||||||
|
|
||||||
|
$file = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/item/ItemTypeNames.php', 'wb'));
|
||||||
|
|
||||||
|
fwrite($file, <<<'HEADER'
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\data\bedrock\item;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is generated automatically from the item type dictionary for the current version. Do not edit it manually.
|
||||||
|
*/
|
||||||
|
final class ItemTypeNames{
|
||||||
|
|
||||||
|
HEADER
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach(Utils::stringifyKeys($ids) as $id){
|
||||||
|
fwrite($file, "\tpublic const " . constifyMcId($id) . " = \"" . $id . "\";\n");
|
||||||
|
}
|
||||||
|
fwrite($file, "}\n");
|
||||||
|
fclose($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($argv) !== 2){
|
||||||
|
fwrite(STDERR, "This script regenerates ItemTypeNames from a given item dictionary file\n");
|
||||||
|
fwrite(STDERR, "Required argument: path to item type dictionary file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = file_get_contents($argv[1]);
|
||||||
|
if($raw === false){
|
||||||
|
fwrite(STDERR, "Failed to read item type dictionary file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dictionary = ItemTypeDictionaryFromDataHelper::loadFromString($raw);
|
||||||
|
generateItemIds($dictionary);
|
||||||
|
|
||||||
|
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ namespace pocketmine\build\generate_known_translation_apis;
|
|||||||
|
|
||||||
use pocketmine\lang\Translatable;
|
use pocketmine\lang\Translatable;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use Webmozart\PathUtil\Path;
|
use Symfony\Component\Filesystem\Path;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
use function count;
|
use function count;
|
||||||
use function dirname;
|
use function dirname;
|
||||||
@ -75,7 +75,7 @@ const SHARED_HEADER = <<<'HEADER'
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -29,17 +29,21 @@ use function count;
|
|||||||
use function dirname;
|
use function dirname;
|
||||||
use function file_get_contents;
|
use function file_get_contents;
|
||||||
use function file_put_contents;
|
use function file_put_contents;
|
||||||
|
use function fwrite;
|
||||||
use function implode;
|
use function implode;
|
||||||
|
use function is_dir;
|
||||||
use function ksort;
|
use function ksort;
|
||||||
use function mb_strtoupper;
|
use function mb_strtoupper;
|
||||||
use function preg_match;
|
use function preg_match;
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
|
use function str_ends_with;
|
||||||
use function str_replace;
|
use function str_replace;
|
||||||
use function substr;
|
|
||||||
use const SORT_STRING;
|
use const SORT_STRING;
|
||||||
|
use const STDERR;
|
||||||
|
|
||||||
if(count($argv) !== 2){
|
if(count($argv) !== 2){
|
||||||
die("Provide a path to process");
|
fwrite(STDERR, "Provide a path to process\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,29 +84,24 @@ function generateMethodAnnotations(string $namespaceName, array $members) : stri
|
|||||||
return implode("\n", $lines);
|
return implode("\n", $lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
function processFile(string $file) : void{
|
||||||
|
|
||||||
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){
|
|
||||||
if(substr($file, -4) !== ".php"){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$contents = file_get_contents($file);
|
$contents = file_get_contents($file);
|
||||||
if($contents === false){
|
if($contents === false){
|
||||||
throw new \RuntimeException("Failed to get contents of $file");
|
throw new \RuntimeException("Failed to get contents of $file");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(preg_match("/(*ANYCRLF)^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/(*ANYCRLF)^((final|abstract)\s+)?class /m', $contents) !== 1){
|
if(preg_match("/(*ANYCRLF)^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/(*ANYCRLF)^((final|abstract)\s+)?class /m', $contents) !== 1){
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
$shortClassName = basename($file, ".php");
|
$shortClassName = basename($file, ".php");
|
||||||
$className = $matches[1] . "\\" . $shortClassName;
|
$className = $matches[1] . "\\" . $shortClassName;
|
||||||
if(!class_exists($className)){
|
if(!class_exists($className)){
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
$reflect = new \ReflectionClass($className);
|
$reflect = new \ReflectionClass($className);
|
||||||
$docComment = $reflect->getDocComment();
|
$docComment = $reflect->getDocComment();
|
||||||
if($docComment === false || preg_match("/(*ANYCRLF)^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){
|
if($docComment === false || preg_match("/(*ANYCRLF)^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
echo "Found registry in $file\n";
|
echo "Found registry in $file\n";
|
||||||
|
|
||||||
@ -116,3 +115,18 @@ foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1],
|
|||||||
echo "No changes made to file $file\n";
|
echo "No changes made to file $file\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
if(is_dir($argv[1])){
|
||||||
|
/** @var string $file */
|
||||||
|
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){
|
||||||
|
if(!str_ends_with($file, ".php")){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
processFile($file);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
processFile($argv[1]);
|
||||||
|
}
|
||||||
|
|||||||
263
build/generate-runtime-enum-serializers.php
Normal file
263
build/generate-runtime-enum-serializers.php
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\build\generate_runtime_enum_serializers;
|
||||||
|
|
||||||
|
use pocketmine\block\utils\BellAttachmentType;
|
||||||
|
use pocketmine\block\utils\CopperOxidation;
|
||||||
|
use pocketmine\block\utils\CoralType;
|
||||||
|
use pocketmine\block\utils\DirtType;
|
||||||
|
use pocketmine\block\utils\DyeColor;
|
||||||
|
use pocketmine\block\utils\FroglightType;
|
||||||
|
use pocketmine\block\utils\LeverFacing;
|
||||||
|
use pocketmine\block\utils\MushroomBlockType;
|
||||||
|
use pocketmine\block\utils\SkullType;
|
||||||
|
use pocketmine\block\utils\SlabType;
|
||||||
|
use pocketmine\item\MedicineType;
|
||||||
|
use pocketmine\item\PotionType;
|
||||||
|
use pocketmine\item\SuspiciousStewType;
|
||||||
|
use function array_key_first;
|
||||||
|
use function array_keys;
|
||||||
|
use function array_map;
|
||||||
|
use function ceil;
|
||||||
|
use function count;
|
||||||
|
use function dirname;
|
||||||
|
use function file_put_contents;
|
||||||
|
use function implode;
|
||||||
|
use function ksort;
|
||||||
|
use function lcfirst;
|
||||||
|
use function log;
|
||||||
|
use function ob_get_clean;
|
||||||
|
use function ob_start;
|
||||||
|
use const SORT_STRING;
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $memberNames
|
||||||
|
* @phpstan-param list<string> $memberNames
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @phpstan-return list<string>
|
||||||
|
*/
|
||||||
|
function buildWriterFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{
|
||||||
|
$bits = getBitsRequired($memberNames);
|
||||||
|
$lines = [];
|
||||||
|
|
||||||
|
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
|
||||||
|
$lines[] = "\t\$this->writeInt($bits, match(\$value){";
|
||||||
|
|
||||||
|
foreach($memberNames as $key => $memberName){
|
||||||
|
$lines[] = "\t\t$memberName => $key,";
|
||||||
|
}
|
||||||
|
$lines[] = "\t\tdefault => throw new \pocketmine\utils\AssumptionFailedError(\"All $virtualTypeName cases should be covered\")";
|
||||||
|
$lines[] = "\t});";
|
||||||
|
$lines[] = "}";
|
||||||
|
|
||||||
|
return $lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $memberNames
|
||||||
|
* @phpstan-param list<string> $memberNames
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @phpstan-return list<string>
|
||||||
|
*/
|
||||||
|
function buildReaderFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{
|
||||||
|
$bits = getBitsRequired($memberNames);
|
||||||
|
$lines = [];
|
||||||
|
|
||||||
|
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
|
||||||
|
$lines[] = "\t\$value = match(\$this->readInt($bits)){";
|
||||||
|
|
||||||
|
foreach($memberNames as $key => $memberName){
|
||||||
|
$lines[] = "\t\t$key => $memberName,";
|
||||||
|
}
|
||||||
|
$lines[] = "\t\tdefault => throw new InvalidSerializedRuntimeDataException(\"Invalid serialized value for $virtualTypeName\")";
|
||||||
|
$lines[] = "\t};";
|
||||||
|
$lines[] = "}";
|
||||||
|
|
||||||
|
return $lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildInterfaceFunc(string $nativeTypeName, string $functionName) : string{
|
||||||
|
return "public function $functionName(\\$nativeTypeName &\$value) : void;";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $memberNames
|
||||||
|
* @phpstan-param list<string> $memberNames
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @phpstan-return list<string>
|
||||||
|
*/
|
||||||
|
function buildSizeCalculationFunc(string $nativeTypeName, string $functionName, array $memberNames) : array{
|
||||||
|
$lines = [];
|
||||||
|
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
|
||||||
|
$lines[] = "\t\$this->addBits(" . getBitsRequired($memberNames) . ");";
|
||||||
|
$lines[] = "}";
|
||||||
|
|
||||||
|
return $lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed[] $members
|
||||||
|
*/
|
||||||
|
function getBitsRequired(array $members) : int{
|
||||||
|
return (int) ceil(log(count($members), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param object[] $members
|
||||||
|
* @phpstan-param array<string, object> $members
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @phpstan-return list<string>
|
||||||
|
*/
|
||||||
|
function stringifyEnumMembers(array $members, string $enumClass) : array{
|
||||||
|
ksort($members, SORT_STRING);
|
||||||
|
return array_map(fn(string $enumCaseName) => "\\$enumClass::$enumCaseName()", array_keys($members));
|
||||||
|
}
|
||||||
|
|
||||||
|
$enumsUsed = [
|
||||||
|
BellAttachmentType::getAll(),
|
||||||
|
CopperOxidation::getAll(),
|
||||||
|
CoralType::getAll(),
|
||||||
|
DirtType::getAll(),
|
||||||
|
DyeColor::getAll(),
|
||||||
|
FroglightType::getAll(),
|
||||||
|
LeverFacing::getAll(),
|
||||||
|
MedicineType::getAll(),
|
||||||
|
MushroomBlockType::getAll(),
|
||||||
|
SkullType::getAll(),
|
||||||
|
SlabType::getAll(),
|
||||||
|
SuspiciousStewType::getAll(),
|
||||||
|
PotionType::getAll()
|
||||||
|
];
|
||||||
|
|
||||||
|
$readerFuncs = [
|
||||||
|
"" => [
|
||||||
|
"abstract protected function readInt(int \$bits) : int;"
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$writerFuncs = [
|
||||||
|
"" => [
|
||||||
|
"abstract protected function writeInt(int \$bits, int \$value) : void;"
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$interfaceFuncs = [];
|
||||||
|
$sizeCalculationFuncs = [
|
||||||
|
"" => [
|
||||||
|
"abstract protected function addBits(int \$bits) : void;"
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach($enumsUsed as $enumMembers){
|
||||||
|
if(count($enumMembers) === 0){
|
||||||
|
throw new \InvalidArgumentException("Enum members cannot be empty");
|
||||||
|
}
|
||||||
|
$reflect = new \ReflectionClass($enumMembers[array_key_first($enumMembers)]);
|
||||||
|
$virtualTypeName = $reflect->getShortName();
|
||||||
|
$nativeTypeName = $reflect->getName();
|
||||||
|
$functionName = lcfirst($virtualTypeName);
|
||||||
|
|
||||||
|
$stringifiedMembers = stringifyEnumMembers($enumMembers, $nativeTypeName);
|
||||||
|
$writerFuncs[$functionName] = buildWriterFunc(
|
||||||
|
$virtualTypeName,
|
||||||
|
$nativeTypeName,
|
||||||
|
$stringifiedMembers,
|
||||||
|
$functionName
|
||||||
|
);
|
||||||
|
$readerFuncs[$functionName] = buildReaderFunc(
|
||||||
|
$virtualTypeName,
|
||||||
|
$nativeTypeName,
|
||||||
|
$stringifiedMembers,
|
||||||
|
$functionName
|
||||||
|
);
|
||||||
|
$interfaceFuncs[$functionName] = [buildInterfaceFunc(
|
||||||
|
$nativeTypeName,
|
||||||
|
$functionName
|
||||||
|
)];
|
||||||
|
$sizeCalculationFuncs[$functionName] = buildSizeCalculationFunc(
|
||||||
|
$nativeTypeName,
|
||||||
|
$functionName,
|
||||||
|
$stringifiedMembers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[][] $functions
|
||||||
|
* @phpstan-param array<string, list<string>> $functions
|
||||||
|
*/
|
||||||
|
function printFunctions(array $functions, string $className, string $classType) : void{
|
||||||
|
ksort($functions, SORT_STRING);
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
echo <<<'HEADER'
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\data\runtime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is auto-generated. Do not edit it manually.
|
||||||
|
* @see build/generate-runtime-enum-serializers.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
HEADER;
|
||||||
|
|
||||||
|
echo "$classType $className{\n\n";
|
||||||
|
echo implode("\n\n", array_map(fn(array $functionLines) => "\t" . implode("\n\t", $functionLines), $functions));
|
||||||
|
echo "\n\n}\n";
|
||||||
|
|
||||||
|
file_put_contents(dirname(__DIR__) . '/src/data/runtime/' . $className . '.php', ob_get_clean());
|
||||||
|
}
|
||||||
|
|
||||||
|
printFunctions($writerFuncs, "RuntimeEnumSerializerTrait", "trait");
|
||||||
|
printFunctions($readerFuncs, "RuntimeEnumDeserializerTrait", "trait");
|
||||||
|
printFunctions($interfaceFuncs, "RuntimeEnumDescriber", "interface");
|
||||||
|
printFunctions($sizeCalculationFuncs, "RuntimeEnumSizeCalculatorTrait", "trait");
|
||||||
|
|
||||||
|
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
||||||
@ -17,12 +17,13 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\build\make_release;
|
namespace pocketmine\build\make_release;
|
||||||
|
|
||||||
|
use pocketmine\utils\Filesystem;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\utils\VersionString;
|
use pocketmine\utils\VersionString;
|
||||||
use pocketmine\VersionInfo;
|
use pocketmine\VersionInfo;
|
||||||
@ -30,17 +31,17 @@ use function array_keys;
|
|||||||
use function array_map;
|
use function array_map;
|
||||||
use function dirname;
|
use function dirname;
|
||||||
use function fgets;
|
use function fgets;
|
||||||
use function file_get_contents;
|
|
||||||
use function file_put_contents;
|
use function file_put_contents;
|
||||||
use function fwrite;
|
use function fwrite;
|
||||||
use function getopt;
|
use function getopt;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
use function max;
|
use function max;
|
||||||
|
use function preg_match;
|
||||||
use function preg_replace;
|
use function preg_replace;
|
||||||
use function sleep;
|
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
use function str_pad;
|
use function str_pad;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
|
use function strtolower;
|
||||||
use function system;
|
use function system;
|
||||||
use const STDERR;
|
use const STDERR;
|
||||||
use const STDIN;
|
use const STDIN;
|
||||||
@ -50,7 +51,7 @@ use const STR_PAD_LEFT;
|
|||||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
|
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
|
||||||
$versionInfo = Utils::assumeNotFalse(file_get_contents($versionInfoPath), $versionInfoPath . " should always exist");
|
$versionInfo = Filesystem::fileGetContents($versionInfoPath);
|
||||||
$versionInfo = preg_replace(
|
$versionInfo = preg_replace(
|
||||||
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
||||||
'$1const BASE_VERSION = "' . $newVersion . '";',
|
'$1const BASE_VERSION = "' . $newVersion . '";',
|
||||||
@ -102,22 +103,43 @@ function main() : void{
|
|||||||
$filteredOpts[$optName] = $optValue;
|
$filteredOpts[$optName] = $optValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$channel = $filteredOpts["channel"] ?? null;
|
||||||
if(isset($filteredOpts["current"])){
|
if(isset($filteredOpts["current"])){
|
||||||
$currentVer = new VersionString($filteredOpts["current"]);
|
$currentVer = new VersionString($filteredOpts["current"]);
|
||||||
}else{
|
}else{
|
||||||
$currentVer = new VersionString(VersionInfo::BASE_VERSION);
|
$currentVer = new VersionString(VersionInfo::BASE_VERSION);
|
||||||
}
|
}
|
||||||
if(isset($filteredOpts["next"])){
|
|
||||||
$nextVer = new VersionString($filteredOpts["next"]);
|
$nextVer = isset($filteredOpts["next"]) ? new VersionString($filteredOpts["next"]) : null;
|
||||||
|
|
||||||
|
$suffix = $currentVer->getSuffix();
|
||||||
|
if($suffix !== ""){
|
||||||
|
if($channel === "stable"){
|
||||||
|
fwrite(STDERR, "error: cannot release a suffixed build into the stable channel\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(preg_match('/^([A-Za-z]+)(\d+)$/', $suffix, $matches) !== 1){
|
||||||
|
echo "error: invalid current version suffix \"$suffix\"; aborting\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$nextVer ??= new VersionString(sprintf(
|
||||||
|
"%u.%u.%u-%s%u",
|
||||||
|
$currentVer->getMajor(),
|
||||||
|
$currentVer->getMinor(),
|
||||||
|
$currentVer->getPatch(),
|
||||||
|
$matches[1],
|
||||||
|
((int) $matches[2]) + 1
|
||||||
|
));
|
||||||
|
$channel ??= strtolower($matches[1]);
|
||||||
}else{
|
}else{
|
||||||
$nextVer = new VersionString(sprintf(
|
$nextVer ??= new VersionString(sprintf(
|
||||||
"%u.%u.%u",
|
"%u.%u.%u",
|
||||||
$currentVer->getMajor(),
|
$currentVer->getMajor(),
|
||||||
$currentVer->getMinor(),
|
$currentVer->getMinor(),
|
||||||
$currentVer->getPatch() + 1
|
$currentVer->getPatch() + 1
|
||||||
));
|
));
|
||||||
|
$channel ??= "stable";
|
||||||
}
|
}
|
||||||
$channel = $filteredOpts["channel"] ?? VersionInfo::BUILD_CHANNEL;
|
|
||||||
|
|
||||||
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
||||||
echo "$currentVer will be published on release channel \"$channel\".\n";
|
echo "$currentVer will be published on release channel \"$channel\".\n";
|
||||||
@ -137,9 +159,6 @@ function main() : void{
|
|||||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, $channel);
|
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, $channel);
|
||||||
systemWrapper('git add "' . $versionInfoPath . '"', "failed to stage changes for post-release commit");
|
systemWrapper('git add "' . $versionInfoPath . '"', "failed to stage changes for post-release commit");
|
||||||
systemWrapper('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"', "failed to create post-release commit");
|
systemWrapper('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"', "failed to create post-release commit");
|
||||||
echo "pushing changes in 5 seconds\n";
|
|
||||||
sleep(5);
|
|
||||||
systemWrapper('git push origin HEAD ' . $currentVer->getBaseVersion(), "failed to push changes to remote");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|||||||
Submodule build/php updated: bd329dba08...b1d5c0d737
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -40,12 +40,13 @@ use function rtrim;
|
|||||||
use function sprintf;
|
use function sprintf;
|
||||||
use function str_replace;
|
use function str_replace;
|
||||||
use function unlink;
|
use function unlink;
|
||||||
|
use const DIRECTORY_SEPARATOR;
|
||||||
use const PHP_EOL;
|
use const PHP_EOL;
|
||||||
|
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $strings
|
* @param string[] $strings
|
||||||
*
|
*
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -413,6 +413,7 @@ However, if we add `src-namespace-prefix: pmmp\TesterPlugin` to the `plugin.yml`
|
|||||||
|
|
||||||
### Command
|
### Command
|
||||||
- The following classes have been removed:
|
- The following classes have been removed:
|
||||||
|
- `PluginIdentifiableCommand` - use `PluginOwned` and `PluginOwnedTrait`
|
||||||
- `RemoteConsoleCommandSender`
|
- `RemoteConsoleCommandSender`
|
||||||
- The following API methods have signature changes:
|
- The following API methods have signature changes:
|
||||||
- `Command->setPermission()` argument is now mandatory (but still nullable).
|
- `Command->setPermission()` argument is now mandatory (but still nullable).
|
||||||
@ -1054,6 +1055,7 @@ However, if we add `src-namespace-prefix: pmmp\TesterPlugin` to the `plugin.yml`
|
|||||||
- `Player->addWindow()`: use `Player->setCurrentWindow()` instead
|
- `Player->addWindow()`: use `Player->setCurrentWindow()` instead
|
||||||
- `Player->dataPacket()`: replaced by `NetworkSession->sendDataPacket()`
|
- `Player->dataPacket()`: replaced by `NetworkSession->sendDataPacket()`
|
||||||
- `Player->getAddress()`: replaced by `NetworkSession->getIp()`
|
- `Player->getAddress()`: replaced by `NetworkSession->getIp()`
|
||||||
|
- `Player->getClientId()`: the client ID can be found in `PlayerInfo->getExtraData()`
|
||||||
- `Player->getPing()`: moved to `NetworkSession`
|
- `Player->getPing()`: moved to `NetworkSession`
|
||||||
- `Player->getPort()`: moved to `NetworkSession`
|
- `Player->getPort()`: moved to `NetworkSession`
|
||||||
- `Player->getWindow()`: use `Player->getCurrentWindow()` instead
|
- `Player->getWindow()`: use `Player->getCurrentWindow()` instead
|
||||||
@ -1069,6 +1071,8 @@ However, if we add `src-namespace-prefix: pmmp\TesterPlugin` to the `plugin.yml`
|
|||||||
- API version checks are now more strict. It is no longer legal to declare multiple minimum versions on the same major version. Doing so will now cause the plugin to fail to load with the message `Multiple minimum API versions found for some major versions`.
|
- API version checks are now more strict. It is no longer legal to declare multiple minimum versions on the same major version. Doing so will now cause the plugin to fail to load with the message `Multiple minimum API versions found for some major versions`.
|
||||||
- `plugin.yml` YAML commands loading is now internalized inside `PluginBase`.
|
- `plugin.yml` YAML commands loading is now internalized inside `PluginBase`.
|
||||||
- `PluginManager->registerEvent()` now has a simpler signature: `registerEvent(string $event, \Closure $handler, int $priority, Plugin $plugin, bool $handleCancelled = false)`. The provided closure must accept the specified event class as its only parameter. See [Event API changes](#event) for more details.
|
- `PluginManager->registerEvent()` now has a simpler signature: `registerEvent(string $event, \Closure $handler, int $priority, Plugin $plugin, bool $handleCancelled = false)`. The provided closure must accept the specified event class as its only parameter. See [Event API changes](#event) for more details.
|
||||||
|
- The following classes have been added:
|
||||||
|
- `PluginOwned`
|
||||||
- The following classes have been removed:
|
- The following classes have been removed:
|
||||||
- `PluginLogger`
|
- `PluginLogger`
|
||||||
- The following constants have been removed:
|
- The following constants have been removed:
|
||||||
@ -1620,3 +1624,28 @@ Released 21st January 2022.
|
|||||||
- Fixed ender pearls teleporting players when thrown by a player directly against a wall when cancelling `ProjectileLaunchEvent`.
|
- Fixed ender pearls teleporting players when thrown by a player directly against a wall when cancelling `ProjectileLaunchEvent`.
|
||||||
- Fixed collision box of brewing stand.
|
- Fixed collision box of brewing stand.
|
||||||
- Fixed break times and tool types of bamboo, nether wart blocks, infested stone and leaves.
|
- Fixed break times and tool types of bamboo, nether wart blocks, infested stone and leaves.
|
||||||
|
|
||||||
|
# 4.0.8
|
||||||
|
Released 25th January 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
|
||||||
|
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
|
||||||
|
|
||||||
|
# 4.0.9
|
||||||
|
Released 5th February 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
### Core
|
||||||
|
- The spawn chunk of the default world is no longer loaded during shutdown. Previously, it would attempt to find a safe spawn to teleport players to, only to unload the target world of that safe spawn and not use it.
|
||||||
|
- The spawn chunk of the default world is no longer loaded when unloading a non-default world containing zero players.
|
||||||
|
- Fixed chunk version `8` in Bedrock worlds being treated as corrupted. These appeared in worlds between 1.2.13 and 1.8.0.
|
||||||
|
|
||||||
|
### API
|
||||||
|
- Added missing bounds check to `Liquid->setDecay()`.
|
||||||
|
- Fixed `StringToItemParser` returning concrete instead of concrete powder when given `<color>_concrete_powder`.
|
||||||
|
|
||||||
|
### Gameplay
|
||||||
|
- Cobwebs now drop themselves when broken using shears.
|
||||||
|
- Fixed spectator players being able to drop items.
|
||||||
|
- Fixed collision shapes of Bell in different orientations.
|
||||||
|
|||||||
166
changelogs/4.1-beta.md
Normal file
166
changelogs/4.1-beta.md
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.0**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.1.0-BETA1
|
||||||
|
Released 22nd January 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
|
||||||
|
- Increased default maximum render distance to 16 chunks. Players with a render distance smaller than this will notice no difference.
|
||||||
|
- The setup wizard now prompts for a maximum render distance value.
|
||||||
|
- The setup wizard now prompts for an IPv6 port selection. Previously it would always use 19133.
|
||||||
|
- `chunk-ticking.disable-block-ticking` now accepts block names like those used in the `/give` command.
|
||||||
|
- The `/clear` command now behaves more like vanilla:
|
||||||
|
- The order of inventories is now the same as Bedrock.
|
||||||
|
- The cursor and offhand inventories are now cleared if necessary.
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
- `PlayerAuthInputPacket` is now used instead of `MovePlayerPacket` for processing movements. This improves position and rotation accuracy.
|
||||||
|
- `&&` and `||` are now always used instead of `and` and `or`.
|
||||||
|
- New version of `pocketmine/errorhandler` is used by this version, adding support for `ErrorToExceptionHandler::trap()`. This enables reliably capturing `E_WARNING` and `E_NOTICE` from functions such as `yaml_parse()` and friends.
|
||||||
|
- New dependency versions are required by this version:
|
||||||
|
- `pocketmine/bedrock-protocol` has been updated from 7.1.0 to [7.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/7.3.0%2Bbedrock-1.18.0).
|
||||||
|
- `pocketmine/errorhandler` has been updated from 0.3.0 to [0.6.0](https://github.com/pmmp/ErrorHandler/releases/tag/0.6.0).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- The following classes have been added:
|
||||||
|
- `Lectern`
|
||||||
|
- `Pumpkin`
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
|
||||||
|
- `VanillaBlocks::LECTERN()`
|
||||||
|
|
||||||
|
### Entity
|
||||||
|
- The following classes have been added:
|
||||||
|
- `animation\ItemEntityStackSizeChangeAnimation`
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `object\ItemEntity->isMergeable(object\ItemEntity $other) : bool`
|
||||||
|
- `object\ItemEntity->setStackSize(int $size) : void`
|
||||||
|
- `object\ItemEntity->tryMergeInto(object\ItemEntity $other) : bool`
|
||||||
|
- `ExperienceManager->canAttractXpOrbs() : bool`
|
||||||
|
- `ExperienceManager->setCanAttractXpOrbs(bool $v = true) : void`
|
||||||
|
- `Entity->getSize() : EntitySizeInfo`
|
||||||
|
- `Living->isGliding() : bool`
|
||||||
|
- `Living->isSwimming() : bool`
|
||||||
|
- `Living->setGliding(bool $value = true) : void`
|
||||||
|
- `Living->setSwimming(bool $value = true) : void`
|
||||||
|
- The following protected API methods have been added:
|
||||||
|
- `Entity->getBlocksIntersected(float $inset) : \Generator<int, Block, void, void>`
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- `BlockSpreadEvent` is now called when fire spreads to the positions of blocks it burns away.
|
||||||
|
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BlockMeltEvent` - called when ice or snow melts
|
||||||
|
- `ChestPairEvent` - called when two chests try to form a pair
|
||||||
|
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
|
||||||
|
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `SplashPotion->getType() : PotionType`
|
||||||
|
- `VanillaItems::AIR()`
|
||||||
|
- The following API methods have been deprecated:
|
||||||
|
- `ItemFactory::air()` - use `VanillaItems::AIR()` instead
|
||||||
|
|
||||||
|
### Player
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Player->hasBlockCollision() : bool`
|
||||||
|
- `Player->setHasBlockCollision(bool $value)` - allows controlling spectator-like no-clip behaviour without changing game mode
|
||||||
|
- `Player->toggleSwim(bool $swim) : bool` - called by the network system when the client tries to start/stop swimming
|
||||||
|
- `Player->toggleGlide(bool $glide) : bool` - called by the network system when the client tries to start/stop gliding
|
||||||
|
|
||||||
|
### Server
|
||||||
|
- The following public API constants have been added:
|
||||||
|
- `Server::DEFAULT_SERVER_NAME`
|
||||||
|
- `Server::DEFAULT_MAX_PLAYERS`
|
||||||
|
- `Server::DEFAULT_PORT_IPV4`
|
||||||
|
- `Server::DEFAULT_PORT_IPV6`
|
||||||
|
- `Server::DEFAULT_MAX_VIEW_DISTANCE`
|
||||||
|
|
||||||
|
### Utils
|
||||||
|
- Config parsing errors are now always represented by `ConfigLoadException` and include the path to the file in the message.
|
||||||
|
- Added `TextFormat::MINECOIN_GOLD`, and support for it to the various `TextFormat` methods.
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Utils::assumeNotFalse()` - static analysis crutch to silence PHPStan errors without using `ignoreErrors` or `@phpstan-ignore-line`, which are both too coarse.
|
||||||
|
- The following public API properties have been added:
|
||||||
|
- `Terminal::$COLOR_MINECOIN_GOLD`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `ConfigLoadException`
|
||||||
|
- Fixed `Random->nextSignedInt()` to actually return a signed int. Previously it would return any integer value between 0 and 4,294,957,295.
|
||||||
|
- Fixed `Random->nextSignedFloat()` to return a float between `-1.0` and `1.0`. Previously it would return any value between `0.0` and `2.0`.
|
||||||
|
- `VersionString->getNumber()` output is now structured differently to fix overflow issues caused by the old format.
|
||||||
|
|
||||||
|
### World
|
||||||
|
- The following classes have been added:
|
||||||
|
- `sound\ItemUseOnBlockSound`
|
||||||
|
- `sound\LecternPlaceBookSound`
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
### Blocks
|
||||||
|
- Fire now spreads.
|
||||||
|
- Implemented lectern blocks.
|
||||||
|
- Added missing sounds for hoeing grass and dirt.
|
||||||
|
- Added missing sounds for using a shovel on grass to create grass path.
|
||||||
|
- Pumpkins can now be carved using shears.
|
||||||
|
|
||||||
|
### Items
|
||||||
|
- Dropped items of the same type now merge with each other.
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
- Implemented player swimming.
|
||||||
|
|
||||||
|
# 4.1.0-BETA2
|
||||||
|
Released 27th January 2022.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `utils\BrewingStandSlot->getSlotNumber() : int`
|
||||||
|
- `utils\FurnaceType->getCookSound() : Sound`
|
||||||
|
- The following API constants have been added:
|
||||||
|
- `tile\BrewingStand::BREW_TIME_TICKS`
|
||||||
|
|
||||||
|
### Crafting
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
|
||||||
|
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
|
||||||
|
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
|
||||||
|
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BrewingRecipe`
|
||||||
|
- `PotionContainerChangeRecipe`
|
||||||
|
- `PotionTypeRecipe`
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
|
||||||
|
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
|
||||||
|
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
|
||||||
|
|
||||||
|
### World
|
||||||
|
#### Sound
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BlastFurnaceSound` - the sound made by a blast furnace during smelting
|
||||||
|
- `FurnaceSound` - the sound made by a regular furnace during cooking or smelting
|
||||||
|
- `PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
|
||||||
|
- `SmokerSound` - the sound made by a smoker during cooking
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
### Blocks
|
||||||
|
- Brewing stands can now be used for brewing potions.
|
||||||
|
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
|
||||||
|
- Added missing sounds for furnace, blast furnace and smoker.
|
||||||
|
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
|
||||||
|
- Cobwebs now drop themselves when mined using shears.
|
||||||
|
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
|
||||||
|
- Fixed block updating bug introduced by beta1 which caused crops and other plants to never grow.
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
- Added a workaround for client hitbox size bug after swimming which caused the player to be able to fit into one-block-tall gaps.
|
||||||
@ -6,8 +6,8 @@ Plugin developers should **only** update their required API to this version if y
|
|||||||
|
|
||||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
# 4.1.0-BETA1
|
# 4.1.0
|
||||||
Released 22nd January 2022.
|
Released 7th February 2022.
|
||||||
|
|
||||||
## General
|
## General
|
||||||
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
|
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
|
||||||
@ -35,6 +35,21 @@ Released 22nd January 2022.
|
|||||||
- The following public API methods have been added:
|
- The following public API methods have been added:
|
||||||
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
|
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
|
||||||
- `VanillaBlocks::LECTERN()`
|
- `VanillaBlocks::LECTERN()`
|
||||||
|
- `utils\BrewingStandSlot->getSlotNumber() : int`
|
||||||
|
- `utils\FurnaceType->getCookSound() : Sound`
|
||||||
|
- The following API constants have been added:
|
||||||
|
- `tile\BrewingStand::BREW_TIME_TICKS`
|
||||||
|
|
||||||
|
### Crafting
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
|
||||||
|
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
|
||||||
|
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
|
||||||
|
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BrewingRecipe`
|
||||||
|
- `PotionContainerChangeRecipe`
|
||||||
|
- `PotionTypeRecipe`
|
||||||
|
|
||||||
### Entity
|
### Entity
|
||||||
- The following classes have been added:
|
- The following classes have been added:
|
||||||
@ -58,9 +73,12 @@ Released 22nd January 2022.
|
|||||||
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
|
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
|
||||||
- The following classes have been added:
|
- The following classes have been added:
|
||||||
- `BlockMeltEvent` - called when ice or snow melts
|
- `BlockMeltEvent` - called when ice or snow melts
|
||||||
|
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
|
||||||
|
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
|
||||||
- `ChestPairEvent` - called when two chests try to form a pair
|
- `ChestPairEvent` - called when two chests try to form a pair
|
||||||
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
|
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
|
||||||
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
|
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
|
||||||
|
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
|
||||||
|
|
||||||
### Item
|
### Item
|
||||||
- The following public API methods have been added:
|
- The following public API methods have been added:
|
||||||
@ -99,8 +117,12 @@ Released 22nd January 2022.
|
|||||||
|
|
||||||
### World
|
### World
|
||||||
- The following classes have been added:
|
- The following classes have been added:
|
||||||
|
- `sound\BlastFurnaceSound` - the sound made by a blast furnace during smelting
|
||||||
|
- `sound\FurnaceSound` - the sound made by a regular furnace during cooking or smelting
|
||||||
- `sound\ItemUseOnBlockSound`
|
- `sound\ItemUseOnBlockSound`
|
||||||
- `sound\LecternPlaceBookSound`
|
- `sound\LecternPlaceBookSound`
|
||||||
|
- `sound\PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
|
||||||
|
- `sound\SmokerSound` - the sound made by a smoker during cooking
|
||||||
|
|
||||||
## Gameplay
|
## Gameplay
|
||||||
### Blocks
|
### Blocks
|
||||||
@ -109,9 +131,12 @@ Released 22nd January 2022.
|
|||||||
- Added missing sounds for hoeing grass and dirt.
|
- Added missing sounds for hoeing grass and dirt.
|
||||||
- Added missing sounds for using a shovel on grass to create grass path.
|
- Added missing sounds for using a shovel on grass to create grass path.
|
||||||
- Pumpkins can now be carved using shears.
|
- Pumpkins can now be carved using shears.
|
||||||
|
- Brewing stands can now be used for brewing potions.
|
||||||
|
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
|
||||||
|
- Added missing sounds for furnace, blast furnace and smoker.
|
||||||
|
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
|
||||||
|
- Cobwebs now drop themselves when mined using shears.
|
||||||
|
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
|
||||||
|
|
||||||
### Items
|
### Items
|
||||||
- Dropped items of the same type now merge with each other.
|
- Dropped items of the same type now merge with each other.
|
||||||
|
|
||||||
### Misc
|
|
||||||
- Implemented player swimming.
|
|
||||||
|
|||||||
53
changelogs/4.10.md
Normal file
53
changelogs/4.10.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.40**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.10.0
|
||||||
|
Released 26th October 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.40.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed incorrect command descriptions showing in `/help` when multiple commands use the same name. Previously, the most recently registered command would show, even though it wouldn't actually be invoked.
|
||||||
|
- Fixed splash potions affecting players in spectator mode.
|
||||||
|
- Fixed `World->addParticle()` sending particles to players who couldn't possibly see them when a list of targets was used.
|
||||||
|
- Fixed `World->addSound()` sending sounds to players who couldn't possibly hear them when a list of targets was used.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Improved type information available for various API methods in `World`.
|
||||||
|
|
||||||
|
# 4.10.1
|
||||||
|
Released 7th November 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed spawning in the void if spawn terrain in a world is solid at the default spawn position.
|
||||||
|
- Fixed totems of undying activating when the player has 1 HP remaining.
|
||||||
|
- Fixed durable items such as tools becoming unbreakable when in stacks larger than 1. Now, the durability correctly resets when the tool breaks.
|
||||||
|
- TPS below 12 now correctly shows as red in `/status`. Previously, it showed as orange due to a condition ordering bug.
|
||||||
|
- Improved handling of missing arguments in user-defined `pocketmine.yml` command aliases. Previously, missing arguments would be filled with an empty string, which caused a variety of unexpected behaviour.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Added validation for the array given to `BaseInventory->setContents()` to ensure that it contains only `Item` instances.
|
||||||
|
- Silenced `PlayerAuthInputPacket` spam when the session is in the "spawn response" state.
|
||||||
|
- Updated to PHPStan 1.9.
|
||||||
|
|
||||||
|
# 4.10.2
|
||||||
|
Released 25th November 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed crashes on macOS and Linux when using console colours without the `TERM` environment variable set.
|
||||||
|
- Fixed crashdumps not being generated when error messages contained invalid UTF-8 characters.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Clarified documentation of caching behaviour for `Internet::getIP()`.
|
||||||
|
- Added and improved documentation for many `Inventory` methods.
|
||||||
|
- Rewritten documentation for `PlayerCreationEvent` with warnings and more detail.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.
|
||||||
92
changelogs/4.11-beta.md
Normal file
92
changelogs/4.11-beta.md
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.40**
|
||||||
|
|
||||||
|
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.11.0-BETA1
|
||||||
|
Released 7th November 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Packet receive timings have now been split into two subcategories - Decode and Handle.
|
||||||
|
- Console command entry can now be disabled via the `console.enable-input` setting in `pocketmine.yml`.
|
||||||
|
- Best suited for headless servers (e.g. in a Docker container) where the console will never be used anyway.
|
||||||
|
- Disabling the console reader slightly reduces memory usage, because console reading currently requires an additional subprocess.
|
||||||
|
- Console command output now appears on the terminal only, and is not written to the log file.
|
||||||
|
- The output from console commands now appears with a `Command output |` prefix, instead of as a log message.
|
||||||
|
- Introduced validation for the `--data` and `--plugins` command line options.
|
||||||
|
- Encrypted resource packs are now supported, by means of adding a `.key` file alongside the pack in the `resource_packs` folder.
|
||||||
|
- e.g. `MyEncryptedPack.zip` -> `MyEncryptedPack.zip.key`
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Fixed supporting blocks of dead bush to be in line with vanilla.
|
||||||
|
- Sugarcane can now be grown using bonemeal on any part of the sugarcane. Previously, it only worked when used on the bottom block.
|
||||||
|
- Fixed modifier values for Instant Damage and Regeneration effects.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### General
|
||||||
|
- Plugins are now always disabled before their dependencies, to ensure that they are able to shutdown properly (e.g. a core plugin depending on a database plugin may want to save data to a DB during `onDisable()`).
|
||||||
|
- [`webmozart/path-util`](https://packagist.org/packages/webmozart/path-util) has been deprecated, and will be dropped in favour of [`symfony/filesystem`](https://packagist.org/packages/symfony/filesystem) in PM5.
|
||||||
|
- To prepare for this change, simply replace any usage of `Webmozart\PathUtil\Path` with `Symfony\Component\Filesystem\Path`, which is available as a dependency in this release.
|
||||||
|
|
||||||
|
### `pocketmine`
|
||||||
|
- The following API methods are now deprecated:
|
||||||
|
- `Server->getPlayerByPrefix()`
|
||||||
|
|
||||||
|
### `pocketmine\entity`
|
||||||
|
- `EntitySpawnEvent` and `ItemSpawnEvent` are now fired on the first tick after the entity is added to the world. Previously, these events were called directly from the entity constructor, making it impossible to get properties like velocity which are often set after the entity is created.
|
||||||
|
- The following API methods are now deprecated:
|
||||||
|
- `Living->hasLineOfSight()`
|
||||||
|
|
||||||
|
### `pocketmine\item`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Armor->clearCustomColor() : $this`
|
||||||
|
|
||||||
|
### `pocketmine\inventory\transaction`
|
||||||
|
- Introduced a `TransactionBuilder` class. This makes it less of a hassle to build an `InventoryTransaction` server-side, since the regular `Inventory` API methods can be used, rather than having to manually create `SlotChangeAction`s.
|
||||||
|
|
||||||
|
### `pocketmine\player`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Player->sendToastNotification(string $title, string $body) : void` - makes a grey box appear at the top of the player's screen containing the specified message
|
||||||
|
|
||||||
|
### `pocketmine\utils`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public static TextFormat::addBase(string $baseFormat, string $string) : string` - used for coloured log messages, changes the base formatting of a string by inserting the given formatting codes after every RESET code
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Improved performance of `ContainerTrait` dropping items on block destroy. (24e72ec109c1442b09558df89b6833cf2f2e0ec7)
|
||||||
|
- Avoid repeated calls to `Position->getWorld()` (use local variables). (2940547026db40ce76deb46e992870de3ead79ad)
|
||||||
|
- Revamped the way `InventoryManager` handles fake inventory slot mappings for stuff like crafting tables. (e90abecf38d9c57635fa0497514bba7e546a2469)
|
||||||
|
- Console polling is now done on the main thread (no longer a performance concern).
|
||||||
|
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie.
|
||||||
|
- `ConsoleCommandSender` is no longer responsible for relaying broadcast messages to `MainLogger`. A new `BroadcastLoggerForwarder` has been added, which is subscribed to the appropriate server broadcast channels in order to relay messages. This ensures that chat messages and command audit messages are logged.
|
||||||
|
- `DelegateInventory` now uses `WeakReference` to track its inventory listener. This allows the delegate to be reused.
|
||||||
|
|
||||||
|
# 4.11.0-BETA2
|
||||||
|
Released 13th November 2022.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
- The `chunk-ticking.per-tick` setting is now deprecated, and will be removed in a future release.
|
||||||
|
- The functionality of this setting has been removed, since it caused more problems than it solved.
|
||||||
|
- Setting it to zero will still disable chunk ticking (for now), but this should now be done by setting `chunk-ticking.tick-radius` to `0` instead.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Improved chunk random ticking:
|
||||||
|
- Removed the limit on chunks ticked per tick, and its associated config option is no longer respected.
|
||||||
|
- This change significantly improves crop and plant growth with large numbers of players, but may cause higher CPU usage.
|
||||||
|
- This limit was causing a linear decrease in chunk ticking speed with larger numbers of players, leading to worsened gameplay experience.
|
||||||
|
- Every chunk within the configured tick radius of a player will be ticked. Previously, chunks were randomly selected from the radius.
|
||||||
|
- Implemented Darkness effect.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\world`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public World->getChunkTickRadius() : int` - returns the world's simulation radius
|
||||||
|
- `public World->setChunkTickRadius(int $radius) : void` - sets the world's simulation radius
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.
|
||||||
106
changelogs/4.11.md
Normal file
106
changelogs/4.11.md
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.40**
|
||||||
|
|
||||||
|
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.11.0
|
||||||
|
Released 25th November 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Packet receive timings have now been split into two subcategories - Decode and Handle.
|
||||||
|
- Console command entry can now be disabled via the `console.enable-input` setting in `pocketmine.yml`.
|
||||||
|
- Best suited for headless servers (e.g. in a Docker container) where the console will never be used anyway.
|
||||||
|
- Disabling the console reader slightly reduces memory usage, because console reading currently requires an additional subprocess.
|
||||||
|
- Console command output now appears on the terminal only, and is not written to the log file.
|
||||||
|
- The output from console commands now appears with a `Command output |` prefix, instead of as a log message.
|
||||||
|
- User-defined `pocketmine.yml` custom commands now use a generic description which makes clear the command is config-defined.
|
||||||
|
- Introduced validation for the `--data` and `--plugins` command line options.
|
||||||
|
- Encrypted resource packs are now supported, by means of adding a `.key` file alongside the pack in the `resource_packs` folder.
|
||||||
|
- e.g. `MyEncryptedPack.zip` -> `MyEncryptedPack.zip.key`
|
||||||
|
- The file must contain the raw key bytes, and must not end with a newline.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
- The `chunk-ticking.per-tick` setting is now deprecated, and will be removed in a future release.
|
||||||
|
- The functionality of this setting has been removed, since it caused more problems than it solved.
|
||||||
|
- Setting it to zero will still disable chunk ticking (for now), but this should now be done by setting `chunk-ticking.tick-radius` to `0` instead.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Fixed supporting blocks of dead bush to be in line with vanilla.
|
||||||
|
- Sugarcane can now be grown using bonemeal on any part of the sugarcane. Previously, it only worked when used on the bottom block.
|
||||||
|
- Fixed missing sounds when adding, rotating, or removing items in item frames.
|
||||||
|
- Fixed modifier values for Instant Damage and Regeneration effects.
|
||||||
|
- Implemented Darkness effect.
|
||||||
|
- Improved chunk random ticking:
|
||||||
|
- Removed the limit on chunks ticked per tick, and its associated config option is no longer respected.
|
||||||
|
- This change significantly improves crop and plant growth with large numbers of players.
|
||||||
|
- This limit was causing a linear decrease in chunk ticking speed with larger numbers of players, leading to worsened gameplay experience.
|
||||||
|
- **Warning: This change will result in increased CPU usage if players are spread over a very large area.**
|
||||||
|
- Every chunk within the configured tick radius of a player will be ticked. Previously, chunks were randomly selected from the radius.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### General
|
||||||
|
- Plugins are now always disabled before their dependencies, to ensure that they are able to shutdown properly (e.g. a core plugin depending on a database plugin may want to save data to a DB during `onDisable()`).
|
||||||
|
- [`webmozart/path-util`](https://packagist.org/packages/webmozart/path-util) has been deprecated, and will be dropped in favour of [`symfony/filesystem`](https://packagist.org/packages/symfony/filesystem) in PM5.
|
||||||
|
- To prepare for this change, simply replace any usage of `Webmozart\PathUtil\Path` with `Symfony\Component\Filesystem\Path`, which is available as a dependency in this release.
|
||||||
|
|
||||||
|
### `pocketmine`
|
||||||
|
- The following API methods are now deprecated:
|
||||||
|
- `Server->getPlayerByPrefix()`
|
||||||
|
|
||||||
|
### `pocketmine\entity`
|
||||||
|
- `EntitySpawnEvent` and `ItemSpawnEvent` are now fired on the first tick after the entity is added to the world. Previously, these events were called directly from the entity constructor, making it impossible to get properties like velocity which are often set after the entity is created.
|
||||||
|
- The following API methods are now deprecated:
|
||||||
|
- `Living->hasLineOfSight()`
|
||||||
|
|
||||||
|
### `pocketmine\event\block`
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `BlockDeathEvent` - event called when coral or coral blocks die due to lack of water
|
||||||
|
|
||||||
|
### `pocketmine\item`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Armor->clearCustomColor() : $this`
|
||||||
|
|
||||||
|
### `pocketmine\inventory\transaction`
|
||||||
|
- Introduced a `TransactionBuilder` class. This makes it less of a hassle to build an `InventoryTransaction` server-side, since the regular `Inventory` API methods can be used, rather than having to manually create `SlotChangeAction`s.
|
||||||
|
|
||||||
|
### `pocketmine\lang`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Language->getAll() : array<string, string>`
|
||||||
|
|
||||||
|
### `pocketmine\player`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Player->sendToastNotification(string $title, string $body) : void` - makes a grey box appear at the top of the player's screen containing the specified message
|
||||||
|
|
||||||
|
### `pocketmine\utils`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public static TextFormat::addBase(string $baseFormat, string $string) : string` - used for coloured log messages, changes the base formatting of a string by inserting the given formatting codes after every RESET code
|
||||||
|
|
||||||
|
### `pocketmine\world`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public World->getChunkTickRadius() : int` - returns the world's simulation radius
|
||||||
|
- `public World->setChunkTickRadius(int $radius) : void` - sets the world's simulation radius
|
||||||
|
|
||||||
|
### `pocketmine\world\sound`
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `ItemFrameAddItemSound`
|
||||||
|
- `ItemFrameRemoveItemSound`
|
||||||
|
- `ItemFrameRotateItemSound`
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Improved performance of `ContainerTrait` dropping items on block destroy. ([link](https://github.com/pmmp/PocketMine-MP/commits/24e72ec109c1442b09558df89b6833cf2f2e0ec7))
|
||||||
|
- Avoid repeated calls to `Position->getWorld()` (use local variables). ([link](https://github.com/pmmp/PocketMine-MP/commit/2940547026db40ce76deb46e992870de3ead79ad))
|
||||||
|
- Revamped the way `InventoryManager` handles fake inventory slot mappings for stuff like crafting tables. ([link](https://github.com/pmmp/PocketMine-MP/commit/e90abecf38d9c57635fa0497514bba7e546a2469))
|
||||||
|
- Inventories are now mapped on a per-slot basis. This means that more than one inventory can be mapped to the same window ID, which is necessary for correctly handling "UI" inventories like crafting tables.
|
||||||
|
- `InventoryManager->getWindow(int $windowId) : ?Inventory` is replaced by `locateWindowAndSlot` (see below).
|
||||||
|
- Added `InventoryManager->locateWindowAndSlot(int $windowId, int $netSlotId) : array{Inventory, int}` - accepts a window ID and absolute slot ID, and returns the associated inventory and the slot relative to the inventory's own start (for use with `getItem()` etc.).
|
||||||
|
- Slot offset mapping for "UI" inventories is now handled in `InventoryManager->createComplexSlotMapping()` instead of in `TypeConverter`.
|
||||||
|
- Console polling is now done on the main thread (no longer a performance concern). ([link](https://github.com/pmmp/PocketMine-MP/commit/b3f03d7ae645de67a54b7300c09b94eeca16298e))
|
||||||
|
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie. ([link](https://github.com/pmmp/PocketMine-MP/commit/2585160ca2c4df5758b8b980331307402ff9f0fb))
|
||||||
|
- `ConsoleCommandSender` is no longer responsible for relaying broadcast messages to `MainLogger`. A new `BroadcastLoggerForwarder` has been added, which is subscribed to the appropriate server broadcast channels in order to relay messages. This ensures that chat messages and command audit messages are logged. ([link](https://github.com/pmmp/PocketMine-MP/commit/83e5b0adb6fa0dddec377182bb1c7945ac8f7820))
|
||||||
|
- `DelegateInventory` now uses `WeakReference` to track its inventory listener. This allows the delegate to be reused. ([link](https://github.com/pmmp/PocketMine-MP/commit/3feaa18f6c10c3a99c0deca75f57ec2d74b92ab4))
|
||||||
|
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.
|
||||||
119
changelogs/4.12.md
Normal file
119
changelogs/4.12.md
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.50**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.12.0
|
||||||
|
Released 30th November 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.50.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.12.1
|
||||||
|
Released 4th December 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed items glitching when dragging a stack of items across the crafting grid (desync issues).
|
||||||
|
|
||||||
|
# 4.12.2
|
||||||
|
Released 15th December 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Folder used for plugins (optionally specified by `--plugins`) is no longer required to be writable.
|
||||||
|
- Fixed broken writable check for server data folder (`is_writable()` broken on NFS and similar filesystems).
|
||||||
|
- `Filesystem::createLockFile()` exceptions now include more information about why the lock file could not be created.
|
||||||
|
- Fixed client-side item predictions not being rolled back when cancelling events such as `PlayerItemUseEvent`.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- Updated BedrockProtocol to [17.1.0](https://github.com/pmmp/BedrockProtocol/releases/tag/17.1.0+bedrock-1.19.50). This adds some missing `LevelSoundEvent` constants and fixes the values for `ContainerUIIds`.
|
||||||
|
|
||||||
|
# 4.12.3
|
||||||
|
Released 28th December 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed unauthenticated connections taking up player count slots, preventing players from joining.
|
||||||
|
- Fixed a possible crash in `World->tickChunk()` when plugins unload chunks during some events.
|
||||||
|
- `/gamemode` will now report a failure to change game mode if the player is already in the requested game mode.
|
||||||
|
|
||||||
|
# 4.12.4
|
||||||
|
Released 3rd January 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Added workarounds for an active exploit being used to deny service to servers.
|
||||||
|
|
||||||
|
# 4.12.5
|
||||||
|
Released 6th January 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Removed a workaround for an old client bug in custom form responses. The code contained a denial-of-service vulnerability.
|
||||||
|
|
||||||
|
# 4.12.6
|
||||||
|
Released 7th January 2023.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets.
|
||||||
|
|
||||||
|
# 4.12.7
|
||||||
|
Released 8th January 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed players getting kicked when the server lags for too long.
|
||||||
|
- Fixed players getting kicked when a debugging session is active and a breakpoint is hit.
|
||||||
|
|
||||||
|
# 4.12.8
|
||||||
|
Released 9th January 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed players getting kicked during PvP.
|
||||||
|
- Fixed players randomly getting kicked on Windows (improper rate limit handling wrt. 15ms timer resolution).
|
||||||
|
|
||||||
|
# 4.12.9
|
||||||
|
Released 16th January 2023.
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
### Timings
|
||||||
|
- Added new timers:
|
||||||
|
- `Server Mid-Tick Processing` - time spent processing Snooze interrupts between ticks (e.g. incoming network packets)
|
||||||
|
- `Server Tick Update Cycle` - time spent processing regular per-tick updates (e.g. entity movement, world updates, etc.) (`Server->tick()`)
|
||||||
|
- `Full Server Tick` timer now counts the total of `Server Mid-Tick Processing` and `Server Tick Update Cycle`, which generates more accurate performance metrics.
|
||||||
|
- Previously, this timer only counted the time spent during regular per-tick updates, and the time recorded by `Server Mid-Tick Processing` was not included in the report at all.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed blocks such as pressure plates being able to be placed without the correct supporting blocks if the clicked block was solid.
|
||||||
|
- Pressure plates now self-destruct when the block below them is removed.
|
||||||
|
- Fixed being unable to place blocks by clicking on the side of a bell (when the click doesn't result in ringing the bell).
|
||||||
|
- Fixed various rotation-aware blocks (e.g. stairs) behaving incorrectly when placed by clicking on the side of a replaceable block (e.g. tall grass).
|
||||||
|
- Fixed banners being able to be placed on top of blocks such as skulls.
|
||||||
|
- Fixed server-side collision boxes of walls and glass (which should connect, but didn't). Note that wall connections still don't show client side - this just fixes the collision boxes.
|
||||||
|
- Fixed `PlayerInteractEvent` with `LEFT_CLICK` sometimes firing before `BlockBreakEvent` when breaking blocks.
|
||||||
|
|
||||||
|
## Other changes
|
||||||
|
- Increased packet batch budget for player sessions.
|
||||||
|
|
||||||
|
# 4.12.10
|
||||||
|
Released 18th January 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed reported server load not including the time spent processing Snooze interrupts between ticks (e.g. incoming network packets).
|
||||||
|
- Fixed `Connection Handler` entry in timings report not including time spent receiving packets.
|
||||||
|
|
||||||
|
## Note about server load & performance
|
||||||
|
This version will report higher apparent server load than previous versions. The actual performance of the server is unchanged; the previous reported load was inaccurate.
|
||||||
|
These bugs have been present for nearly 5 years (ever since the first introduction of Snooze in 3.0.0).
|
||||||
|
|
||||||
|
# 4.12.11
|
||||||
|
Released 22nd January 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Code is now tested and analysed using PHP 8.2 in addition to 8.1 and 8.0.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed pthreads 5.0.0 incorrectly being treated as compatible.
|
||||||
|
- Fixed deprecation errors on PHP 8.2.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Updated documentation in `PlayerPreLoginEvent`.
|
||||||
94
changelogs/4.13-beta.md
Normal file
94
changelogs/4.13-beta.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.50**
|
||||||
|
|
||||||
|
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.13.0-BETA1
|
||||||
|
Released 18th January 2023.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Death message is now shown on the death screen when a player dies.
|
||||||
|
- Armour damage is now only increased if the armour reduced the damage taken.
|
||||||
|
- Implemented Swift Sneak enchantment.
|
||||||
|
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
|
||||||
|
|
||||||
|
## Localization
|
||||||
|
- Added localized description for the `/dumpmemory` command.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
- Added the following new core permissions:
|
||||||
|
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
|
||||||
|
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
|
||||||
|
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
|
||||||
|
- Replaced hardcoded strings with constants in various places.
|
||||||
|
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
|
||||||
|
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
|
||||||
|
- Added documentation for some internal methods.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\command`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
|
||||||
|
|
||||||
|
### `pocketmine\entity`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
|
||||||
|
|
||||||
|
### `pocketmine\event\world`
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `WorldSoundEvent` - called when a sound is played in a world
|
||||||
|
- `WorldParticleEvent` - called when a particle is spawned in a world
|
||||||
|
|
||||||
|
### `pocketmine\item`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
|
||||||
|
|
||||||
|
### `pocketmine\lang`
|
||||||
|
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
|
||||||
|
|
||||||
|
### `pocketmine\player`
|
||||||
|
- The following new interfaces have been added:
|
||||||
|
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
|
||||||
|
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
|
||||||
|
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
|
||||||
|
- The following API methods have been deprecated:
|
||||||
|
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
|
||||||
|
|
||||||
|
### `pocketmine\resourcepacks`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
|
||||||
|
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
|
||||||
|
|
||||||
|
### `pocketmine\utils`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
|
||||||
|
|
||||||
|
### `pocketmine\world`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning
|
||||||
94
changelogs/4.13.md
Normal file
94
changelogs/4.13.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.50**
|
||||||
|
|
||||||
|
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.13.0
|
||||||
|
Released 30th January 2023.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Death message is now shown on the death screen when a player dies.
|
||||||
|
- Armour damage is now only increased if the armour reduced the damage taken.
|
||||||
|
- Implemented Swift Sneak enchantment.
|
||||||
|
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
|
||||||
|
|
||||||
|
## Localization
|
||||||
|
- Added localized description for the `/dumpmemory` command.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
- Added the following new core permissions:
|
||||||
|
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
|
||||||
|
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
|
||||||
|
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
|
||||||
|
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
|
||||||
|
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
|
||||||
|
- Replaced hardcoded strings with constants in various places.
|
||||||
|
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
|
||||||
|
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
|
||||||
|
- Added documentation for some internal methods.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\command`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
|
||||||
|
|
||||||
|
### `pocketmine\entity`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
|
||||||
|
|
||||||
|
### `pocketmine\event\world`
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `WorldSoundEvent` - called when a sound is played in a world
|
||||||
|
- `WorldParticleEvent` - called when a particle is spawned in a world
|
||||||
|
|
||||||
|
### `pocketmine\item`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
|
||||||
|
|
||||||
|
### `pocketmine\lang`
|
||||||
|
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
|
||||||
|
|
||||||
|
### `pocketmine\player`
|
||||||
|
- The following new interfaces have been added:
|
||||||
|
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
|
||||||
|
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
|
||||||
|
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
|
||||||
|
- The following API methods have been deprecated:
|
||||||
|
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
|
||||||
|
|
||||||
|
### `pocketmine\resourcepacks`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
|
||||||
|
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
|
||||||
|
|
||||||
|
### `pocketmine\utils`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
|
||||||
|
|
||||||
|
### `pocketmine\world`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning
|
||||||
21
changelogs/4.14.md
Normal file
21
changelogs/4.14.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.60**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.14.0
|
||||||
|
Released 8th February 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.60.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.14.1
|
||||||
|
Released 15th February 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed all players getting kicked with `Receiving packets too fast` if a server tick takes longer than 5 seconds (e.g. because of autosave or GC).
|
||||||
|
- Fixed players getting kicked when linking with entities.
|
||||||
38
changelogs/4.15.md
Normal file
38
changelogs/4.15.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.62**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.15.0
|
||||||
|
Released 17th February 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.62.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.15.1
|
||||||
|
Released 21st February 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed dropped items not despawning when in non-ticking chunks.
|
||||||
|
- Fixed dropped items not despawning if an infinite pickup delay is set.
|
||||||
|
- Fixed infinite despawn delay (never despawn) being ignored for dropped items.
|
||||||
|
|
||||||
|
# 4.15.2
|
||||||
|
Released 24th February 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Accept Minecraft: Bedrock Edition 1.19.63 (identical protocol to 1.19.62, but different version due to Mojang mixup).
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed `World Population` timer sometimes not being stopped, causing strange results in timings reports.
|
||||||
|
|
||||||
|
# 4.15.3
|
||||||
|
Released 7th March 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed `/dumpmemory` crash when any object contained an `INF` or `NaN` float value.
|
||||||
|
- Updated RakLib for security fixes.
|
||||||
45
changelogs/4.16-beta.md
Normal file
45
changelogs/4.16-beta.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.62**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.16.0-BETA1
|
||||||
|
Released 4th March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added granular timings for packet encode, similar to the existing timings for packet decode.
|
||||||
|
- Timings now covers several areas of the network system which were previously not counted by network timings, but were counted by total timings. This provides a better insight into the performance of the network system.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
- Improved performance of packet batch handling by avoiding unnecessary object allocations.
|
||||||
|
- Improved performance of packet broadcasting when the broadcast size is below the batch threshold. Previously, the packets would be encoded once by every recipient, but now they are encoded once and then added to the send buffer of each session in their raw form.
|
||||||
|
- This change mostly affects servers with larger maps, where players are more widely distributed.
|
||||||
|
|
||||||
|
## Build system
|
||||||
|
- Added a new script `build/generate-bedrockdata-path-consts.php`, which must be run whenever BedrockData is updated. This script generates a class of constants with the file paths of all BedrockData files.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\entity`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Entity->getGravity() : float` - returns the entity's gravity acceleration in blocks/tick^2
|
||||||
|
- `public Entity->setGravity(float $gravity) : void` - sets the entity's gravity acceleration in blocks/tick^2
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Now uses [`pocketmine/bedrock-data` 2.0.0](https://github.com/pmmp/BedrockData/releases/tag/2.0.0+bedrock-1.19.60).
|
||||||
|
- This version is now used by both PM4 and PM5, reducing maintenance burden.
|
||||||
|
- Now uses [`pocketmine/bedrock-protocol` 19.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/19.3.0+bedrock-1.19.62).
|
||||||
|
- This version provides new APIs for handling packet batches which enabled improving performance and adding new features, such as detailed packet encode timings.
|
||||||
|
- Crafting recipes and creative inventory data are now loaded from `recipes/legacy_recipes.json` and `recipes/legacy_creativeitems.json` respectively. Previously, these were loaded from BedrockData directly, but BedrockData 2.0 now uses a format which can't be supported in 4.x without BC breaks.
|
||||||
|
- Added dependencies on [`pocketmine/bedrock-block-upgrade-schema`](https://github.com/pmmp/BedrockBlockUpgradeSchema) and [`pocketmine/bedrock-item-upgrade-schema`](https://github.com/pmmp/BedrockItemUpgradeSchema). These provide mapping files no longer present in BedrockData 2.0.
|
||||||
|
- Reduced and/or eliminated most usages of `PacketBatch`, since it only appeared as a throwaway object and was therefore wasting performance.
|
||||||
|
- `Compressor` now exposes `getCompressionThreshold()` instead of `willCompress()`, which allows determining whether a batch will be compressed without allocating it.
|
||||||
|
- Added `pocketmine\data\bedrock\BedrockDataFiles`, an auto-generated class of constants with the file paths of all BedrockData files. This makes it easier to locate usages, detect unused files and avoid typos.
|
||||||
|
|
||||||
|
# 4.16.0-BETA2
|
||||||
|
Released 4th March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Fixed incorrect release channel for 4.16.0-BETA1.
|
||||||
41
changelogs/4.16.md
Normal file
41
changelogs/4.16.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.62**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.16.0
|
||||||
|
Released 7th March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added granular timings for packet encode, similar to the existing timings for packet decode.
|
||||||
|
- Split `Player Network Send - Compression` timings into two timers, one for `Session Buffer` compression and one for `Broadcast` compression.
|
||||||
|
- Timings now covers several areas of the network system which were previously not counted by network timings, but were counted by total timings. This provides a better insight into the performance of the network system.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
- Improved performance of packet batch handling by avoiding unnecessary object allocations.
|
||||||
|
- Improved performance of packet broadcasting when the broadcast size is below the batch threshold. Previously, the packets would be encoded once by every recipient, but now they are encoded once and then added to the send buffer of each session in their raw form.
|
||||||
|
- This change mostly affects servers with larger maps, where players are more widely distributed.
|
||||||
|
- Improved performance of packet broadcasting when the broadcast has only one recipient (allow the session to compress the packet with the rest of its buffer).
|
||||||
|
|
||||||
|
## Build system
|
||||||
|
- Added a new script `build/generate-bedrockdata-path-consts.php`, which must be run whenever BedrockData is updated. This script generates a class of constants with the file paths of all BedrockData files.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\entity`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public Entity->getGravity() : float` - returns the entity's gravity acceleration in blocks/tick^2
|
||||||
|
- `public Entity->setGravity(float $gravity) : void` - sets the entity's gravity acceleration in blocks/tick^2
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Now uses [`pocketmine/bedrock-data` 2.0.0](https://github.com/pmmp/BedrockData/releases/tag/2.0.0+bedrock-1.19.60).
|
||||||
|
- This version is now used by both PM4 and PM5, reducing maintenance burden.
|
||||||
|
- Now uses [`pocketmine/bedrock-protocol` 19.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/19.3.0+bedrock-1.19.62).
|
||||||
|
- This version provides new APIs for handling packet batches which enabled improving performance and adding new features, such as detailed packet encode timings.
|
||||||
|
- Crafting recipes and creative inventory data are now loaded from `recipes/legacy_recipes.json` and `recipes/legacy_creativeitems.json` respectively. Previously, these were loaded from BedrockData directly, but BedrockData 2.0 now uses a format which can't be supported in 4.x without BC breaks.
|
||||||
|
- Added dependencies on [`pocketmine/bedrock-block-upgrade-schema`](https://github.com/pmmp/BedrockBlockUpgradeSchema) and [`pocketmine/bedrock-item-upgrade-schema`](https://github.com/pmmp/BedrockItemUpgradeSchema). These provide mapping files no longer present in BedrockData 2.0.
|
||||||
|
- Reduced and/or eliminated most usages of `PacketBatch`, since it only appeared as a throwaway object and was therefore wasting performance.
|
||||||
|
- `Compressor` now exposes `getCompressionThreshold()` instead of `willCompress()`, which allows determining whether a batch will be compressed without allocating it.
|
||||||
|
- Added `pocketmine\data\bedrock\BedrockDataFiles`, an auto-generated class of constants with the file paths of all BedrockData files. This makes it easier to locate usages, detect unused files and avoid typos.
|
||||||
39
changelogs/4.17.md
Normal file
39
changelogs/4.17.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.70**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.17.0
|
||||||
|
Released 14th March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.70.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.17.1
|
||||||
|
Released 22nd March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Docker images for PocketMine-MP are now published on [GitHub Container Registry](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp). The Docker Hub images will stop being maintained in the future.
|
||||||
|
- Updated translations.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed server crash on empty packets in certain cases.
|
||||||
|
- Fixed mushroom blocks dropping the wrong items when broken with a silk-touch tool.
|
||||||
|
- Fixed mushroom blocks giving the wrong items when block-picked.
|
||||||
|
- Fixed missing ability flag `PRIVILEGED_BUILDER`.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- `update-updater-api.yml` workflow now uses `github.repository_owner` to make it easier to test the workflow on forks.
|
||||||
|
- Added version-specific channels to `update.pmmp.io`, such as `4`, `4.18-beta`, `4.17`, etc.
|
||||||
|
- Replaced deprecated `::set-output` commands in GitHub Actions workflows.
|
||||||
|
- `build/make-release.php` no longer automatically pushes changes, to avoid accidents when testing release workflows on forks.
|
||||||
|
|
||||||
|
# 4.17.2
|
||||||
|
Released 29th March 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed players being unable to join due to the appearance of a new `x5t` field in the JWT header of Xbox Live authentication tokens.
|
||||||
91
changelogs/4.18-alpha.md
Normal file
91
changelogs/4.18-alpha.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.70**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||||
|
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||||
|
|
||||||
|
### Alpha release warning
|
||||||
|
Alpha releases are **experimental**. Features introduced in these releases are subject to change or removal.
|
||||||
|
|
||||||
|
APIs which existed **prior** to this version will continue to work as normal, so plugins which use them will continue to work.
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
This version makes changes to the internal network system to improve server performance and reduce memory usage.
|
||||||
|
|
||||||
|
While these changes don't affect non-internal API, they are still significant enough to warrant a new minor version, as they may break plugins which use the internal network API (not recommended).
|
||||||
|
|
||||||
|
# 4.18.0-ALPHA1
|
||||||
|
Released 16th March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Improved server performance in congested areas of the world (lots of players and/or entities in the same area).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\event\server`
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `DataPacketDecodeEvent` - called before a packet is decoded by a `NetworkSession`; useful to mitigate DoS attacks if PocketMine-MP hasn't been patched against new bugs yet
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Introduced new system for broadcasting entity events to network sessions.
|
||||||
|
- This change improves performance when lots of players and/or entities are in the same area.
|
||||||
|
- New interface `EntityEventBroadcaster` and class `StandardEntityEventBroadcaster` have been added to implement this.
|
||||||
|
- All entity-specific `on*()` and `sync*()` methods have been removed from `NetworkSession` (BC break).
|
||||||
|
- `NetworkSession` now accepts an `EntityEventBroadcaster` instance in its constructor.
|
||||||
|
- `NetworkBroadcastUtils::broadcastEntityEvent()` can be used to efficiently broadcast events to unique broadcasters shared by several network sessions.
|
||||||
|
- All network sessions now share the same `PacketSerializerContext` and `PacketBroadcaster` by default.
|
||||||
|
- Previously, every session had its own context, meaning that broadcast optimisations were not used, causing significant performance losses compared to 3.x.
|
||||||
|
- This change improves performance in congested areas by allowing reuse of previously encoded packet buffers for all sessions sharing the same context.
|
||||||
|
- Packet broadcasts are automatically encoded separately per unique `PacketSerializerContext` instance. This allows, for example, a multi-version fork to have a separate context for each protocol version, to ensure maximum broadcast efficiency while encoding different packets for different versions.
|
||||||
|
- `PacketSerializerContext` is now passed in `NetworkSession::__construct()`, instead of being created by the session.
|
||||||
|
- `StandardPacketBroadcaster` is now locked to a single `PacketSerializer` context, reducing complexity.
|
||||||
|
- Introduced `NetworkBroadcastUtils::broadcastPackets()`, replacing `Server->broadcastPackets()`.
|
||||||
|
- `Server->broadcastPackets()` has been deprecated. It will be removed in a future version.
|
||||||
|
|
||||||
|
# 4.18.0-ALPHA2
|
||||||
|
Released 21st March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Included more sections of the network system in Player Network Send timings.
|
||||||
|
- Changed the names of some timings to make them more user-friendly.
|
||||||
|
- Removed packet IDs from `receivePacket` and `sendPacket` timings, as they were not very useful.
|
||||||
|
- Added new specialized timers for the following:
|
||||||
|
- Item entity base ticking (merging)
|
||||||
|
- Player movement processing
|
||||||
|
- Entity movement processing (collision checking section)
|
||||||
|
- Projectile movement (all)
|
||||||
|
- Projectile movement processing (ray tracing section)
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\crafting`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `CraftingManager->getCraftingRecipeIndex() : array<int, CraftingRecipe>` - returns a list of all crafting recipes
|
||||||
|
- `CraftingManager->getCraftingRecipeFromIndex(int $index) : ?CraftingRecipe` - returns the crafting recipe at the given index, or null if it doesn't exist
|
||||||
|
|
||||||
|
### `pocketmine\inventory\transaction`
|
||||||
|
- The following API methods have changed signatures:
|
||||||
|
- `CraftingTransaction->__construct()` now accepts additional arguments `?CraftingRecipe $recipe = null, ?int $repetitions = null`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `TransactionBuilderInventory->getActualInventory() : Inventory` - returns the actual inventory that this inventory is a proxy for
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
### Network
|
||||||
|
- Introduced support for the `ItemStackRequest` Minecraft: Bedrock network protocol.
|
||||||
|
- This fixes a large number of inventory- and crafting-related bugs.
|
||||||
|
- This also improves server security by closing off many code pathways that might have been used for exploits. `TypeConverter->netItemStackToCore()` is no longer used in server code, and remains for tool usage only.
|
||||||
|
- This system is also significantly more bandwidth-efficient and has lower overhead than the legacy system.
|
||||||
|
- This now opens the gateway to easily implement lots of gameplay features which have been missing for a long time, such as enchanting, anvils, looms, and more.
|
||||||
|
- Significant changes have been made to `pocketmine\network\mcpe\InventoryManager` internals. These shouldn't affect plugins, but may affect plugins which use internal network API.
|
||||||
|
- **No changes have been made to the plugin `InventoryTransaction` API**.
|
||||||
|
- This system has been implemented as a shim for the existing PocketMine-MP transaction system to preserve plugin compatibility. Plugins using `InventoryTransactionEvent` should continue to work seamlessly.
|
||||||
|
- The `InventoryTransaction` API will be redesigned in a future major version to make use of the new information provided by the `ItemStackRequest` system.
|
||||||
|
- `InventoryTransactionPacket` is no longer sent by the client for "regular" inventory actions. However, it is still sent when dropping items, interacting with blocks, and using items.
|
||||||
|
- Inventory slot and content syncing is now buffered until the end of the tick. This reduces outbound network usage when the client performs multiple transactions in a single tick (e.g. crafting a stack of items).
|
||||||
|
- Renamed some `InventoryManager` internal properties to make them easier to understand.
|
||||||
|
- `TypeConverter->createInventoryAction()` has been removed.
|
||||||
|
- Packet batch limit has been lowered to `100` packets. With the introduction of `ItemStackRequest`, this is more than sufficient for normal gameplay.
|
||||||
|
|
||||||
|
### Other
|
||||||
|
- Use `Vector3::zero()` instead of `new Vector3()` in some places.
|
||||||
123
changelogs/4.18.md
Normal file
123
changelogs/4.18.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.70**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||||
|
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
This version significantly improves server performance with many players and/or entities by making changes to the internal network system.
|
||||||
|
|
||||||
|
It also introduces support for the newer `ItemStackRequest` protocol, which fixes many bugs and improves server security.
|
||||||
|
|
||||||
|
While these changes don't affect non-internal API, they are still significant enough to warrant a new minor version, as they may break plugins which use the internal network API (not recommended).
|
||||||
|
|
||||||
|
# 4.18.0
|
||||||
|
Released 25th March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Significantly improved server performance in congested areas of the world (lots of players and/or entities in the same area).
|
||||||
|
- Included more sections of the network system in `Player Network Send` performance timings.
|
||||||
|
- Changed the names of some performance timings to make them more user-friendly.
|
||||||
|
- Removed packet IDs from `receivePacket` and `sendPacket` performance timings, as they were not very useful.
|
||||||
|
- Added new specialized performance timings for the following:
|
||||||
|
- Item entity base ticking (merging)
|
||||||
|
- Player movement processing
|
||||||
|
- Entity movement processing (collision checking section)
|
||||||
|
- Projectile movement (all)
|
||||||
|
- Projectile movement processing (ray tracing section)
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\crafting`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `CraftingManager->getCraftingRecipeIndex() : array<int, CraftingRecipe>` - returns a list of all crafting recipes
|
||||||
|
- `CraftingManager->getCraftingRecipeFromIndex(int $index) : ?CraftingRecipe` - returns the crafting recipe at the given index, or null if it doesn't exist
|
||||||
|
|
||||||
|
### `pocketmine\event\server`
|
||||||
|
- The following new classes have been added:
|
||||||
|
- `DataPacketDecodeEvent` - called before a packet is decoded by a `NetworkSession`; useful to mitigate DoS attacks if PocketMine-MP hasn't been patched against new bugs yet
|
||||||
|
|
||||||
|
### `pocketmine\inventory\transaction`
|
||||||
|
- The following API methods have changed signatures:
|
||||||
|
- `CraftingTransaction->__construct()` now accepts additional arguments `?CraftingRecipe $recipe = null, ?int $repetitions = null`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `TransactionBuilderInventory->getActualInventory() : Inventory` - returns the actual inventory that this inventory is a proxy for
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
### Network
|
||||||
|
- Introduced new system for broadcasting entity events to network sessions.
|
||||||
|
- This change improves performance when lots of players and/or entities are in the same area.
|
||||||
|
- New interface `EntityEventBroadcaster` and class `StandardEntityEventBroadcaster` have been added to implement this.
|
||||||
|
- All entity-specific `on*()` and `sync*()` methods have been removed from `NetworkSession` (internals backwards compatibility break, not covered by API version guarantee).
|
||||||
|
- `NetworkSession` now accepts an `EntityEventBroadcaster` instance in its constructor.
|
||||||
|
- `NetworkBroadcastUtils::broadcastEntityEvent()` can be used to efficiently broadcast events to unique broadcasters shared by several network sessions.
|
||||||
|
- All network sessions now share the same `PacketSerializerContext` and `PacketBroadcaster` by default.
|
||||||
|
- Previously, every session had its own context, meaning that broadcast optimisations were not used, causing significant performance losses compared to 3.x.
|
||||||
|
- This change improves performance in congested areas by allowing reuse of previously encoded packet buffers for all sessions sharing the same context.
|
||||||
|
- Packet broadcasts are automatically encoded separately per unique `PacketSerializerContext` instance. This allows, for example, a multi-version fork to have a separate context for each protocol version, to ensure maximum broadcast efficiency while encoding different packets for different versions.
|
||||||
|
- `PacketSerializerContext` is now passed in `NetworkSession::__construct()`, instead of being created by the session.
|
||||||
|
- `StandardPacketBroadcaster` is now locked to a single `PacketSerializer` context, reducing complexity.
|
||||||
|
- Introduced `NetworkBroadcastUtils::broadcastPackets()`, replacing `Server->broadcastPackets()`.
|
||||||
|
- `Server->broadcastPackets()` has been deprecated. It will be removed in a future version.
|
||||||
|
- Introduced support for the `ItemStackRequest` Minecraft: Bedrock network protocol.
|
||||||
|
- This fixes a large number of inventory- and crafting-related bugs.
|
||||||
|
- This also improves server security by closing off many code pathways that might have been used for exploits. `TypeConverter->netItemStackToCore()` is no longer used in server code, and remains for tool usage only.
|
||||||
|
- This system is also significantly more bandwidth-efficient and has lower overhead than the legacy system.
|
||||||
|
- This now opens the gateway to easily implement lots of gameplay features which have been missing for a long time, such as enchanting, anvils, looms, and more.
|
||||||
|
- Significant changes have been made to `pocketmine\network\mcpe\InventoryManager` internals. These shouldn't affect plugins, but may affect plugins which use internal network API.
|
||||||
|
- **No changes have been made to the plugin `InventoryTransaction` API**.
|
||||||
|
- This system has been implemented as a shim for the existing PocketMine-MP transaction system to preserve plugin compatibility. Plugins using `InventoryTransactionEvent` should continue to work seamlessly.
|
||||||
|
- The `InventoryTransaction` API will be redesigned in a future major version to make use of the new information provided by the `ItemStackRequest` system.
|
||||||
|
- `InventoryTransactionPacket` is no longer sent by the client for "regular" inventory actions. However, it is still sent when dropping items, interacting with blocks, and using items.
|
||||||
|
- Inventory slot and content syncing is now buffered until the end of the tick. This reduces outbound network usage when the client performs multiple transactions in a single tick (e.g. crafting a stack of items).
|
||||||
|
- Renamed some `InventoryManager` internal properties to make them easier to understand.
|
||||||
|
- `TypeConverter->createInventoryAction()` has been removed.
|
||||||
|
- Packet batch limit has been lowered to `100` packets. With the introduction of `ItemStackRequest`, this is more than sufficient for normal gameplay.
|
||||||
|
|
||||||
|
### Other
|
||||||
|
- Use `Vector3::zero()` instead of `new Vector3()` in some places.
|
||||||
|
|
||||||
|
# 4.18.1
|
||||||
|
Released 27th March 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- `RakLibInterface` now logs the name of the currently active session if a crash occurs when processing a packet. This makes it easier to reproduce bugs, which is important to be able to fix them.
|
||||||
|
- Added more detailed debugging information to `InventoryManager->syncSelectedHotbarSlot()`.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed server crash when attempting to drop more of an item from a stack than available in the inventory.
|
||||||
|
- Fixed packet processing errors when editing writable books.
|
||||||
|
- Fixed packet processing errors when shift-clicking on the recipe book to craft recipes which draw from a large number of inventory slots.
|
||||||
|
|
||||||
|
# 4.18.2
|
||||||
|
Released 29th March 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed players being unable to join due to the appearance of a new `x5t` field in the JWT header of Xbox Live authentication tokens.
|
||||||
|
- Fixed items' durability appearing to reset when moving them around in the inventory.
|
||||||
|
|
||||||
|
# 4.18.3
|
||||||
|
Released 5th April 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed Average Players not being shown on timings reports when custom player classes are used.
|
||||||
|
- Fixed incorrect tick violation calculation in timings reports.
|
||||||
|
- Fixed not being able to add or remove items from the offhand slot.
|
||||||
|
- Fixed creative inventory item count corruption when taking items (some players would see 64x items in the creative inventory after rejoining or changing gamemode).
|
||||||
|
- Fixed not being able to drop items directly from the creative inventory on mobile.
|
||||||
|
- Fixed `DataPacketReceiveEvent` not being called for packets sent by `EntityEventBroadcaster`.
|
||||||
|
- `CreativeInventory::getItem()` and `CreativeInventory::getAll()` now return cloned itemstacks, to prevent accidental modification of the creative inventory.
|
||||||
|
|
||||||
|
# 4.18.4
|
||||||
|
Released 10th April 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed movement becoming broken when the player moves at high speed (e.g. due to high levels of the Speed effect).
|
||||||
|
- Updated dependencies to get fixes in `pocketmine/nbt` and `pocketmine/bedrock-protocol`.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
### Network
|
||||||
|
- Game packets are now rate-limited in a similar manner to packet batches. This helps to more effectively mitigate certain types of DoS attacks.
|
||||||
|
- Added a new class `PacketRateLimiter`, implementing functionality previously baked directly into `NetworkSession` in a more generic way to allow reuse.
|
||||||
111
changelogs/4.19.md
Normal file
111
changelogs/4.19.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.70**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||||
|
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
This version introduces support for a new, more advanced version of Timings.
|
||||||
|
This improved system provides more detail than the old system, and supports being displayed in a tree view, making it much easier to see which timers contribute to which other timers.
|
||||||
|
|
||||||
|
In addition, some minor performance improvements have been made, along with a couple of minor API additions.
|
||||||
|
|
||||||
|
# 4.19.0
|
||||||
|
Released 11th April 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Updated the Timings system.
|
||||||
|
- Timings records now include parent information, allowing them to be displayed in a tree view (e.g. https://timings.pmmp.io/?id=303556).
|
||||||
|
- Timings records now include additional information, such as Peak (max time spent on any single tick), and Ticks (number of ticks the timer was active on).
|
||||||
|
- New timings have been added for every event.
|
||||||
|
- A new timer `Player Network Send - Pre-Spawn Game Data` has been added, and covers most of the time spent handling `ResourcePackClientResponsePacket`, giving a clearer picture of what's happening.
|
||||||
|
- Improved performance of the plugin event system.
|
||||||
|
- By introducing some caching, the event system now has 90% less overhead than in previous versions.
|
||||||
|
- Improved performance of the random chunk ticking system.
|
||||||
|
- The selection of ticked random chunks, and their validation for ticking, is now cached. This significantly reduces the overhead of chunk selection.
|
||||||
|
- Factions servers and other game modes with big maps and sparsely populated areas will see the most benefit from this change.
|
||||||
|
- Real-world performance benefit of this change is anywhere from 0-20%, depending on server type and configuration.
|
||||||
|
- The `timings paste` command now logs a debug message with the server response on failure to paste a timings report.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\entity\object`
|
||||||
|
- The following API constants have been added:
|
||||||
|
- `ExperienceOrb::DEFAULT_DESPAWN_DELAY` - the default delay in ticks before an experience orb despawns
|
||||||
|
- `ExperienceOrb::NEVER_DESPAWN` - magic value for `setDespawnDelay()` to make an experience orb never despawn
|
||||||
|
- `ExperienceOrb::MAX_DESPAWN_DELAY` - the maximum delay in ticks before an experience orb despawns
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public ExperienceOrb->getDespawnDelay() : int` - returns the delay in ticks before this experience orb despawns
|
||||||
|
- `public ExperienceOrb->setDespawnDelay(int $despawnDelay) : void` - sets the delay in ticks before this experience orb despawns
|
||||||
|
- The following properties have been deprecated
|
||||||
|
- `ExperienceOrb->age` - superseded by despawn delay methods
|
||||||
|
|
||||||
|
### `pocketmine\event`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public HandlerList->getListenerList() : list<RegisteredListener>` - returns an ordered list of handlers to be called for the event
|
||||||
|
|
||||||
|
### `pocketmine\player`
|
||||||
|
- The following API methods have behavioural changes:
|
||||||
|
- `ChunkSelector->selectChunks()` now yields the distance in chunks from the center as the key, instead of an incrementing integer.
|
||||||
|
- The following classes have been deprecated:
|
||||||
|
- `PlayerChunkLoader` (this was technically internal, but never marked as such)
|
||||||
|
|
||||||
|
### `pocketmine\timings`
|
||||||
|
- The following API constants have been deprecated:
|
||||||
|
- `Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX` - this is superseded by timings group support (see `Timings::GROUP_BREAKDOWN`)
|
||||||
|
- The following API constants have been added:
|
||||||
|
- `Timings::GROUP_BREAKDOWN` - this group makes a timer appear in the `Minecraft - Breakdown` section of a timings report
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public TimingsHandler->getGroup() : string` - returns the name of the table in which this timer will appear in a timings report
|
||||||
|
- The following API methods have changed signatures:
|
||||||
|
- `TimingsHandler->__construct()` now accepts an additional, optional `string $group` parameter, which defaults to `Minecraft`.
|
||||||
|
|
||||||
|
### `pocketmine\world`
|
||||||
|
#### Highlights
|
||||||
|
Ticking chunks is now done using the `ChunkTicker` system, which has a much more fine-grained API than the old `TickingChunkLoader` system, as well as better performance.
|
||||||
|
It works similarly to the `ChunkLoader` system, in that chunks will be ticked as long as at least one `ChunkTicker` is registered for them.
|
||||||
|
|
||||||
|
#### API changes
|
||||||
|
- The following classes have been deprecated:
|
||||||
|
- `TickingChunkLoader` - this has been superseded by the more powerful and performant `ChunkTicker` APIs
|
||||||
|
- The following classes have been added:
|
||||||
|
- `ChunkTicker` - an opaque object used for `registerTickingChunk()` to instruct the `World` that we want a chunk to be ticked
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public World->registerTickingChunk(ChunkTicker $ticker, int $chunkX, int $chunkZ) : void` - registers a chunk to be ticked by the given `ChunkTicker`
|
||||||
|
- `public World->unregisterTickingChunk(ChunkTicker $ticker, int $chunkX, int $chunkZ) : void` - unregisters a chunk from being ticked by the given `ChunkTicker`
|
||||||
|
|
||||||
|
# 4.19.1
|
||||||
|
Released 14th April 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed inventory rollbacks when spreading items in ender chests.
|
||||||
|
- Fixed inventory rollbacks when shift-clicking to craft and the outputs would have been split across multiple inventory slots.
|
||||||
|
- Fixed incorrect spawn terrain generation for newly created worlds.
|
||||||
|
- Fixed `chunk-ticking.tick-radius` not disabling chunk ticking when set to `0`.
|
||||||
|
- Fixed chunks not being ticked if they previously left a player's simulation distance without leaving their view distance.
|
||||||
|
- Fixed height of collision boxes for Grass Path and Farmland blocks.
|
||||||
|
|
||||||
|
# 4.19.2
|
||||||
|
Released 14th April 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed player timings duplication leading to extremely large timings reports when timings runs for a long time with many players.
|
||||||
|
- Packet timings are now indexed by class FQN instead of packet ID. This prevents erroneous timer reuse on packet ID reuse (e.g. multi version servers).
|
||||||
|
- Fixed entity timings being shared by different classes with the same short name. This led to incorrect timings being reported for some entities when custom entities were used.
|
||||||
|
|
||||||
|
# 4.19.3
|
||||||
|
Released 21st April 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Error IDs for `Packet processing error` disconnects are now split into 4-character chunks to make them easier to type (since they can't be copied from the disconnection screen of a client).
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed entity-block intersections being checked twice per tick. Besides wasting CPU time, this may have caused unexpected behaviour during entity-block interactions with blocks like water or cacti.
|
||||||
|
- Fixed performance issue in network inventory synchronization due item NBT being prepared twice.
|
||||||
|
- Fixed `tools/simulate-chunk-selector.php` argument parsing being completely broken (weird behaviour of PHP `getopt()`).
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- `TimingsHandler->stopTiming()` now logs an error message if a subtimer wasn't stopped, rather than throwing an exception.
|
||||||
|
- Due to interactions between `try...finally` and unexpected errors, throwing exceptions made it difficult for plugin developers to debug errors in their plugins, since it obscured the original error.
|
||||||
121
changelogs/4.2.md
Normal file
121
changelogs/4.2.md
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.10**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.2.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.18.10.
|
||||||
|
|
||||||
|
# 4.2.1
|
||||||
|
Released 19th February 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Improved performance of `Item::nbtSerialize()` - this will improve performance during world saves.
|
||||||
|
- Added more missing changes to the 4.0.0 changelog.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed multiple players being able to sleep in the same bed.
|
||||||
|
- Fixed hitbox not resetting properly after swimming or gliding.
|
||||||
|
|
||||||
|
# 4.2.2
|
||||||
|
Released 2nd March 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed crash in `/dumpmemory` due to usage of non-printable string keys in `CraftingManager`. Array contents in memory dumps are now rendered as prettified key-value pairs.
|
||||||
|
- Fixed output directory for `/dumpmemory`.
|
||||||
|
- `PlayerInventory->isHotbarSlot()` now correctly returns `false` when given `9`.
|
||||||
|
- Fixed ghost items left in the inventory when dropping tools while mining.
|
||||||
|
|
||||||
|
# 4.2.3
|
||||||
|
Released 9th March 2022.
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
- Now analysed using PHPStan 1.4.8.
|
||||||
|
- Now using `pocketmine/bedrock-protocol` [`8.0.1`](https://github.com/pmmp/BedrockProtocol/releases/tag/8.0.1%2Bbedrock-1.18.10).
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
### Core
|
||||||
|
- Fixed a memory leak and other bugs related to plugins disabling themselves during `onEnable()`.
|
||||||
|
|
||||||
|
### Gameplay
|
||||||
|
- Sweet berry bushes now absorb fall damage.
|
||||||
|
- Fixed mycelium spreading onto coarse dirt.
|
||||||
|
- Fixed blocks placed during `Block->onIncinerate()` getting overwritten.
|
||||||
|
- Fixed shulker boxes being unopenable when underwater.
|
||||||
|
- Fixed invisible fire on top of transparent non-flammable blocks.
|
||||||
|
|
||||||
|
### API
|
||||||
|
- Various APIs accepting `Vector3`, `Position` or `Location` no longer accept objects containing `INF` or `NaN` in any component. Previously, this was allowed, but would cause lots of obscure crashes later on.
|
||||||
|
- `Entity->setRotation()` no longer accepts `INF` or `NaN`.
|
||||||
|
- Fixed missing bounds check for `ItemFrame->setItemDropChance()`.
|
||||||
|
|
||||||
|
# 4.2.4
|
||||||
|
Released 18th March 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed a crash when handling out-of-bounds meta values on the network.
|
||||||
|
|
||||||
|
# 4.2.5
|
||||||
|
Released 28th March 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The layout of the human-readable part of crashdumps has been changed in an effort to improve the useful information density. It is hoped that this change will cause more useful information to be provided when people paste crash traces on Discord, since all the most important information is now at the top of the file.
|
||||||
|
- Version, git hash, PHP version and OS have been moved to the top of the crashdump.
|
||||||
|
- Backtrace has been moved above code sample.
|
||||||
|
- Docker images are now built by GitHub Actions (first live test).
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
- The methods of `Inventory` and `BaseInventory` have been rearranged to improve coherency.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
### API
|
||||||
|
- Enum members of enums created using `EnumTrait` are now able to have single-character names.
|
||||||
|
- Registry members of registries created using `RegistryTrait` or `CloningRegistryTrait` now have their names checked for invalid characters.
|
||||||
|
- `Entity::__construct()` now uses a guard variable to prevent it from being called multiple times unintentionally. This is necessary because `Entity::__construct()` has side effects.
|
||||||
|
- Fixed `PlayerItemHeldEvent` not being called when the content of the held slot was changed (e.g. replacing the held item via inventory menu).
|
||||||
|
|
||||||
|
### Gameplay
|
||||||
|
- Reduced the appearance of ghost items in unsupported gameplay scenarios using client prediction information. This fixes, for example, the appearance of ghost items when right-clicking on a filled flower pot.
|
||||||
|
|
||||||
|
# 4.2.6
|
||||||
|
Released 1st April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed buffer length underflow crash in `LoginPacket` handling.
|
||||||
|
|
||||||
|
# 4.2.7
|
||||||
|
Released 15th April 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added lots more documentation (in comments) about the `aliases` section in `pocketmine.yml`. You can read about this feature in the `aliases` section of the [updated `pocketmine.yml` template](/resources/pocketmine.yml).
|
||||||
|
- Improved wording of documentation of `PlayerPreLoginEvent`.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed core server crash when a plugin causes another plugin to be disabled during a scheduled task.
|
||||||
|
- Fixed core server crash when loading a plugin with an abstract main class.
|
||||||
|
- Fixed ghost items in many interaction situations (most notably, using projectiles while looking at an entity or block).
|
||||||
|
- Implemented a workaround for a client teleport bug which led to player positions not updating properly when using ender pearls.
|
||||||
|
- Fixed buggy movement when teleporting the player during `PlayerToggleSneakEvent`, `PlayerToggleSprintEvent`, `PlayerToggleSwimEvent` and `PlayerToggleGlideEvent`.
|
||||||
|
|
||||||
|
# 4.2.8
|
||||||
|
Released 17th April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed a memory leak in RakLib which could result in a server crash when players stay online for a long time.
|
||||||
|
- Fixed server crash when attempting to load a corrupted empty resource pack.
|
||||||
|
- Fixed users with the same name with differerently cased letters being able to duplicate items (userdata is matched by case-insensitive name).
|
||||||
|
|
||||||
|
# 4.2.9
|
||||||
|
Released 19th April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed several potential crashes when deserializing item NBT (due to insufficient validation of input data).
|
||||||
|
|
||||||
|
# 4.2.10
|
||||||
|
Released 20th April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed performance issue when chat messages received from the client contain many newlines. This security vulnerability was disclosed publicly necessitating a priority fix.
|
||||||
73
changelogs/4.20.md
Normal file
73
changelogs/4.20.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.80**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||||
|
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||||
|
|
||||||
|
### Interim releases
|
||||||
|
If you're upgrading from 4.17.x directly to 4.20.x, please also read the following changelogs, as the interim releases contain important changes:
|
||||||
|
|
||||||
|
- [4.18.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.18.md#4180) - major performance improvements, internal network changes, minor API additions
|
||||||
|
- [4.19.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.19.md#4190) - minor performance improvements, improved timings system, minor API additions
|
||||||
|
|
||||||
|
# 4.20.0
|
||||||
|
Released 26th April 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.80.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed packet processing error when attempting to use a stonecutter.
|
||||||
|
- Fixed armor slots containing ghost items when cancelling right-click to equip armor.
|
||||||
|
- Fixed crash in `HandlerList->getListenersByPriority()` when no listeners are registered at the given priority.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\block`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public BaseSign->getEditorEntityRuntimeId() : int` - returns the entity runtime ID of the player currently editing this sign, or `null` if none
|
||||||
|
- `public BaseSign->setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : $this` - sets the entity runtime ID of the player currently editing this sign
|
||||||
|
|
||||||
|
### `pocketmine\player`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public Player->openSignEditor(Vector3 $position) : void` - opens the client-side sign editor GUI for the given position
|
||||||
|
|
||||||
|
# 4.20.1
|
||||||
|
Released 27th April 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed server crash when firing a bow while holding arrows in the offhand slot.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- `ItemStackContainerIdTranslator::translate()` now requires an additional `int $slotId` parameter and returns `array{int, int}` (translated window ID, translated slot ID) to be used with `InventoryManager->locateWindowAndSlot()`.
|
||||||
|
- `InventoryManager->locateWindowAndSlot()` now checks if the translated slot actually exists in the requested inventory, and returns `null` if not. Previously, it would return potentially invalid slot IDs without checking them, potentially leading to crashes.
|
||||||
|
|
||||||
|
# 4.20.2
|
||||||
|
Released 4th May 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed all types of wooden logs appearing as oak in the inventory.
|
||||||
|
- Fixed a performance issue in `BaseInventory->canAddItem()` (missing `continue` causing useless logic to run).
|
||||||
|
|
||||||
|
# 4.20.3
|
||||||
|
Released 6th May 2023.
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
- Reduced memory usage of `RuntimeBlockMapping` from 25 MB to 9 MB. Since every thread has its own copy of the block map, this saves a substantial amount of memory.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed players falling through blocks in spectator mode.
|
||||||
|
- Fixed timings reports getting bloated by prolific usage of `PluginManager->registerEvent()`.
|
||||||
|
- This was caused by creating a new timings handler for each call, regardless of whether a timer already existed for the given event and callback.
|
||||||
|
- Fixed `Full Server Tick` and other records being missing from timings reports.
|
||||||
|
- This was caused by timings handler depth not getting reset when timings was disabled and later re-enabled.
|
||||||
|
|
||||||
|
# 4.20.4
|
||||||
|
Released 6th May 2023.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed players being forced into flight mode in every game mode.
|
||||||
|
- Moral of the story: do not assume anything in Mojang internals does what its name suggests...
|
||||||
71
changelogs/4.21.md
Normal file
71
changelogs/4.21.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.80**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the `pocketmine\network\mcpe` namespace, and don't use reflection or any internal methods,
|
||||||
|
will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||||
|
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||||
|
|
||||||
|
# 4.21.0
|
||||||
|
Released 17th May 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- PHP 8.1 is now required. Most plugins should run without changes, but some might need to be updated due to language-level deprecations.
|
||||||
|
- Ticking chunk count is now shown separately from loaded chunk count in the `/status` command, providing useful performance information.
|
||||||
|
- Further improved performance of ticking chunk selection.
|
||||||
|
- Improved performance of some inventory functions.
|
||||||
|
- Reduced server memory footprint in most cases by ~9 MB per thread.
|
||||||
|
- Due to large overhead, async network compression is now only used for packets larger than 10 KB by default.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
- Added the following new `pocketmine.yml` configuration options:
|
||||||
|
- `network.async-compression-threshold` - minimum size of packet which will be compressed using `AsyncTask`
|
||||||
|
- Default is 10 KB, which means that very few packets will use async compression in practice. This is because the overhead of compressing async is currently so high that it's not worth it for smaller packets.
|
||||||
|
|
||||||
|
## Timings
|
||||||
|
- Timings reports no longer include the unused metadata fields `Entities` and `LivingEntities`.
|
||||||
|
- Timings reports now correctly calculate the peak time of a timer.
|
||||||
|
- Previously it was incorrectly recorded as the longest time spent in a single tick, rather than the longest time spent in a single activation.
|
||||||
|
- Timings report version has been bumped to `2` to reflect this change.
|
||||||
|
- All world-specific timers now have generic aggregate timings, making it much easier to locate performance patterns across all worlds.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Players in spectator mode are no longer able to pick blocks, and now have finite resources similar to survival mode.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\world`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public World->getTickingChunks() : list<int>` - returns a list of chunk position hashes (a la `World::chunkHash()`) which are currently valid for random ticking
|
||||||
|
|
||||||
|
### `pocketmine\inventory`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `protected BaseInventory->getMatchingItemCount(int $slot, Item $test, bool $checkDamage, bool $checkTags) : int` - returns the number of items in the given stack if the content of the slot matches the test item, or zero otherwise
|
||||||
|
- This should be overridden if directly extending `BaseInventory` to provide a performance-optimised version. A slow default implementation is provided, but it will be removed in the future.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
### Entity
|
||||||
|
- Unused `NameTag` tag is no longer saved for `Human` entities.
|
||||||
|
|
||||||
|
### Inventory
|
||||||
|
- `BaseInventory` now uses a new internal method `getMatchingItemCount()` to locate items in the inventory without useless cloning. This improves performance of various API methods, such as `addItem()`, `contains()`, and more.
|
||||||
|
- Specialization of `Inventory->isSlotEmpty()` in `BaseInventory` subclasses has been added to improve performance of some API methods.
|
||||||
|
|
||||||
|
### Network
|
||||||
|
- `RuntimeBlockMapping` no longer keeps all block palette NBT data in memory.
|
||||||
|
- This significantly reduces server idle memory footprint.
|
||||||
|
- For multi-version implementations, this will have a significant impact on memory usage, since a different block palette is often required to support each version.
|
||||||
|
- NBT will be lazy-loaded into memory and cached if `getBedrockKnownStates()` is called. However, this is not used by PocketMine-MP under normal circumstances.
|
||||||
|
- Removed unnecessary usage of `Utils::validateCallableSignature()` from some internal network pathways, improving performance.
|
||||||
|
|
||||||
|
### Scheduler
|
||||||
|
- `AsyncPool` no longer double-checks progress updates on completed tasks.
|
||||||
|
|
||||||
|
### World
|
||||||
|
- Ticking chunks are now tracked in `World->validTickingChunks` and `World->recheckTickingChunks`.
|
||||||
|
- This allows avoiding rechecking every ticking chunk for validity during ticking chunk selection, improving performance.
|
||||||
|
- In some cases, this allows bypassing chunk selection entirely, reducing selection cost to zero.
|
||||||
|
- Registered but ineligible ticking chunks are no longer rechecked every tick.
|
||||||
|
- This was causing wasted cycles during async worker backlog.
|
||||||
|
- The internal system must call `markTickingChunkForRecheck()` whenever a ticking chunk's eligibility for ticking has potentially changed, rather than just when it has changed from a yes to a no.
|
||||||
77
changelogs/4.3.md
Normal file
77
changelogs/4.3.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.3.0
|
||||||
|
Released 20th April 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.18.30.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.3.1
|
||||||
|
Released 23rd April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Updated BedrockProtocol dependency to fix incorrect command argument types.
|
||||||
|
- Creative players no longer die in the void.
|
||||||
|
|
||||||
|
# 4.3.2
|
||||||
|
Released 10th May 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed an assertion failure in certain edge cases during world generation.
|
||||||
|
- Fixed `Entity::setNameTagVisible()` not immediately showing results to players already online.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Added more documentation in the template `pocketmine.yml` for the `aliases` config section.
|
||||||
|
- Removed useless doc comment in `PlayerChangeSkinEvent`.
|
||||||
|
|
||||||
|
# 4.3.3
|
||||||
|
Released 16th May 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Improved display of parameters in exception stack trace logs.
|
||||||
|
- Exception stack traces now include names for dynamic named arguments (i.e. arguments that don't match any parameter of the function), if any were given.
|
||||||
|
- Note: Named arguments which do match parameters are not shown this way, since PHP reduces them to positional arguments for performance reasons.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed server crash when chunks are unloaded during chunk generation callbacks
|
||||||
|
- Fixed dead coral fan items placing coral fans in the wrong orientation.
|
||||||
|
- Fixed max stack size of boat items.
|
||||||
|
|
||||||
|
# 4.3.4
|
||||||
|
Released 22nd May 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed `difficulty` in `server.properties` having no effect - it's now applied to newly generated worlds.
|
||||||
|
- Note: this setting still doesn't behave the same way as vanilla due to potential disruption to existing servers.
|
||||||
|
- Fixed paintings not working in newly generated worlds and some other cases.
|
||||||
|
- Fixed inventory window switching breaking the inventory UI in some cases (e.g. pressing E while clicking a chest).
|
||||||
|
- Fixed minecart items incorrectly stacking.
|
||||||
|
- Fixed incorrect light levels in translucent blocks at the top of the world.
|
||||||
|
- Fixed teleporting sleeping players causing broken behaviour on the sleeping player's client.
|
||||||
|
- Fixed `EntityExplodeEvent->setYield()` accepting values outside the range 0-100.
|
||||||
|
- Fixed `ExplosionPrimeEvent->setForce()` accepting negative values (later resulting in crashes).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Updated documentation for the following events:
|
||||||
|
- `CommandEvent`
|
||||||
|
- `EntityDespawnEvent`
|
||||||
|
- `EntityExplodeEvent`
|
||||||
|
- `EntitySpawnEvent`
|
||||||
|
- `ExplosionPrimeEvent`
|
||||||
|
- `InventoryTransactionEvent`
|
||||||
|
- `ItemDespawnEvent`
|
||||||
|
- `ItemSpawnEvent`
|
||||||
|
- `PlayerCommandPreprocessEvent`
|
||||||
|
- `PlayerDropItemEvent`
|
||||||
|
- `PlayerItemHeldEvent`
|
||||||
|
- `PlayerKickEvent`
|
||||||
|
- `PlayerQuitEvent`
|
||||||
|
- `PlayerTransferEvent`
|
||||||
|
- `UpdateNotifyEvent`
|
||||||
77
changelogs/4.4-beta.md
Normal file
77
changelogs/4.4-beta.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.4.0-BETA1
|
||||||
|
Released 25th May 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The server will now shut itself down if any of the following errors occur during startup:
|
||||||
|
- Any plugin fails to load or enable (plugins loaded by other plugins post-startup are **not** affected by this change) (**PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)**)
|
||||||
|
- The motivation for this change is to prevent situations where plugins failing to load could result in adverse outcomes, such as a world protection plugin leaving a lobby unprotected from griefing.
|
||||||
|
- If you encounter this problem, remove the offending plugin(s) or prevent it from loading using `plugin_list.yml`.
|
||||||
|
- See **PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)** for more detail on this change.
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to load (worlds loaded by plugins are **not** affected by this change)
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to generate (e.g. due to invalid generator settings)
|
||||||
|
- Enabling the server whitelist while the server is running (e.g. using `/whitelist on`) will now kick any non-whitelisted players currently on the server (**PR [#4774](https://github.com/pmmp/PocketMine-MP/pull/4774)**).
|
||||||
|
- Help for commands (`/help <name of command>`) now displays a list of aliases of that command.
|
||||||
|
- A CRITICAL log message is now generated if a plugin disables itself when enabling, in case the plugin doesn't emit any error of its own.
|
||||||
|
- The `/give` command now shows the alias used to find the given item in the success message, instead of the item ID/meta.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Block placement has been fixed in many places where it previously didn't work correctly (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**):
|
||||||
|
- torches on top of slabs, upside-down stairs
|
||||||
|
- torches on the back face of stairs
|
||||||
|
- flower pots on top of fences
|
||||||
|
- the list goes on and on ...
|
||||||
|
- Fixed backslash escapes not getting properly removed from commands in some cases.
|
||||||
|
- Fixed aliases defined in the `aliases` section of `pocketmine.yml` not being treated as quote-aware.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Plants in flower pots can now be removed by right-clicking on the flower pot.
|
||||||
|
- Leaves now have a 2% chance of dropping sticks when destroyed by hand (**PR [#5019](https://github.com/pmmp/PocketMine-MP/pull/5019)**).
|
||||||
|
- Food exhaustion now matches Bedrock 1.18.30 (**PR [#5034](https://github.com/pmmp/PocketMine-MP/pull/5034)**).
|
||||||
|
- Implemented Stonecutter block (**PR [#4732](https://github.com/pmmp/PocketMine-MP/pull/4732)**).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- Added `Block->getSupportType(Facing) : SupportType` (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- This is used to determine the kind of support a block face can provide to a block (e.g. a torch) placed on it.
|
||||||
|
- Added `utils\SupportType` enum (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- `tile\Spawnable->isDirty()` and `tile\Spawnable->setDirty()` are now `@deprecated`.
|
||||||
|
|
||||||
|
### Command
|
||||||
|
- Added `CommandStringHelper::parseQuoteAware()`. This static method contains the code used by `SimpleCommandMap` used to parse quoted command arguments.
|
||||||
|
|
||||||
|
### Entity
|
||||||
|
- Added `Human::emote()` (**PR [#4610](https://github.com/pmmp/PocketMine-MP/pull/4610)**)
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- `PlayerCommandPreprocessEvent` is now `@deprecated`, since its functionality is entirely replaced by other, general-purpose events.
|
||||||
|
- Use `CommandEvent` to intercept commands.
|
||||||
|
- Use `PlayerChatEvent` to intercept chat messages.
|
||||||
|
- To convert a chat message into a command, pass it directly to `Server->dispatchCommand()` with the player as sender.
|
||||||
|
- Added `PlayerPostChunkSendEvent` (**PR [#4937](https://github.com/pmmp/PocketMine-MP/pull/4937)**).
|
||||||
|
- Added `PlayerDeathEvent->setKeepXp()` (**PR [#4015](https://github.com/pmmp/PocketMine-MP/pull/4015)**).
|
||||||
|
- `InventoryCloseEvent` is now called **after** the target window has been removed. This fixes various feedback loops caused by trying to open new windows to a player while there was one still active.
|
||||||
|
- As a side effect, this now means that `Player->getCurrentWindow()` will return `null` during `InventoryCloseEvent`. Use `InventoryCloseEvent->getInventory()` instead.
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- `StringToItemParser` now recognizes `cod`, `raw_cod` and `cooked_cod` aliases.
|
||||||
|
|
||||||
|
### Plugin
|
||||||
|
- `DisablePluginException` may now be thrown from `Plugin::onEnable()` to make the server gracefully disable the plugin (without crashing) (**PR [#4780](https://github.com/pmmp/PocketMine-MP/pull/4780)**).
|
||||||
|
- `PluginManager->registerEvent()` now returns the `RegisteredListener` created for the handler, to permit unregistering it later.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Private property declarations now use typed properties (PHP 7.4) and promoted constructor properties (PHP 8.0) wherever possible.
|
||||||
|
- Protected and public properties remain unchanged, since they can't be changed without breaking subclasses.
|
||||||
|
- Promoted constructor properties are only used when it's consistently possible to promote most or all properties in a class.
|
||||||
|
- Simplified and improved legibility of `FormattedCommandAlias`.
|
||||||
|
- Added unit tests for the quote-aware command parser used by `SimpleCommandMap`.
|
||||||
|
- Various hardcoded values in `block` package classes have been moved to private constants to improve readability.
|
||||||
|
- Added various constants used in the `LevelDB` world provider.
|
||||||
97
changelogs/4.4.md
Normal file
97
changelogs/4.4.md
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.4.0
|
||||||
|
Released 1st June 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The server will now shut itself down if any of the following errors occur during startup:
|
||||||
|
- Any plugin fails to load or enable (plugins loaded by other plugins post-startup are **not** affected by this change) (**PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)**)
|
||||||
|
- The motivation for this change is to prevent situations where plugins failing to load could result in adverse outcomes, such as a world protection plugin leaving a lobby unprotected from griefing.
|
||||||
|
- If you encounter this problem, remove the offending plugin(s) or prevent it from loading using `plugin_list.yml`.
|
||||||
|
- See **PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)** for more detail on this change.
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to load (worlds loaded by plugins are **not** affected by this change)
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to generate (e.g. due to invalid generator settings)
|
||||||
|
- Enabling the server whitelist while the server is running (e.g. using `/whitelist on`) will now kick any non-whitelisted players currently on the server (**PR [#4774](https://github.com/pmmp/PocketMine-MP/pull/4774)**).
|
||||||
|
- Help for commands (`/help <name of command>`) now displays a list of aliases of that command.
|
||||||
|
- A CRITICAL log message is now generated if a plugin disables itself when enabling, in case the plugin doesn't emit any error of its own.
|
||||||
|
- The `/give` command now shows the alias used to find the given item in the success message, instead of the item ID/meta.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Block placement has been fixed in many places where it previously didn't work correctly (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**):
|
||||||
|
- torches on top of slabs, upside-down stairs
|
||||||
|
- torches on the back face of stairs
|
||||||
|
- flower pots on top of fences
|
||||||
|
- the list goes on and on ...
|
||||||
|
- Fixed backslash escapes not getting properly removed from commands in some cases.
|
||||||
|
- Fixed aliases defined in the `aliases` section of `pocketmine.yml` not being treated as quote-aware.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Plants in flower pots can now be removed by right-clicking on the flower pot.
|
||||||
|
- Leaves now have a 2% chance of dropping sticks when destroyed by hand (**PR [#5019](https://github.com/pmmp/PocketMine-MP/pull/5019)**).
|
||||||
|
- Food exhaustion now matches Bedrock 1.18.30 (**PR [#5034](https://github.com/pmmp/PocketMine-MP/pull/5034)**).
|
||||||
|
- Implemented Stonecutter block (**PR [#4732](https://github.com/pmmp/PocketMine-MP/pull/4732)**).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- Added `Block->getSupportType(Facing) : SupportType` (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- This is used to determine the kind of support a block face can provide to a block (e.g. a torch) placed on it.
|
||||||
|
- Added `utils\SupportType` enum (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- `tile\Spawnable->isDirty()` and `tile\Spawnable->setDirty()` are now `@deprecated`.
|
||||||
|
|
||||||
|
### Command
|
||||||
|
- Added `CommandStringHelper::parseQuoteAware()`. This static method contains the code used by `SimpleCommandMap` used to parse quoted command arguments.
|
||||||
|
|
||||||
|
### Entity
|
||||||
|
- Added `Human::emote()` (**PR [#4610](https://github.com/pmmp/PocketMine-MP/pull/4610)**)
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- `PlayerCommandPreprocessEvent` is now `@deprecated`, since its functionality is entirely replaced by other, general-purpose events.
|
||||||
|
- Use `CommandEvent` to intercept commands.
|
||||||
|
- Use `PlayerChatEvent` to intercept chat messages.
|
||||||
|
- To convert a chat message into a command, pass it directly to `Server->dispatchCommand()` with the player as sender.
|
||||||
|
- Added `PlayerPostChunkSendEvent` (**PR [#4937](https://github.com/pmmp/PocketMine-MP/pull/4937)**).
|
||||||
|
- Added `PlayerDeathEvent->setKeepXp()` (**PR [#4015](https://github.com/pmmp/PocketMine-MP/pull/4015)**).
|
||||||
|
- `InventoryCloseEvent` is now called **after** the target window has been removed. This fixes various feedback loops caused by trying to open new windows to a player while there was one still active.
|
||||||
|
- As a side effect, this now means that `Player->getCurrentWindow()` will return `null` during `InventoryCloseEvent`. Use `InventoryCloseEvent->getInventory()` instead.
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- `StringToItemParser` now recognizes `cod`, `raw_cod` and `cooked_cod` aliases.
|
||||||
|
|
||||||
|
### Plugin
|
||||||
|
- `DisablePluginException` may now be thrown from `Plugin::onEnable()` to make the server gracefully disable the plugin (without crashing) (**PR [#4780](https://github.com/pmmp/PocketMine-MP/pull/4780)**).
|
||||||
|
- `PluginManager->registerEvent()` now returns the `RegisteredListener` created for the handler, to permit unregistering it later.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Private property declarations now use typed properties (PHP 7.4) and promoted constructor properties (PHP 8.0) wherever possible.
|
||||||
|
- Protected and public properties remain unchanged, since they can't be changed without breaking subclasses.
|
||||||
|
- Promoted constructor properties are only used when it's consistently possible to promote most or all properties in a class.
|
||||||
|
- Simplified and improved legibility of `FormattedCommandAlias`.
|
||||||
|
- Added unit tests for the quote-aware command parser used by `SimpleCommandMap`.
|
||||||
|
- Various hardcoded values in `block` package classes have been moved to private constants to improve readability.
|
||||||
|
- Added various constants used in the `LevelDB` world provider.
|
||||||
|
|
||||||
|
# 4.4.1
|
||||||
|
Released 5th June 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The server process will now exit with an error code if plugins, worlds or network interfaces failed to start.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed graylisted plugins preventing the server from starting.
|
||||||
|
- Fixed `composer make-devtools` command.
|
||||||
|
- Fixed the `Maximum memory (manager)` units being incorrectly displayed in `/status`.
|
||||||
|
- Fixed `Player->removeCurrentWindow()` breaking inventory windows.
|
||||||
|
|
||||||
|
# 4.4.2
|
||||||
|
Released 7th June 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed a crash when arbitrary item IDs appeared in network items in some cases.
|
||||||
|
- Fixed saved paintings being deleted when loaded from disk (regression from 4.3.4).
|
||||||
|
- Fixed max stack size of fishing rods.
|
||||||
28
changelogs/4.5.md
Normal file
28
changelogs/4.5.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.0**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.5.0
|
||||||
|
Released 7th June 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.0.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.5.1
|
||||||
|
Released 8th June 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed commands defined in `pocketmine.yml` `aliases` not passing the correct arguments.
|
||||||
|
- Updated BedrockProtocol to fix command argument types displayed on client-side command suggestions.
|
||||||
|
|
||||||
|
# 4.5.2
|
||||||
|
Released 29th June 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed terrain getting redrawn when flying in spectator mode (or when using `Player->setHasBlockCollision(false)`).
|
||||||
|
- Fixed skulls with the `noDrops` flag set being treated as unknown blocks.
|
||||||
42
changelogs/4.6.md
Normal file
42
changelogs/4.6.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.10**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.6.0
|
||||||
|
Released 13th July 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.10.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.6.1
|
||||||
|
Released 22nd July 2022.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
- `build/generate-registry-annotations.php` now supports processing single files (useful for PhpStorm file watchers).
|
||||||
|
|
||||||
|
## API
|
||||||
|
- Updated documentation for `AsyncTask`.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed incorrect items being displayed in item frames.
|
||||||
|
- Fixed books not showing in lecterns.
|
||||||
|
- Fixed incorrect damage interval of Wither status effect.
|
||||||
|
- Fixed incorrect fire ticks when being set on fire by lava (8 seconds in Bedrock instead of 15).
|
||||||
|
- `Entity->attack()` now cancels damage from `FIRE` and `FIRE_TICK` damage causes if the entity is fireproof.
|
||||||
|
- Fixed inventory windows getting force-closed when the client attempts to use an enchanting table or anvil.
|
||||||
|
|
||||||
|
# 4.6.2
|
||||||
|
Released 6th August 2022.
|
||||||
|
|
||||||
|
## Core
|
||||||
|
- Improved server-side performance of `PlayerAuthInputPacket` handler.
|
||||||
|
- Improved client-side performance of `FloatingTextParticle` by using an invisible falling block entity. This offered a roughly 5x performance improvement over using tiny invisible players in local testing.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed assert failures and debug spam on debug Minecraft clients related to abilities in `AddPlayerPacket`.
|
||||||
|
- Fixed crash in `ReversePriorityQueue` on PHP 8.1 by adding `#[ReturnTypeWillChange]` attribute.
|
||||||
46
changelogs/4.7.md
Normal file
46
changelogs/4.7.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.20**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.7.0
|
||||||
|
Released 9th August 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.20.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.7.1
|
||||||
|
Released 14th August 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed server crash when loading items from disk which have negative meta values.
|
||||||
|
- Fixed Turtle Master potions not giving any effects.
|
||||||
|
- Unimplemented items are no longer craftable.
|
||||||
|
- Fixed incorrect items appearing in item frames (due to an obsolete workaround for 1.19.10).
|
||||||
|
|
||||||
|
# 4.7.2
|
||||||
|
Released 16th August 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed crash when processing player skins with invalid geometry data.
|
||||||
|
- Fixed spectator players being able to pick blocks using mousewheel click.
|
||||||
|
- Improved supporting requirements for sugarcane.
|
||||||
|
|
||||||
|
# 4.7.3
|
||||||
|
Released 22nd August 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added complete translations for Spanish and Vietnamese.
|
||||||
|
- All continuous integration (static analysis, unit tests, integration tests) are now performed on PHP 8.1 as well as 8.0.
|
||||||
|
- InventoryTransaction now verifies that stack sizes of items after the transaction don't exceed the maximum stack size of the item type or the containing inventory.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed Normal generator crash on PHP 8.1.
|
||||||
|
- Fixed a race condition during async worker shutdown that could lead to tasks executing in the wrong order. This (very rarely) led to a crash in `PopulationTask` due to its preceding `GeneratorRegisterTask` not being executed.
|
||||||
|
- Fixed `/give` accepting negative amounts or amounts larger than 32767 (vanilla max).
|
||||||
|
- Fixed placement conditions for vines (no longer able to be placed on the side of cacti).
|
||||||
|
- Fixed incorrect documentation of `SignText::__construct()`.
|
||||||
23
changelogs/4.8.md
Normal file
23
changelogs/4.8.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.21**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.8.0
|
||||||
|
Released 24th August 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.21.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.8.1
|
||||||
|
Released 26th August 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Crashdumps now include JIT mode information for use by the Crash Archive.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed uninitialized offset error in `DyeColorIdMap` when given invalid dye color IDs.
|
||||||
36
changelogs/4.9.md
Normal file
36
changelogs/4.9.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.9.0
|
||||||
|
Released 20th September 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.30.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.9.1
|
||||||
|
Released 11th October 2022.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Added and improved documentation for many API methods in `Player` and `Block`.
|
||||||
|
- Added missing `@internal` tag for `TaskHandler->setNextRun()`, `TaskHandler->remove()` and `TaskHandler->run()`.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Flight state is now locked by the server in spectator mode. This prevents any attempt by the client to toggle flight mode.
|
||||||
|
- Fixed entity health exceeding its max health after the expiry of Health Boost effect.
|
||||||
|
- Fixed burp sound not being played when a player eats food.
|
||||||
|
- Fixed placement conditions for mushrooms - they can now only be placed when the light level at the target is <= 12, or on podzol or mycelium.
|
||||||
|
- Fixed sign text appearing to change colour and/or glow when using dye on a sign - since this feature is not yet implemented, no change should occur.
|
||||||
|
- Fixed players drowning when sprint-swimming on the surface of water.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Added more detailed debug logging during the player login sequence.
|
||||||
|
- Silenced debug spam during `PreSpawnPacketHandler`, considerably reducing debug noise when players join.
|
||||||
|
- Fixed an edge case in `InventoryManager->removeWindow()`. This bug didn't have any effect on stable versions, but caused a `next-minor` development version to crash.
|
||||||
|
- `Item`s returned by event getters are now cloned if modifying the result will have no useful side effects.
|
||||||
|
- Updated `pocketmine/bedrock-data` to [`1.11.1`](https://github.com/pmmp/BedrockData/tree/1.11.1%2Bbedrock-1.19.30), which reduces bandwidth consumption during logins by not sending useless biome generation data.
|
||||||
1038
changelogs/5.0-alpha.md
Normal file
1038
changelogs/5.0-alpha.md
Normal file
File diff suppressed because it is too large
Load Diff
215
changelogs/5.0-beta.md
Normal file
215
changelogs/5.0-beta.md
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.62**
|
||||||
|
|
||||||
|
5.0.0 is a major update to PocketMine-MP, including many new features and API changes. It is **not** compatible with plugins written for previous versions of PocketMine-MP.
|
||||||
|
|
||||||
|
**During the beta phase, no new features will be added.**
|
||||||
|
|
||||||
|
This stage of development is focused on stability and cleaning up any major issues introduced during the alpha stage.
|
||||||
|
|
||||||
|
## WARNING
|
||||||
|
**This is a BETA release.** This means that it may be unstable, and is not yet ready for production use.
|
||||||
|
|
||||||
|
Since this version has undergone substantial changes compared to 4.x, plugins written for 4.x will need to be updated to work on this version.
|
||||||
|
|
||||||
|
Breaking API changes may still occur during the beta phase, but only if they are strictly necessary to fix a problem prior to full release.
|
||||||
|
|
||||||
|
**BACK UP your data before testing this.** This version will work with worlds and player data from 4.x,
|
||||||
|
BUT any world or player data loaded in 5.0.0 will not work in 4.x due to backwards-incompatible storage format changes.
|
||||||
|
|
||||||
|
# 5.0.0-BETA1
|
||||||
|
Released 7th March 2023.
|
||||||
|
|
||||||
|
**This release includes changes from the following releases:**
|
||||||
|
- [All 5.0.0 alpha releases](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/5.0-alpha.md)
|
||||||
|
- [4.15.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/4.15.md#4152)
|
||||||
|
- [4.15.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/4.15.md#4153)
|
||||||
|
- [4.16.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/4.16.md#4160)
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\block`
|
||||||
|
- Improved documentation for the following methods:
|
||||||
|
- `Block->getTypeId()`
|
||||||
|
- `Block->getStateId()`
|
||||||
|
- `Block->describeType()`
|
||||||
|
- `Block->describeState()`
|
||||||
|
|
||||||
|
### `pocketmine\command`
|
||||||
|
- The following API methods have been renamed:
|
||||||
|
- `Command->getPermission()` -> `Command->getPermissions()`
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- The following methods have been renamed:
|
||||||
|
- `Block->computeStateData()` -> `Block->computeTypeAndStateData()`
|
||||||
|
- `Block->decodeStateData()` -> `Block->decodeTypeAndStateData()`
|
||||||
|
- Wall state data now packs connections into 7 bits instead of 8.
|
||||||
|
|
||||||
|
# 5.0.0-BETA2
|
||||||
|
Released 11th April 2023.
|
||||||
|
|
||||||
|
**This release includes changes from the following releases:**
|
||||||
|
- [4.17.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.17.md#4170)
|
||||||
|
- [4.17.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.17.md#4171)
|
||||||
|
- [4.17.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.17.md#4172)
|
||||||
|
- [4.18.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4180)
|
||||||
|
- [4.18.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4181)
|
||||||
|
- [4.18.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4182)
|
||||||
|
- [4.18.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4183)
|
||||||
|
- [4.18.4](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4184)
|
||||||
|
- [4.19.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.19.md#4190)
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
- Added script `tools/generate-bedrock-data-from-packets.php`. This tool accepts a txt file containing base64-encoded packet dumps.
|
||||||
|
- This script has been used to generate data for [BedrockData](https://github.com/pmmp/BedrockData) for several years, but has only now been open-sourced.
|
||||||
|
- It's used to generate data such as crafting recipes, creative inventory data, and various other blobs of data needed to support the current version of Minecraft: Bedrock Edition.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Anvils now damage entities when they fall on top of them.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\block\utils`
|
||||||
|
- The following API interface requirements have been added (BC breaking):
|
||||||
|
- `public Fallable->getFallDamagePerBlock() : float` (default implementation provided by `FallableTrait`)
|
||||||
|
- `public Fallable->getMaxFallDamage() : float` (default implementation provided by `FallableTrait`)
|
||||||
|
|
||||||
|
### `pocketmine\data\bedrock\block`
|
||||||
|
- The following new API methods have been added:
|
||||||
|
- `public BlockStateData->getVersionAsString() : string`
|
||||||
|
|
||||||
|
#### `pocketmine\data\bedrock\block\upgrade\model`
|
||||||
|
- `BlockStateUpgradeSchemaModelBlockRemap` now accepts `null` for `oldState` and `newState`. This makes it easier to generate portable schemas for other languages to read.
|
||||||
|
|
||||||
|
### `pocketmine\event\entity`
|
||||||
|
- The following new API constants have been added:
|
||||||
|
- `EntityDamageEvent::CAUSE_FALLING_BLOCK`
|
||||||
|
- `EntityDamageEvent::MODIFIER_ARMOR_HELMET`
|
||||||
|
|
||||||
|
### `pocketmine\item`
|
||||||
|
- The following API methods have signature changes:
|
||||||
|
- `ItemTypeIds::toBlockTypeId()` may now return `null` if the item type ID is not a block.
|
||||||
|
|
||||||
|
### `pocketmine\player`
|
||||||
|
- The following classes have been removed:
|
||||||
|
- `PlayerChunkLoader` - deprecated in 4.19.0 (this was technically internal, but never marked as such)
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Make use of `Item->canStackWith()` instead of `Item->equals()` wherever possible, to make the code more readable.
|
||||||
|
|
||||||
|
# 5.0.0-BETA3
|
||||||
|
Released 17th May 2023.
|
||||||
|
|
||||||
|
**This release includes changes from the following releases:**
|
||||||
|
- [4.19.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4191)
|
||||||
|
- [4.19.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4192)
|
||||||
|
- [4.19.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4193)
|
||||||
|
- [4.20.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4200)
|
||||||
|
- [4.20.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4201)
|
||||||
|
- [4.20.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4202)
|
||||||
|
- [4.20.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4203)
|
||||||
|
- [4.20.4](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4204)
|
||||||
|
- [4.21.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.21.md#4210)
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Improved light propagation performance by 10-15%.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed late initialization of coral type in `BaseCoral`.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
- `tools/generate-blockstate-upgrade-schema.php` has the following improvements:
|
||||||
|
- Now generates better errors when inconsistent blockstate versions are encountered.
|
||||||
|
- Now generates more stable outputs when re-run on the same input.
|
||||||
|
- Output now uses `copiedState` in `remappedStates` where possible. This significantly reduces the size of the output for blocks with partially flattened states.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- The following blocks have been added:
|
||||||
|
- Cave Vines
|
||||||
|
- The following items have been added:
|
||||||
|
- Glow Berries
|
||||||
|
- Mangrove Boat (incomplete)
|
||||||
|
- Fixed flower pots being able to be placed inside flower pots.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `pocketmine\block`
|
||||||
|
- The following API methods have been renamed:
|
||||||
|
- `Block->isSameType()` -> `Block->hasSameTypeId()`
|
||||||
|
- `Block->describeType()` -> `Block->describeBlockItemState()`
|
||||||
|
- `Block->describeState()` -> `Block->describeBlockOnlyState()`
|
||||||
|
- The following API methods have been removed:
|
||||||
|
- `Block->getRequiredTypeDataBits()`
|
||||||
|
- `Block->getRequiredStateDataBits()`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public Block->generateStatePermutations() : \Generator<int, Block, void, void>` - yields all possible states this block type can be in (used for `RuntimeBlockStateRegistry`)
|
||||||
|
- The following API methods have signature changes:
|
||||||
|
- `Sapling::__construct()` now accepts `SaplingType $saplingType` instead of `TreeType $treeType`
|
||||||
|
- `RuntimeBlockStateRegistry->register()` no longer accepts an `$override` parameter.
|
||||||
|
- The following classes have been added:
|
||||||
|
- `utils\SaplingType` - enum of all sapling types
|
||||||
|
- `utils\TreeType` has been moved to `pocketmine\world\generator\object` namespace.
|
||||||
|
|
||||||
|
### `pocketmine\data\bedrock\item\upgrade`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public ItemIdMetaUpgrader->getSchemas() : array<int, BlockStateUpgradeSchema>` - returns a list of loaded schemas indexed by schema ID
|
||||||
|
- `public ItemIdMetaUpgradeSchema->getRenamedIds() : array<string, string>` - returns a map of old ID -> new ID
|
||||||
|
- `public ItemIdMetaUpgradeSchema->getRemappedMetas() : array<string, array<int, string>>` - returns a map of old ID -> list of old meta -> new ID
|
||||||
|
|
||||||
|
### `pocketmine\event\block`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public BlockGrowEvent->getPlayer() : ?Player` - returns the player that triggered the block growth, or `null` if it was not triggered by a player
|
||||||
|
- The following API methods have signature changes:
|
||||||
|
- `BlockGrowEvent::__construct()` now accepts an optional `?Player $player` parameter.
|
||||||
|
|
||||||
|
### `pocketmine\event\world`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `WorldDisplayNameChangeEvent` - called when a world's display name is changed
|
||||||
|
|
||||||
|
### `pocketmine\item`
|
||||||
|
- `Boat` now uses a new `BoatType` enum instead of `TreeType`. This is because not all tree types have an associated boat type, and some boat types are not made from tree materials (e.g. bamboo raft).
|
||||||
|
- The following API methods have been removed:
|
||||||
|
- `Boat->getWoodType()`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public Boat->getType() : BoatType`
|
||||||
|
- `public Item->getStateId() : int` - returns an encoded ID containing the item type ID and encoded item state
|
||||||
|
- The following API methods have been renamed:
|
||||||
|
- `Item->describeType()` -> `Item->describeState()`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BoatType` - enum of all boat types
|
||||||
|
- The following API methods have signature changes:
|
||||||
|
- `BoatType::__construct()` now accepts `BoatType $boatType` instead of `TreeType $woodType`.
|
||||||
|
|
||||||
|
### `pocketmine\world`
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `public World->setDisplayName(string $name) : void`
|
||||||
|
|
||||||
|
### `pocketmine\world\format`
|
||||||
|
- Fixed outdated documentation for various methods of `Chunk`.
|
||||||
|
|
||||||
|
### `pocketmine\world\format\io\data`
|
||||||
|
- The following API interface requirements have been added:
|
||||||
|
- `public WorldData->setDisplayName(string $value) : void`
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Reduced global usage in world providers. In the future, we want to have blockstate deserializers etc. injected rather than being global singletons.
|
||||||
|
- `BlockStateUpgrader` now always updates the blockstate version, even if no changes were made. PM itself doesn't require this, but it's useful for tools to know whether to upgrade the data again (e.g. in testing scenarios).
|
||||||
|
- `BlockStateDictionary` memory usage is now reduced from 9 MB to 3.5 MB using various techniques, including string reuse and binary-encoded states.
|
||||||
|
- `RuntimeBlockMapping` has been renamed to `BlockTranslator`.
|
||||||
|
- Singletons in the `pocketmine\network\mcpe\convert` package have been centralized under `TypeConverter`. In the future, this will be injected where needed, allowing different converters to be used for different sessions (useful for multiversion).
|
||||||
|
- Overriding of serializers and deserializers of items and blocks is now consistently disallowed. Due to the lack of a good reason to allow overriding built-in blocks and items, this is no longer allowed.
|
||||||
|
|
||||||
|
# 5.0.0-BETA4
|
||||||
|
Released 23rd May 2023.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- [`ext-pmmpthread` version 6.0.0](https://github.com/pmmp/ext-pmmpthread/releases/6.0.0) (renamed from `ext-pthreads`) is now required. This version has API changes compared to pthreads v5. Please read the linked changelog for details.
|
||||||
|
- [`pocketmine/snooze` version 0.5.0](https://github.com/pmmp/Snooze/releases/0.5.0) is now required.
|
||||||
|
- `pocketmine/classloader` and `pocketmine/log-pthreads` packages have been removed. The relevant classes from these packages are now included in-house in the `pocketmine/thread` namespace.
|
||||||
|
- `BaseClassLoader` is replaced with `pocketmine\thread\ThreadSafeClassLoader`
|
||||||
|
- `ThreadedLogger` is replaced by `pocketmine\thread\ThreadSafeLogger`
|
||||||
|
- `AttachableThreadedLogger` is replaced by `pocketmine\thread\AttachableThreadSafeLogger`
|
||||||
|
- `ThreadedLoggerAttachment` is replaced by `pocketmine\thread\ThreadSafeLoggerAttachment`
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed crash on unknown blocks due to late initialization of properties in `UnknownBlock`.
|
||||||
|
|
||||||
|
## API changes
|
||||||
|
### `pocketmine\scheduler`
|
||||||
|
- `AsyncTask->setResult()` now works with thread-safe objects. This was previously not possible due to limitations in the `pthreads` extension.
|
||||||
@ -5,7 +5,7 @@
|
|||||||
"homepage": "https://pmmp.io",
|
"homepage": "https://pmmp.io",
|
||||||
"license": "LGPL-3.0",
|
"license": "LGPL-3.0",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0",
|
"php": "^8.1",
|
||||||
"php-64bit": "*",
|
"php-64bit": "*",
|
||||||
"ext-chunkutils2": "^0.3.1",
|
"ext-chunkutils2": "^0.3.1",
|
||||||
"ext-crypto": "^0.3.1",
|
"ext-crypto": "^0.3.1",
|
||||||
@ -22,7 +22,7 @@
|
|||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"ext-pcre": "*",
|
"ext-pcre": "*",
|
||||||
"ext-phar": "*",
|
"ext-phar": "*",
|
||||||
"ext-pthreads": "^4.0",
|
"ext-pmmpthread": "^6.0",
|
||||||
"ext-reflection": "*",
|
"ext-reflection": "*",
|
||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*",
|
||||||
"ext-sockets": "*",
|
"ext-sockets": "*",
|
||||||
@ -34,28 +34,28 @@
|
|||||||
"adhocore/json-comment": "^1.1",
|
"adhocore/json-comment": "^1.1",
|
||||||
"fgrosse/phpasn1": "^2.3",
|
"fgrosse/phpasn1": "^2.3",
|
||||||
"netresearch/jsonmapper": "^4.0",
|
"netresearch/jsonmapper": "^4.0",
|
||||||
"pocketmine/bedrock-data": "~1.5.0+bedrock-1.18.0",
|
"pocketmine/bedrock-block-upgrade-schema": "~2.1.0+bedrock-1.19.80",
|
||||||
"pocketmine/bedrock-protocol": "~7.3.0+bedrock-1.18.0",
|
"pocketmine/bedrock-data": "~2.2.0+bedrock-1.19.80",
|
||||||
|
"pocketmine/bedrock-item-upgrade-schema": "~1.2.0+bedrock-1.19.80",
|
||||||
|
"pocketmine/bedrock-protocol": "~21.0.0+bedrock-1.19.80",
|
||||||
"pocketmine/binaryutils": "^0.2.1",
|
"pocketmine/binaryutils": "^0.2.1",
|
||||||
"pocketmine/callback-validator": "^1.0.2",
|
"pocketmine/callback-validator": "^1.0.2",
|
||||||
"pocketmine/classloader": "^0.2.0",
|
"pocketmine/color": "^0.3.0",
|
||||||
"pocketmine/color": "^0.2.0",
|
|
||||||
"pocketmine/errorhandler": "^0.6.0",
|
"pocketmine/errorhandler": "^0.6.0",
|
||||||
"pocketmine/locale-data": "~2.3.0",
|
"pocketmine/locale-data": "~2.19.0",
|
||||||
"pocketmine/log": "^0.4.0",
|
"pocketmine/log": "^0.4.0",
|
||||||
"pocketmine/log-pthreads": "^0.4.0",
|
|
||||||
"pocketmine/math": "^0.4.0",
|
"pocketmine/math": "^0.4.0",
|
||||||
"pocketmine/nbt": "^0.3.2",
|
"pocketmine/nbt": "^0.3.2",
|
||||||
"pocketmine/raklib": "^0.14.2",
|
"pocketmine/raklib": "^0.15.0",
|
||||||
"pocketmine/raklib-ipc": "^0.1.0",
|
"pocketmine/raklib-ipc": "^0.2.0",
|
||||||
"pocketmine/snooze": "^0.3.0",
|
"pocketmine/snooze": "^0.5.0",
|
||||||
"ramsey/uuid": "^4.1",
|
"ramsey/uuid": "^4.1",
|
||||||
"webmozart/path-util": "^2.3"
|
"symfony/filesystem": "^5.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpstan/phpstan": "1.3.3",
|
"phpstan/phpstan": "1.10.15",
|
||||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||||
"phpunit/phpunit": "^9.2"
|
"phpunit/phpunit": "^9.2"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -74,12 +74,12 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "8.0.0"
|
"php": "8.1.0"
|
||||||
},
|
},
|
||||||
"sort-packages": true
|
"sort-packages": true
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/ConsoleScript.php --make ./ --relative tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||||
"make-server": [
|
"make-server": [
|
||||||
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
||||||
"@php -dphar.readonly=0 build/server-phar.php"
|
"@php -dphar.readonly=0 build/server-phar.php"
|
||||||
|
|||||||
1383
composer.lock
generated
1383
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
# Doxyfile 1.8.15
|
# Doxyfile 1.9.3
|
||||||
|
|
||||||
# This file describes the settings to be used by the documentation system
|
# This file describes the settings to be used by the documentation system
|
||||||
# doxygen (www.doxygen.org) for a project.
|
# doxygen (www.doxygen.org) for a project.
|
||||||
@ -93,14 +93,6 @@ ALLOW_UNICODE_NAMES = NO
|
|||||||
|
|
||||||
OUTPUT_LANGUAGE = English
|
OUTPUT_LANGUAGE = English
|
||||||
|
|
||||||
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
|
|
||||||
# documentation generated by doxygen is written. Doxygen will use this
|
|
||||||
# information to generate all generated output in the proper direction.
|
|
||||||
# Possible values are: None, LTR, RTL and Context.
|
|
||||||
# The default value is: None.
|
|
||||||
|
|
||||||
OUTPUT_TEXT_DIRECTION = None
|
|
||||||
|
|
||||||
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
||||||
# descriptions after the members that are listed in the file and class
|
# descriptions after the members that are listed in the file and class
|
||||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||||
@ -197,6 +189,16 @@ SHORT_NAMES = NO
|
|||||||
|
|
||||||
JAVADOC_AUTOBRIEF = NO
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
|
||||||
|
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
|
||||||
|
# such as
|
||||||
|
# /***************
|
||||||
|
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
|
||||||
|
# Javadoc-style will behave just like regular comments and it will not be
|
||||||
|
# interpreted by doxygen.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
JAVADOC_BANNER = NO
|
||||||
|
|
||||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||||
@ -217,6 +219,14 @@ QT_AUTOBRIEF = NO
|
|||||||
|
|
||||||
MULTILINE_CPP_IS_BRIEF = NO
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
|
||||||
|
# By default Python docstrings are displayed as preformatted text and doxygen's
|
||||||
|
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
|
||||||
|
# doxygen's special commands can be used and the contents of the docstring
|
||||||
|
# documentation blocks is shown as doxygen documentation.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
PYTHON_DOCSTRING = YES
|
||||||
|
|
||||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||||
# documentation from any documented member that it re-implements.
|
# documentation from any documented member that it re-implements.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@ -240,25 +250,19 @@ TAB_SIZE = 4
|
|||||||
# the documentation. An alias has the form:
|
# the documentation. An alias has the form:
|
||||||
# name=value
|
# name=value
|
||||||
# For example adding
|
# For example adding
|
||||||
# "sideeffect=@par Side Effects:\n"
|
# "sideeffect=@par Side Effects:^^"
|
||||||
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
||||||
# documentation, which will result in a user-defined paragraph with heading
|
# documentation, which will result in a user-defined paragraph with heading
|
||||||
# "Side Effects:". You can put \n's in the value part of an alias to insert
|
# "Side Effects:". Note that you cannot put \n's in the value part of an alias
|
||||||
# newlines (in the resulting output). You can put ^^ in the value part of an
|
# to insert newlines (in the resulting output). You can put ^^ in the value part
|
||||||
# alias to insert a newline as if a physical newline was in the original file.
|
# of an alias to insert a newline as if a physical newline was in the original
|
||||||
# When you need a literal { or } or , in the value part of an alias you have to
|
# file. When you need a literal { or } or , in the value part of an alias you
|
||||||
# escape them by means of a backslash (\), this can lead to conflicts with the
|
# have to escape them by means of a backslash (\), this can lead to conflicts
|
||||||
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
# with the commands \{ and \} for these it is advised to use the version @{ and
|
||||||
# a double escape (\\{ and \\})
|
# @} or use a double escape (\\{ and \\})
|
||||||
|
|
||||||
ALIASES =
|
ALIASES =
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
|
||||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
|
||||||
# will allow you to use the command class in the itcl::class meaning.
|
|
||||||
|
|
||||||
TCL_SUBST =
|
|
||||||
|
|
||||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||||
# only. Doxygen will then generate output that is more tailored for C. For
|
# only. Doxygen will then generate output that is more tailored for C. For
|
||||||
# instance, some of the names that are used will be different. The list of all
|
# instance, some of the names that are used will be different. The list of all
|
||||||
@ -299,19 +303,22 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
|||||||
# parses. With this tag you can assign which parser to use for a given
|
# parses. With this tag you can assign which parser to use for a given
|
||||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||||
# Fortran), use: inc=Fortran f=C.
|
# use: inc=Fortran f=C.
|
||||||
#
|
#
|
||||||
# Note: For files without extension you can use no_extension as a placeholder.
|
# Note: For files without extension you can use no_extension as a placeholder.
|
||||||
#
|
#
|
||||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||||
# the files are not read by doxygen.
|
# the files are not read by doxygen. When specifying no_extension you should add
|
||||||
|
# * to the FILE_PATTERNS.
|
||||||
|
#
|
||||||
|
# Note see also the list of default file extension mappings.
|
||||||
|
|
||||||
EXTENSION_MAPPING =
|
EXTENSION_MAPPING =
|
||||||
|
|
||||||
@ -329,7 +336,7 @@ MARKDOWN_SUPPORT = YES
|
|||||||
# to that level are automatically included in the table of contents, even if
|
# to that level are automatically included in the table of contents, even if
|
||||||
# they do not have an id attribute.
|
# they do not have an id attribute.
|
||||||
# Note: This feature currently applies only to Markdown headings.
|
# Note: This feature currently applies only to Markdown headings.
|
||||||
# Minimum value: 0, maximum value: 99, default value: 0.
|
# Minimum value: 0, maximum value: 99, default value: 5.
|
||||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||||
|
|
||||||
TOC_INCLUDE_HEADINGS = 0
|
TOC_INCLUDE_HEADINGS = 0
|
||||||
@ -445,6 +452,19 @@ TYPEDEF_HIDES_STRUCT = NO
|
|||||||
|
|
||||||
LOOKUP_CACHE_SIZE = 0
|
LOOKUP_CACHE_SIZE = 0
|
||||||
|
|
||||||
|
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
|
||||||
|
# during processing. When set to 0 doxygen will based this on the number of
|
||||||
|
# cores available in the system. You can set it explicitly to a value larger
|
||||||
|
# than 0 to get more control over the balance between CPU load and processing
|
||||||
|
# speed. At this moment only the input processing can be done using multiple
|
||||||
|
# threads. Since this is still an experimental feature the default is set to 1,
|
||||||
|
# which effectively disables parallel processing. Please report any issues you
|
||||||
|
# encounter. Generating dot graphs in parallel is controlled by the
|
||||||
|
# DOT_NUM_THREADS setting.
|
||||||
|
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||||
|
|
||||||
|
NUM_PROC_THREADS = 1
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Build related configuration options
|
# Build related configuration options
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@ -465,6 +485,12 @@ EXTRACT_ALL = NO
|
|||||||
|
|
||||||
EXTRACT_PRIVATE = NO
|
EXTRACT_PRIVATE = NO
|
||||||
|
|
||||||
|
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||||
|
# methods of a class will be included in the documentation.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
EXTRACT_PRIV_VIRTUAL = NO
|
||||||
|
|
||||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||||
# scope will be included in the documentation.
|
# scope will be included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@ -502,6 +528,13 @@ EXTRACT_LOCAL_METHODS = YES
|
|||||||
|
|
||||||
EXTRACT_ANON_NSPACES = YES
|
EXTRACT_ANON_NSPACES = YES
|
||||||
|
|
||||||
|
# If this flag is set to YES, the name of an unnamed parameter in a declaration
|
||||||
|
# will be determined by the corresponding definition. By default unnamed
|
||||||
|
# parameters remain unnamed in the output.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
RESOLVE_UNNAMED_PARAMS = YES
|
||||||
|
|
||||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||||
# undocumented members inside documented classes or files. If set to NO these
|
# undocumented members inside documented classes or files. If set to NO these
|
||||||
# members will be included in the various overviews, but no documentation
|
# members will be included in the various overviews, but no documentation
|
||||||
@ -519,8 +552,8 @@ HIDE_UNDOC_MEMBERS = NO
|
|||||||
HIDE_UNDOC_CLASSES = NO
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
|
||||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
# declarations. If set to NO, these declarations will be included in the
|
||||||
# included in the documentation.
|
# documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
HIDE_FRIEND_COMPOUNDS = NO
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
@ -539,11 +572,18 @@ HIDE_IN_BODY_DOCS = YES
|
|||||||
|
|
||||||
INTERNAL_DOCS = NO
|
INTERNAL_DOCS = NO
|
||||||
|
|
||||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
|
||||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
# able to match the capabilities of the underlying filesystem. In case the
|
||||||
# allowed. This is useful if you have classes or files whose names only differ
|
# filesystem is case sensitive (i.e. it supports files in the same directory
|
||||||
# in case and if your file system supports case sensitive file names. Windows
|
# whose names only differ in casing), the option must be set to YES to properly
|
||||||
# and Mac users are advised to set this option to NO.
|
# deal with such files in case they appear in the input. For filesystems that
|
||||||
|
# are not case sensitive the option should be be set to NO to properly deal with
|
||||||
|
# output files written for symbols that only differ in casing, such as for two
|
||||||
|
# classes, one named CLASS and the other named Class, and to also support
|
||||||
|
# references to files without having to specify the exact matching casing. On
|
||||||
|
# Windows (including Cygwin) and MacOS, users should typically set this option
|
||||||
|
# to NO, whereas on Linux or other Unix flavors it should typically be set to
|
||||||
|
# YES.
|
||||||
# The default value is: system dependent.
|
# The default value is: system dependent.
|
||||||
|
|
||||||
CASE_SENSE_NAMES = NO
|
CASE_SENSE_NAMES = NO
|
||||||
@ -562,6 +602,12 @@ HIDE_SCOPE_NAMES = NO
|
|||||||
|
|
||||||
HIDE_COMPOUND_REFERENCE= NO
|
HIDE_COMPOUND_REFERENCE= NO
|
||||||
|
|
||||||
|
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
|
||||||
|
# will show which file needs to be included to use the class.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
SHOW_HEADERFILE = YES
|
||||||
|
|
||||||
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
||||||
# the files that are included by a file in the documentation of that file.
|
# the files that are included by a file in the documentation of that file.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@ -719,7 +765,8 @@ FILE_VERSION_FILTER =
|
|||||||
# output files in an output format independent way. To create the layout file
|
# output files in an output format independent way. To create the layout file
|
||||||
# that represents doxygen's defaults, run doxygen with the -l option. You can
|
# that represents doxygen's defaults, run doxygen with the -l option. You can
|
||||||
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
|
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
|
||||||
# will be used as the name of the layout file.
|
# will be used as the name of the layout file. See also section "Changing the
|
||||||
|
# layout of pages" for information.
|
||||||
#
|
#
|
||||||
# Note that if you run doxygen from a directory containing a file called
|
# Note that if you run doxygen from a directory containing a file called
|
||||||
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
||||||
@ -765,24 +812,35 @@ WARNINGS = NO
|
|||||||
WARN_IF_UNDOCUMENTED = NO
|
WARN_IF_UNDOCUMENTED = NO
|
||||||
|
|
||||||
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
||||||
# potential errors in the documentation, such as not documenting some parameters
|
# potential errors in the documentation, such as documenting some parameters in
|
||||||
# in a documented function, or documenting parameters that don't exist or using
|
# a documented function twice, or documenting parameters that don't exist or
|
||||||
# markup commands wrongly.
|
# using markup commands wrongly.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
WARN_IF_DOC_ERROR = YES
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
|
||||||
|
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
|
||||||
|
# function parameter documentation. If set to NO, doxygen will accept that some
|
||||||
|
# parameters have no documentation without warning.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
WARN_IF_INCOMPLETE_DOC = YES
|
||||||
|
|
||||||
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
||||||
# are documented, but have no documentation for their parameters or return
|
# are documented, but have no documentation for their parameters or return
|
||||||
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
# value. If set to NO, doxygen will only warn about wrong parameter
|
||||||
# parameter documentation, but not about the absence of documentation. If
|
# documentation, but not about the absence of documentation. If EXTRACT_ALL is
|
||||||
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
|
# set to YES then this flag will automatically be disabled. See also
|
||||||
|
# WARN_IF_INCOMPLETE_DOC
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
WARN_NO_PARAMDOC = NO
|
WARN_NO_PARAMDOC = NO
|
||||||
|
|
||||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||||
# a warning is encountered.
|
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||||
|
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||||
|
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||||
|
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
WARN_AS_ERROR = NO
|
WARN_AS_ERROR = NO
|
||||||
@ -799,7 +857,10 @@ WARN_FORMAT = "$file:$line: $text"
|
|||||||
|
|
||||||
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
|
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
|
||||||
# messages should be written. If left blank the output is written to standard
|
# messages should be written. If left blank the output is written to standard
|
||||||
# error (stderr).
|
# error (stderr). In case the file specified cannot be opened for writing the
|
||||||
|
# warning and error messages are written to standard error. When as file - is
|
||||||
|
# specified the warning and error messages are written to standard output
|
||||||
|
# (stdout).
|
||||||
|
|
||||||
WARN_LOGFILE =
|
WARN_LOGFILE =
|
||||||
|
|
||||||
@ -820,8 +881,8 @@ INPUT = ../src \
|
|||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
# documentation (see:
|
||||||
# possible encodings.
|
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
|
||||||
# The default value is: UTF-8.
|
# The default value is: UTF-8.
|
||||||
|
|
||||||
INPUT_ENCODING = UTF-8
|
INPUT_ENCODING = UTF-8
|
||||||
@ -834,11 +895,15 @@ INPUT_ENCODING = UTF-8
|
|||||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||||
# read by doxygen.
|
# read by doxygen.
|
||||||
#
|
#
|
||||||
|
# Note the list of default checked file patterns might differ from the list of
|
||||||
|
# default file extension mappings.
|
||||||
|
#
|
||||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
|
||||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
|
||||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
|
||||||
|
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||||
|
|
||||||
FILE_PATTERNS = *.php
|
FILE_PATTERNS = *.php
|
||||||
|
|
||||||
@ -883,7 +948,7 @@ EXCLUDE_PATTERNS = */bin/* \
|
|||||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||||
# output. The symbol name can be a fully qualified name, a word, or if the
|
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||||
# AClass::ANamespace, ANamespace::*Test
|
# ANamespace::AClass, ANamespace::*Test
|
||||||
#
|
#
|
||||||
# Note that the wildcards are matched against the file with absolute path, so to
|
# Note that the wildcards are matched against the file with absolute path, so to
|
||||||
# exclude all test directories use the pattern */test/*
|
# exclude all test directories use the pattern */test/*
|
||||||
@ -1059,16 +1124,24 @@ USE_HTAGS = NO
|
|||||||
VERBATIM_HEADERS = YES
|
VERBATIM_HEADERS = YES
|
||||||
|
|
||||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
# clang parser (see:
|
||||||
# cost of reduced performance. This can be particularly helpful with template
|
# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
|
||||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
# performance. This can be particularly helpful with template rich C++ code for
|
||||||
# information.
|
# which doxygen's built-in parser lacks the necessary type information.
|
||||||
# Note: The availability of this option depends on whether or not doxygen was
|
# Note: The availability of this option depends on whether or not doxygen was
|
||||||
# generated with the -Duse_libclang=ON option for CMake.
|
# generated with the -Duse_libclang=ON option for CMake.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
CLANG_ASSISTED_PARSING = NO
|
CLANG_ASSISTED_PARSING = NO
|
||||||
|
|
||||||
|
# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
|
||||||
|
# tag is set to YES then doxygen will add the directory of each input to the
|
||||||
|
# include path.
|
||||||
|
# The default value is: YES.
|
||||||
|
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||||
|
|
||||||
|
CLANG_ADD_INC_PATHS = YES
|
||||||
|
|
||||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||||
# line options that you would normally use when invoking the compiler. Note that
|
# line options that you would normally use when invoking the compiler. Note that
|
||||||
# the include paths will already be set by doxygen for the files and directories
|
# the include paths will already be set by doxygen for the files and directories
|
||||||
@ -1078,10 +1151,13 @@ CLANG_ASSISTED_PARSING = NO
|
|||||||
CLANG_OPTIONS =
|
CLANG_OPTIONS =
|
||||||
|
|
||||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||||
# path to the compilation database (see:
|
# path to the directory containing a file called compile_commands.json. This
|
||||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
|
# file is the compilation database (see:
|
||||||
# were built. This is equivalent to specifying the "-p" option to a clang tool,
|
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
|
||||||
# such as clang-check. These options will then be passed to the parser.
|
# options used when the source files were built. This is equivalent to
|
||||||
|
# specifying the -p option to a clang tool, such as clang-check. These options
|
||||||
|
# will then be passed to the parser. Any options specified with CLANG_OPTIONS
|
||||||
|
# will be added as well.
|
||||||
# Note: The availability of this option depends on whether or not doxygen was
|
# Note: The availability of this option depends on whether or not doxygen was
|
||||||
# generated with the -Duse_libclang=ON option for CMake.
|
# generated with the -Duse_libclang=ON option for CMake.
|
||||||
|
|
||||||
@ -1098,13 +1174,6 @@ CLANG_DATABASE_PATH =
|
|||||||
|
|
||||||
ALPHABETICAL_INDEX = YES
|
ALPHABETICAL_INDEX = YES
|
||||||
|
|
||||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
|
||||||
# which the alphabetical index list will be split.
|
|
||||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
|
||||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
|
||||||
|
|
||||||
COLS_IN_ALPHA_INDEX = 5
|
|
||||||
|
|
||||||
# In case all classes in a project start with a common prefix, all classes will
|
# In case all classes in a project start with a common prefix, all classes will
|
||||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||||
@ -1204,7 +1273,7 @@ HTML_EXTRA_FILES =
|
|||||||
|
|
||||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||||
# will adjust the colors in the style sheet and background images according to
|
# will adjust the colors in the style sheet and background images according to
|
||||||
# this color. Hue is specified as an angle on a colorwheel, see
|
# this color. Hue is specified as an angle on a color-wheel, see
|
||||||
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||||
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||||
# purple, and 360 is red again.
|
# purple, and 360 is red again.
|
||||||
@ -1214,7 +1283,7 @@ HTML_EXTRA_FILES =
|
|||||||
HTML_COLORSTYLE_HUE = 220
|
HTML_COLORSTYLE_HUE = 220
|
||||||
|
|
||||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
||||||
# in the HTML output. For a value of 0 the output will use grayscales only. A
|
# in the HTML output. For a value of 0 the output will use gray-scales only. A
|
||||||
# value of 255 will produce the most vivid colors.
|
# value of 255 will produce the most vivid colors.
|
||||||
# Minimum value: 0, maximum value: 255, default value: 100.
|
# Minimum value: 0, maximum value: 255, default value: 100.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
@ -1239,13 +1308,13 @@ HTML_COLORSTYLE_GAMMA = 80
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_TIMESTAMP = YES
|
HTML_TIMESTAMP = NO
|
||||||
|
|
||||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||||
# documentation will contain a main index with vertical navigation menus that
|
# documentation will contain a main index with vertical navigation menus that
|
||||||
# are dynamically created via Javascript. If disabled, the navigation index will
|
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||||
# page. Disable this option to support browsers that do not have Javascript,
|
# page. Disable this option to support browsers that do not have JavaScript,
|
||||||
# like the Qt help browser.
|
# like the Qt help browser.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
@ -1275,10 +1344,11 @@ HTML_INDEX_NUM_ENTRIES = 100
|
|||||||
|
|
||||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
# environment (see:
|
||||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
|
||||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
# create a documentation set, doxygen will generate a Makefile in the HTML
|
||||||
# that directory and running make install will install the docset in
|
# output directory. Running make will produce the docset in that directory and
|
||||||
|
# running make install will install the docset in
|
||||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||||
# genXcode/_index.html for more information.
|
# genXcode/_index.html for more information.
|
||||||
@ -1295,6 +1365,13 @@ GENERATE_DOCSET = NO
|
|||||||
|
|
||||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
|
||||||
|
# This tag determines the URL of the docset feed. A documentation feed provides
|
||||||
|
# an umbrella under which multiple documentation sets from a single provider
|
||||||
|
# (such as a company or product suite) can be grouped.
|
||||||
|
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||||
|
|
||||||
|
DOCSET_FEEDURL =
|
||||||
|
|
||||||
# This tag specifies a string that should uniquely identify the documentation
|
# This tag specifies a string that should uniquely identify the documentation
|
||||||
# set bundle. This should be a reverse domain-name style string, e.g.
|
# set bundle. This should be a reverse domain-name style string, e.g.
|
||||||
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
|
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
|
||||||
@ -1320,8 +1397,12 @@ DOCSET_PUBLISHER_NAME = Publisher
|
|||||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
# on Windows. In the beginning of 2021 Microsoft took the original page, with
|
||||||
# Windows.
|
# a.o. the download links, offline the HTML help workshop was already many years
|
||||||
|
# in maintenance mode). You can download the HTML help workshop from the web
|
||||||
|
# archives at Installation executable (see:
|
||||||
|
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
|
||||||
|
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
|
||||||
#
|
#
|
||||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||||
@ -1351,7 +1432,7 @@ CHM_FILE =
|
|||||||
HHC_LOCATION =
|
HHC_LOCATION =
|
||||||
|
|
||||||
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
||||||
# (YES) or that it should be included in the master .chm file (NO).
|
# (YES) or that it should be included in the main .chm file (NO).
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
@ -1396,7 +1477,8 @@ QCH_FILE =
|
|||||||
|
|
||||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||||
# Project output. For more information please see Qt Help Project / Namespace
|
# Project output. For more information please see Qt Help Project / Namespace
|
||||||
# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
# (see:
|
||||||
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||||
# The default value is: org.doxygen.Project.
|
# The default value is: org.doxygen.Project.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
@ -1404,8 +1486,8 @@ QHP_NAMESPACE = org.doxygen.Project
|
|||||||
|
|
||||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||||
# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
# Folders (see:
|
||||||
# folders).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
|
||||||
# The default value is: doc.
|
# The default value is: doc.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
@ -1413,30 +1495,30 @@ QHP_VIRTUAL_FOLDER = doc
|
|||||||
|
|
||||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||||
# filter to add. For more information please see Qt Help Project / Custom
|
# filter to add. For more information please see Qt Help Project / Custom
|
||||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
# Filters (see:
|
||||||
# filters).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_CUST_FILTER_NAME =
|
QHP_CUST_FILTER_NAME =
|
||||||
|
|
||||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
# Filters (see:
|
||||||
# filters).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_CUST_FILTER_ATTRS =
|
QHP_CUST_FILTER_ATTRS =
|
||||||
|
|
||||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||||
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_SECT_FILTER_ATTRS =
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
|
||||||
# The QHG_LOCATION tag can be used to specify the location of Qt's
|
# The QHG_LOCATION tag can be used to specify the location (absolute path
|
||||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
|
||||||
# generated .qhp file.
|
# run qhelpgenerator on the generated .qhp file.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHG_LOCATION =
|
QHG_LOCATION =
|
||||||
@ -1479,16 +1561,28 @@ DISABLE_INDEX = NO
|
|||||||
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
||||||
# (i.e. any modern browser). Windows users are probably better off using the
|
# (i.e. any modern browser). Windows users are probably better off using the
|
||||||
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
|
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
|
||||||
# further fine-tune the look of the index. As an example, the default style
|
# further fine tune the look of the index (see "Fine-tuning the output"). As an
|
||||||
# sheet generated by doxygen has an example that shows how to put an image at
|
# example, the default style sheet generated by doxygen has an example that
|
||||||
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
|
||||||
# the same information as the tab index, you could consider setting
|
# Since the tree basically has the same information as the tab index, you could
|
||||||
# DISABLE_INDEX to YES when enabling this option.
|
# consider setting DISABLE_INDEX to YES when enabling this option.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
GENERATE_TREEVIEW = YES
|
GENERATE_TREEVIEW = YES
|
||||||
|
|
||||||
|
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
|
||||||
|
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
|
||||||
|
# area (value NO) or if it should extend to the full height of the window (value
|
||||||
|
# YES). Setting this to YES gives a layout similar to
|
||||||
|
# https://docs.readthedocs.io with more room for contents, but less room for the
|
||||||
|
# project logo, title, and description. If either GENERATE_TREEVIEW or
|
||||||
|
# DISABLE_INDEX is set to NO, this option has no effect.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
|
FULL_SIDEBAR = NO
|
||||||
|
|
||||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||||
# doxygen will group on one line in the generated HTML documentation.
|
# doxygen will group on one line in the generated HTML documentation.
|
||||||
#
|
#
|
||||||
@ -1513,6 +1607,24 @@ TREEVIEW_WIDTH = 250
|
|||||||
|
|
||||||
EXT_LINKS_IN_WINDOW = NO
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
|
||||||
|
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
|
||||||
|
# addresses.
|
||||||
|
# The default value is: YES.
|
||||||
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
|
OBFUSCATE_EMAILS = YES
|
||||||
|
|
||||||
|
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||||
|
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||||
|
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||||
|
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||||
|
# Possible values are: png (the default) and svg (looks nicer but requires the
|
||||||
|
# pdf2svg or inkscape tool).
|
||||||
|
# The default value is: png.
|
||||||
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
|
HTML_FORMULA_FORMAT = png
|
||||||
|
|
||||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||||
# the HTML documentation. When you change the font size after a successful
|
# the HTML documentation. When you change the font size after a successful
|
||||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||||
@ -1533,8 +1645,14 @@ FORMULA_FONTSIZE = 10
|
|||||||
|
|
||||||
FORMULA_TRANSPARENT = YES
|
FORMULA_TRANSPARENT = YES
|
||||||
|
|
||||||
|
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||||
|
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||||
|
# the section "Including formulas" for details.
|
||||||
|
|
||||||
|
FORMULA_MACROFILE =
|
||||||
|
|
||||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||||
# https://www.mathjax.org) which uses client side Javascript for the rendering
|
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||||
# installed or if you want to formulas look prettier in the HTML output. When
|
# installed or if you want to formulas look prettier in the HTML output. When
|
||||||
# enabled you may also need to install MathJax separately and configure the path
|
# enabled you may also need to install MathJax separately and configure the path
|
||||||
@ -1544,11 +1662,29 @@ FORMULA_TRANSPARENT = YES
|
|||||||
|
|
||||||
USE_MATHJAX = YES
|
USE_MATHJAX = YES
|
||||||
|
|
||||||
|
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
|
||||||
|
# Note that the different versions of MathJax have different requirements with
|
||||||
|
# regards to the different settings, so it is possible that also other MathJax
|
||||||
|
# settings have to be changed when switching between the different MathJax
|
||||||
|
# versions.
|
||||||
|
# Possible values are: MathJax_2 and MathJax_3.
|
||||||
|
# The default value is: MathJax_2.
|
||||||
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
|
MATHJAX_VERSION = MathJax_2
|
||||||
|
|
||||||
# When MathJax is enabled you can set the default output format to be used for
|
# When MathJax is enabled you can set the default output format to be used for
|
||||||
# the MathJax output. See the MathJax site (see:
|
# the MathJax output. For more details about the output format see MathJax
|
||||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
# version 2 (see:
|
||||||
|
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
|
||||||
|
# (see:
|
||||||
|
# http://docs.mathjax.org/en/latest/web/components/output.html).
|
||||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
|
||||||
|
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
|
||||||
|
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
|
||||||
|
# is the name for Mathjax version 3, for MathJax version 2 this will be
|
||||||
|
# translated into HTML-CSS) and SVG.
|
||||||
# The default value is: HTML-CSS.
|
# The default value is: HTML-CSS.
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
@ -1561,22 +1697,29 @@ MATHJAX_FORMAT = HTML-CSS
|
|||||||
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
||||||
# Content Delivery Network so you can quickly see the result without installing
|
# Content Delivery Network so you can quickly see the result without installing
|
||||||
# MathJax. However, it is strongly recommended to install a local copy of
|
# MathJax. However, it is strongly recommended to install a local copy of
|
||||||
# MathJax from https://www.mathjax.org before deployment.
|
# MathJax from https://www.mathjax.org before deployment. The default value is:
|
||||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
|
||||||
|
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
|
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
|
||||||
|
|
||||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
||||||
# extension names that should be enabled during MathJax rendering. For example
|
# extension names that should be enabled during MathJax rendering. For example
|
||||||
|
# for MathJax version 2 (see
|
||||||
|
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
|
||||||
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||||
|
# For example for MathJax version 3 (see
|
||||||
|
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
|
||||||
|
# MATHJAX_EXTENSIONS = ams
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
MATHJAX_EXTENSIONS =
|
MATHJAX_EXTENSIONS =
|
||||||
|
|
||||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
# (see:
|
||||||
|
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
|
||||||
# example see the documentation.
|
# example see the documentation.
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
@ -1604,7 +1747,7 @@ MATHJAX_CODEFILE =
|
|||||||
SEARCHENGINE = YES
|
SEARCHENGINE = YES
|
||||||
|
|
||||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||||
# implemented using a web server instead of a web client using Javascript. There
|
# implemented using a web server instead of a web client using JavaScript. There
|
||||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||||
@ -1623,7 +1766,8 @@ SERVER_BASED_SEARCH = NO
|
|||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: https://xapian.org/).
|
# Xapian (see:
|
||||||
|
# https://xapian.org/).
|
||||||
#
|
#
|
||||||
# See the section "External Indexing and Searching" for details.
|
# See the section "External Indexing and Searching" for details.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@ -1636,8 +1780,9 @@ EXTERNAL_SEARCH = NO
|
|||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
# Xapian (see:
|
||||||
# Searching" for details.
|
# https://xapian.org/). See the section "External Indexing and Searching" for
|
||||||
|
# details.
|
||||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||||
|
|
||||||
SEARCHENGINE_URL =
|
SEARCHENGINE_URL =
|
||||||
@ -1708,10 +1853,11 @@ LATEX_CMD_NAME = latex
|
|||||||
MAKEINDEX_CMD_NAME = makeindex
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
|
||||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
||||||
# generate index for LaTeX.
|
# generate index for LaTeX. In case there is no backslash (\) as first character
|
||||||
|
# it will be automatically added in the LaTeX code.
|
||||||
# Note: This tag is used in the generated output file (.tex).
|
# Note: This tag is used in the generated output file (.tex).
|
||||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
||||||
# The default value is: \makeindex.
|
# The default value is: makeindex.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_MAKEINDEX_CMD = \makeindex
|
LATEX_MAKEINDEX_CMD = \makeindex
|
||||||
@ -1745,29 +1891,31 @@ PAPER_TYPE = a4
|
|||||||
|
|
||||||
EXTRA_PACKAGES =
|
EXTRA_PACKAGES =
|
||||||
|
|
||||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
|
# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
|
||||||
# generated LaTeX document. The header should contain everything until the first
|
# the generated LaTeX document. The header should contain everything until the
|
||||||
# chapter. If it is left blank doxygen will generate a standard header. See
|
# first chapter. If it is left blank doxygen will generate a standard header. It
|
||||||
# section "Doxygen usage" for information on how to let doxygen write the
|
# is highly recommended to start with a default header using
|
||||||
# default header to a separate file.
|
# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
|
||||||
|
# and then modify the file new_header.tex. See also section "Doxygen usage" for
|
||||||
|
# information on how to generate the default header that doxygen normally uses.
|
||||||
#
|
#
|
||||||
# Note: Only use a user-defined header if you know what you are doing! The
|
# Note: Only use a user-defined header if you know what you are doing!
|
||||||
# following commands have a special meaning inside the header: $title,
|
# Note: The header is subject to change so you typically have to regenerate the
|
||||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
# default header when upgrading to a newer version of doxygen. The following
|
||||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
|
# commands have a special meaning inside the header (and footer): For a
|
||||||
# string, for the replacement values of the other commands the user is referred
|
# description of the possible markers and block names see the documentation.
|
||||||
# to HTML_HEADER.
|
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_HEADER =
|
LATEX_HEADER =
|
||||||
|
|
||||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
|
||||||
# generated LaTeX document. The footer should contain everything after the last
|
# the generated LaTeX document. The footer should contain everything after the
|
||||||
# chapter. If it is left blank doxygen will generate a standard footer. See
|
# last chapter. If it is left blank doxygen will generate a standard footer. See
|
||||||
# LATEX_HEADER for more information on how to generate a default footer and what
|
# LATEX_HEADER for more information on how to generate a default footer and what
|
||||||
# special commands can be used inside the footer.
|
# special commands can be used inside the footer. See also section "Doxygen
|
||||||
#
|
# usage" for information on how to generate the default footer that doxygen
|
||||||
# Note: Only use a user-defined footer if you know what you are doing!
|
# normally uses. Note: Only use a user-defined footer if you know what you are
|
||||||
|
# doing!
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_FOOTER =
|
LATEX_FOOTER =
|
||||||
@ -1800,9 +1948,11 @@ LATEX_EXTRA_FILES =
|
|||||||
|
|
||||||
PDF_HYPERLINKS = YES
|
PDF_HYPERLINKS = YES
|
||||||
|
|
||||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
|
||||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
|
||||||
# higher quality PDF documentation.
|
# files. Set this option to YES, to get a higher quality PDF documentation.
|
||||||
|
#
|
||||||
|
# See also section LATEX_CMD_NAME for selecting the engine.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
@ -1810,8 +1960,7 @@ USE_PDFLATEX = YES
|
|||||||
|
|
||||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
||||||
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
||||||
# if errors occur, instead of asking the user for help. This option is also used
|
# if errors occur, instead of asking the user for help.
|
||||||
# when generating formulas in HTML.
|
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
@ -1824,16 +1973,6 @@ LATEX_BATCHMODE = NO
|
|||||||
|
|
||||||
LATEX_HIDE_INDICES = NO
|
LATEX_HIDE_INDICES = NO
|
||||||
|
|
||||||
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
|
|
||||||
# code with syntax highlighting in the LaTeX output.
|
|
||||||
#
|
|
||||||
# Note that which sources are shown also depends on other settings such as
|
|
||||||
# SOURCE_BROWSER.
|
|
||||||
# The default value is: NO.
|
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
|
||||||
|
|
||||||
LATEX_SOURCE_CODE = NO
|
|
||||||
|
|
||||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||||
# bibliography, e.g. plainnat, or ieeetr. See
|
# bibliography, e.g. plainnat, or ieeetr. See
|
||||||
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||||
@ -1914,16 +2053,6 @@ RTF_STYLESHEET_FILE =
|
|||||||
|
|
||||||
RTF_EXTENSIONS_FILE =
|
RTF_EXTENSIONS_FILE =
|
||||||
|
|
||||||
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
|
|
||||||
# with syntax highlighting in the RTF output.
|
|
||||||
#
|
|
||||||
# Note that which sources are shown also depends on other settings such as
|
|
||||||
# SOURCE_BROWSER.
|
|
||||||
# The default value is: NO.
|
|
||||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
|
||||||
|
|
||||||
RTF_SOURCE_CODE = NO
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the man page output
|
# Configuration options related to the man page output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@ -2020,15 +2149,6 @@ GENERATE_DOCBOOK = NO
|
|||||||
|
|
||||||
DOCBOOK_OUTPUT = docbook
|
DOCBOOK_OUTPUT = docbook
|
||||||
|
|
||||||
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
|
|
||||||
# program listings (including syntax highlighting and cross-referencing
|
|
||||||
# information) to the DOCBOOK output. Note that enabling this will significantly
|
|
||||||
# increase the size of the DOCBOOK output.
|
|
||||||
# The default value is: NO.
|
|
||||||
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
|
||||||
|
|
||||||
DOCBOOK_PROGRAMLISTING = NO
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options for the AutoGen Definitions output
|
# Configuration options for the AutoGen Definitions output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@ -2203,34 +2323,10 @@ EXTERNAL_GROUPS = YES
|
|||||||
|
|
||||||
EXTERNAL_PAGES = YES
|
EXTERNAL_PAGES = YES
|
||||||
|
|
||||||
# The PERL_PATH should be the absolute path and name of the perl script
|
|
||||||
# interpreter (i.e. the result of 'which perl').
|
|
||||||
# The default file (with absolute path) is: /usr/bin/perl.
|
|
||||||
|
|
||||||
PERL_PATH = /usr/bin/perl
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the dot tool
|
# Configuration options related to the dot tool
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
|
|
||||||
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
|
|
||||||
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
|
|
||||||
# disabled, but it is recommended to install and use dot, since it yields more
|
|
||||||
# powerful graphs.
|
|
||||||
# The default value is: YES.
|
|
||||||
|
|
||||||
CLASS_DIAGRAMS = NO
|
|
||||||
|
|
||||||
# You can define message sequence charts within doxygen comments using the \msc
|
|
||||||
# command. Doxygen will then run the mscgen tool (see:
|
|
||||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
|
||||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
|
||||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
|
||||||
# default search path.
|
|
||||||
|
|
||||||
MSCGEN_PATH =
|
|
||||||
|
|
||||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||||
# then run dia to produce the diagram and insert it in the documentation. The
|
# then run dia to produce the diagram and insert it in the documentation. The
|
||||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||||
@ -2287,11 +2383,14 @@ DOT_FONTSIZE = 10
|
|||||||
|
|
||||||
DOT_FONTPATH =
|
DOT_FONTPATH =
|
||||||
|
|
||||||
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
|
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
|
||||||
# each documented class showing the direct and indirect inheritance relations.
|
# graph for each documented class showing the direct and indirect inheritance
|
||||||
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
|
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
|
||||||
|
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
|
||||||
|
# to TEXT the direct and indirect inheritance relations will be shown as texts /
|
||||||
|
# links.
|
||||||
|
# Possible values are: NO, YES, TEXT and GRAPH.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
|
||||||
|
|
||||||
CLASS_GRAPH = YES
|
CLASS_GRAPH = YES
|
||||||
|
|
||||||
@ -2328,10 +2427,32 @@ UML_LOOK = YES
|
|||||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||||
# 10.
|
# 10.
|
||||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag UML_LOOK is set to YES.
|
||||||
|
|
||||||
UML_LIMIT_NUM_FIELDS = 10
|
UML_LIMIT_NUM_FIELDS = 10
|
||||||
|
|
||||||
|
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
|
||||||
|
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
|
||||||
|
# tag is set to YES, doxygen will add type and arguments for attributes and
|
||||||
|
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
|
||||||
|
# will not generate fields with class member information in the UML graphs. The
|
||||||
|
# class diagrams will look similar to the default class diagrams but using UML
|
||||||
|
# notation for the relationships.
|
||||||
|
# Possible values are: NO, YES and NONE.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag UML_LOOK is set to YES.
|
||||||
|
|
||||||
|
DOT_UML_DETAILS = NO
|
||||||
|
|
||||||
|
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||||
|
# to display on a single line. If the actual line length exceeds this threshold
|
||||||
|
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||||
|
# to avoid ugly line breaks.
|
||||||
|
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||||
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
|
DOT_WRAP_THRESHOLD = 17
|
||||||
|
|
||||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||||
# collaboration graphs will show the relations between templates and their
|
# collaboration graphs will show the relations between templates and their
|
||||||
# instances.
|
# instances.
|
||||||
@ -2398,6 +2519,13 @@ GRAPHICAL_HIERARCHY = YES
|
|||||||
|
|
||||||
DIRECTORY_GRAPH = YES
|
DIRECTORY_GRAPH = YES
|
||||||
|
|
||||||
|
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
|
||||||
|
# of child directories generated in directory dependency graphs by dot.
|
||||||
|
# Minimum value: 1, maximum value: 25, default value: 1.
|
||||||
|
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
|
||||||
|
|
||||||
|
DIR_GRAPH_MAX_DEPTH = 1
|
||||||
|
|
||||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||||
# generated by dot. For an explanation of the image formats see the section
|
# generated by dot. For an explanation of the image formats see the section
|
||||||
# output formats in the documentation of the dot tool (Graphviz (see:
|
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||||
@ -2451,10 +2579,10 @@ MSCFILE_DIRS =
|
|||||||
DIAFILE_DIRS =
|
DIAFILE_DIRS =
|
||||||
|
|
||||||
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
||||||
# path where java can find the plantuml.jar file. If left blank, it is assumed
|
# path where java can find the plantuml.jar file or to the filename of jar file
|
||||||
# PlantUML is not used or called during a preprocessing step. Doxygen will
|
# to be used. If left blank, it is assumed PlantUML is not used or called during
|
||||||
# generate a warning when it encounters a \startuml command in this case and
|
# a preprocessing step. Doxygen will generate a warning when it encounters a
|
||||||
# will not generate output for the diagram.
|
# \startuml command in this case and will not generate output for the diagram.
|
||||||
|
|
||||||
PLANTUML_JAR_PATH =
|
PLANTUML_JAR_PATH =
|
||||||
|
|
||||||
@ -2516,14 +2644,18 @@ DOT_MULTI_TARGETS = YES
|
|||||||
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
|
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
|
||||||
# explaining the meaning of the various boxes and arrows in the dot generated
|
# explaining the meaning of the various boxes and arrows in the dot generated
|
||||||
# graphs.
|
# graphs.
|
||||||
|
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
|
||||||
|
# graphical representation for inheritance and collaboration diagrams is used.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
GENERATE_LEGEND = YES
|
GENERATE_LEGEND = YES
|
||||||
|
|
||||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||||
# files that are used to generate the various graphs.
|
# files that are used to generate the various graphs.
|
||||||
|
#
|
||||||
|
# Note: This setting is not only used for dot files but also for msc temporary
|
||||||
|
# files.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
|
||||||
|
|
||||||
DOT_CLEANUP = YES
|
DOT_CLEANUP = YES
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
includes:
|
includes:
|
||||||
|
- tests/phpstan/analyse-for-current-php-version.neon.php
|
||||||
- tests/phpstan/configs/actual-problems.neon
|
- tests/phpstan/configs/actual-problems.neon
|
||||||
- tests/phpstan/configs/gc-hacks.neon
|
|
||||||
- tests/phpstan/configs/impossible-generics.neon
|
- tests/phpstan/configs/impossible-generics.neon
|
||||||
- tests/phpstan/configs/php-bugs.neon
|
- tests/phpstan/configs/php-bugs.neon
|
||||||
- tests/phpstan/configs/phpstan-bugs.neon
|
- tests/phpstan/configs/phpstan-bugs.neon
|
||||||
- tests/phpstan/configs/runtime-type-checks.neon
|
|
||||||
- tests/phpstan/configs/spl-fixed-array-sucks.neon
|
- tests/phpstan/configs/spl-fixed-array-sucks.neon
|
||||||
- vendor/phpstan/phpstan-phpunit/extension.neon
|
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||||
- vendor/phpstan/phpstan-phpunit/rules.neon
|
- vendor/phpstan/phpstan-phpunit/rules.neon
|
||||||
@ -45,7 +44,7 @@ parameters:
|
|||||||
- tests/phpstan/stubs/JsonMapper.stub
|
- tests/phpstan/stubs/JsonMapper.stub
|
||||||
- tests/phpstan/stubs/leveldb.stub
|
- tests/phpstan/stubs/leveldb.stub
|
||||||
- tests/phpstan/stubs/phpasn1.stub
|
- tests/phpstan/stubs/phpasn1.stub
|
||||||
- tests/phpstan/stubs/pthreads.stub
|
- tests/phpstan/stubs/pmmpthread.stub
|
||||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||||
staticReflectionClassNamePatterns:
|
staticReflectionClassNamePatterns:
|
||||||
- "#^COM$#"
|
- "#^COM$#"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -85,8 +85,11 @@ network:
|
|||||||
batch-threshold: 256
|
batch-threshold: 256
|
||||||
#Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage
|
#Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage
|
||||||
compression-level: 6
|
compression-level: 6
|
||||||
#Use AsyncTasks for compression. Adds half/one tick delay, less CPU load on main thread
|
#Use AsyncTasks for compression during the main game session. Increases latency, but may reduce main thread load
|
||||||
async-compression: false
|
async-compression: false
|
||||||
|
#Threshold for async compression, in bytes. Only packets larger than this will be compressed asynchronously
|
||||||
|
#Due to large overhead of AsyncTask, async compression isn't worth it except for large packets
|
||||||
|
async-compression-threshold: 10000
|
||||||
#Experimental. Use UPnP to automatically port forward
|
#Experimental. Use UPnP to automatically port forward
|
||||||
upnp-forwarding: false
|
upnp-forwarding: false
|
||||||
#Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be
|
#Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be
|
||||||
@ -119,8 +122,6 @@ chunk-sending:
|
|||||||
spawn-radius: 4
|
spawn-radius: 4
|
||||||
|
|
||||||
chunk-ticking:
|
chunk-ticking:
|
||||||
#Max amount of chunks processed each tick
|
|
||||||
per-tick: 40
|
|
||||||
#Radius of chunks around a player to tick
|
#Radius of chunks around a player to tick
|
||||||
tick-radius: 3
|
tick-radius: 3
|
||||||
#Number of blocks inside ticking areas' subchunks that get ticked every tick. Higher values will accelerate events
|
#Number of blocks inside ticking areas' subchunks that get ticked every tick. Higher values will accelerate events
|
||||||
@ -168,15 +169,45 @@ timings:
|
|||||||
host: timings.pmmp.io
|
host: timings.pmmp.io
|
||||||
|
|
||||||
console:
|
console:
|
||||||
|
#Whether to accept commands via the console. If disabled, anything typed on the console will be ignored.
|
||||||
|
#Useful to save resources on headless servers where the console is never used (e.g. hosted server, Docker, etc.)
|
||||||
|
enable-input: true
|
||||||
#Choose whether to enable server stats reporting on the console title.
|
#Choose whether to enable server stats reporting on the console title.
|
||||||
#NOTE: The title ticker will be disabled regardless if console colours are not enabled.
|
#NOTE: The title ticker will be disabled regardless if console colours are not enabled.
|
||||||
title-tick: true
|
title-tick: true
|
||||||
|
|
||||||
aliases:
|
aliases:
|
||||||
#Examples:
|
##This section allows you to add, remove or remap command aliases.
|
||||||
#showtheversion: version
|
##A single alias can call one or more other commands (or aliases).
|
||||||
|
##Aliases defined here will override any command aliases declared by plugins or PocketMine-MP itself.
|
||||||
|
|
||||||
|
##To remove an alias, set it to [], like so (note that prefixed aliases like "pocketmine:stop" will remain and can't
|
||||||
|
##be removed):
|
||||||
|
#stop: []
|
||||||
|
|
||||||
|
##Commands are not removed, only their aliases. You can still refer to a command using its full (prefixed)
|
||||||
|
##name, even if all its aliases are overwritten. The full name is usually something like "pocketmine:commandname" or
|
||||||
|
##"pluginname:commandname".
|
||||||
|
#abort: [pocketmine:stop]
|
||||||
|
|
||||||
|
##To add an alias, list the command(s) that it calls:
|
||||||
|
#showtheversion: [version]
|
||||||
#savestop: [save-all, stop]
|
#savestop: [save-all, stop]
|
||||||
|
|
||||||
|
##To invoke another command with arguments, use $1 to pass the first argument, $2 for the second etc:
|
||||||
|
#giveadmin: [op $1] ## `giveadmin alex` -> `op alex`
|
||||||
|
#kill: [suicide, say "I tried to kill $1"] ## `kill alex` -> `suicide` + `say "I tried to kill alex"`
|
||||||
|
#giverandom: [give $1 $2, say "Someone has just received a $2!"] ## `giverandom alex diamond` -> `give alex diamond` + `say "Someone has just received a diamond!"`
|
||||||
|
|
||||||
|
##To make arguments mandatory (so that the command fails if they are not provided), use $$, e.g. $$1, $$2:
|
||||||
|
#makeadmin: [op $$1] ## `makeadmin alex` -> `op alex`, `makeadmin` with no arguments = error
|
||||||
|
|
||||||
|
##To pass through a range of arguments, put a - (hyphen) after the index:
|
||||||
|
#tpalias: [tp $1-] ## `tpalias 256 70 256` -> `tp 256 70 256` - this passes arguments 1 and everything after it to the `tp` command
|
||||||
|
|
||||||
|
##To change an existing command alias and make it do something else:
|
||||||
|
#tp: [suicide]
|
||||||
|
|
||||||
worlds:
|
worlds:
|
||||||
#These settings will override the generator set in server.properties and allows loading multiple worlds
|
#These settings will override the generator set in server.properties and allows loading multiple worlds
|
||||||
#Example:
|
#Example:
|
||||||
|
|||||||
@ -10,3 +10,4 @@ resource_stack:
|
|||||||
# - natural.zip
|
# - natural.zip
|
||||||
# - vanilla.zip
|
# - vanilla.zip
|
||||||
#If you want to force clients to use vanilla resources, you must place a vanilla resource pack in your resources folder and add it to the stack here.
|
#If you want to force clients to use vanilla resources, you must place a vanilla resource pack in your resources folder and add it to the stack here.
|
||||||
|
#To specify a resource encryption key, put the key in the <resource>.key file alongside the resource pack. Example: vanilla.zip.key
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -37,4 +37,6 @@ define('pocketmine\PATH', dirname(__DIR__) . '/');
|
|||||||
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
|
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
|
||||||
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
|
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
|
||||||
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
|
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
|
||||||
|
define('pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-block-upgrade-schema/');
|
||||||
|
define('pocketmine\BEDROCK_ITEM_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-item-upgrade-schema/');
|
||||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');
|
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ use pocketmine\scheduler\GarbageCollectionTask;
|
|||||||
use pocketmine\timings\Timings;
|
use pocketmine\timings\Timings;
|
||||||
use pocketmine\utils\Process;
|
use pocketmine\utils\Process;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use Webmozart\PathUtil\Path;
|
use Symfony\Component\Filesystem\Path;
|
||||||
use function arsort;
|
use function arsort;
|
||||||
use function count;
|
use function count;
|
||||||
use function fclose;
|
use function fclose;
|
||||||
@ -49,6 +49,7 @@ use function ini_get;
|
|||||||
use function ini_set;
|
use function ini_set;
|
||||||
use function intdiv;
|
use function intdiv;
|
||||||
use function is_array;
|
use function is_array;
|
||||||
|
use function is_float;
|
||||||
use function is_object;
|
use function is_object;
|
||||||
use function is_resource;
|
use function is_resource;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
@ -69,8 +70,9 @@ use const JSON_UNESCAPED_SLASHES;
|
|||||||
use const SORT_NUMERIC;
|
use const SORT_NUMERIC;
|
||||||
|
|
||||||
class MemoryManager{
|
class MemoryManager{
|
||||||
|
private const DEFAULT_CHECK_RATE = Server::TARGET_TICKS_PER_SECOND;
|
||||||
private Server $server;
|
private const DEFAULT_CONTINUOUS_TRIGGER_RATE = Server::TARGET_TICKS_PER_SECOND * 2;
|
||||||
|
private const DEFAULT_TICKS_PER_GC = 30 * 60 * Server::TARGET_TICKS_PER_SECOND;
|
||||||
|
|
||||||
private int $memoryLimit;
|
private int $memoryLimit;
|
||||||
private int $globalMemoryLimit;
|
private int $globalMemoryLimit;
|
||||||
@ -98,8 +100,9 @@ class MemoryManager{
|
|||||||
|
|
||||||
private \Logger $logger;
|
private \Logger $logger;
|
||||||
|
|
||||||
public function __construct(Server $server){
|
public function __construct(
|
||||||
$this->server = $server;
|
private Server $server
|
||||||
|
){
|
||||||
$this->logger = new \PrefixedLogger($server->getLogger(), "Memory Manager");
|
$this->logger = new \PrefixedLogger($server->getLogger(), "Memory Manager");
|
||||||
|
|
||||||
$this->init($server->getConfigGroup());
|
$this->init($server->getConfigGroup());
|
||||||
@ -115,20 +118,12 @@ class MemoryManager{
|
|||||||
if($m <= 0){
|
if($m <= 0){
|
||||||
$defaultMemory = 0;
|
$defaultMemory = 0;
|
||||||
}else{
|
}else{
|
||||||
switch(mb_strtoupper($matches[2])){
|
$defaultMemory = match(mb_strtoupper($matches[2])){
|
||||||
case "K":
|
"K" => intdiv($m, 1024),
|
||||||
$defaultMemory = intdiv($m, 1024);
|
"M" => $m,
|
||||||
break;
|
"G" => $m * 1024,
|
||||||
case "M":
|
default => $m,
|
||||||
$defaultMemory = $m;
|
};
|
||||||
break;
|
|
||||||
case "G":
|
|
||||||
$defaultMemory = $m * 1024;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$defaultMemory = $m;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,11 +136,11 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
|
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
|
||||||
$this->checkRate = $config->getPropertyInt("memory.check-rate", 20);
|
$this->checkRate = $config->getPropertyInt("memory.check-rate", self::DEFAULT_CHECK_RATE);
|
||||||
$this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true);
|
$this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true);
|
||||||
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", 30);
|
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
|
||||||
|
|
||||||
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", 36000);
|
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", self::DEFAULT_TICKS_PER_GC);
|
||||||
$this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true);
|
$this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true);
|
||||||
$this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true);
|
$this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true);
|
||||||
|
|
||||||
@ -287,10 +282,8 @@ class MemoryManager{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Static memory dumper accessible from any thread.
|
* Static memory dumper accessible from any thread.
|
||||||
*
|
|
||||||
* @param mixed $startingObject
|
|
||||||
*/
|
*/
|
||||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
|
public static function dumpMemory(mixed $startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
|
||||||
$hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist");
|
$hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist");
|
||||||
ini_set('memory_limit', '-1');
|
ini_set('memory_limit', '-1');
|
||||||
gc_disable();
|
gc_disable();
|
||||||
@ -400,7 +393,7 @@ class MemoryManager{
|
|||||||
|
|
||||||
do{
|
do{
|
||||||
$continue = false;
|
$continue = false;
|
||||||
foreach($objects as $hash => $object){
|
foreach(Utils::stringifyKeys($objects) as $hash => $object){
|
||||||
if(!is_object($object)){
|
if(!is_object($object)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -481,13 +474,15 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $from
|
* @param object[] $objects reference parameter
|
||||||
* @param object[] $objects reference parameter
|
|
||||||
* @param int[] $refCounts reference parameter
|
* @param int[] $refCounts reference parameter
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @phpstan-param array<string, object> $objects
|
||||||
|
* @phpstan-param array<string, int> $refCounts
|
||||||
|
* @phpstan-param-out array<string, object> $objects
|
||||||
|
* @phpstan-param-out array<string, int> $refCounts
|
||||||
*/
|
*/
|
||||||
private static function continueDump($from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
|
private static function continueDump(mixed $from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : mixed{
|
||||||
if($maxNesting <= 0){
|
if($maxNesting <= 0){
|
||||||
return "(error) NESTING LIMIT REACHED";
|
return "(error) NESTING LIMIT REACHED";
|
||||||
}
|
}
|
||||||
@ -508,13 +503,20 @@ class MemoryManager{
|
|||||||
return "(error) ARRAY RECURSION LIMIT REACHED";
|
return "(error) ARRAY RECURSION LIMIT REACHED";
|
||||||
}
|
}
|
||||||
$data = [];
|
$data = [];
|
||||||
|
$numeric = 0;
|
||||||
foreach($from as $key => $value){
|
foreach($from as $key => $value){
|
||||||
$data[$key] = self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
$data[$numeric] = [
|
||||||
|
"k" => self::continueDump($key, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||||
|
"v" => self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||||
|
];
|
||||||
|
$numeric++;
|
||||||
}
|
}
|
||||||
}elseif(is_string($from)){
|
}elseif(is_string($from)){
|
||||||
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
||||||
}elseif(is_resource($from)){
|
}elseif(is_resource($from)){
|
||||||
$data = "(resource) " . print_r($from, true);
|
$data = "(resource) " . print_r($from, true);
|
||||||
|
}elseif(is_float($from)){
|
||||||
|
$data = "(float) $from";
|
||||||
}else{
|
}else{
|
||||||
$data = $from;
|
$data = $from;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ namespace pocketmine {
|
|||||||
use Composer\InstalledVersions;
|
use Composer\InstalledVersions;
|
||||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||||
use pocketmine\thread\ThreadManager;
|
use pocketmine\thread\ThreadManager;
|
||||||
|
use pocketmine\thread\ThreadSafeClassLoader;
|
||||||
use pocketmine\utils\Filesystem;
|
use pocketmine\utils\Filesystem;
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
use pocketmine\utils\Process;
|
use pocketmine\utils\Process;
|
||||||
@ -34,19 +35,23 @@ namespace pocketmine {
|
|||||||
use pocketmine\utils\Timezone;
|
use pocketmine\utils\Timezone;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\wizard\SetupWizard;
|
use pocketmine\wizard\SetupWizard;
|
||||||
use Webmozart\PathUtil\Path;
|
use Symfony\Component\Filesystem\Path;
|
||||||
use function defined;
|
use function defined;
|
||||||
use function extension_loaded;
|
use function extension_loaded;
|
||||||
|
use function function_exists;
|
||||||
use function getcwd;
|
use function getcwd;
|
||||||
|
use function is_dir;
|
||||||
|
use function mkdir;
|
||||||
use function phpversion;
|
use function phpversion;
|
||||||
use function preg_match;
|
use function preg_match;
|
||||||
use function preg_quote;
|
use function preg_quote;
|
||||||
use function realpath;
|
use function realpath;
|
||||||
use function version_compare;
|
use function version_compare;
|
||||||
|
use const DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
require_once __DIR__ . '/VersionInfo.php';
|
require_once __DIR__ . '/VersionInfo.php';
|
||||||
|
|
||||||
const MIN_PHP_VERSION = "8.0.0";
|
const MIN_PHP_VERSION = "8.1.0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $message
|
* @param string $message
|
||||||
@ -99,7 +104,7 @@ namespace pocketmine {
|
|||||||
"openssl" => "OpenSSL",
|
"openssl" => "OpenSSL",
|
||||||
"pcre" => "PCRE",
|
"pcre" => "PCRE",
|
||||||
"phar" => "Phar",
|
"phar" => "Phar",
|
||||||
"pthreads" => "pthreads",
|
"pmmpthread" => "pmmpthread",
|
||||||
"reflection" => "Reflection",
|
"reflection" => "Reflection",
|
||||||
"sockets" => "Sockets",
|
"sockets" => "Sockets",
|
||||||
"spl" => "SPL",
|
"spl" => "SPL",
|
||||||
@ -114,12 +119,9 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(($pthreads_version = phpversion("pthreads")) !== false){
|
if(($pmmpthread_version = phpversion("pmmpthread")) !== false){
|
||||||
if(substr_count($pthreads_version, ".") < 2){
|
if(version_compare($pmmpthread_version, "6.0.0-beta1") < 0 || version_compare($pmmpthread_version, "7.0.0") >= 0){
|
||||||
$pthreads_version = "0.$pthreads_version";
|
$messages[] = "pmmpthread ^6.0.0 is required, while you have $pmmpthread_version.";
|
||||||
}
|
|
||||||
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") > 0){
|
|
||||||
$messages[] = "pthreads ^4.0.0 is required, while you have $pthreads_version.";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +162,7 @@ namespace pocketmine {
|
|||||||
if(PHP_DEBUG !== 0){
|
if(PHP_DEBUG !== 0){
|
||||||
$logger->warning("This PHP binary was compiled in debug mode. This has a major impact on performance.");
|
$logger->warning("This PHP binary was compiled in debug mode. This has a major impact on performance.");
|
||||||
}
|
}
|
||||||
if(extension_loaded("xdebug")){
|
if(extension_loaded("xdebug") && (!function_exists('xdebug_info') || count(xdebug_info('mode')) !== 0)){
|
||||||
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
||||||
}
|
}
|
||||||
if(((int) ini_get('zend.assertions')) !== -1){
|
if(((int) ini_get('zend.assertions')) !== -1){
|
||||||
@ -176,10 +178,10 @@ namespace pocketmine {
|
|||||||
|
|
||||||
|
|
||||||
--------------------------------------- ! WARNING ! ---------------------------------------
|
--------------------------------------- ! WARNING ! ---------------------------------------
|
||||||
You're using PHP 8.0 with JIT enabled. This provides significant performance improvements.
|
You're using PHP with JIT enabled. This provides significant performance improvements.
|
||||||
HOWEVER, it is EXPERIMENTAL, and has already been seen to cause weird and unexpected bugs.
|
HOWEVER, it is EXPERIMENTAL, and has already been seen to cause weird and unexpected bugs.
|
||||||
Proceed with caution.
|
Proceed with caution.
|
||||||
If you want to report any bugs, make sure to mention that you are using PHP 8.0 with JIT.
|
If you want to report any bugs, make sure to mention that you have enabled PHP JIT.
|
||||||
To turn off JIT, change `opcache.jit` to `0` in your php.ini file.
|
To turn off JIT, change `opcache.jit` to `0` in your php.ini file.
|
||||||
-------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -200,6 +202,22 @@ JIT_WARNING
|
|||||||
ini_set('assert.exception', '1');
|
ini_set('assert.exception', '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getopt_string(string $opt) : ?string{
|
||||||
|
$opts = getopt("", ["$opt:"]);
|
||||||
|
if(isset($opts[$opt])){
|
||||||
|
if(is_string($opts[$opt])){
|
||||||
|
return $opts[$opt];
|
||||||
|
}
|
||||||
|
if(is_array($opts[$opt])){
|
||||||
|
critical_error("Cannot specify --$opt multiple times");
|
||||||
|
}else{
|
||||||
|
critical_error("Missing value for --$opt");
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@ -245,33 +263,45 @@ JIT_WARNING
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(extension_loaded('parallel')){
|
|
||||||
\parallel\bootstrap(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorToExceptionHandler::set();
|
ErrorToExceptionHandler::set();
|
||||||
|
|
||||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
|
||||||
|
|
||||||
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
|
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
|
||||||
$dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR;
|
$dataPath = getopt_string("data") ?? $cwd;
|
||||||
$pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR;
|
$pluginPath = getopt_string("plugins") ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
|
||||||
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
|
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
|
||||||
|
|
||||||
if(!file_exists($dataPath)){
|
if(!@mkdir($dataPath, 0777, true) && !is_dir($dataPath)){
|
||||||
mkdir($dataPath, 0777, true);
|
critical_error("Unable to create/access data directory at $dataPath. Check that the target location is accessible by the current user.");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
//this has to be done after we're sure the data path exists
|
||||||
|
$dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
$lockFilePath = Path::join($dataPath, 'server.lock');
|
$lockFilePath = Path::join($dataPath, 'server.lock');
|
||||||
if(($pid = Filesystem::createLockFile($lockFilePath)) !== null){
|
try{
|
||||||
|
$pid = Filesystem::createLockFile($lockFilePath);
|
||||||
|
}catch(\InvalidArgumentException $e){
|
||||||
|
critical_error($e->getMessage());
|
||||||
|
critical_error("Please ensure that there is enough space on the disk and that the current user has read/write permissions to the selected data directory $dataPath.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if($pid !== null){
|
||||||
critical_error("Another " . VersionInfo::NAME . " instance (PID $pid) is already using this folder (" . realpath($dataPath) . ").");
|
critical_error("Another " . VersionInfo::NAME . " instance (PID $pid) is already using this folder (" . realpath($dataPath) . ").");
|
||||||
critical_error("Please stop the other server first before running a new one.");
|
critical_error("Please stop the other server first before running a new one.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!@mkdir($pluginPath, 0777, true) && !is_dir($pluginPath)){
|
||||||
|
critical_error("Unable to create plugin directory at $pluginPath. Check that the target location is accessible by the current user.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
//Logger has a dependency on timezone
|
//Logger has a dependency on timezone
|
||||||
Timezone::init();
|
Timezone::init();
|
||||||
|
|
||||||
|
$opts = getopt("", ["no-wizard", "enable-ansi", "disable-ansi"]);
|
||||||
if(isset($opts["enable-ansi"])){
|
if(isset($opts["enable-ansi"])){
|
||||||
Terminal::init(true);
|
Terminal::init(true);
|
||||||
}elseif(isset($opts["disable-ansi"])){
|
}elseif(isset($opts["disable-ansi"])){
|
||||||
@ -298,7 +328,7 @@ JIT_WARNING
|
|||||||
/*
|
/*
|
||||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||||
*/
|
*/
|
||||||
$autoloader = new \BaseClassLoader();
|
$autoloader = new ThreadSafeClassLoader();
|
||||||
$autoloader->register(false);
|
$autoloader->register(false);
|
||||||
|
|
||||||
new Server($autoloader, $logger, $dataPath, $pluginPath);
|
new Server($autoloader, $logger, $dataPath, $pluginPath);
|
||||||
@ -306,7 +336,7 @@ JIT_WARNING
|
|||||||
$logger->info("Stopping other threads");
|
$logger->info("Stopping other threads");
|
||||||
|
|
||||||
$killer = new ServerKiller(8);
|
$killer = new ServerKiller(8);
|
||||||
$killer->start(PTHREADS_INHERIT_NONE);
|
$killer->start();
|
||||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||||
|
|
||||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||||
|
|||||||
489
src/Server.php
489
src/Server.php
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ use pocketmine\command\Command;
|
|||||||
use pocketmine\command\CommandSender;
|
use pocketmine\command\CommandSender;
|
||||||
use pocketmine\command\SimpleCommandMap;
|
use pocketmine\command\SimpleCommandMap;
|
||||||
use pocketmine\console\ConsoleCommandSender;
|
use pocketmine\console\ConsoleCommandSender;
|
||||||
use pocketmine\console\ConsoleReaderThread;
|
use pocketmine\console\ConsoleReaderChildProcessDaemon;
|
||||||
use pocketmine\crafting\CraftingManager;
|
use pocketmine\crafting\CraftingManager;
|
||||||
use pocketmine\crafting\CraftingManagerFromDataHelper;
|
use pocketmine\crafting\CraftingManagerFromDataHelper;
|
||||||
use pocketmine\crash\CrashDump;
|
use pocketmine\crash\CrashDump;
|
||||||
@ -43,27 +43,26 @@ use pocketmine\event\player\PlayerCreationEvent;
|
|||||||
use pocketmine\event\player\PlayerDataSaveEvent;
|
use pocketmine\event\player\PlayerDataSaveEvent;
|
||||||
use pocketmine\event\player\PlayerLoginEvent;
|
use pocketmine\event\player\PlayerLoginEvent;
|
||||||
use pocketmine\event\server\CommandEvent;
|
use pocketmine\event\server\CommandEvent;
|
||||||
use pocketmine\event\server\DataPacketSendEvent;
|
|
||||||
use pocketmine\event\server\QueryRegenerateEvent;
|
use pocketmine\event\server\QueryRegenerateEvent;
|
||||||
use pocketmine\lang\KnownTranslationFactory;
|
use pocketmine\lang\KnownTranslationFactory;
|
||||||
use pocketmine\lang\Language;
|
use pocketmine\lang\Language;
|
||||||
use pocketmine\lang\LanguageNotFoundException;
|
use pocketmine\lang\LanguageNotFoundException;
|
||||||
use pocketmine\lang\Translatable;
|
use pocketmine\lang\Translatable;
|
||||||
use pocketmine\nbt\BigEndianNbtSerializer;
|
|
||||||
use pocketmine\nbt\NbtDataException;
|
|
||||||
use pocketmine\nbt\tag\CompoundTag;
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
use pocketmine\nbt\TreeRoot;
|
|
||||||
use pocketmine\network\mcpe\compression\CompressBatchPromise;
|
use pocketmine\network\mcpe\compression\CompressBatchPromise;
|
||||||
use pocketmine\network\mcpe\compression\CompressBatchTask;
|
use pocketmine\network\mcpe\compression\CompressBatchTask;
|
||||||
use pocketmine\network\mcpe\compression\Compressor;
|
use pocketmine\network\mcpe\compression\Compressor;
|
||||||
use pocketmine\network\mcpe\compression\ZlibCompressor;
|
use pocketmine\network\mcpe\compression\ZlibCompressor;
|
||||||
|
use pocketmine\network\mcpe\convert\TypeConverter;
|
||||||
use pocketmine\network\mcpe\encryption\EncryptionContext;
|
use pocketmine\network\mcpe\encryption\EncryptionContext;
|
||||||
|
use pocketmine\network\mcpe\EntityEventBroadcaster;
|
||||||
use pocketmine\network\mcpe\NetworkSession;
|
use pocketmine\network\mcpe\NetworkSession;
|
||||||
use pocketmine\network\mcpe\PacketBroadcaster;
|
use pocketmine\network\mcpe\PacketBroadcaster;
|
||||||
use pocketmine\network\mcpe\protocol\ClientboundPacket;
|
|
||||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||||
use pocketmine\network\mcpe\protocol\serializer\PacketBatch;
|
use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext;
|
||||||
use pocketmine\network\mcpe\raklib\RakLibInterface;
|
use pocketmine\network\mcpe\raklib\RakLibInterface;
|
||||||
|
use pocketmine\network\mcpe\StandardEntityEventBroadcaster;
|
||||||
|
use pocketmine\network\mcpe\StandardPacketBroadcaster;
|
||||||
use pocketmine\network\Network;
|
use pocketmine\network\Network;
|
||||||
use pocketmine\network\NetworkInterfaceStartException;
|
use pocketmine\network\NetworkInterfaceStartException;
|
||||||
use pocketmine\network\query\DedicatedQueryNetworkInterface;
|
use pocketmine\network\query\DedicatedQueryNetworkInterface;
|
||||||
@ -72,9 +71,13 @@ use pocketmine\network\query\QueryInfo;
|
|||||||
use pocketmine\network\upnp\UPnPNetworkInterface;
|
use pocketmine\network\upnp\UPnPNetworkInterface;
|
||||||
use pocketmine\permission\BanList;
|
use pocketmine\permission\BanList;
|
||||||
use pocketmine\permission\DefaultPermissions;
|
use pocketmine\permission\DefaultPermissions;
|
||||||
|
use pocketmine\player\DatFilePlayerDataProvider;
|
||||||
use pocketmine\player\GameMode;
|
use pocketmine\player\GameMode;
|
||||||
use pocketmine\player\OfflinePlayer;
|
use pocketmine\player\OfflinePlayer;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
|
use pocketmine\player\PlayerDataLoadException;
|
||||||
|
use pocketmine\player\PlayerDataProvider;
|
||||||
|
use pocketmine\player\PlayerDataSaveException;
|
||||||
use pocketmine\player\PlayerInfo;
|
use pocketmine\player\PlayerInfo;
|
||||||
use pocketmine\plugin\PharPluginLoader;
|
use pocketmine\plugin\PharPluginLoader;
|
||||||
use pocketmine\plugin\Plugin;
|
use pocketmine\plugin\Plugin;
|
||||||
@ -88,12 +91,14 @@ use pocketmine\promise\PromiseResolver;
|
|||||||
use pocketmine\resourcepacks\ResourcePackManager;
|
use pocketmine\resourcepacks\ResourcePackManager;
|
||||||
use pocketmine\scheduler\AsyncPool;
|
use pocketmine\scheduler\AsyncPool;
|
||||||
use pocketmine\snooze\SleeperHandler;
|
use pocketmine\snooze\SleeperHandler;
|
||||||
use pocketmine\snooze\SleeperNotifier;
|
|
||||||
use pocketmine\stats\SendUsageTask;
|
use pocketmine\stats\SendUsageTask;
|
||||||
|
use pocketmine\thread\log\AttachableThreadSafeLogger;
|
||||||
|
use pocketmine\thread\ThreadSafeClassLoader;
|
||||||
use pocketmine\timings\Timings;
|
use pocketmine\timings\Timings;
|
||||||
use pocketmine\timings\TimingsHandler;
|
use pocketmine\timings\TimingsHandler;
|
||||||
use pocketmine\updater\UpdateChecker;
|
use pocketmine\updater\UpdateChecker;
|
||||||
use pocketmine\utils\AssumptionFailedError;
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
|
use pocketmine\utils\BroadcastLoggerForwarder;
|
||||||
use pocketmine\utils\Config;
|
use pocketmine\utils\Config;
|
||||||
use pocketmine\utils\Filesystem;
|
use pocketmine\utils\Filesystem;
|
||||||
use pocketmine\utils\Internet;
|
use pocketmine\utils\Internet;
|
||||||
@ -105,17 +110,18 @@ use pocketmine\utils\SignalHandler;
|
|||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\world\format\Chunk;
|
|
||||||
use pocketmine\world\format\io\WorldProviderManager;
|
use pocketmine\world\format\io\WorldProviderManager;
|
||||||
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
||||||
use pocketmine\world\generator\Generator;
|
use pocketmine\world\generator\Generator;
|
||||||
use pocketmine\world\generator\GeneratorManager;
|
use pocketmine\world\generator\GeneratorManager;
|
||||||
use pocketmine\world\generator\InvalidGeneratorOptionsException;
|
use pocketmine\world\generator\InvalidGeneratorOptionsException;
|
||||||
|
use pocketmine\world\Position;
|
||||||
use pocketmine\world\World;
|
use pocketmine\world\World;
|
||||||
use pocketmine\world\WorldCreationOptions;
|
use pocketmine\world\WorldCreationOptions;
|
||||||
use pocketmine\world\WorldManager;
|
use pocketmine\world\WorldManager;
|
||||||
use Ramsey\Uuid\UuidInterface;
|
use Ramsey\Uuid\UuidInterface;
|
||||||
use Webmozart\PathUtil\Path;
|
use Symfony\Component\Filesystem\Path;
|
||||||
|
use function array_fill;
|
||||||
use function array_sum;
|
use function array_sum;
|
||||||
use function base64_encode;
|
use function base64_encode;
|
||||||
use function cli_set_process_title;
|
use function cli_set_process_title;
|
||||||
@ -124,7 +130,6 @@ use function count;
|
|||||||
use function date;
|
use function date;
|
||||||
use function fclose;
|
use function fclose;
|
||||||
use function file_exists;
|
use function file_exists;
|
||||||
use function file_get_contents;
|
|
||||||
use function file_put_contents;
|
use function file_put_contents;
|
||||||
use function filemtime;
|
use function filemtime;
|
||||||
use function fopen;
|
use function fopen;
|
||||||
@ -132,6 +137,8 @@ use function get_class;
|
|||||||
use function ini_set;
|
use function ini_set;
|
||||||
use function is_array;
|
use function is_array;
|
||||||
use function is_dir;
|
use function is_dir;
|
||||||
|
use function is_int;
|
||||||
|
use function is_object;
|
||||||
use function is_resource;
|
use function is_resource;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
use function json_decode;
|
use function json_decode;
|
||||||
@ -159,13 +166,9 @@ use function time;
|
|||||||
use function touch;
|
use function touch;
|
||||||
use function trim;
|
use function trim;
|
||||||
use function yaml_parse;
|
use function yaml_parse;
|
||||||
use function zlib_decode;
|
|
||||||
use function zlib_encode;
|
|
||||||
use const DIRECTORY_SEPARATOR;
|
use const DIRECTORY_SEPARATOR;
|
||||||
use const PHP_EOL;
|
use const PHP_EOL;
|
||||||
use const PHP_INT_MAX;
|
use const PHP_INT_MAX;
|
||||||
use const PTHREADS_INHERIT_NONE;
|
|
||||||
use const ZLIB_ENCODING_GZIP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class that manages everything
|
* The class that manages everything
|
||||||
@ -183,9 +186,32 @@ class Server{
|
|||||||
public const DEFAULT_PORT_IPV6 = 19133;
|
public const DEFAULT_PORT_IPV6 = 19133;
|
||||||
public const DEFAULT_MAX_VIEW_DISTANCE = 16;
|
public const DEFAULT_MAX_VIEW_DISTANCE = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Worlds, network, commands and most other things are polled this many times per second on average.
|
||||||
|
* Between ticks, the server will sleep to ensure that the average tick rate is maintained.
|
||||||
|
* It may wake up between ticks if a Snooze notification source is triggered (e.g. to process network packets).
|
||||||
|
*/
|
||||||
|
public const TARGET_TICKS_PER_SECOND = 20;
|
||||||
|
/**
|
||||||
|
* The average time between ticks, in seconds.
|
||||||
|
*/
|
||||||
|
public const TARGET_SECONDS_PER_TICK = 1 / self::TARGET_TICKS_PER_SECOND;
|
||||||
|
public const TARGET_NANOSECONDS_PER_TICK = 1_000_000_000 / self::TARGET_TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TPS threshold below which the server will generate log warnings.
|
||||||
|
*/
|
||||||
|
private const TPS_OVERLOAD_WARNING_THRESHOLD = self::TARGET_TICKS_PER_SECOND * 0.6;
|
||||||
|
|
||||||
|
private const TICKS_PER_WORLD_CACHE_CLEAR = 5 * self::TARGET_TICKS_PER_SECOND;
|
||||||
|
private const TICKS_PER_TPS_OVERLOAD_WARNING = 5 * self::TARGET_TICKS_PER_SECOND;
|
||||||
|
private const TICKS_PER_STATS_REPORT = 300 * self::TARGET_TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
private const DEFAULT_ASYNC_COMPRESSION_THRESHOLD = 10_000;
|
||||||
|
|
||||||
private static ?Server $instance = null;
|
private static ?Server $instance = null;
|
||||||
|
|
||||||
private SleeperHandler $tickSleeper;
|
private TimeTrackingSleeperHandler $tickSleeper;
|
||||||
|
|
||||||
private BanList $banByName;
|
private BanList $banByName;
|
||||||
|
|
||||||
@ -201,7 +227,7 @@ class Server{
|
|||||||
|
|
||||||
private PluginManager $pluginManager;
|
private PluginManager $pluginManager;
|
||||||
|
|
||||||
private float $profilingTickRate = 20;
|
private float $profilingTickRate = self::TARGET_TICKS_PER_SECOND;
|
||||||
|
|
||||||
private UpdateChecker $updater;
|
private UpdateChecker $updater;
|
||||||
|
|
||||||
@ -211,10 +237,10 @@ class Server{
|
|||||||
private int $tickCounter = 0;
|
private int $tickCounter = 0;
|
||||||
private float $nextTick = 0;
|
private float $nextTick = 0;
|
||||||
/** @var float[] */
|
/** @var float[] */
|
||||||
private array $tickAverage = [20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20];
|
private array $tickAverage;
|
||||||
/** @var float[] */
|
/** @var float[] */
|
||||||
private array $useAverage = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
private array $useAverage;
|
||||||
private float $currentTPS = 20;
|
private float $currentTPS = self::TARGET_TICKS_PER_SECOND;
|
||||||
private float $currentUse = 0;
|
private float $currentUse = 0;
|
||||||
private float $startTime;
|
private float $startTime;
|
||||||
|
|
||||||
@ -222,11 +248,10 @@ class Server{
|
|||||||
|
|
||||||
private int $sendUsageTicker = 0;
|
private int $sendUsageTicker = 0;
|
||||||
|
|
||||||
private \AttachableThreadedLogger $logger;
|
|
||||||
|
|
||||||
private MemoryManager $memoryManager;
|
private MemoryManager $memoryManager;
|
||||||
|
|
||||||
private ConsoleReaderThread $console;
|
private ?ConsoleReaderChildProcessDaemon $console = null;
|
||||||
|
private ?ConsoleCommandSender $consoleSender = null;
|
||||||
|
|
||||||
private SimpleCommandMap $commandMap;
|
private SimpleCommandMap $commandMap;
|
||||||
|
|
||||||
@ -242,16 +267,18 @@ class Server{
|
|||||||
|
|
||||||
private Network $network;
|
private Network $network;
|
||||||
private bool $networkCompressionAsync = true;
|
private bool $networkCompressionAsync = true;
|
||||||
|
private int $networkCompressionAsyncThreshold = self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD;
|
||||||
|
|
||||||
private Language $language;
|
private Language $language;
|
||||||
private bool $forceLanguage = false;
|
private bool $forceLanguage = false;
|
||||||
|
|
||||||
private UuidInterface $serverID;
|
private UuidInterface $serverID;
|
||||||
|
|
||||||
private \DynamicClassLoader $autoloader;
|
|
||||||
private string $dataPath;
|
private string $dataPath;
|
||||||
private string $pluginPath;
|
private string $pluginPath;
|
||||||
|
|
||||||
|
private PlayerDataProvider $playerDataProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
* @phpstan-var array<string, string>
|
* @phpstan-var array<string, string>
|
||||||
@ -388,11 +415,11 @@ class Server{
|
|||||||
return $this->configGroup->getConfigString("motd", self::DEFAULT_SERVER_NAME);
|
return $this->configGroup->getConfigString("motd", self::DEFAULT_SERVER_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLoader() : \DynamicClassLoader{
|
public function getLoader() : ThreadSafeClassLoader{
|
||||||
return $this->autoloader;
|
return $this->autoloader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLogger() : \AttachableThreadedLogger{
|
public function getLogger() : AttachableThreadSafeLogger{
|
||||||
return $this->logger;
|
return $this->logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,10 +498,7 @@ class Server{
|
|||||||
return $this->configGroup->getPropertyBool("player.save-player-data", true);
|
return $this->configGroup->getPropertyBool("player.save-player-data", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getOfflinePlayer(string $name) : Player|OfflinePlayer|null{
|
||||||
* @return OfflinePlayer|Player
|
|
||||||
*/
|
|
||||||
public function getOfflinePlayer(string $name){
|
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
$result = $this->getPlayerExact($name);
|
$result = $this->getPlayerExact($name);
|
||||||
|
|
||||||
@ -485,49 +509,22 @@ class Server{
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getPlayerDataPath(string $username) : string{
|
|
||||||
return Path::join($this->getDataPath(), 'players', strtolower($username) . '.dat');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the server has stored any saved data for this player.
|
* Returns whether the server has stored any saved data for this player.
|
||||||
*/
|
*/
|
||||||
public function hasOfflinePlayerData(string $name) : bool{
|
public function hasOfflinePlayerData(string $name) : bool{
|
||||||
return file_exists($this->getPlayerDataPath($name));
|
return $this->playerDataProvider->hasData($name);
|
||||||
}
|
|
||||||
|
|
||||||
private function handleCorruptedPlayerData(string $name) : void{
|
|
||||||
$path = $this->getPlayerDataPath($name);
|
|
||||||
rename($path, $path . '.bak');
|
|
||||||
$this->logger->error($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOfflinePlayerData(string $name) : ?CompoundTag{
|
public function getOfflinePlayerData(string $name) : ?CompoundTag{
|
||||||
return Timings::$syncPlayerDataLoad->time(function() use ($name) : ?CompoundTag{
|
return Timings::$syncPlayerDataLoad->time(function() use ($name) : ?CompoundTag{
|
||||||
$name = strtolower($name);
|
try{
|
||||||
$path = $this->getPlayerDataPath($name);
|
return $this->playerDataProvider->loadData($name);
|
||||||
|
}catch(PlayerDataLoadException $e){
|
||||||
if(file_exists($path)){
|
$this->logger->debug("Failed to load player data for $name: " . $e->getMessage());
|
||||||
$contents = @file_get_contents($path);
|
$this->logger->error($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
|
||||||
if($contents === false){
|
return null;
|
||||||
throw new \RuntimeException("Failed to read player data file \"$path\" (permission denied?)");
|
|
||||||
}
|
|
||||||
$decompressed = @zlib_decode($contents);
|
|
||||||
if($decompressed === false){
|
|
||||||
$this->logger->debug("Failed to decompress raw player data for \"$name\"");
|
|
||||||
$this->handleCorruptedPlayerData($name);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try{
|
|
||||||
return (new BigEndianNbtSerializer())->read($decompressed)->mustGetCompoundTag();
|
|
||||||
}catch(NbtDataException $e){ //corrupt data
|
|
||||||
$this->logger->debug("Failed to decode NBT data for \"$name\": " . $e->getMessage());
|
|
||||||
$this->handleCorruptedPlayerData($name);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,11 +538,9 @@ class Server{
|
|||||||
|
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
|
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
|
||||||
$nbt = new BigEndianNbtSerializer();
|
|
||||||
$contents = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP), "zlib_encode() failed unexpectedly");
|
|
||||||
try{
|
try{
|
||||||
Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents);
|
$this->playerDataProvider->saveData($name, $ev->getSaveData());
|
||||||
}catch(\RuntimeException $e){
|
}catch(PlayerDataSaveException $e){
|
||||||
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
||||||
$this->logger->logException($e);
|
$this->logger->logException($e);
|
||||||
}
|
}
|
||||||
@ -561,54 +556,54 @@ class Server{
|
|||||||
$ev->call();
|
$ev->call();
|
||||||
$class = $ev->getPlayerClass();
|
$class = $ev->getPlayerClass();
|
||||||
|
|
||||||
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString("Level", ""))) !== null){
|
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString(Player::TAG_LEVEL, ""))) !== null){
|
||||||
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
|
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
|
||||||
$spawn = $playerPos->asVector3();
|
|
||||||
}else{
|
}else{
|
||||||
$world = $this->worldManager->getDefaultWorld();
|
$world = $this->worldManager->getDefaultWorld();
|
||||||
if($world === null){
|
if($world === null){
|
||||||
throw new AssumptionFailedError("Default world should always be loaded");
|
throw new AssumptionFailedError("Default world should always be loaded");
|
||||||
}
|
}
|
||||||
$playerPos = null;
|
$playerPos = null;
|
||||||
$spawn = $world->getSpawnLocation();
|
|
||||||
}
|
}
|
||||||
|
/** @phpstan-var PromiseResolver<Player> $playerPromiseResolver */
|
||||||
$playerPromiseResolver = new PromiseResolver();
|
$playerPromiseResolver = new PromiseResolver();
|
||||||
$world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
|
|
||||||
function() use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
|
|
||||||
if(!$session->isConnected()){
|
|
||||||
$playerPromiseResolver->reject();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stick with the original spawn at the time of generation request, even if it changed since then.
|
$createPlayer = function(Location $location) use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $offlinePlayerData) : void{
|
||||||
* This is because we know for sure that that chunk will be generated, but the one at the new location
|
$player = new $class($this, $session, $playerInfo, $authenticated, $location, $offlinePlayerData);
|
||||||
* might not be, and it would be much more complex to go back and redo the whole thing.
|
if(!$player->hasPlayedBefore()){
|
||||||
*
|
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||||
* TODO: this relies on the assumption that getSafeSpawn() will only alter the Y coordinate of the
|
|
||||||
* provided position. If this assumption is broken, we'll start seeing crashes in here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Player::__construct()
|
|
||||||
* @var Player $player
|
|
||||||
*/
|
|
||||||
$player = new $class($this, $session, $playerInfo, $authenticated, $playerPos ?? Location::fromObject($world->getSafeSpawn($spawn), $world), $offlinePlayerData);
|
|
||||||
if(!$player->hasPlayedBefore()){
|
|
||||||
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
|
||||||
}
|
|
||||||
$playerPromiseResolver->resolve($player);
|
|
||||||
},
|
|
||||||
static function() use ($playerPromiseResolver, $session) : void{
|
|
||||||
if($session->isConnected()){
|
|
||||||
$session->disconnect("Spawn terrain generation failed");
|
|
||||||
}
|
|
||||||
$playerPromiseResolver->reject();
|
|
||||||
}
|
}
|
||||||
);
|
$playerPromiseResolver->resolve($player);
|
||||||
|
};
|
||||||
|
|
||||||
|
if($playerPos === null){ //new player or no valid position due to world not being loaded
|
||||||
|
$world->requestSafeSpawn()->onCompletion(
|
||||||
|
function(Position $spawn) use ($createPlayer, $playerPromiseResolver, $session, $world) : void{
|
||||||
|
if(!$session->isConnected()){
|
||||||
|
$playerPromiseResolver->reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$createPlayer(Location::fromObject($spawn, $world));
|
||||||
|
},
|
||||||
|
function() use ($playerPromiseResolver, $session) : void{
|
||||||
|
if($session->isConnected()){
|
||||||
|
$session->disconnectWithError(KnownTranslationFactory::pocketmine_disconnect_error_respawn());
|
||||||
|
}
|
||||||
|
$playerPromiseResolver->reject();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}else{ //returning player with a valid position - safe spawn not required
|
||||||
|
$createPlayer($playerPos);
|
||||||
|
}
|
||||||
|
|
||||||
return $playerPromiseResolver->getPromise();
|
return $playerPromiseResolver->getPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated This method's results are unpredictable. The string "Steve" will return the player named "SteveJobs",
|
||||||
|
* until another player named "SteveJ" joins the server, at which point it will return that player instead. Prefer
|
||||||
|
* filtering the results of {@link Server::getOnlinePlayers()} yourself.
|
||||||
|
*
|
||||||
* Returns an online player whose name begins with or equals the given string (case insensitive).
|
* Returns an online player whose name begins with or equals the given string (case insensitive).
|
||||||
* The closest match will be returned, or null if there are no online matches.
|
* The closest match will be returned, or null if there are no online matches.
|
||||||
*
|
*
|
||||||
@ -765,16 +760,22 @@ class Server{
|
|||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(\DynamicClassLoader $autoloader, \AttachableThreadedLogger $logger, string $dataPath, string $pluginPath){
|
public function __construct(
|
||||||
|
private ThreadSafeClassLoader $autoloader,
|
||||||
|
private AttachableThreadSafeLogger $logger,
|
||||||
|
string $dataPath,
|
||||||
|
string $pluginPath
|
||||||
|
){
|
||||||
if(self::$instance !== null){
|
if(self::$instance !== null){
|
||||||
throw new \LogicException("Only one server instance can exist at once");
|
throw new \LogicException("Only one server instance can exist at once");
|
||||||
}
|
}
|
||||||
self::$instance = $this;
|
self::$instance = $this;
|
||||||
$this->startTime = microtime(true);
|
$this->startTime = microtime(true);
|
||||||
|
$this->tickAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, self::TARGET_TICKS_PER_SECOND);
|
||||||
|
$this->useAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, 0);
|
||||||
|
|
||||||
$this->tickSleeper = new SleeperHandler();
|
Timings::init();
|
||||||
$this->autoloader = $autoloader;
|
$this->tickSleeper = new TimeTrackingSleeperHandler(Timings::$serverInterrupts);
|
||||||
$this->logger = $logger;
|
|
||||||
|
|
||||||
$this->signalHandler = new SignalHandler(function() : void{
|
$this->signalHandler = new SignalHandler(function() : void{
|
||||||
$this->logger->info("Received signal interrupt, stopping the server");
|
$this->logger->info("Received signal interrupt, stopping the server");
|
||||||
@ -799,7 +800,7 @@ class Server{
|
|||||||
$this->logger->info("Loading server configuration");
|
$this->logger->info("Loading server configuration");
|
||||||
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
|
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
|
||||||
if(!file_exists($pocketmineYmlPath)){
|
if(!file_exists($pocketmineYmlPath)){
|
||||||
$content = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")), "Missing required resource file");
|
$content = Filesystem::fileGetContents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml"));
|
||||||
if(VersionInfo::IS_DEVELOPMENT_BUILD){
|
if(VersionInfo::IS_DEVELOPMENT_BUILD){
|
||||||
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
|
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
|
||||||
}
|
}
|
||||||
@ -860,7 +861,7 @@ class Server{
|
|||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3()));
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3()));
|
||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4("settings.enable-dev-builds")));
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4("settings.enable-dev-builds")));
|
||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases")));
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases")));
|
||||||
$this->forceShutdown();
|
$this->forceShutdownExit();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -893,6 +894,9 @@ class Server{
|
|||||||
if($this->configGroup->getPropertyInt("network.batch-threshold", 256) >= 0){
|
if($this->configGroup->getPropertyInt("network.batch-threshold", 256) >= 0){
|
||||||
$netCompressionThreshold = $this->configGroup->getPropertyInt("network.batch-threshold", 256);
|
$netCompressionThreshold = $this->configGroup->getPropertyInt("network.batch-threshold", 256);
|
||||||
}
|
}
|
||||||
|
if($netCompressionThreshold < 0){
|
||||||
|
$netCompressionThreshold = null;
|
||||||
|
}
|
||||||
|
|
||||||
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
|
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
|
||||||
if($netCompressionLevel < 1 || $netCompressionLevel > 9){
|
if($netCompressionLevel < 1 || $netCompressionLevel > 9){
|
||||||
@ -902,6 +906,10 @@ class Server{
|
|||||||
ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE));
|
ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE));
|
||||||
|
|
||||||
$this->networkCompressionAsync = $this->configGroup->getPropertyBool("network.async-compression", true);
|
$this->networkCompressionAsync = $this->configGroup->getPropertyBool("network.async-compression", true);
|
||||||
|
$this->networkCompressionAsyncThreshold = max(
|
||||||
|
$this->configGroup->getPropertyInt("network.async-compression-threshold", self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD),
|
||||||
|
$netCompressionThreshold ?? self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD
|
||||||
|
);
|
||||||
|
|
||||||
EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool("network.enable-encryption", true);
|
EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool("network.enable-encryption", true);
|
||||||
|
|
||||||
@ -954,15 +962,14 @@ class Server{
|
|||||||
)));
|
)));
|
||||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
|
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
|
||||||
|
|
||||||
Timings::init();
|
|
||||||
TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false));
|
TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false));
|
||||||
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", 20);
|
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", self::TARGET_TICKS_PER_SECOND);
|
||||||
|
|
||||||
DefaultPermissions::registerCorePermissions();
|
DefaultPermissions::registerCorePermissions();
|
||||||
|
|
||||||
$this->commandMap = new SimpleCommandMap($this);
|
$this->commandMap = new SimpleCommandMap($this);
|
||||||
|
|
||||||
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes.json"));
|
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes"));
|
||||||
|
|
||||||
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
|
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
|
||||||
|
|
||||||
@ -972,10 +979,10 @@ class Server{
|
|||||||
copy(Path::join(\pocketmine\RESOURCE_PATH, 'plugin_list.yml'), $graylistFile);
|
copy(Path::join(\pocketmine\RESOURCE_PATH, 'plugin_list.yml'), $graylistFile);
|
||||||
}
|
}
|
||||||
try{
|
try{
|
||||||
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(file_get_contents($graylistFile)));
|
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(Filesystem::fileGetContents($graylistFile)));
|
||||||
}catch(\InvalidArgumentException $e){
|
}catch(\InvalidArgumentException $e){
|
||||||
$this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage());
|
$this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage());
|
||||||
$this->forceShutdown();
|
$this->forceShutdownExit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
|
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
|
||||||
@ -994,29 +1001,47 @@ class Server{
|
|||||||
|
|
||||||
$this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager);
|
$this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager);
|
||||||
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
|
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
|
||||||
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", 6000));
|
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval()));
|
||||||
|
|
||||||
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io"));
|
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io"));
|
||||||
|
|
||||||
$this->queryInfo = new QueryInfo($this);
|
$this->queryInfo = new QueryInfo($this);
|
||||||
|
|
||||||
|
$this->playerDataProvider = new DatFilePlayerDataProvider(Path::join($this->dataPath, "players"));
|
||||||
|
|
||||||
register_shutdown_function([$this, "crashDump"]);
|
register_shutdown_function([$this, "crashDump"]);
|
||||||
|
|
||||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
$loadErrorCount = 0;
|
||||||
$this->enablePlugins(PluginEnableOrder::STARTUP());
|
$this->pluginManager->loadPlugins($this->pluginPath, $loadErrorCount);
|
||||||
|
if($loadErrorCount > 0){
|
||||||
if(!$this->startupPrepareWorlds()){
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someLoadErrors()));
|
||||||
|
$this->forceShutdownExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!$this->enablePlugins(PluginEnableOrder::STARTUP())){
|
||||||
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someEnableErrors()));
|
||||||
|
$this->forceShutdownExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$this->startupPrepareWorlds()){
|
||||||
|
$this->forceShutdownExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$this->enablePlugins(PluginEnableOrder::POSTWORLD())){
|
||||||
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someEnableErrors()));
|
||||||
|
$this->forceShutdownExit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->enablePlugins(PluginEnableOrder::POSTWORLD());
|
|
||||||
|
|
||||||
if(!$this->startupPrepareNetworkInterfaces()){
|
if(!$this->startupPrepareNetworkInterfaces()){
|
||||||
$this->forceShutdown();
|
$this->forceShutdownExit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
|
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
|
||||||
$this->sendUsageTicker = 6000;
|
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
|
||||||
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,22 +1051,14 @@ class Server{
|
|||||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_donate(TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET)));
|
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_donate(TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET)));
|
||||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_startFinished(strval(round(microtime(true) - $this->startTime, 3)))));
|
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_startFinished(strval(round(microtime(true) - $this->startTime, 3)))));
|
||||||
|
|
||||||
//TODO: move console parts to a separate component
|
$forwarder = new BroadcastLoggerForwarder($this, $this->logger, $this->language);
|
||||||
$consoleSender = new ConsoleCommandSender($this, $this->language);
|
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $forwarder);
|
||||||
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $consoleSender);
|
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $forwarder);
|
||||||
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $consoleSender);
|
|
||||||
|
|
||||||
$consoleNotifier = new SleeperNotifier();
|
//TODO: move console parts to a separate component
|
||||||
$commandBuffer = new \Threaded();
|
if($this->configGroup->getPropertyBool("console.enable-input", true)){
|
||||||
$this->console = new ConsoleReaderThread($commandBuffer, $consoleNotifier);
|
$this->console = new ConsoleReaderChildProcessDaemon($this->logger);
|
||||||
$this->tickSleeper->addNotifier($consoleNotifier, function() use ($commandBuffer, $consoleSender) : void{
|
}
|
||||||
Timings::$serverCommand->startTiming();
|
|
||||||
while(($line = $commandBuffer->shift()) !== null){
|
|
||||||
$this->dispatchCommand($consoleSender, (string) $line);
|
|
||||||
}
|
|
||||||
Timings::$serverCommand->stopTiming();
|
|
||||||
});
|
|
||||||
$this->console->start(PTHREADS_INHERIT_NONE);
|
|
||||||
|
|
||||||
$this->tickProcessor();
|
$this->tickProcessor();
|
||||||
$this->forceShutdown();
|
$this->forceShutdown();
|
||||||
@ -1072,13 +1089,21 @@ class Server{
|
|||||||
return $generatorEntry->getGeneratorClass();
|
return $generatorEntry->getGeneratorClass();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$anyWorldFailedToLoad = false;
|
||||||
|
|
||||||
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
||||||
if($options === null){
|
if($options === null){
|
||||||
$options = [];
|
$options = [];
|
||||||
}elseif(!is_array($options)){
|
}elseif(!is_array($options)){
|
||||||
|
//TODO: this probably should be an error
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(!$this->worldManager->loadWorld($name, true) && !$this->worldManager->isWorldGenerated($name)){
|
if(!$this->worldManager->loadWorld($name, true)){
|
||||||
|
if($this->worldManager->isWorldGenerated($name)){
|
||||||
|
//allow checking if other worlds are loadable, so the user gets all the errors in one go
|
||||||
|
$anyWorldFailedToLoad = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$creationOptions = WorldCreationOptions::create();
|
$creationOptions = WorldCreationOptions::create();
|
||||||
//TODO: error checking
|
//TODO: error checking
|
||||||
|
|
||||||
@ -1087,11 +1112,13 @@ class Server{
|
|||||||
|
|
||||||
$generatorClass = $getGenerator($generatorName, $generatorOptions, $name);
|
$generatorClass = $getGenerator($generatorName, $generatorOptions, $name);
|
||||||
if($generatorClass === null){
|
if($generatorClass === null){
|
||||||
|
$anyWorldFailedToLoad = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$creationOptions->setGeneratorClass($generatorClass);
|
$creationOptions->setGeneratorClass($generatorClass);
|
||||||
$creationOptions->setGeneratorOptions($generatorOptions);
|
$creationOptions->setGeneratorOptions($generatorOptions);
|
||||||
|
|
||||||
|
$creationOptions->setDifficulty($this->getDifficulty());
|
||||||
if(isset($options["difficulty"]) && is_string($options["difficulty"])){
|
if(isset($options["difficulty"]) && is_string($options["difficulty"])){
|
||||||
$creationOptions->setDifficulty(World::getDifficultyFromString($options["difficulty"]));
|
$creationOptions->setDifficulty(World::getDifficultyFromString($options["difficulty"]));
|
||||||
}
|
}
|
||||||
@ -1114,39 +1141,54 @@ class Server{
|
|||||||
$default = "world";
|
$default = "world";
|
||||||
$this->configGroup->setConfigString("level-name", "world");
|
$this->configGroup->setConfigString("level-name", "world");
|
||||||
}
|
}
|
||||||
if(!$this->worldManager->loadWorld($default, true) && !$this->worldManager->isWorldGenerated($default)){
|
if(!$this->worldManager->loadWorld($default, true)){
|
||||||
|
if($this->worldManager->isWorldGenerated($default)){
|
||||||
|
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$generatorName = $this->configGroup->getConfigString("level-type");
|
$generatorName = $this->configGroup->getConfigString("level-type");
|
||||||
$generatorOptions = $this->configGroup->getConfigString("generator-settings");
|
$generatorOptions = $this->configGroup->getConfigString("generator-settings");
|
||||||
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
|
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
|
||||||
if($generatorClass !== null){
|
|
||||||
$creationOptions = WorldCreationOptions::create()
|
if($generatorClass === null){
|
||||||
->setGeneratorClass($generatorClass)
|
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||||
->setGeneratorOptions($generatorOptions);
|
return false;
|
||||||
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
|
|
||||||
if($convertedSeed !== null){
|
|
||||||
$creationOptions->setSeed($convertedSeed);
|
|
||||||
}
|
|
||||||
$this->worldManager->generateWorld($default, $creationOptions);
|
|
||||||
}
|
}
|
||||||
|
$creationOptions = WorldCreationOptions::create()
|
||||||
|
->setGeneratorClass($generatorClass)
|
||||||
|
->setGeneratorOptions($generatorOptions);
|
||||||
|
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
|
||||||
|
if($convertedSeed !== null){
|
||||||
|
$creationOptions->setSeed($convertedSeed);
|
||||||
|
}
|
||||||
|
$creationOptions->setDifficulty($this->getDifficulty());
|
||||||
|
$this->worldManager->generateWorld($default, $creationOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
$world = $this->worldManager->getWorldByName($default);
|
$world = $this->worldManager->getWorldByName($default);
|
||||||
if($world === null){
|
if($world === null){
|
||||||
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
throw new AssumptionFailedError("We just loaded/generated the default world, so it must exist");
|
||||||
$this->forceShutdown();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
$this->worldManager->setDefaultWorld($world);
|
$this->worldManager->setDefaultWorld($world);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return !$anyWorldFailedToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function startupPrepareConnectableNetworkInterfaces(string $ip, int $port, bool $ipV6, bool $useQuery) : bool{
|
private function startupPrepareConnectableNetworkInterfaces(
|
||||||
|
string $ip,
|
||||||
|
int $port,
|
||||||
|
bool $ipV6,
|
||||||
|
bool $useQuery,
|
||||||
|
PacketBroadcaster $packetBroadcaster,
|
||||||
|
EntityEventBroadcaster $entityEventBroadcaster,
|
||||||
|
PacketSerializerContext $packetSerializerContext,
|
||||||
|
TypeConverter $typeConverter
|
||||||
|
) : bool{
|
||||||
$prettyIp = $ipV6 ? "[$ip]" : $ip;
|
$prettyIp = $ipV6 ? "[$ip]" : $ip;
|
||||||
try{
|
try{
|
||||||
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6));
|
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter));
|
||||||
}catch(NetworkInterfaceStartException $e){
|
}catch(NetworkInterfaceStartException $e){
|
||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
|
||||||
$ip,
|
$ip,
|
||||||
@ -1172,11 +1214,16 @@ class Server{
|
|||||||
private function startupPrepareNetworkInterfaces() : bool{
|
private function startupPrepareNetworkInterfaces() : bool{
|
||||||
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
||||||
|
|
||||||
|
$typeConverter = TypeConverter::getInstance();
|
||||||
|
$packetSerializerContext = new PacketSerializerContext($typeConverter->getItemTypeDictionary());
|
||||||
|
$packetBroadcaster = new StandardPacketBroadcaster($this, $packetSerializerContext);
|
||||||
|
$entityEventBroadcaster = new StandardEntityEventBroadcaster($packetBroadcaster, $typeConverter);
|
||||||
|
|
||||||
if(
|
if(
|
||||||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery) ||
|
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) ||
|
||||||
(
|
(
|
||||||
$this->configGroup->getConfigBool("enable-ipv6", true) &&
|
$this->configGroup->getConfigBool("enable-ipv6", true) &&
|
||||||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery)
|
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter)
|
||||||
)
|
)
|
||||||
){
|
){
|
||||||
return false;
|
return false;
|
||||||
@ -1237,7 +1284,7 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CommandSender[]|null $recipients
|
* @param CommandSender[]|null $recipients
|
||||||
*/
|
*/
|
||||||
public function broadcastMessage(Translatable|string $message, ?array $recipients = null) : int{
|
public function broadcastMessage(Translatable|string $message, ?array $recipients = null) : int{
|
||||||
$recipients = $recipients ?? $this->getBroadcastChannelSubscribers(self::BROADCAST_CHANNEL_USERS);
|
$recipients = $recipients ?? $this->getBroadcastChannelSubscribers(self::BROADCAST_CHANNEL_USERS);
|
||||||
@ -1290,9 +1337,9 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $fadeIn Duration in ticks for fade-in. If -1 is given, client-sided defaults will be used.
|
* @param int $fadeIn Duration in ticks for fade-in. If -1 is given, client-sided defaults will be used.
|
||||||
* @param int $stay Duration in ticks to stay on screen for
|
* @param int $stay Duration in ticks to stay on screen for
|
||||||
* @param int $fadeOut Duration in ticks for fade-out.
|
* @param int $fadeOut Duration in ticks for fade-out.
|
||||||
* @param Player[]|null $recipients
|
* @param Player[]|null $recipients
|
||||||
*/
|
*/
|
||||||
public function broadcastTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1, ?array $recipients = null) : int{
|
public function broadcastTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1, ?array $recipients = null) : int{
|
||||||
@ -1305,68 +1352,23 @@ class Server{
|
|||||||
return count($recipients);
|
return count($recipients);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Player[] $players
|
|
||||||
* @param ClientboundPacket[] $packets
|
|
||||||
*/
|
|
||||||
public function broadcastPackets(array $players, array $packets) : bool{
|
|
||||||
if(count($packets) === 0){
|
|
||||||
throw new \InvalidArgumentException("Cannot broadcast empty list of packets");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Timings::$broadcastPackets->time(function() use ($players, $packets) : bool{
|
|
||||||
/** @var NetworkSession[] $recipients */
|
|
||||||
$recipients = [];
|
|
||||||
foreach($players as $player){
|
|
||||||
if($player->isConnected()){
|
|
||||||
$recipients[] = $player->getNetworkSession();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(count($recipients) === 0){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ev = new DataPacketSendEvent($recipients, $packets);
|
|
||||||
$ev->call();
|
|
||||||
if($ev->isCancelled()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$recipients = $ev->getTargets();
|
|
||||||
|
|
||||||
/** @var PacketBroadcaster[] $broadcasters */
|
|
||||||
$broadcasters = [];
|
|
||||||
/** @var NetworkSession[][] $broadcasterTargets */
|
|
||||||
$broadcasterTargets = [];
|
|
||||||
foreach($recipients as $recipient){
|
|
||||||
$broadcaster = $recipient->getBroadcaster();
|
|
||||||
$broadcasters[spl_object_id($broadcaster)] = $broadcaster;
|
|
||||||
$broadcasterTargets[spl_object_id($broadcaster)][] = $recipient;
|
|
||||||
}
|
|
||||||
foreach($broadcasters as $broadcaster){
|
|
||||||
$broadcaster->broadcastPackets($broadcasterTargets[spl_object_id($broadcaster)], $packets);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcasts a list of packets in a batch to a list of players
|
* Broadcasts a list of packets in a batch to a list of players
|
||||||
*
|
*
|
||||||
* @param bool|null $sync Compression on the main thread (true) or workers (false). Default is automatic (null).
|
* @param bool|null $sync Compression on the main thread (true) or workers (false). Default is automatic (null).
|
||||||
*/
|
*/
|
||||||
public function prepareBatch(PacketBatch $stream, Compressor $compressor, ?bool $sync = null) : CompressBatchPromise{
|
public function prepareBatch(string $buffer, Compressor $compressor, ?bool $sync = null, ?TimingsHandler $timings = null) : CompressBatchPromise{
|
||||||
|
$timings ??= Timings::$playerNetworkSendCompress;
|
||||||
try{
|
try{
|
||||||
Timings::$playerNetworkSendCompress->startTiming();
|
$timings->startTiming();
|
||||||
|
|
||||||
$buffer = $stream->getBuffer();
|
|
||||||
|
|
||||||
if($sync === null){
|
if($sync === null){
|
||||||
$sync = !($this->networkCompressionAsync && $compressor->willCompress($buffer));
|
$threshold = $compressor->getCompressionThreshold();
|
||||||
|
$sync = !$this->networkCompressionAsync || $threshold === null || strlen($buffer) < $threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
$promise = new CompressBatchPromise();
|
$promise = new CompressBatchPromise();
|
||||||
if(!$sync){
|
if(!$sync && strlen($buffer) >= $this->networkCompressionAsyncThreshold){
|
||||||
$task = new CompressBatchTask($buffer, $promise, $compressor);
|
$task = new CompressBatchTask($buffer, $promise, $compressor);
|
||||||
$this->asyncPool->submitTask($task);
|
$this->asyncPool->submitTask($task);
|
||||||
}else{
|
}else{
|
||||||
@ -1375,20 +1377,25 @@ class Server{
|
|||||||
|
|
||||||
return $promise;
|
return $promise;
|
||||||
}finally{
|
}finally{
|
||||||
Timings::$playerNetworkSendCompress->stopTiming();
|
$timings->stopTiming();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enablePlugins(PluginEnableOrder $type) : void{
|
public function enablePlugins(PluginEnableOrder $type) : bool{
|
||||||
|
$allSuccess = true;
|
||||||
foreach($this->pluginManager->getPlugins() as $plugin){
|
foreach($this->pluginManager->getPlugins() as $plugin){
|
||||||
if(!$plugin->isEnabled() && $plugin->getDescription()->getOrder()->equals($type)){
|
if(!$plugin->isEnabled() && $plugin->getDescription()->getOrder()->equals($type)){
|
||||||
$this->pluginManager->enablePlugin($plugin);
|
if(!$this->pluginManager->enablePlugin($plugin)){
|
||||||
|
$allSuccess = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($type->equals(PluginEnableOrder::POSTWORLD())){
|
if($type->equals(PluginEnableOrder::POSTWORLD())){
|
||||||
$this->commandMap->registerServerAliases();
|
$this->commandMap->registerServerAliases();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $allSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1418,6 +1425,11 @@ class Server{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function forceShutdownExit() : void{
|
||||||
|
$this->forceShutdown();
|
||||||
|
Process::kill(Process::pid(), true);
|
||||||
|
}
|
||||||
|
|
||||||
public function forceShutdown() : void{
|
public function forceShutdown() : void{
|
||||||
if($this->hasStopped){
|
if($this->hasStopped){
|
||||||
return;
|
return;
|
||||||
@ -1428,7 +1440,7 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($this->isRunning){
|
if($this->isRunning){
|
||||||
$this->logger->emergency("Forcing server shutdown");
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_forcingShutdown()));
|
||||||
}
|
}
|
||||||
try{
|
try{
|
||||||
if(!$this->isRunning()){
|
if(!$this->isRunning()){
|
||||||
@ -1468,7 +1480,7 @@ class Server{
|
|||||||
$this->configGroup->save();
|
$this->configGroup->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($this->console)){
|
if($this->console !== null){
|
||||||
$this->getLogger()->debug("Closing console");
|
$this->getLogger()->debug("Closing console");
|
||||||
$this->console->quit();
|
$this->console->quit();
|
||||||
}
|
}
|
||||||
@ -1496,7 +1508,7 @@ class Server{
|
|||||||
* @param mixed[][]|null $trace
|
* @param mixed[][]|null $trace
|
||||||
* @phpstan-param list<array<string, mixed>>|null $trace
|
* @phpstan-param list<array<string, mixed>>|null $trace
|
||||||
*/
|
*/
|
||||||
public function exceptionHandler(\Throwable $e, $trace = null) : void{
|
public function exceptionHandler(\Throwable $e, ?array $trace = null) : void{
|
||||||
while(@ob_end_flush()){}
|
while(@ob_end_flush()){}
|
||||||
global $lastError;
|
global $lastError;
|
||||||
|
|
||||||
@ -1606,13 +1618,15 @@ class Server{
|
|||||||
"reportPaste" => base64_encode($dump->getEncodedData())
|
"reportPaste" => base64_encode($dump->getEncodedData())
|
||||||
], 10, [], $postUrlError);
|
], 10, [], $postUrlError);
|
||||||
|
|
||||||
if($reply !== null && ($data = json_decode($reply->getBody())) !== null){
|
if($reply !== null && is_object($data = json_decode($reply->getBody()))){
|
||||||
if(isset($data->crashId) && isset($data->crashUrl)){
|
if(isset($data->crashId) && is_int($data->crashId) && isset($data->crashUrl) && is_string($data->crashUrl)){
|
||||||
$reportId = $data->crashId;
|
$reportId = $data->crashId;
|
||||||
$reportUrl = $data->crashUrl;
|
$reportUrl = $data->crashUrl;
|
||||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
|
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
|
||||||
}elseif(isset($data->error)){
|
}elseif(isset($data->error) && is_string($data->error)){
|
||||||
$this->logger->emergency("Automatic crash report submission failed: $data->error");
|
$this->logger->emergency("Automatic crash report submission failed: $data->error");
|
||||||
|
}else{
|
||||||
|
$this->logger->emergency("Invalid JSON response received from crash archive: " . $reply->getBody());
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
$this->logger->emergency("Failed to communicate with crash archive: $postUrlError");
|
$this->logger->emergency("Failed to communicate with crash archive: $postUrlError");
|
||||||
@ -1673,7 +1687,7 @@ class Server{
|
|||||||
$session = $player->getNetworkSession();
|
$session = $player->getNetworkSession();
|
||||||
$position = $player->getPosition();
|
$position = $player->getPosition();
|
||||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_player_logIn(
|
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_player_logIn(
|
||||||
TextFormat::AQUA . $player->getName() . TextFormat::WHITE,
|
TextFormat::AQUA . $player->getName() . TextFormat::RESET,
|
||||||
$session->getIp(),
|
$session->getIp(),
|
||||||
(string) $session->getPort(),
|
(string) $session->getPort(),
|
||||||
(string) $player->getId(),
|
(string) $player->getId(),
|
||||||
@ -1778,11 +1792,11 @@ class Server{
|
|||||||
$this->network->tick();
|
$this->network->tick();
|
||||||
Timings::$connection->stopTiming();
|
Timings::$connection->stopTiming();
|
||||||
|
|
||||||
if(($this->tickCounter % 20) === 0){
|
if(($this->tickCounter % self::TARGET_TICKS_PER_SECOND) === 0){
|
||||||
if($this->doTitleTick){
|
if($this->doTitleTick){
|
||||||
$this->titleTick();
|
$this->titleTick();
|
||||||
}
|
}
|
||||||
$this->currentTPS = 20;
|
$this->currentTPS = self::TARGET_TICKS_PER_SECOND;
|
||||||
$this->currentUse = 0;
|
$this->currentUse = 0;
|
||||||
|
|
||||||
$queryRegenerateEvent = new QueryRegenerateEvent(new QueryInfo($this));
|
$queryRegenerateEvent = new QueryRegenerateEvent(new QueryInfo($this));
|
||||||
@ -1794,38 +1808,49 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($this->sendUsageTicker > 0 && --$this->sendUsageTicker === 0){
|
if($this->sendUsageTicker > 0 && --$this->sendUsageTicker === 0){
|
||||||
$this->sendUsageTicker = 6000;
|
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
|
||||||
$this->sendUsage(SendUsageTask::TYPE_STATUS);
|
$this->sendUsage(SendUsageTask::TYPE_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(($this->tickCounter % 100) === 0){
|
if(($this->tickCounter % self::TICKS_PER_WORLD_CACHE_CLEAR) === 0){
|
||||||
foreach($this->worldManager->getWorlds() as $world){
|
foreach($this->worldManager->getWorlds() as $world){
|
||||||
$world->clearCache();
|
$world->clearCache();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if($this->getTicksPerSecondAverage() < 12){
|
if(($this->tickCounter % self::TICKS_PER_TPS_OVERLOAD_WARNING) === 0 && $this->getTicksPerSecondAverage() < self::TPS_OVERLOAD_WARNING_THRESHOLD){
|
||||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
|
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getMemoryManager()->check();
|
$this->getMemoryManager()->check();
|
||||||
|
|
||||||
|
if($this->console !== null){
|
||||||
|
Timings::$serverCommand->startTiming();
|
||||||
|
while(($line = $this->console->readLine()) !== null){
|
||||||
|
$this->consoleSender ??= new ConsoleCommandSender($this, $this->language);
|
||||||
|
$this->dispatchCommand($this->consoleSender, $line);
|
||||||
|
}
|
||||||
|
Timings::$serverCommand->stopTiming();
|
||||||
|
}
|
||||||
|
|
||||||
Timings::$serverTick->stopTiming();
|
Timings::$serverTick->stopTiming();
|
||||||
|
|
||||||
$now = microtime(true);
|
$now = microtime(true);
|
||||||
$this->currentTPS = min(20, 1 / max(0.001, $now - $tickTime));
|
$totalTickTimeSeconds = $now - $tickTime + ($this->tickSleeper->getNotificationProcessingTime() / 1_000_000_000);
|
||||||
$this->currentUse = min(1, ($now - $tickTime) / 0.05);
|
$this->currentTPS = min(self::TARGET_TICKS_PER_SECOND, 1 / max(0.001, $totalTickTimeSeconds));
|
||||||
|
$this->currentUse = min(1, $totalTickTimeSeconds / self::TARGET_SECONDS_PER_TICK);
|
||||||
|
|
||||||
TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate);
|
TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate);
|
||||||
|
|
||||||
$idx = $this->tickCounter % 20;
|
$idx = $this->tickCounter % self::TARGET_TICKS_PER_SECOND;
|
||||||
$this->tickAverage[$idx] = $this->currentTPS;
|
$this->tickAverage[$idx] = $this->currentTPS;
|
||||||
$this->useAverage[$idx] = $this->currentUse;
|
$this->useAverage[$idx] = $this->currentUse;
|
||||||
|
$this->tickSleeper->resetNotificationProcessingTime();
|
||||||
|
|
||||||
if(($this->nextTick - $tickTime) < -1){
|
if(($this->nextTick - $tickTime) < -1){
|
||||||
$this->nextTick = $tickTime;
|
$this->nextTick = $tickTime;
|
||||||
}else{
|
}else{
|
||||||
$this->nextTick += 0.05;
|
$this->nextTick += self::TARGET_SECONDS_PER_TICK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -32,29 +32,18 @@ use function is_string;
|
|||||||
use function strtolower;
|
use function strtolower;
|
||||||
|
|
||||||
final class ServerConfigGroup{
|
final class ServerConfigGroup{
|
||||||
|
|
||||||
/** @var Config */
|
|
||||||
private $pocketmineYml;
|
|
||||||
/** @var Config */
|
|
||||||
private $serverProperties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var mixed[]
|
* @var mixed[]
|
||||||
* @phpstan-var array<string, mixed>
|
* @phpstan-var array<string, mixed>
|
||||||
*/
|
*/
|
||||||
private $propertyCache = [];
|
private array $propertyCache = [];
|
||||||
|
|
||||||
public function __construct(Config $pocketmineYml, Config $serverProperties){
|
public function __construct(
|
||||||
$this->pocketmineYml = $pocketmineYml;
|
private Config $pocketmineYml,
|
||||||
$this->serverProperties = $serverProperties;
|
private Config $serverProperties
|
||||||
}
|
){}
|
||||||
|
|
||||||
/**
|
public function getProperty(string $variable, mixed $defaultValue = null) : mixed{
|
||||||
* @param mixed $defaultValue
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getProperty(string $variable, $defaultValue = null){
|
|
||||||
if(!array_key_exists($variable, $this->propertyCache)){
|
if(!array_key_exists($variable, $this->propertyCache)){
|
||||||
$v = getopt("", ["$variable::"]);
|
$v = getopt("", ["$variable::"]);
|
||||||
if(isset($v[$variable])){
|
if(isset($v[$variable])){
|
||||||
|
|||||||
64
src/TimeTrackingSleeperHandler.php
Normal file
64
src/TimeTrackingSleeperHandler.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine;
|
||||||
|
|
||||||
|
use pocketmine\snooze\SleeperHandler;
|
||||||
|
use pocketmine\timings\TimingsHandler;
|
||||||
|
use function hrtime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom Snooze sleeper handler which captures notification processing time.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class TimeTrackingSleeperHandler extends SleeperHandler{
|
||||||
|
|
||||||
|
private int $notificationProcessingTimeNs = 0;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private TimingsHandler $timings
|
||||||
|
){
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time in nanoseconds spent processing notifications since the last reset.
|
||||||
|
*/
|
||||||
|
public function getNotificationProcessingTime() : int{ return $this->notificationProcessingTimeNs; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the notification processing time tracker to zero.
|
||||||
|
*/
|
||||||
|
public function resetNotificationProcessingTime() : void{ $this->notificationProcessingTimeNs = 0; }
|
||||||
|
|
||||||
|
public function processNotifications() : void{
|
||||||
|
$startTime = hrtime(true);
|
||||||
|
$this->timings->startTiming();
|
||||||
|
try{
|
||||||
|
parent::processNotifications();
|
||||||
|
}finally{
|
||||||
|
$this->notificationProcessingTimeNs += hrtime(true) - $startTime;
|
||||||
|
$this->timings->stopTiming();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ use function str_repeat;
|
|||||||
|
|
||||||
final class VersionInfo{
|
final class VersionInfo{
|
||||||
public const NAME = "PocketMine-MP";
|
public const NAME = "PocketMine-MP";
|
||||||
public const BASE_VERSION = "4.1.0-BETA1";
|
public const BASE_VERSION = "5.0.0-BETA4";
|
||||||
public const IS_DEVELOPMENT_BUILD = false;
|
public const IS_DEVELOPMENT_BUILD = false;
|
||||||
public const BUILD_CHANNEL = "beta";
|
public const BUILD_CHANNEL = "beta";
|
||||||
|
|
||||||
@ -39,8 +39,7 @@ final class VersionInfo{
|
|||||||
//NOOP
|
//NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var string|null */
|
private static ?string $gitHash = null;
|
||||||
private static $gitHash = null;
|
|
||||||
|
|
||||||
public static function GIT_HASH() : string{
|
public static function GIT_HASH() : string{
|
||||||
if(self::$gitHash === null){
|
if(self::$gitHash === null){
|
||||||
@ -79,8 +78,7 @@ final class VersionInfo{
|
|||||||
return self::$buildNumber;
|
return self::$buildNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var VersionString|null */
|
private static ?VersionString $fullVersion = null;
|
||||||
private static $fullVersion = null;
|
|
||||||
|
|
||||||
public static function VERSION() : VersionString{
|
public static function VERSION() : VersionString{
|
||||||
if(self::$fullVersion === null){
|
if(self::$fullVersion === null){
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|||||||
@ -17,22 +17,16 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Air block
|
* Air block
|
||||||
*/
|
*/
|
||||||
class Air extends Transparent{
|
class Air extends Flowable{
|
||||||
|
|
||||||
public function canBeFlowedInto() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canBeReplaced() : bool{
|
public function canBeReplaced() : bool{
|
||||||
return true;
|
return true;
|
||||||
@ -41,15 +35,4 @@ class Air extends Transparent{
|
|||||||
public function canBePlaced() : bool{
|
public function canBePlaced() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isSolid() : bool{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return AxisAlignedBB[]
|
|
||||||
*/
|
|
||||||
protected function recalculateCollisionBoxes() : array{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,53 +17,54 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\inventory\AnvilInventory;
|
use pocketmine\block\inventory\AnvilInventory;
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
|
||||||
use pocketmine\block\utils\Fallable;
|
use pocketmine\block\utils\Fallable;
|
||||||
use pocketmine\block\utils\FallableTrait;
|
use pocketmine\block\utils\FallableTrait;
|
||||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
|
use pocketmine\entity\object\FallingBlock;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
|
use pocketmine\world\sound\AnvilFallSound;
|
||||||
|
use pocketmine\world\sound\Sound;
|
||||||
|
use function lcg_value;
|
||||||
|
use function round;
|
||||||
|
|
||||||
class Anvil extends Transparent implements Fallable{
|
class Anvil extends Transparent implements Fallable{
|
||||||
use FallableTrait;
|
use FallableTrait;
|
||||||
use HorizontalFacingTrait;
|
use HorizontalFacingTrait;
|
||||||
|
|
||||||
private int $damage = 0;
|
public const UNDAMAGED = 0;
|
||||||
|
public const SLIGHTLY_DAMAGED = 1;
|
||||||
|
public const VERY_DAMAGED = 2;
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
private int $damage = self::UNDAMAGED;
|
||||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->damage << 2);
|
|
||||||
|
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
|
||||||
|
$w->boundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x3);
|
$w->horizontalFacing($this->facing);
|
||||||
$this->damage = BlockDataSerializer::readBoundedInt("damage", $stateMeta >> 2, 0, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
|
||||||
return 0b1111;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function writeStateToItemMeta() : int{
|
|
||||||
return $this->damage << 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDamage() : int{ return $this->damage; }
|
public function getDamage() : int{ return $this->damage; }
|
||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
public function setDamage(int $damage) : self{
|
public function setDamage(int $damage) : self{
|
||||||
if($damage < 0 || $damage > 2){
|
if($damage < self::UNDAMAGED || $damage > self::VERY_DAMAGED){
|
||||||
throw new \InvalidArgumentException("Damage must be in range 0-2");
|
throw new \InvalidArgumentException("Damage must be in range " . self::UNDAMAGED . " ... " . self::VERY_DAMAGED);
|
||||||
}
|
}
|
||||||
$this->damage = $damage;
|
$this->damage = $damage;
|
||||||
return $this;
|
return $this;
|
||||||
@ -76,7 +77,11 @@ class Anvil extends Transparent implements Fallable{
|
|||||||
return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)];
|
return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$player->setCurrentWindow(new AnvilInventory($this->position));
|
$player->setCurrentWindow(new AnvilInventory($this->position));
|
||||||
}
|
}
|
||||||
@ -91,7 +96,26 @@ class Anvil extends Transparent implements Fallable{
|
|||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tickFalling() : ?Block{
|
public function onHitGround(FallingBlock $blockEntity) : bool{
|
||||||
return null;
|
if(lcg_value() < 0.05 + (round($blockEntity->getFallDistance()) - 1) * 0.05){
|
||||||
|
if($this->damage !== self::VERY_DAMAGED){
|
||||||
|
$this->damage = $this->damage + 1;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFallDamagePerBlock() : float{
|
||||||
|
return 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMaxFallDamage() : float{
|
||||||
|
return 40.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLandSound() : ?Sound{
|
||||||
|
return new AnvilFallSound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,17 +17,19 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
use pocketmine\event\block\StructureGrowEvent;
|
use pocketmine\event\block\StructureGrowEvent;
|
||||||
use pocketmine\item\Bamboo as ItemBamboo;
|
use pocketmine\item\Bamboo as ItemBamboo;
|
||||||
use pocketmine\item\Fertilizer;
|
use pocketmine\item\Fertilizer;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\VanillaItems;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -53,18 +55,10 @@ class Bamboo extends Transparent{
|
|||||||
protected bool $ready = false;
|
protected bool $ready = false;
|
||||||
protected int $leafSize = self::NO_LEAVES;
|
protected int $leafSize = self::NO_LEAVES;
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
$this->thick = ($stateMeta & BlockLegacyMetadata::BAMBOO_FLAG_THICK) !== 0;
|
$w->boundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->leafSize);
|
||||||
$this->leafSize = BlockDataSerializer::readBoundedInt("leafSize", ($stateMeta >> BlockLegacyMetadata::BAMBOO_LEAF_SIZE_SHIFT) & BlockLegacyMetadata::BAMBOO_LEAF_SIZE_MASK, self::NO_LEAVES, self::LARGE_LEAVES);
|
$w->bool($this->thick);
|
||||||
$this->ready = ($stateMeta & BlockLegacyMetadata::BAMBOO_FLAG_READY) !== 0;
|
$w->bool($this->ready);
|
||||||
}
|
|
||||||
|
|
||||||
public function writeStateToMeta() : int{
|
|
||||||
return ($this->thick ? BlockLegacyMetadata::BAMBOO_FLAG_THICK : 0) | ($this->leafSize << BlockLegacyMetadata::BAMBOO_LEAF_SIZE_SHIFT) | ($this->ready ? BlockLegacyMetadata::BAMBOO_FLAG_READY : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
|
||||||
return 0b1111;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isThick() : bool{ return $this->thick; }
|
public function isThick() : bool{ return $this->thick; }
|
||||||
@ -100,6 +94,10 @@ class Bamboo extends Transparent{
|
|||||||
return [AxisAlignedBB::one()->trim(Facing::SOUTH, $inset)->trim(Facing::EAST, $inset)];
|
return [AxisAlignedBB::one()->trim(Facing::SOUTH, $inset)->trim(Facing::EAST, $inset)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
private static function getOffsetSeed(int $x, int $y, int $z) : int{
|
private static function getOffsetSeed(int $x, int $y, int $z) : int{
|
||||||
$p1 = gmp_mul($z, 0x6ebfff5);
|
$p1 = gmp_mul($z, 0x6ebfff5);
|
||||||
$p2 = gmp_mul($x, 0x2fc20f);
|
$p2 = gmp_mul($x, 0x2fc20f);
|
||||||
@ -123,26 +121,23 @@ class Bamboo extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function canBeSupportedBy(Block $block) : bool{
|
private function canBeSupportedBy(Block $block) : bool{
|
||||||
//TODO: tags would be better for this
|
|
||||||
return
|
return
|
||||||
$block instanceof Dirt ||
|
$block->getTypeId() === BlockTypeIds::GRAVEL ||
|
||||||
$block instanceof Grass ||
|
$block->hasTypeTag(BlockTypeTags::DIRT) ||
|
||||||
$block instanceof Gravel ||
|
$block->hasTypeTag(BlockTypeTags::MUD) ||
|
||||||
$block instanceof Sand ||
|
$block->hasTypeTag(BlockTypeTags::SAND);
|
||||||
$block instanceof Mycelium ||
|
|
||||||
$block instanceof Podzol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function seekToTop() : Bamboo{
|
private function seekToTop() : Bamboo{
|
||||||
$world = $this->position->getWorld();
|
$world = $this->position->getWorld();
|
||||||
$top = $this;
|
$top = $this;
|
||||||
while(($next = $world->getBlock($top->position->up())) instanceof Bamboo && $next->isSameType($this)){
|
while(($next = $world->getBlock($top->position->up())) instanceof Bamboo && $next->hasSameTypeId($this)){
|
||||||
$top = $next;
|
$top = $next;
|
||||||
}
|
}
|
||||||
return $top;
|
return $top;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
if($item instanceof Fertilizer){
|
if($item instanceof Fertilizer){
|
||||||
$top = $this->seekToTop();
|
$top = $this->seekToTop();
|
||||||
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
|
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
|
||||||
@ -159,9 +154,10 @@ class Bamboo extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
$below = $this->position->getWorld()->getBlock($this->position->down());
|
$world = $this->position->getWorld();
|
||||||
if(!$this->canBeSupportedBy($below) && !$below->isSameType($this)){
|
$below = $world->getBlock($this->position->down());
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
if(!$this->canBeSupportedBy($below) && !$below->hasSameTypeId($this)){
|
||||||
|
$world->useBreakOn($this->position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +168,7 @@ class Bamboo extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$height = 1;
|
$height = 1;
|
||||||
while($world->getBlock($this->position->subtract(0, $height, 0))->isSameType($this)){
|
while($world->getBlock($this->position->subtract(0, $height, 0))->hasSameTypeId($this)){
|
||||||
if(++$height >= $maxHeight){
|
if(++$height >= $maxHeight){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -207,7 +203,7 @@ class Bamboo extends Transparent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$tx = new BlockTransaction($this->position->getWorld());
|
$tx = new BlockTransaction($world);
|
||||||
foreach($newBlocks as $idx => $newBlock){
|
foreach($newBlocks as $idx => $newBlock){
|
||||||
$tx->addBlock($this->position->subtract(0, $idx - $growAmount, 0), $newBlock);
|
$tx->addBlock($this->position->subtract(0, $idx - $growAmount, 0), $newBlock);
|
||||||
}
|
}
|
||||||
@ -237,4 +233,8 @@ class Bamboo extends Transparent{
|
|||||||
$world->setBlock($this->position, $this);
|
$world->setBlock($this->position, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function asItem() : Item{
|
||||||
|
return VanillaItems::BAMBOO();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,34 +17,29 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
use pocketmine\event\block\StructureGrowEvent;
|
use pocketmine\event\block\StructureGrowEvent;
|
||||||
use pocketmine\item\Bamboo as ItemBamboo;
|
use pocketmine\item\Bamboo as ItemBamboo;
|
||||||
use pocketmine\item\Fertilizer;
|
use pocketmine\item\Fertilizer;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\VanillaItems;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
|
|
||||||
final class BambooSapling extends Flowable{
|
final class BambooSapling extends Flowable{
|
||||||
|
|
||||||
private bool $ready = false;
|
private bool $ready = false;
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
$this->ready = ($stateMeta & BlockLegacyMetadata::SAPLING_FLAG_READY) !== 0;
|
$w->bool($this->ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
|
||||||
return $this->ready ? BlockLegacyMetadata::SAPLING_FLAG_READY : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStateBitmask() : int{ return 0b1000; }
|
|
||||||
|
|
||||||
public function isReady() : bool{ return $this->ready; }
|
public function isReady() : bool{ return $this->ready; }
|
||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
@ -54,14 +49,11 @@ final class BambooSapling extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function canBeSupportedBy(Block $block) : bool{
|
private function canBeSupportedBy(Block $block) : bool{
|
||||||
//TODO: tags would be better for this
|
|
||||||
return
|
return
|
||||||
$block instanceof Dirt ||
|
$block->getTypeId() === BlockTypeIds::GRAVEL ||
|
||||||
$block instanceof Grass ||
|
$block->hasTypeTag(BlockTypeTags::DIRT) ||
|
||||||
$block instanceof Gravel ||
|
$block->hasTypeTag(BlockTypeTags::MUD) ||
|
||||||
$block instanceof Sand ||
|
$block->hasTypeTag(BlockTypeTags::SAND);
|
||||||
$block instanceof Mycelium ||
|
|
||||||
$block instanceof Podzol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
@ -71,7 +63,7 @@ final class BambooSapling extends Flowable{
|
|||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
|
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
|
||||||
if($this->grow($player)){
|
if($this->grow($player)){
|
||||||
$item->pop();
|
$item->pop();
|
||||||
@ -82,8 +74,9 @@ final class BambooSapling extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->canBeSupportedBy($this->position->getWorld()->getBlock($this->position->down()))){
|
$world = $this->position->getWorld();
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
|
||||||
|
$world->useBreakOn($this->position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +118,6 @@ final class BambooSapling extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function asItem() : Item{
|
public function asItem() : Item{
|
||||||
return VanillaBlocks::BAMBOO()->asItem();
|
return VanillaItems::BAMBOO();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\tile\Barrel as TileBarrel;
|
use pocketmine\block\tile\Barrel as TileBarrel;
|
||||||
use pocketmine\block\utils\AnyFacingTrait;
|
use pocketmine\block\utils\AnyFacingTrait;
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -38,17 +38,9 @@ class Barrel extends Opaque{
|
|||||||
|
|
||||||
protected bool $open = false;
|
protected bool $open = false;
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
return BlockDataSerializer::writeFacing($this->facing) | ($this->open ? BlockLegacyMetadata::BARREL_FLAG_OPEN : 0);
|
$w->facing($this->facing);
|
||||||
}
|
$w->bool($this->open);
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
|
||||||
$this->facing = BlockDataSerializer::readFacing($stateMeta & 0x07);
|
|
||||||
$this->open = ($stateMeta & BlockLegacyMetadata::BARREL_FLAG_OPEN) === BlockLegacyMetadata::BARREL_FLAG_OPEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
|
||||||
return 0b1111;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isOpen() : bool{
|
public function isOpen() : bool{
|
||||||
@ -81,7 +73,7 @@ class Barrel extends Opaque{
|
|||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$barrel = $this->position->getWorld()->getTile($this->position);
|
$barrel = $this->position->getWorld()->getTile($this->position);
|
||||||
if($barrel instanceof TileBarrel){
|
if($barrel instanceof TileBarrel){
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -27,9 +27,10 @@ use pocketmine\block\tile\Banner as TileBanner;
|
|||||||
use pocketmine\block\utils\BannerPatternLayer;
|
use pocketmine\block\utils\BannerPatternLayer;
|
||||||
use pocketmine\block\utils\ColoredTrait;
|
use pocketmine\block\utils\ColoredTrait;
|
||||||
use pocketmine\block\utils\DyeColor;
|
use pocketmine\block\utils\DyeColor;
|
||||||
use pocketmine\data\bedrock\DyeColorIdMap;
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\item\Banner as ItemBanner;
|
use pocketmine\item\Banner as ItemBanner;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\VanillaItems;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
@ -47,18 +48,20 @@ abstract class BaseBanner extends Transparent{
|
|||||||
*/
|
*/
|
||||||
protected array $patterns = [];
|
protected array $patterns = [];
|
||||||
|
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||||
$this->color = DyeColor::BLACK();
|
$this->color = DyeColor::BLACK();
|
||||||
parent::__construct($idInfo, $name, $breakInfo);
|
parent::__construct($idInfo, $name, $typeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromWorld() : void{
|
public function readStateFromWorld() : Block{
|
||||||
parent::readStateFromWorld();
|
parent::readStateFromWorld();
|
||||||
$tile = $this->position->getWorld()->getTile($this->position);
|
$tile = $this->position->getWorld()->getTile($this->position);
|
||||||
if($tile instanceof TileBanner){
|
if($tile instanceof TileBanner){
|
||||||
$this->color = $tile->getBaseColor();
|
$this->color = $tile->getBaseColor();
|
||||||
$this->setPatterns($tile->getPatterns());
|
$this->setPatterns($tile->getPatterns());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeStateToWorld() : void{
|
public function writeStateToWorld() : void{
|
||||||
@ -86,7 +89,7 @@ abstract class BaseBanner extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BannerPatternLayer[] $patterns
|
* @param BannerPatternLayer[] $patterns
|
||||||
*
|
*
|
||||||
* @phpstan-param list<BannerPatternLayer> $patterns
|
* @phpstan-param list<BannerPatternLayer> $patterns
|
||||||
* @return $this
|
* @return $this
|
||||||
@ -107,7 +110,18 @@ abstract class BaseBanner extends Transparent{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function canBeSupportedBy(Block $block) : bool{
|
||||||
|
return $block->isSolid();
|
||||||
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
|
if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportingFace()))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if($item instanceof ItemBanner){
|
if($item instanceof ItemBanner){
|
||||||
$this->color = $item->getColor();
|
$this->color = $item->getColor();
|
||||||
$this->setPatterns($item->getPatterns());
|
$this->setPatterns($item->getPatterns());
|
||||||
@ -119,15 +133,11 @@ abstract class BaseBanner extends Transparent{
|
|||||||
abstract protected function getSupportingFace() : int;
|
abstract protected function getSupportingFace() : int;
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide($this->getSupportingFace())->getId() === BlockLegacyIds::AIR){
|
if(!$this->canBeSupportedBy($this->getSide($this->getSupportingFace()))){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function writeStateToItemMeta() : int{
|
|
||||||
return DyeColorIdMap::getInstance()->toInvertedId($this->color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
$drop = $this->asItem();
|
$drop = $this->asItem();
|
||||||
if($drop instanceof ItemBanner && count($this->patterns) > 0){
|
if($drop instanceof ItemBanner && count($this->patterns) > 0){
|
||||||
@ -144,4 +154,8 @@ abstract class BaseBanner extends Transparent{
|
|||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function asItem() : Item{
|
||||||
|
return VanillaItems::BANNER()->setColor($this->color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
89
src/block/BaseCake.php
Normal file
89
src/block/BaseCake.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\entity\effect\EffectInstance;
|
||||||
|
use pocketmine\entity\FoodSource;
|
||||||
|
use pocketmine\entity\Living;
|
||||||
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\player\Player;
|
||||||
|
use pocketmine\world\BlockTransaction;
|
||||||
|
|
||||||
|
abstract class BaseCake extends Transparent implements FoodSource{
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
|
$down = $this->getSide(Facing::DOWN);
|
||||||
|
if($down->getTypeId() !== BlockTypeIds::AIR){
|
||||||
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
if($this->getSide(Facing::DOWN)->getTypeId() === BlockTypeIds::AIR){ //Replace with common break method
|
||||||
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
|
if($player !== null){
|
||||||
|
return $player->consumeObject($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFoodRestore() : int{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSaturationRestore() : float{
|
||||||
|
return 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function requiresHunger() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return EffectInstance[]
|
||||||
|
*/
|
||||||
|
public function getAdditionalEffects() : array{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public function getResidue() : Block;
|
||||||
|
|
||||||
|
public function onConsume(Living $consumer) : void{
|
||||||
|
$this->position->getWorld()->setBlock($this->position, $this->getResidue());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,31 +25,31 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\utils\CoralType;
|
use pocketmine\block\utils\CoralType;
|
||||||
use pocketmine\block\utils\CoralTypeTrait;
|
use pocketmine\block\utils\CoralTypeTrait;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\event\block\BlockDeathEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
abstract class BaseCoral extends Transparent{
|
abstract class BaseCoral extends Transparent{
|
||||||
use CoralTypeTrait;
|
use CoralTypeTrait;
|
||||||
|
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||||
parent::__construct($idInfo, $name, $breakInfo);
|
|
||||||
$this->coralType = CoralType::TUBE();
|
$this->coralType = CoralType::TUBE();
|
||||||
|
parent::__construct($idInfo, $name, $typeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->dead){
|
if(!$this->dead){
|
||||||
$world = $this->position->getWorld();
|
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(40, 200));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$hasWater = false;
|
public function onScheduledUpdate() : void{
|
||||||
foreach($this->position->sides() as $vector3){
|
if(!$this->dead && !$this->isCoveredWithWater()){
|
||||||
if($world->getBlock($vector3) instanceof Water){
|
$ev = new BlockDeathEvent($this, $this->setDead(true));
|
||||||
$hasWater = true;
|
$ev->call();
|
||||||
break;
|
if(!$ev->isCancelled()){
|
||||||
}
|
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: check water inside the block itself (not supported on the API yet)
|
|
||||||
if(!$hasWater){
|
|
||||||
$world->setBlock($this->position, $this->setDead(true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,5 +64,24 @@ abstract class BaseCoral extends Transparent{
|
|||||||
|
|
||||||
public function isSolid() : bool{ return false; }
|
public function isSolid() : bool{ return false; }
|
||||||
|
|
||||||
|
protected function isCoveredWithWater() : bool{
|
||||||
|
$world = $this->position->getWorld();
|
||||||
|
|
||||||
|
$hasWater = false;
|
||||||
|
foreach($this->position->sides() as $vector3){
|
||||||
|
if($world->getBlock($vector3) instanceof Water){
|
||||||
|
$hasWater = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: check water inside the block itself (not supported on the API yet)
|
||||||
|
return $hasWater;
|
||||||
|
}
|
||||||
|
|
||||||
protected function recalculateCollisionBoxes() : array{ return []; }
|
protected function recalculateCollisionBoxes() : array{ return []; }
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/block/BaseFire.php
Normal file
63
src/block/BaseFire.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\entity\Entity;
|
||||||
|
use pocketmine\entity\projectile\Arrow;
|
||||||
|
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
||||||
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
|
use pocketmine\item\Item;
|
||||||
|
|
||||||
|
abstract class BaseFire extends Flowable{
|
||||||
|
|
||||||
|
public function hasEntityCollision() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canBeReplaced() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onEntityInside(Entity $entity) : bool{
|
||||||
|
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, $this->getFireDamage());
|
||||||
|
$entity->attack($ev);
|
||||||
|
|
||||||
|
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
|
||||||
|
if($entity instanceof Arrow){
|
||||||
|
$ev->cancel();
|
||||||
|
}
|
||||||
|
$ev->call();
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$entity->setOnFire($ev->getDuration());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function getFireDamage() : int;
|
||||||
|
|
||||||
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ use function in_array;
|
|||||||
abstract class BaseRail extends Flowable{
|
abstract class BaseRail extends Flowable{
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if(!$blockReplace->getSide(Facing::DOWN)->isTransparent()){
|
if($blockReplace->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +162,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
$thisConnections = $this->getConnectedDirections();
|
$thisConnections = $this->getConnectedDirections();
|
||||||
$changed = false;
|
$changed = false;
|
||||||
|
|
||||||
|
$world = $this->position->getWorld();
|
||||||
do{
|
do{
|
||||||
$possible = $this->getPossibleConnectionDirections($thisConnections);
|
$possible = $this->getPossibleConnectionDirections($thisConnections);
|
||||||
$continue = false;
|
$continue = false;
|
||||||
@ -189,7 +190,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
if(isset($otherPossible[$otherSide])){
|
if(isset($otherPossible[$otherSide])){
|
||||||
$otherConnections[] = $otherSide;
|
$otherConnections[] = $otherSide;
|
||||||
$other->setConnections($otherConnections);
|
$other->setConnections($otherConnections);
|
||||||
$this->position->getWorld()->setBlock($other->position, $other);
|
$world->setBlock($other->position, $other);
|
||||||
|
|
||||||
$changed = true;
|
$changed = true;
|
||||||
$thisConnections[] = $thisSide;
|
$thisConnections[] = $thisSide;
|
||||||
@ -202,7 +203,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
|
|
||||||
if($changed){
|
if($changed){
|
||||||
$this->setConnections($thisConnections);
|
$this->setConnections($thisConnections);
|
||||||
$this->position->getWorld()->setBlock($this->position, $this);
|
$world->setBlock($this->position, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,12 +221,13 @@ abstract class BaseRail extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Facing::DOWN)->isTransparent()){
|
$world = $this->position->getWorld();
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
if(!$this->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||||
|
$world->useBreakOn($this->position);
|
||||||
}else{
|
}else{
|
||||||
foreach($this->getCurrentShapeConnections() as $connection){
|
foreach($this->getCurrentShapeConnections() as $connection){
|
||||||
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && $this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->isTransparent()){
|
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && !$this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$world->useBreakOn($this->position);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,41 +17,62 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\tile\Sign as TileSign;
|
use pocketmine\block\tile\Sign as TileSign;
|
||||||
|
use pocketmine\block\utils\DyeColor;
|
||||||
use pocketmine\block\utils\SignText;
|
use pocketmine\block\utils\SignText;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\block\utils\WoodType;
|
||||||
|
use pocketmine\block\utils\WoodTypeTrait;
|
||||||
|
use pocketmine\color\Color;
|
||||||
use pocketmine\event\block\SignChangeEvent;
|
use pocketmine\event\block\SignChangeEvent;
|
||||||
|
use pocketmine\item\Dye;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\ItemTypeIds;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
|
use pocketmine\world\sound\DyeUseSound;
|
||||||
|
use pocketmine\world\sound\InkSacUseSound;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
use function assert;
|
use function assert;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
|
|
||||||
abstract class BaseSign extends Transparent{
|
abstract class BaseSign extends Transparent{
|
||||||
|
use WoodTypeTrait;
|
||||||
|
|
||||||
protected SignText $text;
|
protected SignText $text;
|
||||||
protected ?int $editorEntityRuntimeId = null;
|
protected ?int $editorEntityRuntimeId = null;
|
||||||
|
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
/** @var \Closure() : Item */
|
||||||
parent::__construct($idInfo, $name, $breakInfo);
|
private \Closure $asItemCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Closure() : Item $asItemCallback
|
||||||
|
*/
|
||||||
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, WoodType $woodType, \Closure $asItemCallback){
|
||||||
|
$this->woodType = $woodType;
|
||||||
|
parent::__construct($idInfo, $name, $typeInfo);
|
||||||
$this->text = new SignText();
|
$this->text = new SignText();
|
||||||
|
$this->asItemCallback = $asItemCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromWorld() : void{
|
public function readStateFromWorld() : Block{
|
||||||
parent::readStateFromWorld();
|
parent::readStateFromWorld();
|
||||||
$tile = $this->position->getWorld()->getTile($this->position);
|
$tile = $this->position->getWorld()->getTile($this->position);
|
||||||
if($tile instanceof TileSign){
|
if($tile instanceof TileSign){
|
||||||
$this->text = $tile->getText();
|
$this->text = $tile->getText();
|
||||||
$this->editorEntityRuntimeId = $tile->getEditorEntityRuntimeId();
|
$this->editorEntityRuntimeId = $tile->getEditorEntityRuntimeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeStateToWorld() : void{
|
public function writeStateToWorld() : void{
|
||||||
@ -77,10 +98,14 @@ abstract class BaseSign extends Transparent{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
abstract protected function getSupportingFace() : int;
|
abstract protected function getSupportingFace() : int;
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide($this->getSupportingFace())->getId() === BlockLegacyIds::AIR){
|
if($this->getSide($this->getSupportingFace())->getTypeId() === BlockTypeIds::AIR){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,6 +117,64 @@ abstract class BaseSign extends Transparent{
|
|||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onPostPlace() : void{
|
||||||
|
$player = $this->editorEntityRuntimeId !== null ?
|
||||||
|
$this->position->getWorld()->getEntity($this->editorEntityRuntimeId) :
|
||||||
|
null;
|
||||||
|
if($player instanceof Player){
|
||||||
|
$player->openSignEditor($this->position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doSignChange(SignText $newText, Player $player, Item $item) : bool{
|
||||||
|
$ev = new SignChangeEvent($this, $player, $newText);
|
||||||
|
$ev->call();
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$this->text = $ev->getNewText();
|
||||||
|
$this->position->getWorld()->setBlock($this->position, $this);
|
||||||
|
$item->pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function changeSignGlowingState(bool $glowing, Player $player, Item $item) : bool{
|
||||||
|
if($this->text->isGlowing() !== $glowing && $this->doSignChange(new SignText($this->text->getLines(), $this->text->getBaseColor(), $glowing), $player, $item)){
|
||||||
|
$this->position->getWorld()->addSound($this->position, new InkSacUseSound());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
|
if($player === null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$dyeColor = $item instanceof Dye ? $item->getColor() : match($item->getTypeId()){
|
||||||
|
ItemTypeIds::BONE_MEAL => DyeColor::WHITE(),
|
||||||
|
ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE(),
|
||||||
|
ItemTypeIds::COCOA_BEANS => DyeColor::BROWN(),
|
||||||
|
default => null
|
||||||
|
};
|
||||||
|
if($dyeColor !== null){
|
||||||
|
$color = $dyeColor->equals(DyeColor::BLACK()) ? new Color(0, 0, 0) : $dyeColor->getRgbValue();
|
||||||
|
if($color->toARGB() === $this->text->getBaseColor()->toARGB()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item)){
|
||||||
|
$this->position->getWorld()->addSound($this->position, new DyeUseSound());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}elseif($item->getTypeId() === ItemTypeIds::INK_SAC){
|
||||||
|
return $this->changeSignGlowingState(false, $player, $item);
|
||||||
|
}elseif($item->getTypeId() === ItemTypeIds::GLOW_INK_SAC){
|
||||||
|
return $this->changeSignGlowingState(true, $player, $item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object containing information about the sign text.
|
* Returns an object containing information about the sign text.
|
||||||
*/
|
*/
|
||||||
@ -105,6 +188,19 @@ abstract class BaseSign extends Transparent{
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the runtime entity ID of the player editing this sign. Only this player will be able to edit the sign.
|
||||||
|
* This is used to prevent multiple players from editing the same sign at the same time, and to prevent players
|
||||||
|
* from editing signs they didn't place.
|
||||||
|
*/
|
||||||
|
public function getEditorEntityRuntimeId() : ?int{ return $this->editorEntityRuntimeId; }
|
||||||
|
|
||||||
|
/** @return $this */
|
||||||
|
public function setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : self{
|
||||||
|
$this->editorEntityRuntimeId = $editorEntityRuntimeId;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the player controller (network session) to update the sign text, firing events as appropriate.
|
* Called by the player controller (network session) to update the sign text, firing events as appropriate.
|
||||||
*
|
*
|
||||||
@ -128,10 +224,15 @@ abstract class BaseSign extends Transparent{
|
|||||||
$ev->call();
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->setText($ev->getNewText());
|
$this->setText($ev->getNewText());
|
||||||
|
$this->setEditorEntityRuntimeId(null);
|
||||||
$this->position->getWorld()->setBlock($this->position, $this);
|
$this->position->getWorld()->setBlock($this->position, $this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function asItem() : Item{
|
||||||
|
return ($this->asItemCallback)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|||||||
@ -17,18 +17,18 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\tile\Bed as TileBed;
|
use pocketmine\block\tile\Bed as TileBed;
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
|
||||||
use pocketmine\block\utils\ColoredTrait;
|
use pocketmine\block\utils\ColoredTrait;
|
||||||
use pocketmine\block\utils\DyeColor;
|
use pocketmine\block\utils\DyeColor;
|
||||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||||
use pocketmine\data\bedrock\DyeColorIdMap;
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\entity\Living;
|
use pocketmine\entity\Living;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
@ -48,34 +48,26 @@ class Bed extends Transparent{
|
|||||||
protected bool $occupied = false;
|
protected bool $occupied = false;
|
||||||
protected bool $head = false;
|
protected bool $head = false;
|
||||||
|
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||||
$this->color = DyeColor::RED();
|
$this->color = DyeColor::RED();
|
||||||
parent::__construct($idInfo, $name, $breakInfo);
|
parent::__construct($idInfo, $name, $typeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) |
|
$w->horizontalFacing($this->facing);
|
||||||
($this->occupied ? BlockLegacyMetadata::BED_FLAG_OCCUPIED : 0) |
|
$w->bool($this->occupied);
|
||||||
($this->head ? BlockLegacyMetadata::BED_FLAG_HEAD : 0);
|
$w->bool($this->head);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
public function readStateFromWorld() : Block{
|
||||||
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
|
|
||||||
$this->occupied = ($stateMeta & BlockLegacyMetadata::BED_FLAG_OCCUPIED) !== 0;
|
|
||||||
$this->head = ($stateMeta & BlockLegacyMetadata::BED_FLAG_HEAD) !== 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
|
||||||
return 0b1111;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function readStateFromWorld() : void{
|
|
||||||
parent::readStateFromWorld();
|
parent::readStateFromWorld();
|
||||||
//read extra state information from the tile - this is an ugly hack
|
//read extra state information from the tile - this is an ugly hack
|
||||||
$tile = $this->position->getWorld()->getTile($this->position);
|
$tile = $this->position->getWorld()->getTile($this->position);
|
||||||
if($tile instanceof TileBed){
|
if($tile instanceof TileBed){
|
||||||
$this->color = $tile->getColor();
|
$this->color = $tile->getColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeStateToWorld() : void{
|
public function writeStateToWorld() : void{
|
||||||
@ -94,6 +86,10 @@ class Bed extends Transparent{
|
|||||||
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
|
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function isHeadPart() : bool{
|
public function isHeadPart() : bool{
|
||||||
return $this->head;
|
return $this->head;
|
||||||
}
|
}
|
||||||
@ -127,7 +123,7 @@ class Bed extends Transparent{
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
if($player !== null){
|
if($player !== null){
|
||||||
$other = $this->getOtherHalf();
|
$other = $this->getOtherHalf();
|
||||||
$playerPos = $player->getPosition();
|
$playerPos = $player->getPosition();
|
||||||
@ -166,7 +162,7 @@ class Bed extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(($other = $this->getOtherHalf()) !== null && $other->occupied !== $this->occupied){
|
if(!$this->head && ($other = $this->getOtherHalf()) !== null && $other->occupied !== $this->occupied){
|
||||||
$this->occupied = $other->occupied;
|
$this->occupied = $other->occupied;
|
||||||
$this->position->getWorld()->setBlock($this->position, $this);
|
$this->position->getWorld()->setBlock($this->position, $this);
|
||||||
}
|
}
|
||||||
@ -181,12 +177,11 @@ class Bed extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
$down = $this->getSide(Facing::DOWN);
|
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
|
||||||
if(!$down->isTransparent()){
|
|
||||||
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
|
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
|
||||||
|
|
||||||
$next = $this->getSide($this->getOtherHalfSide());
|
$next = $this->getSide($this->getOtherHalfSide());
|
||||||
if($next->canBeReplaced() && !$next->getSide(Facing::DOWN)->isTransparent()){
|
if($next->canBeReplaced() && $this->canBeSupportedBy($next->getSide(Facing::DOWN))){
|
||||||
$nextState = clone $this;
|
$nextState = clone $this;
|
||||||
$nextState->head = true;
|
$nextState->head = true;
|
||||||
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);
|
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);
|
||||||
@ -205,10 +200,6 @@ class Bed extends Transparent{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function writeStateToItemMeta() : int{
|
|
||||||
return DyeColorIdMap::getInstance()->toId($this->color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAffectedBlocks() : array{
|
public function getAffectedBlocks() : array{
|
||||||
if(($other = $this->getOtherHalf()) !== null){
|
if(($other = $this->getOtherHalf()) !== null){
|
||||||
return [$this, $other];
|
return [$this, $other];
|
||||||
@ -216,4 +207,10 @@ class Bed extends Transparent{
|
|||||||
|
|
||||||
return parent::getAffectedBlocks();
|
return parent::getAffectedBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function canBeSupportedBy(Block $block) : bool{
|
||||||
|
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMaxStackSize() : int{ return 1; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,26 +17,19 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
class Bedrock extends Opaque{
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
|
|
||||||
|
class Bedrock extends Opaque{
|
||||||
private bool $burnsForever = false;
|
private bool $burnsForever = false;
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
$this->burnsForever = ($stateMeta & BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN) !== 0;
|
$w->bool($this->burnsForever);
|
||||||
}
|
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
|
||||||
return $this->burnsForever ? BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
|
||||||
return 0b1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function burnsForever() : bool{
|
public function burnsForever() : bool{
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ use function mt_rand;
|
|||||||
class Beetroot extends Crops{
|
class Beetroot extends Crops{
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($this->age >= 7){
|
if($this->age >= self::MAX_AGE){
|
||||||
return [
|
return [
|
||||||
VanillaItems::BEETROOT(),
|
VanillaItems::BEETROOT(),
|
||||||
VanillaItems::BEETROOT_SEEDS()->setCount(mt_rand(0, 3))
|
VanillaItems::BEETROOT_SEEDS()->setCount(mt_rand(0, 3))
|
||||||
@ -42,7 +42,7 @@ class Beetroot extends Crops{
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPickedItem(bool $addUserData = false) : Item{
|
public function asItem() : Item{
|
||||||
return VanillaItems::BEETROOT_SEEDS();
|
return VanillaItems::BEETROOT_SEEDS();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,14 +25,16 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\tile\Bell as TileBell;
|
use pocketmine\block\tile\Bell as TileBell;
|
||||||
use pocketmine\block\utils\BellAttachmentType;
|
use pocketmine\block\utils\BellAttachmentType;
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
|
||||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||||
use pocketmine\block\utils\InvalidBlockStateException;
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
|
use pocketmine\entity\projectile\Projectile;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
|
use pocketmine\math\RayTraceResult;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\utils\AssumptionFailedError;
|
|
||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
use pocketmine\world\sound\BellRingSound;
|
use pocketmine\world\sound\BellRingSound;
|
||||||
|
|
||||||
@ -41,41 +43,40 @@ final class Bell extends Transparent{
|
|||||||
|
|
||||||
private BellAttachmentType $attachmentType;
|
private BellAttachmentType $attachmentType;
|
||||||
|
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||||
$this->attachmentType = BellAttachmentType::FLOOR();
|
$this->attachmentType = BellAttachmentType::FLOOR();
|
||||||
parent::__construct($idInfo, $name, $breakInfo);
|
parent::__construct($idInfo, $name, $typeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
$this->setFacing(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03));
|
$w->bellAttachmentType($this->attachmentType);
|
||||||
|
$w->horizontalFacing($this->facing);
|
||||||
|
}
|
||||||
|
|
||||||
$attachmentType = [
|
protected function recalculateCollisionBoxes() : array{
|
||||||
BlockLegacyMetadata::BELL_ATTACHMENT_FLOOR => BellAttachmentType::FLOOR(),
|
if($this->attachmentType->equals(BellAttachmentType::FLOOR())){
|
||||||
BlockLegacyMetadata::BELL_ATTACHMENT_CEILING => BellAttachmentType::CEILING(),
|
return [
|
||||||
BlockLegacyMetadata::BELL_ATTACHMENT_ONE_WALL => BellAttachmentType::ONE_WALL(),
|
AxisAlignedBB::one()->squash(Facing::axis($this->facing), 1 / 4)->trim(Facing::UP, 3 / 16)
|
||||||
BlockLegacyMetadata::BELL_ATTACHMENT_TWO_WALLS => BellAttachmentType::TWO_WALLS()
|
];
|
||||||
][($stateMeta >> 2) & 0b11] ?? null;
|
|
||||||
if($attachmentType === null){
|
|
||||||
throw new InvalidBlockStateException("No such attachment type");
|
|
||||||
}
|
}
|
||||||
$this->setAttachmentType($attachmentType);
|
if($this->attachmentType->equals(BellAttachmentType::CEILING())){
|
||||||
}
|
return [
|
||||||
|
AxisAlignedBB::one()->contract(1 / 4, 0, 1 / 4)->trim(Facing::DOWN, 1 / 4)
|
||||||
public function writeStateToMeta() : int{
|
];
|
||||||
$attachmentTypeMeta = [
|
|
||||||
BellAttachmentType::FLOOR()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_FLOOR,
|
|
||||||
BellAttachmentType::CEILING()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_CEILING,
|
|
||||||
BellAttachmentType::ONE_WALL()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_ONE_WALL,
|
|
||||||
BellAttachmentType::TWO_WALLS()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_TWO_WALLS
|
|
||||||
][$this->getAttachmentType()->id()] ?? null;
|
|
||||||
if($attachmentTypeMeta === null){
|
|
||||||
throw new AssumptionFailedError("Mapping should cover all cases");
|
|
||||||
}
|
}
|
||||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->getFacing()) | ($attachmentTypeMeta << 2);
|
|
||||||
|
$box = AxisAlignedBB::one()
|
||||||
|
->squash(Facing::axis(Facing::rotateY($this->facing, true)), 1 / 4)
|
||||||
|
->trim(Facing::UP, 1 / 16)
|
||||||
|
->trim(Facing::DOWN, 1 / 4);
|
||||||
|
|
||||||
|
return [
|
||||||
|
$this->attachmentType->equals(BellAttachmentType::ONE_WALL()) ? $box->trim($this->facing, 3 / 16) : $box
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
public function getSupportType(int $facing) : SupportType{
|
||||||
return 0b1111;
|
return SupportType::NONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
|
public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
|
||||||
@ -86,14 +87,13 @@ final class Bell extends Transparent{
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function canBeSupportedBy(Block $block) : bool{
|
private function canBeSupportedBy(Block $block, int $face) : bool{
|
||||||
//TODO: this isn't the actual logic, but it's the closest approximation we can support for now
|
return !$block->getSupportType($face)->equals(SupportType::NONE());
|
||||||
return $block->isSolid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($face === Facing::UP){
|
if($face === Facing::UP){
|
||||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()))){
|
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()), Facing::UP)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if($player !== null){
|
if($player !== null){
|
||||||
@ -101,18 +101,18 @@ final class Bell extends Transparent{
|
|||||||
}
|
}
|
||||||
$this->setAttachmentType(BellAttachmentType::FLOOR());
|
$this->setAttachmentType(BellAttachmentType::FLOOR());
|
||||||
}elseif($face === Facing::DOWN){
|
}elseif($face === Facing::DOWN){
|
||||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()))){
|
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()), Facing::DOWN)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->setAttachmentType(BellAttachmentType::CEILING());
|
$this->setAttachmentType(BellAttachmentType::CEILING());
|
||||||
}else{
|
}else{
|
||||||
$this->setFacing($face);
|
$this->setFacing($face);
|
||||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))))){
|
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))), $face)){
|
||||||
$this->setAttachmentType(BellAttachmentType::ONE_WALL());
|
$this->setAttachmentType(BellAttachmentType::ONE_WALL());
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)))){
|
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)), Facing::opposite($face))){
|
||||||
$this->setAttachmentType(BellAttachmentType::TWO_WALLS());
|
$this->setAttachmentType(BellAttachmentType::TWO_WALLS());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,40 +121,51 @@ final class Bell extends Transparent{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(
|
if(
|
||||||
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP))) ||
|
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP), Facing::DOWN)) ||
|
||||||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))) ||
|
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN), Facing::UP)) ||
|
||||||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)))) ||
|
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)) ||
|
||||||
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)))))
|
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing), Facing::opposite($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)))
|
||||||
){
|
){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
if($player !== null){
|
if($player !== null){
|
||||||
$faceHit = Facing::opposite($player->getHorizontalFacing());
|
$faceHit = Facing::opposite($player->getHorizontalFacing());
|
||||||
if($this->attachmentType->equals(BellAttachmentType::CEILING())){
|
if($this->isValidFaceToRing($faceHit)){
|
||||||
$this->ring($faceHit);
|
|
||||||
}
|
|
||||||
if($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)){
|
|
||||||
$this->ring($faceHit);
|
|
||||||
}
|
|
||||||
if(
|
|
||||||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
|
|
||||||
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
|
|
||||||
){
|
|
||||||
$this->ring($faceHit);
|
$this->ring($faceHit);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
|
||||||
|
$faceHit = Facing::opposite($projectile->getHorizontalFacing());
|
||||||
|
if($this->isValidFaceToRing($faceHit)){
|
||||||
|
$this->ring($faceHit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ring(int $faceHit) : void{
|
public function ring(int $faceHit) : void{
|
||||||
$this->position->getWorld()->addSound($this->position, new BellRingSound());
|
$world = $this->position->getWorld();
|
||||||
$tile = $this->position->getWorld()->getTile($this->position);
|
$world->addSound($this->position, new BellRingSound());
|
||||||
|
$tile = $world->getTile($this->position);
|
||||||
if($tile instanceof TileBell){
|
if($tile instanceof TileBell){
|
||||||
$this->position->getWorld()->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
|
$world->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function isValidFaceToRing(int $faceHit) : bool{
|
||||||
|
return (
|
||||||
|
$this->attachmentType->equals(BellAttachmentType::CEILING()) ||
|
||||||
|
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)) ||
|
||||||
|
(
|
||||||
|
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
|
||||||
|
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -28,131 +28,316 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\tile\Spawnable;
|
use pocketmine\block\tile\Spawnable;
|
||||||
use pocketmine\block\tile\Tile;
|
use pocketmine\block\tile\Tile;
|
||||||
use pocketmine\block\utils\InvalidBlockStateException;
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\data\runtime\InvalidSerializedRuntimeDataException;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataReader;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataSizeCalculator;
|
||||||
|
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
|
use pocketmine\entity\projectile\Projectile;
|
||||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemBlock;
|
||||||
use pocketmine\math\Axis;
|
use pocketmine\math\Axis;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\RayTraceResult;
|
use pocketmine\math\RayTraceResult;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\nbt\tag\CompoundTag;
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
use pocketmine\world\format\Chunk;
|
use pocketmine\world\format\Chunk;
|
||||||
use pocketmine\world\Position;
|
use pocketmine\world\Position;
|
||||||
use pocketmine\world\World;
|
use pocketmine\world\World;
|
||||||
use function assert;
|
|
||||||
use function count;
|
use function count;
|
||||||
use function dechex;
|
use function get_class;
|
||||||
use const PHP_INT_MAX;
|
use const PHP_INT_MAX;
|
||||||
|
|
||||||
class Block{
|
class Block{
|
||||||
public const INTERNAL_METADATA_BITS = 4;
|
public const INTERNAL_STATE_DATA_BITS = 8;
|
||||||
public const INTERNAL_METADATA_MASK = ~(~0 << self::INTERNAL_METADATA_BITS);
|
public const INTERNAL_STATE_DATA_MASK = ~(~0 << self::INTERNAL_STATE_DATA_BITS);
|
||||||
|
|
||||||
protected BlockIdentifier $idInfo;
|
protected BlockIdentifier $idInfo;
|
||||||
protected string $fallbackName;
|
protected string $fallbackName;
|
||||||
protected BlockBreakInfo $breakInfo;
|
protected BlockTypeInfo $typeInfo;
|
||||||
protected Position $position;
|
protected Position $position;
|
||||||
|
|
||||||
/** @var AxisAlignedBB[]|null */
|
/** @var AxisAlignedBB[]|null */
|
||||||
protected ?array $collisionBoxes = null;
|
protected ?array $collisionBoxes = null;
|
||||||
|
|
||||||
|
private int $requiredBlockItemStateDataBits;
|
||||||
|
private int $requiredBlockOnlyStateDataBits;
|
||||||
|
private int $defaultBlockOnlyStateData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name English name of the block type (TODO: implement translations)
|
* @param string $name English name of the block type (TODO: implement translations)
|
||||||
*/
|
*/
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||||
if(($idInfo->getVariant() & $this->getStateBitmask()) !== 0){
|
|
||||||
throw new \InvalidArgumentException("Variant 0x" . dechex($idInfo->getVariant()) . " collides with state bitmask 0x" . dechex($this->getStateBitmask()));
|
|
||||||
}
|
|
||||||
$this->idInfo = $idInfo;
|
$this->idInfo = $idInfo;
|
||||||
$this->fallbackName = $name;
|
$this->fallbackName = $name;
|
||||||
$this->breakInfo = $breakInfo;
|
$this->typeInfo = $typeInfo;
|
||||||
$this->position = new Position(0, 0, 0, null);
|
$this->position = new Position(0, 0, 0, null);
|
||||||
|
|
||||||
|
$calculator = new RuntimeDataSizeCalculator();
|
||||||
|
$this->describeBlockItemState($calculator);
|
||||||
|
$this->requiredBlockItemStateDataBits = $calculator->getBitsUsed();
|
||||||
|
|
||||||
|
$calculator = new RuntimeDataSizeCalculator();
|
||||||
|
$this->describeBlockOnlyState($calculator);
|
||||||
|
$this->requiredBlockOnlyStateDataBits = $calculator->getBitsUsed();
|
||||||
|
|
||||||
|
$this->defaultBlockOnlyStateData = $this->encodeBlockOnlyState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __clone(){
|
public function __clone(){
|
||||||
$this->position = clone $this->position;
|
$this->position = clone $this->position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object containing information about how to identify and store this block type, such as type ID and
|
||||||
|
* tile type (if any).
|
||||||
|
*/
|
||||||
public function getIdInfo() : BlockIdentifier{
|
public function getIdInfo() : BlockIdentifier{
|
||||||
return $this->idInfo;
|
return $this->idInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the printable English name of the block.
|
||||||
|
*/
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return $this->fallbackName;
|
return $this->fallbackName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId() : int{
|
/**
|
||||||
return $this->idInfo->getBlockId();
|
* Returns a type ID that identifies this type of block. This allows comparing basic block types, e.g. wool, stone,
|
||||||
|
* glass, etc. Type ID will not change for a given block type.
|
||||||
|
*
|
||||||
|
* Information such as colour, powered, open/closed, etc. is **not** included in this ID.
|
||||||
|
* If you want to get a state ID that includes this information, use {@link Block::getStateId()} instead.
|
||||||
|
*
|
||||||
|
* @see BlockTypeIds
|
||||||
|
*/
|
||||||
|
public function getTypeId() : int{
|
||||||
|
return $this->idInfo->getBlockTypeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
*
|
||||||
|
* Returns the full blockstate ID of this block. This is a compact way of representing a blockstate used to store
|
||||||
|
* blocks in chunks at runtime.
|
||||||
|
*
|
||||||
|
* This usually encodes all properties of the block, such as facing, open/closed, powered/unpowered, colour, etc.
|
||||||
|
* State ID may change depending on the properties of the block (e.g. a torch facing east will have a different
|
||||||
|
* state ID to one facing west).
|
||||||
|
*
|
||||||
|
* Some blocks (such as signs and chests) may store additional properties in an associated "tile" if they
|
||||||
|
* have too many possible values to be encoded into the state ID. These extra properties are **NOT** included in
|
||||||
|
* this function's result.
|
||||||
|
*
|
||||||
|
* This ID can be used to later obtain a copy of the block with the same state properties by using
|
||||||
|
* {@link RuntimeBlockStateRegistry::fromStateId()}.
|
||||||
*/
|
*/
|
||||||
public function getFullId() : int{
|
public function getStateId() : int{
|
||||||
return ($this->getId() << self::INTERNAL_METADATA_BITS) | $this->getMeta();
|
return ($this->getTypeId() << self::INTERNAL_STATE_DATA_BITS) | $this->encodeFullState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given block has the same type ID as this one.
|
||||||
|
*/
|
||||||
|
public function hasSameTypeId(Block $other) : bool{
|
||||||
|
return $this->getTypeId() === $other->getTypeId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given block has the same type and properties as this block.
|
||||||
|
*
|
||||||
|
* Note: Tile data (e.g. sign text, chest contents) are not compared here.
|
||||||
|
*/
|
||||||
|
public function isSameState(Block $other) : bool{
|
||||||
|
return $this->getStateId() === $other->getStateId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getTypeTags() : array{
|
||||||
|
return $this->typeInfo->getTypeTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this block type has the given type tag. Type tags are used as a dynamic way to tag blocks as
|
||||||
|
* having certain properties, allowing type checks which are more dynamic than hardcoding a bunch of IDs or a bunch
|
||||||
|
* of instanceof checks.
|
||||||
|
*
|
||||||
|
* For example, grass blocks, dirt, farmland, podzol and mycelium are all dirt-like blocks, and support the
|
||||||
|
* placement of blocks like flowers, so they have a common tag which allows them to be identified as such.
|
||||||
|
*/
|
||||||
|
public function hasTypeTag(string $tag) : bool{
|
||||||
|
return $this->typeInfo->hasTypeTag($tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the block as an item.
|
||||||
|
* Block-only state such as facing, powered/unpowered, open/closed, etc., is discarded.
|
||||||
|
* Block-item state such as colour, wood type, etc. is preserved.
|
||||||
|
*/
|
||||||
public function asItem() : Item{
|
public function asItem() : Item{
|
||||||
return ItemFactory::getInstance()->get(
|
$normalized = clone $this;
|
||||||
$this->idInfo->getItemId(),
|
$normalized->decodeBlockOnlyState($this->defaultBlockOnlyStateData);
|
||||||
$this->idInfo->getVariant() | $this->writeStateToItemMeta()
|
return new ItemBlock($normalized);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMeta() : int{
|
private function decodeBlockItemState(int $data) : void{
|
||||||
$stateMeta = $this->writeStateToMeta();
|
$reader = new RuntimeDataReader($this->requiredBlockItemStateDataBits, $data);
|
||||||
assert(($stateMeta & ~$this->getStateBitmask()) === 0);
|
|
||||||
return $this->idInfo->getVariant() | $stateMeta;
|
$this->describeBlockItemState($reader);
|
||||||
|
$readBits = $reader->getOffset();
|
||||||
|
if($this->requiredBlockItemStateDataBits !== $readBits){
|
||||||
|
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockItemStateDataBits bits of block-item state data were provided, but $readBits were read");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function writeStateToItemMeta() : int{
|
private function decodeBlockOnlyState(int $data) : void{
|
||||||
return 0;
|
$reader = new RuntimeDataReader($this->requiredBlockOnlyStateDataBits, $data);
|
||||||
|
|
||||||
|
$this->describeBlockOnlyState($reader);
|
||||||
|
$readBits = $reader->getOffset();
|
||||||
|
if($this->requiredBlockOnlyStateDataBits !== $readBits){
|
||||||
|
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockOnlyStateDataBits bits of block-only state data were provided, but $readBits were read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function decodeFullState(int $data) : void{
|
||||||
|
$reader = new RuntimeDataReader($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits, $data);
|
||||||
|
$this->decodeBlockItemState($reader->readInt($this->requiredBlockItemStateDataBits));
|
||||||
|
$this->decodeBlockOnlyState($reader->readInt($this->requiredBlockOnlyStateDataBits));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function encodeBlockItemState() : int{
|
||||||
|
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits);
|
||||||
|
|
||||||
|
$this->describeBlockItemState($writer);
|
||||||
|
$writtenBits = $writer->getOffset();
|
||||||
|
if($this->requiredBlockItemStateDataBits !== $writtenBits){
|
||||||
|
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockItemStateDataBits bits of block-item state data were expected, but $writtenBits were written");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $writer->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function encodeBlockOnlyState() : int{
|
||||||
|
$writer = new RuntimeDataWriter($this->requiredBlockOnlyStateDataBits);
|
||||||
|
|
||||||
|
$this->describeBlockOnlyState($writer);
|
||||||
|
$writtenBits = $writer->getOffset();
|
||||||
|
if($this->requiredBlockOnlyStateDataBits !== $writtenBits){
|
||||||
|
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockOnlyStateDataBits bits of block-only state data were expected, but $writtenBits were written");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $writer->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function encodeFullState() : int{
|
||||||
|
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits);
|
||||||
|
$writer->writeInt($this->requiredBlockItemStateDataBits, $this->encodeBlockItemState());
|
||||||
|
$writer->writeInt($this->requiredBlockOnlyStateDataBits, $this->encodeBlockOnlyState());
|
||||||
|
|
||||||
|
return $writer->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a bitmask used to extract state bits from block metadata.
|
* Describes properties of this block which apply to both the block and item form of the block.
|
||||||
|
* Examples of suitable properties include colour, skull type, and any other information which **IS** kept when the
|
||||||
|
* block is mined or block-picked.
|
||||||
|
*
|
||||||
|
* The method implementation must NOT use conditional logic to determine which properties are written. It must
|
||||||
|
* always write the same properties in the same order, regardless of the current state of the block.
|
||||||
*/
|
*/
|
||||||
public function getStateBitmask() : int{
|
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws InvalidBlockStateException
|
|
||||||
*/
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
|
||||||
//NOOP
|
//NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes properties of this block which apply only to the block form of the block.
|
||||||
|
* Examples of suitable properties include facing, open/closed, powered/unpowered, on/off, and any other information
|
||||||
|
* which **IS NOT** kept when the block is mined or block-picked.
|
||||||
|
*
|
||||||
|
* The method implementation must NOT use conditional logic to determine which properties are written. It must
|
||||||
|
* always write the same properties in the same order, regardless of the current state of the block.
|
||||||
|
*/
|
||||||
|
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||||
|
//NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates copies of this Block in all possible state permutations.
|
||||||
|
* Every possible combination of known properties (e.g. facing, open/closed, powered/unpowered, on/off) will be
|
||||||
|
* generated.
|
||||||
|
*
|
||||||
|
* @phpstan-return \Generator<int, Block, void, void>
|
||||||
|
*/
|
||||||
|
public function generateStatePermutations() : \Generator{
|
||||||
|
//TODO: this bruteforce approach to discovering all valid states is very inefficient for larger state data sizes
|
||||||
|
//at some point we'll need to find a better way to do this
|
||||||
|
$bits = $this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits;
|
||||||
|
if($bits > Block::INTERNAL_STATE_DATA_BITS){
|
||||||
|
throw new \LogicException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits");
|
||||||
|
}
|
||||||
|
for($stateData = 0; $stateData < (1 << $bits); ++$stateData){
|
||||||
|
$v = clone $this;
|
||||||
|
try{
|
||||||
|
$v->decodeFullState($stateData);
|
||||||
|
if($v->encodeFullState() !== $stateData){
|
||||||
|
throw new \LogicException(static::class . "::decodeStateData() accepts invalid state data (returned " . $v->encodeFullState() . " for input $stateData)");
|
||||||
|
}
|
||||||
|
}catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when this block is created, set, or has a neighbouring block update, to re-detect dynamic properties which
|
* Called when this block is created, set, or has a neighbouring block update, to re-detect dynamic properties which
|
||||||
* are not saved on the world.
|
* are not saved on the world.
|
||||||
*
|
*
|
||||||
* Clears any cached precomputed objects, such as bounding boxes. Remove any outdated precomputed things such as
|
* Clears any cached precomputed objects, such as bounding boxes. Remove any outdated precomputed things such as
|
||||||
* AABBs and force recalculation.
|
* AABBs and force recalculation.
|
||||||
|
*
|
||||||
|
* A replacement block may be returned. This is useful if the block type changed due to reading of world data (e.g.
|
||||||
|
* data from a block entity).
|
||||||
*/
|
*/
|
||||||
public function readStateFromWorld() : void{
|
public function readStateFromWorld() : Block{
|
||||||
$this->collisionBoxes = null;
|
$this->collisionBoxes = null;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes information about the block into the world. This writes the blockstate ID into the chunk, and creates
|
||||||
|
* and/or removes tiles as necessary.
|
||||||
|
*
|
||||||
|
* Note: Do not call this directly. Pass the block to {@link World::setBlock()} instead.
|
||||||
|
*/
|
||||||
public function writeStateToWorld() : void{
|
public function writeStateToWorld() : void{
|
||||||
$this->position->getWorld()->getOrLoadChunkAtPosition($this->position)->setFullBlock($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getFullId());
|
$world = $this->position->getWorld();
|
||||||
|
$chunk = $world->getOrLoadChunkAtPosition($this->position);
|
||||||
|
if($chunk === null){
|
||||||
|
throw new AssumptionFailedError("World::setBlock() should have loaded the chunk before calling this method");
|
||||||
|
}
|
||||||
|
$chunk->setBlockStateId($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getStateId());
|
||||||
|
|
||||||
$tileType = $this->idInfo->getTileClass();
|
$tileType = $this->idInfo->getTileClass();
|
||||||
$oldTile = $this->position->getWorld()->getTile($this->position);
|
$oldTile = $world->getTile($this->position);
|
||||||
if($oldTile !== null){
|
if($oldTile !== null){
|
||||||
if($tileType === null || !($oldTile instanceof $tileType)){
|
if($tileType === null || !($oldTile instanceof $tileType)){
|
||||||
$oldTile->close();
|
$oldTile->close();
|
||||||
$oldTile = null;
|
$oldTile = null;
|
||||||
}elseif($oldTile instanceof Spawnable){
|
}elseif($oldTile instanceof Spawnable){
|
||||||
$oldTile->setDirty(); //destroy old network cache
|
$oldTile->clearSpawnCompoundCache(); //destroy old network cache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($oldTile === null && $tileType !== null){
|
if($oldTile === null && $tileType !== null){
|
||||||
@ -160,36 +345,11 @@ class Block{
|
|||||||
* @var Tile $tile
|
* @var Tile $tile
|
||||||
* @see Tile::__construct()
|
* @see Tile::__construct()
|
||||||
*/
|
*/
|
||||||
$tile = new $tileType($this->position->getWorld(), $this->position->asVector3());
|
$tile = new $tileType($world, $this->position->asVector3());
|
||||||
$this->position->getWorld()->addTile($tile);
|
$world->addTile($tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a type ID that identifies this type of block. This does not include information like facing, colour,
|
|
||||||
* powered/unpowered, etc.
|
|
||||||
*/
|
|
||||||
public function getTypeId() : int{
|
|
||||||
return ($this->idInfo->getBlockId() << Block::INTERNAL_METADATA_BITS) | $this->idInfo->getVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the given block has an equivalent type to this one. This compares the type IDs.
|
|
||||||
*
|
|
||||||
* Note: This ignores additional IDs used to represent additional states. This means that, for example, a lit
|
|
||||||
* furnace and unlit furnace are considered the same type.
|
|
||||||
*/
|
|
||||||
public function isSameType(Block $other) : bool{
|
|
||||||
return $this->getTypeId() === $other->getTypeId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the given block has the same type and properties as this block.
|
|
||||||
*/
|
|
||||||
public function isSameState(Block $other) : bool{
|
|
||||||
return $this->getFullId() === $other->getFullId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AKA: Block->isPlaceable
|
* AKA: Block->isPlaceable
|
||||||
*/
|
*/
|
||||||
@ -197,22 +357,44 @@ class Block{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this block can be replaced by another block placed in the same position.
|
||||||
|
*/
|
||||||
public function canBeReplaced() : bool{
|
public function canBeReplaced() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this block can replace the given block in the given placement conditions.
|
||||||
|
* This is used to allow slabs of the same type to combine into double slabs.
|
||||||
|
*/
|
||||||
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
|
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
|
||||||
return $blockReplace->canBeReplaced();
|
return $blockReplace->canBeReplaced();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
|
* Generates a block transaction to set all blocks affected by placing this block. Usually this is just the block
|
||||||
|
* itself, but may be multiple blocks in some cases (such as doors).
|
||||||
|
*
|
||||||
|
* @param BlockTransaction $tx Blocks to be set should be added to this transaction (do not modify thr world directly)
|
||||||
|
* @param Item $item Item used to place the block
|
||||||
|
* @param Block $blockReplace Block expected to be replaced
|
||||||
|
* @param Block $blockClicked Block that was clicked using the item
|
||||||
|
* @param int $face Face of the clicked block which was clicked
|
||||||
|
* @param Vector3 $clickVector Exact position inside the clicked block where the click occurred, relative to the block's position
|
||||||
|
* @param Player|null $player Player who placed the block, or null if it was not a player
|
||||||
|
*
|
||||||
|
* @return bool whether the placement should go ahead
|
||||||
*/
|
*/
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
$tx->addBlock($blockReplace->position, $this);
|
$tx->addBlock($blockReplace->position, $this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called immediately after the block has been placed in the world. Since placement uses a block transaction, some
|
||||||
|
* things may not be possible until after the transaction has been executed.
|
||||||
|
*/
|
||||||
public function onPostPlace() : void{
|
public function onPostPlace() : void{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -221,17 +403,20 @@ class Block{
|
|||||||
* Returns an object containing information about the destruction requirements of this block.
|
* Returns an object containing information about the destruction requirements of this block.
|
||||||
*/
|
*/
|
||||||
public function getBreakInfo() : BlockBreakInfo{
|
public function getBreakInfo() : BlockBreakInfo{
|
||||||
return $this->breakInfo;
|
return $this->typeInfo->getBreakInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do the actions needed so the block is broken with the Item
|
* Do the actions needed so the block is broken with the Item
|
||||||
|
*
|
||||||
|
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if full)
|
||||||
*/
|
*/
|
||||||
public function onBreak(Item $item, ?Player $player = null) : bool{
|
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
if(($t = $this->position->getWorld()->getTile($this->position)) !== null){
|
$world = $this->position->getWorld();
|
||||||
|
if(($t = $world->getTile($this->position)) !== null){
|
||||||
$t->onBlockDestroyed();
|
$t->onBlockDestroyed();
|
||||||
}
|
}
|
||||||
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
|
$world->setBlock($this->position, VanillaBlocks::AIR());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +436,7 @@ class Block{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when this block is randomly updated due to chunk ticking.
|
* Called when this block is randomly updated due to chunk ticking.
|
||||||
* WARNING: This will not be called if ticksRandomly() does not return true!
|
* WARNING: This will not be called if {@link Block::ticksRandomly()} does not return true!
|
||||||
*/
|
*/
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
|
|
||||||
@ -266,14 +451,15 @@ class Block{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Do actions when interacted by Item. Returns if it has done anything
|
* Do actions when interacted by Item. Returns if it has done anything
|
||||||
|
*
|
||||||
|
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||||
*/
|
*/
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when this block is attacked (left-clicked). This is called when a player left-clicks the block to try and
|
* Called when this block is attacked (left-clicked) by a player attempting to start breaking it in survival.
|
||||||
* start to break it in survival mode.
|
|
||||||
*
|
*
|
||||||
* @return bool if an action took place, prevents starting to break the block if true.
|
* @return bool if an action took place, prevents starting to break the block if true.
|
||||||
*/
|
*/
|
||||||
@ -281,11 +467,19 @@ class Block{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a multiplier applied to the velocity of entities moving on top of this block. A higher value will make
|
||||||
|
* the block more slippery (like ice).
|
||||||
|
*
|
||||||
|
* @return float 0.0-1.0
|
||||||
|
*/
|
||||||
public function getFrictionFactor() : float{
|
public function getFrictionFactor() : float{
|
||||||
return 0.6;
|
return 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the amount of light emitted by this block.
|
||||||
|
*
|
||||||
* @return int 0-15
|
* @return int 0-15
|
||||||
*/
|
*/
|
||||||
public function getLightLevel() : int{
|
public function getLightLevel() : int{
|
||||||
@ -328,10 +522,6 @@ class Block{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasEntityCollision() : bool{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether entities can climb up this block.
|
* Returns whether entities can climb up this block.
|
||||||
*/
|
*/
|
||||||
@ -339,10 +529,6 @@ class Block{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addVelocityToEntity(Entity $entity) : ?Vector3{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final public function getPosition() : Position{
|
final public function getPosition() : Position{
|
||||||
return $this->position;
|
return $this->position;
|
||||||
}
|
}
|
||||||
@ -360,7 +546,7 @@ class Block{
|
|||||||
* @return Item[]
|
* @return Item[]
|
||||||
*/
|
*/
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($this->breakInfo->isToolCompatible($item)){
|
if($this->getBreakInfo()->isToolCompatible($item)){
|
||||||
if($this->isAffectedBySilkTouch() && $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
if($this->isAffectedBySilkTouch() && $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
||||||
return $this->getSilkTouchDrops($item);
|
return $this->getSilkTouchDrops($item);
|
||||||
}
|
}
|
||||||
@ -402,7 +588,7 @@ class Block{
|
|||||||
* Returns how much XP will be dropped by breaking this block with the given item.
|
* Returns how much XP will be dropped by breaking this block with the given item.
|
||||||
*/
|
*/
|
||||||
public function getXpDropForTool(Item $item) : int{
|
public function getXpDropForTool(Item $item) : int{
|
||||||
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) || !$this->breakInfo->isToolCompatible($item)){
|
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) || !$this->getBreakInfo()->isToolCompatible($item)){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,6 +611,7 @@ class Block{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the item that players will equip when middle-clicking on this block.
|
* Returns the item that players will equip when middle-clicking on this block.
|
||||||
|
* If addUserData is true, additional data may be added, such as banner patterns, chest contents, etc.
|
||||||
*/
|
*/
|
||||||
public function getPickedItem(bool $addUserData = false) : Item{
|
public function getPickedItem(bool $addUserData = false) : Item{
|
||||||
$item = $this->asItem();
|
$item = $this->asItem();
|
||||||
@ -455,6 +642,10 @@ class Block{
|
|||||||
return 64;
|
return 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isFireProofAsItem() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
||||||
* fire.
|
* fire.
|
||||||
@ -544,11 +735,11 @@ class Block{
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function __toString(){
|
public function __toString(){
|
||||||
return "Block[" . $this->getName() . "] (" . $this->getId() . ":" . $this->getMeta() . ")";
|
return "Block[" . $this->getName() . "] (" . $this->getTypeId() . ":" . $this->encodeFullState() . ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for collision against an AxisAlignedBB
|
* Returns whether any of the block's collision boxes intersect with the given AxisAlignedBB.
|
||||||
*/
|
*/
|
||||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||||
foreach($this->getCollisionBoxes() as $bb2){
|
foreach($this->getCollisionBoxes() as $bb2){
|
||||||
@ -560,10 +751,21 @@ class Block{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the block has actions to be executed when an entity enters its cell (full cube space).
|
||||||
|
*
|
||||||
|
* @see Block::onEntityInside()
|
||||||
|
*/
|
||||||
|
public function hasEntityCollision() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an entity's bounding box clips inside this block's cell. Note that the entity may not be intersecting
|
* Called when an entity's bounding box clips inside this block's cell. Note that the entity may not be intersecting
|
||||||
* with the collision box or bounding box.
|
* with the collision box or bounding box.
|
||||||
*
|
*
|
||||||
|
* WARNING: This will not be called if {@link Block::hasEntityCollision()} returns false.
|
||||||
|
*
|
||||||
* @return bool Whether the block is still the same after the intersection. If it changed (e.g. due to an explosive
|
* @return bool Whether the block is still the same after the intersection. If it changed (e.g. due to an explosive
|
||||||
* being ignited), this should return false.
|
* being ignited), this should return false.
|
||||||
*/
|
*/
|
||||||
@ -571,6 +773,19 @@ class Block{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a direction vector describing which way an entity intersecting this block should be pushed.
|
||||||
|
* This is used by liquids to push entities in liquid currents.
|
||||||
|
*
|
||||||
|
* The returned vector is summed with vectors from every other block the entity is intersecting, and normalized to
|
||||||
|
* produce a final direction vector.
|
||||||
|
*
|
||||||
|
* WARNING: This will not be called if {@link Block::hasEntityCollision()} does not return true!
|
||||||
|
*/
|
||||||
|
public function addVelocityToEntity(Entity $entity) : ?Vector3{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an entity lands on this block (usually due to falling).
|
* Called when an entity lands on this block (usually due to falling).
|
||||||
* @return float|null The new vertical velocity of the entity, or null if unchanged.
|
* @return float|null The new vertical velocity of the entity, or null if unchanged.
|
||||||
@ -580,6 +795,20 @@ class Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Called when a projectile collides with one of this block's collision boxes.
|
||||||
|
*/
|
||||||
|
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
|
||||||
|
//NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of collision bounding boxes for this block.
|
||||||
|
* These are used for:
|
||||||
|
* - entity movement collision checks (to ensure entities can't clip through blocks)
|
||||||
|
* - projectile flight paths
|
||||||
|
* - block placement (to ensure the player can't place blocks inside itself or another entity)
|
||||||
|
* - anti-cheat checks in plugins
|
||||||
|
*
|
||||||
* @return AxisAlignedBB[]
|
* @return AxisAlignedBB[]
|
||||||
*/
|
*/
|
||||||
final public function getCollisionBoxes() : array{
|
final public function getCollisionBoxes() : array{
|
||||||
@ -610,12 +839,24 @@ class Block{
|
|||||||
return [AxisAlignedBB::one()];
|
return [AxisAlignedBB::one()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of support that the block can provide on the given face. This is used to determine whether
|
||||||
|
* blocks placed on the given face can be supported by this block.
|
||||||
|
*/
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::FULL();
|
||||||
|
}
|
||||||
|
|
||||||
public function isFullCube() : bool{
|
public function isFullCube() : bool{
|
||||||
$bb = $this->getCollisionBoxes();
|
$bb = $this->getCollisionBoxes();
|
||||||
|
|
||||||
return count($bb) === 1 && $bb[0]->getAverageEdgeLength() >= 1 && $bb[0]->isCube();
|
return count($bb) === 1 && $bb[0]->getAverageEdgeLength() >= 1 && $bb[0]->isCube();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a ray trace along the line between the two positions using the block's collision boxes.
|
||||||
|
* Returns the intersection point closest to pos1, or null if no intersection occurred.
|
||||||
|
*/
|
||||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||||
$bbs = $this->getCollisionBoxes();
|
$bbs = $this->getCollisionBoxes();
|
||||||
if(count($bbs) === 0){
|
if(count($bbs) === 0){
|
||||||
|
|||||||
@ -17,13 +17,14 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\ToolTier;
|
||||||
use function get_class;
|
use function get_class;
|
||||||
|
|
||||||
class BlockBreakInfo{
|
class BlockBreakInfo{
|
||||||
@ -38,21 +39,36 @@ class BlockBreakInfo{
|
|||||||
*/
|
*/
|
||||||
public const INCOMPATIBLE_TOOL_MULTIPLIER = 5.0;
|
public const INCOMPATIBLE_TOOL_MULTIPLIER = 5.0;
|
||||||
|
|
||||||
private float $hardness;
|
|
||||||
private float $blastResistance;
|
private float $blastResistance;
|
||||||
private int $toolType;
|
|
||||||
private int $toolHarvestLevel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param float|null $blastResistance default 5x hardness
|
* @param float|null $blastResistance default 5x hardness
|
||||||
*/
|
*/
|
||||||
public function __construct(float $hardness, int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0, ?float $blastResistance = null){
|
public function __construct(
|
||||||
$this->hardness = $hardness;
|
private float $hardness,
|
||||||
$this->toolType = $toolType;
|
private int $toolType = BlockToolType::NONE,
|
||||||
$this->toolHarvestLevel = $toolHarvestLevel;
|
private int $toolHarvestLevel = 0,
|
||||||
|
?float $blastResistance = null
|
||||||
|
){
|
||||||
$this->blastResistance = $blastResistance ?? $hardness * 5;
|
$this->blastResistance = $blastResistance ?? $hardness * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function tier(float $hardness, int $toolType, ToolTier $toolTier, ?float $blastResistance = null) : self{
|
||||||
|
return new self($hardness, $toolType, $toolTier->getHarvestLevel(), $blastResistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function pickaxe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
|
||||||
|
return new self($hardness, BlockToolType::PICKAXE, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function shovel(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
|
||||||
|
return new self($hardness, BlockToolType::SHOVEL, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function axe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
|
||||||
|
return new self($hardness, BlockToolType::AXE, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
|
||||||
|
}
|
||||||
|
|
||||||
public static function instant(int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0) : self{
|
public static function instant(int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0) : self{
|
||||||
return new self(0.0, $toolType, $toolHarvestLevel, 0.0);
|
return new self(0.0, $toolType, $toolHarvestLevel, 0.0);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -27,45 +27,22 @@ use pocketmine\block\tile\Tile;
|
|||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
|
|
||||||
class BlockIdentifier{
|
class BlockIdentifier{
|
||||||
|
|
||||||
private int $blockId;
|
|
||||||
private int $variant;
|
|
||||||
private ?int $itemId;
|
|
||||||
/** @phpstan-var class-string<Tile>|null */
|
|
||||||
private ?string $tileClass;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-param class-string<Tile>|null $tileClass
|
* @phpstan-param class-string<Tile>|null $tileClass
|
||||||
*/
|
*/
|
||||||
public function __construct(int $blockId, int $variant, ?int $itemId = null, ?string $tileClass = null){
|
public function __construct(
|
||||||
$this->blockId = $blockId;
|
private int $blockTypeId,
|
||||||
$this->variant = $variant;
|
private ?string $tileClass = null
|
||||||
$this->itemId = $itemId;
|
){
|
||||||
|
if($blockTypeId < 0){
|
||||||
|
throw new \InvalidArgumentException("Block type ID may not be negative");
|
||||||
|
}
|
||||||
if($tileClass !== null){
|
if($tileClass !== null){
|
||||||
Utils::testValidInstance($tileClass, Tile::class);
|
Utils::testValidInstance($tileClass, Tile::class);
|
||||||
}
|
}
|
||||||
$this->tileClass = $tileClass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBlockId() : int{
|
public function getBlockTypeId() : int{ return $this->blockTypeId; }
|
||||||
return $this->blockId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int[]
|
|
||||||
*/
|
|
||||||
public function getAllBlockIds() : array{
|
|
||||||
return [$this->blockId];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVariant() : int{
|
|
||||||
return $this->variant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getItemId() : int{
|
|
||||||
return $this->itemId ?? ($this->blockId > 255 ? 255 - $this->blockId : $this->blockId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-return class-string<Tile>|null
|
* @phpstan-return class-string<Tile>|null
|
||||||
|
|||||||
@ -1,59 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ____ _ _ __ __ _ __ __ ____
|
|
||||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
||||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
||||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
||||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* @author PocketMine Team
|
|
||||||
* @link http://www.pocketmine.net/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace pocketmine\block;
|
|
||||||
|
|
||||||
use function count;
|
|
||||||
|
|
||||||
class BlockIdentifierFlattened extends BlockIdentifier{
|
|
||||||
|
|
||||||
/** @var int[] */
|
|
||||||
private array $additionalIds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int[] $additionalIds
|
|
||||||
*/
|
|
||||||
public function __construct(int $blockId, array $additionalIds, int $variant, ?int $itemId = null, ?string $tileClass = null){
|
|
||||||
if(count($additionalIds) === 0){
|
|
||||||
throw new \InvalidArgumentException("Expected at least 1 additional ID");
|
|
||||||
}
|
|
||||||
parent::__construct($blockId, $variant, $itemId, $tileClass);
|
|
||||||
|
|
||||||
$this->additionalIds = $additionalIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAdditionalId(int $index) : int{
|
|
||||||
if(!isset($this->additionalIds[$index])){
|
|
||||||
throw new \InvalidArgumentException("No such ID at index $index");
|
|
||||||
}
|
|
||||||
return $this->additionalIds[$index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSecondId() : int{
|
|
||||||
return $this->getAdditionalId(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAllBlockIds() : array{
|
|
||||||
return [$this->getBlockId(), ...$this->additionalIds];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,248 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ____ _ _ __ __ _ __ __ ____
|
|
||||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
||||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
||||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
||||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* @author PocketMine Team
|
|
||||||
* @link http://www.pocketmine.net/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace pocketmine\block;
|
|
||||||
|
|
||||||
use pocketmine\block\BlockIdentifier as BID;
|
|
||||||
use pocketmine\block\BlockLegacyIds as Ids;
|
|
||||||
use pocketmine\block\tile\Sign as TileSign;
|
|
||||||
use pocketmine\block\utils\DyeColor;
|
|
||||||
use pocketmine\block\utils\TreeType;
|
|
||||||
use pocketmine\item\ItemIds;
|
|
||||||
use pocketmine\utils\AssumptionFailedError;
|
|
||||||
|
|
||||||
final class BlockLegacyIdHelper{
|
|
||||||
|
|
||||||
public static function getWoodenFloorSignIdentifier(TreeType $treeType) : BID{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BID(Ids::SIGN_POST, 0, ItemIds::SIGN, TileSign::class);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BID(Ids::SPRUCE_STANDING_SIGN, 0, ItemIds::SPRUCE_SIGN, TileSign::class);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BID(Ids::BIRCH_STANDING_SIGN, 0, ItemIds::BIRCH_SIGN, TileSign::class);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BID(Ids::JUNGLE_STANDING_SIGN, 0, ItemIds::JUNGLE_SIGN, TileSign::class);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BID(Ids::ACACIA_STANDING_SIGN,0, ItemIds::ACACIA_SIGN, TileSign::class);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BID(Ids::DARKOAK_STANDING_SIGN, 0, ItemIds::DARKOAK_SIGN, TileSign::class);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getWoodenWallSignIdentifier(TreeType $treeType) : BID{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BID(Ids::WALL_SIGN, 0, ItemIds::SIGN, TileSign::class);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BID(Ids::SPRUCE_WALL_SIGN, 0, ItemIds::SPRUCE_SIGN, TileSign::class);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BID(Ids::BIRCH_WALL_SIGN, 0, ItemIds::BIRCH_SIGN, TileSign::class);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BID(Ids::JUNGLE_WALL_SIGN, 0, ItemIds::JUNGLE_SIGN, TileSign::class);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BID(Ids::ACACIA_WALL_SIGN, 0, ItemIds::ACACIA_SIGN, TileSign::class);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BID(Ids::DARKOAK_WALL_SIGN, 0, ItemIds::DARKOAK_SIGN, TileSign::class);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getWoodenTrapdoorIdentifier(TreeType $treeType) : BlockIdentifier{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::WOODEN_TRAPDOOR, 0);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BlockIdentifier(Ids::SPRUCE_TRAPDOOR, 0);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BlockIdentifier(Ids::BIRCH_TRAPDOOR, 0);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BlockIdentifier(Ids::JUNGLE_TRAPDOOR, 0);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BlockIdentifier(Ids::ACACIA_TRAPDOOR, 0);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::DARK_OAK_TRAPDOOR, 0);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getWoodenButtonIdentifier(TreeType $treeType) : BlockIdentifier{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::WOODEN_BUTTON, 0);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BlockIdentifier(Ids::SPRUCE_BUTTON, 0);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BlockIdentifier(Ids::BIRCH_BUTTON, 0);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BlockIdentifier(Ids::JUNGLE_BUTTON, 0);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BlockIdentifier(Ids::ACACIA_BUTTON, 0);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::DARK_OAK_BUTTON, 0);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getWoodenPressurePlateIdentifier(TreeType $treeType) : BlockIdentifier{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::WOODEN_PRESSURE_PLATE, 0);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BlockIdentifier(Ids::SPRUCE_PRESSURE_PLATE, 0);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BlockIdentifier(Ids::BIRCH_PRESSURE_PLATE, 0);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BlockIdentifier(Ids::JUNGLE_PRESSURE_PLATE, 0);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BlockIdentifier(Ids::ACACIA_PRESSURE_PLATE, 0);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::DARK_OAK_PRESSURE_PLATE, 0);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getWoodenDoorIdentifier(TreeType $treeType) : BlockIdentifier{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BID(Ids::OAK_DOOR_BLOCK, 0, ItemIds::OAK_DOOR);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BID(Ids::SPRUCE_DOOR_BLOCK, 0, ItemIds::SPRUCE_DOOR);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BID(Ids::BIRCH_DOOR_BLOCK, 0, ItemIds::BIRCH_DOOR);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BID(Ids::JUNGLE_DOOR_BLOCK, 0, ItemIds::JUNGLE_DOOR);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BID(Ids::ACACIA_DOOR_BLOCK, 0, ItemIds::ACACIA_DOOR);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BID(Ids::DARK_OAK_DOOR_BLOCK, 0, ItemIds::DARK_OAK_DOOR);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getWoodenFenceIdentifier(TreeType $treeType) : BlockIdentifier{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::OAK_FENCE_GATE, 0);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BlockIdentifier(Ids::SPRUCE_FENCE_GATE, 0);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BlockIdentifier(Ids::BIRCH_FENCE_GATE, 0);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BlockIdentifier(Ids::JUNGLE_FENCE_GATE, 0);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BlockIdentifier(Ids::ACACIA_FENCE_GATE, 0);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::DARK_OAK_FENCE_GATE, 0);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getWoodenStairsIdentifier(TreeType $treeType) : BlockIdentifier{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::OAK_STAIRS, 0);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BlockIdentifier(Ids::SPRUCE_STAIRS, 0);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BlockIdentifier(Ids::BIRCH_STAIRS, 0);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BlockIdentifier(Ids::JUNGLE_STAIRS, 0);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BlockIdentifier(Ids::ACACIA_STAIRS, 0);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::DARK_OAK_STAIRS, 0);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getStrippedLogIdentifier(TreeType $treeType) : BlockIdentifier{
|
|
||||||
switch($treeType->id()){
|
|
||||||
case TreeType::OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::STRIPPED_OAK_LOG, 0);
|
|
||||||
case TreeType::SPRUCE()->id():
|
|
||||||
return new BlockIdentifier(Ids::STRIPPED_SPRUCE_LOG, 0);
|
|
||||||
case TreeType::BIRCH()->id():
|
|
||||||
return new BlockIdentifier(Ids::STRIPPED_BIRCH_LOG, 0);
|
|
||||||
case TreeType::JUNGLE()->id():
|
|
||||||
return new BlockIdentifier(Ids::STRIPPED_JUNGLE_LOG, 0);
|
|
||||||
case TreeType::ACACIA()->id():
|
|
||||||
return new BlockIdentifier(Ids::STRIPPED_ACACIA_LOG, 0);
|
|
||||||
case TreeType::DARK_OAK()->id():
|
|
||||||
return new BlockIdentifier(Ids::STRIPPED_DARK_OAK_LOG, 0);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all wood types");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getGlazedTerracottaIdentifier(DyeColor $color) : BlockIdentifier{
|
|
||||||
switch($color->id()){
|
|
||||||
case DyeColor::WHITE()->id():
|
|
||||||
return new BlockIdentifier(Ids::WHITE_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::ORANGE()->id():
|
|
||||||
return new BlockIdentifier(Ids::ORANGE_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::MAGENTA()->id():
|
|
||||||
return new BlockIdentifier(Ids::MAGENTA_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::LIGHT_BLUE()->id():
|
|
||||||
return new BlockIdentifier(Ids::LIGHT_BLUE_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::YELLOW()->id():
|
|
||||||
return new BlockIdentifier(Ids::YELLOW_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::LIME()->id():
|
|
||||||
return new BlockIdentifier(Ids::LIME_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::PINK()->id():
|
|
||||||
return new BlockIdentifier(Ids::PINK_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::GRAY()->id():
|
|
||||||
return new BlockIdentifier(Ids::GRAY_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::LIGHT_GRAY()->id():
|
|
||||||
return new BlockIdentifier(Ids::SILVER_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::CYAN()->id():
|
|
||||||
return new BlockIdentifier(Ids::CYAN_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::PURPLE()->id():
|
|
||||||
return new BlockIdentifier(Ids::PURPLE_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::BLUE()->id():
|
|
||||||
return new BlockIdentifier(Ids::BLUE_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::BROWN()->id():
|
|
||||||
return new BlockIdentifier(Ids::BROWN_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::GREEN()->id():
|
|
||||||
return new BlockIdentifier(Ids::GREEN_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::RED()->id():
|
|
||||||
return new BlockIdentifier(Ids::RED_GLAZED_TERRACOTTA, 0);
|
|
||||||
case DyeColor::BLACK()->id():
|
|
||||||
return new BlockIdentifier(Ids::BLACK_GLAZED_TERRACOTTA, 0);
|
|
||||||
}
|
|
||||||
throw new AssumptionFailedError("Switch should cover all colours");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getStoneSlabIdentifier(int $stoneSlabId, int $meta) : BlockIdentifierFlattened{
|
|
||||||
$id = [
|
|
||||||
1 => [Ids::STONE_SLAB, Ids::DOUBLE_STONE_SLAB],
|
|
||||||
2 => [Ids::STONE_SLAB2, Ids::DOUBLE_STONE_SLAB2],
|
|
||||||
3 => [Ids::STONE_SLAB3, Ids::DOUBLE_STONE_SLAB3],
|
|
||||||
4 => [Ids::STONE_SLAB4, Ids::DOUBLE_STONE_SLAB4]
|
|
||||||
][$stoneSlabId] ?? null;
|
|
||||||
if($id === null){
|
|
||||||
throw new \InvalidArgumentException("Stone slab type should be 1, 2, 3 or 4");
|
|
||||||
}
|
|
||||||
return new BlockIdentifierFlattened($id[0], [$id[1]], $meta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,501 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ____ _ _ __ __ _ __ __ ____
|
|
||||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
||||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
||||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
||||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* @author PocketMine Team
|
|
||||||
* @link http://www.pocketmine.net/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace pocketmine\block;
|
|
||||||
|
|
||||||
final class BlockLegacyIds{
|
|
||||||
|
|
||||||
private function __construct(){
|
|
||||||
//NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
public const AIR = 0;
|
|
||||||
public const STONE = 1;
|
|
||||||
public const GRASS = 2;
|
|
||||||
public const DIRT = 3;
|
|
||||||
public const COBBLESTONE = 4;
|
|
||||||
public const PLANKS = 5, WOODEN_PLANKS = 5;
|
|
||||||
public const SAPLING = 6;
|
|
||||||
public const BEDROCK = 7;
|
|
||||||
public const FLOWING_WATER = 8;
|
|
||||||
public const STILL_WATER = 9, WATER = 9;
|
|
||||||
public const FLOWING_LAVA = 10;
|
|
||||||
public const LAVA = 11, STILL_LAVA = 11;
|
|
||||||
public const SAND = 12;
|
|
||||||
public const GRAVEL = 13;
|
|
||||||
public const GOLD_ORE = 14;
|
|
||||||
public const IRON_ORE = 15;
|
|
||||||
public const COAL_ORE = 16;
|
|
||||||
public const LOG = 17;
|
|
||||||
public const LEAVES = 18;
|
|
||||||
public const SPONGE = 19;
|
|
||||||
public const GLASS = 20;
|
|
||||||
public const LAPIS_ORE = 21;
|
|
||||||
public const LAPIS_BLOCK = 22;
|
|
||||||
public const DISPENSER = 23;
|
|
||||||
public const SANDSTONE = 24;
|
|
||||||
public const NOTEBLOCK = 25, NOTE_BLOCK = 25;
|
|
||||||
public const BED_BLOCK = 26;
|
|
||||||
public const GOLDEN_RAIL = 27, POWERED_RAIL = 27;
|
|
||||||
public const DETECTOR_RAIL = 28;
|
|
||||||
public const STICKY_PISTON = 29;
|
|
||||||
public const COBWEB = 30, WEB = 30;
|
|
||||||
public const TALLGRASS = 31, TALL_GRASS = 31;
|
|
||||||
public const DEADBUSH = 32, DEAD_BUSH = 32;
|
|
||||||
public const PISTON = 33;
|
|
||||||
public const PISTONARMCOLLISION = 34, PISTON_ARM_COLLISION = 34;
|
|
||||||
public const WOOL = 35;
|
|
||||||
public const ELEMENT_0 = 36;
|
|
||||||
public const DANDELION = 37, YELLOW_FLOWER = 37;
|
|
||||||
public const POPPY = 38, RED_FLOWER = 38;
|
|
||||||
public const BROWN_MUSHROOM = 39;
|
|
||||||
public const RED_MUSHROOM = 40;
|
|
||||||
public const GOLD_BLOCK = 41;
|
|
||||||
public const IRON_BLOCK = 42;
|
|
||||||
public const DOUBLE_STONE_SLAB = 43;
|
|
||||||
public const STONE_SLAB = 44;
|
|
||||||
public const BRICK_BLOCK = 45;
|
|
||||||
public const TNT = 46;
|
|
||||||
public const BOOKSHELF = 47;
|
|
||||||
public const MOSSY_COBBLESTONE = 48, MOSS_STONE = 48;
|
|
||||||
public const OBSIDIAN = 49;
|
|
||||||
public const TORCH = 50;
|
|
||||||
public const FIRE = 51;
|
|
||||||
public const MOB_SPAWNER = 52, MONSTER_SPAWNER = 52;
|
|
||||||
public const OAK_STAIRS = 53, WOODEN_STAIRS = 53;
|
|
||||||
public const CHEST = 54;
|
|
||||||
public const REDSTONE_WIRE = 55;
|
|
||||||
public const DIAMOND_ORE = 56;
|
|
||||||
public const DIAMOND_BLOCK = 57;
|
|
||||||
public const CRAFTING_TABLE = 58, WORKBENCH = 58;
|
|
||||||
public const WHEAT_BLOCK = 59;
|
|
||||||
public const FARMLAND = 60;
|
|
||||||
public const FURNACE = 61;
|
|
||||||
public const BURNING_FURNACE = 62, LIT_FURNACE = 62;
|
|
||||||
public const SIGN_POST = 63, STANDING_SIGN = 63;
|
|
||||||
public const OAK_DOOR_BLOCK = 64, WOODEN_DOOR_BLOCK = 64;
|
|
||||||
public const LADDER = 65;
|
|
||||||
public const RAIL = 66;
|
|
||||||
public const COBBLESTONE_STAIRS = 67, STONE_STAIRS = 67;
|
|
||||||
public const WALL_SIGN = 68;
|
|
||||||
public const LEVER = 69;
|
|
||||||
public const STONE_PRESSURE_PLATE = 70;
|
|
||||||
public const IRON_DOOR_BLOCK = 71;
|
|
||||||
public const WOODEN_PRESSURE_PLATE = 72;
|
|
||||||
public const REDSTONE_ORE = 73;
|
|
||||||
public const GLOWING_REDSTONE_ORE = 74, LIT_REDSTONE_ORE = 74;
|
|
||||||
public const UNLIT_REDSTONE_TORCH = 75;
|
|
||||||
public const LIT_REDSTONE_TORCH = 76, REDSTONE_TORCH = 76;
|
|
||||||
public const STONE_BUTTON = 77;
|
|
||||||
public const SNOW_LAYER = 78;
|
|
||||||
public const ICE = 79;
|
|
||||||
public const SNOW = 80, SNOW_BLOCK = 80;
|
|
||||||
public const CACTUS = 81;
|
|
||||||
public const CLAY_BLOCK = 82;
|
|
||||||
public const REEDS_BLOCK = 83, SUGARCANE_BLOCK = 83;
|
|
||||||
public const JUKEBOX = 84;
|
|
||||||
public const FENCE = 85;
|
|
||||||
public const PUMPKIN = 86;
|
|
||||||
public const NETHERRACK = 87;
|
|
||||||
public const SOUL_SAND = 88;
|
|
||||||
public const GLOWSTONE = 89;
|
|
||||||
public const PORTAL = 90;
|
|
||||||
public const JACK_O_LANTERN = 91, LIT_PUMPKIN = 91;
|
|
||||||
public const CAKE_BLOCK = 92;
|
|
||||||
public const REPEATER_BLOCK = 93, UNPOWERED_REPEATER = 93;
|
|
||||||
public const POWERED_REPEATER = 94;
|
|
||||||
public const INVISIBLEBEDROCK = 95, INVISIBLE_BEDROCK = 95;
|
|
||||||
public const TRAPDOOR = 96, WOODEN_TRAPDOOR = 96;
|
|
||||||
public const MONSTER_EGG = 97;
|
|
||||||
public const STONEBRICK = 98, STONE_BRICK = 98, STONE_BRICKS = 98;
|
|
||||||
public const BROWN_MUSHROOM_BLOCK = 99;
|
|
||||||
public const RED_MUSHROOM_BLOCK = 100;
|
|
||||||
public const IRON_BARS = 101;
|
|
||||||
public const GLASS_PANE = 102;
|
|
||||||
public const MELON_BLOCK = 103;
|
|
||||||
public const PUMPKIN_STEM = 104;
|
|
||||||
public const MELON_STEM = 105;
|
|
||||||
public const VINE = 106, VINES = 106;
|
|
||||||
public const FENCE_GATE = 107, OAK_FENCE_GATE = 107;
|
|
||||||
public const BRICK_STAIRS = 108;
|
|
||||||
public const STONE_BRICK_STAIRS = 109;
|
|
||||||
public const MYCELIUM = 110;
|
|
||||||
public const LILY_PAD = 111, WATERLILY = 111, WATER_LILY = 111;
|
|
||||||
public const NETHER_BRICK_BLOCK = 112;
|
|
||||||
public const NETHER_BRICK_FENCE = 113;
|
|
||||||
public const NETHER_BRICK_STAIRS = 114;
|
|
||||||
public const NETHER_WART_PLANT = 115;
|
|
||||||
public const ENCHANTING_TABLE = 116, ENCHANTMENT_TABLE = 116;
|
|
||||||
public const BREWING_STAND_BLOCK = 117;
|
|
||||||
public const CAULDRON_BLOCK = 118;
|
|
||||||
public const END_PORTAL = 119;
|
|
||||||
public const END_PORTAL_FRAME = 120;
|
|
||||||
public const END_STONE = 121;
|
|
||||||
public const DRAGON_EGG = 122;
|
|
||||||
public const REDSTONE_LAMP = 123;
|
|
||||||
public const LIT_REDSTONE_LAMP = 124;
|
|
||||||
public const DROPPER = 125;
|
|
||||||
public const ACTIVATOR_RAIL = 126;
|
|
||||||
public const COCOA = 127, COCOA_BLOCK = 127;
|
|
||||||
public const SANDSTONE_STAIRS = 128;
|
|
||||||
public const EMERALD_ORE = 129;
|
|
||||||
public const ENDER_CHEST = 130;
|
|
||||||
public const TRIPWIRE_HOOK = 131;
|
|
||||||
public const TRIPWIRE = 132, TRIP_WIRE = 132;
|
|
||||||
public const EMERALD_BLOCK = 133;
|
|
||||||
public const SPRUCE_STAIRS = 134;
|
|
||||||
public const BIRCH_STAIRS = 135;
|
|
||||||
public const JUNGLE_STAIRS = 136;
|
|
||||||
public const COMMAND_BLOCK = 137;
|
|
||||||
public const BEACON = 138;
|
|
||||||
public const COBBLESTONE_WALL = 139, STONE_WALL = 139;
|
|
||||||
public const FLOWER_POT_BLOCK = 140;
|
|
||||||
public const CARROTS = 141, CARROT_BLOCK = 141;
|
|
||||||
public const POTATOES = 142, POTATO_BLOCK = 142;
|
|
||||||
public const WOODEN_BUTTON = 143;
|
|
||||||
public const MOB_HEAD_BLOCK = 144, SKULL_BLOCK = 144;
|
|
||||||
public const ANVIL = 145;
|
|
||||||
public const TRAPPED_CHEST = 146;
|
|
||||||
public const LIGHT_WEIGHTED_PRESSURE_PLATE = 147;
|
|
||||||
public const HEAVY_WEIGHTED_PRESSURE_PLATE = 148;
|
|
||||||
public const COMPARATOR_BLOCK = 149, UNPOWERED_COMPARATOR = 149;
|
|
||||||
public const POWERED_COMPARATOR = 150;
|
|
||||||
public const DAYLIGHT_DETECTOR = 151, DAYLIGHT_SENSOR = 151;
|
|
||||||
public const REDSTONE_BLOCK = 152;
|
|
||||||
public const NETHER_QUARTZ_ORE = 153, QUARTZ_ORE = 153;
|
|
||||||
public const HOPPER_BLOCK = 154;
|
|
||||||
public const QUARTZ_BLOCK = 155;
|
|
||||||
public const QUARTZ_STAIRS = 156;
|
|
||||||
public const DOUBLE_WOODEN_SLAB = 157;
|
|
||||||
public const WOODEN_SLAB = 158;
|
|
||||||
public const STAINED_CLAY = 159, STAINED_HARDENED_CLAY = 159, TERRACOTTA = 159;
|
|
||||||
public const STAINED_GLASS_PANE = 160;
|
|
||||||
public const LEAVES2 = 161;
|
|
||||||
public const LOG2 = 162;
|
|
||||||
public const ACACIA_STAIRS = 163;
|
|
||||||
public const DARK_OAK_STAIRS = 164;
|
|
||||||
public const SLIME = 165, SLIME_BLOCK = 165;
|
|
||||||
public const GLOW_STICK = 166;
|
|
||||||
public const IRON_TRAPDOOR = 167;
|
|
||||||
public const PRISMARINE = 168;
|
|
||||||
public const SEALANTERN = 169, SEA_LANTERN = 169;
|
|
||||||
public const HAY_BALE = 170, HAY_BLOCK = 170;
|
|
||||||
public const CARPET = 171;
|
|
||||||
public const HARDENED_CLAY = 172;
|
|
||||||
public const COAL_BLOCK = 173;
|
|
||||||
public const PACKED_ICE = 174;
|
|
||||||
public const DOUBLE_PLANT = 175;
|
|
||||||
public const STANDING_BANNER = 176;
|
|
||||||
public const WALL_BANNER = 177;
|
|
||||||
public const DAYLIGHT_DETECTOR_INVERTED = 178, DAYLIGHT_SENSOR_INVERTED = 178;
|
|
||||||
public const RED_SANDSTONE = 179;
|
|
||||||
public const RED_SANDSTONE_STAIRS = 180;
|
|
||||||
public const DOUBLE_STONE_SLAB2 = 181;
|
|
||||||
public const STONE_SLAB2 = 182;
|
|
||||||
public const SPRUCE_FENCE_GATE = 183;
|
|
||||||
public const BIRCH_FENCE_GATE = 184;
|
|
||||||
public const JUNGLE_FENCE_GATE = 185;
|
|
||||||
public const DARK_OAK_FENCE_GATE = 186;
|
|
||||||
public const ACACIA_FENCE_GATE = 187;
|
|
||||||
public const REPEATING_COMMAND_BLOCK = 188;
|
|
||||||
public const CHAIN_COMMAND_BLOCK = 189;
|
|
||||||
public const HARD_GLASS_PANE = 190;
|
|
||||||
public const HARD_STAINED_GLASS_PANE = 191;
|
|
||||||
public const CHEMICAL_HEAT = 192;
|
|
||||||
public const SPRUCE_DOOR_BLOCK = 193;
|
|
||||||
public const BIRCH_DOOR_BLOCK = 194;
|
|
||||||
public const JUNGLE_DOOR_BLOCK = 195;
|
|
||||||
public const ACACIA_DOOR_BLOCK = 196;
|
|
||||||
public const DARK_OAK_DOOR_BLOCK = 197;
|
|
||||||
public const GRASS_PATH = 198;
|
|
||||||
public const FRAME_BLOCK = 199, ITEM_FRAME_BLOCK = 199;
|
|
||||||
public const CHORUS_FLOWER = 200;
|
|
||||||
public const PURPUR_BLOCK = 201;
|
|
||||||
public const COLORED_TORCH_RG = 202;
|
|
||||||
public const PURPUR_STAIRS = 203;
|
|
||||||
public const COLORED_TORCH_BP = 204;
|
|
||||||
public const UNDYED_SHULKER_BOX = 205;
|
|
||||||
public const END_BRICKS = 206;
|
|
||||||
public const FROSTED_ICE = 207;
|
|
||||||
public const END_ROD = 208;
|
|
||||||
public const END_GATEWAY = 209;
|
|
||||||
|
|
||||||
public const MAGMA = 213;
|
|
||||||
public const NETHER_WART_BLOCK = 214;
|
|
||||||
public const RED_NETHER_BRICK = 215;
|
|
||||||
public const BONE_BLOCK = 216;
|
|
||||||
|
|
||||||
public const SHULKER_BOX = 218;
|
|
||||||
public const PURPLE_GLAZED_TERRACOTTA = 219;
|
|
||||||
public const WHITE_GLAZED_TERRACOTTA = 220;
|
|
||||||
public const ORANGE_GLAZED_TERRACOTTA = 221;
|
|
||||||
public const MAGENTA_GLAZED_TERRACOTTA = 222;
|
|
||||||
public const LIGHT_BLUE_GLAZED_TERRACOTTA = 223;
|
|
||||||
public const YELLOW_GLAZED_TERRACOTTA = 224;
|
|
||||||
public const LIME_GLAZED_TERRACOTTA = 225;
|
|
||||||
public const PINK_GLAZED_TERRACOTTA = 226;
|
|
||||||
public const GRAY_GLAZED_TERRACOTTA = 227;
|
|
||||||
public const SILVER_GLAZED_TERRACOTTA = 228;
|
|
||||||
public const CYAN_GLAZED_TERRACOTTA = 229;
|
|
||||||
|
|
||||||
public const BLUE_GLAZED_TERRACOTTA = 231;
|
|
||||||
public const BROWN_GLAZED_TERRACOTTA = 232;
|
|
||||||
public const GREEN_GLAZED_TERRACOTTA = 233;
|
|
||||||
public const RED_GLAZED_TERRACOTTA = 234;
|
|
||||||
public const BLACK_GLAZED_TERRACOTTA = 235;
|
|
||||||
public const CONCRETE = 236;
|
|
||||||
public const CONCRETEPOWDER = 237, CONCRETE_POWDER = 237;
|
|
||||||
public const CHEMISTRY_TABLE = 238;
|
|
||||||
public const UNDERWATER_TORCH = 239;
|
|
||||||
public const CHORUS_PLANT = 240;
|
|
||||||
public const STAINED_GLASS = 241;
|
|
||||||
|
|
||||||
public const PODZOL = 243;
|
|
||||||
public const BEETROOT_BLOCK = 244;
|
|
||||||
public const STONECUTTER = 245;
|
|
||||||
public const GLOWINGOBSIDIAN = 246, GLOWING_OBSIDIAN = 246;
|
|
||||||
public const NETHERREACTOR = 247, NETHER_REACTOR = 247;
|
|
||||||
public const INFO_UPDATE = 248;
|
|
||||||
public const INFO_UPDATE2 = 249;
|
|
||||||
public const MOVINGBLOCK = 250, MOVING_BLOCK = 250;
|
|
||||||
public const OBSERVER = 251;
|
|
||||||
public const STRUCTURE_BLOCK = 252;
|
|
||||||
public const HARD_GLASS = 253;
|
|
||||||
public const HARD_STAINED_GLASS = 254;
|
|
||||||
public const RESERVED6 = 255;
|
|
||||||
|
|
||||||
public const PRISMARINE_STAIRS = 257;
|
|
||||||
public const DARK_PRISMARINE_STAIRS = 258;
|
|
||||||
public const PRISMARINE_BRICKS_STAIRS = 259;
|
|
||||||
public const STRIPPED_SPRUCE_LOG = 260;
|
|
||||||
public const STRIPPED_BIRCH_LOG = 261;
|
|
||||||
public const STRIPPED_JUNGLE_LOG = 262;
|
|
||||||
public const STRIPPED_ACACIA_LOG = 263;
|
|
||||||
public const STRIPPED_DARK_OAK_LOG = 264;
|
|
||||||
public const STRIPPED_OAK_LOG = 265;
|
|
||||||
public const BLUE_ICE = 266;
|
|
||||||
public const ELEMENT_1 = 267;
|
|
||||||
public const ELEMENT_2 = 268;
|
|
||||||
public const ELEMENT_3 = 269;
|
|
||||||
public const ELEMENT_4 = 270;
|
|
||||||
public const ELEMENT_5 = 271;
|
|
||||||
public const ELEMENT_6 = 272;
|
|
||||||
public const ELEMENT_7 = 273;
|
|
||||||
public const ELEMENT_8 = 274;
|
|
||||||
public const ELEMENT_9 = 275;
|
|
||||||
public const ELEMENT_10 = 276;
|
|
||||||
public const ELEMENT_11 = 277;
|
|
||||||
public const ELEMENT_12 = 278;
|
|
||||||
public const ELEMENT_13 = 279;
|
|
||||||
public const ELEMENT_14 = 280;
|
|
||||||
public const ELEMENT_15 = 281;
|
|
||||||
public const ELEMENT_16 = 282;
|
|
||||||
public const ELEMENT_17 = 283;
|
|
||||||
public const ELEMENT_18 = 284;
|
|
||||||
public const ELEMENT_19 = 285;
|
|
||||||
public const ELEMENT_20 = 286;
|
|
||||||
public const ELEMENT_21 = 287;
|
|
||||||
public const ELEMENT_22 = 288;
|
|
||||||
public const ELEMENT_23 = 289;
|
|
||||||
public const ELEMENT_24 = 290;
|
|
||||||
public const ELEMENT_25 = 291;
|
|
||||||
public const ELEMENT_26 = 292;
|
|
||||||
public const ELEMENT_27 = 293;
|
|
||||||
public const ELEMENT_28 = 294;
|
|
||||||
public const ELEMENT_29 = 295;
|
|
||||||
public const ELEMENT_30 = 296;
|
|
||||||
public const ELEMENT_31 = 297;
|
|
||||||
public const ELEMENT_32 = 298;
|
|
||||||
public const ELEMENT_33 = 299;
|
|
||||||
public const ELEMENT_34 = 300;
|
|
||||||
public const ELEMENT_35 = 301;
|
|
||||||
public const ELEMENT_36 = 302;
|
|
||||||
public const ELEMENT_37 = 303;
|
|
||||||
public const ELEMENT_38 = 304;
|
|
||||||
public const ELEMENT_39 = 305;
|
|
||||||
public const ELEMENT_40 = 306;
|
|
||||||
public const ELEMENT_41 = 307;
|
|
||||||
public const ELEMENT_42 = 308;
|
|
||||||
public const ELEMENT_43 = 309;
|
|
||||||
public const ELEMENT_44 = 310;
|
|
||||||
public const ELEMENT_45 = 311;
|
|
||||||
public const ELEMENT_46 = 312;
|
|
||||||
public const ELEMENT_47 = 313;
|
|
||||||
public const ELEMENT_48 = 314;
|
|
||||||
public const ELEMENT_49 = 315;
|
|
||||||
public const ELEMENT_50 = 316;
|
|
||||||
public const ELEMENT_51 = 317;
|
|
||||||
public const ELEMENT_52 = 318;
|
|
||||||
public const ELEMENT_53 = 319;
|
|
||||||
public const ELEMENT_54 = 320;
|
|
||||||
public const ELEMENT_55 = 321;
|
|
||||||
public const ELEMENT_56 = 322;
|
|
||||||
public const ELEMENT_57 = 323;
|
|
||||||
public const ELEMENT_58 = 324;
|
|
||||||
public const ELEMENT_59 = 325;
|
|
||||||
public const ELEMENT_60 = 326;
|
|
||||||
public const ELEMENT_61 = 327;
|
|
||||||
public const ELEMENT_62 = 328;
|
|
||||||
public const ELEMENT_63 = 329;
|
|
||||||
public const ELEMENT_64 = 330;
|
|
||||||
public const ELEMENT_65 = 331;
|
|
||||||
public const ELEMENT_66 = 332;
|
|
||||||
public const ELEMENT_67 = 333;
|
|
||||||
public const ELEMENT_68 = 334;
|
|
||||||
public const ELEMENT_69 = 335;
|
|
||||||
public const ELEMENT_70 = 336;
|
|
||||||
public const ELEMENT_71 = 337;
|
|
||||||
public const ELEMENT_72 = 338;
|
|
||||||
public const ELEMENT_73 = 339;
|
|
||||||
public const ELEMENT_74 = 340;
|
|
||||||
public const ELEMENT_75 = 341;
|
|
||||||
public const ELEMENT_76 = 342;
|
|
||||||
public const ELEMENT_77 = 343;
|
|
||||||
public const ELEMENT_78 = 344;
|
|
||||||
public const ELEMENT_79 = 345;
|
|
||||||
public const ELEMENT_80 = 346;
|
|
||||||
public const ELEMENT_81 = 347;
|
|
||||||
public const ELEMENT_82 = 348;
|
|
||||||
public const ELEMENT_83 = 349;
|
|
||||||
public const ELEMENT_84 = 350;
|
|
||||||
public const ELEMENT_85 = 351;
|
|
||||||
public const ELEMENT_86 = 352;
|
|
||||||
public const ELEMENT_87 = 353;
|
|
||||||
public const ELEMENT_88 = 354;
|
|
||||||
public const ELEMENT_89 = 355;
|
|
||||||
public const ELEMENT_90 = 356;
|
|
||||||
public const ELEMENT_91 = 357;
|
|
||||||
public const ELEMENT_92 = 358;
|
|
||||||
public const ELEMENT_93 = 359;
|
|
||||||
public const ELEMENT_94 = 360;
|
|
||||||
public const ELEMENT_95 = 361;
|
|
||||||
public const ELEMENT_96 = 362;
|
|
||||||
public const ELEMENT_97 = 363;
|
|
||||||
public const ELEMENT_98 = 364;
|
|
||||||
public const ELEMENT_99 = 365;
|
|
||||||
public const ELEMENT_100 = 366;
|
|
||||||
public const ELEMENT_101 = 367;
|
|
||||||
public const ELEMENT_102 = 368;
|
|
||||||
public const ELEMENT_103 = 369;
|
|
||||||
public const ELEMENT_104 = 370;
|
|
||||||
public const ELEMENT_105 = 371;
|
|
||||||
public const ELEMENT_106 = 372;
|
|
||||||
public const ELEMENT_107 = 373;
|
|
||||||
public const ELEMENT_108 = 374;
|
|
||||||
public const ELEMENT_109 = 375;
|
|
||||||
public const ELEMENT_110 = 376;
|
|
||||||
public const ELEMENT_111 = 377;
|
|
||||||
public const ELEMENT_112 = 378;
|
|
||||||
public const ELEMENT_113 = 379;
|
|
||||||
public const ELEMENT_114 = 380;
|
|
||||||
public const ELEMENT_115 = 381;
|
|
||||||
public const ELEMENT_116 = 382;
|
|
||||||
public const ELEMENT_117 = 383;
|
|
||||||
public const ELEMENT_118 = 384;
|
|
||||||
public const SEAGRASS = 385;
|
|
||||||
public const CORAL = 386;
|
|
||||||
public const CORAL_BLOCK = 387;
|
|
||||||
public const CORAL_FAN = 388;
|
|
||||||
public const CORAL_FAN_DEAD = 389;
|
|
||||||
public const CORAL_FAN_HANG = 390;
|
|
||||||
public const CORAL_FAN_HANG2 = 391;
|
|
||||||
public const CORAL_FAN_HANG3 = 392;
|
|
||||||
public const KELP = 393;
|
|
||||||
public const DRIED_KELP_BLOCK = 394;
|
|
||||||
public const ACACIA_BUTTON = 395;
|
|
||||||
public const BIRCH_BUTTON = 396;
|
|
||||||
public const DARK_OAK_BUTTON = 397;
|
|
||||||
public const JUNGLE_BUTTON = 398;
|
|
||||||
public const SPRUCE_BUTTON = 399;
|
|
||||||
public const ACACIA_TRAPDOOR = 400;
|
|
||||||
public const BIRCH_TRAPDOOR = 401;
|
|
||||||
public const DARK_OAK_TRAPDOOR = 402;
|
|
||||||
public const JUNGLE_TRAPDOOR = 403;
|
|
||||||
public const SPRUCE_TRAPDOOR = 404;
|
|
||||||
public const ACACIA_PRESSURE_PLATE = 405;
|
|
||||||
public const BIRCH_PRESSURE_PLATE = 406;
|
|
||||||
public const DARK_OAK_PRESSURE_PLATE = 407;
|
|
||||||
public const JUNGLE_PRESSURE_PLATE = 408;
|
|
||||||
public const SPRUCE_PRESSURE_PLATE = 409;
|
|
||||||
public const CARVED_PUMPKIN = 410;
|
|
||||||
public const SEA_PICKLE = 411;
|
|
||||||
public const CONDUIT = 412;
|
|
||||||
|
|
||||||
public const TURTLE_EGG = 414;
|
|
||||||
public const BUBBLE_COLUMN = 415;
|
|
||||||
public const BARRIER = 416;
|
|
||||||
public const STONE_SLAB3 = 417;
|
|
||||||
public const BAMBOO = 418;
|
|
||||||
public const BAMBOO_SAPLING = 419;
|
|
||||||
public const SCAFFOLDING = 420;
|
|
||||||
public const STONE_SLAB4 = 421;
|
|
||||||
public const DOUBLE_STONE_SLAB3 = 422;
|
|
||||||
public const DOUBLE_STONE_SLAB4 = 423;
|
|
||||||
public const GRANITE_STAIRS = 424;
|
|
||||||
public const DIORITE_STAIRS = 425;
|
|
||||||
public const ANDESITE_STAIRS = 426;
|
|
||||||
public const POLISHED_GRANITE_STAIRS = 427;
|
|
||||||
public const POLISHED_DIORITE_STAIRS = 428;
|
|
||||||
public const POLISHED_ANDESITE_STAIRS = 429;
|
|
||||||
public const MOSSY_STONE_BRICK_STAIRS = 430;
|
|
||||||
public const SMOOTH_RED_SANDSTONE_STAIRS = 431;
|
|
||||||
public const SMOOTH_SANDSTONE_STAIRS = 432;
|
|
||||||
public const END_BRICK_STAIRS = 433;
|
|
||||||
public const MOSSY_COBBLESTONE_STAIRS = 434;
|
|
||||||
public const NORMAL_STONE_STAIRS = 435;
|
|
||||||
public const SPRUCE_STANDING_SIGN = 436;
|
|
||||||
public const SPRUCE_WALL_SIGN = 437;
|
|
||||||
public const SMOOTH_STONE = 438;
|
|
||||||
public const RED_NETHER_BRICK_STAIRS = 439;
|
|
||||||
public const SMOOTH_QUARTZ_STAIRS = 440;
|
|
||||||
public const BIRCH_STANDING_SIGN = 441;
|
|
||||||
public const BIRCH_WALL_SIGN = 442;
|
|
||||||
public const JUNGLE_STANDING_SIGN = 443;
|
|
||||||
public const JUNGLE_WALL_SIGN = 444;
|
|
||||||
public const ACACIA_STANDING_SIGN = 445;
|
|
||||||
public const ACACIA_WALL_SIGN = 446;
|
|
||||||
public const DARKOAK_STANDING_SIGN = 447;
|
|
||||||
public const DARKOAK_WALL_SIGN = 448;
|
|
||||||
public const LECTERN = 449;
|
|
||||||
public const GRINDSTONE = 450;
|
|
||||||
public const BLAST_FURNACE = 451;
|
|
||||||
public const STONECUTTER_BLOCK = 452;
|
|
||||||
public const SMOKER = 453;
|
|
||||||
public const LIT_SMOKER = 454;
|
|
||||||
public const CARTOGRAPHY_TABLE = 455;
|
|
||||||
public const FLETCHING_TABLE = 456;
|
|
||||||
public const SMITHING_TABLE = 457;
|
|
||||||
public const BARREL = 458;
|
|
||||||
public const LOOM = 459;
|
|
||||||
|
|
||||||
public const BELL = 461;
|
|
||||||
public const SWEET_BERRY_BUSH = 462;
|
|
||||||
public const LANTERN = 463;
|
|
||||||
public const CAMPFIRE = 464;
|
|
||||||
public const LAVA_CAULDRON = 465;
|
|
||||||
public const JIGSAW = 466;
|
|
||||||
public const WOOD = 467;
|
|
||||||
public const COMPOSTER = 468;
|
|
||||||
public const LIT_BLAST_FURNACE = 469;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,301 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ____ _ _ __ __ _ __ __ ____
|
|
||||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
||||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
||||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
||||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* @author PocketMine Team
|
|
||||||
* @link http://www.pocketmine.net/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace pocketmine\block;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constants for legacy metadata for various blocks.
|
|
||||||
*/
|
|
||||||
final class BlockLegacyMetadata{
|
|
||||||
|
|
||||||
private function __construct(){
|
|
||||||
//NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
public const ANVIL_NORMAL = 0;
|
|
||||||
public const ANVIL_SLIGHTLY_DAMAGED = 4;
|
|
||||||
public const ANVIL_VERY_DAMAGED = 8;
|
|
||||||
|
|
||||||
public const BAMBOO_FLAG_THICK = 0x01;
|
|
||||||
public const BAMBOO_FLAG_READY = 0x08;
|
|
||||||
|
|
||||||
public const BAMBOO_LEAF_SIZE_SHIFT = 1;
|
|
||||||
public const BAMBOO_LEAF_SIZE_MASK = 0x03;
|
|
||||||
|
|
||||||
public const BARREL_FLAG_OPEN = 0x08;
|
|
||||||
|
|
||||||
public const BED_FLAG_HEAD = 0x08;
|
|
||||||
public const BED_FLAG_OCCUPIED = 0x04;
|
|
||||||
|
|
||||||
public const BEDROCK_FLAG_INFINIBURN = 0x01;
|
|
||||||
|
|
||||||
public const BELL_ATTACHMENT_FLOOR = 0;
|
|
||||||
public const BELL_ATTACHMENT_CEILING = 1;
|
|
||||||
public const BELL_ATTACHMENT_ONE_WALL = 2;
|
|
||||||
public const BELL_ATTACHMENT_TWO_WALLS = 3;
|
|
||||||
|
|
||||||
public const BREWING_STAND_FLAG_EAST = 0x01;
|
|
||||||
public const BREWING_STAND_FLAG_SOUTHWEST = 0x02;
|
|
||||||
public const BREWING_STAND_FLAG_NORTHWEST = 0x04;
|
|
||||||
|
|
||||||
public const BUTTON_FLAG_POWERED = 0x08;
|
|
||||||
|
|
||||||
public const CHEMISTRY_COMPOUND_CREATOR = 0;
|
|
||||||
public const CHEMISTRY_MATERIAL_REDUCER = 4;
|
|
||||||
public const CHEMISTRY_ELEMENT_CONSTRUCTOR = 8;
|
|
||||||
public const CHEMISTRY_LAB_TABLE = 12;
|
|
||||||
|
|
||||||
public const COLORED_TORCH_BP_BLUE = 0;
|
|
||||||
public const COLORED_TORCH_BP_PURPLE = 8;
|
|
||||||
public const COLORED_TORCH_RG_RED = 0;
|
|
||||||
public const COLORED_TORCH_RG_GREEN = 8;
|
|
||||||
|
|
||||||
public const CORAL_BLOCK_FLAG_DEAD = 0x8;
|
|
||||||
|
|
||||||
public const CORAL_FAN_EAST_WEST = 0;
|
|
||||||
public const CORAL_FAN_NORTH_SOUTH = 1;
|
|
||||||
public const CORAL_FAN_TYPE_MASK = 0x7;
|
|
||||||
|
|
||||||
public const CORAL_FAN_HANG_FLAG_DEAD = 0x2;
|
|
||||||
|
|
||||||
public const CORAL_FAN_HANG_TUBE = 0;
|
|
||||||
public const CORAL_FAN_HANG_BRAIN = 1;
|
|
||||||
public const CORAL_FAN_HANG2_BUBBLE = 0;
|
|
||||||
public const CORAL_FAN_HANG2_FIRE = 1;
|
|
||||||
public const CORAL_FAN_HANG3_HORN = 0;
|
|
||||||
public const CORAL_FAN_HANG_TYPE_MASK = 0x1;
|
|
||||||
|
|
||||||
public const CORAL_VARIANT_TUBE = 0;
|
|
||||||
public const CORAL_VARIANT_BRAIN = 1;
|
|
||||||
public const CORAL_VARIANT_BUBBLE = 2;
|
|
||||||
public const CORAL_VARIANT_FIRE = 3;
|
|
||||||
public const CORAL_VARIANT_HORN = 4;
|
|
||||||
|
|
||||||
public const DIRT_FLAG_COARSE = 0x1;
|
|
||||||
|
|
||||||
public const DOOR_FLAG_TOP = 0x08;
|
|
||||||
public const DOOR_BOTTOM_FLAG_OPEN = 0x04;
|
|
||||||
public const DOOR_TOP_FLAG_RIGHT = 0x01;
|
|
||||||
public const DOOR_TOP_FLAG_POWERED = 0x02;
|
|
||||||
|
|
||||||
public const DOUBLE_PLANT_SUNFLOWER = 0;
|
|
||||||
public const DOUBLE_PLANT_LILAC = 1;
|
|
||||||
public const DOUBLE_PLANT_TALLGRASS = 2;
|
|
||||||
public const DOUBLE_PLANT_LARGE_FERN = 3;
|
|
||||||
public const DOUBLE_PLANT_ROSE_BUSH = 4;
|
|
||||||
public const DOUBLE_PLANT_PEONY = 5;
|
|
||||||
|
|
||||||
public const DOUBLE_PLANT_FLAG_TOP = 0x08;
|
|
||||||
|
|
||||||
public const END_PORTAL_FRAME_FLAG_EYE = 0x04;
|
|
||||||
|
|
||||||
public const FENCE_GATE_FLAG_OPEN = 0x04;
|
|
||||||
public const FENCE_GATE_FLAG_IN_WALL = 0x08;
|
|
||||||
|
|
||||||
public const FLOWER_POPPY = 0;
|
|
||||||
public const FLOWER_BLUE_ORCHID = 1;
|
|
||||||
public const FLOWER_ALLIUM = 2;
|
|
||||||
public const FLOWER_AZURE_BLUET = 3;
|
|
||||||
public const FLOWER_RED_TULIP = 4;
|
|
||||||
public const FLOWER_ORANGE_TULIP = 5;
|
|
||||||
public const FLOWER_WHITE_TULIP = 6;
|
|
||||||
public const FLOWER_PINK_TULIP = 7;
|
|
||||||
public const FLOWER_OXEYE_DAISY = 8;
|
|
||||||
public const FLOWER_CORNFLOWER = 9;
|
|
||||||
public const FLOWER_LILY_OF_THE_VALLEY = 10;
|
|
||||||
|
|
||||||
public const FLOWER_POT_FLAG_OCCUPIED = 0x01;
|
|
||||||
|
|
||||||
public const HOPPER_FLAG_POWERED = 0x08;
|
|
||||||
|
|
||||||
public const INFESTED_STONE = 0;
|
|
||||||
public const INFESTED_COBBLESTONE = 1;
|
|
||||||
public const INFESTED_STONE_BRICK = 2;
|
|
||||||
public const INFESTED_STONE_BRICK_MOSSY = 3;
|
|
||||||
public const INFESTED_STONE_BRICK_CRACKED = 4;
|
|
||||||
public const INFESTED_STONE_BRICK_CHISELED = 5;
|
|
||||||
|
|
||||||
public const ITEM_FRAME_FLAG_HAS_MAP = 0x04;
|
|
||||||
|
|
||||||
public const LANTERN_FLAG_HANGING = 0x01;
|
|
||||||
|
|
||||||
public const LEAVES_FLAG_NO_DECAY = 0x04;
|
|
||||||
public const LEAVES_FLAG_CHECK_DECAY = 0x08;
|
|
||||||
|
|
||||||
public const LECTERN_FLAG_POWERED = 0x04;
|
|
||||||
|
|
||||||
public const LEVER_FLAG_POWERED = 0x08;
|
|
||||||
|
|
||||||
public const LIQUID_FLAG_FALLING = 0x08;
|
|
||||||
|
|
||||||
public const MUSHROOM_BLOCK_ALL_PORES = 0;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_NORTHWEST_CORNER = 1;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_NORTH_SIDE = 2;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_NORTHEAST_CORNER = 3;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_WEST_SIDE = 4;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_TOP_ONLY = 5;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_EAST_SIDE = 6;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_SOUTHWEST_CORNER = 7;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_SOUTH_SIDE = 8;
|
|
||||||
public const MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER = 9;
|
|
||||||
public const MUSHROOM_BLOCK_STEM = 10;
|
|
||||||
//11, 12 and 13 appear the same as 0
|
|
||||||
public const MUSHROOM_BLOCK_ALL_CAP = 14;
|
|
||||||
public const MUSHROOM_BLOCK_ALL_STEM = 15;
|
|
||||||
|
|
||||||
public const NETHER_PORTAL_AXIS_X = 1;
|
|
||||||
public const NETHER_PORTAL_AXIS_Z = 2;
|
|
||||||
|
|
||||||
public const NETHER_REACTOR_INACTIVE = 0;
|
|
||||||
public const NETHER_REACTOR_ACTIVE = 1;
|
|
||||||
public const NETHER_REACTOR_USED = 2;
|
|
||||||
|
|
||||||
public const PRESSURE_PLATE_FLAG_POWERED = 0x01;
|
|
||||||
|
|
||||||
public const PRISMARINE_NORMAL = 0;
|
|
||||||
public const PRISMARINE_DARK = 1;
|
|
||||||
public const PRISMARINE_BRICKS = 2;
|
|
||||||
|
|
||||||
public const PURPUR_NORMAL = 0;
|
|
||||||
public const PURPUR_PILLAR = 2;
|
|
||||||
|
|
||||||
public const QUARTZ_NORMAL = 0;
|
|
||||||
public const QUARTZ_CHISELED = 1;
|
|
||||||
public const QUARTZ_PILLAR = 2;
|
|
||||||
public const QUARTZ_SMOOTH = 3;
|
|
||||||
|
|
||||||
public const RAIL_STRAIGHT_NORTH_SOUTH = 0;
|
|
||||||
public const RAIL_STRAIGHT_EAST_WEST = 1;
|
|
||||||
public const RAIL_ASCENDING_EAST = 2;
|
|
||||||
public const RAIL_ASCENDING_WEST = 3;
|
|
||||||
public const RAIL_ASCENDING_NORTH = 4;
|
|
||||||
public const RAIL_ASCENDING_SOUTH = 5;
|
|
||||||
public const RAIL_CURVE_SOUTHEAST = 6;
|
|
||||||
public const RAIL_CURVE_SOUTHWEST = 7;
|
|
||||||
public const RAIL_CURVE_NORTHWEST = 8;
|
|
||||||
public const RAIL_CURVE_NORTHEAST = 9;
|
|
||||||
|
|
||||||
public const REDSTONE_COMPARATOR_FLAG_SUBTRACT = 0x04;
|
|
||||||
public const REDSTONE_COMPARATOR_FLAG_POWERED = 0x08;
|
|
||||||
|
|
||||||
public const REDSTONE_RAIL_FLAG_POWERED = 0x08;
|
|
||||||
|
|
||||||
public const SANDSTONE_NORMAL = 0;
|
|
||||||
public const SANDSTONE_CHISELED = 1;
|
|
||||||
public const SANDSTONE_CUT = 2;
|
|
||||||
public const SANDSTONE_SMOOTH = 3;
|
|
||||||
|
|
||||||
public const SAPLING_FLAG_READY = 0x08;
|
|
||||||
|
|
||||||
public const SEA_PICKLE_FLAG_NOT_UNDERWATER = 0x04;
|
|
||||||
|
|
||||||
public const SKULL_FLAG_NO_DROPS = 0x08;
|
|
||||||
|
|
||||||
public const SLAB_FLAG_UPPER = 0x08;
|
|
||||||
|
|
||||||
public const SPONGE_FLAG_WET = 0x01;
|
|
||||||
|
|
||||||
public const STAIR_FLAG_UPSIDE_DOWN = 0x04;
|
|
||||||
|
|
||||||
public const STONE_NORMAL = 0;
|
|
||||||
public const STONE_GRANITE = 1;
|
|
||||||
public const STONE_POLISHED_GRANITE = 2;
|
|
||||||
public const STONE_DIORITE = 3;
|
|
||||||
public const STONE_POLISHED_DIORITE = 4;
|
|
||||||
public const STONE_ANDESITE = 5;
|
|
||||||
public const STONE_POLISHED_ANDESITE = 6;
|
|
||||||
|
|
||||||
public const STONE_BRICK_NORMAL = 0;
|
|
||||||
public const STONE_BRICK_MOSSY = 1;
|
|
||||||
public const STONE_BRICK_CRACKED = 2;
|
|
||||||
public const STONE_BRICK_CHISELED = 3;
|
|
||||||
|
|
||||||
public const STONE_SLAB_SMOOTH_STONE = 0;
|
|
||||||
public const STONE_SLAB_SANDSTONE = 1;
|
|
||||||
public const STONE_SLAB_FAKE_WOODEN = 2;
|
|
||||||
public const STONE_SLAB_COBBLESTONE = 3;
|
|
||||||
public const STONE_SLAB_BRICK = 4;
|
|
||||||
public const STONE_SLAB_STONE_BRICK = 5;
|
|
||||||
public const STONE_SLAB_QUARTZ = 6;
|
|
||||||
public const STONE_SLAB_NETHER_BRICK = 7;
|
|
||||||
public const STONE_SLAB2_RED_SANDSTONE = 0;
|
|
||||||
public const STONE_SLAB2_PURPUR = 1;
|
|
||||||
public const STONE_SLAB2_PRISMARINE = 2;
|
|
||||||
public const STONE_SLAB2_DARK_PRISMARINE = 3;
|
|
||||||
public const STONE_SLAB2_PRISMARINE_BRICKS = 4;
|
|
||||||
public const STONE_SLAB2_MOSSY_COBBLESTONE = 5;
|
|
||||||
public const STONE_SLAB2_SMOOTH_SANDSTONE = 6;
|
|
||||||
public const STONE_SLAB2_RED_NETHER_BRICK = 7;
|
|
||||||
public const STONE_SLAB3_END_STONE_BRICK = 0;
|
|
||||||
public const STONE_SLAB3_SMOOTH_RED_SANDSTONE = 1;
|
|
||||||
public const STONE_SLAB3_POLISHED_ANDESITE = 2;
|
|
||||||
public const STONE_SLAB3_ANDESITE = 3;
|
|
||||||
public const STONE_SLAB3_DIORITE = 4;
|
|
||||||
public const STONE_SLAB3_POLISHED_DIORITE = 5;
|
|
||||||
public const STONE_SLAB3_GRANITE = 6;
|
|
||||||
public const STONE_SLAB3_POLISHED_GRANITE = 7;
|
|
||||||
public const STONE_SLAB4_MOSSY_STONE_BRICK = 0;
|
|
||||||
public const STONE_SLAB4_SMOOTH_QUARTZ = 1;
|
|
||||||
public const STONE_SLAB4_STONE = 2;
|
|
||||||
public const STONE_SLAB4_CUT_SANDSTONE = 3;
|
|
||||||
public const STONE_SLAB4_CUT_RED_SANDSTONE = 4;
|
|
||||||
|
|
||||||
public const TALLGRASS_NORMAL = 1;
|
|
||||||
public const TALLGRASS_FERN = 2;
|
|
||||||
|
|
||||||
public const TNT_FLAG_UNSTABLE = 0x01;
|
|
||||||
public const TNT_FLAG_UNDERWATER = 0x02;
|
|
||||||
|
|
||||||
public const TRAPDOOR_FLAG_UPPER = 0x04;
|
|
||||||
public const TRAPDOOR_FLAG_OPEN = 0x08;
|
|
||||||
|
|
||||||
public const TRIPWIRE_FLAG_TRIGGERED = 0x01;
|
|
||||||
public const TRIPWIRE_FLAG_SUSPENDED = 0x02;
|
|
||||||
public const TRIPWIRE_FLAG_CONNECTED = 0x04;
|
|
||||||
public const TRIPWIRE_FLAG_DISARMED = 0x08;
|
|
||||||
|
|
||||||
public const TRIPWIRE_HOOK_FLAG_CONNECTED = 0x04;
|
|
||||||
public const TRIPWIRE_HOOK_FLAG_POWERED = 0x08;
|
|
||||||
|
|
||||||
public const VINE_FLAG_SOUTH = 0x01;
|
|
||||||
public const VINE_FLAG_WEST = 0x02;
|
|
||||||
public const VINE_FLAG_NORTH = 0x04;
|
|
||||||
public const VINE_FLAG_EAST = 0x08;
|
|
||||||
|
|
||||||
public const WALL_COBBLESTONE = 0;
|
|
||||||
public const WALL_MOSSY_COBBLESTONE = 1;
|
|
||||||
public const WALL_GRANITE = 2;
|
|
||||||
public const WALL_DIORITE = 3;
|
|
||||||
public const WALL_ANDESITE = 4;
|
|
||||||
public const WALL_SANDSTONE = 5;
|
|
||||||
public const WALL_BRICK = 6;
|
|
||||||
public const WALL_STONE_BRICK = 7;
|
|
||||||
public const WALL_MOSSY_STONE_BRICK = 8;
|
|
||||||
public const WALL_NETHER_BRICK = 9;
|
|
||||||
public const WALL_END_STONE_BRICK = 10;
|
|
||||||
public const WALL_PRISMARINE = 11;
|
|
||||||
public const WALL_RED_SANDSTONE = 12;
|
|
||||||
public const WALL_RED_NETHER_BRICK = 13;
|
|
||||||
|
|
||||||
public const WOOD_FLAG_STRIPPED = 0x8;
|
|
||||||
}
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|||||||
728
src/block/BlockTypeIds.php
Normal file
728
src/block/BlockTypeIds.php
Normal file
@ -0,0 +1,728 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum of all the block runtime IDs used by PocketMine-MP. These IDs are specific to PocketMine-MP and have no
|
||||||
|
* relevance to any Minecraft vanilla things.
|
||||||
|
*
|
||||||
|
* WARNING: DO NOT STORE THESE IDS. They can and will change without warning.
|
||||||
|
* They should ONLY be used to IDENTIFY blocks at runtime.
|
||||||
|
*/
|
||||||
|
final class BlockTypeIds{
|
||||||
|
|
||||||
|
private function __construct(){
|
||||||
|
//NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
public const AIR = 10000;
|
||||||
|
|
||||||
|
public const ACACIA_BUTTON = 10001;
|
||||||
|
public const ACACIA_DOOR = 10002;
|
||||||
|
public const ACACIA_FENCE = 10003;
|
||||||
|
public const ACACIA_FENCE_GATE = 10004;
|
||||||
|
public const ACACIA_LEAVES = 10005;
|
||||||
|
public const ACACIA_LOG = 10006;
|
||||||
|
public const ACACIA_PLANKS = 10007;
|
||||||
|
public const ACACIA_PRESSURE_PLATE = 10008;
|
||||||
|
public const ACACIA_SAPLING = 10009;
|
||||||
|
public const ACACIA_SIGN = 10010;
|
||||||
|
public const ACACIA_SLAB = 10011;
|
||||||
|
public const ACACIA_STAIRS = 10012;
|
||||||
|
public const ACACIA_TRAPDOOR = 10013;
|
||||||
|
public const ACACIA_WALL_SIGN = 10014;
|
||||||
|
public const ACACIA_WOOD = 10015;
|
||||||
|
public const ACTIVATOR_RAIL = 10016;
|
||||||
|
public const ALL_SIDED_MUSHROOM_STEM = 10017;
|
||||||
|
public const ALLIUM = 10018;
|
||||||
|
public const ANDESITE = 10019;
|
||||||
|
public const ANDESITE_SLAB = 10020;
|
||||||
|
public const ANDESITE_STAIRS = 10021;
|
||||||
|
public const ANDESITE_WALL = 10022;
|
||||||
|
public const ANVIL = 10023;
|
||||||
|
public const AZURE_BLUET = 10024;
|
||||||
|
public const BAMBOO = 10025;
|
||||||
|
public const BAMBOO_SAPLING = 10026;
|
||||||
|
public const BANNER = 10027;
|
||||||
|
public const BARREL = 10028;
|
||||||
|
public const BARRIER = 10029;
|
||||||
|
public const BEACON = 10030;
|
||||||
|
public const BED = 10031;
|
||||||
|
public const BEDROCK = 10032;
|
||||||
|
public const BEETROOTS = 10033;
|
||||||
|
public const BELL = 10034;
|
||||||
|
public const BIRCH_BUTTON = 10035;
|
||||||
|
public const BIRCH_DOOR = 10036;
|
||||||
|
public const BIRCH_FENCE = 10037;
|
||||||
|
public const BIRCH_FENCE_GATE = 10038;
|
||||||
|
public const BIRCH_LEAVES = 10039;
|
||||||
|
public const BIRCH_LOG = 10040;
|
||||||
|
public const BIRCH_PLANKS = 10041;
|
||||||
|
public const BIRCH_PRESSURE_PLATE = 10042;
|
||||||
|
public const BIRCH_SAPLING = 10043;
|
||||||
|
public const BIRCH_SIGN = 10044;
|
||||||
|
public const BIRCH_SLAB = 10045;
|
||||||
|
public const BIRCH_STAIRS = 10046;
|
||||||
|
public const BIRCH_TRAPDOOR = 10047;
|
||||||
|
public const BIRCH_WALL_SIGN = 10048;
|
||||||
|
public const BIRCH_WOOD = 10049;
|
||||||
|
|
||||||
|
public const BLAST_FURNACE = 10051;
|
||||||
|
|
||||||
|
public const BLUE_ICE = 10053;
|
||||||
|
public const BLUE_ORCHID = 10054;
|
||||||
|
public const BLUE_TORCH = 10055;
|
||||||
|
public const BONE_BLOCK = 10056;
|
||||||
|
public const BOOKSHELF = 10057;
|
||||||
|
public const BREWING_STAND = 10058;
|
||||||
|
public const BRICK_SLAB = 10059;
|
||||||
|
public const BRICK_STAIRS = 10060;
|
||||||
|
public const BRICK_WALL = 10061;
|
||||||
|
public const BRICKS = 10062;
|
||||||
|
|
||||||
|
public const BROWN_MUSHROOM = 10064;
|
||||||
|
public const BROWN_MUSHROOM_BLOCK = 10065;
|
||||||
|
public const CACTUS = 10066;
|
||||||
|
public const CAKE = 10067;
|
||||||
|
public const CARPET = 10068;
|
||||||
|
public const CARROTS = 10069;
|
||||||
|
public const CARVED_PUMPKIN = 10070;
|
||||||
|
public const CHEMICAL_HEAT = 10071;
|
||||||
|
public const CHEST = 10072;
|
||||||
|
public const CHISELED_QUARTZ = 10073;
|
||||||
|
public const CHISELED_RED_SANDSTONE = 10074;
|
||||||
|
public const CHISELED_SANDSTONE = 10075;
|
||||||
|
public const CHISELED_STONE_BRICKS = 10076;
|
||||||
|
public const CLAY = 10077;
|
||||||
|
public const COAL = 10078;
|
||||||
|
public const COAL_ORE = 10079;
|
||||||
|
public const COBBLESTONE = 10080;
|
||||||
|
public const COBBLESTONE_SLAB = 10081;
|
||||||
|
public const COBBLESTONE_STAIRS = 10082;
|
||||||
|
public const COBBLESTONE_WALL = 10083;
|
||||||
|
public const COBWEB = 10084;
|
||||||
|
public const COCOA_POD = 10085;
|
||||||
|
public const COMPOUND_CREATOR = 10086;
|
||||||
|
public const CONCRETE = 10087;
|
||||||
|
public const CONCRETE_POWDER = 10088;
|
||||||
|
public const CORAL = 10089;
|
||||||
|
public const CORAL_BLOCK = 10090;
|
||||||
|
public const CORAL_FAN = 10091;
|
||||||
|
public const CORNFLOWER = 10092;
|
||||||
|
public const CRACKED_STONE_BRICKS = 10093;
|
||||||
|
public const CRAFTING_TABLE = 10094;
|
||||||
|
public const CUT_RED_SANDSTONE = 10095;
|
||||||
|
public const CUT_RED_SANDSTONE_SLAB = 10096;
|
||||||
|
public const CUT_SANDSTONE = 10097;
|
||||||
|
public const CUT_SANDSTONE_SLAB = 10098;
|
||||||
|
|
||||||
|
public const DANDELION = 10100;
|
||||||
|
public const DARK_OAK_BUTTON = 10101;
|
||||||
|
public const DARK_OAK_DOOR = 10102;
|
||||||
|
public const DARK_OAK_FENCE = 10103;
|
||||||
|
public const DARK_OAK_FENCE_GATE = 10104;
|
||||||
|
public const DARK_OAK_LEAVES = 10105;
|
||||||
|
public const DARK_OAK_LOG = 10106;
|
||||||
|
public const DARK_OAK_PLANKS = 10107;
|
||||||
|
public const DARK_OAK_PRESSURE_PLATE = 10108;
|
||||||
|
public const DARK_OAK_SAPLING = 10109;
|
||||||
|
public const DARK_OAK_SIGN = 10110;
|
||||||
|
public const DARK_OAK_SLAB = 10111;
|
||||||
|
public const DARK_OAK_STAIRS = 10112;
|
||||||
|
public const DARK_OAK_TRAPDOOR = 10113;
|
||||||
|
public const DARK_OAK_WALL_SIGN = 10114;
|
||||||
|
public const DARK_OAK_WOOD = 10115;
|
||||||
|
public const DARK_PRISMARINE = 10116;
|
||||||
|
public const DARK_PRISMARINE_SLAB = 10117;
|
||||||
|
public const DARK_PRISMARINE_STAIRS = 10118;
|
||||||
|
public const DAYLIGHT_SENSOR = 10119;
|
||||||
|
public const DEAD_BUSH = 10120;
|
||||||
|
public const DETECTOR_RAIL = 10121;
|
||||||
|
public const DIAMOND = 10122;
|
||||||
|
public const DIAMOND_ORE = 10123;
|
||||||
|
public const DIORITE = 10124;
|
||||||
|
public const DIORITE_SLAB = 10125;
|
||||||
|
public const DIORITE_STAIRS = 10126;
|
||||||
|
public const DIORITE_WALL = 10127;
|
||||||
|
public const DIRT = 10128;
|
||||||
|
public const DOUBLE_TALLGRASS = 10129;
|
||||||
|
public const DRAGON_EGG = 10130;
|
||||||
|
public const DRIED_KELP = 10131;
|
||||||
|
public const DYED_SHULKER_BOX = 10132;
|
||||||
|
public const ELEMENT_ACTINIUM = 10133;
|
||||||
|
public const ELEMENT_ALUMINUM = 10134;
|
||||||
|
public const ELEMENT_AMERICIUM = 10135;
|
||||||
|
public const ELEMENT_ANTIMONY = 10136;
|
||||||
|
public const ELEMENT_ARGON = 10137;
|
||||||
|
public const ELEMENT_ARSENIC = 10138;
|
||||||
|
public const ELEMENT_ASTATINE = 10139;
|
||||||
|
public const ELEMENT_BARIUM = 10140;
|
||||||
|
public const ELEMENT_BERKELIUM = 10141;
|
||||||
|
public const ELEMENT_BERYLLIUM = 10142;
|
||||||
|
public const ELEMENT_BISMUTH = 10143;
|
||||||
|
public const ELEMENT_BOHRIUM = 10144;
|
||||||
|
public const ELEMENT_BORON = 10145;
|
||||||
|
public const ELEMENT_BROMINE = 10146;
|
||||||
|
public const ELEMENT_CADMIUM = 10147;
|
||||||
|
public const ELEMENT_CALCIUM = 10148;
|
||||||
|
public const ELEMENT_CALIFORNIUM = 10149;
|
||||||
|
public const ELEMENT_CARBON = 10150;
|
||||||
|
public const ELEMENT_CERIUM = 10151;
|
||||||
|
public const ELEMENT_CESIUM = 10152;
|
||||||
|
public const ELEMENT_CHLORINE = 10153;
|
||||||
|
public const ELEMENT_CHROMIUM = 10154;
|
||||||
|
public const ELEMENT_COBALT = 10155;
|
||||||
|
public const ELEMENT_CONSTRUCTOR = 10156;
|
||||||
|
public const ELEMENT_COPERNICIUM = 10157;
|
||||||
|
public const ELEMENT_COPPER = 10158;
|
||||||
|
public const ELEMENT_CURIUM = 10159;
|
||||||
|
public const ELEMENT_DARMSTADTIUM = 10160;
|
||||||
|
public const ELEMENT_DUBNIUM = 10161;
|
||||||
|
public const ELEMENT_DYSPROSIUM = 10162;
|
||||||
|
public const ELEMENT_EINSTEINIUM = 10163;
|
||||||
|
public const ELEMENT_ERBIUM = 10164;
|
||||||
|
public const ELEMENT_EUROPIUM = 10165;
|
||||||
|
public const ELEMENT_FERMIUM = 10166;
|
||||||
|
public const ELEMENT_FLEROVIUM = 10167;
|
||||||
|
public const ELEMENT_FLUORINE = 10168;
|
||||||
|
public const ELEMENT_FRANCIUM = 10169;
|
||||||
|
public const ELEMENT_GADOLINIUM = 10170;
|
||||||
|
public const ELEMENT_GALLIUM = 10171;
|
||||||
|
public const ELEMENT_GERMANIUM = 10172;
|
||||||
|
public const ELEMENT_GOLD = 10173;
|
||||||
|
public const ELEMENT_HAFNIUM = 10174;
|
||||||
|
public const ELEMENT_HASSIUM = 10175;
|
||||||
|
public const ELEMENT_HELIUM = 10176;
|
||||||
|
public const ELEMENT_HOLMIUM = 10177;
|
||||||
|
public const ELEMENT_HYDROGEN = 10178;
|
||||||
|
public const ELEMENT_INDIUM = 10179;
|
||||||
|
public const ELEMENT_IODINE = 10180;
|
||||||
|
public const ELEMENT_IRIDIUM = 10181;
|
||||||
|
public const ELEMENT_IRON = 10182;
|
||||||
|
public const ELEMENT_KRYPTON = 10183;
|
||||||
|
public const ELEMENT_LANTHANUM = 10184;
|
||||||
|
public const ELEMENT_LAWRENCIUM = 10185;
|
||||||
|
public const ELEMENT_LEAD = 10186;
|
||||||
|
public const ELEMENT_LITHIUM = 10187;
|
||||||
|
public const ELEMENT_LIVERMORIUM = 10188;
|
||||||
|
public const ELEMENT_LUTETIUM = 10189;
|
||||||
|
public const ELEMENT_MAGNESIUM = 10190;
|
||||||
|
public const ELEMENT_MANGANESE = 10191;
|
||||||
|
public const ELEMENT_MEITNERIUM = 10192;
|
||||||
|
public const ELEMENT_MENDELEVIUM = 10193;
|
||||||
|
public const ELEMENT_MERCURY = 10194;
|
||||||
|
public const ELEMENT_MOLYBDENUM = 10195;
|
||||||
|
public const ELEMENT_MOSCOVIUM = 10196;
|
||||||
|
public const ELEMENT_NEODYMIUM = 10197;
|
||||||
|
public const ELEMENT_NEON = 10198;
|
||||||
|
public const ELEMENT_NEPTUNIUM = 10199;
|
||||||
|
public const ELEMENT_NICKEL = 10200;
|
||||||
|
public const ELEMENT_NIHONIUM = 10201;
|
||||||
|
public const ELEMENT_NIOBIUM = 10202;
|
||||||
|
public const ELEMENT_NITROGEN = 10203;
|
||||||
|
public const ELEMENT_NOBELIUM = 10204;
|
||||||
|
public const ELEMENT_OGANESSON = 10205;
|
||||||
|
public const ELEMENT_OSMIUM = 10206;
|
||||||
|
public const ELEMENT_OXYGEN = 10207;
|
||||||
|
public const ELEMENT_PALLADIUM = 10208;
|
||||||
|
public const ELEMENT_PHOSPHORUS = 10209;
|
||||||
|
public const ELEMENT_PLATINUM = 10210;
|
||||||
|
public const ELEMENT_PLUTONIUM = 10211;
|
||||||
|
public const ELEMENT_POLONIUM = 10212;
|
||||||
|
public const ELEMENT_POTASSIUM = 10213;
|
||||||
|
public const ELEMENT_PRASEODYMIUM = 10214;
|
||||||
|
public const ELEMENT_PROMETHIUM = 10215;
|
||||||
|
public const ELEMENT_PROTACTINIUM = 10216;
|
||||||
|
public const ELEMENT_RADIUM = 10217;
|
||||||
|
public const ELEMENT_RADON = 10218;
|
||||||
|
public const ELEMENT_RHENIUM = 10219;
|
||||||
|
public const ELEMENT_RHODIUM = 10220;
|
||||||
|
public const ELEMENT_ROENTGENIUM = 10221;
|
||||||
|
public const ELEMENT_RUBIDIUM = 10222;
|
||||||
|
public const ELEMENT_RUTHENIUM = 10223;
|
||||||
|
public const ELEMENT_RUTHERFORDIUM = 10224;
|
||||||
|
public const ELEMENT_SAMARIUM = 10225;
|
||||||
|
public const ELEMENT_SCANDIUM = 10226;
|
||||||
|
public const ELEMENT_SEABORGIUM = 10227;
|
||||||
|
public const ELEMENT_SELENIUM = 10228;
|
||||||
|
public const ELEMENT_SILICON = 10229;
|
||||||
|
public const ELEMENT_SILVER = 10230;
|
||||||
|
public const ELEMENT_SODIUM = 10231;
|
||||||
|
public const ELEMENT_STRONTIUM = 10232;
|
||||||
|
public const ELEMENT_SULFUR = 10233;
|
||||||
|
public const ELEMENT_TANTALUM = 10234;
|
||||||
|
public const ELEMENT_TECHNETIUM = 10235;
|
||||||
|
public const ELEMENT_TELLURIUM = 10236;
|
||||||
|
public const ELEMENT_TENNESSINE = 10237;
|
||||||
|
public const ELEMENT_TERBIUM = 10238;
|
||||||
|
public const ELEMENT_THALLIUM = 10239;
|
||||||
|
public const ELEMENT_THORIUM = 10240;
|
||||||
|
public const ELEMENT_THULIUM = 10241;
|
||||||
|
public const ELEMENT_TIN = 10242;
|
||||||
|
public const ELEMENT_TITANIUM = 10243;
|
||||||
|
public const ELEMENT_TUNGSTEN = 10244;
|
||||||
|
public const ELEMENT_URANIUM = 10245;
|
||||||
|
public const ELEMENT_VANADIUM = 10246;
|
||||||
|
public const ELEMENT_XENON = 10247;
|
||||||
|
public const ELEMENT_YTTERBIUM = 10248;
|
||||||
|
public const ELEMENT_YTTRIUM = 10249;
|
||||||
|
public const ELEMENT_ZERO = 10250;
|
||||||
|
public const ELEMENT_ZINC = 10251;
|
||||||
|
public const ELEMENT_ZIRCONIUM = 10252;
|
||||||
|
public const EMERALD = 10253;
|
||||||
|
public const EMERALD_ORE = 10254;
|
||||||
|
public const ENCHANTING_TABLE = 10255;
|
||||||
|
public const END_PORTAL_FRAME = 10256;
|
||||||
|
public const END_ROD = 10257;
|
||||||
|
public const END_STONE = 10258;
|
||||||
|
public const END_STONE_BRICK_SLAB = 10259;
|
||||||
|
public const END_STONE_BRICK_STAIRS = 10260;
|
||||||
|
public const END_STONE_BRICK_WALL = 10261;
|
||||||
|
public const END_STONE_BRICKS = 10262;
|
||||||
|
public const ENDER_CHEST = 10263;
|
||||||
|
public const FAKE_WOODEN_SLAB = 10264;
|
||||||
|
public const FARMLAND = 10265;
|
||||||
|
public const FERN = 10266;
|
||||||
|
public const FIRE = 10267;
|
||||||
|
public const FLETCHING_TABLE = 10268;
|
||||||
|
public const FLOWER_POT = 10269;
|
||||||
|
public const FROSTED_ICE = 10270;
|
||||||
|
public const FURNACE = 10271;
|
||||||
|
public const GLASS = 10272;
|
||||||
|
public const GLASS_PANE = 10273;
|
||||||
|
public const GLOWING_OBSIDIAN = 10274;
|
||||||
|
public const GLOWSTONE = 10275;
|
||||||
|
public const GOLD = 10276;
|
||||||
|
public const GOLD_ORE = 10277;
|
||||||
|
public const GRANITE = 10278;
|
||||||
|
public const GRANITE_SLAB = 10279;
|
||||||
|
public const GRANITE_STAIRS = 10280;
|
||||||
|
public const GRANITE_WALL = 10281;
|
||||||
|
public const GRASS = 10282;
|
||||||
|
public const GRASS_PATH = 10283;
|
||||||
|
public const GRAVEL = 10284;
|
||||||
|
|
||||||
|
public const GREEN_TORCH = 10287;
|
||||||
|
public const HARDENED_CLAY = 10288;
|
||||||
|
public const HARDENED_GLASS = 10289;
|
||||||
|
public const HARDENED_GLASS_PANE = 10290;
|
||||||
|
public const HAY_BALE = 10291;
|
||||||
|
public const HOPPER = 10292;
|
||||||
|
public const ICE = 10293;
|
||||||
|
public const INFESTED_CHISELED_STONE_BRICK = 10294;
|
||||||
|
public const INFESTED_COBBLESTONE = 10295;
|
||||||
|
public const INFESTED_CRACKED_STONE_BRICK = 10296;
|
||||||
|
public const INFESTED_MOSSY_STONE_BRICK = 10297;
|
||||||
|
public const INFESTED_STONE = 10298;
|
||||||
|
public const INFESTED_STONE_BRICK = 10299;
|
||||||
|
public const INFO_UPDATE = 10300;
|
||||||
|
public const INFO_UPDATE2 = 10301;
|
||||||
|
public const INVISIBLE_BEDROCK = 10302;
|
||||||
|
public const IRON = 10303;
|
||||||
|
public const IRON_BARS = 10304;
|
||||||
|
public const IRON_DOOR = 10305;
|
||||||
|
public const IRON_ORE = 10306;
|
||||||
|
public const IRON_TRAPDOOR = 10307;
|
||||||
|
public const ITEM_FRAME = 10308;
|
||||||
|
public const JUKEBOX = 10309;
|
||||||
|
public const JUNGLE_BUTTON = 10310;
|
||||||
|
public const JUNGLE_DOOR = 10311;
|
||||||
|
public const JUNGLE_FENCE = 10312;
|
||||||
|
public const JUNGLE_FENCE_GATE = 10313;
|
||||||
|
public const JUNGLE_LEAVES = 10314;
|
||||||
|
public const JUNGLE_LOG = 10315;
|
||||||
|
public const JUNGLE_PLANKS = 10316;
|
||||||
|
public const JUNGLE_PRESSURE_PLATE = 10317;
|
||||||
|
public const JUNGLE_SAPLING = 10318;
|
||||||
|
public const JUNGLE_SIGN = 10319;
|
||||||
|
public const JUNGLE_SLAB = 10320;
|
||||||
|
public const JUNGLE_STAIRS = 10321;
|
||||||
|
public const JUNGLE_TRAPDOOR = 10322;
|
||||||
|
public const JUNGLE_WALL_SIGN = 10323;
|
||||||
|
public const JUNGLE_WOOD = 10324;
|
||||||
|
public const LAB_TABLE = 10325;
|
||||||
|
public const LADDER = 10326;
|
||||||
|
public const LANTERN = 10327;
|
||||||
|
public const LAPIS_LAZULI = 10328;
|
||||||
|
public const LAPIS_LAZULI_ORE = 10329;
|
||||||
|
public const LARGE_FERN = 10330;
|
||||||
|
public const LAVA = 10331;
|
||||||
|
public const LECTERN = 10332;
|
||||||
|
public const LEGACY_STONECUTTER = 10333;
|
||||||
|
public const LEVER = 10334;
|
||||||
|
|
||||||
|
public const LILAC = 10337;
|
||||||
|
public const LILY_OF_THE_VALLEY = 10338;
|
||||||
|
public const LILY_PAD = 10339;
|
||||||
|
|
||||||
|
public const LIT_PUMPKIN = 10341;
|
||||||
|
public const LOOM = 10342;
|
||||||
|
|
||||||
|
public const MAGMA = 10344;
|
||||||
|
public const MATERIAL_REDUCER = 10345;
|
||||||
|
public const MELON = 10346;
|
||||||
|
public const MELON_STEM = 10347;
|
||||||
|
public const MOB_HEAD = 10348;
|
||||||
|
public const MONSTER_SPAWNER = 10349;
|
||||||
|
public const MOSSY_COBBLESTONE = 10350;
|
||||||
|
public const MOSSY_COBBLESTONE_SLAB = 10351;
|
||||||
|
public const MOSSY_COBBLESTONE_STAIRS = 10352;
|
||||||
|
public const MOSSY_COBBLESTONE_WALL = 10353;
|
||||||
|
public const MOSSY_STONE_BRICK_SLAB = 10354;
|
||||||
|
public const MOSSY_STONE_BRICK_STAIRS = 10355;
|
||||||
|
public const MOSSY_STONE_BRICK_WALL = 10356;
|
||||||
|
public const MOSSY_STONE_BRICKS = 10357;
|
||||||
|
public const MUSHROOM_STEM = 10358;
|
||||||
|
public const MYCELIUM = 10359;
|
||||||
|
public const NETHER_BRICK_FENCE = 10360;
|
||||||
|
public const NETHER_BRICK_SLAB = 10361;
|
||||||
|
public const NETHER_BRICK_STAIRS = 10362;
|
||||||
|
public const NETHER_BRICK_WALL = 10363;
|
||||||
|
public const NETHER_BRICKS = 10364;
|
||||||
|
public const NETHER_PORTAL = 10365;
|
||||||
|
public const NETHER_QUARTZ_ORE = 10366;
|
||||||
|
public const NETHER_REACTOR_CORE = 10367;
|
||||||
|
public const NETHER_WART = 10368;
|
||||||
|
public const NETHER_WART_BLOCK = 10369;
|
||||||
|
public const NETHERRACK = 10370;
|
||||||
|
public const NOTE_BLOCK = 10371;
|
||||||
|
public const OAK_BUTTON = 10372;
|
||||||
|
public const OAK_DOOR = 10373;
|
||||||
|
public const OAK_FENCE = 10374;
|
||||||
|
public const OAK_FENCE_GATE = 10375;
|
||||||
|
public const OAK_LEAVES = 10376;
|
||||||
|
public const OAK_LOG = 10377;
|
||||||
|
public const OAK_PLANKS = 10378;
|
||||||
|
public const OAK_PRESSURE_PLATE = 10379;
|
||||||
|
public const OAK_SAPLING = 10380;
|
||||||
|
public const OAK_SIGN = 10381;
|
||||||
|
public const OAK_SLAB = 10382;
|
||||||
|
public const OAK_STAIRS = 10383;
|
||||||
|
public const OAK_TRAPDOOR = 10384;
|
||||||
|
public const OAK_WALL_SIGN = 10385;
|
||||||
|
public const OAK_WOOD = 10386;
|
||||||
|
public const OBSIDIAN = 10387;
|
||||||
|
|
||||||
|
public const ORANGE_TULIP = 10389;
|
||||||
|
public const OXEYE_DAISY = 10390;
|
||||||
|
public const PACKED_ICE = 10391;
|
||||||
|
public const PEONY = 10392;
|
||||||
|
|
||||||
|
public const PINK_TULIP = 10394;
|
||||||
|
public const PODZOL = 10395;
|
||||||
|
public const POLISHED_ANDESITE = 10396;
|
||||||
|
public const POLISHED_ANDESITE_SLAB = 10397;
|
||||||
|
public const POLISHED_ANDESITE_STAIRS = 10398;
|
||||||
|
public const POLISHED_DIORITE = 10399;
|
||||||
|
public const POLISHED_DIORITE_SLAB = 10400;
|
||||||
|
public const POLISHED_DIORITE_STAIRS = 10401;
|
||||||
|
public const POLISHED_GRANITE = 10402;
|
||||||
|
public const POLISHED_GRANITE_SLAB = 10403;
|
||||||
|
public const POLISHED_GRANITE_STAIRS = 10404;
|
||||||
|
public const POPPY = 10405;
|
||||||
|
public const POTATOES = 10406;
|
||||||
|
public const POWERED_RAIL = 10407;
|
||||||
|
public const PRISMARINE = 10408;
|
||||||
|
public const PRISMARINE_BRICKS = 10409;
|
||||||
|
public const PRISMARINE_BRICKS_SLAB = 10410;
|
||||||
|
public const PRISMARINE_BRICKS_STAIRS = 10411;
|
||||||
|
public const PRISMARINE_SLAB = 10412;
|
||||||
|
public const PRISMARINE_STAIRS = 10413;
|
||||||
|
public const PRISMARINE_WALL = 10414;
|
||||||
|
public const PUMPKIN = 10415;
|
||||||
|
public const PUMPKIN_STEM = 10416;
|
||||||
|
|
||||||
|
public const PURPLE_TORCH = 10418;
|
||||||
|
public const PURPUR = 10419;
|
||||||
|
public const PURPUR_PILLAR = 10420;
|
||||||
|
public const PURPUR_SLAB = 10421;
|
||||||
|
public const PURPUR_STAIRS = 10422;
|
||||||
|
public const QUARTZ = 10423;
|
||||||
|
public const QUARTZ_PILLAR = 10424;
|
||||||
|
public const QUARTZ_SLAB = 10425;
|
||||||
|
public const QUARTZ_STAIRS = 10426;
|
||||||
|
public const RAIL = 10427;
|
||||||
|
|
||||||
|
public const RED_MUSHROOM = 10429;
|
||||||
|
public const RED_MUSHROOM_BLOCK = 10430;
|
||||||
|
public const RED_NETHER_BRICK_SLAB = 10431;
|
||||||
|
public const RED_NETHER_BRICK_STAIRS = 10432;
|
||||||
|
public const RED_NETHER_BRICK_WALL = 10433;
|
||||||
|
public const RED_NETHER_BRICKS = 10434;
|
||||||
|
public const RED_SAND = 10435;
|
||||||
|
public const RED_SANDSTONE = 10436;
|
||||||
|
public const RED_SANDSTONE_SLAB = 10437;
|
||||||
|
public const RED_SANDSTONE_STAIRS = 10438;
|
||||||
|
public const RED_SANDSTONE_WALL = 10439;
|
||||||
|
public const RED_TORCH = 10440;
|
||||||
|
public const RED_TULIP = 10441;
|
||||||
|
public const REDSTONE = 10442;
|
||||||
|
public const REDSTONE_COMPARATOR = 10443;
|
||||||
|
public const REDSTONE_LAMP = 10444;
|
||||||
|
public const REDSTONE_ORE = 10445;
|
||||||
|
public const REDSTONE_REPEATER = 10446;
|
||||||
|
public const REDSTONE_TORCH = 10447;
|
||||||
|
public const REDSTONE_WIRE = 10448;
|
||||||
|
public const RESERVED6 = 10449;
|
||||||
|
public const ROSE_BUSH = 10450;
|
||||||
|
public const SAND = 10451;
|
||||||
|
public const SANDSTONE = 10452;
|
||||||
|
public const SANDSTONE_SLAB = 10453;
|
||||||
|
public const SANDSTONE_STAIRS = 10454;
|
||||||
|
public const SANDSTONE_WALL = 10455;
|
||||||
|
public const SEA_LANTERN = 10456;
|
||||||
|
public const SEA_PICKLE = 10457;
|
||||||
|
public const SHULKER_BOX = 10458;
|
||||||
|
public const SLIME = 10459;
|
||||||
|
public const SMOKER = 10460;
|
||||||
|
public const SMOOTH_QUARTZ = 10461;
|
||||||
|
public const SMOOTH_QUARTZ_SLAB = 10462;
|
||||||
|
public const SMOOTH_QUARTZ_STAIRS = 10463;
|
||||||
|
public const SMOOTH_RED_SANDSTONE = 10464;
|
||||||
|
public const SMOOTH_RED_SANDSTONE_SLAB = 10465;
|
||||||
|
public const SMOOTH_RED_SANDSTONE_STAIRS = 10466;
|
||||||
|
public const SMOOTH_SANDSTONE = 10467;
|
||||||
|
public const SMOOTH_SANDSTONE_SLAB = 10468;
|
||||||
|
public const SMOOTH_SANDSTONE_STAIRS = 10469;
|
||||||
|
public const SMOOTH_STONE = 10470;
|
||||||
|
public const SMOOTH_STONE_SLAB = 10471;
|
||||||
|
public const SNOW = 10472;
|
||||||
|
public const SNOW_LAYER = 10473;
|
||||||
|
public const SOUL_SAND = 10474;
|
||||||
|
public const SPONGE = 10475;
|
||||||
|
public const SPRUCE_BUTTON = 10476;
|
||||||
|
public const SPRUCE_DOOR = 10477;
|
||||||
|
public const SPRUCE_FENCE = 10478;
|
||||||
|
public const SPRUCE_FENCE_GATE = 10479;
|
||||||
|
public const SPRUCE_LEAVES = 10480;
|
||||||
|
public const SPRUCE_LOG = 10481;
|
||||||
|
public const SPRUCE_PLANKS = 10482;
|
||||||
|
public const SPRUCE_PRESSURE_PLATE = 10483;
|
||||||
|
public const SPRUCE_SAPLING = 10484;
|
||||||
|
public const SPRUCE_SIGN = 10485;
|
||||||
|
public const SPRUCE_SLAB = 10486;
|
||||||
|
public const SPRUCE_STAIRS = 10487;
|
||||||
|
public const SPRUCE_TRAPDOOR = 10488;
|
||||||
|
public const SPRUCE_WALL_SIGN = 10489;
|
||||||
|
public const SPRUCE_WOOD = 10490;
|
||||||
|
public const STAINED_CLAY = 10491;
|
||||||
|
public const STAINED_GLASS = 10492;
|
||||||
|
public const STAINED_GLASS_PANE = 10493;
|
||||||
|
public const STAINED_HARDENED_GLASS = 10494;
|
||||||
|
public const STAINED_HARDENED_GLASS_PANE = 10495;
|
||||||
|
public const STONE = 10496;
|
||||||
|
public const STONE_BRICK_SLAB = 10497;
|
||||||
|
public const STONE_BRICK_STAIRS = 10498;
|
||||||
|
public const STONE_BRICK_WALL = 10499;
|
||||||
|
public const STONE_BRICKS = 10500;
|
||||||
|
public const STONE_BUTTON = 10501;
|
||||||
|
public const STONE_PRESSURE_PLATE = 10502;
|
||||||
|
public const STONE_SLAB = 10503;
|
||||||
|
public const STONE_STAIRS = 10504;
|
||||||
|
public const STONECUTTER = 10505;
|
||||||
|
|
||||||
|
public const SUGARCANE = 10518;
|
||||||
|
public const SUNFLOWER = 10519;
|
||||||
|
public const SWEET_BERRY_BUSH = 10520;
|
||||||
|
public const TALL_GRASS = 10521;
|
||||||
|
public const TNT = 10522;
|
||||||
|
public const TORCH = 10523;
|
||||||
|
public const TRAPPED_CHEST = 10524;
|
||||||
|
public const TRIPWIRE = 10525;
|
||||||
|
public const TRIPWIRE_HOOK = 10526;
|
||||||
|
public const UNDERWATER_TORCH = 10527;
|
||||||
|
public const VINES = 10528;
|
||||||
|
public const WALL_BANNER = 10529;
|
||||||
|
public const WALL_CORAL_FAN = 10530;
|
||||||
|
public const WATER = 10531;
|
||||||
|
public const WEIGHTED_PRESSURE_PLATE_HEAVY = 10532;
|
||||||
|
public const WEIGHTED_PRESSURE_PLATE_LIGHT = 10533;
|
||||||
|
public const WHEAT = 10534;
|
||||||
|
|
||||||
|
public const WHITE_TULIP = 10536;
|
||||||
|
public const WOOL = 10537;
|
||||||
|
|
||||||
|
public const GLAZED_TERRACOTTA = 10539;
|
||||||
|
public const AMETHYST = 10540;
|
||||||
|
public const ANCIENT_DEBRIS = 10541;
|
||||||
|
public const BASALT = 10542;
|
||||||
|
public const POLISHED_BASALT = 10543;
|
||||||
|
public const SMOOTH_BASALT = 10544;
|
||||||
|
public const BLACKSTONE = 10545;
|
||||||
|
public const BLACKSTONE_SLAB = 10546;
|
||||||
|
public const BLACKSTONE_STAIRS = 10547;
|
||||||
|
public const BLACKSTONE_WALL = 10548;
|
||||||
|
public const POLISHED_BLACKSTONE = 10549;
|
||||||
|
public const POLISHED_BLACKSTONE_BUTTON = 10550;
|
||||||
|
public const POLISHED_BLACKSTONE_PRESSURE_PLATE = 10551;
|
||||||
|
public const POLISHED_BLACKSTONE_SLAB = 10552;
|
||||||
|
public const POLISHED_BLACKSTONE_STAIRS = 10553;
|
||||||
|
public const POLISHED_BLACKSTONE_WALL = 10554;
|
||||||
|
public const CHISELED_POLISHED_BLACKSTONE = 10555;
|
||||||
|
public const POLISHED_BLACKSTONE_BRICKS = 10556;
|
||||||
|
public const POLISHED_BLACKSTONE_BRICK_SLAB = 10557;
|
||||||
|
public const POLISHED_BLACKSTONE_BRICK_STAIRS = 10558;
|
||||||
|
public const POLISHED_BLACKSTONE_BRICK_WALL = 10559;
|
||||||
|
public const CRACKED_POLISHED_BLACKSTONE_BRICKS = 10560;
|
||||||
|
public const LIGHT = 10561;
|
||||||
|
public const RAW_COPPER = 10562;
|
||||||
|
public const RAW_GOLD = 10563;
|
||||||
|
public const RAW_IRON = 10564;
|
||||||
|
public const CALCITE = 10565;
|
||||||
|
public const DEEPSLATE = 10566;
|
||||||
|
public const DEEPSLATE_BRICKS = 10567;
|
||||||
|
public const DEEPSLATE_BRICK_SLAB = 10568;
|
||||||
|
public const DEEPSLATE_BRICK_STAIRS = 10569;
|
||||||
|
public const DEEPSLATE_BRICK_WALL = 10570;
|
||||||
|
public const CRACKED_DEEPSLATE_BRICKS = 10571;
|
||||||
|
public const DEEPSLATE_TILES = 10572;
|
||||||
|
public const DEEPSLATE_TILE_SLAB = 10573;
|
||||||
|
public const DEEPSLATE_TILE_STAIRS = 10574;
|
||||||
|
public const DEEPSLATE_TILE_WALL = 10575;
|
||||||
|
public const CRACKED_DEEPSLATE_TILES = 10576;
|
||||||
|
public const COBBLED_DEEPSLATE = 10577;
|
||||||
|
public const COBBLED_DEEPSLATE_SLAB = 10578;
|
||||||
|
public const COBBLED_DEEPSLATE_STAIRS = 10579;
|
||||||
|
public const COBBLED_DEEPSLATE_WALL = 10580;
|
||||||
|
public const POLISHED_DEEPSLATE = 10581;
|
||||||
|
public const POLISHED_DEEPSLATE_SLAB = 10582;
|
||||||
|
public const POLISHED_DEEPSLATE_STAIRS = 10583;
|
||||||
|
public const POLISHED_DEEPSLATE_WALL = 10584;
|
||||||
|
public const QUARTZ_BRICKS = 10585;
|
||||||
|
public const CHISELED_DEEPSLATE = 10586;
|
||||||
|
public const CHISELED_NETHER_BRICKS = 10587;
|
||||||
|
public const CRACKED_NETHER_BRICKS = 10588;
|
||||||
|
public const TUFF = 10589;
|
||||||
|
public const SOUL_TORCH = 10590;
|
||||||
|
public const SOUL_LANTERN = 10591;
|
||||||
|
public const SOUL_SOIL = 10592;
|
||||||
|
public const SOUL_FIRE = 10593;
|
||||||
|
public const SHROOMLIGHT = 10594;
|
||||||
|
public const MANGROVE_PLANKS = 10595;
|
||||||
|
public const CRIMSON_PLANKS = 10596;
|
||||||
|
public const WARPED_PLANKS = 10597;
|
||||||
|
public const MANGROVE_FENCE = 10598;
|
||||||
|
public const CRIMSON_FENCE = 10599;
|
||||||
|
public const WARPED_FENCE = 10600;
|
||||||
|
public const MANGROVE_SLAB = 10601;
|
||||||
|
public const CRIMSON_SLAB = 10602;
|
||||||
|
public const WARPED_SLAB = 10603;
|
||||||
|
public const MANGROVE_LOG = 10604;
|
||||||
|
public const CRIMSON_STEM = 10605;
|
||||||
|
public const WARPED_STEM = 10606;
|
||||||
|
public const MANGROVE_WOOD = 10607;
|
||||||
|
public const CRIMSON_HYPHAE = 10608;
|
||||||
|
public const WARPED_HYPHAE = 10609;
|
||||||
|
public const MANGROVE_TRAPDOOR = 10610;
|
||||||
|
public const CRIMSON_TRAPDOOR = 10611;
|
||||||
|
public const WARPED_TRAPDOOR = 10612;
|
||||||
|
public const MANGROVE_BUTTON = 10613;
|
||||||
|
public const CRIMSON_BUTTON = 10614;
|
||||||
|
public const WARPED_BUTTON = 10615;
|
||||||
|
public const MANGROVE_PRESSURE_PLATE = 10616;
|
||||||
|
public const CRIMSON_PRESSURE_PLATE = 10617;
|
||||||
|
public const WARPED_PRESSURE_PLATE = 10618;
|
||||||
|
public const MANGROVE_DOOR = 10619;
|
||||||
|
public const CRIMSON_DOOR = 10620;
|
||||||
|
public const WARPED_DOOR = 10621;
|
||||||
|
public const MANGROVE_FENCE_GATE = 10622;
|
||||||
|
public const CRIMSON_FENCE_GATE = 10623;
|
||||||
|
public const WARPED_FENCE_GATE = 10624;
|
||||||
|
public const MANGROVE_STAIRS = 10625;
|
||||||
|
public const CRIMSON_STAIRS = 10626;
|
||||||
|
public const WARPED_STAIRS = 10627;
|
||||||
|
public const MANGROVE_SIGN = 10628;
|
||||||
|
public const CRIMSON_SIGN = 10629;
|
||||||
|
public const WARPED_SIGN = 10630;
|
||||||
|
public const MANGROVE_WALL_SIGN = 10631;
|
||||||
|
public const CRIMSON_WALL_SIGN = 10632;
|
||||||
|
public const WARPED_WALL_SIGN = 10633;
|
||||||
|
public const TINTED_GLASS = 10634;
|
||||||
|
public const HONEYCOMB = 10635;
|
||||||
|
public const DEEPSLATE_COAL_ORE = 10636;
|
||||||
|
public const DEEPSLATE_DIAMOND_ORE = 10637;
|
||||||
|
public const DEEPSLATE_EMERALD_ORE = 10638;
|
||||||
|
public const DEEPSLATE_LAPIS_LAZULI_ORE = 10639;
|
||||||
|
public const DEEPSLATE_REDSTONE_ORE = 10640;
|
||||||
|
public const DEEPSLATE_IRON_ORE = 10641;
|
||||||
|
public const DEEPSLATE_GOLD_ORE = 10642;
|
||||||
|
public const DEEPSLATE_COPPER_ORE = 10643;
|
||||||
|
public const COPPER_ORE = 10644;
|
||||||
|
public const NETHER_GOLD_ORE = 10645;
|
||||||
|
public const MUD = 10646;
|
||||||
|
public const MUD_BRICKS = 10647;
|
||||||
|
public const MUD_BRICK_SLAB = 10648;
|
||||||
|
public const MUD_BRICK_STAIRS = 10649;
|
||||||
|
public const MUD_BRICK_WALL = 10650;
|
||||||
|
public const PACKED_MUD = 10651;
|
||||||
|
public const WARPED_WART_BLOCK = 10652;
|
||||||
|
public const CRYING_OBSIDIAN = 10653;
|
||||||
|
public const GILDED_BLACKSTONE = 10654;
|
||||||
|
public const LIGHTNING_ROD = 10655;
|
||||||
|
public const COPPER = 10656;
|
||||||
|
public const CUT_COPPER = 10657;
|
||||||
|
public const CUT_COPPER_SLAB = 10658;
|
||||||
|
public const CUT_COPPER_STAIRS = 10659;
|
||||||
|
public const CANDLE = 10660;
|
||||||
|
public const DYED_CANDLE = 10661;
|
||||||
|
public const CAKE_WITH_CANDLE = 10662;
|
||||||
|
public const CAKE_WITH_DYED_CANDLE = 10663;
|
||||||
|
public const WITHER_ROSE = 10664;
|
||||||
|
public const HANGING_ROOTS = 10665;
|
||||||
|
public const CARTOGRAPHY_TABLE = 10666;
|
||||||
|
public const SMITHING_TABLE = 10667;
|
||||||
|
public const NETHERITE = 10668;
|
||||||
|
public const SPORE_BLOSSOM = 10669;
|
||||||
|
public const CAULDRON = 10670;
|
||||||
|
public const WATER_CAULDRON = 10671;
|
||||||
|
public const LAVA_CAULDRON = 10672;
|
||||||
|
public const POTION_CAULDRON = 10673;
|
||||||
|
public const POWDER_SNOW_CAULDRON = 10674;
|
||||||
|
public const CHORUS_FLOWER = 10675;
|
||||||
|
public const CHORUS_PLANT = 10676;
|
||||||
|
public const MANGROVE_ROOTS = 10677;
|
||||||
|
public const MUDDY_MANGROVE_ROOTS = 10678;
|
||||||
|
public const FROGLIGHT = 10679;
|
||||||
|
public const TWISTING_VINES = 10680;
|
||||||
|
public const WEEPING_VINES = 10681;
|
||||||
|
public const CHAIN = 10682;
|
||||||
|
public const SCULK = 10683;
|
||||||
|
public const GLOWING_ITEM_FRAME = 10684;
|
||||||
|
public const MANGROVE_LEAVES = 10685;
|
||||||
|
public const AZALEA_LEAVES = 10686;
|
||||||
|
public const FLOWERING_AZALEA_LEAVES = 10687;
|
||||||
|
public const REINFORCED_DEEPSLATE = 10688;
|
||||||
|
public const CAVE_VINES = 10689;
|
||||||
|
|
||||||
|
public const FIRST_UNUSED_BLOCK_ID = 10690;
|
||||||
|
|
||||||
|
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new runtime block type ID, e.g. for use by a custom block.
|
||||||
|
*/
|
||||||
|
public static function newId() : int{
|
||||||
|
return self::$nextDynamicId++;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/block/BlockTypeInfo.php
Normal file
52
src/block/BlockTypeInfo.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use function array_fill_keys;
|
||||||
|
use function array_keys;
|
||||||
|
|
||||||
|
final class BlockTypeInfo{
|
||||||
|
/**
|
||||||
|
* @var true[]
|
||||||
|
* @phpstan-var array<string, true>
|
||||||
|
*/
|
||||||
|
private array $typeTags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $typeTags
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private BlockBreakInfo $breakInfo,
|
||||||
|
array $typeTags = []
|
||||||
|
){
|
||||||
|
$this->typeTags = array_fill_keys($typeTags, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBreakInfo() : BlockBreakInfo{ return $this->breakInfo; }
|
||||||
|
|
||||||
|
/** @return string[] */
|
||||||
|
public function getTypeTags() : array{ return array_keys($this->typeTags); }
|
||||||
|
|
||||||
|
public function hasTypeTag(string $tag) : bool{ return isset($this->typeTags[$tag]); }
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user