mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-13 12:55:06 +00:00
Compare commits
1754 Commits
3.6.5
...
before-psr
Author | SHA1 | Date | |
---|---|---|---|
7a77d3dc30 | |||
6b4d8b91c6 | |||
ece28e5d7b | |||
3eb1a56985 | |||
8f5eb7ef37 | |||
cf1b140d57 | |||
2ecdea2cc6 | |||
334d15339f | |||
c40074d0bf | |||
96d8790028 | |||
452cfe2f59 | |||
a4042e5d18 | |||
1111d0d4c7 | |||
17a3ca066e | |||
52412e9c21 | |||
a621bf66ff | |||
18d05f57b5 | |||
23b00bea5b | |||
0ea9a08963 | |||
18a1bfe4dd | |||
2d3562c687 | |||
f3f8cd98de | |||
b98dad6f63 | |||
e06ab0869a | |||
6c0ae6bf0b | |||
379a40c13a | |||
c9ecd04353 | |||
cde2c10c1d | |||
34ed2980e5 | |||
87fb42cabd | |||
cb40484a2e | |||
6566dd8c8f | |||
1e65ac0d85 | |||
e75a08a5a3 | |||
cb247a5f28 | |||
bb048fb361 | |||
95dfff727e | |||
d55889d85f | |||
99f65f19ac | |||
581eeee01d | |||
7275952fc2 | |||
17341d7406 | |||
a91a86bf1d | |||
b543744534 | |||
e95b9fa432 | |||
72c0af2e82 | |||
04c0cd142d | |||
7a747d6f93 | |||
e93d034a4e | |||
5a08a10448 | |||
622f93df45 | |||
80d277f1b5 | |||
703ae3a172 | |||
6fdcb09891 | |||
a9c6489e08 | |||
e388ac9c8b | |||
08a654760c | |||
b788982d60 | |||
1e057394c0 | |||
47b120fa0e | |||
556beacdbf | |||
b4df1ac547 | |||
3965c9419d | |||
26faf4a952 | |||
14d79c205b | |||
99bba66f13 | |||
1fee70abfb | |||
ac12911561 | |||
0ebd3e6ca2 | |||
5a5ce84ebc | |||
a4c7744188 | |||
c5ebc12f1a | |||
5e8c92b1da | |||
a8fa3ba434 | |||
670bf2b9d1 | |||
f5491346ce | |||
b5b4133c5d | |||
e22986f065 | |||
3632e07cdb | |||
64948f38d0 | |||
728aa8aae7 | |||
1a1feefd3e | |||
7954a81602 | |||
73d3f9f7f7 | |||
ccf165b107 | |||
6aba9fadfc | |||
af73c5f2b1 | |||
fec8c75fd8 | |||
74572fde08 | |||
ad4ed1c95c | |||
382d97a178 | |||
b57dcebb6f | |||
711ea3185d | |||
ff21977461 | |||
49a6821195 | |||
8f64d6b053 | |||
73a847123b | |||
3d0e47ba14 | |||
27352486a0 | |||
d624c38ab1 | |||
52de5a6e49 | |||
d874be99a6 | |||
1767cbe80d | |||
484f2f43c0 | |||
0ba3121c43 | |||
64fbf5025a | |||
aaa01bb6f8 | |||
50d71809e1 | |||
6839712394 | |||
9b5ae7ec75 | |||
94eb64c2be | |||
3fae57508b | |||
f637f14e4a | |||
1391e4826f | |||
544bbf849d | |||
a883c35fd0 | |||
6a93eb8361 | |||
740398282f | |||
9d14bc54d6 | |||
bd69c66d03 | |||
c58a1bf9b7 | |||
59c310b914 | |||
790fcc4ebb | |||
5430f19e7a | |||
12ee885432 | |||
39bcd2ec3d | |||
e8fe3d0664 | |||
41705db687 | |||
08e1f6405c | |||
b6efb33b91 | |||
c07396442c | |||
1cf4cf8614 | |||
5f959a148f | |||
5a2e84eb9f | |||
4264923f4f | |||
c1212eab8e | |||
bda9bd2f2d | |||
9ef5f9518c | |||
fe3a4baddb | |||
c42817f02f | |||
007aee72f8 | |||
4e2f430f06 | |||
cdab3e967a | |||
55cccff850 | |||
03e70e68f4 | |||
2cab22fd38 | |||
7c52b4c93d | |||
3f31dbde57 | |||
1bfd6f2a90 | |||
c7a5b8b0b4 | |||
11fc16617a | |||
f9bfaa0c6a | |||
77a4393c7b | |||
5274a0fe3c | |||
da0358529a | |||
4d7c18f65b | |||
119cb083bf | |||
5c25f770c2 | |||
f3995f7cb0 | |||
a2bb6a41d9 | |||
ce77e283ab | |||
13de99315b | |||
80747814fb | |||
bda3631c24 | |||
f714ed6e90 | |||
124640737a | |||
ceeed57118 | |||
45b0cbc796 | |||
2e01bd1029 | |||
77919b70b2 | |||
f356bf0893 | |||
fe850a184c | |||
2bd2e1125c | |||
b021cc2138 | |||
453c5a329d | |||
ceb6529ee3 | |||
3d118a415c | |||
7fc45bc5c3 | |||
3bdf740597 | |||
9ed13bf112 | |||
a125980ada | |||
062e692069 | |||
1d96c1810f | |||
4c5d8c12dd | |||
134a87ec7d | |||
ee885bb725 | |||
85051554c4 | |||
e07523056d | |||
ab4b1be363 | |||
4a6d4953f2 | |||
80b29250c8 | |||
02bbf50dbe | |||
5b02ca8a64 | |||
720254f64f | |||
d23eeff832 | |||
206b397ee1 | |||
b0a85155d7 | |||
3c7f68dc1e | |||
b90be8dc5f | |||
7aa4d974ef | |||
601ba4264d | |||
a325b1f3a1 | |||
9e993aa83f | |||
fab12707ae | |||
b1ef1026ee | |||
1156d5bdba | |||
5e5f43242e | |||
68bff6cf69 | |||
80d4eeaa3c | |||
0d769aab48 | |||
44a205b1cc | |||
a4b50e57a4 | |||
e7733718b6 | |||
872b6ed708 | |||
0e4966dfdf | |||
193a41566d | |||
1749b57a83 | |||
6da2bd4bb3 | |||
45f5f112dd | |||
6f087190f4 | |||
a279648c68 | |||
6838a1e07a | |||
f3882dd658 | |||
2ba76bd97d | |||
7f56f27505 | |||
61d443bf4e | |||
9fe073fa73 | |||
3f9493bcd0 | |||
7eaca6bbaa | |||
9cedfeb2b2 | |||
f62d9cbb99 | |||
7bdb99ae8b | |||
eee039a490 | |||
ee72680f44 | |||
26178b4435 | |||
9bebc6c69d | |||
4448919a8b | |||
42b1c45fa5 | |||
a6395c9ac7 | |||
44b7239847 | |||
e8d9acb59f | |||
73938486fc | |||
6bbae4b2df | |||
ec25a71396 | |||
15fa1056b7 | |||
ff55f5e9ac | |||
8c2ca098e1 | |||
f152ae9cbf | |||
c19c42a934 | |||
edccce1419 | |||
d85a27c5b2 | |||
8ec25b59a3 | |||
94ee33e47b | |||
75a4136ab2 | |||
de10e401bf | |||
d15284e638 | |||
feac2df088 | |||
4c2015fd0f | |||
16482e6a95 | |||
9f09dc3dd7 | |||
91580ce321 | |||
ae9115ad0d | |||
6b090d653c | |||
012f015e7d | |||
181cfef731 | |||
197a56e3e1 | |||
3103579ba6 | |||
6925451f3f | |||
6db2a3a0fb | |||
51f299f196 | |||
0273bd4f53 | |||
2bb52cf811 | |||
6afc689529 | |||
ce74549ba3 | |||
46054803d5 | |||
a9f99240b5 | |||
a16b44ea12 | |||
ff8ca99c9f | |||
c5707f6174 | |||
2559f5ec2b | |||
e82a40b2ba | |||
c66af4648c | |||
075f49aef0 | |||
709963f90a | |||
b18bd4f33c | |||
87c3636d44 | |||
94299534b3 | |||
9df2ca3655 | |||
bb675ac99b | |||
7b049b6db1 | |||
e0a9ea2573 | |||
db3305cb16 | |||
92e81e3298 | |||
3c677bd3ec | |||
20f092a685 | |||
fe98b6c765 | |||
c45c1c930e | |||
b344427a30 | |||
698193622a | |||
4878fc4c93 | |||
cd48d8272c | |||
6d09460abc | |||
b71bb867f4 | |||
94180cda72 | |||
5a17a0d1aa | |||
b38c81c96f | |||
0fabc0c199 | |||
0ca07ad075 | |||
60b183b0d9 | |||
ec5598dbb1 | |||
5d3b4f23a3 | |||
7b98d203f4 | |||
dbf4054b1f | |||
82e4ef6d48 | |||
4635b93f4d | |||
a8433697ad | |||
d0d300a6f8 | |||
680cdb8e3e | |||
eaa78fe849 | |||
eedea4998b | |||
4e5a80c481 | |||
4d54dc30c1 | |||
ac5339414a | |||
6161155660 | |||
2a5561fcd1 | |||
4e734989bc | |||
93b83b4189 | |||
312a755a27 | |||
a94541c531 | |||
4bbf1d56dc | |||
50a7fc0ba3 | |||
c77e75fa93 | |||
468340d55b | |||
8356285b66 | |||
f671f2ebfa | |||
787d305c2a | |||
2cb6fda286 | |||
08de657c8d | |||
92035ac2ec | |||
722da5e88d | |||
c8eefddfc0 | |||
211836274f | |||
5d531b56db | |||
9e9de1e8ba | |||
da4c646d27 | |||
44be2179c4 | |||
8551d1e282 | |||
7ba1dd3242 | |||
f128fc1849 | |||
3568c7b1c7 | |||
862c844759 | |||
6bd67730eb | |||
e95d81e04b | |||
31f0576725 | |||
8afea36919 | |||
4364d2a942 | |||
42954c1d72 | |||
9765d78a5d | |||
4c5f6eb1b7 | |||
02bc43b440 | |||
5832f42783 | |||
858f440bcf | |||
de6053de11 | |||
f349a58f2b | |||
1c69226187 | |||
8e6f21afad | |||
f0d56f25b6 | |||
dd45753fa9 | |||
3ac0c98199 | |||
714393820f | |||
3175a319a2 | |||
7c1f038f20 | |||
a42f68d3cf | |||
b6f3f6120b | |||
96d3f4f78b | |||
6756203aec | |||
419fc418fe | |||
261ba017a6 | |||
adb78679c5 | |||
c1f900ab18 | |||
f84040a7ad | |||
1b629d7ac0 | |||
73964e6e2f | |||
ad1b9e5cdd | |||
43dfc8ae0f | |||
fefc9b5278 | |||
5e88fda824 | |||
3bc8244673 | |||
659cad0eff | |||
f30cee15ca | |||
a2274429ab | |||
cc6296b019 | |||
7eb9b33fd6 | |||
41039cecc1 | |||
857092cf65 | |||
741d2a7380 | |||
b0071ed703 | |||
b5805c2d0a | |||
67321bb3f6 | |||
d176f6f1ca | |||
f8a7766880 | |||
b60731607d | |||
44c791f03e | |||
e07f3e8e65 | |||
5c5fbf9b78 | |||
32c832c87e | |||
0058bfcd23 | |||
9f31b479e1 | |||
eb161f8e1c | |||
61afc7b62c | |||
9f0a184a5d | |||
3b5df90b0b | |||
287c8c2dd4 | |||
09afb8e772 | |||
cda565ba8c | |||
80f8a27094 | |||
6f29fe063f | |||
89d4f596bd | |||
3c3e5a9850 | |||
5d16a48361 | |||
0ae3c734ea | |||
f5b149a022 | |||
6743234461 | |||
e69ab60034 | |||
3569f8dfbe | |||
df0acea2f4 | |||
56a4e8c032 | |||
7a05c46ff6 | |||
341c480e13 | |||
8e24e5655a | |||
971ad04299 | |||
087df45a3c | |||
9d42bc3c0c | |||
ad79e6cd8e | |||
e091cfe1de | |||
df8db3b8e3 | |||
025b72e2f2 | |||
efe30ffb07 | |||
cf538afb84 | |||
1049ffecc9 | |||
77ace57985 | |||
790c2cd4b7 | |||
1bf5c74053 | |||
f18da8d879 | |||
ece4d99c1e | |||
3d8cd54f16 | |||
f3daf612ee | |||
7ff91337ad | |||
63e5867727 | |||
c38779f1fd | |||
bcff124953 | |||
28f3322337 | |||
11d21448fc | |||
7eb8d8e366 | |||
2720ff9607 | |||
89242543b9 | |||
0a891f5408 | |||
3902a3c28c | |||
14bae72dd5 | |||
2eb498b84c | |||
c1a7d86670 | |||
e6048e115e | |||
2c40fbfe11 | |||
33d1203bfd | |||
85718e2750 | |||
32e03cd92d | |||
685f5d562b | |||
d23dbc69f1 | |||
a44d47fd3c | |||
b329cac3d2 | |||
066eadd687 | |||
c29523baf4 | |||
54216c2fee | |||
d25ecbebd4 | |||
f35b43613d | |||
3d0fa10437 | |||
3ea8da2dd3 | |||
9ce1e29a17 | |||
1c99602a3f | |||
297ca25123 | |||
cd0f0cb66c | |||
d6ce3f82b1 | |||
c21a25efb9 | |||
04d0b6c054 | |||
c13b352b76 | |||
d9bc48bb01 | |||
bca0833035 | |||
cd103cefcc | |||
dec6c9f49b | |||
67affcea32 | |||
57219abc9d | |||
c3c2dd3988 | |||
fa9fcea189 | |||
d44ec702b0 | |||
b11d3b0401 | |||
cd8645ff20 | |||
6de0b48c1f | |||
64f7f558a4 | |||
76e5ea385b | |||
0f398bbe66 | |||
f7a9da4e92 | |||
dd914e0752 | |||
1898db840d | |||
642c16dfe7 | |||
ff2600a0d0 | |||
5024de38b8 | |||
9ea684581f | |||
fd413b512e | |||
10831821be | |||
85c6eb5003 | |||
166d821bcf | |||
d6b720b55d | |||
a19651a8dc | |||
adf4639625 | |||
db4dac6d45 | |||
90e6073202 | |||
41d754de5a | |||
5a351d3caf | |||
bb93d4f8de | |||
66818e178a | |||
c99846e069 | |||
51f96b195e | |||
0bf7fd2c0d | |||
650e186481 | |||
01ad568256 | |||
9e72bc91a2 | |||
3be5de4570 | |||
5eb3c52a37 | |||
51a8c2be9d | |||
ca7c23c137 | |||
4634baeb02 | |||
cf73c7f5c1 | |||
a51c06116a | |||
f782a478c4 | |||
19ac0811f4 | |||
a331c5e13f | |||
9fbf41b9a1 | |||
c06b4830d1 | |||
fc90cdcc95 | |||
cf0c0e72a9 | |||
78bb6f4a0c | |||
51548d1a27 | |||
c1a483a36d | |||
d7a7ab5102 | |||
66481fedeb | |||
00944eff72 | |||
cb3a225d45 | |||
3cd6e12e71 | |||
427e334426 | |||
ce61c6e0fd | |||
3415edf600 | |||
c2771eba88 | |||
82974e0271 | |||
685481b172 | |||
5250a432d1 | |||
6d64ef8d74 | |||
c5498bb3fa | |||
7ae84944ca | |||
6b4c11febb | |||
9fd922fe6a | |||
59334d652f | |||
5c81da9b1e | |||
b08affc4c6 | |||
af07ffb292 | |||
fdaf9dce73 | |||
cb49f1e835 | |||
f6a0f4aa82 | |||
de09c8c082 | |||
0ac87989dc | |||
0317b0f22d | |||
732e27751c | |||
13ea984b12 | |||
3878f58847 | |||
d7a35a5302 | |||
1730415643 | |||
293311569d | |||
932c489de1 | |||
67e75d6c0a | |||
854a2f5135 | |||
ea8c723092 | |||
854c3a816c | |||
7c7f42eba6 | |||
6aa8276532 | |||
6a2d1fbdda | |||
d850a84d0d | |||
22d9260a3b | |||
3c90ed13b9 | |||
396efbac7e | |||
00644dd529 | |||
c2c210e25a | |||
86c4e936cb | |||
3b103dcd62 | |||
48dfc5b232 | |||
39360f127a | |||
25890e76e2 | |||
810bdeb965 | |||
b6b3dcc1aa | |||
e0818e7e52 | |||
4ca40a21ae | |||
d0c4463773 | |||
7521160f53 | |||
7ec926867f | |||
4f5190e3f8 | |||
7d712d68c4 | |||
3c941dd992 | |||
89f457b397 | |||
2bdbb9794c | |||
898009a91b | |||
c5ca623124 | |||
a3dea09e2a | |||
793f93afdb | |||
64506ea3ae | |||
4a35516441 | |||
74b9922a28 | |||
088fbf65b1 | |||
fa70127241 | |||
fc76d04dcb | |||
15ae323bcb | |||
353bae87a7 | |||
dc7be3fd52 | |||
f28a0740a0 | |||
df990fb47a | |||
ffb0ed80a2 | |||
6af84caba6 | |||
98ca28d96e | |||
0dac982f16 | |||
db896b9faf | |||
76c234e4e6 | |||
2ef3962028 | |||
86cc151e60 | |||
7720a0534e | |||
f933ce31dd | |||
1e5941c98c | |||
752e398970 | |||
a4c7ec077b | |||
5913d5038b | |||
cc01dfe8df | |||
d68501c748 | |||
939dfd9269 | |||
0973e39697 | |||
3468f006a2 | |||
e62bbd4754 | |||
b4f6c1e1a6 | |||
9ca7c0c883 | |||
b4a8f8391b | |||
142d750b9f | |||
209ae51a67 | |||
948b0b4cbc | |||
d6b596a8ac | |||
eab2d4d704 | |||
8114551600 | |||
8e1d1993c5 | |||
82bf5f6193 | |||
76a86e51f7 | |||
d1e803685a | |||
0a884aa5fb | |||
c410e676b3 | |||
8f1f5fde47 | |||
0f268df2e0 | |||
86108e7010 | |||
5ea448ef36 | |||
389e7767d1 | |||
4c268acc00 | |||
e506c7f7de | |||
cfd4580388 | |||
9b0b8b9a0c | |||
8a1c362db7 | |||
6428ca2a42 | |||
e34a4f6b98 | |||
c4b4575c74 | |||
bf2851f324 | |||
5f23fffdda | |||
342b48b758 | |||
3925e598d6 | |||
383ec8a8e3 | |||
95313e0a90 | |||
e9a87978a6 | |||
c310a0c50c | |||
612e9e162c | |||
c49ead1a4c | |||
fdc3faadc9 | |||
e07b3f534b | |||
9644e72acf | |||
86a5a50330 | |||
5a989d82bb | |||
e6a1f0eb8d | |||
0e3e984db9 | |||
a0b8d9a64e | |||
2c678dcf0d | |||
f901c2a612 | |||
f332550e52 | |||
80a6fc5dd1 | |||
b6e453a5f4 | |||
7d22b2a6d7 | |||
e5756dbf0b | |||
2c4f2810d2 | |||
6214a9398d | |||
f0b85936cf | |||
c59a2d1b93 | |||
f8ce7797db | |||
42a263a9df | |||
0017c0087a | |||
8c19f6cac8 | |||
cdeb3ea5a6 | |||
aff2e0c86c | |||
7bd9a2b2e0 | |||
004e81ea35 | |||
3ea5260935 | |||
5c26deb517 | |||
8fcb44de7d | |||
bd2e7db3b9 | |||
f4480c07ee | |||
1fd4077907 | |||
f638845ef6 | |||
c09e2301c8 | |||
8e9f787d33 | |||
260fa50db4 | |||
de193d41a0 | |||
649ce5080b | |||
0e806854b9 | |||
3de08bf452 | |||
2091354927 | |||
d8c81c0a11 | |||
7b2b43c0ca | |||
0aebb3f4fb | |||
e1504c668e | |||
10db57655e | |||
37b5ad8350 | |||
1bf0802275 | |||
7333e7118e | |||
c98801402b | |||
a9c76c2424 | |||
161d5bd6b8 | |||
89833b3b68 | |||
a10a656a5d | |||
01e048c4d1 | |||
ca22223b62 | |||
999174b0a7 | |||
0811ce81e5 | |||
23071d257e | |||
1ea5316a37 | |||
97ccc6e880 | |||
d0940e4be2 | |||
6990d6239e | |||
a753c1342d | |||
9c76fb7d96 | |||
aea775c7c6 | |||
d9134f28e4 | |||
2a3e6dcf00 | |||
79ef8e0803 | |||
f84d7ad70d | |||
be0436b2a0 | |||
397713247d | |||
6efdac63d0 | |||
06a37cc462 | |||
e088da320c | |||
d51ca0b655 | |||
a2f42a7016 | |||
1e096a408a | |||
74e134136d | |||
a8fa8572e1 | |||
3c283aa700 | |||
905cb7544a | |||
765c5963a8 | |||
53bb05a6a7 | |||
034bd716c8 | |||
a74a4b579d | |||
98f56087de | |||
15c6554d8a | |||
d4fe004375 | |||
1045088668 | |||
1bc37a1a8a | |||
9cddfdf8ec | |||
1d1a416afe | |||
f3309d3aec | |||
9ec62643d5 | |||
433dab078b | |||
afbd016611 | |||
712e077bc1 | |||
9904810f24 | |||
60225a378f | |||
f84a1729c6 | |||
8e48c61daf | |||
2659ed8d91 | |||
9b11e39efc | |||
d03f0aab37 | |||
6ec2a69417 | |||
3dbed830ef | |||
b8d1eb20b0 | |||
89c0836047 | |||
9ad7f74501 | |||
9c01ecbe7e | |||
6a55021779 | |||
588ebe446f | |||
8c536c248d | |||
1ac255f955 | |||
2966e87aae | |||
2e5ef4ba03 | |||
6ada261b04 | |||
14a6779e08 | |||
cce99b07af | |||
c3d80d711d | |||
cc78c9ef18 | |||
1a8b33dafe | |||
8de9e61651 | |||
5830ca958b | |||
6f54b53f7a | |||
87928038e6 | |||
7d72b8e756 | |||
9205bbaa42 | |||
a91f49220c | |||
62185d476b | |||
1e0f1e5b1a | |||
d080d3bae0 | |||
41d13b6f06 | |||
a1ffaffa7f | |||
ebfe9caca3 | |||
26a5d97499 | |||
fa7a4dc22e | |||
34758e3bc6 | |||
08c399529d | |||
ad19696364 | |||
01904adf49 | |||
7f4b76aa86 | |||
0e1a88f7e5 | |||
8b9eeb0b7f | |||
2e4b3d3d46 | |||
1d4f44d259 | |||
13bea6c787 | |||
48427290c9 | |||
437750785f | |||
c2a069afd3 | |||
84bbd14a21 | |||
85e1b77cae | |||
18e16f8615 | |||
7aa4c18afa | |||
a858103e6b | |||
dfc26395e2 | |||
8cb24547ff | |||
8d83d59cf0 | |||
a0a8026cba | |||
ae9f57ac28 | |||
c266f86b1b | |||
c05bc6a53e | |||
baa094a2d1 | |||
4c10476b15 | |||
3079fd0251 | |||
b9208eb1fb | |||
2ae09f635b | |||
6fe366e1ac | |||
8f1bc5d497 | |||
bb718faa2e | |||
c68ee1d9d9 | |||
2b6a62be77 | |||
3f66600271 | |||
f2404804d7 | |||
07a9c35ee2 | |||
4d9b074641 | |||
e31603fc45 | |||
2795ad674b | |||
2cad7166b1 | |||
3789f4d643 | |||
f87dac7bb2 | |||
5017e61cb2 | |||
f83e5c195c | |||
54ef965b2a | |||
f5dbbea5f5 | |||
3509b26751 | |||
1bb9b3d3ab | |||
6e00ab2069 | |||
93cd00ae8f | |||
c3e66e0adc | |||
6bd43a8215 | |||
d9880de2ef | |||
743d91a670 | |||
fc9a61859a | |||
abbdd7efdd | |||
1c79d43d88 | |||
0573838be3 | |||
158f81b427 | |||
2bffd5cc1c | |||
382488dd07 | |||
808259dccd | |||
6c8fa8ae28 | |||
1f5c901f29 | |||
418d0f12fb | |||
d961b272c7 | |||
72233a509d | |||
e9125af51d | |||
80ac0180b3 | |||
12dfcc9eb6 | |||
1e9e179ec0 | |||
741d061415 | |||
943906cc6b | |||
7b23baa020 | |||
97a1d997e8 | |||
d679fb7546 | |||
c9eb642afd | |||
08e799c35a | |||
5cca4b5e31 | |||
f680a239f7 | |||
13b9fd7b66 | |||
d528fdddfa | |||
fb02071a9d | |||
08673172c7 | |||
9ad0ea85c7 | |||
ba616ed8a7 | |||
31336a0d09 | |||
2d8480d801 | |||
9b3230aa9c | |||
440dd21550 | |||
ceaf969203 | |||
cb91afcc00 | |||
edf4a719d5 | |||
202aef9846 | |||
d7e73705c2 | |||
9afcd72fb6 | |||
53af7f5da8 | |||
2d51622b12 | |||
6124f93cb4 | |||
fb378d9091 | |||
0f7f5362b8 | |||
6cb263fcca | |||
b7b05e729e | |||
023fecabac | |||
6edd4fd9c7 | |||
73305a7425 | |||
899081e1b9 | |||
369a1e1472 | |||
832ad0501a | |||
a3907377f5 | |||
97687f2236 | |||
0bd1c1529e | |||
ff35736bf9 | |||
998dcb421e | |||
878c704597 | |||
49f9605620 | |||
eadb1d310e | |||
e1ef52c7c3 | |||
991483938c | |||
66a1b35767 | |||
0daf695825 | |||
f669677d17 | |||
707faef0f7 | |||
0f2f05fbb9 | |||
9c085799e6 | |||
c26544475e | |||
73a565355b | |||
a5c260352d | |||
461233db09 | |||
3037f45a0c | |||
2bfcd25848 | |||
fd4a441f3a | |||
f9da0f3ece | |||
eabd8ce026 | |||
28d01025b0 | |||
0120585aee | |||
e063c567be | |||
6ab171d629 | |||
635fb5dde4 | |||
3d1502c9ad | |||
89fce7712a | |||
e93464f318 | |||
5fac5c7281 | |||
7aa263d320 | |||
efc2d72d5f | |||
58cafc853f | |||
9354929cad | |||
7170d9009d | |||
646fea5a4e | |||
15d4201c3a | |||
2c8a065b94 | |||
36e9db4c07 | |||
88c4b836f0 | |||
f351a86653 | |||
18f765338c | |||
bf71ddb0b5 | |||
a4c3ee20b2 | |||
6174f1e0ae | |||
6f4cec6465 | |||
a95ecb3ff9 | |||
6f7c63e2a8 | |||
8f26c3a2d4 | |||
12dd6adfcc | |||
6cdd716c34 | |||
b8adfd6948 | |||
cd733c658b | |||
ab58d46a7f | |||
00b92eaa40 | |||
1bc6483608 | |||
9b372f8435 | |||
3bbc0b5d5f | |||
9137eb0757 | |||
c2735286ab | |||
7ea1f4fc91 | |||
84cf7c11e6 | |||
22a21ecfd6 | |||
0794c94b4b | |||
b252be1c7a | |||
0ac7164b16 | |||
f49d590794 | |||
65ce1a7581 | |||
01255c5368 | |||
19f0d7f336 | |||
dce08b4e88 | |||
d9bbe99b83 | |||
d8a25020f1 | |||
6424dc9c82 | |||
205e13d880 | |||
470879c9bf | |||
7b6d76871c | |||
55be0716d8 | |||
01e7ebeb5c | |||
260c5dcf00 | |||
1496eefb8b | |||
59b62eaeba | |||
d30316101a | |||
5227679602 | |||
7b3993730a | |||
18440f612f | |||
b6bcb47deb | |||
9ebd559907 | |||
0c89159cf2 | |||
1a8a04eab8 | |||
b7973ef782 | |||
d23e32622e | |||
c6a5829a92 | |||
c872b120d0 | |||
acd0a8f2d4 | |||
537afbc23b | |||
55cd1f263d | |||
923b1ad9a6 | |||
2c0f91ce50 | |||
ce8d9fa9f4 | |||
002f030970 | |||
dbae667dec | |||
ad6ae20d6b | |||
3e58708130 | |||
8387c08db2 | |||
c9f9f551f4 | |||
c124aae219 | |||
5c24ac604a | |||
90f3cb95d8 | |||
c5f0665853 | |||
b6ecab1d49 | |||
ceddf6f5d8 | |||
c3bbb8905c | |||
78dfcc5f2d | |||
a6237958e8 | |||
9ec40c421f | |||
729ae8bab7 | |||
ac551cf248 | |||
bccc07633c | |||
6f9c4eb8e8 | |||
0b1bdec3ac | |||
e86ff7d988 | |||
d378371cc8 | |||
1e708db26c | |||
d052b1a45f | |||
d6e44c7475 | |||
eac8f639a7 | |||
519f6e2668 | |||
939f3efa3b | |||
6ee484e401 | |||
bb27c76d13 | |||
8a0f5cd7c9 | |||
9d69154da5 | |||
469b24b0a5 | |||
df09b0101a | |||
738e310798 | |||
61e04d5284 | |||
6277787e0a | |||
d2284d5c47 | |||
23a18a8eb6 | |||
2356991022 | |||
17fee801e6 | |||
1ebc101ded | |||
48a99937b9 | |||
053defb7dc | |||
4ae6428641 | |||
425ad6101f | |||
d586a18a16 | |||
ae7d6cc4a2 | |||
467caf347d | |||
5d8568b1a4 | |||
842eb0200e | |||
f9c067db50 | |||
6df983da3e | |||
9d8a70d5cf | |||
65927e6965 | |||
d3f9d1f3e7 | |||
179fb9c7cb | |||
6b7710e62b | |||
c5998a92a8 | |||
c5df2f6f0d | |||
2dee7e9e0f | |||
38cf8d157d | |||
41676cb4d4 | |||
bbc8bc4df5 | |||
e341f3dce2 | |||
76f1ee1827 | |||
b82e00ffdf | |||
9c0ebb6350 | |||
38afe22b79 | |||
2e7e56de1e | |||
2656993223 | |||
fc98f4c42b | |||
44ef9fc577 | |||
c9c6a5dc94 | |||
23269da1a6 | |||
ddc2bed63f | |||
8bc33a849a | |||
390501ec35 | |||
728bc95d73 | |||
acdd0fec5f | |||
f647b1b7a5 | |||
c34a4f45d4 | |||
f882f557fb | |||
242c7e3777 | |||
797aabdf15 | |||
ff5cb84b81 | |||
3e1aa3e2b4 | |||
9c53b41851 | |||
d2082c0383 | |||
1dca9074d5 | |||
82788774b0 | |||
d2768188e8 | |||
5052b75565 | |||
27761ac26e | |||
a756519e6b | |||
49bdd92faa | |||
e9f023fe69 | |||
19614ed25e | |||
f4d07f0c1e | |||
1f54760dae | |||
5d8fa2e126 | |||
cc230034f9 | |||
b9ce6537a8 | |||
8452c7bdbd | |||
2924303169 | |||
9c16caf27b | |||
4f50119b74 | |||
8663be8504 | |||
78cb6445a5 | |||
7d827a1c65 | |||
b1cef8509a | |||
3ae722867c | |||
f0733f6ab6 | |||
f80eeee20f | |||
cdf2f98e26 | |||
532def67ab | |||
d83f024a1f | |||
226db35cf9 | |||
d8d04aeb53 | |||
adc1069ed2 | |||
febf1b1801 | |||
7a4e2371e6 | |||
e1064a9e36 | |||
8ef15d728a | |||
c559dfccfe | |||
60687d8d6c | |||
9840a3c980 | |||
4d15eb3327 | |||
134956ac58 | |||
5806ce9205 | |||
7853076d80 | |||
19fa6f5e8f | |||
6ad405950a | |||
71f123c616 | |||
5bb414620c | |||
171be946c6 | |||
f81bbd60e8 | |||
4a629e1a26 | |||
c6a32ccf2a | |||
ff3d2ba19e | |||
3b183447b0 | |||
8415e49a7f | |||
c6036fb012 | |||
ae497a828f | |||
1e58144a38 | |||
39c0fa6103 | |||
2e5465e328 | |||
7b3115c00c | |||
ac87319aed | |||
aaaddd1fd6 | |||
d86107e22a | |||
498bffb34f | |||
10ac322b8f | |||
23954c4cda | |||
baf278831e | |||
e6381297c7 | |||
3ebd7e8ba6 | |||
f06e67a792 | |||
78a80a6958 | |||
333773bf14 | |||
045868783c | |||
e9d43aa44f | |||
f64cef7eb6 | |||
ab75e89d95 | |||
cf20f0e23a | |||
8564efc011 | |||
b8f8a81704 | |||
ba33d8340a | |||
a6cd9ae029 | |||
2c6381632c | |||
f6983efec1 | |||
9f4bb440bd | |||
02efa93e3a | |||
f313d06070 | |||
0e108341d7 | |||
1520bccf7d | |||
e5cb48bec2 | |||
17e5f60410 | |||
16ffd99005 | |||
b709e21622 | |||
a2e4fdc8a2 | |||
2506947641 | |||
20aaa8373a | |||
3c520aa786 | |||
ebf9cb3e62 | |||
19edacbea9 | |||
c5262fdf61 | |||
e0558d2551 | |||
125cc28aa0 | |||
e92aac847c | |||
ffa733fe0c | |||
a9dc447f8f | |||
d72e4cb9a1 | |||
6dbceda3e8 | |||
7d594ac6d8 | |||
7f0667a1f0 | |||
9fed25d3a5 | |||
8dbeda69a7 | |||
1cac2b098e | |||
39e383a175 | |||
f60d13548e | |||
c53d3c28fb | |||
281d8fd813 | |||
2014ebccd8 | |||
ceef3110d7 | |||
cd5b81bdb9 | |||
8dd2ea22b8 | |||
47e62b1b38 | |||
b50e29085e | |||
05e968d9fd | |||
bfe766e626 | |||
8fc11c6ce0 | |||
8051fa4f6d | |||
9fb365306a | |||
c3623478c1 | |||
302c509b9f | |||
df9534e220 | |||
5936205760 | |||
206f913d2b | |||
c46475ac4a | |||
16006f9175 | |||
a2253e9e7d | |||
ed531c0009 | |||
790ef0325c | |||
c3063ccc44 | |||
650a2eee4b | |||
5024713291 | |||
20f0e344d6 | |||
328ee40d5d | |||
c809365c39 | |||
8fe3f6ef1b | |||
a9a647855b | |||
2ef91f6e2e | |||
d0e2cdb54c | |||
d8ea8fa0f0 | |||
7399e9036a | |||
4698c723bd | |||
7ddcd2941b | |||
fcd81ada04 | |||
0fec58730b | |||
d426d18b77 | |||
1170b66fd5 | |||
3f3bdaeba5 | |||
3af293f024 | |||
b2201c8c59 | |||
d5ae4ad141 | |||
101de7adda | |||
4c848bb4c1 | |||
8b350808ef | |||
98efd27543 | |||
507d47a6f5 | |||
a4e81674c3 | |||
f7ba4f553c | |||
e67b1a20de | |||
20dad95755 | |||
5d7feaaf21 | |||
ddef7bb09b | |||
3fb8029dff | |||
3c86944a7c | |||
45caec874e | |||
3031128520 | |||
e16171e37e | |||
95bf3ab7a8 | |||
2965109484 | |||
3a6af3327f | |||
8b9ec5dde3 | |||
0b03e3c95b | |||
67a5f3f557 | |||
ed8569a3f4 | |||
c201a0e909 | |||
ce7718f0d1 | |||
2a5ab1f397 | |||
6437078c8b | |||
0028ce0ed2 | |||
2a43d9ecb6 | |||
1c9137aa94 | |||
38d419fb29 | |||
6e05b5cc4b | |||
0e87cf801e | |||
652256a109 | |||
e94dd367ef | |||
1b4c65e74d | |||
acd3116591 | |||
4879eac946 | |||
d011fc518e | |||
95be571481 | |||
3760307a88 | |||
a6c31b72ae | |||
7607e484dd | |||
1e8b153662 | |||
e1795dfd49 | |||
f4105fd91a | |||
ff28c982ac | |||
9bb3c93285 | |||
d2513ff908 | |||
0ef81e701a | |||
93131b4d92 | |||
7dd3b5b996 | |||
327c8361bd | |||
f438736af5 | |||
51e13104dc | |||
712cafa0cc | |||
88b3df76eb | |||
c6a160d362 | |||
212d72657a | |||
a7eaec13b9 | |||
2aaac5a425 | |||
011b9ae159 | |||
a49abff099 | |||
90482e79bc | |||
00b567e397 | |||
e9a4acda1d | |||
62db7727c0 | |||
08cf7e489f | |||
742fbc25c3 | |||
159c3a1a91 | |||
bae140dc02 | |||
fb128d0276 | |||
605e7e08ed | |||
e035be8498 | |||
831a35ec69 | |||
517a21c418 | |||
d60c19551b | |||
93b8a6c44a | |||
7642298b4f | |||
39808dd94f | |||
d88b32da91 | |||
20b87b7875 | |||
a2a6286e1c | |||
e7494fff96 | |||
f81849e550 | |||
9284e53f9e | |||
ec5af0398e | |||
7d74ebbebc | |||
70054de575 | |||
cfee0a4e0b | |||
1b572d3e40 | |||
bb286dea91 | |||
39d1196e4c | |||
f671da99a6 | |||
7af7783cc8 | |||
0520598584 | |||
873b64259d | |||
d151a89037 | |||
c96203b528 | |||
acb794e728 | |||
97c836f199 | |||
a944641509 | |||
9901e61d65 | |||
9ac7c75e5b | |||
d583dc25c3 | |||
2e265423c7 | |||
e2af394c81 | |||
9b31484655 | |||
3bb450244f | |||
a653289c40 | |||
24677e1d79 | |||
a0f3c03b50 | |||
6ac0c517f5 | |||
2bc663968e | |||
db9b235aa5 | |||
cc876b0e03 | |||
8d1400115e | |||
e13764832d | |||
7c1432526f | |||
139aaa5577 | |||
82c718cff0 | |||
706082deb1 | |||
36548a335c | |||
5fb7825485 | |||
14ef4558c2 | |||
cdb17b1cee | |||
a430f7f4f7 | |||
9338061390 | |||
785df3789d | |||
7ee4fd55d3 | |||
78bb0145aa | |||
4608ecde9b | |||
495a0b1dc2 | |||
47f43c5e6b | |||
b407eba1a3 | |||
b214601a82 | |||
a273a0c8a9 | |||
0cc4bc48cc | |||
49e47edcf5 | |||
f23bba053b | |||
b0f1863c4f | |||
41f335e7d9 | |||
4d9d4d7c60 | |||
4f421d561c | |||
f787552e97 | |||
65b49dec71 | |||
eaf6b316c7 | |||
050e972add | |||
23132b899c | |||
8a062f440d | |||
77fd57e11a | |||
94936d0f6b | |||
74486d6880 | |||
274a4d892f | |||
1a2312418b | |||
5344c0a627 | |||
8e6a5813ea | |||
594a2041b6 | |||
2600cf5977 | |||
e038c4295d | |||
35d51570be | |||
8910c93de1 | |||
73f1480e10 | |||
0b49ec46c6 | |||
75f364fcf2 | |||
16f2ac14b3 | |||
8a8f1d84ff | |||
e6a1398992 | |||
ac3509aa3d | |||
f2c960cfd8 | |||
ebf5ccea8a | |||
896ecb52f4 | |||
9651b3f470 | |||
a195e940db | |||
a77e05f875 | |||
0b989925d7 | |||
c501c740a1 | |||
3eca64e893 | |||
4f200c5183 | |||
8873efc303 | |||
1427da0aeb | |||
ed1c511c3c | |||
9d2e9e1663 | |||
3edf3a3a80 | |||
02d5f4da85 | |||
a093ba3ed9 | |||
4a7f8fd9d9 | |||
56d9943b0d | |||
a55ab54ddb | |||
eab7424955 | |||
960fdb433e | |||
9b4d82630b | |||
19e68f98a7 | |||
668da0772a | |||
058bd07319 | |||
7da51ae97e | |||
d92e79ba54 | |||
0f33459632 | |||
d291345ed7 | |||
caca097300 | |||
dbe0ee2d44 | |||
ef038d9625 | |||
48a5eeb3a4 | |||
a80d5bb6a8 | |||
01f12d6147 | |||
c721503b7a | |||
31e4093882 | |||
8aab51c532 | |||
1bb4daa7d1 | |||
f7f06c993d | |||
ed8b8a13a3 | |||
54e19a6d2f | |||
932705e114 | |||
0e5cbca983 | |||
db2567f965 | |||
b660bcdb65 | |||
1f3c0524d9 | |||
d4580fa683 | |||
8ad57f7ca0 | |||
2b8405e6ee | |||
f488e594f6 | |||
65684eec99 | |||
0406c49ba9 | |||
3b772f54e9 | |||
fee42e9f34 | |||
c0962a47be | |||
54342ab0ce | |||
778eb5fb33 | |||
e0574008b4 | |||
653fa1213e | |||
535d4e2c9b | |||
ebc1524f9a | |||
dd2861dd1a | |||
e50ba18bbd | |||
b3902ed76f | |||
f03ab76c83 | |||
37190c9a65 | |||
d62e00cc74 | |||
5ce2d5e072 | |||
0d152a2139 | |||
3bd224ae1a | |||
bd091eb744 | |||
f218868338 | |||
99fb267333 | |||
034472bfe7 | |||
bc7cefff77 | |||
71ece194e4 | |||
9553df0f03 | |||
5b75c5953f | |||
b2c0bba86e | |||
cf7071de3d | |||
9b49d09714 | |||
91064b3209 | |||
66e46e1c07 | |||
b99decc585 | |||
fa77a4fa58 | |||
5d1ec1ad49 | |||
3b62926721 | |||
4fb1f8dd76 | |||
d6376a236d | |||
286e062086 | |||
b5aa80b375 | |||
f830eddd59 | |||
ac8565fc2e | |||
358d8b7af7 | |||
848bce193c | |||
7c41bfcdf3 | |||
92aeab0d00 | |||
475ec413e5 | |||
b629738312 | |||
aa55cd9acf | |||
1177a381c8 | |||
3a1f0eca7c | |||
9ad30e239a | |||
06d7ee283d | |||
a306421737 | |||
f8e3b0b16b | |||
bbd878986d | |||
44daf57fbb | |||
2438d20971 | |||
24d0102ffb | |||
718ca40379 | |||
d32b9ec5dc | |||
2ee0436f46 | |||
30fcfac8cf | |||
728142b113 | |||
b3d8d10bec | |||
d8198d8130 | |||
cef1fe9524 | |||
0ae9b41062 | |||
ce58294305 | |||
0273e2484e | |||
4b7300de8d | |||
59a51a6c75 | |||
f2fd505bae | |||
78671bafe3 | |||
15bac8c58a | |||
22c8077bdf | |||
078a2486b5 | |||
dbf5d9e985 | |||
10f14beb4b | |||
0d9968f305 | |||
9c94ebcf82 | |||
82bd6c5b34 | |||
d3fa8e0a0a | |||
ec9ef891ee | |||
16b789a528 | |||
55ac1c80c9 | |||
12a7436aea | |||
202fb08792 | |||
3fa9712a1e | |||
bd993b2342 | |||
4597899ac3 | |||
e5b69deccf | |||
4142666df8 | |||
fb0cc0804c | |||
ff6d590d0c | |||
c90e3e351d | |||
6fcb221453 | |||
90f80782d4 | |||
ea9415961b | |||
5df56a1bac | |||
d81388f62c | |||
ac832f94a8 | |||
a5383b4a82 | |||
25660843c5 | |||
905c0c825c | |||
83077309ef | |||
20f3b82d52 | |||
779d92c656 | |||
2cb6307e5b | |||
2170411cf8 | |||
425b1aa6f5 | |||
588d6c4b26 | |||
0e44e5b681 | |||
10ba3d6359 | |||
e43496e7e4 | |||
7560880168 | |||
c345e6f22c | |||
af6b279e54 | |||
809b33033e | |||
1ef538b69e | |||
47cf6e4833 | |||
32a78e679a | |||
488c03c200 | |||
2bf6764112 | |||
62cb7963dc | |||
4e8a256a53 | |||
58b46179f9 | |||
0d9952d53e | |||
d26631d8e0 | |||
cab2d52ff8 | |||
fd3456e831 | |||
14f144b6f6 | |||
bdd42d6a78 | |||
2647b3f404 | |||
7541a6070f | |||
f3cf64c2cf | |||
df45e8a2cc | |||
eb738d1d72 | |||
edb03e8a9b | |||
20a5b75622 | |||
c3bc751b04 | |||
be37236c76 | |||
e016693779 | |||
d305a1342f | |||
b9769c407b | |||
522f0f5c25 | |||
7e81a09409 | |||
e6cbdd090e | |||
203d7e23f4 | |||
057d4fc62f | |||
98b34aaac8 | |||
7f87714dae | |||
c09a774da7 | |||
4059e1f84c | |||
622fe99982 | |||
cc84ec8629 | |||
fe1df70923 | |||
c1843ac2d4 | |||
85105ed066 | |||
a86d3fe071 | |||
b93318b2cf | |||
ca1a0c8643 | |||
57e5b1309d | |||
34d64be427 | |||
dc29b4dc3f | |||
01a9e53394 | |||
c5bf746e4c | |||
7d8624b12f | |||
da876cc8f3 | |||
d6e61e3e00 | |||
b9cd96f6e0 | |||
25a5394152 | |||
bfc372c6fb | |||
c257a791e1 | |||
59f6821c29 | |||
30c044f028 | |||
015ee90571 | |||
f626b9e8a0 | |||
97a1483f75 | |||
a4939b6bf1 | |||
7633136a86 | |||
3cd105ff33 | |||
0fecb79add | |||
aae19d45b7 | |||
57a86d9ed7 | |||
25cfcada26 | |||
e16f20affa | |||
08621604cd | |||
cdcafb1e75 | |||
64ecc373be | |||
bdd9a7eb52 | |||
85647c03bf | |||
f969f3b77f | |||
bf4c6e4c2b | |||
f77ab468e3 | |||
424e9f4a49 | |||
1144620f2b | |||
e57dd3e8ba | |||
36e197e2a9 | |||
4d1e2d1b3a | |||
965f0d670d | |||
bc9a387b0b | |||
df3870a112 | |||
f47d6ee683 | |||
73afa22f50 | |||
ddc118a562 | |||
1f023bdcef | |||
70f874a559 | |||
e502280b20 | |||
4962d9df97 | |||
340de1c478 | |||
fbbb6f3beb | |||
25022b3144 | |||
599a64c80c | |||
ee5165b040 | |||
83065024f7 | |||
33ad4de981 | |||
eb8eac42b8 | |||
80ebc0bc5f | |||
46ea0186e4 | |||
9c80e349ce | |||
258b4f9dde | |||
78d27dc3e4 | |||
7e7cd6c995 | |||
b23c947060 | |||
4ccbb8b21a | |||
120eb8e362 | |||
2907de81ad | |||
950465d283 | |||
2bba3a0805 | |||
fbd4f4a849 | |||
399870bf31 | |||
2252f7498d | |||
5dc4e17a96 | |||
49bca0d5a1 | |||
3846ee3d1d | |||
d49a41f788 | |||
4a11ded185 | |||
fc8dc8a497 | |||
cfee9aa117 | |||
884ebe632d | |||
d67149376d | |||
78aa1ee22e | |||
f60b0e5cc7 | |||
9a6a5e2088 | |||
23085bf9b3 | |||
0948c65276 | |||
2308eadf53 | |||
eddd626461 | |||
8a65941489 | |||
99a0c2a188 |
8
.github/FUNDING.yml
vendored
Normal file
8
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: pocketminemp
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: https://github.com/pmmp/PocketMine-MP#donate
|
48
.github/ISSUE_TEMPLATE.md
vendored
48
.github/ISSUE_TEMPLATE.md
vendored
@ -1,48 +0,0 @@
|
||||
### Issue description
|
||||
<!---
|
||||
THIS ISSUE TRACKER IS FOR BUG REPORTING, NOT FOR HELP & SUPPORT. If you need help, use the links below.
|
||||
- http://pmmp.readthedocs.io/en/rtfd/ - Documentation
|
||||
- https://forums.pmmp.io - PMMP Forums
|
||||
|
||||
Any issues requesting updates to new versions of MCPE will be treated as spam.
|
||||
Please do not create issues for missing/un-implemented gameplay features - they will be closed.
|
||||
-->
|
||||
|
||||
<!--- Write a short description about the issue -->
|
||||
|
||||
<!--- If you are reporting a regression or unexpected behaviour, please include the below information: -->
|
||||
- Expected result: What were you expecting to happen?
|
||||
- Actual result: What actually happened?
|
||||
|
||||
### Steps to reproduce the issue
|
||||
<!--- help us find the problem by adding steps to reproduce the issue -->
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
### OS and versions
|
||||
<!--- use the 'version' command in PocketMine-MP
|
||||
|
||||
NOTE: LATEST is not a valid version. PocketMine-MP version should include Jenkins build number and/or git commit hash.
|
||||
|
||||
NO support whatsoever will be provided for third-party modified variants of PocketMine-MP. Issues relating to third-party modifications will be closed as spam.
|
||||
|
||||
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
|
||||
-->
|
||||
* PocketMine-MP: <!-- LATEST IS NOT A VALID VERSION -->
|
||||
* PHP:
|
||||
* Server OS:
|
||||
* Game version: PE/Win10 (delete as appropriate)
|
||||
|
||||
### Plugins
|
||||
- Test on a clean server without plugins: is the issue reproducible without any plugins loaded?
|
||||
|
||||
If the issue is **not** reproducible without plugins:
|
||||
- Have you asked for help on our forums before creating an issue?
|
||||
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
|
||||
- Paste your list of plugins here (use the 'plugins' command in PocketMine-MP)
|
||||
|
||||
### Crashdump, backtrace or other files
|
||||
- Do not paste crashdumps into an issue - please use our Crash Archive at https://crash.pmmp.io for submitting crash reports to not spam the issue tracker. Add links to your reports in the Crash Archive here.
|
||||
- Please use gist or anything else to add other files and add links here
|
||||
|
||||
* ...
|
19
.github/ISSUE_TEMPLATE/api-change-request.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE/api-change-request.md
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
name: API change request
|
||||
about: Suggest a change, addition or removal to the plugin API
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--- tell us what you want -->
|
||||
## Description
|
||||
|
||||
|
||||
<!--- explain why you want this and why it's a good idea -->
|
||||
## Justification
|
||||
|
||||
|
||||
<!--- (optional) describe alternative methods you've explored to achieve your goal -->
|
||||
## Alternative methods
|
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Unexpected non-crash behaviour (except missing gameplay features)
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Issue description
|
||||
|
||||
- Expected result: What were you expecting to happen?
|
||||
- Actual result: What actually happened?
|
||||
|
||||
### Steps to reproduce the issue
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
### OS and versions
|
||||
<!-- try the `version` command | LATEST IS NOT A VALID VERSION -->
|
||||
* PocketMine-MP:
|
||||
* PHP:
|
||||
* Server OS:
|
||||
* Game version: PE/Win10 (delete as appropriate)
|
||||
|
||||
### Plugins
|
||||
<!--- use the `plugins` command and paste the output below -->
|
||||
|
||||
- If you remove all plugins, does the issue still occur?
|
||||
- If the issue is **not** reproducible without plugins:
|
||||
- Have you asked for help on our forums before creating an issue?
|
||||
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
|
||||
|
||||
### Crashdump, backtrace or other files
|
||||
<!--- Submit crashdumps at https://crash.pmmp.io and paste a link -->
|
||||
<!--- Use gist or anything else to add other files and add links here -->
|
15
.github/ISSUE_TEMPLATE/crash.md
vendored
Normal file
15
.github/ISSUE_TEMPLATE/crash.md
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
name: Crash
|
||||
about: Report a crash in PocketMine-MP (not plugins)
|
||||
title: Server crashed
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--- submit crashdump files to https://crash.pmmp.io -->
|
||||
<!--- or, copy the data between ===BEGIN CRASH DUMP=== and ===END CRASH DUMP and paste it on a site like https://pastebin.com -->
|
||||
Link to crashdump:
|
||||
|
||||
<!--- write additional information about the crash to help us find the problem -->
|
||||
### Additional comments (optional)
|
14
.github/ISSUE_TEMPLATE/help---support.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE/help---support.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
name: Help & support
|
||||
about: We don't accept support requests here. Try the links on the README.
|
||||
title: ''
|
||||
labels: Support request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
We don't accept support requests on the issue tracker. Please try the following links instead:
|
||||
|
||||
Documentation: http://pmmp.rtfd.io
|
||||
Forums: https://forums.pmmp.io
|
||||
Discord: https://discord.gg/bge7dYQ
|
12
.github/ISSUE_TEMPLATE/security-dos-vulnerability.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE/security-dos-vulnerability.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
name: Security/DoS vulnerability
|
||||
about: 'Bug or exploit that can be used to attack servers (hint: don''t report it
|
||||
on a public issue tracker)'
|
||||
title: ''
|
||||
labels: 'Auto: Spam'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please DO NOT report security vulnerabilities here.
|
||||
Instead, send an email to team@pmmp.io or contact a developer directly, IN PRIVATE.
|
6
.github/support.yml
vendored
6
.github/support.yml
vendored
@ -5,7 +5,11 @@ supportLabel: "Support request"
|
||||
# Comment to post on issues marked as support requests. Add a link
|
||||
# to a support page, or set to `false` to disable
|
||||
supportComment: >
|
||||
This issue tracker is not a support forum. Please use the [forums](https://forums.pmmp.io) for support.
|
||||
Thanks, but this issue tracker 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).
|
||||
|
||||
|
||||
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bge7dYQ) | [Forums](https://forums.pmmp.io)
|
||||
|
||||
# Whether to close issues marked as support requests
|
||||
close: true
|
||||
# Whether to lock issues marked as support requests
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
players/*
|
||||
worlds/*
|
||||
world_conversion_backups/*
|
||||
plugin_data/*
|
||||
plugins/*
|
||||
bin*/*
|
||||
@ -10,8 +11,10 @@ crashdumps/*
|
||||
*.phar
|
||||
server.properties
|
||||
/pocketmine.yml
|
||||
/plugin_list.yml
|
||||
memory_dumps/*
|
||||
resource_packs/
|
||||
server.lock
|
||||
|
||||
# Common IDEs
|
||||
.idea/
|
||||
|
10
.gitmodules
vendored
10
.gitmodules
vendored
@ -1,12 +1,12 @@
|
||||
[submodule "src/pocketmine/lang/locale"]
|
||||
path = src/pocketmine/lang/locale
|
||||
[submodule "resources/locale"]
|
||||
path = resources/locale
|
||||
url = https://github.com/pmmp/PocketMine-Language.git
|
||||
[submodule "tests/preprocessor"]
|
||||
path = tests/preprocessor
|
||||
path = build/preprocessor
|
||||
url = https://github.com/pmmp/preprocessor.git
|
||||
[submodule "tests/plugins/PocketMine-DevTools"]
|
||||
path = tests/plugins/PocketMine-DevTools
|
||||
url = https://github.com/pmmp/PocketMine-DevTools.git
|
||||
[submodule "src/pocketmine/resources/vanilla"]
|
||||
path = src/pocketmine/resources/vanilla
|
||||
[submodule "resources/vanilla"]
|
||||
path = resources/vanilla
|
||||
url = https://github.com/pmmp/BedrockData.git
|
||||
|
21
.travis.yml
21
.travis.yml
@ -1,3 +1,4 @@
|
||||
dist: xenial
|
||||
language: php
|
||||
|
||||
php:
|
||||
@ -5,8 +6,26 @@ php:
|
||||
- 7.3
|
||||
|
||||
before_script:
|
||||
- LEVELDB_VERSION=f1463cb0b2486b0caf7d42ca3c7684545e875f04
|
||||
- curl -fsSL "https://github.com/pmmp/leveldb-mcpe/archive/f1463cb0b2486b0caf7d42ca3c7684545e875f04.tar.gz" | tar -zx
|
||||
- mv leveldb-mcpe-$LEVELDB_VERSION leveldb-mcpe
|
||||
- cd leveldb-mcpe && make -j4 && mv out-shared/libleveldb.* . && cd ..
|
||||
- git clone https://github.com/reeze/php-leveldb.git leveldb
|
||||
- cd leveldb
|
||||
- git checkout 9bcae79f71b81a5c3ea6f67e45ae9ae9fb2775a5
|
||||
- phpize
|
||||
- ./configure --with-leveldb=../leveldb-mcpe && make && make install
|
||||
- cd ..
|
||||
- git clone https://github.com/pmmp/ext-chunkutils2.git chunkutils
|
||||
- cd chunkutils
|
||||
- git checkout d8d762a597ac0da6f333f862096d6af0e6286b75
|
||||
- phpize
|
||||
- ./configure && make && make install
|
||||
- cd ..
|
||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
||||
- pecl install channel://pecl.php.net/crypto-0.3.1
|
||||
- pecl install channel://pecl.php.net/ds-1.2.8
|
||||
- git clone https://github.com/pmmp/pthreads.git
|
||||
- cd pthreads
|
||||
- git checkout 6ca019c58b4fa09ee2ff490f2444e34bef0773d0
|
||||
@ -16,6 +35,8 @@ before_script:
|
||||
- make install
|
||||
- cd ..
|
||||
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
- echo "extension=chunkutils2.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
- echo "extension=leveldb.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
- composer install
|
||||
|
||||
script:
|
||||
|
49
README.md
49
README.md
@ -1,45 +1,32 @@
|
||||
# [](https://pmmp.io)
|
||||
|
||||
__A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP__
|
||||
<p align="center">
|
||||
<a href="https://pmmp.io"><img src="http://cdn.pocketmine.net/img/PocketMine-MP-h.png"></img></a><br>
|
||||
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
||||
</p>
|
||||
|
||||
[](https://travis-ci.org/pmmp/PocketMine-MP)
|
||||
|
||||
### Setup, help & support, FAQs
|
||||
Head over to the [documentation site](http://pmmp.readthedocs.org/).
|
||||
If you don't find what you're looking for there, [talk to a human](#discussion). Please do not use our issue tracker for support requests.
|
||||
### Getting started
|
||||
- [Documentation](http://pmmp.readthedocs.org/)
|
||||
- [Installation instructions](https://pmmp.readthedocs.io/en/rtfd/installation.html)
|
||||
- [Docker image](https://hub.docker.com/r/pmmp/pocketmine-mp)
|
||||
- [Plugin repository](https://poggit.pmmp.io/plugins)
|
||||
|
||||
### Discussion
|
||||
- [Forums](https://forums.pmmp.io/)
|
||||
|
||||
### Plugins
|
||||
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [Poggit](https://poggit.pmmp.io), or just search GitHub.
|
||||
- [Community Discord](https://discord.gg/bge7dYQ)
|
||||
|
||||
### For developers
|
||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
||||
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - A development tools plugin for creating plugins.
|
||||
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
|
||||
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||
* [Contributing Guidelines](CONTRIBUTING.md)
|
||||
|
||||
### Can I contribute?
|
||||
Yes you can! Contributions are welcomed provided that they comply with our [Contributing Guidelines](CONTRIBUTING.md). Please ensure you read the relevant sections of the guidelines carefully before making a Pull Request or opening an Issue.
|
||||
|
||||
### Where can I get the latest .phar?
|
||||
- Latest release builds can be found in our [GitHub releases](https://github.com/pmmp/PocketMine-MP/releases).
|
||||
- Latest bleeding-edge development builds (and other builds in the build job channels) can be found on our [Jenkins server](https://jenkins.pmmp.io/).
|
||||
|
||||
**Note: Please avoid development builds unless there is no other alternative for what you need.** Development builds are subject to changes at any time without notice, and it is likely that your server or plugins might break without warning.
|
||||
### Donate
|
||||
- Bitcoin Cash (BCH): `qq3r46hn6ljnhnqnfwxt5pg3g447eq9jhvw5ddfear`
|
||||
- Bitcoin (BTC): `171u8K9e4FtU6j3e5sqNoxKUgEw9qWQdRV`
|
||||
- [Patreon](https://www.patreon.com/pocketminemp)
|
||||
|
||||
## Licensing information
|
||||
|
||||
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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
This project is licensed under LGPL-3.0. Please see the [LICENSE](/LICENSE) file for details.
|
||||
|
||||
pmmp/PocketMine are not affiliated with Mojang. All brands and trademarks belong to their respective owners. PocketMine-MP is not a Mojang-approved software, nor is it associated with Mojang.
|
||||
|
81
build/make-release.php
Normal file
81
build/make-release.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?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_script;
|
||||
|
||||
use pocketmine\utils\VersionString;
|
||||
use function dirname;
|
||||
use function fgets;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function preg_quote;
|
||||
use function preg_replace;
|
||||
use function sleep;
|
||||
use function sprintf;
|
||||
use function system;
|
||||
use const pocketmine\BASE_VERSION;
|
||||
use const STDIN;
|
||||
|
||||
require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
if(isset($argv[1])){
|
||||
$currentVer = new VersionString($argv[1]);
|
||||
}else{
|
||||
$currentVer = new VersionString(BASE_VERSION);
|
||||
}
|
||||
$nextVer = new VersionString(sprintf(
|
||||
"%u.%u.%u",
|
||||
$currentVer->getMajor(),
|
||||
$currentVer->getMinor(),
|
||||
$currentVer->getPatch() + 1
|
||||
));
|
||||
|
||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{
|
||||
$versionInfo = file_get_contents($versionInfoPath);
|
||||
$versionInfo = preg_replace(
|
||||
$pattern = '/^const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
||||
'const BASE_VERSION = "' . $newVersion . '";',
|
||||
$versionInfo
|
||||
);
|
||||
$versionInfo = preg_replace(
|
||||
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
|
||||
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';',
|
||||
$versionInfo
|
||||
);
|
||||
file_put_contents($versionInfoPath, $versionInfo);
|
||||
}
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
|
||||
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
||||
system('git tag ' . $currentVer->getBaseVersion());
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
|
||||
system('git add "' . $versionInfoPath . '"');
|
||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
||||
echo "pushing changes in 10 seconds\n";
|
||||
sleep(10);
|
||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
1
build/preprocessor
Submodule
1
build/preprocessor
Submodule
Submodule build/preprocessor added at 4d4d2a74a6
182
changelogs/1.3.md
Normal file
182
changelogs/1.3.md
Normal file
@ -0,0 +1,182 @@
|
||||
# 1.3.3
|
||||
- Minecraft: Pocket Edition alpha 0.7.2 compatible!
|
||||
- Unicode support
|
||||
- Fixed /difficulty command
|
||||
- Fixed a few flying kicks
|
||||
- Fixed async. operations thread
|
||||
- Added whitelist enabled property to Query
|
||||
|
||||
# 1.3.4
|
||||
**This is a compatibility update for Minecraft: Pocket Edition v0.7.3 alpha.**
|
||||
|
||||
Double chests do not work yet, we will fix more bugs and add them when MCPE 0.7.4 is released. There were too many bugs in 0.7.3 to test double chests properly.
|
||||
|
||||
#### Including in this release:
|
||||
- Fixed armor crash
|
||||
- Fixed ghost armor
|
||||
- Fixed packets being received after player disconnection
|
||||
- Fixed player count bug
|
||||
- Added compatibility with encrypted login
|
||||
- Fixed flying check on fences
|
||||
- Fixed players connecting with empty usernames
|
||||
- Fixed several crashes related to Items
|
||||
- Added temporal water flowing. Really buggy
|
||||
- Automatic recovery of index-corrupted maps
|
||||
- Fixed hotbar reset when changing armor
|
||||
- Fixed some hotbar reset bugs on block placement
|
||||
- Added basic tool durability and breaking
|
||||
- Chests now have opening/closing animation.
|
||||
- Fixed /difficulty
|
||||
- In-game player list is now handled correctly
|
||||
- Player entities are saved in all worlds to remove join/leave spam
|
||||
- Quartz slabs
|
||||
|
||||
# 1.3.5
|
||||
#### Including in this release:
|
||||
- Fixed block durability (blocks being replaced)
|
||||
- Added armor replacing (changing the armor while you have other)
|
||||
- Added proper Player object cleanups as a fix to a memory leak
|
||||
|
||||
# 1.3.7
|
||||
**This update is compatible with Minecraft: Pocket Edition v0.7.4 alpha.** Older versions won't work.
|
||||
|
||||
In Minecraft: PE 0.7.4 you can add External servers directly. [How to add servers](https://github.com/PocketMine/PocketMine-MP/wiki/How-to-add-servers)
|
||||
|
||||

|
||||
|
||||
### Changelog
|
||||
- **Updated for 0.7.4 alpha**
|
||||
- **New API version 10**
|
||||
- Adds Tile methods
|
||||
- Changes message events to use new Minecraft protocol
|
||||
- Added Level::getSafeSpawn()
|
||||
- Linux now uses PHP 5.5.3
|
||||
- Removed water updating
|
||||
- Fixes for Player teleporting
|
||||
- Removed invalid Cookie and fish items
|
||||
- Fixed Stone brick and quartz slab recipes
|
||||
- Shears now are used to drop leaves
|
||||
- Fixed a crash on Windows XP
|
||||
- Cake is removed when the bottom block is broken
|
||||
- Added new NBT parser/writer
|
||||
- Fixed chests and furnaces drops when broken.
|
||||
- Fixed signs not spawning on world load
|
||||
- Fixed actions not being deleted (memory leak)
|
||||
- Chests now are spawned correctly
|
||||
- Double chests
|
||||
- Added random x,z offset to item drops
|
||||
|
||||
# 1.3.8
|
||||
This release consists of a few bugfixes and several features added. It is compatible with MCPE 0.7.4 and 0.7.5
|
||||
|
||||
**Changelog:**
|
||||
- No API changes
|
||||
- Fixed x,y,z indexes when opening a Furnace
|
||||
- Fixed invalid fix for CPU usage limiter on idle
|
||||
- Fixed cross-compiling
|
||||
- Fixed some Stonecutter recipes
|
||||
- Fixed a few items stack sizes
|
||||
- Fixed TimeAPI bugs
|
||||
- Forces position on teleport, blocks fast teleport mods
|
||||
- Fixed some blocks havin a send lag on place/break
|
||||
- Fixed Sign Posts not deleting the Tile data when broken by update
|
||||
- Fixed Ice converting to Water on creative mode
|
||||
- Added beds
|
||||
- Added scheduled teleport on spawn to fix spawning underground
|
||||
- Added date to console logs
|
||||
|
||||
# 1.3.9
|
||||
This release is compatible with MCPE 0.7.4 and 0.7.5.
|
||||
|
||||
**Changelog:**
|
||||
- Fixed server crash related to beds
|
||||
- Player movement is less laggy
|
||||
- Added new text formatting system for future updates
|
||||
- New Terminal Emulator for Windows
|
||||
- More colors! Less warnings!
|
||||
|
||||
# 1.3.10
|
||||
**Changelog:**
|
||||
- Added door sounds
|
||||
- Fixed bed sleeping position offset
|
||||
- Added explosions
|
||||
- Flint & Steel on Creative Mode (replaces Eggs)
|
||||
- Changed the Sword and Hoe to the diamond tier on the Creative inventory
|
||||
- Fixed colors on MacOS
|
||||
- Water flow
|
||||
- Fixed Windows console input not being accepted when using special keys
|
||||
- Added a way to disable console colors
|
||||
- Updated PHP to 5.5.6, pthreads to 0.0.55, and cURL
|
||||
- Armor drops
|
||||
- Fixed plugin issues
|
||||
- Fixed some block drops
|
||||
- Fixed a crash when @all is used in console, and only usable for OPs
|
||||
- Fixed some issues regarding teleporting
|
||||
- deop no longer op the player again
|
||||
|
||||
# 1.3.11
|
||||
And here it comes the stable release for **MCPE v0.8.1 alpha**. We decided to remove the improved networking that was delaying this release, but you should see it in the next one. Minecarts couldn't be added for the same reason as mobs, but we will try to implement "fake" minecarts that behave correctly inside rails, but not outside of them.
|
||||
|
||||
Starting with this release, all PocketMine-MP versions will be given a codename. This one received the codename 「甘いビートルート」_(Amai Beetroot)_.
|
||||
|
||||
**Changelog:**
|
||||
- Fixed existing Packets of Death
|
||||
- Fixed lots of bugs related to crafting
|
||||
- Fixed block placement bugs
|
||||
- Redstone ore drops redstone dust
|
||||
- Sideway logs
|
||||
- Sponges
|
||||
- Added new wooden planks & stairs
|
||||
- Added iron bars, cobblestone walls and pumpkins
|
||||
- Added carpets, hay bales and coal blocks
|
||||
- Added potatoes, carrots and beetroots
|
||||
- Additional tall grass drops
|
||||
- Achievements
|
||||
- Added multiple orders for _/gamemode_ command
|
||||
- Chat plugins can work with each other #975
|
||||
- Fixed internal world chunks bug
|
||||
- Private messages are now hidden on console except when the console is the target/origin
|
||||
- PHP plugins are now loaded with include()
|
||||
- Fixed plugin paths
|
||||
- Added source SHA1 sum to crash reports
|
||||
- Added Level::startTime() and Level::stopTime()
|
||||
- Fixed server not being able to start on several OS when offline
|
||||
- More small fixes and small additions
|
||||
|
||||
For more information, check the [complete changelog](https://github.com/PocketMine/PocketMine-MP/compare/Alpha_1.3.10...Alpha_1.3.11).
|
||||
|
||||
# 1.3.12
|
||||
Before starting to rewrite even more parts of the code, we are releasing the last version of the Alpha_1.3.x Amai Beetroot「甘いビートルート」. Next one will be Alpha_1.4 with more rewrite!
|
||||
We have included the new Event API that will be used on the next release, but now it is only used to hook on packets.
|
||||
|
||||
**API Changelog:**
|
||||
- **Full network rewrite.** Plugins can work with packets easily now.
|
||||
- **New Event API,** only implemented for packets right now.
|
||||
- Added player.block.place.bypass and player.block.break.bypass
|
||||
- Level included in data for event item.drop
|
||||
- Added Utils::getUniqueID()
|
||||
- **Added default support in PHP binaries for MySQLi**
|
||||
- Removed Spyc
|
||||
- Call Plugin::__destruct() on PluginAPI::__destruct()
|
||||
- Added more OS detection on Utils::getOS()
|
||||
|
||||
**Changelog:**
|
||||
- New set-up wizard in multiple languages. Help translate it to more languages on http://translate.pocketmine.net/
|
||||
- Updated pthreads and PHP binaries
|
||||
- New font for MinTTY console on Windows
|
||||
- Send partial hotbar history
|
||||
- Fixed Tile saving indexes
|
||||
- Fixed a few teleport bugs
|
||||
- Improved crash dumps
|
||||
- Increased apple health restore
|
||||
- Fixed players being invincible after death
|
||||
- Fixed Level::unloadChunk() not using saveEnabled
|
||||
- Show player name on bad username kick
|
||||
- Fixed item duplication on void #1100
|
||||
- OPs can bypass the player limit
|
||||
- Fixed item replacing on furnace #1114
|
||||
- Fixed multiple small bugs #1058 #1032 #854 #823 #1135 #1150 #1172 #1173 #486 #466 #483
|
||||
- Fixed PHP compilation on 64-bit linux #519 #861 #940 #505 #590 #761 #129
|
||||
- Included OPCache to optimize opcodes
|
||||
|
||||
If you are on Linux, you can use `wget -q -O - http://cdn.pocketmine.net/installer.sh | bash -s - -v Alpha_1.3.12` to update. If you are on a MacOS, use `curl -sL http://cdn.pocketmine.net/installer.sh | bash -s - -v Alpha_1.3.12`
|
1278
changelogs/1.4.md
Normal file
1278
changelogs/1.4.md
Normal file
File diff suppressed because it is too large
Load Diff
72
changelogs/1.6.md
Normal file
72
changelogs/1.6.md
Normal file
@ -0,0 +1,72 @@
|
||||
# 1.6.1dev-87
|
||||
**For Minecraft PE 0.16.0.5 alpha**
|
||||
|
||||
**THIS IS A PRE RELEASE. Do not use it in production unless you are sure you know what you are doing.**
|
||||
|
||||
Only changes since the 1.6dev tag will be documented here. Changes between 1.4.1 and 1.6dev are far too extensive to document effectively.
|
||||
|
||||
## Core
|
||||
- New RNG, based on XorShift128 from the php-random library. This fixes issue with repeating terrain on 32-bit systems. _Note however that new generation into existing worlds will not be seamless._
|
||||
- Block and Item IDs have been moved to interfaces for better consistency
|
||||
- Better method for synchronisation of client/server time (less packet spam)
|
||||
- Utils::getRandomBytes() has been deprecated in favour of php7's random_bytes() function.
|
||||
- `<player>.dat` saving/reading can now be disabled in `pocketmine.yml` (set `player.save-player-data` to `false`)
|
||||
|
||||
## Gameplay/game features
|
||||
- Added Flower Pots
|
||||
- Containers can now be opened in creative
|
||||
- Trapdoors can now be placed without a supporting block
|
||||
|
||||
## API
|
||||
|
||||
This release has API changes, bumping the version to 2.1.0.
|
||||
|
||||
### Entity metadata (0.16)
|
||||
|
||||
Many changes have been made to entity metadata. Many true/false data properties are now entity status flags, such as NoAI, NametagVisible and various others. Entity status flags can be set using:
|
||||
`$entity->setDataFlag(Entity::DATA_FLAGS, Entity::INSERT_DATA_FLAG_NAME, true/false);`
|
||||
|
||||
**Breaking** changes are detailed here. Additions are not documented. https://gist.github.com/dktapps/76b291b7a861762b54f7a8b834389883
|
||||
|
||||
**NOTE: It's strongly recommended to use provided API methods where possible instead of tampering with metadata directly.**
|
||||
|
||||
### AsyncTask API additions
|
||||
- Main thread local storage: Developers can pass any data including objects to the constructor of AsyncTask such that the data can be retrieved after the AsyncTask completes using the new `AsyncTask::fetchLocal()` method, or use the `AsyncTask::peekLocal()` method to get the data without removing it.
|
||||
- Progress updates: Developers can use the new `AsyncTask::publishProgress() method and override`AsyncTask::onProgressUpdated()` to handle AsyncTask progress information in the main thread.
|
||||
|
||||
Refer to #1 and #100 for details.
|
||||
|
||||
### WeakPosition
|
||||
|
||||
WeakPosition was added in 1.6.1 to fix bugs with unloading levels which have player spawn points set in them. This type of position holds a level ID instead of a direct reference. Use this when your position may outlive the level it is in.
|
||||
|
||||
### Removal of Item/NBT circular dependency
|
||||
|
||||
Refer to #121 for details.
|
||||
|
||||
### Other
|
||||
- Added Player->sendWhisper() (#73).
|
||||
- Removed LargeExplodeParticle due to incorrect name - use HugeExplodeParticle. Added HugeExplodeSeedParticle and BlockForceFieldParticle (7314aaf7f7bdae582f674c085c7ae879985bf847)
|
||||
|
||||
## Fixes
|
||||
- Fixed the infamous hotbar spaz bug
|
||||
- Creative/spectator inventory now sends correctly
|
||||
- Fixed spectator flight controls
|
||||
- Fixed issues with items going past the end of the regular inventory
|
||||
- Fixed furnace client crashes
|
||||
- Fixed inventory windows for anvils and enchanting tables
|
||||
- Fixed kicked for walking on lily pads (#blameshoghicp)
|
||||
- Fixed a nasty entity-related memory leak on chunk unload
|
||||
- Fixed sleeping players floating above beds and teleportation of sleeping players.
|
||||
- Fixed a bug in Level::updateAround() where only one block would update
|
||||
- Fixed some slab placement issues (#31)
|
||||
- Fixed crash loading 1.11 worlds (#32)
|
||||
- Fixed broken `--disable-readline` command-line option (#34)
|
||||
- Fixed world unload crash when players have spawnpoints set in that world (#24)
|
||||
- Fixed start.sh detection of system PHP binaries (#66)
|
||||
- Fixed anvil rotation when placed and variant drops (d696049a0ad5e3b878a8f902e4ef75f19ec8cecc)
|
||||
- /timings command is now more verbose about paste errors (#95)
|
||||
- Fixed server crash at shutdown when RCON is enabled (#101)
|
||||
- Fixed server name is always "Minecraft: PE Server" when running setup wizard (92bd1a755d4b171b687538db83893b9bd9c70420)
|
||||
- Fixed CraftItemEvent->getInput() does not return used items (7eb9530346e953d1555623ff871086f85447b6c6)
|
||||
- Fixed useless ServerKiller (#122)
|
1155
changelogs/3.0-alpha.md
Normal file
1155
changelogs/3.0-alpha.md
Normal file
File diff suppressed because it is too large
Load Diff
264
changelogs/3.0.md
Normal file
264
changelogs/3.0.md
Normal file
@ -0,0 +1,264 @@
|
||||
**For Minecraft: Bedrock Edition 1.4.0**
|
||||
|
||||
Plugin scheduler rewrite, RCON rewrite, performance improvements, improved idle memory usage
|
||||
|
||||
**While this release is nominally not an alpha, it is still not feature complete and does not include all gameplay features. Please do not create issues for missing gameplay features.**
|
||||
|
||||
This build has breaking API changes.
|
||||
This release is the first to use the new merged versioning system. The PocketMine-MP version and the API version are now one and the same.
|
||||
|
||||
Please use our issue tracker to report bugs.
|
||||
|
||||
# 3.0.0
|
||||
## Core
|
||||
### General
|
||||
- This release introduces a new dependency library called `Snooze`, which PocketMine-MP utilizes for managing notifications between threads. This library is currently utilized by command reading, RCON and RakLib, allowing faster response times to commands, reduced network latency, and better performance due to lack of need for polling.
|
||||
- Fixed race condition causing `ServerKiller` to sometimes kill the server for no reason on shutdown.
|
||||
|
||||
### Dependency libraries
|
||||
Requires the following libraries:
|
||||
- [`pocketmine/raklib` `^0.12.0`](https://github.com/pmmp/RakLib/releases/0.12.0)
|
||||
- [`pocketmine/spl` `^0.3.0`](https://github.com/pmmp/SPL/releases/0.3.0)
|
||||
- [`pocketmine/binaryutils` `^0.1.0`](https://github.com/pmmp/BinaryUtils/releases/0.1.0)
|
||||
- [`pocketmine/nbt` `^0.2.0`](https://github.com/pmmp/NBT/releases/0.2.0)
|
||||
- [`pocketmine/math` `^0.2.0`](https://github.com/pmmp/Math/releases/0.2.0)
|
||||
- [`pocketmine/snooze` `^0.1.0`](https://github.com/pmmp/Snooze/releases/0.1.0)
|
||||
|
||||
These libraries may individually have changes which are not recorded here. See their independent repository releases for their changelogs.
|
||||
|
||||
### Async pooling
|
||||
- Async workers are now started dynamically when they are needed only, instead of being started immediately on startup. This allows reducing idle memory usage.
|
||||
- AsyncPool now appropriately shuts down the workers when instructed to, instead of leaving it up to the ThreadManager to clean it up. This eliminates debug messages of shutting down async workers on server shutdown.
|
||||
- Default maximum async worker memory limit has been lowered from 1024MB to 256MB.
|
||||
- Async workers are now started using the options `PTHREADS_INHERIT_CONSTANTS | PTHREADS_INHERIT_INI`, which reduces idle memory wastage and works around some bugs in pthreads.
|
||||
|
||||
### Entities
|
||||
- Fixed entities not being despawned when flagged, if they weren't scheduled for an update.
|
||||
|
||||
### Levels
|
||||
- Seed handling is now always consistent between `pocketmine.yml` and `server.properties`.
|
||||
- Fixed generation bugs in imported LevelDB worlds where the classpath was saved into level.dat.
|
||||
- Generators for levels are no longer created on the main thread, reducing memory usage.
|
||||
|
||||
### Plugins
|
||||
- Plugin data is now stored under `<data dir>/plugin_data` by default on new installations, instead of in `<plugins dir>`. This behaviour does not affect existing installations by default - if you want to enable it, set `plugins.legacy-data-dir` to `false` in `pocketmine.yml`.
|
||||
|
||||
### RCON
|
||||
RCON has been almost completely rewritten in this release.
|
||||
- Now event-driven (using Snooze) instead of poll-based, improving performance.
|
||||
- Fixed segmentation fault when stopping the server with RCON enabled.
|
||||
|
||||
## API
|
||||
**WARNING: Dependency library API changes are not listed here. See their individual release notes for changes (linked above in the Core section).**
|
||||
|
||||
### API versioning changes for plugins
|
||||
The way that the API versioning is done has changed. Now the API version is synonymous with the PocketMine-MP version.
|
||||
Plugin compatibility is determined by the following:
|
||||
- Take the base version, and strip any metadata (everything after the `+` sign, for example `3.0.0+dev.1191` becomes `3.0.0`).
|
||||
- Assert that:
|
||||
- The major versions is the same
|
||||
- The server's minor version is greater than or equal to the plugin's
|
||||
- The server's patch version is greater than or equal to the plugin's
|
||||
|
||||
Currently there is no support for locking version by metadata, although this could be implemented if it is a wanted feature.
|
||||
|
||||
### General
|
||||
- `Server->getCodename()` and `\pocketmine\CODENAME` have been removed.
|
||||
- Added API method `Server->getTickSleeper()`, which returns a `\pocketmine\snooze\SleeperHandler` instance.
|
||||
- `Server->getIp()` now returns `0.0.0.0` if not set.
|
||||
|
||||
### Block
|
||||
- Added `Block->getXpDropForTool()`.
|
||||
|
||||
### Entity
|
||||
- Calling `scheduleUpdate()` on an `Entity` after it has been `close()`d will now cause an exception to be thrown.
|
||||
- `Entity->motionX`, `Entity->motionY` `Entity->motionZ` have been removed in favour of an `Entity->motion` `Vector3` field. This also applies for the `lastMotion` fields.
|
||||
- `Entity->isInsideOfWater()` has been renamed to `isUnderwater()`.
|
||||
|
||||
### Events
|
||||
- Added support for `@softDepend` annotation on event handlers, which allows the event handler to not be registered if the dependency plugin is not loaded.
|
||||
- Added support for `@notHandler` annotation for `Listener` methods to indicate that such methods are not event handlers.
|
||||
- Typehints have been applied to the events API to PHP 7.2 standards.
|
||||
- Fixed preventing effect expiry using `EntityEffectRemoveEvent` not being reflected on the client.
|
||||
- `EntityDamageEvent` API has significant changes. The general purpose of this is to split up base damage from modifiers.
|
||||
- Added methods `getBaseDamage()`, `setBaseDamage()`, `getOriginalBaseDamage()`, `getModifiers()`, `getOriginalModifiers()`
|
||||
- `setDamage()` renamed to `setModifier()`, and type parameter is now mandatory
|
||||
- `getDamage()` renamed to `getModifier()`, and type parameter is now mandatory
|
||||
- `getOriginalDamage()` renamed to `getOriginalModifier()`, and type parameter is now mandatory
|
||||
- Removed `MODIFIER_BASE` constant
|
||||
- Constructors now accept: `float baseDamage`, `float[] modifiers` instead of just `float[] modifiers`
|
||||
- Added `BlockBreakEvent->getXpDropAmount()` and `BlockBreakEvent->setXpDropAmount()`.
|
||||
|
||||
### Inventory
|
||||
- `InventoryTransaction->getCreationTime()` has been removed.
|
||||
- `EntityInventoryChangeEvent` and `EntityArmorChangeEvent` are no longer fired during entity inventory intialization.
|
||||
|
||||
### Item
|
||||
- Methods `isPickaxe()`, `isAxe()`, `isSword()`, `isShovel()`, `isHoe()`, `isShears()` have been removed. These should be replaced with `instanceof` checks for the relevant classes.
|
||||
- Removed `Item->useOn()`. This has been superseded by new methods used for handling durability changes.
|
||||
- Added hooks `Item->onDestroyBlock()` and `Item->onAttackEntity()`. These are called when a player uses the item to destroy a block or attack an entity respectively. This is used in the core code for updating durability.
|
||||
- `Item->pop()` now accepts an optional count parameter.
|
||||
- `Enchantment` now has separated primary items (which can be enchanted directly) and secondary items (which can be enchanted on an anvil). The constructor of `Enchantment` has been updated to reflect this.
|
||||
- Removed `Enchantment->getSlot()` and `Enchantment->hasSlot()`.
|
||||
- Added `Enchantment->getPrimaryItemFlags()`, `Enchantment->hasPrimaryItemFlag()`, `Enchantment->getSecondaryItemFlags()` and `Enchantment->hasSecondaryItemFlag()`
|
||||
|
||||
### Level
|
||||
- `Biome` classes have been moved to `pocketmine\level\biome` namespace. This is in preparation for future work on Levels which requires biome information (such as weather conditions).
|
||||
- `WeakPosition` has been removed.
|
||||
- Added `Level->getBiome()`.
|
||||
- `Level->getSafeSpawn()` now always returns a `Position` instance.
|
||||
- `Level->getBlockExtraData()` and `Level->setBlockExtraData()` have been removed (as well as their associated `Chunk` methods).
|
||||
- `ChunkManager->isInWorld()` now accepts integers instead of floats.
|
||||
- Added `SubChunkIteratorManager->invalidate()`.
|
||||
|
||||
#### Generator
|
||||
- `BiomeSelector` has been refactored to make it simpler and more robust.
|
||||
- Generator-management methods `registerDefaultGenerators()`, `addGenerator()`, `getGeneratorList()`, `getGenerator()`, and `getGeneratorName()` have been moved from `Generator` to a new `GeneratorManager` class.
|
||||
- Static noise functions in the `Generator` base class have been moved to `Noise` instance methods.
|
||||
- Added static method `Generator::convertSeed()`, which converts an int or string into a numeric seed for generation.
|
||||
|
||||
### Network
|
||||
- `SourceInterface->process()` no longer returns a value.
|
||||
|
||||
### Plugin
|
||||
- `PluginBase->getResources()` now returns an associative array where the index is the path to the resource relative to the plugin's `resources` directory.
|
||||
- `PluginLoader`s have been almost completely rewritten to make them simpler and more robust.
|
||||
- `PluginManager->registerInterface()` does not return anything, and now accepts a `PluginLoader` instance instead of a `string`.
|
||||
- `PluginLoader`:
|
||||
- `getPluginFilters()`, `enablePlugin()` and `disablePlugin()` are removed.
|
||||
- `loadPlugin()` responsibilities are now solely confined to doing whatever is necessary to make the plugin's classes visible by the server, and does not emit log messages or check for data directories.
|
||||
- Added method `getAccessProtocol()` which determines what prefix to apply to the plugin path to access the files inside it (for example `phar://`).
|
||||
- `PluginBase->init()` and `PluginBase->isInitialized()` have been removed.
|
||||
- `Plugin` interface now declares a signature for the constructor which implementations must comply with.
|
||||
- `Plugin` interface now declares `setEnabled()`.
|
||||
- It is now possible to create a custom `Plugin` implementation without requiring a custom `PluginLoader`.
|
||||
|
||||
### Scheduler
|
||||
This release features major changes to how plugin task scheduling works.
|
||||
- Removed `Server->getScheduler()`. All plugins now have their own scheduler which is accessible using `Plugin->getScheduler()`. Aside from being syntactically more concise and pleasant, this also allows much more effective management of tasks when plugins are disabled.
|
||||
- Removed `PluginTask` class, because it's now unnecessary. Previously it was required to allow the server to delete tasks associated with a plugin when the plugin was disabled. With plugin-owned schedulers, this is no longer a requirement. Plugins may now utilize the `Task` class as a base if they like.
|
||||
- Added `Server->getAsyncPool()`. Since the global scheduler does not exist any more, it does not manage the server's `AsyncPool` any more. Additionally, `ServerScheduler` was previously bloated by a lot of `AsyncTask` related methods, which are now not necessary because direct access to `AsyncPool` is granted instead.
|
||||
- `ServerScheduler`:
|
||||
- `ServerScheduler` has been renamed to `TaskScheduler` since it is now a general-purpose task scheduler which is non-dependent on the user. This allows much greater flexibility and also makes it possible to unit-test.
|
||||
- All `AsyncTask`/`AsyncPool` related methods have been removed - the task scheduler does not manage the async pool anymore.
|
||||
- Calls to `Server->getScheduler()->scheduleAsyncTask()` should be replaced with `Server->getAsyncPool()->submitTask()`.
|
||||
- Calls to `Server->getScheduler()->scheduleAsyncTaskToWorker()` should be replaced with and `Server->getAsyncPool()->submitTaskToWorker()`.
|
||||
|
||||
### Tile
|
||||
- Calling `scheduleUpdate()` on a `Tile` after it has been `close()`d will now cause an exception to be thrown.
|
||||
- Tile NBT is now ephemeral and is not retained after creating the tile.
|
||||
- `Tile->namedtag` has been removed.
|
||||
- `Tile->saveNBT()` now returns a new `CompoundTag` containing saved data.
|
||||
- Added new protected methods `Tile->readSaveData()` and `Tile->writeSaveData()`. These should be overridden to add or read tile-specific data, instead of overriding `saveNBT()` and `__construct()`.
|
||||
|
||||
### Utils
|
||||
- Added `MainLogger->getFormat()` and `MainLogger->setFormat()` to allow manipulating console output format.
|
||||
|
||||
## Gameplay
|
||||
### General
|
||||
- Fixed a range of block collision issues stemming from off-by-one errors when fetching areas.
|
||||
|
||||
### Blocks
|
||||
- Fixed a crash which occurred when leaving a bed which was broken and replaced during sleep.
|
||||
- Fixed dark oak and acacia saplings growing into oak trees - now they will not grow at all (they need to be implemented).
|
||||
- Saplings now take light level into account when trying to grow.
|
||||
- Ores and other blocks now drop experience when broken with an appropriate tool.
|
||||
|
||||
### Entities
|
||||
- Fixed dropped items not being correctly destroyed by fire, cacti and other damage sources.
|
||||
|
||||
### Generation
|
||||
- Grass no longer generates as the top layer of ground cover in river biomes.
|
||||
- Ocean biomes now use gravel instead of grass+dirt for ground cover.
|
||||
- Reduced maximum elevation of plains biomes to make them less bumpy.
|
||||
- Snow layers and other can-be-flowed-into blocks no longer generate underwater.
|
||||
|
||||
### Items
|
||||
- Buckets are no longer able to delete any block by replacing it with water.
|
||||
- Dried Kelp, Bleach, Nautilus Shell and Heart of the Sea items are registered (although crafting recipes for these are not yet available).
|
||||
- Implemented `Vanishing` enchantment.
|
||||
- Implemented Totems.
|
||||
|
||||
### World
|
||||
- Fixed explosions sometimes leaving behind air blocks with non-zero damage values.
|
||||
|
||||
# 3.0.1
|
||||
- Fixed error when players move things around in the crafting grid after plugins cancel `PlayerInteractEvent` on crafting tables.
|
||||
|
||||
# 3.0.2
|
||||
- Fixed memory dumps not showing private properties of parent classes.
|
||||
- Fixed a memory leak when cancelling all tasks in the `TaskScheduler`.
|
||||
- Fixed scheduled task timings showing `Unknown` as the plugin name.
|
||||
|
||||
# 3.0.3
|
||||
- Fixed possible crash in Sign when placed by a plugin.
|
||||
- Fixed slightly-damaged and very-damaged anvils dropping incorrect items.
|
||||
- `Living->applyPostDamageEffects()` is no longer called if the mob died from an attack.
|
||||
- Cooldown for mob attack is now reset prior to applying post-damage effects.
|
||||
- Added constant `ItemIds::MUTTON` to resolve crashes using PC worlds.
|
||||
- Fixed emerald ore not dropping XP when broken with a valid tool.
|
||||
- Fixed mobs getting crazy vertical knockback if attacked while airborne.
|
||||
- Fixed XP orbs continuing to follow dead players.
|
||||
|
||||
# 3.0.4
|
||||
- Fixed RCON spamming the console when a client does not disconnect correctly.
|
||||
- Fixed dropping chunk cache unnecessarily when no blocks need to be updated on a chunk.
|
||||
- Fixed outdated block updates getting sent on chunks replaced using `setBlock()`.
|
||||
|
||||
# 3.0.5
|
||||
- Fixed not being able to place blocks where a player died and has not yet respawned (#2265).
|
||||
- Fixed mob death animation not being played when `Entity->kill()` is called directly or `/kill` is used.
|
||||
- Fixed viewers of different halves of double chests not seeing changes made by viewers who opened the other half (#2261).
|
||||
- Fixed bugs setting items into wrong indexes when double chest halves have differently sized inventories.
|
||||
- Fixed `getConfig()` crashing when called when the plugin's data directory doesn't exist.
|
||||
- Fixed a possible exploit with keychain signing for XBL login.
|
||||
|
||||
# 3.0.6
|
||||
- Fixed invalid keys in `.properties` config files being considered as invalid strings.
|
||||
- Fixed whitespace between key and value `key = value` being invalid in `.properties` config files.
|
||||
- Fixed a bug in exception message when an invalid permission type is written for a command in plugin.yml.
|
||||
- Properly fixed newline issues when parsing event handler annotations - `@notHandler` will now work as expected when CRLF line endings are used.
|
||||
- Fixed `PluginManager->registerEvents()` registering functions as event handlers declared by parent classes which are not `Listener` instances (#2293).
|
||||
|
||||
# 3.0.7
|
||||
- Fixed setting spawn points in un-generated chunks causing the player to fall out of the world.
|
||||
- Fixed spawn protection deactivating when there are no ops set (this was an unwanted/unexpected feature, so it's considered a bug).
|
||||
- Fixed cursor items not getting dropped when closing the inventory or dying.
|
||||
- Fixed more issues with blocks with invalid metadata appearing as update! blocks.
|
||||
- `Entity->setNameTagAlwaysVisible()` now works (although nametags will still not be shown if the entity is invisible, due to a behavioural change in Minecraft PE).
|
||||
- Fixed errors passing zero motions to projectiles in some cases.
|
||||
|
||||
# 3.0.8
|
||||
- Fixed player on-ground state not updating when moving horizontally. This allowed fly hacks with the built in anti-cheat, and also affected some third party anti-cheat plugins due to the effect on `inAirTicks`.
|
||||
- Fixed knockback. PC 1.9-style knockback was mistakenly introduced in 3.0.3. This has now been reverted back to the old 1.8-style behaviour.
|
||||
|
||||
# 3.0.9
|
||||
- Cleaned up odd behaviour of `/kill` due to old broken code.
|
||||
- Fixed patch level check for plugin APIs not allowing lesser patch versions on greater minor versions.
|
||||
- Fixed `/timings paste`. This now reports directly to the timings host instead of using Ubuntu Pastebin.
|
||||
- Minor code cleanups in various places.
|
||||
- Zip resource packs will now give slightly less useless errors - errors for broken manifest have been separated from those with fields missing, and now reports why decoding failed if it failed.
|
||||
|
||||
# 3.0.10
|
||||
- Syntax error crashdumps will no longer be reported to the crash archive.
|
||||
- Chunk sending is now fault-tolerant. Before this release, any error on a worker during async chunk sending (such as memory errors caused by pthreads) would cause that chunk to never get sent, resulting in invisible and missing chunks. Levels will now attempt to retry chunk prepare when a task crashes, which should fix most invisible chunk bugs.
|
||||
- `MainLogger` now logs exception stack traces in a synchronized block to ensure that they are coherent when log messages are emitted from multiple threads at once.
|
||||
- `AsyncTask->isCrashed()` now returns `true` if a fatal error occurred during the task execution.
|
||||
|
||||
# 3.0.11
|
||||
- `DropItemAction` will now consider itself invalid if attempting to drop a null item.
|
||||
- Fixed leaking globally broadcasted Level packets when no players are on the server.
|
||||
- Fixed title bar not being cleared on server stop on some terminals.
|
||||
- Fixed `FallingBlock` saving corrupted data.
|
||||
- Fixed the structure of `GuiDataPickItemPacket`.
|
||||
- Cleaned up some code in `OfflinePlayer`.
|
||||
- Splash potions no longer apply effects to dead (but not yet respawned) players.
|
||||
- Coal ore no longer drops XP when mined with a silk touch tool.
|
||||
- Item entities now cannot be picked up when a negative pickup delay is used.
|
||||
|
||||
# 3.0.12
|
||||
- `Config` keys which are considered bools by YAML 1.1 will no longer be transformed into 1 or 0.
|
||||
- Fixed painting motives not getting saved.
|
||||
- Fixed cacti spewing items when placed in some invalid locations.
|
||||
- Fixed entity fire damage not applying in the void.
|
||||
- Fixed entities not getting updated appropriately in some conditions.
|
68
changelogs/3.1.md
Normal file
68
changelogs/3.1.md
Normal file
@ -0,0 +1,68 @@
|
||||
**For Minecraft: Bedrock Edition 1.5.0**
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.x.y version will also run on this build 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.
|
||||
|
||||
**This build contains changes to the **protocol** which are not covered by the API version. To lock your plugin to a specific protocol version, declare the `mcpe-protocol` attribute in your `plugin.yml`.
|
||||
|
||||
# 3.1.0
|
||||
- Support for Minecraft: Bedrock Edition version 1.5.0
|
||||
|
||||
# 3.1.1
|
||||
- Fixed player on-ground state not updating when moving horizontally. This allowed fly hacks with the built in anti-cheat, and also affected some third party anti-cheat plugins due to the effect on `inAirTicks`.
|
||||
- Fixed knockback. PC 1.9-style knockback was mistakenly introduced in 3.0.3. This has now been reverted back to the old 1.8-style behaviour.
|
||||
|
||||
# 3.1.2
|
||||
- Cleaned up odd behaviour of `/kill` due to old broken code.
|
||||
- Fixed patch level check for plugin APIs not allowing lesser patch versions on greater minor versions.
|
||||
- Fixed `/timings paste`. This now reports directly to the timings host instead of using Ubuntu Pastebin.
|
||||
- Minor code cleanups in various places.
|
||||
- Zip resource packs will now give slightly less useless errors - errors for broken manifest have been separated from those with fields missing, and now reports why decoding failed if it failed.
|
||||
- Added constant `Entity::DATA_FLAG_SHOW_TRIDENT_ROPE`.
|
||||
|
||||
# 3.1.3
|
||||
- Syntax error crashdumps will no longer be reported to the crash archive.
|
||||
- Chunk sending is now fault-tolerant. Before this release, any error on a worker during async chunk sending (such as memory errors caused by pthreads) would cause that chunk to never get sent, resulting in invisible and missing chunks. Levels will now attempt to retry chunk prepare when a task crashes, which should fix most invisible chunk bugs.
|
||||
- `MainLogger` now logs exception stack traces in a synchronized block to ensure that they are coherent when log messages are emitted from multiple threads at once.
|
||||
- `AsyncTask->isCrashed()` now returns `true` if a fatal error occurred during the task execution.
|
||||
|
||||
# 3.1.4
|
||||
- `DropItemAction` will now consider itself invalid if attempting to drop a null item.
|
||||
- Fixed leaking globally broadcasted Level packets when no players are on the server.
|
||||
- Fixed title bar not being cleared on server stop on some terminals.
|
||||
- Fixed `FallingBlock` saving corrupted data.
|
||||
- Fixed the structure of `GuiDataPickItemPacket`.
|
||||
- Cleaned up some code in `OfflinePlayer`.
|
||||
- Splash potions no longer apply effects to dead (but not yet respawned) players.
|
||||
- Coal ore no longer drops XP when mined with a silk touch tool.
|
||||
- Item entities now cannot be picked up when a negative pickup delay is used.
|
||||
- Fixed extra byte at the end of `PlayerSkinPacket` not being read (1.5 protocol change that somehow got lost).
|
||||
|
||||
# 3.1.5
|
||||
- `Config` keys which are considered bools by YAML 1.1 will no longer be transformed into 1 or 0.
|
||||
- Fixed painting motives not getting saved.
|
||||
- Fixed cacti spewing items when placed in some invalid locations.
|
||||
- Fixed entity fire damage not applying in the void.
|
||||
- Fixed entities not getting updated appropriately in some conditions.
|
||||
|
||||
# 3.1.6
|
||||
- Fixed players disconnected during login verification getting leaked and not destroyed correctly.
|
||||
- Updated NBT dependency to 0.2.1 to receive bug fixes (see https://github.com/pmmp/NBT/releases/tag/0.2.1).
|
||||
|
||||
# 3.1.7
|
||||
- Errors thrown during level tick will now crash the server instead of spamming the console.
|
||||
- Fixed arrows despawning too soon after hitting the ground.
|
||||
- Fixed projectiles despawning before colliding if they were airborne for > 60 seconds.
|
||||
|
||||
# 3.1.8
|
||||
- Fixed levels unloaded during an earlier level's tick on the same tick causing a crash.
|
||||
- PermissibleBase->clearPermissions() now properly unsubscribes from all permissions.
|
||||
- Fixed incorrect break check for standing torch.
|
||||
- Fixed drops for brewing stand.
|
||||
- Fixed block picking brewing stand, bed, double slab, cake, farmland, and mob heads giving the wrong items.
|
||||
- Fixed blocks not placing correctly when clicking on redstone ore.
|
||||
- Fixed unknown PC items in tile inventories crashing the server - now they'll be quietly removed instead.
|
||||
- Fixed server freezing when eating chorus fruit from high altitude.
|
||||
- `readline` is now disabled by default on Windows and must be explicitly enabled with `--enable-readline` due to thread-safety issues.
|
||||
- Fixed server crash when trying to use non-implemented splash potions.
|
||||
- Removed incorrect maximum region file size cap which may have caused some worlds to be incorrectly detected as corrupted.
|
121
changelogs/3.2.md
Normal file
121
changelogs/3.2.md
Normal file
@ -0,0 +1,121 @@
|
||||
**For Minecraft: Bedrock Edition 1.6.0**
|
||||
|
||||
This is a minor feature release, including support for Minecraft Bedrock 1.6.0, some new minor gameplay features and some API deprecations and additions.
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.x.y version will also run on this build and do not need API bumps.
|
||||
|
||||
However, some API features have been deprecated in this version. Plugin developers do not need to do anything about these deprecations immediately, however they may raise harmless warnings if used.
|
||||
|
||||
Features marked **`@deprecated`** are **recommended** not to be used, but will continue to work for any future 3.x.y versions. They will be removed in the next major release (4.0).
|
||||
|
||||
# 3.2.0
|
||||
### Core
|
||||
- `Level` generators are now registered only when needed instead of as soon as a worker starts. This drastically reduces memory consumption on servers with lots of workers.
|
||||
- Async workers are now garbage-collected along with everything else on the default schedule. Idle workers with 0 queued tasks will be shutdown and removed from the pool to reduce memory usage.
|
||||
- UPnP error messages are now more informative of troubleshooting steps.
|
||||
- Errors are no longer caught in cases where they are unrecoverable.
|
||||
|
||||
### API
|
||||
#### Entity
|
||||
- Arrow pickup mode can now be controlled via `Arrow->setPickupMode()`. This accepts one of three `Arrow` constants: `PICKUP_NONE`, `PICKUP_ANY`, `PICKUP_CREATIVE`.
|
||||
- Added new API methods `Projectile->getBaseDamage()` and `Projectile->setBaseDamage()`.
|
||||
- Added new API methods `Entity->getScoreTag()` and `Entity->setScoreTag()`.
|
||||
|
||||
#### Events
|
||||
- The `Listener` interface has now received in-depth documentation about its behaviour and uses. See the top of the `Listener` class to read it.
|
||||
- It is now possible to declare `@ignoreCancelled` on an event handler without specifying `true` or `false`. If no value is found, `true` will be assumed.
|
||||
- `ServerCommandEvent` and `RemoteServerCommandEvent` are now **`@deprecated`** and their usage discouraged. A new generic `CommandEvent` has been introduced in its place, which allows capturing commands from any type of command sender. This was done in response to difficulties of code duplication when wanting to intercept commands from both console and players.
|
||||
- `EntityDamageEvent`
|
||||
- Added `MODIFIER_WEAPON_ENCHANTMENTS` constant for attack damage bonuses due to enchantments like Sharpness.
|
||||
- Added new API methods `getAttackCooldown()` and `setAttackCooldown()` to allow controlling Living entities attack cooldown times (default 10 ticks).
|
||||
- `PlayerDeathEvent`: Added new static method `deriveMessage()`.
|
||||
- `PlayerKickEvent`: Added new method `setReason()`.
|
||||
|
||||
#### Forms
|
||||
- Added a new `pocketmine\form\Form` interface. Implementing this interface permits custom form implementations to make use of `Player->sendForm()`, eliminating the need to handle packets directly and also solving the form ID collision problem.
|
||||
|
||||
#### Items
|
||||
- `Item` and `ItemFactory` now support negative item IDs (needed for future extended blocks support).
|
||||
- Updated `ItemIds` interface with new constants.
|
||||
|
||||
#### Permission
|
||||
- Added a new `PermissionManager` class which encapsulates all of the permission-management functionality originally bloating `PluginManager`. The API is identical to that of `PluginManager`'s permission API. All methods moved to `PermissionManager` have **`@deprecated`** redirects remaining behind in `PluginManager`, which will be removed in the next major release (4.0).
|
||||
|
||||
#### Plugin
|
||||
- `PluginBase->getConfig()` will now automatically save the default config if it does not already exist.
|
||||
- Plugin data directories will now be automatically created on plugin load, eliminating the need for boilerplate `@mkdir($this->getDataFolder())` calls at the top of every plugin.
|
||||
|
||||
#### Tile
|
||||
- `Tile::createNBT()` will now throw a `BadMethodCallException` when called directly.
|
||||
|
||||
#### Utils
|
||||
- `Utils::getURL()`, `Utils::postURL()`, `Utils::simpleCurl()` and `Utils::getIP()` have been moved to a new `pocketmine\utils\Internet` class. The original methods are **`@deprecated`** and will be removed for the next major version (4.0).
|
||||
- Removed the ability for `Config` to be asynchronously saved. This was discussed for removal because of various problems that it causes. It was deemed not worth fixing since `Config` saving should not be significant enough to cause problems anyway. See #2298 for details.
|
||||
|
||||
#### Server
|
||||
- Deprecated `level` parameter of `findEntity()`. This parameter was premature optimization. Code using it will continue to work as before.
|
||||
|
||||
### Gameplay
|
||||
#### General
|
||||
- Air bubbles are now regenerated at the same speed as vanilla UpdateAquatic, instead of instantly when leaving water.
|
||||
- Implemented Conduit Power effect.
|
||||
|
||||
#### Enchantments
|
||||
- Implemented the following enchantments: Thorns, Sharpness, Knockback, Fire Aspect, Power, Punch, Flame, Infinity, Mending.
|
||||
|
||||
#### Items
|
||||
- Added the following new items: `Scute`
|
||||
|
||||
# 3.2.1
|
||||
- Fixed `VerifyLoginTask` completion bug when players get disconnected prior to the task completing.
|
||||
- Fixed client crash issue due to outdated runtime ID mappings.
|
||||
|
||||
# 3.2.2
|
||||
- Updated NBT dependency to 0.2.1 to receive bug fixes (see https://github.com/pmmp/NBT/releases/tag/0.2.1).
|
||||
|
||||
# 3.2.3
|
||||
- Errors thrown during level tick will now crash the server instead of spamming the console.
|
||||
- Fixed arrows despawning too soon after hitting the ground.
|
||||
- Fixed projectiles despawning before colliding if they were airborne for > 60 seconds.
|
||||
- Fixed crash related to Flame enchantment when the player shooting the arrow was on fire.
|
||||
|
||||
# 3.2.4
|
||||
- Fixed levels unloaded during an earlier level's tick on the same tick causing a crash.
|
||||
- PermissibleBase->clearPermissions() now properly unsubscribes from all permissions.
|
||||
- Fixed incorrect break check for standing torch.
|
||||
- Fixed drops for brewing stand.
|
||||
- Fixed block picking brewing stand, bed, double slab, cake, farmland, and mob heads giving the wrong items.
|
||||
- Fixed blocks not placing correctly when clicking on redstone ore.
|
||||
- Fixed unknown PC items in tile inventories crashing the server - now they'll be quietly removed instead.
|
||||
- Fixed server freezing when eating chorus fruit from high altitude.
|
||||
- `readline` is now disabled by default on Windows and must be explicitly enabled with `--enable-readline` due to thread-safety issues.
|
||||
- Fixed server crash when trying to use non-implemented splash potions.
|
||||
- Removed incorrect maximum region file size cap which may have caused some worlds to be incorrectly detected as corrupted.
|
||||
|
||||
# 3.2.5
|
||||
- `Player->sendForm()` now throws a proper exception when failing to JSON-encode `Form` objects given to it.
|
||||
- Fixed crash when handling later packets in a batch when an earlier packet triggered termination of the player's connection.
|
||||
- Fixed a race condition causing progress updates in `AsyncTasks` to be lost when published near completion.
|
||||
- Fixed bad decoding for some packets with unsupported structures.
|
||||
- Crash dumps no longer report 20 empty lines when an error occurs in `eval()`'d code.
|
||||
- `pocketmine/nbt` dependency updated to `0.2.2` to fix bugs (see NBT repo for changelog).
|
||||
|
||||
# 3.2.6
|
||||
- Chunk ticking no longer occurs in chunks which have an adjacent unloaded chunks, fixing things like grass ticking triggering unintentional chunk loading.
|
||||
- Fixed some lighting propagation issues where step count is the same but light level is different.
|
||||
- Fixed full-chunk light repopulation producing broken lighting when the generator hasn't been registered on a worker.
|
||||
- Fixed a missing field in `MoveEntityDeltaPacket`.
|
||||
- Added client-sided rate limiting for crashdump reporting to mitigate involuntary DDoS of the crash archive.
|
||||
- Fixed a bug in `start.cmd` where quotes would appear around the "couldn't find installation" message.
|
||||
|
||||
# 3.2.7
|
||||
- Added a network-layer check for item NBT size to avoid unexplained client-sided crashes due to length overflow.
|
||||
- Fixed some desync bugs with double chests when one half of a double chest is unloaded.
|
||||
- Anonymous class timings will now have a cleaned path for the identifier relative to the plugins directory.
|
||||
- Anonymous class timings now render correctly on timings.pmmp.io.
|
||||
- Fixed empty garbage subchunks not getting removed from long-life chunks.
|
||||
- `start.ps1`, `start.sh` and `start.cmd` no longer recognize source-code installations. Since source-code installations should only be used by developers who know what they are doing anyway, this was considered unwise to keep.
|
||||
- Fixed a bug/oversight in network chunk preparation that caused chunk prepare to be 4x slower than necessary.
|
||||
- `Chunk->fastSerialize()` now doesn't serialize useless data (data is omitted based on chunk flags). This significantly reduces the amount of useless data getting copied for generation, population and light calculation.
|
||||
- `TaskHandler->cancel()` was incorrectly marked as `@internal` in 2014. This has been fixed. Plugin developers should in fact prefer `TaskHandler->cancel()` since it does not require a task to have a circular dependency on its own executor.
|
44
changelogs/3.3.md
Normal file
44
changelogs/3.3.md
Normal file
@ -0,0 +1,44 @@
|
||||
**For Minecraft: Bedrock Edition 1.7.0**
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.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 bug fixes in this build.
|
||||
|
||||
# 3.3.0
|
||||
- Compatibility with Minecraft: Bedrock Edition 1.7.0
|
||||
- Removed compatibility with 1.6.0
|
||||
- `Player->sendForm()` now throws a proper exception when failing to JSON-encode `Form` objects given to it.
|
||||
- Fixed crash when handling later packets in a batch when an earlier packet triggered termination of the player's connection.
|
||||
- Fixed a race condition causing progress updates in `AsyncTasks` to be lost when published near completion.
|
||||
- Fixed bad decoding for some packets with unsupported structures.
|
||||
- Crash dumps no longer report 20 empty lines when an error occurs in `eval()`'d code.
|
||||
- `pocketmine/nbt` dependency updated to `0.2.2` to fix bugs (see NBT repo for changelog).
|
||||
|
||||
# 3.3.1
|
||||
- Chunk ticking no longer occurs in chunks which have an adjacent unloaded chunks, fixing things like grass ticking triggering unintentional chunk loading.
|
||||
- Fixed some lighting propagation issues where step count is the same but light level is different.
|
||||
- Fixed full-chunk light repopulation producing broken lighting when the generator hasn't been registered on a worker.
|
||||
- Fixed a missing field in `MoveEntityDeltaPacket`.
|
||||
- Added client-sided rate limiting for crashdump reporting to mitigate involuntary DDoS of the crash archive.
|
||||
- Fixed a bug in `start.cmd` where quotes would appear around the "couldn't find installation" message.
|
||||
|
||||
# 3.3.2
|
||||
- Added a network-layer check for item NBT size to avoid unexplained client-sided crashes due to length overflow.
|
||||
- Fixed some desync bugs with double chests when one half of a double chest is unloaded.
|
||||
- Anonymous class timings will now have a cleaned path for the identifier relative to the plugins directory.
|
||||
- Anonymous class timings now render correctly on timings.pmmp.io.
|
||||
- Fixed empty garbage subchunks not getting removed from long-life chunks.
|
||||
- `start.ps1`, `start.sh` and `start.cmd` no longer recognize source-code installations. Since source-code installations should only be used by developers who know what they are doing anyway, this was considered unwise to keep.
|
||||
- Fixed a bug/oversight in network chunk preparation that caused chunk prepare to be 4x slower than necessary.
|
||||
- `Chunk->fastSerialize()` now doesn't serialize useless data (data is omitted based on chunk flags). This significantly reduces the amount of useless data getting copied for generation, population and light calculation.
|
||||
- `TaskHandler->cancel()` was incorrectly marked as `@internal` in 2014. This has been fixed. Plugin developers should in fact prefer `TaskHandler->cancel()` since it does not require a task to have a circular dependency on its own executor.
|
||||
|
||||
# 3.3.3
|
||||
- Development build error messages are now more user friendly.
|
||||
- Fixed meta-only changes not getting saved correctly in `SubChunk->setBlock()`.
|
||||
- Server will now sleep for up to 120 seconds on a crash if the uptime was less than 120 seconds. This delay is intended to reduce crash archive spam and can be skipped by the user if attended by pressing CTRL+C.
|
||||
- Fixed preprocessed builds sometimes having `new ` calls treated as function calls.
|
||||
- Fixed a rare corruption case where player data could be written incorrectly due to a race condition.
|
||||
- `DataPacket` will now throw errors when attempting to read/write nonexisting fields to make it easier to debug protocol change errors.
|
||||
|
||||
# 3.3.4
|
||||
- Fixed an undefined `DataPacket` field making the previous release unusable.
|
97
changelogs/3.4.md
Normal file
97
changelogs/3.4.md
Normal file
@ -0,0 +1,97 @@
|
||||
**For Minecraft: Bedrock Edition 1.7.0**
|
||||
|
||||
This is a cumulative minor release featuring performance improvements, memory usage improvements, some new minor gameplay features, some API deprecations and additions, and significant changes to error handling.
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
|
||||
However, some API features have been deprecated in this version. Plugin developers do not need to do anything about these deprecations immediately, however they may raise harmless warnings if used.
|
||||
|
||||
Features marked **`@deprecated`** are **recommended** not to be used, but will continue to work for any future 3.x.y versions. They will be removed in the next major release (4.0).
|
||||
|
||||
# 3.4.0
|
||||
## Core changes
|
||||
### Performance & memory improvements
|
||||
- Entity `EXHAUSTION` attribute is no longer synced to the client, which reduces network traffic for survival players and reduces client-sided lag.
|
||||
- A redundant call was removed from an `Event` call hot path which improves event calling performance by ~15% per event handler executed.
|
||||
- Light updates are now batched together and executed on the end of each tick. The effects of this are noticeable when setting a large number of blocks in a close area - significant performance improvements should be noticeable for world editors (the ones that didn't disable light updates) and liquid flow is now significantly less expensive.
|
||||
- Internal enhancements have been made to subchunk light array interfacing to reduce branching and improve access performance.
|
||||
- Memory usage of most chunks has dropped by ~30-40% due to some improvements to internal storage of unlit subchunks. In real terms this translates to ~30% memory usage reduction for a freshly generated world.
|
||||
|
||||
### Error handling
|
||||
The most notable core change in this release revolves around error handling. Internals have been cleaned up substantially to improve the server behaviour under occurrence of unexpected behaviour. The goal of this is to improve consistency and quality while reducing undefined runtime behaviour.
|
||||
The following changes have been made:
|
||||
- Throwing **unexpected** `Throwable`s in the following cases will now cause a server crash (except on network (this will be changed in the future)):
|
||||
- Event handlers
|
||||
- `Task->onRun()` on a scheduler
|
||||
- `AsyncTask->onCompletion()`
|
||||
- `Command->execute()` and `CommandExecutor->onCommand()`
|
||||
- Unexpected `Throwable`s thrown during packet handling will now cause the target player to be disconnected with an `Internal server error` message.
|
||||
|
||||
### Other changes
|
||||
- Anti-flight has been removed, along with the `allow-flight` directive in `server.properties`.
|
||||
- Server language is now controlled by the `language` directive in `server.properties`.
|
||||
- Added `unban` and `unban-ip` as aliases of `pardon` and `pardon-ip` commands respectively.
|
||||
|
||||
## API changes
|
||||
### Block
|
||||
- `BlockSpreadEvent` is now fired when lava or water tries to flow into a block.
|
||||
- `BlockFormEvent` is now fired when lava and water collide to form cobblestone, obsidian or stone.
|
||||
|
||||
### Event
|
||||
- Added new method `Event->call()`. This should be used instead of `PluginManager->callEvent()` in plugins only supporting 3.4+.
|
||||
- `PluginManager->callEvent()` has been `@deprecated`.
|
||||
|
||||
### Level
|
||||
- Attempting to unload a level during its tick will now throw an `InvalidStateException`.
|
||||
- Added the following new methods:
|
||||
- `Level->broadcastPacketToViewers()`
|
||||
- `Level->getViewersForPosition()`
|
||||
- `Level->broadcastGlobalPacket()`
|
||||
- `Level->getChunkAtPosition()`
|
||||
- `Level->isInLoadedTerrain()`
|
||||
- `Level->addGlobalPacket()` has been `@deprecated`.
|
||||
- `LightUpdate` now allows calling `setAndUpdateLight()` for the same position multiple times (needed for light update batching).
|
||||
|
||||
### Permission
|
||||
- `Permission::getByName()` now throws an exception on invalid values instead of silently returning `DEFAULT_FALSE`. This may cause new errors to appear if your plugins had broken permission defaults in `plugin.yml`.
|
||||
|
||||
### Player
|
||||
- `addWindow()` now has stricter validity checks and will now throw exceptions in the following cases: No window IDs left to use, and when a forced window ID collides with an existing window.
|
||||
- The public `$speed` field has been removed (this was only used by anti-cheat which has now been removed).
|
||||
|
||||
### Scheduler
|
||||
- `AsyncTask->setResult()` has had the `$serialize` parameter removed - now it will automatically serialize (or not) as appropriate.
|
||||
- Added a new `ClosureTask` which allows concisely scheduling closure execution on a `TaskScheduler`.
|
||||
- `TaskScheduler->__construct()` `$logger` parameter has been `@deprecated` and will be removed in a future major version.
|
||||
|
||||
### Server
|
||||
- Added new method `Server->hasOfflinePlayerData(string $name) : bool`.
|
||||
- `Server->getAllowFlight()` has been `@deprecated`.
|
||||
|
||||
### Utils
|
||||
- `Config->save()` will no longer catch unexpected exceptions thrown while encoding data.
|
||||
|
||||
## Gameplay changes
|
||||
### Blocks
|
||||
- Rail connectivity has been implemented for normal, powered, detector and activator rails (but there are currently no minecarts).
|
||||
|
||||
# 3.4.1
|
||||
- Updated crashdump format to be compatible with newest CA. This version or newer is required if you want to be able to submit crashdumps to crash.pmmp.io.
|
||||
|
||||
# 3.4.2
|
||||
- `DataPacket` errors when writing to undefined fields are now more clear.
|
||||
- Fixed trees being able to overwrite the log parts of other trees.
|
||||
- Fixed `Player->sendForm()` not working during `PlayerJoinEvent`.
|
||||
- `Entity->setScale()` now explicitly requires a scale larger than 0.
|
||||
- Adding invisible `FloatingTextParticle` to a level no longer causes an error.
|
||||
|
||||
# 3.4.3
|
||||
- Fixed burning TNT setting hurt entities on fire when exploding.
|
||||
- `~` relative coordinates now work in the `/particle` command.
|
||||
- Various boring fixes to error stack trace reporting.
|
||||
- `Level->setChunk()` no longer deletes tiles and entities when replacing a chunk with itself.
|
||||
- Fixed a generator race condition causing rare appearances of half-trees on the client in freshly generated terrain.
|
||||
- `Attribute->resetToDefault()` now fits the default per the min/max bounds, fixing crashes when the bounds are changed to exclude the default.
|
||||
- Fixed a crash with LevelDB worlds when the `TAG_2D_MAPS` tag is missing.
|
||||
- Fixed `Utils::getCoreCount()` crashing on some Debian variants.
|
149
changelogs/3.5.md
Normal file
149
changelogs/3.5.md
Normal file
@ -0,0 +1,149 @@
|
||||
**For Minecraft: Bedrock Edition 1.8.0**
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.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.
|
||||
|
||||
# 3.5.0
|
||||
- Compatibility with Minecraft: Bedrock Edition 1.8.0
|
||||
- Removed compatibility with 1.7.0
|
||||
|
||||
# 3.5.1
|
||||
- Fixed internal server errors when attempting to craft.
|
||||
- `DataPacket` errors when writing to undefined fields are now more clear.
|
||||
- Fixed trees being able to overwrite the log parts of other trees.
|
||||
- Fixed `Player->sendForm()` not working during `PlayerJoinEvent`.
|
||||
- `Entity->setScale()` now explicitly requires a scale larger than 0.
|
||||
- Adding invisible `FloatingTextParticle` to a level no longer causes an error.
|
||||
|
||||
# 3.5.2
|
||||
- Updated some misc protocol magic numbers.
|
||||
- Fixed burning TNT setting hurt entities on fire when exploding.
|
||||
- `~` relative coordinates now work in the `/particle` command.
|
||||
- Various boring fixes to error stack trace reporting.
|
||||
- `Level->setChunk()` no longer deletes tiles and entities when replacing a chunk with itself.
|
||||
- Fixed a generator race condition causing rare appearances of half-trees on the client in freshly generated terrain.
|
||||
- `Attribute->resetToDefault()` now fits the default per the min/max bounds, fixing crashes when the bounds are changed to exclude the default.
|
||||
- Fixed a crash with LevelDB worlds when the `TAG_2D_MAPS` tag is missing.
|
||||
- Fixed `Utils::getCoreCount()` crashing on some Debian variants.
|
||||
|
||||
# 3.5.3
|
||||
- Rewritten documentation of `PlayerPreLoginEvent`, `PlayerLoginEvent` and `PlayerJoinEvent`. They are now much more detailed and no longer misleading.
|
||||
- Chest items block-picked from double chests will no longer place chests that crash the server when opened.
|
||||
- Ender chests now make the correct sounds when opening and closing.
|
||||
- Fixed Sign errors when a buggy or malicious client sent broken NBT with the wrong tags or wrong number of lines.
|
||||
- Resource packs with comments in the manifest will now load correctly. (MOJANG!!!)
|
||||
- Placement of unknown blocks is now disallowed. This solves a range of problems with invalid blocks in the world, such as #2260 .
|
||||
- Errors thrown during `PlayerQuitEvent` or other `Player->close()` errors will now crash the server instead of causing cryptic bugs later on.
|
||||
- Fixed large chunks (>= 1044476 bytes) becoming corrupted when saved in Region-based worlds - now an exception is thrown instead.
|
||||
- Reduced the range of exceptions caught during chunk loading. Now, only chunk corruption errors are caught, and anything else will produce a crash.
|
||||
- Removed catch-all block on chunk saving. Unexpected errors thrown during chunk save will now create a crash.
|
||||
- Fixed some asserts in packet decode methods.
|
||||
- `Attribute` now throws exceptions with more informative messages on errors.
|
||||
- Properly handled some remaining `Uninitialized string offset` bugs when decoding packets.
|
||||
- Fixed chunk updates taking several seconds to show up on the client. This bug was most apparent during generation and some world editing tools using asynchronous tasks.
|
||||
- Fixed CPU waste ordering chunks for non-moving players.
|
||||
|
||||
# 3.5.4
|
||||
### Fixes
|
||||
- Fixed server crash when a block update occurs on a torch with corrupted metadata.
|
||||
- Added a hack to mitigate client-side right-click spam bug. This mostly eliminates spam of `PlayerInteractEvent` on right-click.
|
||||
- Players will no longer see commands they don't have permission to use in client-sided hints when typing a `/` in the chat window.
|
||||
- `Event->isCancelled()` and `Event->setCancelled()` now throw more informative errors.
|
||||
- Errors thrown during a network interface processing will now _actually_ crash the server.
|
||||
|
||||
### API changes
|
||||
- Deprecated `NetworkInterfaceCrashEvent`. Nobody should have been using this anyway.
|
||||
- Deprecated `Network->processInterface()`
|
||||
- Deprecated `SourceInterface->emergencyShutdown()`
|
||||
|
||||
# 3.5.5
|
||||
- Mobs no longer spawn with their heads facing a different direction to their bodies.
|
||||
- Added a console message when the crash strangler sleeps to stop crash spam.
|
||||
- Fixed crash in `/title` command `times` subcommand when not enough arguments were passed.
|
||||
- AsyncWorkers will now not be shut down on GC unless they have not been used for the last 5 minutes. This reduces lag spikes on garbage collection.
|
||||
- Fixed some unhandled error cases in `AddEntityPacket` encoding.
|
||||
- Fixed `LogicException` descendents being thrown from some packet decoding methods when encountering bad userdata.
|
||||
- Player network inventory transaction processing now catches more specific errors.
|
||||
- Fixed missing decode for `TakeItemEntityPacket`.
|
||||
- Fixed `/gc` and `/status` truncating memory statistics - now they report to 0.01 precision.
|
||||
- Global functions and constants are now imported to improve performance.
|
||||
- Fixed a typo in `pocketmine.command.op.take` description.
|
||||
- Ice no longer creates water when a creative player breaks it.
|
||||
- `spawn-mobs` and `spawn-animals` no longer appear in generated `server.properties` on a newly-installed server.
|
||||
- Added a hack to disable pre-spawn client-sided movement.
|
||||
- Assertions enabled warning now always shows when `zend.assertions` is not `-1`. The config option to disable this warning has been removed.
|
||||
- `/status`,`/dumpmemory` and `/gc` are now enabled by default. The `debug.commands` config option has been removed.
|
||||
- Crash dumps are now more thorough at catching plugin-related crashes.
|
||||
|
||||
# 3.5.6
|
||||
- Fixed `#`-commenting properties in `.properties` files not working.
|
||||
- `pocketmine.yml` now permits writing `worldname:` with no generation settings in the `worlds` section to force a world to be loaded.
|
||||
- Fixed Bow force being too low - now it's consistent with Minecraft Java (but not with Bedrock due to a vanilla bug).
|
||||
- Fixed `recursion detected` bug when encoding crashdumps in some cases.
|
||||
- Items with too-large NBT tags on network will now have their tags ignored when sending over network, instead of crashing the server. This is a workaround for a protocol bug which will be addressed in a future Minecraft release.
|
||||
- `/enchant` no longer crashes the server when out-of-bounds enchantment levels are used.
|
||||
- Fixed some crashes loading Region-based worlds when encountering unexpected EOF.
|
||||
- `Entity->fireTicks` is now protected (but accessible by magic method for BC purposes) and will now throw an exception when written to if the value is > 32767 or < 0.
|
||||
- Fixed Signs asserting on corrupted world data with more than 4 lines of text per sign.
|
||||
|
||||
# 3.5.7
|
||||
- Fixed several bugs in RCON packet receive that would allow an attacker to block or crash the RCON thread, denying service to other legitimate RCON clients.
|
||||
- Fixed RCON connections not working (timing out with no response) on some platforms.
|
||||
- Logins are now permitted to have up to 60 seconds clock drift on the `nbf` and `exp` timestamps in the login JWT.
|
||||
- Fixed XP orbs following players who switched to a location spatially nearby in a different world.
|
||||
- `Player->removeWindow()` now throws `InvalidArgumentException` instead of `BadMethodCallException` when trying to non-forcefully remove a fixed window ID.
|
||||
|
||||
# 3.5.8
|
||||
- Fixed player XP not dropping if a player was fast enough to respawn.
|
||||
- Player XP drop amount now matches vanilla (7x level points, incurs some loss of points for higher levels)
|
||||
- Fixed Doxygen configuration including test sources.
|
||||
- Improved performance of block-cache accesses.
|
||||
- Improved performance of random block-ticking.
|
||||
- Closure tasks will now show the correctly formatted name on timings.
|
||||
- Fixed a crash when a local update happens next to an `ItemFrame` with invalid metadata.
|
||||
- Fixed player being subscribed to broadcast permissions too early when permissions are modified before spawn.
|
||||
- Block-picking is now disallowed on unknown blocks.
|
||||
- Internal IP detection now works correctly on all platforms.
|
||||
- Fixed UPnP portforwarding not working correctly when multiple network adapters are installed.
|
||||
- Starting or stopping flight now resets fall distance and in-air ticks.
|
||||
- Fixed falling causing starvation.
|
||||
- Fixed crops consuming bone meal when fully grown.
|
||||
- Users are no longer able to avoid agreeing to the license by restarting the server.
|
||||
- Explosions no longer create broken double chests which crash the server. Existing chests affected by this bug will continue to crash. This will be addressed in a future release.
|
||||
- Cactus and sugarcane no longer grow through non-air blocks.
|
||||
- Fixed a memory leak in `setChunk()` when the `unload` parameter is true.
|
||||
- Generator will now crash if preset is invalid, instead of producing unexpected results.
|
||||
|
||||
# 3.5.9
|
||||
- Fixed a `setChunk()` bug introduced by 3.5.8.
|
||||
- Applied a hack to disable client-sided automatic regeneration.
|
||||
- `Level->getChunkPlayers()` is now deprecated.
|
||||
|
||||
# 3.5.10
|
||||
- Some internal `Level` functions are now correctly marked `@internal`.
|
||||
- Fixed splash potion distance being measured from player feet instead of eye height.
|
||||
- Fixed tall grass being unplaceable on dirt.
|
||||
- A debug message is now recorded when a chunk is loaded with no associated loaders.
|
||||
- Composer dependencies have been updated to fix bugs in some dependencies.
|
||||
|
||||
# 3.5.11
|
||||
- Fixed crashing when items with negative IDs are found in the inventory (caused by downgrading from dev builds).
|
||||
- Updated creative inventory and crafting recipes.
|
||||
|
||||
# 3.5.12
|
||||
- Fixed crash when too-large values are given to `/effect` for duration.
|
||||
- `/op` and other commands no longer crash when an invalid player name is given.
|
||||
- Startup time no longer includes the time spent in the setup wizard.
|
||||
- `TextFormat::clean()` is now UTF-8 aware, and will scrub any invalid UTF-8 characters from the given string.
|
||||
- Fixed `TextFormat::clean()` not fully removing ANSI escape codes in some cases.
|
||||
- Fixed Korean command arguments failing to parse.
|
||||
- `Sign->setText()` and `Sign->setLine()` now enforce that the given text must be UTF-8 text, or an exception will be thrown.
|
||||
- Sign text is now processed by `mb_scrub()` immediately after loading to remove invalid UTF-8 characters that could crash the client.
|
||||
- `Human->exhaust()` no longer underflows when the hunger attribute has a fractional value.
|
||||
|
||||
# 3.5.13
|
||||
- Added a hack to disable client sided AI for non-moving entities. This fixes items floating in water despite it not being implemented server-side yet.
|
||||
- Fixed max health not working as expected on respawn if changed by plugins.
|
||||
- Fixed Item Frame hardness (0.25 instead of 0).
|
||||
- Fire Aspect tools will now light TNT when right-clicked with.
|
||||
- Fixed incorrect nullable typehints on `TaskScheduler` return values.
|
65
changelogs/3.6.md
Normal file
65
changelogs/3.6.md
Normal file
@ -0,0 +1,65 @@
|
||||
**For Minecraft: Bedrock Edition 1.9.0**
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.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.
|
||||
|
||||
This changelog **does not account for protocol changes**. If your plugin uses the protocol, you're not shielded by API change constraints.
|
||||
|
||||
# 3.6.0
|
||||
- Compatibility with Minecraft: Bedrock Edition 1.9.0
|
||||
- Removed compatibility with 1.8.0
|
||||
- `Item->getCompoundTag()` is now `@deprecated`.
|
||||
- `Item->setCompoundTag()` now accepts NULL as a possible value.
|
||||
- `ItemFactory::fromString()` now accepts NULL for the `tags` parameter.
|
||||
|
||||
# 3.6.1
|
||||
- Fixed crashing when items with negative IDs are found in the inventory (caused by downgrading from dev builds).
|
||||
- Updated creative inventory and crafting recipes.
|
||||
- Fixed handling for some new blocks which magically appeared without appropriate implementations (extra meta values).
|
||||
|
||||
# 3.6.2
|
||||
- Fixed client-sided crash when upper-case letters appear in command names.
|
||||
- Fixed crash when too-large values are given to `/effect` for duration.
|
||||
- `/op` and other commands no longer crash when an invalid player name is given.
|
||||
- Startup time no longer includes the time spent in the setup wizard.
|
||||
- `TextFormat::clean()` is now UTF-8 aware, and will scrub any invalid UTF-8 characters from the given string.
|
||||
- Fixed `TextFormat::clean()` not fully removing ANSI escape codes in some cases.
|
||||
- Fixed Korean command arguments failing to parse.
|
||||
- `Sign->setText()` and `Sign->setLine()` now enforce that the given text must be UTF-8 text, or an exception will be thrown.
|
||||
- Sign text is now processed by `mb_scrub()` immediately after loading to remove invalid UTF-8 characters that could crash the client.
|
||||
- `Human->exhaust()` no longer underflows when the hunger attribute has a fractional value.
|
||||
|
||||
# 3.6.3
|
||||
- Added a hack to disable client sided AI for non-moving entities. This fixes items floating in water despite it not being implemented server-side yet.
|
||||
- Fixed max health not working as expected on respawn if changed by plugins.
|
||||
- Fixed Item Frame hardness (0.25 instead of 0).
|
||||
- Fire Aspect tools will now light TNT when right-clicked with.
|
||||
- Fixed incorrect nullable typehints on `TaskScheduler` return values.
|
||||
|
||||
# 3.6.4
|
||||
- `NetworkStackLatencyPacket` unhandled debug has been silenced.
|
||||
- Fixed `Player->removeWindow()` removing GUI or crashing clients when removing a window which was not added.
|
||||
- Fixed packed ice dropping itself when mined without a silk touch pickaxe.
|
||||
- Fixed players not taking fall damage when falling off the side of a ladder when their AABB was intersecting with the ladder's full block area.
|
||||
- Fixed arrows reloaded from disk never despawning.
|
||||
- Fixed player XP not dropping on death.
|
||||
- Fixed player's held slot being out of sync when respawning.
|
||||
- Fixed items with different NBT being considered stackable in some cases by `BaseInventory->canAddItem()`.
|
||||
|
||||
# 3.6.5
|
||||
- Fixed stdout silence on crash if a crash occurs when PHP output buffering is enabled.
|
||||
- Fixed `RegionLoader` considering a range of invalid chunk coordinates as valid.
|
||||
- Fixed `RegionLoader` causing region header corruption when an oversized chunk was discovered. This was causing entire regions to be discarded next time they were freshly loaded.
|
||||
- Fixed performance issue loading old LevelDB worlds (from before MCPE 1.0) due to unmodified chunks being converted every time they were loaded.
|
||||
- Added new debug messages when a world takes too long (longer than 50ms) to complete a tick.
|
||||
- Debug messages are now logged when autosave kicks in (with time measurements), which helps debugging unexplained lag spikes.
|
||||
- Level "auto tick rate" anti-feature and its associated `pocketmine.yml` settings have been removed (see #2665). The settings will persist in old configurations, but will be ignored by this version and future versions.
|
||||
- The `/save-all` command now outputs custom (non-vanilla) messages informing the user how long it took to complete autosaving.
|
||||
- The word `level` has been replaced with `world` (where appropriate) throughout language strings and general user interface messages.
|
||||
|
||||
# 3.6.6
|
||||
- Fixed protocol argument types for commands.
|
||||
- Autosave debug message will now report in milliseconds when the time taken is less than 1 second.
|
||||
- Flatworld presets now allow `*` as a multiplier symbol (fixes PC compatibility).
|
||||
- Network runtimeIDs for blocks are now randomized to prevent things (like plugins) relying on them.
|
||||
- Updated NBT dependency to 0.2.7 for some bug fixes.
|
33
changelogs/3.7.md
Normal file
33
changelogs/3.7.md
Normal file
@ -0,0 +1,33 @@
|
||||
**For Minecraft: Bedrock Edition 1.10.0**
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.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.
|
||||
|
||||
This changelog **does not account for protocol changes**. If your plugin uses the protocol, you're not shielded by API change constraints.
|
||||
|
||||
# 3.7.0
|
||||
- Compatibility with Minecraft: Bedrock Edition 1.10.0
|
||||
- Removed compatibility with 1.9.0
|
||||
|
||||
# 3.7.1
|
||||
- Fixed protocol argument types for commands.
|
||||
- Autosave debug message will now report in milliseconds when the time taken is less than 1 second.
|
||||
- Flatworld presets now allow `*` as a multiplier symbol (fixes PC compatibility).
|
||||
- Network runtimeIDs for blocks are now randomized to prevent things (like plugins) relying on them.
|
||||
- Updated NBT dependency to 0.2.7 for some bug fixes.
|
||||
|
||||
# 3.7.2
|
||||
- Fixed a memory leak when `PlayerLoginEvent` is cancelled.
|
||||
- Fixed permissions `pocketmine.command.ban.list`, `pocketmine.command.difficulty`, `pocketmine.command.whitelist.enable` and `pocketmine.command.whitelist.disable` always being granted to operators.
|
||||
- Fixed some commands outputting `commands.generic.permission` instead of the proper message when running commands that the sender doesn't have permission to use.
|
||||
- Worlds with unknown generator types will now refuse to load instead of getting incorrect terrain generation ruining them.
|
||||
- `TextFormat::tokenize()` no longer corrupts Unicode sequences.
|
||||
- `TextFormat::clean()` now removes non-printable Unicode code points in the private-use area.
|
||||
- Running two servers in the same data directory is no longer allowed and will gracefully halt instead of corrupting your data.
|
||||
- Sign text length is now soft-capped at 1000 characters.
|
||||
|
||||
# 3.7.3
|
||||
- World save timings now include saves that are triggered by chunk unloading.
|
||||
- Fixed several network denial-of-service bugs.
|
||||
- A warning is now emitted when the `ChunkUtils` extension is not loaded.
|
||||
- Moved version constants to a separate `VersionInfo` file for easier parsing and handling.
|
69
changelogs/3.8.md
Normal file
69
changelogs/3.8.md
Normal file
@ -0,0 +1,69 @@
|
||||
**For Minecraft: Bedrock Edition 1.11.0**
|
||||
|
||||
### Note
|
||||
Plugins compatible with any previous 3.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.
|
||||
|
||||
This changelog **does not account for protocol changes**. If your plugin uses the protocol, you're not shielded by API change constraints.
|
||||
|
||||
# 3.8.0
|
||||
- Compatibility with Minecraft: Bedrock Edition 1.11.0
|
||||
- Removed compatibility with 1.10.0
|
||||
|
||||
# 3.8.1
|
||||
- Fixed furnace smelting recipes not working.
|
||||
- Reduced legacy hacks dealing with `BatchPacket` to fix possible ID collisions.
|
||||
- Reduced release phar size by minifying JSON data blobs.
|
||||
- Moved some MCPE-specific JSON blobs to submodule.
|
||||
|
||||
# 3.8.2
|
||||
- Fixed --enable-ansi and --disable-ansi not being respected on threads.
|
||||
- Fixed a crash that could occur when decoding `AvailableCommandsPacket`.
|
||||
- Fixed a crash when loading worlds with entities with missing `Motion` NBT tag.
|
||||
- Fixed a crash when world time overflows signed int64 max.
|
||||
- Fixed world generators and providers being registered too late (this was causing plugin issues).
|
||||
- Updated RakLib version to get a security fix.
|
||||
- Fixed errors when custom clients fill the wrong information in `ResourcePackClientResponsePacket`.
|
||||
- Fixed `setImmobile()` getting overridden directly after `PlayerJoinEvent`.
|
||||
- Fixed air being breakable by creative players.
|
||||
- Fixed performance loss caused by bugs in the preprocessor.
|
||||
|
||||
# 3.8.3
|
||||
- Fixed infinite recursion when using `Entity->close()` during `EntityDespawnEvent`.
|
||||
- Fixed crash reports caused by folder plugins being reported to the crash archive.
|
||||
- Fixed spawning entities on unloaded chunks during spawn sequence (possible client crash cause).
|
||||
- Fixed `/time query` output message.
|
||||
- Fixed `Server->hasOfflinePlayerData()` being case-sensitive.
|
||||
- Improved error messages for skin validation in some places.
|
||||
- Fixed classic stonecutter hardness.
|
||||
- Fixed iron trapdoors being considered a valid furnace fuel.
|
||||
- Fixed apple dropping from leaves happening less frequently than intended.
|
||||
- Fixed tall plants like sunflower being replaceable by the top half.
|
||||
|
||||
# 3.8.4
|
||||
- Plugin load order is now randomised to remove the ability to implicitly depend on filesystem-specific ordering.
|
||||
- Packet logging in debug messages now uses base64 instead of hex (uses less space).
|
||||
- Array and string size are now shown in error stack trace logs.
|
||||
- Stack traces now render a maximum of 80 characters when making string parameters printable.
|
||||
- Improved documentation for some transaction classes.
|
||||
- Action order in inventory transactions is now randomised to prevent dependencies on any accidental or client-dependent ordering. Since the transaction system is specifically designed to avoid depending on order, this does not affect any core functionality.
|
||||
|
||||
# 3.8.5
|
||||
- Moved preprocessor to build/ directory.
|
||||
- Added documentation for `Server->getPlayer()`, `Server->getPlayerExact()` and `Server->matchPlayer()`.
|
||||
- `server.lock` now contains the PID of the currently-running server.
|
||||
- PID of server is now reported in the error message when attempting to run two servers from the same data directory at once.
|
||||
- Fixed sluggish playercount updating on MOTD.
|
||||
- Added new MultiRecipe UUIDs.
|
||||
- Added an extra field to `StartGamePacket` to resolve minor incompatibility issues on different 1.11.x patch versions.
|
||||
|
||||
# 3.8.6
|
||||
- Fixed `Entity->isNameTagAlwaysVisible()` not working.
|
||||
- Log messages are now cleaned of invalid UTF-8 sequences before emitting them.
|
||||
- Fixed negative integers being considered as strings for world seeds.
|
||||
- Fixed out-of-bounds access on invalid inventory data in player data saves.
|
||||
- Fixed crash when custom liquids have flow decays which aren't factors of 4.
|
||||
- Fixed `Entity->noDamageTicks` not working when the entity had no previous damage cause.
|
||||
|
||||
# 3.8.7
|
||||
- Improved documentation of `Player->getDisplayName()` and `Player::isValidUserName()`.
|
||||
- Fixed a bug in `SetScorePacket` decoding causing the entry list to always be empty.
|
59
changelogs/3.9.md
Normal file
59
changelogs/3.9.md
Normal file
@ -0,0 +1,59 @@
|
||||
**For Minecraft: Bedrock Edition 1.12.0**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.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.
|
||||
|
||||
# 3.9.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.12.0
|
||||
- Removed compatibility with 1.11.0
|
||||
|
||||
## Protocol
|
||||
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been renamed:
|
||||
- `AddEntityPacket` -> `AddActorPacket`
|
||||
- `AddItemEntityPacket` -> `AddItemActorPacket`
|
||||
- `AvailableEntityIdentifiersPacket` -> `AvailableActorIdentifiersPacket`
|
||||
- `BlockEntityDataPacket` -> `BlockActorDataPacket`
|
||||
- `EntityEventPacket` -> `ActorEventPacket`
|
||||
- `EntityFallPacket` -> `ActorFallPacket`
|
||||
- `EntityPickRequestPacket` -> `ActorPickRequestPacket`
|
||||
- `MoveEntityAbsolutePacket` -> `MoveActorAbsolutePacket`
|
||||
- `MoveEntityDeltaPacket` -> `MoveActorDeltaPacket`
|
||||
- `RemoveEntityPacket` -> `RemoveActorPacket`
|
||||
- `SetEntityDataPacket` -> `SetActorDataPacket`
|
||||
- `SetEntityLinkPacket` -> `SetActorLinkPacket`
|
||||
- `SetEntityMotionPacket` -> `SetActorMotionPacket`
|
||||
- `TakeItemEntityPacket` -> `TakeItemActorPacket`
|
||||
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been removed:
|
||||
- `FullChunkDataPacket`
|
||||
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been added:
|
||||
- `AddEntityPacket` (not to be confused with the old one)
|
||||
- `ClientCacheBlobStatusPacket`
|
||||
- `ClientCacheMissResponsePacket`
|
||||
- `ClientCacheStatusPacket`
|
||||
- `LevelChunkPacket`
|
||||
- `RemoveEntityPacket` (not to be confused with the old one)
|
||||
- `StructureTemplateDataExportRequestPacket`
|
||||
- `StructureTemplateDataExportResponsePacket`
|
||||
|
||||
# 3.9.1
|
||||
- Fixed resource packs not working on 1.12 clients.
|
||||
- Fixed some particles displaying incorrectly (some still don't render at all).
|
||||
- Fixed `Entity->setFireTicks()` with a value of `0` setting the on-fire flag.
|
||||
- Silenced a debug message which appeared every time a player right-clicked a block.
|
||||
- Updated constants for `LevelSoundEventPacket`.
|
||||
|
||||
# 3.9.2
|
||||
- Logger warnings for illegal player movements have been lowered to debug.
|
||||
- TNT explosions now start from the center instead of the base. This fixes unexpected results when TNT is lit on top of obsidian.
|
||||
- Fixed the `loadbefore` directive in `plugin.yml` sometimes being ignored.
|
||||
- Fixed `Item->setCustomName()` with an empty string leaving behind an empty tag.
|
||||
- Fixed incorrect positioning of bucket empty sound.
|
||||
- Fixed some incorrect tag parsing in `/give` involving quoted numbers.
|
||||
|
||||
# 3.9.3
|
||||
- Fixed a memory leak on async task removal in error conditions.
|
||||
- Fixed scheduled block updates (for example liquid) triggering chunk reloading. This could cause a significant performance issue in some conditions.
|
||||
- Fixed some minor cosmetic issues in documentation.
|
765
changelogs/4.0-snapshot.md
Normal file
765
changelogs/4.0-snapshot.md
Normal file
@ -0,0 +1,765 @@
|
||||
# 4.0.0-SNAPSHOT-1907XX (2019-07-XX)
|
||||
|
||||
This major version features substantial changes throughout the core, including significant API changes, new world format support, performance improvements and a network revamp.
|
||||
|
||||
## Core
|
||||
### General
|
||||
- A new "plugin greylist" feature has been introduced, which allows whitelisting or blacklisting plugins from loading.
|
||||
- The `/reload` command has been removed.
|
||||
- The `/effect` command no longer supports numeric IDs - it's now required to use names.
|
||||
- Remote console (RCON) has been removed. The [RconServer](https://github.com/pmmp/RconServer) plugin is provided as a substitute.
|
||||
- Spawn protection has been removed. The [BasicSpawnProtection](https://github.com/pmmp/BasicSpawnProtection) plugin is provided as a substitute.
|
||||
- CTRL+C signal handling has been removed. The [PcntlSignalHandler](https://github.com/pmmp/PcntlSignalHandler) plugin is provided as a substitute.
|
||||
- Player movement anti-cheat has been removed. Its corresponding `pocketmine.yml` setting `player.anti-cheat.allow-movement-cheats` has been removed.
|
||||
- The `pocketmine_chunkutils` PHP extension has been dropped.
|
||||
- New PHP extensions are required by this version:
|
||||
- [ds](https://github.com/php-ds/ext-ds)
|
||||
- [chunkutils2](https://github.com/pmmp/ext-chunkutils2)
|
||||
|
||||
### World format support
|
||||
- Modern Minecraft Bedrock world formats are now supported.
|
||||
- Automatic conversion of deprecated world formats is now implemented.
|
||||
- The following world formats have been deprecated and will be **automatically converted on load to a new format**:
|
||||
- `mcregion`
|
||||
- `anvil`
|
||||
- `pmanvil`
|
||||
- 256 build-height is now supported in all worlds (facilitated by automatic conversion).
|
||||
- Extended blocks are now supported (facilitated by automatic conversion).
|
||||
- Unsupported world formats no longer causes a crash, but a graceful shutdown instead.
|
||||
- World corruption no longer causes a crash.
|
||||
|
||||
### Logger revamp
|
||||
- Many components now have a dedicated logger which automatically adds [prefixes] to their messages.
|
||||
- Main logger now includes milliseconds in timestamps.
|
||||
|
||||
### Network
|
||||
This version features substantial changes to the network system, improving coherency, reliability and modularity.
|
||||
|
||||
#### Minecraft Bedrock packet encryption
|
||||
- This fixes replay attacks where hackers steal and replay player logins.
|
||||
- A new setting has been added to `pocketmine.yml`: `network.enable-encryption` which is `true` by default.
|
||||
|
||||
#### Packet receive error handling has been overhauled
|
||||
- Only `BadPacketException` is now caught during packet decode and handling. This requires that all decoding MUST perform proper data error checking.
|
||||
- Throwing a `BadPacketException` from decoding will now cause players to be kicked with the message `Packet processing error`.
|
||||
- The disconnect message includes a random hex ID to help server owners identify the problems reported by their players.
|
||||
- Throwing any other exception will now cause a server crash. `Internal server error` has been removed.
|
||||
- It is now illegal to send a clientbound packet to the server. Doing so will result in the client being kicked with the message `Unexpected non-serverbound packet`.
|
||||
|
||||
#### New packet handler system
|
||||
- Packet handlers have been separated from NetworkSession into a dedicated packet handler structure.
|
||||
- A network session may have exactly 1 handler at a time, which is mutable and may be replaced at any time. This allows packet handling logic to be broken up into multiple stages:
|
||||
- preventing undefined behaviour when sending wrong packets at the wrong time (they'll now be silently dropped)
|
||||
- allowing the existence of ephemeral state-specific logic (for example stricter resource packs download checks)
|
||||
- Packet handlers are now almost entirely absent from `Player` and instead appear in their own dedicated units.
|
||||
- Almost all game logic that was previously locked up inside packet handlers in `Player` has been extracted into new API methods. See Player API changes for details.
|
||||
|
||||
## API
|
||||
### General
|
||||
- Most places which previously allowed `callable` now only allow `\Closure`. This is because closures have more consistent behaviour and are more performant.
|
||||
- `void` and `?nullable` parameter and return types have been applied in many places.
|
||||
- Everything in the `pocketmine\metadata` namespace and related implementations have been removed.
|
||||
|
||||
### Block
|
||||
- Blocks with IDs >= 256 are now supported.
|
||||
- Block state and variant metadata have been separated.
|
||||
- Variant is considered an extension of ID and is immutable.
|
||||
- `Block->setDamage()` has been removed. `Block->readStateFromData()` is now used for state deserialization.
|
||||
- Tile entities are now created and deleted automatically when `World->setBlock()` is used with a block that requires a tile entity.
|
||||
- Some tile entities' API has been exposed on their corresponding `Block` classes, with the tile entity classes being deprecated.
|
||||
- The `pocketmine\tile` namespace has been relocated to `pocketmine\block\tile`.
|
||||
- `Block->recalculateBoundingBox()` and `Block->recalculateCollisionBoxes()` are now expected to return AABBs relative to `0,0,0` instead of their own position.
|
||||
- Block break-info has been extracted into a new dynamic `BlockBreakInfo` unit. The following methods have been moved:
|
||||
- `Block->getBlastResistance()` -> `BlockBreakInfo->getBlastResistance()`
|
||||
- `Block->getBreakTime()` -> `BlockBreakInfo->getBreakTime()`
|
||||
- `Block->getHardness()` -> `BlockBreakInfo->getHardness()`
|
||||
- `Block->getToolHarvestLevel()` -> `BlockBreakInfo->getToolHarvestLevel()`
|
||||
- `Block->getToolType()` -> `BlockBreakInfo->getToolType()`
|
||||
- `Block->isBreakable()` -> `BlockBreakInfo->isBreakable()`
|
||||
- `Block->isCompatibleWithTool()` -> `BlockBreakInfo->isToolCompatible()`
|
||||
- The following API methods have been added:
|
||||
- `Block->asItem()`: returns an itemstack corresponding to the block
|
||||
- `Block->isSameState()`: returns whether the block is the same as the parameter, including state information
|
||||
- `Block->isSameType()`: returns whether the block is the same as the parameter, without state information
|
||||
- The following hooks have been added:
|
||||
- `Block->onAttack()`: called when a player in survival left-clicks the block to try to start breaking it
|
||||
- `Block->onPostPlace()`: called directly after placement in the world, handles things like rail connections and chest pairing
|
||||
- The following API methods have been renamed:
|
||||
- `Block->getDamage()` -> `Block->getMeta()`
|
||||
- `Block->onActivate()` -> `Block->onInteract()`
|
||||
- `Block->onEntityCollide()` -> `Block->onEntityInside()`
|
||||
- The following API methods have changed signatures:
|
||||
- `Block->onInteract()` now has the signature `onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool`
|
||||
- The following API methods have been removed:
|
||||
- `Block->canPassThrough()`
|
||||
- `Block->setDamage()`
|
||||
- `Block::get()`: this was superseded by `BlockFactory::get()` a long time ago
|
||||
- The following classes have been renamed:
|
||||
- `BlockIds` -> `BlockLegacyIds`
|
||||
- `CobblestoneWall` -> `Wall`
|
||||
- `NoteBlock` -> `Note`
|
||||
- `SignPost` -> `Sign`
|
||||
- `StandingBanner` -> `Banner`
|
||||
- The following classes have been removed:
|
||||
- `Bricks`
|
||||
- `BurningFurnace`
|
||||
- `CobblestoneStairs`
|
||||
- `Dandelion`
|
||||
- `DoubleSlab`
|
||||
- `DoubleStoneSlab`
|
||||
- `EndStone`
|
||||
- `GlowingRedstoneOre`
|
||||
- `GoldOre`
|
||||
- `Gold`
|
||||
- `IronDoor`
|
||||
- `IronOre`
|
||||
- `IronTrapdoor`
|
||||
- `Iron`
|
||||
- `Lapis`
|
||||
- `NetherBrickFence`
|
||||
- `NetherBrickStairs`
|
||||
- `Obsidian`
|
||||
- `PurpurStairs`
|
||||
- `Purpur`
|
||||
- `QuartzStairs`
|
||||
- `Quartz`
|
||||
- `RedSandstoneStairs`
|
||||
- `RedSandstone`
|
||||
- `SandstoneStairs`
|
||||
- `Sandstone`
|
||||
- `StainedClay`
|
||||
- `StainedGlassPane`
|
||||
- `StainedGlass`
|
||||
- `StoneBrickStairs`
|
||||
- `StoneBricks`
|
||||
- `StoneSlab2`
|
||||
- `StoneSlab`
|
||||
- `Stone`
|
||||
- `WallBanner`
|
||||
- `WallSign`
|
||||
- `Wood2`
|
||||
- `BlockToolType` constants have been renamed to remove the `TYPE_` prefix.
|
||||
|
||||
### Command
|
||||
- The following classes have been removed:
|
||||
- `RemoteConsoleCommandSender`
|
||||
- The following API methods have signature changes:
|
||||
- `Command->setPermission()` argument is now mandatory (but still nullable).
|
||||
- `CommandSender->setScreenLineHeight()` argument is now mandatory (but still nullable).
|
||||
|
||||
### Entity
|
||||
#### General
|
||||
- The following API methods have been added:
|
||||
- `ItemEntity->getDespawnDelay()`
|
||||
- `ItemEntity->setDespawnDelay()`
|
||||
- `Human->getHungerManager()`
|
||||
- `Human->getXpManager()`
|
||||
- The following methods have signature changes:
|
||||
- `Entity->entityBaseTick()` is now `protected`.
|
||||
- `Entity->move()` is now `protected`.
|
||||
- `Living->knockBack()` now accepts `float, float, float` (the first two parameters have been removed).
|
||||
- `Living->getEffects()` now returns `EffectManager` instead of `Effect[]`.
|
||||
- The following classes have been added:
|
||||
- `effect\EffectManager`: contains effect-management functionality extracted from `Living`
|
||||
- `HungerManager`: contains hunger-management functionality extracted from `Human`
|
||||
- `ExperienceManager`: contains XP-management functionality extracted from `Human`
|
||||
- The following API methods have been moved / renamed:
|
||||
- `Living->removeAllEffects()` -> `EffectManager->clear()`
|
||||
- `Living->removeEffect()` -> `EffectManager->remove()`
|
||||
- `Living->addEffect()` -> `EffectManager->add()`
|
||||
- `Living->getEffect()` -> `EffectManager->get()`
|
||||
- `Living->hasEffect()` -> `EffectManager->has()`
|
||||
- `Living->hasEffects()` -> `EffectManager->hasEffects()`
|
||||
- `Living->getEffects()` -> `EffectManager->all()`
|
||||
- `Human->getFood()` -> `HungerManager->getFood()`
|
||||
- `Human->setFood()` -> `HungerManager->setFood()`
|
||||
- `Human->getMaxFood()` -> `HungerManager->getMaxFood()`
|
||||
- `Human->addFood()` -> `HungerManager->addFood()`
|
||||
- `Human->isHungry()` -> `HungerManager->isHungry()`
|
||||
- `Human->getSaturation()` -> `HungerManager->getSaturation()`
|
||||
- `Human->setSaturation()` -> `HungerManager->setSaturation()`
|
||||
- `Human->addSaturation()` -> `HungerManager->addSaturation()`
|
||||
- `Human->getExhaustion()` -> `HungerManager->getExhaustion()`
|
||||
- `Human->setExhaustion()` -> `HungerManager->setExhaustion()`
|
||||
- `Human->exhaust()` -> `HungerManager->exhaust()`
|
||||
- `Human->getXpLevel()` -> `ExperienceManager->getXpLevel()`
|
||||
- `Human->setXpLevel()` -> `ExperienceManager->setXpLevel()`
|
||||
- `Human->addXpLevels()` -> `ExperienceManager->addXpLevels()`
|
||||
- `Human->subtractXpLevels()` -> `ExperienceManager->subtractXpLevels()`
|
||||
- `Human->getXpProgress()` -> `ExperienceManager->getXpProgress()`
|
||||
- `Human->setXpProgress()` -> `ExperienceManager->setXpProgress()`
|
||||
- `Human->getRemainderXp()` -> `ExperienceManager->getRemainderXp()`
|
||||
- `Human->getCurrentTotalXp()` -> `ExperienceManager->getCurrentTotalXp()`
|
||||
- `Human->setCurrentTotalXp()` -> `ExperienceManager->setCurrentTotalXp()`
|
||||
- `Human->addXp()` -> `ExperienceManager->addXp()`
|
||||
- `Human->subtractXp()` -> `ExperienceManager->subtractXp()`
|
||||
- `Human->getLifetimeTotalXp()` -> `ExperienceManager->getLifetimeTotalXp()`
|
||||
- `Human->setLifetimeTotalXp()` -> `ExperienceManager->setLifetimeTotalXp()`
|
||||
- `Human->canPickupXp()` -> `ExperienceManager->canPickupXp()`
|
||||
- `Human->onPickupXp()` -> `ExperienceManager->onPickupXp()`
|
||||
- `Human->resetXpCooldown()` -> `ExperienceManager->resetXpCooldown()`
|
||||
- The following API methods have been removed:
|
||||
- `Human->getRawUniqueId()`: use `Human->getUniqueId()->toBinary()` instead
|
||||
- The following classes have been removed:
|
||||
- `Creature`
|
||||
- `Damageable`
|
||||
- `Monster`
|
||||
- `NPC`
|
||||
- `Rideable`
|
||||
- `Vehicle`
|
||||
- `Skin` now throws exceptions on creation if given invalid data.
|
||||
|
||||
#### Effect
|
||||
- All `Effect` related classes have been moved to the `pocketmine\entity\effect` namespace.
|
||||
- Effect functionality embedded in the `Effect` class has been separated out into several classes. The following classes have been added:
|
||||
- `AbsorptionEffect`
|
||||
- `HealthBoostEffect`
|
||||
- `HungerEffect`
|
||||
- `InstantDamageEffect`
|
||||
- `InstantEffect`
|
||||
- `InstantHealthEffect`
|
||||
- `InvisibilityEffect`
|
||||
- `LevitationEffect`
|
||||
- `PoisonEffect`
|
||||
- `RegenerationEffect`
|
||||
- `SaturationEffect`
|
||||
- `SlownessEffect`
|
||||
- `SpeedEffect`
|
||||
- `WitherEffect`
|
||||
- Negative effect amplifiers are now explicitly disallowed due to undefined behaviour they created.
|
||||
- The following API methods have been renamed:
|
||||
- `Effect::registerEffect()` -> `Effect::register()`
|
||||
- `Effect::getEffect()` -> `Effect::get()`
|
||||
- `Effect::getEffectByName()` -> `Effect::fromString()`
|
||||
- Static getter methods for all registered enchantment types have been added. `Effect::getEffect(Effect::WHATEVER)` should be replaced by `VanillaEffects::WHATEVER()`.
|
||||
- All effect registry functionality has been removed from the `Effect` base class and migrated to the `VanillaEffects` class.
|
||||
|
||||
#### Removal of runtime entity NBT
|
||||
- Entities no longer keep their NBT alive at runtime.
|
||||
- `Entity->namedtag` has been removed.
|
||||
- `Entity->saveNBT()` now returns a newly created `CompoundTag` instead of modifying the previous one in-place.
|
||||
- `Entity->initEntity()` now accepts a `CompoundTag` parameter.
|
||||
|
||||
#### Entity creation
|
||||
- Entity class overriding is now explicitly supported, without needing to touch save IDs.
|
||||
- Entity classes can be overridden using `EntityFactory::override()`. The provided replacement class **must** be a subclass of the existing class. If the existing class isn't there, an exception will be thrown.
|
||||
- Attempting to register an entity to a save ID that is already registered will now cause an exception to be thrown.
|
||||
- Registering entities will now throw exceptions on error cases instead of returning `false`.
|
||||
- Entity creation has now been split into two paths:
|
||||
- `EntityFactory::create()`: Creates an entity by the given class. This accepts arguments to be passed to the entity constructor. This function is guaranteed to return an entity which is an instanceof the given class.
|
||||
- `EntityFactory::createFromData()`: Creates an entity from save data. This may return any `Entity` class or `NULL`. This function is internal and shouldn't be used by plugins.
|
||||
- It is no longer possible to directly create an entity by save ID. This is discouraged because save IDs are internal and format-dependent.
|
||||
- The following API methods have been moved:
|
||||
- `Entity::registerEntity()` -> `EntityFactory::register()`
|
||||
- `Entity::createEntity()` -> `EntityFactory::create()`
|
||||
- `Entity::getKnownEntityTypes()` -> `EntityFactory::getKnownTypes()`
|
||||
- `Entity::createBaseNBT()` -> `EntityFactory::createBaseNBT()`
|
||||
- The following API methods have been removed:
|
||||
- `Entity->getSaveId()`
|
||||
|
||||
#### WIP removal of entity network metadata
|
||||
- All network metadata related constants have been removed from the `Entity` class and moved to the protocol layer. It is intended to remove network metadata from the API entirely, but this has not yet been completed.
|
||||
- `Entity::DATA_FLAG_*` constants have been moved to `pocketmine\network\mcpe\protocol\types\EntityMetadataFlags`.
|
||||
- `Entity::DATA_TYPE_*` constants have been moved to `pocketmine\network\mcpe\protocol\types\EntityMetadataTypes`.
|
||||
- `Entity::DATA_*` constants have been moved to `pocketmine\network\mcpe\protocol\types\EntityMetadataProperties`.
|
||||
- `DataPropertyManager` has been moved to the `pocketmine\network\mcpe\protocol\types` namespace, and as such isn't considered part of the API anymore.
|
||||
|
||||
### Event
|
||||
#### Internal event system no longer depends on `Listener`s
|
||||
- The internal event processing system no longer depends on `Listener` objects. Arbitrary closures can now be used, provided that they satisfy the standard requirements to be a handler.
|
||||
- This change improves performance of event handler calling by approximately 15%. This does not include anything plugins are doing.
|
||||
- The following classes have been removed:
|
||||
- `pocketmine\plugin\EventExecutor`
|
||||
- `pocketmine\plugin\MethodEventExecutor`
|
||||
- `RegisteredListener->__construct()` now requires `Closure` instead of `Listener, EventExecutor` as the leading parameters.
|
||||
- `RegisteredListener->getListener()` has been removed.
|
||||
|
||||
#### Default cancelled handling behaviour has changed
|
||||
- Handler functions will now **not receive cancelled events by default**. This is a **silent BC break**, i.e. it won't raise errors, but it might cause bugs.
|
||||
- `@ignoreCancelled` is now no longer respected.
|
||||
- `@handleCancelled` has been added. This allows opting _into_ receiving cancelled events (it's the opposite of `@ignoreCancelled`).
|
||||
|
||||
#### `PlayerPreLoginEvent` changes
|
||||
- The `Player` object no longer exists at this phase of the login. Instead, a `PlayerInfo` object is provided, along with connection information.
|
||||
- Ban, server-full and whitelist checks are now centralized to `PlayerPreLoginEvent`. It's no longer necessary (or possible) to intercept `PlayerKickEvent` to handle these types of disconnects.
|
||||
- Multiple kick reasons may be set to ensure that the player is still removed if there are other reasons for them to be disconnected and one of them is cleared. For example, if a player is banned and the server is full, clearing the ban flag will still cause the player to be disconnected because the server is full.
|
||||
- Plugins may set custom kick reasons. Any custom reason has absolute priority.
|
||||
- If multiple flags are set, the kick message corresponding to the highest priority reason will be shown. The priority (as of this snapshot) is as follows:
|
||||
- Custom (highest priority)
|
||||
- Server full
|
||||
- Whitelisted
|
||||
- Banned
|
||||
- The `PlayerPreLoginEvent::KICK_REASON_PRIORITY` constant contains a list of kick reason priorities, highest first.
|
||||
- The following constants have been added:
|
||||
- `PlayerPreLoginEvent::KICK_REASON_PLUGIN`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_SERVER_FULL`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_SERVER_WHITELISTED`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_BANNED`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_PRIORITY`: ordered list of kick reason priorities, highest first
|
||||
- The following API methods have been added:
|
||||
- `PlayerPreLoginEvent->clearAllKickReasons()`
|
||||
- `PlayerPreLoginEvent->clearKickReason()`
|
||||
- `PlayerPreLoginEvent->getFinalKickMessage()`: the message to be shown to the player with the current reason list in place
|
||||
- `PlayerPreLoginEvent->getIp()`
|
||||
- `PlayerPreLoginEvent->getKickReasons()`: returns an array of flags indicating kick reasons, must be empty to allow joining
|
||||
- `PlayerPreLoginEvent->getPlayerInfo()`
|
||||
- `PlayerPreLoginEvent->getPort()`
|
||||
- `PlayerPreLoginEvent->isAllowed()`
|
||||
- `PlayerPreLoginEvent->isAuthRequired()`: whether XBL authentication will be enforced
|
||||
- `PlayerPreLoginEvent->isKickReasonSet()`
|
||||
- `PlayerPreLoginEvent->setAuthRequired()`
|
||||
- `PlayerPreLoginEvent->setKickReason()`
|
||||
- The following API methods have been changed:
|
||||
- `PlayerPreLoginEvent->getKickMessage()` now has the signature `getKickMessage(int $flag) : ?string`
|
||||
- The following API methods have been removed:
|
||||
- `PlayerPreLoginEvent->setKickMessage()`
|
||||
- `PlayerPreLoginEvent->getPlayer()`
|
||||
|
||||
#### Other changes
|
||||
- Disconnecting players during events no longer crashes the server (although it might cause other side effects).
|
||||
- `PlayerKickEvent` is no longer fired for disconnects that occur before the player completes the initial login sequence (i.e. completing downloading resource packs).
|
||||
- Cancellable events must now implement `CancellableTrait` to get the cancellable components needed to satisfy interface requirements.
|
||||
- `PlayerInteractEvent` is no longer fired when a player activates an item. This fixes the age-old complaint of `PlayerInteractEvent` firing multiple times when interacting once. The following constants have been removed:
|
||||
- `PlayerInteractEvent::LEFT_CLICK_AIR`
|
||||
- `PlayerInteractEvent::RIGHT_CLICK_AIR`
|
||||
- `PlayerInteractEvent::PHYSICAL`
|
||||
- The following events have been added:
|
||||
- `PlayerItemUseEvent`: player activating their held item, for example to throw it.
|
||||
- `BlockTeleportEvent`: block teleporting, for example dragon egg when attacked.
|
||||
- The following events have been removed:
|
||||
- `EntityArmorChangeEvent`
|
||||
- `EntityInventoryChangeEvent`
|
||||
- `EntityLevelChangeEvent` - `EntityTeleportEvent` with world checks should be used instead.
|
||||
- `NetworkInterfaceCrashEvent`
|
||||
- `PlayerCheatEvent`
|
||||
- `PlayerIllegalMoveEvent`
|
||||
- The following API methods have been added:
|
||||
- `EntityDeathEvent->getXpDropAmount()`
|
||||
- `EntityDeathEvent->setXpDropAmount()`
|
||||
- `PlayerDeathEvent->getXpDropAmount()`
|
||||
- `PlayerDeathEvent->setXpDropAmount()`
|
||||
- The following API methods have been removed:
|
||||
- `PlayerPreLoginEvent->getPlayer()`
|
||||
- The following API methods have been moved:
|
||||
- `Event->isCancelled()` -> `CancellableTrait->isCancelled()`: this was a stub which threw `BadMethodCallException` if the class didn't implement `Cancellable`; now this is simply not available on non-cancellable events
|
||||
- `Event->setCancelled()` -> `CancellableTrait->setCancelled()`
|
||||
- `HandlerList::unregisterAll()` -> `HandlerListManager->unregisterAll()`
|
||||
- `HandlerList::getHandlerListFor()` -> `HandlerListManager->getListFor()`
|
||||
- `HandlerList::getHandlerLists()` -> `HandlerListManager->getAll()`
|
||||
- The following classes have been moved:
|
||||
- `pocketmine\plugin\RegisteredListener` -> `pocketmine\event\RegisteredListener`
|
||||
|
||||
### Inventory
|
||||
- All crafting and recipe related classes have been moved to the `pocketmine\crafting` namespace.
|
||||
- The following classes have been added:
|
||||
- `CallbackInventoryChangeListener`
|
||||
- `CreativeInventory`: contains the creative functionality previously embedded in `pocketmine\item\Item`, see Item changes for details
|
||||
- `InventoryChangeListener`: allows listening (but not interfering with) events in an inventory.
|
||||
- `transaction\CreateItemAction`
|
||||
- `transaction\DestroyItemAction`
|
||||
- The following classes have been renamed:
|
||||
- `ContainerInventory` -> `BlockInventory`
|
||||
- The following classes have been removed:
|
||||
- `CustomInventory`
|
||||
- `InventoryEventProcessor`
|
||||
- `Recipe`
|
||||
- `transaction\CreativeInventoryAction`
|
||||
- The following API methods have been added:
|
||||
- `Inventory->addChangeListeners()`
|
||||
- `Inventory->getChangeListeners()`
|
||||
- `Inventory->removeChangeListeners()`
|
||||
- `Inventory->swap()`: swaps the contents of two slots
|
||||
- The following API methods have been removed:
|
||||
- `BaseInventory->getDefaultSize()`
|
||||
- `BaseInventory->setSize()`
|
||||
- `Inventory->close()`
|
||||
- `Inventory->dropContents()`
|
||||
- `Inventory->getName()`
|
||||
- `Inventory->getTitle()`
|
||||
- `Inventory->onSlotChange()`
|
||||
- `Inventory->open()`
|
||||
- `Inventory->sendContents()`
|
||||
- `Inventory->sendSlot()`
|
||||
- `InventoryAction->onExecuteFail()`
|
||||
- `InventoryAction->onExecuteSuccess()`
|
||||
- `PlayerInventory->sendCreativeContents()`
|
||||
- The following API methods have signature changes:
|
||||
- `Inventory->clear()` now returns `void` instead of `bool`.
|
||||
- `Inventory->setItem()` now returns `void` instead of `bool`.
|
||||
- `InventoryAction->execute()` now returns `void` instead of `bool`.
|
||||
- `BaseInventory->construct()` no longer accepts a list of items to initialize with.
|
||||
- `PlayerInventory->setItemInHand()` now sends the update to viewers of the player.
|
||||
|
||||
### Item
|
||||
#### General
|
||||
- `Item->count` is no longer public.
|
||||
- The hierarchy of writable books has been changed: `WritableBook` and `WrittenBook` now extend `WritableBookBase`.
|
||||
- The following API methods have signature changes:
|
||||
- `WritableBookBase->setPages()` now accepts `WritableBookPage[]` instead of `CompoundTag[]`.
|
||||
- `ItemFactory::get()` no longer accepts `string` for the `tags` parameter.
|
||||
- `ItemFactory::fromString()` no longer accepts a `$multiple` parameter and now only returns `Item`, not `Item|Item[]`.
|
||||
- The following methods are now fluent:
|
||||
- `WritableBookBase->setPages()`
|
||||
- `Item->addEnchantment()`
|
||||
- `Item->removeEnchantment()`
|
||||
- `Item->removeEnchantments()`
|
||||
- `Armor->setCustomColor()`
|
||||
- `WrittenBook->setTitle()`
|
||||
- `WrittenBook->setAuthor()`
|
||||
- `WrittenBook->setGeneration()`
|
||||
- The following API methods have been removed:
|
||||
- `Item->getNamedTagEntry()`
|
||||
- `Item->removeNamedTagEntry()`
|
||||
- `Item->setDamage()`: "Damage" is now immutable for all items except `Durable` descendents.
|
||||
- `Item->setNamedTagEntry()`
|
||||
- `Item::get()`: this was superseded by `ItemFactory::get()` a long time ago
|
||||
- `Item::fromString()`: this was superseded by `ItemFactory::fromString()` a long time ago
|
||||
- `Item->setCompoundTag()`
|
||||
- `Item->getCompoundTag()`
|
||||
- `Item->hasCompoundTag()`
|
||||
- `ProjectileItem->getProjectileEntityType()`
|
||||
- The following methods have been renamed:
|
||||
- `Item->getDamage()` -> `Item->getMeta()`
|
||||
- The following methods have been moved to `pocketmine\inventory\CreativeInventory`:
|
||||
- `Item::addCreativeItem()` -> `CreativeInventory::add()`
|
||||
- `Item::clearCreativeItems()` -> `CreativeInventory::clear()`
|
||||
- `Item::getCreativeItemIndex()` -> `CreativeInventory::getItemIndex()`
|
||||
- `Item::getCreativeItems()` -> `CreativeInventory::getAll()`
|
||||
- `Item::initCreativeItems()` -> `CreativeInventory::init()`
|
||||
- `Item::isCreativeItem()` -> `CreativeInventory::contains()`
|
||||
- `Item::removeCreativeItem()` -> `CreativeInventory::remove()`
|
||||
- The following classes have been added:
|
||||
- `ArmorTypeInfo`
|
||||
- `Boots`
|
||||
- `Chestplate`
|
||||
- `Fertilizer`
|
||||
- `Helmet`
|
||||
- `Leggings`
|
||||
- `LiquidBucket`
|
||||
- `MilkBucket`
|
||||
- `WritableBookBase`
|
||||
- `WritableBookPage`
|
||||
- The following API methods have been added:
|
||||
- `Armor->getArmorSlot()`
|
||||
- `ProjectileItem->getProjectileEntityClass()`: returns the class of projectile to be created when thrown
|
||||
- The following classes have been removed:
|
||||
- `ChainBoots`
|
||||
- `ChainChestplate`
|
||||
- `ChainHelmet`
|
||||
- `ChainLeggings`
|
||||
- `DiamondBoots`
|
||||
- `DiamondChestplate`
|
||||
- `DiamondHelmet`
|
||||
- `DiamondLeggings`
|
||||
- `GoldBoots`
|
||||
- `GoldChestplate`
|
||||
- `GoldHelmet`
|
||||
- `GoldLeggings`
|
||||
- `IronBoots`
|
||||
- `IronChesplate`
|
||||
- `IronHelmet`
|
||||
- `IronLeggings`
|
||||
- `LeatherBoots`
|
||||
- `LeatherCap`
|
||||
- `LeatherPants`
|
||||
- `LeatherTunic`
|
||||
|
||||
#### NBT handling
|
||||
- Serialized NBT byte array caches are no longer stored on itemstacks. These caches were a premature optimization used for network layer serialization and as such were dependent on the network NBT format.
|
||||
- Internal NBT usage has been marginalized. It's no longer necessary to immediately write changes to NBT. The following hooks have been added:
|
||||
- `Item->serializeCompoundTag()`
|
||||
- `Item->deserializeCompoundTag()`
|
||||
- It's planned to remove runtime NBT from items completely, but this currently presents unresolved backwards-compatibility problems.
|
||||
|
||||
#### Enchantment
|
||||
- The following API methods have been renamed:
|
||||
- `Enchantment::registerEnchantment()` -> `Enchantment::register()`
|
||||
- `Enchantment::getEnchantment()` -> `Enchantment::get()`
|
||||
- `Enchantment::getEnchantmentByName()` -> `Enchantment::fromString()`
|
||||
- Static getter methods for all registered enchantment types have been added. `Enchantment::getEnchantment(Enchantment::WHATEVER)` should be replaced by `Enchantment::WHATEVER()`.
|
||||
|
||||
### Lang
|
||||
- The following classes have been renamed:
|
||||
- `BaseLang` -> `Language`
|
||||
- `LanguageNotFoundException` has been added. This is thrown when trying to construct a `Language` which doesn't exist in the server files.
|
||||
|
||||
|
||||
### Network
|
||||
- The following fields have been removed:
|
||||
- `Network::$BATCH_THRESHOLD`
|
||||
- The following classes have been renamed:
|
||||
- `SourceInterface` -> `NetworkInterface`
|
||||
- `AdvancedSourceInterface` -> `AdvancedNetworkInterface`
|
||||
- The following classes have been moved:
|
||||
- `CompressBatchedTask` -> `mcpe\CompressBatchTask`
|
||||
- `level\format\io\ChunkRequestTask` -> `mcpe\ChunkRequestTask`
|
||||
- `mcpe\RakLibInterface` -> `mcpe\raklib\RakLibInterface`
|
||||
- The following classes have been removed:
|
||||
- `mcpe\PlayerNetworkSessionAdapter`
|
||||
- The following methods have been removed:
|
||||
- `NetworkInterface->putPacket()`
|
||||
- `NetworkInterface->close()`
|
||||
- `NetworkInterface->emergencyShutdown()`
|
||||
- `NetworkInterface` now represents a more generic interface to be implemented by any network component, as opposed to specifically a player network interface.
|
||||
- Everything under the `rcon` subnamespace has been removed.
|
||||
- `upnp\UPnP` has significant changes. It's now a network component instead of a pair of static methods.
|
||||
|
||||
### Permission
|
||||
- Added `PermissibleDelegateTrait` to reduce boilerplate for users of `PermissibleBase`. This trait is used by `ConsoleCommandSender` and `Player`.
|
||||
- The following API methods have been moved:
|
||||
- `Permission::getByName()` -> `PermissionParser::defaultFromString()`
|
||||
- `Permission::loadPermissions()` -> `PermissionParser::loadPermissions()`
|
||||
- `Permission::loadPermission()` -> `PermissionParser::loadPermission()`
|
||||
- The following API methods have been added:
|
||||
- `PermissionParser::emitPermissions()`
|
||||
- The following API methods have changes:
|
||||
- `PermissionParser::defaultFromString()` now throws `InvalidArgumentException` on unknown values.
|
||||
|
||||
### Player
|
||||
- The following classes have moved to the new `pocketmine\player` namespace:
|
||||
- `Achievement`
|
||||
- `GameMode`
|
||||
- `IPlayer`
|
||||
- `OfflinePlayer`
|
||||
- `PlayerInfo`
|
||||
- `Player`
|
||||
- The following constants have been removed:
|
||||
- `Player::SURVIVAL` - use `GameMode::SURVIVAL()`
|
||||
- `Player::CREATIVE` - use `GameMode::CREATIVE()`
|
||||
- `Player::ADVENTURE` - use `GameMode::ADVENTURE()`
|
||||
- `Player::SPECTATOR` - use `GameMode::SPECTATOR()`
|
||||
- `Player::VIEW` - use `GameMode::SPECTATOR()`
|
||||
- (almost) all packet handlers have been removed from `Player`. They are now encapsulated within the network layer.
|
||||
- The following API methods have been added:
|
||||
- `Player->attackBlock()`: attack (left click) the target block, e.g. to start destroying it (survival)
|
||||
- `Player->attackEntity()`: melee-attack (left click) the target entity (if within range)
|
||||
- `Player->breakBlock()`: destroy the target block in the current world (immediately)
|
||||
- `Player->consumeHeldItem()`: consume the previously activated item, e.g. eating food
|
||||
- `Player->continueBreakBlock()`: punch the target block during destruction in survival, advancing break animation and creating particles
|
||||
- `Player->hasFiniteResources()`
|
||||
- `Player->interactBlock()`: interact (right click) the target block in the current world
|
||||
- `Player->interactEntity()`: interact (right click) the target entity, e.g. to apply a nametag (not implemented yet)
|
||||
- `Player->pickBlock()`: picks (mousewheel click) the target block in the current world
|
||||
- `Player->releaseHeldItem()`: release the previously activated item, e.g. shooting a bow
|
||||
- `Player->selectHotbarSlot()`: select the specified hotbar slot
|
||||
- `Player->stopBreakBlock()`: cease attacking a previously attacked block
|
||||
- `Player->toggleFlight()`: tries to start / stop flying (fires events, may be cancelled)
|
||||
- `Player->updateNextPosition()`: sets the player's next attempted move location (fires events, may be cancelled)
|
||||
- `Player->useHeldItem()`: activate the held item, e.g. throwing a snowball
|
||||
- The following API methods have been removed:
|
||||
- `Player->addActionBarMessage()`: replaced by `sendActionBarMessage()`
|
||||
- `Player->addSubTitle()`: replaced by `sendSubTitle()`
|
||||
- `Player->addTitle()`: replaced by `sendTitle()`
|
||||
- `Player->getAddress()`: replaced by `NetworkSession->getIp()`
|
||||
- `Player->getPing()`: moved to `NetworkSession`
|
||||
- `Player->getPort()`: moved to `NetworkSession`
|
||||
- `Player->updatePing()`: moved to `NetworkSession`
|
||||
|
||||
|
||||
### Plugin
|
||||
- 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`.
|
||||
- `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 removed:
|
||||
- `PluginLogger`
|
||||
- The following interface requirements have been removed:
|
||||
- `Plugin->onEnable()`: this is now internalized inside `PluginBase`
|
||||
- `Plugin->onDisable()`: same as above
|
||||
- `Plugin->onLoad()`: same as above
|
||||
- `Plugin` no longer extends `CommandExecutor`. This means that `Plugin` implementations don't need to implement `onCommand()` anymore.
|
||||
- The following hook methods have changed visibility:
|
||||
- `PluginBase->onEnable()` changed from `public` to `protected`
|
||||
- `PluginBase->onDisable()` changed from `public` to `protected`
|
||||
- `PluginBase->onLoad()` changed from `public` to `protected`
|
||||
- The following hook methods have been renamed:
|
||||
- `Plugin->setEnabled()` -> `Plugin->onEnableStateChange()`. This change was made to force plugin developers misusing this hook to stop, and to give it a name that better describes what it does.
|
||||
- The following (deprecated) API methods have been removed:
|
||||
- `PluginManager->callEvent()`: use `Event->call()` instead
|
||||
- `PluginManager->addPermission()`: use `PermissionManager` instead
|
||||
- `PluginManager->getDefaultPermSubscriptions()`: use `PermissionManager` instead
|
||||
- `PluginManager->getDefaultPermissions()`: use `PermissionManager` instead
|
||||
- `PluginManager->getPermission()`: use `PermissionManager` instead
|
||||
- `PluginManager->getPermissionSubscriptions()`: use `PermissionManager` instead
|
||||
- `PluginManager->getPermissions()`: use `PermissionManager` instead
|
||||
- `PluginManager->recalculatePermissionDefaults()`: use `PermissionManager` instead
|
||||
- `PluginManager->removePermission()`: use `PermissionManager` instead
|
||||
- `PluginManager->subscribeToDefaultPerms()`: use `PermissionManager` instead
|
||||
- `PluginManager->subscribeToPermission()`: use `PermissionManager` instead
|
||||
- `PluginManager->unsubscribeFromDefaultPerms()`: use `PermissionManager` instead
|
||||
- `PluginManager->unsubscribeFromPermission()`: use `PermissionManager` instead
|
||||
- It is no longer permitted to throw exceptions from `PluginBase->onEnable()` or `PluginBase->onLoad()`. Doing so will now cause the server to crash.
|
||||
|
||||
### Scheduler
|
||||
#### Thread-local storage for AsyncTasks
|
||||
- TLS has been completely rewritten in this release to be self contained, more robust and easier to use.
|
||||
- Now behaves more like simple properties. `storeLocal()` writes, `fetchLocal()` reads.
|
||||
- Self-contained and doesn't depend on the async pool to clean up after it.
|
||||
- Values are automatically removed from storage when the `AsyncTask` is garbage-collected, just like a regular property.
|
||||
- Supports storing multiple values, differentiated by string names.
|
||||
- `fetchLocal()` can now be used multiple times. It no longer deletes the stored value.
|
||||
- The following classes have been removed:
|
||||
- `FileWriteTask`
|
||||
- The following methods have been removed:
|
||||
- `AsyncTask->peekLocal()`: use `fetchLocal()` instead
|
||||
- The following methods have signature changes:
|
||||
- `AsyncTask->storeLocal()` now has the signature `storeLocal(string $key, mixed $complexData) : void`
|
||||
- `AsyncTask->fetchLocal()` now has the signature `fetchLocal(string $key) : mixed`
|
||||
|
||||
#### Other changes
|
||||
- `AsyncPool` uses a new, significantly more performant algorithm for task collection.
|
||||
- `BulkCurlTask` has had the `$complexData` constructor parameter removed.
|
||||
- `pocketmine\Collectable` has been removed, and is no longer extended by `AsyncTask`.
|
||||
- The following hooks have been added:
|
||||
- `AsyncTask->onError()`: called on the main thread when an uncontrolled error was detected in the async task, such as a memory failure
|
||||
- The following hooks have signature changes:
|
||||
- `AsyncTask->onCompletion()` no longer accepts a `Server` parameter, and has a `void` return type.
|
||||
- `AsyncTask->onProgressUpdate()` no longer accepts a `Server` parameter, and has a `void` return type.
|
||||
- The following API methods have been removed:
|
||||
- `AsyncTask->getFromThreadStore()`: use `AsyncTask->worker->getFromThreadStore()`
|
||||
- `AsyncTask->removeFromThreadStore()`: use `AsyncTask->worker->removeFromThreadStore()`
|
||||
- `AsyncTask->saveToThreadStore()`: use `AsyncTask->worker->saveToThreadStore()`
|
||||
|
||||
### Server
|
||||
- The following API methods have been removed:
|
||||
- `reloadWhitelist()`
|
||||
- `getLevelMetadata()`
|
||||
- `getPlayerMetadata()`
|
||||
- `getEntityMetadata()`
|
||||
- `getDefaultGamemode()`
|
||||
- `getLoggedInPlayers()`
|
||||
- `onPlayerLogout()`
|
||||
- `addPlayer()`
|
||||
- `removePlayer()`
|
||||
- `reload()`
|
||||
- `getSpawnRadius()`
|
||||
- `enablePlugin()`
|
||||
- `disablePlugin()`
|
||||
- `getGamemodeString()` - replaced by `pocketmine\player\GameMode->getTranslationKey()`
|
||||
- `getGamemodeName()` - replaced by `pocketmine\player\GameMode->name()`
|
||||
- `getGamemodeFromString()` - replaced by `GameMode::fromString()`
|
||||
- The following API methods have changed:
|
||||
- `getOfflinePlayerData()` no longer creates data when it doesn't exist.
|
||||
|
||||
### Level / World
|
||||
#### General
|
||||
- All references to `Level` in the context of "world" have been changed to `World`.
|
||||
- The `pocketmine\level` namespace has been renamed to `pocketmine\world`
|
||||
- All classes containing the world `Level` in the name in the "world" context have been changed to `World`.
|
||||
- `Position->getLevel()` has been renamed to `Position->getWorld()`, and `Position->level` has been renamed to `Position->world`.
|
||||
- Extracted a `WorldManager` unit from `Server`
|
||||
- `Server->findEntity()` -> `WorldManager->findEntity()`
|
||||
- `Server->generateLevel()` -> `WorldManager->generateWorld()`
|
||||
- `Server->getAutoSave()` -> `WorldManager->getAutoSave()`
|
||||
- `Server->getDefaultLevel()` -> `WorldManager->getDefaultWorld()`
|
||||
- `Server->getLevel()` -> `WorldManager->getWorld()`
|
||||
- `Server->getLevelByName()` -> `WorldManager->getWorldByName()`
|
||||
- `Server->getLevels()` -> `WorldManager->getWorlds()`
|
||||
- `Server->isLevelGenerated()` -> `WorldManager->isWorldGenerated()`
|
||||
- `Server->isLevelLoaded()` -> `WorldManager->isWorldLoaded()`
|
||||
- `Server->loadLevel()` -> `WorldManager->loadWorld()`
|
||||
- `Server->setAutoSave()` -> `WorldManager->setAutoSave()`
|
||||
- `Server->setDefaultLevel()` -> `WorldManager->setDefaultWorld()`
|
||||
- `Server->unloadLevel()` -> `WorldManager->unloadWorld()`
|
||||
- Added `WorldManager->getAutoSaveTicks()` and `WorldManager->setAutoSaveTicks()` to allow controlling the autosave interval.
|
||||
- The following classes have been added:
|
||||
- `BlockTransaction`: allows creating batch commits of block changes with validation conditions - if any block can't be applied, the whole transaction fails to apply.
|
||||
- `ChunkListenerNoOpTrait`: contains default no-op stubs for chunk listener implementations
|
||||
- `ChunkListener`: interface allowing subscribing to events happening on a given chunk
|
||||
- The following API methods have been added:
|
||||
- `World->registerChunkListener()`
|
||||
- `World->unregisterChunkListener()`
|
||||
- The following API methods have been removed:
|
||||
- `ChunkLoader->getLoaderId()` (now object ID is used)
|
||||
|
||||
- The following API methods have changed signatures:
|
||||
- `World->addParticle()` now has the signature `addParticle(Vector3 $pos, Particle $particle, ?Player[] $players = null) : void`
|
||||
- `World->addSound()` now has the signature `addSound(?Vector3 $pos, Sound $sound, ?Player[] $players = null) : void`
|
||||
- `World->getRandomTickedBlocks()` now returns `bool[]` instead of `SplFixedArray`.
|
||||
- `World->addRandomTickedBlock()` now accepts `Block` instead of `int, int`.
|
||||
- `World->removeRandomTickedBlock()` now accepts `Block` instead of `int, int`.
|
||||
- `World->setBlock()` has had the `$direct` parameter removed.
|
||||
- The following API methods have been renamed / moved:
|
||||
- `Level->getCollisionCubes()` -> `World->getCollisionBoxes()`
|
||||
- Extracted a unit `pocketmine\world\format\io\FastChunkSerializer` from `Chunk`:
|
||||
- `Chunk->fastDeserialize()` -> `FastChunkSerializer::deserialize()`
|
||||
- `Chunk->fastSerialize()` -> `FastChunkSerializer::serialize()`
|
||||
- A `ChunkListener` interface has been extracted from `ChunkLoader`. The following methods have been moved:
|
||||
- `ChunkLoader->onBlockChanged()` -> `ChunkListener->onBlockChanged()`
|
||||
- `ChunkLoader->onChunkChanged()` -> `ChunkListener->onChunkChanged()`
|
||||
- `ChunkLoader->onChunkLoaded()` -> `ChunkListener->onChunkLoaded()`
|
||||
- `ChunkLoader->onChunkPopulated()` -> `ChunkListener->onChunkPopulated()`
|
||||
- `ChunkLoader->onChunkUnloaded()` -> `ChunkListener->onChunkUnloaded()`
|
||||
|
||||
#### Particles
|
||||
- `pocketmine\world\particle\Particle` no longer extends `pocketmine\math\Vector3`, and has been converted to an interface.
|
||||
- Added the following `Particle` classes:
|
||||
- `DragonEggTeleportParticle`
|
||||
- `PunchBlockParticle`
|
||||
|
||||
#### Sounds
|
||||
- `pocketmine\world\sound\Sound` no longer extends `pocketmine\math\Vector3`, and has been converted to an interface.
|
||||
- `Sound->encode()` now accepts `?\pocketmine\math\Vector3`. `NULL` may be passed for sounds which are global.
|
||||
- Added the following classes:
|
||||
- `ArrowHitSound`
|
||||
- `BlockBreakSound`
|
||||
- `BlockPlaceSound`
|
||||
- `BowShootSound`
|
||||
- `BucketEmptyLavaSound`
|
||||
- `BucketEmptyWaterSound`
|
||||
- `BucketFillLavaSound`
|
||||
- `BucketFillWaterSound`
|
||||
- `ChestCloseSound`
|
||||
- `ChestOpenSound`
|
||||
- `EnderChestCloseSound`
|
||||
- `EnderChestOpenSound`
|
||||
- `ExplodeSound`
|
||||
- `FlintSteelSound`
|
||||
- `ItemBreakSound`
|
||||
- `NoteInstrument`
|
||||
- `NoteSound`
|
||||
- `PaintingPlaceSound`
|
||||
- `PotionSplashSound`
|
||||
- `RedstonePowerOffSound`
|
||||
- `RedstonePowerOnSound`
|
||||
- `ThrowSound`
|
||||
- `XpCollectSound`
|
||||
- `XpLevelUpSound`
|
||||
|
||||
### Utils
|
||||
- `Terminal::hasFormattingCodes()` no longer auto-detects the availability of formatting codes. Instead it's necessary to use `Terminal::init()` with no parameters to initialize, or `true` or `false` to override.
|
||||
- `Config->save()` no longer catches exceptions thrown during emitting to disk.
|
||||
- The following new classes have been added:
|
||||
- `InternetException`
|
||||
- `Internet`
|
||||
- `Process`
|
||||
- The following API methods have been added:
|
||||
- `Color::fromRGBA()`
|
||||
- `Config->getPath()`: returns the path to the config on disk
|
||||
- `Terminal::write()`: emits a Minecraft-formatted text line without newline
|
||||
- `Terminal::writeLine()`: emits a Minecraft-formatted text line with newline
|
||||
- `Utils::recursiveUnlink()`: recursively deletes a directory and its contents
|
||||
- The following deprecated API redirects have been removed:
|
||||
- `Utils::execute()`: moved to `Process`
|
||||
- `Utils::getIP()`: moved to `Internet`
|
||||
- `Utils::getMemoryUsage()`: moved to `Process`
|
||||
- `Utils::getRealMemoryUsage()`: moved to `Process`
|
||||
- `Utils::getThreadCount()`: moved to `Process`
|
||||
- `Utils::getURL()`: moved to `Internet`
|
||||
- `Utils::kill()`: moved to `Process`
|
||||
- `Utils::postURL()`: moved to `Internet`
|
||||
- `Utils::simpleCurl()`: moved to `Internet`
|
||||
- The following API fields have been removed / hidden:
|
||||
- `Utils::$ip`
|
||||
- `Utils::$online`
|
||||
- `Utils::$os`
|
||||
- The following API methods have signature changes:
|
||||
- `Internet::simpleCurl()` now requires a `Closure` for its `onSuccess` parameter instead of `callable`.
|
||||
- The following API methods have been removed:
|
||||
- `Color->setA()`
|
||||
- `Color->setR()`
|
||||
- `Color->setG()`
|
||||
- `Color->setB()`
|
||||
- `Color->toABGR()`
|
||||
- `Color->toBGRA()`
|
||||
- `Color::fromABGR()`
|
||||
- `Utils::getCallableIdentifier()`
|
@ -8,30 +8,37 @@
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"ext-bcmath": "*",
|
||||
"ext-chunkutils2": "^0.1.0",
|
||||
"ext-curl": "*",
|
||||
"ext-crypto": "^0.3.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
"ext-ds": "^1.2.7",
|
||||
"ext-gmp": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-leveldb": "^0.2.1",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-reflection": "*",
|
||||
"ext-sockets": "*",
|
||||
"ext-spl": "*",
|
||||
"ext-yaml": ">=2.0.0",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11",
|
||||
"pocketmine/raklib": "^0.12.0",
|
||||
"pocketmine/spl": "^0.3.0",
|
||||
"pocketmine/binaryutils": "^0.1.0",
|
||||
"pocketmine/nbt": "^0.2.6",
|
||||
"pocketmine/math": "^0.2.0",
|
||||
"mdanter/ecc": "^0.5.0",
|
||||
"pocketmine/raklib": "dev-master",
|
||||
"pocketmine/spl": "dev-master",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
"pocketmine/nbt": "dev-master",
|
||||
"pocketmine/math": "dev-master",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"daverandom/callback-validator": "dev-master",
|
||||
"adhocore/json-comment": "^0.0.7"
|
||||
"adhocore/json-comment": "^0.0.7",
|
||||
"particle/validator": "^2.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
297
composer.lock
generated
297
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2f5313e4ebd7b62c785cf683b27464b4",
|
||||
"content-hash": "3f4e9e3e4dfdd48390caf564839e8b46",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -91,17 +91,220 @@
|
||||
"time": "2017-04-03T15:22:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
"version": "0.1.8",
|
||||
"name": "fgrosse/phpasn1",
|
||||
"version": "v2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BinaryUtils.git",
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806"
|
||||
"url": "https://github.com/fgrosse/PHPASN1.git",
|
||||
"reference": "7ebf2a09084a7bbdb7b879c66fdf7ad80461bbe8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"url": "https://api.github.com/repos/fgrosse/PHPASN1/zipball/7ebf2a09084a7bbdb7b879c66fdf7ad80461bbe8",
|
||||
"reference": "7ebf2a09084a7bbdb7b879c66fdf7ad80461bbe8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~6.3",
|
||||
"satooshi/php-coveralls": "~2.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gmp": "GMP is the preferred extension for big integer calculations",
|
||||
"php-curl": "For loading OID information from the web if they have not bee defined statically"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FG\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Friedrich Große",
|
||||
"email": "friedrich.grosse@gmail.com",
|
||||
"homepage": "https://github.com/FGrosse",
|
||||
"role": "Author"
|
||||
},
|
||||
{
|
||||
"name": "All contributors",
|
||||
"homepage": "https://github.com/FGrosse/PHPASN1/contributors"
|
||||
}
|
||||
],
|
||||
"description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.",
|
||||
"homepage": "https://github.com/FGrosse/PHPASN1",
|
||||
"keywords": [
|
||||
"DER",
|
||||
"asn.1",
|
||||
"asn1",
|
||||
"ber",
|
||||
"binary",
|
||||
"decoding",
|
||||
"encoding",
|
||||
"x.509",
|
||||
"x.690",
|
||||
"x509",
|
||||
"x690"
|
||||
],
|
||||
"time": "2018-12-02T01:34:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mdanter/ecc",
|
||||
"version": "v0.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpecc/phpecc.git",
|
||||
"reference": "b95f25cc1bacc83a9f0ccd375900b7cfd343029e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpecc/phpecc/zipball/b95f25cc1bacc83a9f0ccd375900b7cfd343029e",
|
||||
"reference": "b95f25cc1bacc83a9f0ccd375900b7cfd343029e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-gmp": "*",
|
||||
"fgrosse/phpasn1": "^2.0",
|
||||
"php": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.0",
|
||||
"squizlabs/php_codesniffer": "^2.0",
|
||||
"symfony/yaml": "^2.6|^3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Mdanter\\Ecc\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matyas Danter",
|
||||
"homepage": "http://matejdanter.com/",
|
||||
"role": "Author"
|
||||
},
|
||||
{
|
||||
"name": "Thibaud Fabre",
|
||||
"email": "thibaud@aztech.io",
|
||||
"homepage": "http://aztech.io",
|
||||
"role": "Maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Thomas Kerin",
|
||||
"email": "afk11@users.noreply.github.com",
|
||||
"role": "Maintainer"
|
||||
}
|
||||
],
|
||||
"description": "PHP Elliptic Curve Cryptography library",
|
||||
"homepage": "https://github.com/phpecc/phpecc",
|
||||
"keywords": [
|
||||
"Diffie",
|
||||
"ECDSA",
|
||||
"Hellman",
|
||||
"curve",
|
||||
"ecdh",
|
||||
"elliptic",
|
||||
"nistp192",
|
||||
"nistp224",
|
||||
"nistp256",
|
||||
"nistp384",
|
||||
"nistp521",
|
||||
"phpecc",
|
||||
"secp256k1",
|
||||
"secp256r1"
|
||||
],
|
||||
"time": "2018-12-03T18:17:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "particle/validator",
|
||||
"version": "v2.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/particle-php/Validator.git",
|
||||
"reference": "657c7543e51938dd9d114750e49d695129527a7a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/particle-php/Validator/zipball/657c7543e51938dd9d114750e49d695129527a7a",
|
||||
"reference": "657c7543e51938dd9d114750e49d695129527a7a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"byrokrat/checkdigit": "^1.0",
|
||||
"giggsey/libphonenumber-for-php": "^7.2",
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"squizlabs/php_codesniffer": "2.*"
|
||||
},
|
||||
"suggest": {
|
||||
"byrokrat/checkdigit": "If you want to use CreditCard validation rule, this library must be installed.",
|
||||
"giggsey/libphonenumber-for-php": "If you want to use Phone validation rule, this library must be installed."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Particle\\Validator\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Berry Langerak",
|
||||
"email": "berry@berryllium.nl",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Rick van der Staaij",
|
||||
"homepage": "http://rickvanderstaaij.nl",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Flexible and highly usable validation library with no dependencies.",
|
||||
"homepage": "http://github.com/particle-php/validator",
|
||||
"keywords": [
|
||||
"validation",
|
||||
"validator"
|
||||
],
|
||||
"time": "2019-01-07T13:39:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
"version": "0.1.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BinaryUtils.git",
|
||||
"reference": "8b3b1160679398387cb896fd5d06018413437dfa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/8b3b1160679398387cb896fd5d06018413437dfa",
|
||||
"reference": "8b3b1160679398387cb896fd5d06018413437dfa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -119,23 +322,23 @@
|
||||
],
|
||||
"description": "Classes and methods for conveniently handling binary data",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.8",
|
||||
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.9",
|
||||
"issues": "https://github.com/pmmp/BinaryUtils/issues"
|
||||
},
|
||||
"time": "2019-01-16T17:31:44+00:00"
|
||||
"time": "2019-07-22T13:15:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/math",
|
||||
"version": "0.2.2",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Math.git",
|
||||
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c"
|
||||
"reference": "d436a98b85edd18d7b1542fab66827b1e6fc8d68"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Math/zipball/b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||
"url": "https://api.github.com/repos/pmmp/Math/zipball/d436a98b85edd18d7b1542fab66827b1e6fc8d68",
|
||||
"reference": "d436a98b85edd18d7b1542fab66827b1e6fc8d68",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -148,35 +351,40 @@
|
||||
"pocketmine\\math\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"pocketmine\\math\\": "tests/phpunit/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"description": "PHP library containing math related code used in PocketMine-MP",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/Math/tree/0.2.2",
|
||||
"source": "https://github.com/pmmp/Math/tree/master",
|
||||
"issues": "https://github.com/pmmp/Math/issues"
|
||||
},
|
||||
"time": "2019-01-04T15:42:36+00:00"
|
||||
"time": "2019-07-29T16:46:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/nbt",
|
||||
"version": "0.2.6",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/NBT.git",
|
||||
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4"
|
||||
"reference": "0976fcea814978c4ca7e53f5c19e459ae8e341e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
|
||||
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/0976fcea814978c4ca7e53f5c19e459ae8e341e5",
|
||||
"reference": "0976fcea814978c4ca7e53f5c19e459ae8e341e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-zlib": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"pocketmine/binaryutils": "^0.1.0"
|
||||
"pocketmine/binaryutils": "^0.1.9"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -194,35 +402,35 @@
|
||||
],
|
||||
"description": "PHP library for working with Named Binary Tags",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/NBT/tree/0.2.6",
|
||||
"source": "https://github.com/pmmp/NBT/tree/master",
|
||||
"issues": "https://github.com/pmmp/NBT/issues"
|
||||
},
|
||||
"time": "2019-02-07T16:28:11+00:00"
|
||||
"time": "2019-07-22T15:30:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/raklib",
|
||||
"version": "0.12.2",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/RakLib.git",
|
||||
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3"
|
||||
"reference": "df98f7e1a67629ee743939318810d3d2bafc5ba3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
|
||||
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/df98f7e1a67629ee743939318810d3d2bafc5ba3",
|
||||
"reference": "df98f7e1a67629ee743939318810d3d2bafc5ba3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-bcmath": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-sockets": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"php-ipv6": "*",
|
||||
"pocketmine/binaryutils": "^0.1.0",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"pocketmine/spl": "^0.3.0"
|
||||
"pocketmine/spl": "dev-master"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -235,10 +443,10 @@
|
||||
],
|
||||
"description": "A RakNet server implementation written in PHP",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/RakLib/tree/0.12",
|
||||
"source": "https://github.com/pmmp/RakLib/tree/master",
|
||||
"issues": "https://github.com/pmmp/RakLib/issues"
|
||||
},
|
||||
"time": "2019-01-21T14:17:30+00:00"
|
||||
"time": "2019-07-22T15:27:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/snooze",
|
||||
@ -276,23 +484,20 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/spl",
|
||||
"version": "0.3.2",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/SPL.git",
|
||||
"reference": "7fd53857cd000491ba69e8db865792a024dd2c49"
|
||||
"reference": "49a4b0187f2aa9daa1a9457aefa1f4cbcc5ead92"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/7fd53857cd000491ba69e8db865792a024dd2c49",
|
||||
"reference": "7fd53857cd000491ba69e8db865792a024dd2c49",
|
||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/49a4b0187f2aa9daa1a9457aefa1f4cbcc5ead92",
|
||||
"reference": "49a4b0187f2aa9daa1a9457aefa1f4cbcc5ead92",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"exclude-from-classmap": [
|
||||
"stubs"
|
||||
],
|
||||
"classmap": [
|
||||
"./"
|
||||
]
|
||||
@ -302,16 +507,19 @@
|
||||
],
|
||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/SPL/tree/0.3.2"
|
||||
"source": "https://github.com/pmmp/SPL/tree/master"
|
||||
},
|
||||
"time": "2018-08-12T15:17:39+00:00"
|
||||
"time": "2019-07-20T14:32:24+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"ext-pthreads": 20,
|
||||
"pocketmine/raklib": 20,
|
||||
"pocketmine/spl": 20,
|
||||
"pocketmine/nbt": 20,
|
||||
"pocketmine/math": 20,
|
||||
"daverandom/callback-validator": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
@ -320,16 +528,21 @@
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"ext-bcmath": "*",
|
||||
"ext-chunkutils2": "^0.1.0",
|
||||
"ext-curl": "*",
|
||||
"ext-crypto": "^0.3.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
"ext-ds": "^1.2.7",
|
||||
"ext-gmp": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-leveldb": "^0.2.1",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-reflection": "*",
|
||||
"ext-sockets": "*",
|
||||
"ext-spl": "*",
|
||||
|
File diff suppressed because it is too large
Load Diff
10
doxygen/index.md
Normal file
10
doxygen/index.md
Normal file
@ -0,0 +1,10 @@
|
||||
## PocketMine-MP API Documentation
|
||||
|
||||
This site contains auto-generated API documentation for PocketMine-MP (and dependencies which are not outsourced). Documentation here is regenerated for every release.
|
||||
|
||||
This site can be accessed via https://apidoc.pmmp.io.
|
||||
|
||||
### Additional developer resources
|
||||
- [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
|
||||
- [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||
- [DeveloperDocs](https://github.com/pmmp/DeveloperDocs/) - Reference, guides and specifications for the PocketMine-MP API
|
1
resources/locale
Submodule
1
resources/locale
Submodule
Submodule resources/locale added at 8718542e62
8
resources/plugin_list.yml
Normal file
8
resources/plugin_list.yml
Normal file
@ -0,0 +1,8 @@
|
||||
#This configuration file allows you to control which plugins are loaded on your server.
|
||||
|
||||
#List behaviour
|
||||
# - blacklist: Only plugins which ARE NOT listed will load.
|
||||
# - whitelist: Only plugins which ARE listed will load.
|
||||
mode: blacklist
|
||||
#List names of plugins here.
|
||||
plugins: []
|
@ -94,6 +94,9 @@ network:
|
||||
#Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be
|
||||
#fragmented or split into smaller parts. Clients can request MTU sizes up to but not more than this number.
|
||||
max-mtu-size: 1492
|
||||
#Enable encryption of Minecraft network traffic. This has an impact on performance, but prevents hackers from stealing sessions and pretending to be other players.
|
||||
#DO NOT DISABLE THIS unless you understand the risks involved.
|
||||
enable-encryption: true
|
||||
|
||||
debug:
|
||||
#If > 1, it will show debug messages in the console
|
||||
@ -102,13 +105,10 @@ debug:
|
||||
player:
|
||||
#Choose whether to enable player data saving.
|
||||
save-player-data: true
|
||||
anti-cheat:
|
||||
#If false, will try to prevent speed and noclip cheats. May cause movement issues.
|
||||
allow-movement-cheats: true
|
||||
|
||||
level-settings:
|
||||
#The default format that levels will use when created
|
||||
default-format: pmanvil
|
||||
default-format: leveldb
|
||||
|
||||
chunk-sending:
|
||||
#To change server normal render distance, change view-distance in server.properties.
|
||||
@ -122,8 +122,6 @@ chunk-ticking:
|
||||
per-tick: 40
|
||||
#Radius of chunks around a player to tick
|
||||
tick-radius: 3
|
||||
light-updates: false
|
||||
clear-tick-list: true
|
||||
#IDs of blocks not to perform random ticking on.
|
||||
disable-block-ticking:
|
||||
#- 2 # grass
|
1
resources/vanilla
Submodule
1
resources/vanilla
Submodule
Submodule resources/vanilla added at b5a8c68c42
@ -1,150 +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;
|
||||
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
/**
|
||||
* Handles the achievement list and a bit more
|
||||
*/
|
||||
abstract class Achievement{
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
public static $list = [
|
||||
/*"openInventory" => array(
|
||||
"name" => "Taking Inventory",
|
||||
"requires" => [],
|
||||
),*/
|
||||
"mineWood" => [
|
||||
"name" => "Getting Wood",
|
||||
"requires" => [ //"openInventory",
|
||||
]
|
||||
],
|
||||
"buildWorkBench" => [
|
||||
"name" => "Benchmarking",
|
||||
"requires" => [
|
||||
"mineWood"
|
||||
]
|
||||
],
|
||||
"buildPickaxe" => [
|
||||
"name" => "Time to Mine!",
|
||||
"requires" => [
|
||||
"buildWorkBench"
|
||||
]
|
||||
],
|
||||
"buildFurnace" => [
|
||||
"name" => "Hot Topic",
|
||||
"requires" => [
|
||||
"buildPickaxe"
|
||||
]
|
||||
],
|
||||
"acquireIron" => [
|
||||
"name" => "Acquire hardware",
|
||||
"requires" => [
|
||||
"buildFurnace"
|
||||
]
|
||||
],
|
||||
"buildHoe" => [
|
||||
"name" => "Time to Farm!",
|
||||
"requires" => [
|
||||
"buildWorkBench"
|
||||
]
|
||||
],
|
||||
"makeBread" => [
|
||||
"name" => "Bake Bread",
|
||||
"requires" => [
|
||||
"buildHoe"
|
||||
]
|
||||
],
|
||||
"bakeCake" => [
|
||||
"name" => "The Lie",
|
||||
"requires" => [
|
||||
"buildHoe"
|
||||
]
|
||||
],
|
||||
"buildBetterPickaxe" => [
|
||||
"name" => "Getting an Upgrade",
|
||||
"requires" => [
|
||||
"buildPickaxe"
|
||||
]
|
||||
],
|
||||
"buildSword" => [
|
||||
"name" => "Time to Strike!",
|
||||
"requires" => [
|
||||
"buildWorkBench"
|
||||
]
|
||||
],
|
||||
"diamonds" => [
|
||||
"name" => "DIAMONDS!",
|
||||
"requires" => [
|
||||
"acquireIron"
|
||||
]
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
* @param string $achievementId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function broadcast(Player $player, string $achievementId) : bool{
|
||||
if(isset(Achievement::$list[$achievementId])){
|
||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||
if(Server::getInstance()->getConfigBool("announce-player-achievements", true)){
|
||||
Server::getInstance()->broadcastMessage($translation);
|
||||
}else{
|
||||
$player->sendMessage($translation);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $achievementId
|
||||
* @param string $achievementName
|
||||
* @param array $requires
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function add(string $achievementId, string $achievementName, array $requires = []) : bool{
|
||||
if(!isset(Achievement::$list[$achievementId])){
|
||||
Achievement::$list[$achievementId] = [
|
||||
"name" => $achievementName,
|
||||
"requires" => $requires
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -25,7 +25,6 @@ namespace pocketmine;
|
||||
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\plugin\PluginBase;
|
||||
use pocketmine\plugin\PluginLoadOrder;
|
||||
use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
@ -56,25 +55,11 @@ use function phpversion;
|
||||
use function preg_replace;
|
||||
use function str_split;
|
||||
use function strpos;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
use function time;
|
||||
use function zend_version;
|
||||
use function zlib_encode;
|
||||
use const E_COMPILE_ERROR;
|
||||
use const E_COMPILE_WARNING;
|
||||
use const E_CORE_ERROR;
|
||||
use const E_CORE_WARNING;
|
||||
use const E_DEPRECATED;
|
||||
use const E_ERROR;
|
||||
use const E_NOTICE;
|
||||
use const E_PARSE;
|
||||
use const E_RECOVERABLE_ERROR;
|
||||
use const E_STRICT;
|
||||
use const E_USER_DEPRECATED;
|
||||
use const E_USER_ERROR;
|
||||
use const E_USER_NOTICE;
|
||||
use const E_USER_WARNING;
|
||||
use const E_WARNING;
|
||||
use const FILE_IGNORE_NEW_LINES;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
use const PHP_EOL;
|
||||
@ -134,7 +119,7 @@ class CrashDump{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function getEncodedData(){
|
||||
public function getEncodedData() : string{
|
||||
return $this->encodedData;
|
||||
}
|
||||
|
||||
@ -142,7 +127,7 @@ class CrashDump{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
private function encodeData(){
|
||||
private function encodeData() : void{
|
||||
$this->addLine();
|
||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||
$this->addLine();
|
||||
@ -158,7 +143,7 @@ class CrashDump{
|
||||
$this->addLine("===END CRASH DUMP===");
|
||||
}
|
||||
|
||||
private function pluginsData(){
|
||||
private function pluginsData() : void{
|
||||
if($this->server->getPluginManager() instanceof PluginManager){
|
||||
$this->addLine();
|
||||
$this->addLine("Loaded plugins:");
|
||||
@ -174,7 +159,7 @@ class CrashDump{
|
||||
"depends" => $d->getDepend(),
|
||||
"softDepends" => $d->getSoftDepend(),
|
||||
"main" => $d->getMain(),
|
||||
"load" => $d->getOrder() === PluginLoadOrder::POSTWORLD ? "POSTWORLD" : "STARTUP",
|
||||
"load" => strtoupper($d->getOrder()->name()),
|
||||
"website" => $d->getWebsite()
|
||||
];
|
||||
$this->addLine($d->getName() . " " . $d->getVersion() . " by " . implode(", ", $d->getAuthors()) . " for API(s) " . implode(", ", $d->getCompatibleApis()));
|
||||
@ -182,7 +167,7 @@ class CrashDump{
|
||||
}
|
||||
}
|
||||
|
||||
private function extraData(){
|
||||
private function extraData() : void{
|
||||
global $argv;
|
||||
|
||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||
@ -209,7 +194,7 @@ class CrashDump{
|
||||
}
|
||||
}
|
||||
|
||||
private function baseCrash(){
|
||||
private function baseCrash() : void{
|
||||
global $lastExceptionError, $lastError;
|
||||
|
||||
if(isset($lastExceptionError)){
|
||||
@ -217,26 +202,13 @@ class CrashDump{
|
||||
}else{
|
||||
$error = (array) error_get_last();
|
||||
$error["trace"] = Utils::currentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
||||
$errorConversion = [
|
||||
E_ERROR => "E_ERROR",
|
||||
E_WARNING => "E_WARNING",
|
||||
E_PARSE => "E_PARSE",
|
||||
E_NOTICE => "E_NOTICE",
|
||||
E_CORE_ERROR => "E_CORE_ERROR",
|
||||
E_CORE_WARNING => "E_CORE_WARNING",
|
||||
E_COMPILE_ERROR => "E_COMPILE_ERROR",
|
||||
E_COMPILE_WARNING => "E_COMPILE_WARNING",
|
||||
E_USER_ERROR => "E_USER_ERROR",
|
||||
E_USER_WARNING => "E_USER_WARNING",
|
||||
E_USER_NOTICE => "E_USER_NOTICE",
|
||||
E_STRICT => "E_STRICT",
|
||||
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
|
||||
E_DEPRECATED => "E_DEPRECATED",
|
||||
E_USER_DEPRECATED => "E_USER_DEPRECATED"
|
||||
];
|
||||
$error["fullFile"] = $error["file"];
|
||||
$error["file"] = Utils::cleanPath($error["file"]);
|
||||
$error["type"] = $errorConversion[$error["type"]] ?? $error["type"];
|
||||
try{
|
||||
$error["type"] = \ErrorUtils::errorTypeToString($error["type"]);
|
||||
}catch(\InvalidArgumentException $e){
|
||||
//pass
|
||||
}
|
||||
if(($pos = strpos($error["message"], "\n")) !== false){
|
||||
$error["message"] = substr($error["message"], 0, $pos);
|
||||
}
|
||||
@ -291,7 +263,7 @@ class CrashDump{
|
||||
|
||||
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
|
||||
$frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub
|
||||
if($frameCleanPath !== "" and strpos($frameCleanPath, "src/pocketmine/") === false and strpos($frameCleanPath, "vendor/pocketmine/") === false and file_exists($filePath)){
|
||||
if(strpos($frameCleanPath, "plugins") === 0 and file_exists($filePath)){
|
||||
$this->addLine();
|
||||
if($crashFrame){
|
||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||
@ -317,7 +289,7 @@ class CrashDump{
|
||||
return false;
|
||||
}
|
||||
|
||||
private function generalData(){
|
||||
private function generalData() : void{
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
$this->data["general"] = [];
|
||||
$this->data["general"]["name"] = $this->server->getName();
|
||||
@ -340,11 +312,11 @@ class CrashDump{
|
||||
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
|
||||
}
|
||||
|
||||
public function addLine($line = ""){
|
||||
public function addLine($line = "") : void{
|
||||
fwrite($this->fp, $line . PHP_EOL);
|
||||
}
|
||||
|
||||
public function add($str){
|
||||
public function add($str) : void{
|
||||
fwrite($this->fp, $str);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\event\server\LowMemoryEvent;
|
||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||
use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Utils;
|
||||
use function arsort;
|
||||
use function count;
|
||||
@ -109,13 +110,17 @@ class MemoryManager{
|
||||
/** @var bool */
|
||||
private $dumpWorkers = true;
|
||||
|
||||
/** @var \Logger */
|
||||
private $logger;
|
||||
|
||||
public function __construct(Server $server){
|
||||
$this->server = $server;
|
||||
$this->logger = new \PrefixedLogger($server->getLogger(), "Memory Manager");
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
private function init(){
|
||||
private function init() : void{
|
||||
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
||||
|
||||
$defaultMemory = 1024;
|
||||
@ -176,6 +181,13 @@ class MemoryManager{
|
||||
return $this->lowMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getGlobalMemoryLimit() : int{
|
||||
return $this->globalMemoryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@ -202,18 +214,18 @@ class MemoryManager{
|
||||
* @param bool $global
|
||||
* @param int $triggerCount
|
||||
*/
|
||||
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
|
||||
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
|
||||
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0) : void{
|
||||
$this->logger->debug(sprintf("%sLow memory triggered, limit %gMB, using %gMB",
|
||||
$global ? "Global " : "", round(($limit / 1024) / 1024, 2), round(($memory / 1024) / 1024, 2)));
|
||||
if($this->lowMemClearWorldCache){
|
||||
foreach($this->server->getLevels() as $level){
|
||||
$level->clearCache(true);
|
||||
foreach($this->server->getWorldManager()->getWorlds() as $world){
|
||||
$world->clearCache(true);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->lowMemChunkGC){
|
||||
foreach($this->server->getLevels() as $level){
|
||||
$level->doChunkGarbageCollection();
|
||||
foreach($this->server->getWorldManager()->getWorlds() as $world){
|
||||
$world->doChunkGarbageCollection();
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,18 +237,18 @@ class MemoryManager{
|
||||
$cycles = $this->triggerGarbageCollector();
|
||||
}
|
||||
|
||||
$this->server->getLogger()->debug(sprintf("[Memory Manager] Freed %gMB, $cycles cycles", round(($ev->getMemoryFreed() / 1024) / 1024, 2)));
|
||||
$this->logger->debug(sprintf("Freed %gMB, $cycles cycles", round(($ev->getMemoryFreed() / 1024) / 1024, 2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick to update the memory manager state.
|
||||
*/
|
||||
public function check(){
|
||||
public function check() : void{
|
||||
Timings::$memoryManagerTimer->startTiming();
|
||||
|
||||
if(($this->memoryLimit > 0 or $this->globalMemoryLimit > 0) and ++$this->checkTicker >= $this->checkRate){
|
||||
$this->checkTicker = 0;
|
||||
$memory = Utils::getMemoryUsage(true);
|
||||
$memory = Process::getMemoryUsage(true);
|
||||
$trigger = false;
|
||||
if($this->memoryLimit > 0 and $memory[0] > $this->memoryLimit){
|
||||
$trigger = 0;
|
||||
@ -277,7 +289,7 @@ class MemoryManager{
|
||||
if($this->garbageCollectionAsync){
|
||||
$pool = $this->server->getAsyncPool();
|
||||
if(($w = $pool->shutdownUnusedWorkers()) > 0){
|
||||
$this->server->getLogger()->debug("Shut down $w idle async pool workers");
|
||||
$this->logger->debug("Shut down $w idle async pool workers");
|
||||
}
|
||||
foreach($pool->getRunningWorkers() as $i){
|
||||
$pool->submitTaskToWorker(new GarbageCollectionTask(), $i);
|
||||
@ -298,9 +310,10 @@ class MemoryManager{
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*/
|
||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize, $this->server->getLogger());
|
||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize) : void{
|
||||
$logger = new \PrefixedLogger($this->server->getLogger(), "Memory Dump");
|
||||
$logger->notice("After the memory dump is done, the server might crash");
|
||||
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize, $logger);
|
||||
|
||||
if($this->dumpWorkers){
|
||||
$pool = $this->server->getAsyncPool();
|
||||
@ -321,7 +334,7 @@ class MemoryManager{
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
|
||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
|
||||
$hardLimit = ini_get('memory_limit');
|
||||
ini_set('memory_limit', '-1');
|
||||
gc_disable();
|
||||
@ -365,7 +378,7 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$logger->info("[Dump] Wrote $staticCount static properties");
|
||||
$logger->info("Wrote $staticCount static properties");
|
||||
|
||||
if(isset($GLOBALS)){ //This might be null if we're on a different thread
|
||||
$globalVariables = [];
|
||||
@ -393,7 +406,7 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$logger->info("[Dump] Wrote $globalCount global variables");
|
||||
$logger->info("Wrote $globalCount global variables");
|
||||
}
|
||||
|
||||
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
@ -454,7 +467,7 @@ class MemoryManager{
|
||||
|
||||
}while($continue);
|
||||
|
||||
$logger->info("[Dump] Wrote " . count($objects) . " objects");
|
||||
$logger->info("Wrote " . count($objects) . " objects");
|
||||
|
||||
fclose($obData);
|
||||
|
||||
@ -464,7 +477,7 @@ class MemoryManager{
|
||||
arsort($instanceCounts, SORT_NUMERIC);
|
||||
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
$logger->info("[Dump] Finished!");
|
||||
$logger->info("Finished!");
|
||||
|
||||
ini_set('memory_limit', $hardLimit);
|
||||
gc_enable();
|
||||
@ -479,7 +492,7 @@ class MemoryManager{
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*/
|
||||
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
|
||||
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : void{
|
||||
if($maxNesting <= 0){
|
||||
$data = "(error) NESTING LIMIT REACHED";
|
||||
return;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,18 +28,16 @@ namespace {
|
||||
|
||||
namespace pocketmine {
|
||||
|
||||
use pocketmine\thread\ThreadManager;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\Timezone;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.6.5";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
require_once __DIR__ . '/VersionInfo.php';
|
||||
|
||||
const MIN_PHP_VERSION = "7.2.0";
|
||||
|
||||
@ -76,11 +74,16 @@ namespace pocketmine {
|
||||
|
||||
$extensions = [
|
||||
"bcmath" => "BC Math",
|
||||
"chunkutils2" => "PocketMine ChunkUtils v2",
|
||||
"curl" => "cURL",
|
||||
"crypto" => "php-crypto",
|
||||
"ctype" => "ctype",
|
||||
"date" => "Date",
|
||||
"ds" => "Data Structures",
|
||||
"gmp" => "GMP",
|
||||
"hash" => "Hash",
|
||||
"json" => "JSON",
|
||||
"leveldb" => "LevelDB",
|
||||
"mbstring" => "Multibyte String",
|
||||
"openssl" => "OpenSSL",
|
||||
"pcre" => "PCRE",
|
||||
@ -105,8 +108,8 @@ namespace pocketmine {
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.7dev") < 0){
|
||||
$messages[] = "pthreads >= 3.1.7dev is required, while you have $pthreads_version.";
|
||||
if(version_compare($pthreads_version, "3.2.0") < 0){
|
||||
$messages[] = "pthreads >= 3.2.0 is required, while you have $pthreads_version.";
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,149 +127,175 @@ namespace pocketmine {
|
||||
return $messages;
|
||||
}
|
||||
|
||||
if(!empty($messages = check_platform_dependencies())){
|
||||
echo PHP_EOL;
|
||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
||||
foreach($messages as $m){
|
||||
echo " - $m" . PHP_EOL;
|
||||
}
|
||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||
echo PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
unset($messages);
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}else{
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->register(false);
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", '-1');
|
||||
|
||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard"]);
|
||||
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
if(!file_exists(\pocketmine\DATA)){
|
||||
mkdir(\pocketmine\DATA, 0777, true);
|
||||
}
|
||||
|
||||
//Logger has a dependency on timezone
|
||||
$tzError = Timezone::init();
|
||||
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||
$logger->registerStatic();
|
||||
|
||||
foreach($tzError as $e){
|
||||
$logger->warning($e);
|
||||
}
|
||||
unset($tzError);
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Utils::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
$gitHash = trim($out);
|
||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
function server(){
|
||||
if(!empty($messages = check_platform_dependencies())){
|
||||
echo PHP_EOL;
|
||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
||||
foreach($messages as $m){
|
||||
echo " - $m" . PHP_EOL;
|
||||
}
|
||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||
echo PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
unset($messages);
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
if(extension_loaded('parallel')){
|
||||
\parallel\bootstrap(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}
|
||||
}else{
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
\ErrorUtils::setErrorExceptionHandler();
|
||||
|
||||
$exitCode = 0;
|
||||
do{
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->register(false);
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", '-1');
|
||||
|
||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'resources' . DIRECTORY_SEPARATOR);
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
if(!file_exists(\pocketmine\DATA)){
|
||||
mkdir(\pocketmine\DATA, 0777, true);
|
||||
}
|
||||
|
||||
define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock');
|
||||
define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "a+b"));
|
||||
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
|
||||
//wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the
|
||||
//other server wrote its PID and released exclusive lock before we get our lock
|
||||
flock(\pocketmine\LOCK_FILE, LOCK_SH);
|
||||
$pid = stream_get_contents(\pocketmine\LOCK_FILE);
|
||||
critical_error("Another " . \pocketmine\NAME . " instance (PID $pid) is already using this folder (" . realpath(\pocketmine\DATA) . ").");
|
||||
critical_error("Please stop the other server first before running a new one.");
|
||||
exit(1);
|
||||
}
|
||||
ftruncate(\pocketmine\LOCK_FILE, 0);
|
||||
fwrite(\pocketmine\LOCK_FILE, (string) getmypid());
|
||||
fflush(\pocketmine\LOCK_FILE);
|
||||
flock(\pocketmine\LOCK_FILE, LOCK_SH); //prevent acquiring an exclusive lock from another process, but allow reading
|
||||
|
||||
//Logger has a dependency on timezone
|
||||
Timezone::init();
|
||||
|
||||
if(isset($opts["enable-ansi"])){
|
||||
Terminal::init(true);
|
||||
}elseif(isset($opts["disable-ansi"])){
|
||||
Terminal::init(false);
|
||||
}else{
|
||||
Terminal::init();
|
||||
}
|
||||
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||
\GlobalLogger::set($logger);
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Process::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
$gitHash = trim($out);
|
||||
if(Process::execute("git diff --quiet") === 1 or Process::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: move this to a Server field
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start(PTHREADS_INHERIT_NONE);
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
$exitCode = 0;
|
||||
do{
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Utils::kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
//TODO: move this to a Server field
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
exit($exitCode);
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start(PTHREADS_INHERIT_NONE);
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
Process::kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
|
||||
exit($exitCode);
|
||||
}
|
||||
|
||||
\pocketmine\server();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
27
src/pocketmine/VersionInfo.php
Normal file
27
src/pocketmine/VersionInfo.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "4.0.0";
|
||||
const IS_DEVELOPMENT_BUILD = true;
|
||||
const BUILD_NUMBER = 0;
|
@ -25,11 +25,5 @@ namespace pocketmine\block;
|
||||
|
||||
class ActivatorRail extends RedstoneRail{
|
||||
|
||||
protected $id = self::ACTIVATOR_RAIL;
|
||||
|
||||
public function getName() : string{
|
||||
return "Activator Rail";
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -23,31 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
|
||||
/**
|
||||
* Air block
|
||||
*/
|
||||
class Air extends Transparent{
|
||||
|
||||
protected $id = self::AIR;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Air";
|
||||
}
|
||||
|
||||
public function canPassThrough() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? BlockBreakInfo::indestructible(0.0));
|
||||
}
|
||||
|
||||
public function canBeFlowedInto() : bool{
|
||||
@ -73,12 +57,4 @@ class Air extends Transparent{
|
||||
public function getCollisionBoxes() : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getBlastResistance() : float{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -23,93 +23,60 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\Fallable;
|
||||
use pocketmine\block\utils\FallableTrait;
|
||||
use pocketmine\inventory\AnvilInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\ToolTier;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class Anvil extends Fallable{
|
||||
class Anvil extends Transparent implements Fallable{
|
||||
use FallableTrait;
|
||||
|
||||
public const TYPE_NORMAL = 0;
|
||||
public const TYPE_SLIGHTLY_DAMAGED = 4;
|
||||
public const TYPE_VERY_DAMAGED = 8;
|
||||
/** @var int */
|
||||
protected $facing = Facing::NORTH;
|
||||
|
||||
protected $id = self::ANVIL;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(5.0, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 6000.0));
|
||||
}
|
||||
|
||||
public function isTransparent() : bool{
|
||||
return true;
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing);
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta);
|
||||
}
|
||||
|
||||
public function getBlastResistance() : float{
|
||||
return 6000;
|
||||
public function getStateBitmask() : int{
|
||||
return 0b11;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x0c;
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8);
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
self::TYPE_NORMAL => "Anvil",
|
||||
self::TYPE_SLIGHTLY_DAMAGED => "Slightly Damaged Anvil",
|
||||
self::TYPE_VERY_DAMAGED => "Very Damaged Anvil"
|
||||
];
|
||||
return $names[$this->getVariant()] ?? "Anvil";
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
$inset = 0.125;
|
||||
|
||||
if($this->meta & 0x01){ //east/west
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + $inset,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1 - $inset
|
||||
);
|
||||
}else{
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $inset,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1 - $inset,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->addWindow(new AnvilInventory($this));
|
||||
$player->setCurrentWindow(new AnvilInventory($this));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
|
||||
$this->meta = $this->getVariant() | $direction;
|
||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$this->facing = Facing::rotateY($player->getHorizontalFacing(), true);
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function tickFalling() : ?Block{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
194
src/pocketmine/block/Banner.php
Normal file
194
src/pocketmine/block/Banner.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?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 Ds\Deque;
|
||||
use pocketmine\block\tile\Banner as TileBanner;
|
||||
use pocketmine\block\utils\BannerPattern;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\item\Banner as ItemBanner;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\ItemIds;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function assert;
|
||||
use function floor;
|
||||
|
||||
class Banner extends Transparent{
|
||||
/** @var BlockIdentifierFlattened */
|
||||
protected $idInfo;
|
||||
|
||||
//TODO: conditionally useless properties, find a way to fix
|
||||
|
||||
/** @var int */
|
||||
protected $rotation = 0;
|
||||
|
||||
/** @var int */
|
||||
protected $facing = Facing::UP;
|
||||
|
||||
/** @var DyeColor */
|
||||
protected $baseColor;
|
||||
|
||||
/** @var Deque|BannerPattern[] */
|
||||
protected $patterns;
|
||||
|
||||
public function __construct(BlockIdentifierFlattened $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(1.0, BlockToolType::AXE));
|
||||
$this->baseColor = DyeColor::BLACK();
|
||||
$this->patterns = new Deque();
|
||||
}
|
||||
|
||||
public function __clone(){
|
||||
$this->patterns = $this->patterns->map(Utils::cloneCallback());
|
||||
}
|
||||
|
||||
public function getId() : int{
|
||||
return $this->facing === Facing::UP ? parent::getId() : $this->idInfo->getSecondId();
|
||||
}
|
||||
|
||||
protected function writeStateToMeta() : int{
|
||||
if($this->facing === Facing::UP){
|
||||
return $this->rotation;
|
||||
}
|
||||
return BlockDataSerializer::writeHorizontalFacing($this->facing);
|
||||
}
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
if($id === $this->idInfo->getSecondId()){
|
||||
$this->facing = BlockDataSerializer::readHorizontalFacing($stateMeta);
|
||||
}else{
|
||||
$this->facing = Facing::UP;
|
||||
$this->rotation = $stateMeta;
|
||||
}
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : void{
|
||||
parent::readStateFromWorld();
|
||||
$tile = $this->world->getTile($this);
|
||||
if($tile instanceof TileBanner){
|
||||
$this->baseColor = $tile->getBaseColor();
|
||||
$this->setPatterns($tile->getPatterns());
|
||||
}
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->world->getTile($this);
|
||||
assert($tile instanceof TileBanner);
|
||||
$tile->setBaseColor($this->baseColor);
|
||||
$tile->setPatterns($this->patterns);
|
||||
}
|
||||
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: interface method? this is only the BASE colour...
|
||||
* @return DyeColor
|
||||
*/
|
||||
public function getColor() : DyeColor{
|
||||
return $this->baseColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Deque|BannerPattern[]
|
||||
*/
|
||||
public function getPatterns() : Deque{
|
||||
return $this->patterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Deque|BannerPattern[] $patterns
|
||||
*/
|
||||
public function setPatterns(Deque $patterns) : void{
|
||||
$checked = $patterns->filter(function($v){ return $v instanceof BannerPattern; });
|
||||
if($checked->count() !== $patterns->count()){
|
||||
throw new \TypeError("Deque must only contain " . BannerPattern::class . " objects");
|
||||
}
|
||||
$this->patterns = $checked;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($item instanceof ItemBanner){
|
||||
$this->baseColor = $item->getColor();
|
||||
$this->setPatterns($item->getPatterns());
|
||||
}
|
||||
if($face !== Facing::DOWN){
|
||||
$this->facing = $face;
|
||||
if($face === Facing::UP){
|
||||
$this->rotation = $player !== null ? ((int) floor((($player->yaw + 180) * 16 / 360) + 0.5)) & 0x0f : 0;
|
||||
}
|
||||
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Facing::opposite($this->facing))->getId() === BlockLegacyIds::AIR){
|
||||
$this->getWorld()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return ItemFactory::get(ItemIds::BANNER, $this->baseColor->getInvertedMagicNumber());
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
$drop = $this->asItem();
|
||||
if($drop instanceof ItemBanner and !$this->patterns->isEmpty()){
|
||||
$drop->setPatterns($this->patterns);
|
||||
}
|
||||
|
||||
return [$drop];
|
||||
}
|
||||
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
$result = $this->asItem();
|
||||
if($addUserData and $result instanceof ItemBanner and !$this->patterns->isEmpty()){
|
||||
$result->setPatterns($this->patterns);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -23,9 +23,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\InvalidBlockStateException;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function array_map;
|
||||
use function array_reverse;
|
||||
use function array_search;
|
||||
@ -36,69 +39,76 @@ use function in_array;
|
||||
|
||||
abstract class BaseRail extends Flowable{
|
||||
|
||||
public const STRAIGHT_NORTH_SOUTH = 0;
|
||||
public const STRAIGHT_EAST_WEST = 1;
|
||||
public const ASCENDING_EAST = 2;
|
||||
public const ASCENDING_WEST = 3;
|
||||
public const ASCENDING_NORTH = 4;
|
||||
public const ASCENDING_SOUTH = 5;
|
||||
|
||||
private const ASCENDING_SIDES = [
|
||||
self::ASCENDING_NORTH => Vector3::SIDE_NORTH,
|
||||
self::ASCENDING_EAST => Vector3::SIDE_EAST,
|
||||
self::ASCENDING_SOUTH => Vector3::SIDE_SOUTH,
|
||||
self::ASCENDING_WEST => Vector3::SIDE_WEST
|
||||
];
|
||||
|
||||
protected const FLAG_ASCEND = 1 << 24; //used to indicate direction-up
|
||||
|
||||
protected const CONNECTIONS = [
|
||||
//straights
|
||||
self::STRAIGHT_NORTH_SOUTH => [
|
||||
Vector3::SIDE_NORTH,
|
||||
Vector3::SIDE_SOUTH
|
||||
BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH => [
|
||||
Facing::NORTH,
|
||||
Facing::SOUTH
|
||||
],
|
||||
self::STRAIGHT_EAST_WEST => [
|
||||
Vector3::SIDE_EAST,
|
||||
Vector3::SIDE_WEST
|
||||
BlockLegacyMetadata::RAIL_STRAIGHT_EAST_WEST => [
|
||||
Facing::EAST,
|
||||
Facing::WEST
|
||||
],
|
||||
|
||||
//ascending
|
||||
self::ASCENDING_EAST => [
|
||||
Vector3::SIDE_WEST,
|
||||
Vector3::SIDE_EAST | self::FLAG_ASCEND
|
||||
BlockLegacyMetadata::RAIL_ASCENDING_EAST => [
|
||||
Facing::WEST,
|
||||
Facing::EAST | self::FLAG_ASCEND
|
||||
],
|
||||
self::ASCENDING_WEST => [
|
||||
Vector3::SIDE_EAST,
|
||||
Vector3::SIDE_WEST | self::FLAG_ASCEND
|
||||
BlockLegacyMetadata::RAIL_ASCENDING_WEST => [
|
||||
Facing::EAST,
|
||||
Facing::WEST | self::FLAG_ASCEND
|
||||
],
|
||||
self::ASCENDING_NORTH => [
|
||||
Vector3::SIDE_SOUTH,
|
||||
Vector3::SIDE_NORTH | self::FLAG_ASCEND
|
||||
BlockLegacyMetadata::RAIL_ASCENDING_NORTH => [
|
||||
Facing::SOUTH,
|
||||
Facing::NORTH | self::FLAG_ASCEND
|
||||
],
|
||||
self::ASCENDING_SOUTH => [
|
||||
Vector3::SIDE_NORTH,
|
||||
Vector3::SIDE_SOUTH | self::FLAG_ASCEND
|
||||
BlockLegacyMetadata::RAIL_ASCENDING_SOUTH => [
|
||||
Facing::NORTH,
|
||||
Facing::SOUTH | self::FLAG_ASCEND
|
||||
]
|
||||
];
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
/** @var int[] */
|
||||
protected $connections = [];
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.7));
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.7;
|
||||
protected function writeStateToMeta() : int{
|
||||
if(empty($this->connections)){
|
||||
return BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH;
|
||||
}
|
||||
return $this->getMetaForState($this->connections);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if(!$blockReplace->getSide(Vector3::SIDE_DOWN)->isTransparent() and $this->getLevel()->setBlock($blockReplace, $this, true, true)){
|
||||
$this->tryReconnect();
|
||||
return true;
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$connections = $this->getConnectionsFromMeta($stateMeta);
|
||||
if($connections === null){
|
||||
throw new InvalidBlockStateException("Invalid rail type meta $stateMeta");
|
||||
}
|
||||
$this->connections = $connections;
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
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()){
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onPostPlace() : void{
|
||||
$this->tryReconnect();
|
||||
}
|
||||
|
||||
protected static function searchState(array $connections, array $lookup) : int{
|
||||
$meta = array_search($connections, $lookup, true);
|
||||
if($meta === false){
|
||||
@ -127,9 +137,11 @@ abstract class BaseRail extends Flowable{
|
||||
/**
|
||||
* Returns the connection directions of this rail (depending on the current block state)
|
||||
*
|
||||
* @param int $meta
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
abstract protected function getConnectionsForState() : array;
|
||||
abstract protected function getConnectionsFromMeta(int $meta) : ?array;
|
||||
|
||||
/**
|
||||
* Returns all the directions this rail is already connected in.
|
||||
@ -141,21 +153,21 @@ abstract class BaseRail extends Flowable{
|
||||
$connections = [];
|
||||
|
||||
/** @var int $connection */
|
||||
foreach($this->getConnectionsForState() as $connection){
|
||||
foreach($this->connections as $connection){
|
||||
$other = $this->getSide($connection & ~self::FLAG_ASCEND);
|
||||
$otherConnection = Vector3::getOppositeSide($connection & ~self::FLAG_ASCEND);
|
||||
$otherConnection = Facing::opposite($connection & ~self::FLAG_ASCEND);
|
||||
|
||||
if(($connection & self::FLAG_ASCEND) !== 0){
|
||||
$other = $other->getSide(Vector3::SIDE_UP);
|
||||
$other = $other->getSide(Facing::UP);
|
||||
|
||||
}elseif(!($other instanceof BaseRail)){ //check for rail sloping up to meet this one
|
||||
$other = $other->getSide(Vector3::SIDE_DOWN);
|
||||
$other = $other->getSide(Facing::DOWN);
|
||||
$otherConnection |= self::FLAG_ASCEND;
|
||||
}
|
||||
|
||||
if(
|
||||
$other instanceof BaseRail and
|
||||
in_array($otherConnection, $other->getConnectionsForState(), true)
|
||||
in_array($otherConnection, $other->connections, true)
|
||||
){
|
||||
$connections[] = $connection;
|
||||
}
|
||||
@ -169,10 +181,10 @@ abstract class BaseRail extends Flowable{
|
||||
case 0:
|
||||
//No constraints, can connect in any direction
|
||||
$possible = [
|
||||
Vector3::SIDE_NORTH => true,
|
||||
Vector3::SIDE_SOUTH => true,
|
||||
Vector3::SIDE_WEST => true,
|
||||
Vector3::SIDE_EAST => true
|
||||
Facing::NORTH => true,
|
||||
Facing::SOUTH => true,
|
||||
Facing::WEST => true,
|
||||
Facing::EAST => true
|
||||
];
|
||||
foreach($possible as $p => $_){
|
||||
$possible[$p | self::FLAG_ASCEND] = true;
|
||||
@ -189,7 +201,7 @@ abstract class BaseRail extends Flowable{
|
||||
}
|
||||
|
||||
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
|
||||
$opposite = Vector3::getOppositeSide($constraint & ~self::FLAG_ASCEND);
|
||||
$opposite = Facing::opposite($constraint & ~self::FLAG_ASCEND);
|
||||
|
||||
$possible = [$opposite => true];
|
||||
|
||||
@ -210,15 +222,15 @@ abstract class BaseRail extends Flowable{
|
||||
$continue = false;
|
||||
|
||||
foreach($possible as $thisSide => $_){
|
||||
$otherSide = Vector3::getOppositeSide($thisSide & ~self::FLAG_ASCEND);
|
||||
$otherSide = Facing::opposite($thisSide & ~self::FLAG_ASCEND);
|
||||
|
||||
$other = $this->getSide($thisSide & ~self::FLAG_ASCEND);
|
||||
|
||||
if(($thisSide & self::FLAG_ASCEND) !== 0){
|
||||
$other = $other->getSide(Vector3::SIDE_UP);
|
||||
$other = $other->getSide(Facing::UP);
|
||||
|
||||
}elseif(!($other instanceof BaseRail)){ //check if other rails can slope up to meet this one
|
||||
$other = $other->getSide(Vector3::SIDE_DOWN);
|
||||
$other = $other->getSide(Facing::DOWN);
|
||||
$otherSide |= self::FLAG_ASCEND;
|
||||
}
|
||||
|
||||
@ -231,7 +243,8 @@ abstract class BaseRail extends Flowable{
|
||||
|
||||
if(isset($otherPossible[$otherSide])){
|
||||
$otherConnections[] = $otherSide;
|
||||
$other->updateState($otherConnections);
|
||||
$other->setConnections($otherConnections);
|
||||
$other->world->setBlock($other, $other);
|
||||
|
||||
$changed = true;
|
||||
$thisConnections[] = $thisSide;
|
||||
@ -243,31 +256,31 @@ abstract class BaseRail extends Flowable{
|
||||
}while($continue);
|
||||
|
||||
if($changed){
|
||||
$this->updateState($thisConnections);
|
||||
$this->setConnections($thisConnections);
|
||||
$this->world->setBlock($this, $this);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateState(array $connections) : void{
|
||||
private function setConnections(array $connections) : void{
|
||||
if(count($connections) === 1){
|
||||
$connections[] = Vector3::getOppositeSide($connections[0] & ~self::FLAG_ASCEND);
|
||||
$connections[] = Facing::opposite($connections[0] & ~self::FLAG_ASCEND);
|
||||
}elseif(count($connections) !== 2){
|
||||
throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections));
|
||||
}
|
||||
|
||||
$this->meta = $this->getMetaForState($connections);
|
||||
$this->level->setBlock($this, $this, false, false); //avoid recursion
|
||||
$this->connections = $connections;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() or (
|
||||
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
|
||||
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
|
||||
)){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
if($this->getSide(Facing::DOWN)->isTransparent()){
|
||||
$this->world->useBreakOn($this);
|
||||
}else{
|
||||
foreach($this->connections as $connection){
|
||||
if(($connection & self::FLAG_ASCEND) !== 0 and $this->getSide($connection & ~self::FLAG_ASCEND)->isTransparent()){
|
||||
$this->world->useBreakOn($this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -23,118 +23,116 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Bed as TileBed;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\item\Bed as ItemBed;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Bed as TileBed;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\World;
|
||||
|
||||
class Bed extends Transparent{
|
||||
public const BITFLAG_OCCUPIED = 0x04;
|
||||
public const BITFLAG_HEAD = 0x08;
|
||||
|
||||
protected $id = self::BED_BLOCK;
|
||||
/** @var int */
|
||||
protected $facing = Facing::NORTH;
|
||||
/** @var bool */
|
||||
protected $occupied = false;
|
||||
/** @var bool */
|
||||
protected $head = false;
|
||||
/** @var DyeColor */
|
||||
protected $color;
|
||||
|
||||
protected $itemId = Item::BED;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.2));
|
||||
$this->color = DyeColor::RED();
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.2;
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) |
|
||||
($this->occupied ? BlockLegacyMetadata::BED_FLAG_OCCUPIED : 0) |
|
||||
($this->head ? BlockLegacyMetadata::BED_FLAG_HEAD : 0);
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Bed Block";
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$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();
|
||||
//read extra state information from the tile - this is an ugly hack
|
||||
$tile = $this->world->getTile($this);
|
||||
if($tile instanceof TileBed){
|
||||
$this->color = $tile->getColor();
|
||||
}
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
//extra block properties storage hack
|
||||
$tile = $this->world->getTile($this);
|
||||
if($tile instanceof TileBed){
|
||||
$tile->setColor($this->color);
|
||||
}
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.5625,
|
||||
$this->z + 1
|
||||
);
|
||||
return AxisAlignedBB::one()->trim(Facing::UP, 7 / 16);
|
||||
}
|
||||
|
||||
public function isHeadPart() : bool{
|
||||
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
||||
return $this->head;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOccupied() : bool{
|
||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||
return $this->occupied;
|
||||
}
|
||||
|
||||
public function setOccupied(bool $occupied = true){
|
||||
if($occupied){
|
||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
||||
}else{
|
||||
$this->meta &= ~self::BITFLAG_OCCUPIED;
|
||||
}
|
||||
public function setOccupied(bool $occupied = true) : void{
|
||||
$this->occupied = $occupied;
|
||||
$this->world->setBlock($this, $this, false);
|
||||
|
||||
$this->getLevel()->setBlock($this, $this, false, false);
|
||||
|
||||
if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){
|
||||
$other->setOccupied($occupied);
|
||||
if(($other = $this->getOtherHalf()) !== null){
|
||||
$other->occupied = $occupied;
|
||||
$this->world->setBlock($other, $other, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta
|
||||
* @param bool $isHead
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
|
||||
$rotation = $meta & 0x03;
|
||||
$side = -1;
|
||||
|
||||
switch($rotation){
|
||||
case 0x00: //South
|
||||
$side = Vector3::SIDE_SOUTH;
|
||||
break;
|
||||
case 0x01: //West
|
||||
$side = Vector3::SIDE_WEST;
|
||||
break;
|
||||
case 0x02: //North
|
||||
$side = Vector3::SIDE_NORTH;
|
||||
break;
|
||||
case 0x03: //East
|
||||
$side = Vector3::SIDE_EAST;
|
||||
break;
|
||||
}
|
||||
|
||||
if($isHead){
|
||||
$side = Vector3::getOppositeSide($side);
|
||||
}
|
||||
|
||||
return $side;
|
||||
private function getOtherHalfSide() : int{
|
||||
return $this->head ? Facing::opposite($this->facing) : $this->facing;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Bed|null
|
||||
*/
|
||||
public function getOtherHalf() : ?Bed{
|
||||
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
|
||||
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
|
||||
$other = $this->getSide($this->getOtherHalfSide());
|
||||
if($other instanceof Bed and $other->head !== $this->head and $other->facing === $this->facing){
|
||||
return $other;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$other = $this->getOtherHalf();
|
||||
if($other === null){
|
||||
@ -146,9 +144,9 @@ class Bed extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
|
||||
$time = $this->getWorld()->getTimeOfDay();
|
||||
|
||||
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
|
||||
$isNight = ($time >= World::TIME_NIGHT and $time < World::TIME_SUNRISE);
|
||||
|
||||
if(!$isNight){
|
||||
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.noSleep"));
|
||||
@ -171,18 +169,19 @@ class Bed extends Transparent{
|
||||
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($item instanceof ItemBed){ //TODO: the item should do this
|
||||
$this->color = $item->getColor();
|
||||
}
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
if(!$down->isTransparent()){
|
||||
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
||||
$next = $this->getSide(self::getOtherHalfSide($meta));
|
||||
if($next->canBeReplaced() and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
|
||||
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
|
||||
|
||||
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this, $face, $item, $player));
|
||||
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player));
|
||||
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
|
||||
|
||||
$next = $this->getSide($this->getOtherHalfSide());
|
||||
if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){
|
||||
$nextState = clone $this;
|
||||
$nextState->head = true;
|
||||
$tx->addBlock($blockReplace, $this)->addBlock($next, $nextState);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -190,29 +189,16 @@ class Bed extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if($this->isHeadPart()){
|
||||
return [$this->getItem()];
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->head){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return $this->getItem();
|
||||
}
|
||||
|
||||
private function getItem() : Item{
|
||||
$tile = $this->getLevel()->getTile($this);
|
||||
if($tile instanceof TileBed){
|
||||
return ItemFactory::get($this->getItemId(), $tile->getColor());
|
||||
}
|
||||
|
||||
return ItemFactory::get($this->getItemId(), 14); //Red
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
public function asItem() : Item{
|
||||
return ItemFactory::get($this->idInfo->getItemId(), $this->color->getMagicNumber());
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
|
@ -23,29 +23,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
class Bedrock extends Opaque{
|
||||
|
||||
class Bedrock extends Solid{
|
||||
/** @var bool */
|
||||
private $burnsForever = false;
|
||||
|
||||
protected $id = self::BEDROCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? BlockBreakInfo::indestructible());
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Bedrock";
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->burnsForever = ($stateMeta & BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN) !== 0;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->burnsForever ? BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN : 0;
|
||||
}
|
||||
|
||||
public function getBlastResistance() : float{
|
||||
return 18000000;
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
public function burnsForever() : bool{
|
||||
return $this->burnsForever;
|
||||
}
|
||||
}
|
||||
|
@ -24,35 +24,25 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use function mt_rand;
|
||||
|
||||
class Beetroot extends Crops{
|
||||
|
||||
protected $id = self::BEETROOT_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Beetroot Block";
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if($this->meta >= 0x07){
|
||||
if($this->age >= 7){
|
||||
return [
|
||||
ItemFactory::get(Item::BEETROOT),
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
||||
VanillaItems::BEETROOT(),
|
||||
VanillaItems::BEETROOT_SEEDS()->setCount(mt_rand(0, 3))
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS)
|
||||
VanillaItems::BEETROOT_SEEDS()
|
||||
];
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get(Item::BEETROOT_SEEDS);
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
return VanillaItems::BEETROOT_SEEDS();
|
||||
}
|
||||
}
|
||||
|
@ -26,90 +26,88 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Spawnable;
|
||||
use pocketmine\block\tile\Tile;
|
||||
use pocketmine\block\tile\TileFactory;
|
||||
use pocketmine\block\utils\InvalidBlockStateException;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\metadata\Metadatable;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\World;
|
||||
use function array_merge;
|
||||
use function get_class;
|
||||
use function assert;
|
||||
use function dechex;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
class Block extends Position implements BlockIds, Metadatable{
|
||||
class Block extends Position{
|
||||
|
||||
/**
|
||||
* Returns a new Block instance with the specified ID, meta and position.
|
||||
*
|
||||
* This function redirects to {@link BlockFactory#get}.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $meta
|
||||
* @param Position|null $pos
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
|
||||
return BlockFactory::get($id, $meta, $pos);
|
||||
}
|
||||
/** @var BlockIdentifier */
|
||||
protected $idInfo;
|
||||
|
||||
/** @var int */
|
||||
protected $id;
|
||||
/** @var int */
|
||||
protected $meta = 0;
|
||||
/** @var string|null */
|
||||
/** @var string */
|
||||
protected $fallbackName;
|
||||
/** @var int|null */
|
||||
protected $itemId;
|
||||
|
||||
/** @var BlockBreakInfo */
|
||||
protected $breakInfo;
|
||||
|
||||
|
||||
/** @var AxisAlignedBB */
|
||||
protected $boundingBox = null;
|
||||
|
||||
|
||||
/** @var AxisAlignedBB[]|null */
|
||||
protected $collisionBoxes = null;
|
||||
|
||||
/**
|
||||
* @param int $id The block type's ID, 0-255
|
||||
* @param int $meta Meta value of the block type
|
||||
* @param string|null $name English name of the block type (TODO: implement translations)
|
||||
* @param int $itemId The item ID of the block type, used for block picking and dropping items.
|
||||
* @param BlockIdentifier $idInfo
|
||||
* @param string $name English name of the block type (TODO: implement translations)
|
||||
* @param BlockBreakInfo $breakInfo
|
||||
*/
|
||||
public function __construct(int $id, int $meta = 0, string $name = null, int $itemId = null){
|
||||
$this->id = $id;
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
||||
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->fallbackName = $name;
|
||||
$this->itemId = $itemId;
|
||||
$this->breakInfo = $breakInfo;
|
||||
}
|
||||
|
||||
public function getIdInfo() : BlockIdentifier{
|
||||
return $this->idInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string{
|
||||
return $this->fallbackName ?? "Unknown";
|
||||
return $this->fallbackName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getId() : int{
|
||||
return $this->id;
|
||||
public function getId() : int{
|
||||
return $this->idInfo->getBlockId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the item form of the block.
|
||||
* Used for drops for blocks (some blocks such as doors have a different item ID).
|
||||
*
|
||||
* @internal
|
||||
* @return int
|
||||
*/
|
||||
public function getItemId() : int{
|
||||
return $this->itemId ?? $this->getId();
|
||||
public function getFullId() : int{
|
||||
return ($this->getId() << 4) | $this->getMeta();
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return ItemFactory::get($this->idInfo->getItemId(), $this->idInfo->getVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,48 +115,97 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return int
|
||||
*/
|
||||
public function getRuntimeId() : int{
|
||||
return BlockFactory::toStaticRuntimeId($this->getId(), $this->getDamage());
|
||||
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getDamage() : int{
|
||||
return $this->meta;
|
||||
public function getMeta() : int{
|
||||
$stateMeta = $this->writeStateToMeta();
|
||||
assert(($stateMeta & ~$this->getStateBitmask()) === 0);
|
||||
return $this->idInfo->getVariant() | $stateMeta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a bitmask used to extract state bits from block metadata.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStateBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function writeStateToMeta() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta
|
||||
* @param int $id
|
||||
* @param int $stateMeta
|
||||
*
|
||||
* @throws InvalidBlockStateException
|
||||
*/
|
||||
final public function setDamage(int $meta) : void{
|
||||
if($meta < 0 or $meta > 0xf){
|
||||
throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta");
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Clears any cached precomputed objects, such as bounding boxes. Remove any outdated precomputed things such as
|
||||
* AABBs and force recalculation.
|
||||
*/
|
||||
public function readStateFromWorld() : void{
|
||||
$this->boundingBox = null;
|
||||
$this->collisionBoxes = null;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
$this->world->getChunkAtPosition($this)->setFullBlock($this->x & 0xf, $this->y, $this->z & 0xf, $this->getFullId());
|
||||
|
||||
$tileType = $this->idInfo->getTileClass();
|
||||
$oldTile = $this->world->getTile($this);
|
||||
if($oldTile !== null){
|
||||
if($tileType === null or !($oldTile instanceof $tileType)){
|
||||
$oldTile->close();
|
||||
$oldTile = null;
|
||||
}elseif($oldTile instanceof Spawnable){
|
||||
$oldTile->setDirty(); //destroy old network cache
|
||||
}
|
||||
}
|
||||
if($oldTile === null and $tileType !== null){
|
||||
$this->world->addTile(TileFactory::create($tileType, $this->world, $this->asVector3()));
|
||||
}
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitmask to use to remove superfluous information from block meta when getting its item form or name.
|
||||
* This defaults to -1 (don't remove any data). Used to remove rotation data and bitflags from block drops.
|
||||
* Returns whether the given block has an equivalent type to this one. This compares base legacy ID and variant.
|
||||
*
|
||||
* If your block should not have any meta value when it's dropped as an item, override this to return 0 in
|
||||
* descendent classes.
|
||||
* 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.
|
||||
*
|
||||
* @return int
|
||||
* @param Block $other
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getVariantBitmask() : int{
|
||||
return -1;
|
||||
public function isSameType(Block $other) : bool{
|
||||
return $this->idInfo->getBlockId() === $other->idInfo->getBlockId() and $this->idInfo->getVariant() === $other->idInfo->getVariant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block meta, stripped of non-variant flags.
|
||||
* @return int
|
||||
* Returns whether the given block has the same type and properties as this block.
|
||||
*
|
||||
* @param Block $other
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getVariant() : int{
|
||||
return $this->meta & $this->getVariantBitmask();
|
||||
public function isSameState(Block $other) : bool{
|
||||
return $this->isSameType($other) and $this->writeStateToMeta() === $other->writeStateToMeta();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AKA: Block->isPlaceable
|
||||
* @return bool
|
||||
@ -181,73 +228,32 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
|
||||
*
|
||||
* @param Item $item
|
||||
* @param Block $blockReplace
|
||||
* @param Block $blockClicked
|
||||
* @param int $face
|
||||
* @param Vector3 $clickVector
|
||||
* @param Player|null $player
|
||||
* @param BlockTransaction $tx
|
||||
* @param Item $item
|
||||
* @param Block $blockReplace
|
||||
* @param Block $blockClicked
|
||||
* @param int $face
|
||||
* @param Vector3 $clickVector
|
||||
* @param Player|null $player
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
return $this->getLevel()->setBlock($this, $this, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the block can be broken with an specific Item
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBreakable(Item $item) : bool{
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$tx->addBlock($blockReplace, $this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_NONE;
|
||||
public function onPostPlace() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the level of tool required to harvest this block (for normal blocks). When the tool type matches the
|
||||
* block's required tool type, the tool must have a harvest level greater than or equal to this value to be able to
|
||||
* successfully harvest the block.
|
||||
* Returns an object containing information about the destruction requirements of this block.
|
||||
*
|
||||
* If the block requires a specific minimum tier of tiered tool, the minimum tier required should be returned.
|
||||
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
||||
*
|
||||
* @see Item::getBlockToolHarvestLevel()
|
||||
*
|
||||
* @return int
|
||||
* @return BlockBreakInfo
|
||||
*/
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified item is the proper tool to use for breaking this block. This checks tool type and
|
||||
* harvest level requirement.
|
||||
*
|
||||
* In most cases this is also used to determine whether block drops should be created or not, except in some
|
||||
* special cases such as vines.
|
||||
*
|
||||
* @param Item $tool
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCompatibleWithTool(Item $tool) : bool{
|
||||
if($this->getHardness() < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$toolType = $this->getToolType();
|
||||
$harvestLevel = $this->getToolHarvestLevel();
|
||||
return $toolType === BlockToolType::TYPE_NONE or $harvestLevel === 0 or (
|
||||
($toolType & $tool->getBlockToolType()) !== 0 and $tool->getBlockToolHarvestLevel() >= $harvestLevel);
|
||||
public function getBreakInfo() : BlockBreakInfo{
|
||||
return $this->breakInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,35 +264,12 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the seconds that this block takes to be broken using an specific Item
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return float
|
||||
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||
*/
|
||||
public function getBreakTime(Item $item) : float{
|
||||
$base = $this->getHardness();
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
$base *= 1.5;
|
||||
}else{
|
||||
$base *= 5;
|
||||
public function onBreak(Item $item, ?Player $player = null) : bool{
|
||||
if(($t = $this->world->getTile($this)) !== null){
|
||||
$t->onBlockDestroyed();
|
||||
}
|
||||
|
||||
$efficiency = $item->getMiningEfficiency($this);
|
||||
if($efficiency <= 0){
|
||||
throw new \InvalidArgumentException(get_class($item) . " has invalid mining efficiency: expected >= 0, got $efficiency");
|
||||
}
|
||||
|
||||
$base /= $efficiency;
|
||||
|
||||
return $base;
|
||||
$this->getWorld()->setBlock($this, VanillaBlocks::AIR());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -314,38 +297,38 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is updated by the delayed blockupdate scheduler in the level.
|
||||
* Called when this block is updated by the delayed blockupdate scheduler in the world.
|
||||
*/
|
||||
public function onScheduledUpdate() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Do actions when activated by Item. Returns if it has done anything
|
||||
* Do actions when interacted by Item. Returns if it has done anything
|
||||
*
|
||||
* @param Item $item
|
||||
* @param int $face
|
||||
* @param Vector3 $clickVector
|
||||
* @param Player|null $player
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a base value used to compute block break times.
|
||||
* @return float
|
||||
* Called when this block is attacked (left-clicked). This is called when a player left-clicks the block to try and
|
||||
* start to break it in survival mode.
|
||||
*
|
||||
* @param Item $item
|
||||
* @param int $face
|
||||
* @param Player|null $player
|
||||
*
|
||||
* @return bool if an action took place, prevents starting to break the block if true.
|
||||
*/
|
||||
public function getHardness() : float{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||
* @return float
|
||||
*/
|
||||
public function getBlastResistance() : float{
|
||||
return $this->getHardness() * 5;
|
||||
public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,7 +352,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return int 0-15
|
||||
*/
|
||||
public function getLightFilter() : int{
|
||||
return 15;
|
||||
return $this->isTransparent() ? 0 : 15;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -408,10 +391,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canPassThrough() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether entities can climb up this block.
|
||||
* @return bool
|
||||
@ -426,16 +405,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the block position to a new Position object
|
||||
* @internal
|
||||
*
|
||||
* @param Position $v
|
||||
* @param World $world
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*/
|
||||
final public function position(Position $v) : void{
|
||||
$this->x = (int) $v->x;
|
||||
$this->y = (int) $v->y;
|
||||
$this->z = (int) $v->z;
|
||||
$this->level = $v->level;
|
||||
$this->boundingBox = null;
|
||||
final public function position(World $world, int $x, int $y, int $z) : void{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
$this->world = $world;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -446,8 +427,8 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
if($this->isAffectedBySilkTouch() and $item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||
if($this->breakInfo->isToolCompatible($item)){
|
||||
if($this->isAffectedBySilkTouch() and $item->hasEnchantment(Enchantment::SILK_TOUCH())){
|
||||
return $this->getSilkTouchDrops($item);
|
||||
}
|
||||
|
||||
@ -465,9 +446,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), $this->getVariant())
|
||||
];
|
||||
return [$this->asItem()];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -478,9 +457,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getSilkTouchDrops(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), $this->getVariant())
|
||||
];
|
||||
return [$this->asItem()];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -491,7 +468,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return int
|
||||
*/
|
||||
public function getXpDropForTool(Item $item) : int{
|
||||
if($item->hasEnchantment(Enchantment::SILK_TOUCH) or !$this->isCompatibleWithTool($item)){
|
||||
if($item->hasEnchantment(Enchantment::SILK_TOUCH()) or !$this->breakInfo->isToolCompatible($item)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -519,10 +496,24 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns the item that players will equip when middle-clicking on this block.
|
||||
*
|
||||
* @param bool $addUserData
|
||||
*
|
||||
* @return Item
|
||||
*/
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get($this->getItemId(), $this->getVariant());
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
$item = $this->asItem();
|
||||
if($addUserData){
|
||||
$tile = $this->world->getTile($this);
|
||||
if($tile instanceof Tile){
|
||||
$nbt = $tile->getCleanedNBT();
|
||||
if($nbt instanceof CompoundTag){
|
||||
$item->setCustomBlockData($nbt);
|
||||
$item->setLore(["+(DATA)"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -587,10 +578,10 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
*/
|
||||
public function getSide(int $side, int $step = 1){
|
||||
if($this->isValid()){
|
||||
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
|
||||
return $this->getWorld()->getBlock(Vector3::getSide($side, $step));
|
||||
}
|
||||
|
||||
return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));
|
||||
throw new \InvalidStateException("Block does not have a valid world");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -600,10 +591,10 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
*/
|
||||
public function getHorizontalSides() : array{
|
||||
return [
|
||||
$this->getSide(Vector3::SIDE_NORTH),
|
||||
$this->getSide(Vector3::SIDE_SOUTH),
|
||||
$this->getSide(Vector3::SIDE_WEST),
|
||||
$this->getSide(Vector3::SIDE_EAST)
|
||||
$this->getSide(Facing::NORTH),
|
||||
$this->getSide(Facing::SOUTH),
|
||||
$this->getSide(Facing::WEST),
|
||||
$this->getSide(Facing::EAST)
|
||||
];
|
||||
}
|
||||
|
||||
@ -615,8 +606,8 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
public function getAllSides() : array{
|
||||
return array_merge(
|
||||
[
|
||||
$this->getSide(Vector3::SIDE_DOWN),
|
||||
$this->getSide(Vector3::SIDE_UP)
|
||||
$this->getSide(Facing::DOWN),
|
||||
$this->getSide(Facing::UP)
|
||||
],
|
||||
$this->getHorizontalSides()
|
||||
);
|
||||
@ -636,7 +627,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(){
|
||||
return "Block[" . $this->getName() . "] (" . $this->getId() . ":" . $this->getDamage() . ")";
|
||||
return "Block[" . $this->getName() . "] (" . $this->getId() . ":" . $this->getMeta() . ")";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -657,9 +648,12 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
public function onEntityInside(Entity $entity) : void{
|
||||
|
||||
}
|
||||
|
||||
@ -669,6 +663,9 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
public function getCollisionBoxes() : array{
|
||||
if($this->collisionBoxes === null){
|
||||
$this->collisionBoxes = $this->recalculateCollisionBoxes();
|
||||
foreach($this->collisionBoxes as $bb){
|
||||
$bb->offset($this->x, $this->y, $this->z);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->collisionBoxes;
|
||||
@ -691,6 +688,9 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
public function getBoundingBox() : ?AxisAlignedBB{
|
||||
if($this->boundingBox === null){
|
||||
$this->boundingBox = $this->recalculateBoundingBox();
|
||||
if($this->boundingBox !== null){
|
||||
$this->boundingBox->offset($this->x, $this->y, $this->z);
|
||||
}
|
||||
}
|
||||
return $this->boundingBox;
|
||||
}
|
||||
@ -699,23 +699,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return AxisAlignedBB|null
|
||||
*/
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any cached precomputed objects, such as bounding boxes. This is called on block neighbour update and when
|
||||
* the block is set into the world to remove any outdated precomputed things such as AABBs and force recalculation.
|
||||
*/
|
||||
public function clearCaches() : void{
|
||||
$this->boundingBox = null;
|
||||
$this->collisionBoxes = null;
|
||||
return AxisAlignedBB::one();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -751,31 +735,15 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return $currentHit;
|
||||
}
|
||||
|
||||
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
||||
if($this->isValid()){
|
||||
$this->level->getBlockMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
||||
}
|
||||
}
|
||||
|
||||
public function getMetadata(string $metadataKey){
|
||||
if($this->isValid()){
|
||||
return $this->level->getBlockMetadata()->getMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hasMetadata(string $metadataKey) : bool{
|
||||
if($this->isValid()){
|
||||
return $this->level->getBlockMetadata()->hasMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
||||
if($this->isValid()){
|
||||
$this->level->getBlockMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||
/**
|
||||
* @param self $self
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function cast(self $self){
|
||||
if(!($self instanceof static)){
|
||||
throw new \TypeError("Cannot cast from " . self::class . " to " . static::class);
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
}
|
||||
|
165
src/pocketmine/block/BlockBreakInfo.php
Normal file
165
src/pocketmine/block/BlockBreakInfo.php
Normal file
@ -0,0 +1,165 @@
|
||||
<?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\item\Item;
|
||||
use function get_class;
|
||||
|
||||
class BlockBreakInfo{
|
||||
|
||||
/** @var float */
|
||||
private $hardness;
|
||||
/** @var float */
|
||||
private $blastResistance;
|
||||
/** @var int */
|
||||
private $toolType;
|
||||
/** @var int */
|
||||
private $toolHarvestLevel;
|
||||
|
||||
/**
|
||||
* @param float $hardness
|
||||
* @param int $toolType
|
||||
* @param int $toolHarvestLevel
|
||||
* @param float|null $blastResistance default 5x hardness
|
||||
*/
|
||||
public function __construct(float $hardness, int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0, ?float $blastResistance = null){
|
||||
$this->hardness = $hardness;
|
||||
$this->toolType = $toolType;
|
||||
$this->toolHarvestLevel = $toolHarvestLevel;
|
||||
$this->blastResistance = $blastResistance ?? $hardness * 5;
|
||||
}
|
||||
|
||||
public static function instant(int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0) : self{
|
||||
return new self(0.0, $toolType, $toolHarvestLevel, 0.0);
|
||||
}
|
||||
|
||||
public static function indestructible(float $blastResistance = 18000000.0) : self{
|
||||
return new self(-1.0, BlockToolType::NONE, 0, $blastResistance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a base value used to compute block break times.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getHardness() : float{
|
||||
return $this->hardness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the block can be broken at all.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBreakable() : bool{
|
||||
return $this->hardness >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block can be instantly broken.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function breaksInstantly() : bool{
|
||||
return $this->hardness == 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getBlastResistance() : float{
|
||||
return $this->blastResistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getToolType() : int{
|
||||
return $this->toolType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the level of tool required to harvest the block (for normal blocks). When the tool type matches the
|
||||
* block's required tool type, the tool must have a harvest level greater than or equal to this value to be able to
|
||||
* successfully harvest the block.
|
||||
*
|
||||
* If the block requires a specific minimum tier of tiered tool, the minimum tier required should be returned.
|
||||
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
||||
*
|
||||
* @see Item::getBlockToolHarvestLevel()
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getToolHarvestLevel() : int{
|
||||
return $this->toolHarvestLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified item is the proper tool to use for breaking this block. This checks tool type and
|
||||
* harvest level requirement.
|
||||
*
|
||||
* In most cases this is also used to determine whether block drops should be created or not, except in some
|
||||
* special cases such as vines.
|
||||
*
|
||||
* @param Item $tool
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isToolCompatible(Item $tool) : bool{
|
||||
if($this->hardness < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->toolType === BlockToolType::NONE or $this->toolHarvestLevel === 0 or (
|
||||
($this->toolType & $tool->getBlockToolType()) !== 0 and $tool->getBlockToolHarvestLevel() >= $this->toolHarvestLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the seconds that this block takes to be broken using an specific Item
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return float
|
||||
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||
*/
|
||||
public function getBreakTime(Item $item) : float{
|
||||
$base = $this->hardness;
|
||||
if($this->isToolCompatible($item)){
|
||||
$base *= 1.5;
|
||||
}else{
|
||||
$base *= 5;
|
||||
}
|
||||
|
||||
$efficiency = $item->getMiningEfficiency(($this->toolType & $item->getBlockToolType()) !== 0);
|
||||
if($efficiency <= 0){
|
||||
throw new \InvalidArgumentException(get_class($item) . " has invalid mining efficiency: expected >= 0, got $efficiency");
|
||||
}
|
||||
|
||||
$base /= $efficiency;
|
||||
|
||||
return $base;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
78
src/pocketmine/block/BlockIdentifier.php
Normal file
78
src/pocketmine/block/BlockIdentifier.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?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;
|
||||
|
||||
class BlockIdentifier{
|
||||
|
||||
/** @var int */
|
||||
private $blockId;
|
||||
/** @var int */
|
||||
private $variant;
|
||||
/** @var int|null */
|
||||
private $itemId;
|
||||
/** @var string|null */
|
||||
private $tileClass;
|
||||
|
||||
public function __construct(int $blockId, int $variant = 0, ?int $itemId = null, ?string $tileClass = null){
|
||||
$this->blockId = $blockId;
|
||||
$this->variant = $variant;
|
||||
$this->itemId = $itemId;
|
||||
$this->tileClass = $tileClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockId() : int{
|
||||
return $this->blockId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getAllBlockIds() : array{
|
||||
return [$this->blockId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getVariant() : int{
|
||||
return $this->variant;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getItemId() : int{
|
||||
return $this->itemId ?? ($this->blockId > 255 ? 255 - $this->blockId : $this->blockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTileClass() : ?string{
|
||||
return $this->tileClass;
|
||||
}
|
||||
}
|
@ -21,31 +21,26 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\event\player;
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\Player;
|
||||
class BlockIdentifierFlattened extends BlockIdentifier{
|
||||
|
||||
/**
|
||||
* Called when a player does an animation
|
||||
*/
|
||||
class PlayerAnimationEvent extends PlayerEvent implements Cancellable{
|
||||
/** @var int */
|
||||
private $animationType;
|
||||
private $secondId;
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
* @param int $animation
|
||||
*/
|
||||
public function __construct(Player $player, int $animation){
|
||||
$this->player = $player;
|
||||
$this->animationType = $animation;
|
||||
public function __construct(int $blockId, int $secondId, int $variant = 0, ?int $itemId = null, ?string $tileClass = null){
|
||||
parent::__construct($blockId, $variant, $itemId, $tileClass);
|
||||
$this->secondId = $secondId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getAnimationType() : int{
|
||||
return $this->animationType;
|
||||
public function getSecondId() : int{
|
||||
return $this->secondId;
|
||||
}
|
||||
|
||||
public function getAllBlockIds() : array{
|
||||
return [$this->getBlockId(), $this->getSecondId()];
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
interface BlockIds{
|
||||
interface BlockLegacyIds{
|
||||
|
||||
public const AIR = 0;
|
||||
public const STONE = 1;
|
||||
@ -42,7 +42,7 @@ interface BlockIds{
|
||||
public const GOLD_ORE = 14;
|
||||
public const IRON_ORE = 15;
|
||||
public const COAL_ORE = 16;
|
||||
public const LOG = 17, WOOD = 17;
|
||||
public const LOG = 17;
|
||||
public const LEAVES = 18;
|
||||
public const SPONGE = 19;
|
||||
public const GLASS = 20;
|
||||
@ -61,7 +61,7 @@ interface BlockIds{
|
||||
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;
|
||||
@ -187,11 +187,11 @@ interface BlockIds{
|
||||
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, WOOD2 = 162;
|
||||
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;
|
||||
@ -215,7 +215,9 @@ interface BlockIds{
|
||||
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;
|
||||
@ -225,9 +227,9 @@ interface BlockIds{
|
||||
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;
|
||||
@ -259,7 +261,8 @@ interface BlockIds{
|
||||
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;
|
||||
|
||||
@ -273,7 +276,222 @@ interface BlockIds{
|
||||
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;
|
||||
|
||||
}
|
240
src/pocketmine/block/BlockLegacyMetadata.php
Normal file
240
src/pocketmine/block/BlockLegacyMetadata.php
Normal file
@ -0,0 +1,240 @@
|
||||
<?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.
|
||||
*/
|
||||
interface BlockLegacyMetadata{
|
||||
|
||||
public const ANVIL_NORMAL = 0;
|
||||
public const ANVIL_SLIGHTLY_DAMAGED = 4;
|
||||
public const ANVIL_VERY_DAMAGED = 8;
|
||||
|
||||
public const BED_FLAG_HEAD = 0x08;
|
||||
public const BED_FLAG_OCCUPIED = 0x04;
|
||||
|
||||
public const BEDROCK_FLAG_INFINIBURN = 0x01;
|
||||
|
||||
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 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 DIRT_NORMAL = 0;
|
||||
public const DIRT_COARSE = 1;
|
||||
|
||||
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 LEVER_FLAG_POWERED = 0x08;
|
||||
|
||||
public const LIQUID_FLAG_FALLING = 0x08;
|
||||
|
||||
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 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_NORMAL = 0;
|
||||
public const TNT_UNDERWATER = 2;
|
||||
|
||||
public const TNT_FLAG_UNSTABLE = 0x01;
|
||||
|
||||
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;
|
||||
}
|
@ -29,11 +29,11 @@ namespace pocketmine\block;
|
||||
*/
|
||||
interface BlockToolType{
|
||||
|
||||
public const TYPE_NONE = 0;
|
||||
public const TYPE_SWORD = 1 << 0;
|
||||
public const TYPE_SHOVEL = 1 << 1;
|
||||
public const TYPE_PICKAXE = 1 << 2;
|
||||
public const TYPE_AXE = 1 << 3;
|
||||
public const TYPE_SHEARS = 1 << 4;
|
||||
public const NONE = 0;
|
||||
public const SWORD = 1 << 0;
|
||||
public const SHOVEL = 1 << 1;
|
||||
public const PICKAXE = 1 << 2;
|
||||
public const AXE = 1 << 3;
|
||||
public const SHEARS = 1 << 4;
|
||||
|
||||
}
|
||||
|
45
src/pocketmine/block/BlueIce.php
Normal file
45
src/pocketmine/block/BlueIce.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?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\item\Item;
|
||||
|
||||
class BlueIce extends Opaque{
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(2.8, BlockToolType::PICKAXE));
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getFrictionFactor() : float{
|
||||
return 0.99;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -23,42 +23,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\PillarRotationHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\block\utils\PillarRotationTrait;
|
||||
use pocketmine\item\ToolTier;
|
||||
|
||||
class BoneBlock extends Solid{
|
||||
class BoneBlock extends Opaque{
|
||||
use PillarRotationTrait;
|
||||
|
||||
protected $id = Block::BONE_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Bone Block";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x03;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(2.0, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel()));
|
||||
}
|
||||
}
|
||||
|
@ -24,31 +24,17 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\VanillaItems;
|
||||
|
||||
class Bookshelf extends Solid{
|
||||
class Bookshelf extends Opaque{
|
||||
|
||||
protected $id = self::BOOKSHELF;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Bookshelf";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 1.5;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(1.5, BlockToolType::AXE));
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::BOOK, 0, 3)
|
||||
VanillaItems::BOOK()->setCount(3)
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -23,38 +23,53 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\ToolTier;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class BrewingStand extends Transparent{
|
||||
|
||||
protected $id = self::BREWING_STAND_BLOCK;
|
||||
/** @var bool */
|
||||
protected $eastSlot = false;
|
||||
/** @var bool */
|
||||
protected $northwestSlot = false;
|
||||
/** @var bool */
|
||||
protected $southwestSlot = false;
|
||||
|
||||
protected $itemId = Item::BREWING_STAND;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.5, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel()));
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Brewing Stand";
|
||||
protected function writeStateToMeta() : int{
|
||||
return ($this->eastSlot ? BlockLegacyMetadata::BREWING_STAND_FLAG_EAST : 0) |
|
||||
($this->southwestSlot ? BlockLegacyMetadata::BREWING_STAND_FLAG_SOUTHWEST : 0) |
|
||||
($this->northwestSlot ? BlockLegacyMetadata::BREWING_STAND_FLAG_NORTHWEST : 0);
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->eastSlot = ($stateMeta & BlockLegacyMetadata::BREWING_STAND_FLAG_EAST) !== 0;
|
||||
$this->southwestSlot = ($stateMeta & BlockLegacyMetadata::BREWING_STAND_FLAG_SOUTHWEST) !== 0;
|
||||
$this->northwestSlot = ($stateMeta & BlockLegacyMetadata::BREWING_STAND_FLAG_NORTHWEST) !== 0;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
public function getStateBitmask() : int{
|
||||
return 0b111;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$stand = $this->getWorld()->getTile($this);
|
||||
if($stand instanceof TileBrewingStand and $stand->canOpenWith($item->getCustomName())){
|
||||
$player->setCurrentWindow($stand->getInventory());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
public function onScheduledUpdate() : void{
|
||||
//TODO
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -25,12 +25,6 @@ namespace pocketmine\block;
|
||||
|
||||
class BrownMushroom extends RedMushroom{
|
||||
|
||||
protected $id = self::BROWN_MUSHROOM;
|
||||
|
||||
public function getName() : string{
|
||||
return "Brown Mushroom";
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
@ -28,15 +28,9 @@ use function mt_rand;
|
||||
|
||||
class BrownMushroomBlock extends RedMushroomBlock{
|
||||
|
||||
protected $id = Block::BROWN_MUSHROOM_BLOCK;
|
||||
|
||||
public function getName() : string{
|
||||
return "Brown Mushroom Block";
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
Item::get(Item::BROWN_MUSHROOM, 0, mt_rand(0, 2))
|
||||
VanillaBlocks::BROWN_MUSHROOM()->asItem()->setCount(mt_rand(0, 2))
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,98 +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\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Furnace as TileFurnace;
|
||||
use pocketmine\tile\Tile;
|
||||
|
||||
class BurningFurnace extends Solid{
|
||||
|
||||
protected $id = self::BURNING_FURNACE;
|
||||
|
||||
protected $itemId = self::FURNACE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Burning Furnace";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 3.5;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 13;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$faces = [
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3
|
||||
];
|
||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$furnace = $this->getLevel()->getTile($this);
|
||||
if(!($furnace instanceof TileFurnace)){
|
||||
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
||||
}
|
||||
|
||||
if(!$furnace->canOpenWith($item->getCustomName())){
|
||||
return true;
|
||||
}
|
||||
|
||||
$player->addWindow($furnace->getInventory());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -23,29 +23,60 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\RedstonePowerOffSound;
|
||||
use pocketmine\world\sound\RedstonePowerOnSound;
|
||||
|
||||
abstract class Button extends Flowable{
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
/** @var int */
|
||||
protected $facing = Facing::DOWN;
|
||||
/** @var bool */
|
||||
protected $powered = false;
|
||||
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeFacing($this->facing) | ($this->powered ? BlockLegacyMetadata::BUTTON_FLAG_POWERED : 0);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
//TODO: in PC it's (6 - facing) for every meta except 0 (down)
|
||||
$this->facing = BlockDataSerializer::readFacing($stateMeta & 0x07);
|
||||
$this->powered = ($stateMeta & BlockLegacyMetadata::BUTTON_FLAG_POWERED) !== 0;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
//TODO: check valid target block
|
||||
$this->meta = $face;
|
||||
|
||||
return $this->level->setBlock($this, $this, true, true);
|
||||
$this->facing = $face;
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
//TODO
|
||||
abstract protected function getActivationTime() : int;
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(!$this->powered){
|
||||
$this->powered = true;
|
||||
$this->world->setBlock($this, $this);
|
||||
$this->world->scheduleDelayedBlockUpdate($this, $this->getActivationTime());
|
||||
$this->world->addSound($this->add(0.5, 0.5, 0.5), new RedstonePowerOnSound());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onScheduledUpdate() : void{
|
||||
if($this->powered){
|
||||
$this->powered = false;
|
||||
$this->world->setBlock($this, $this);
|
||||
$this->world->addSound($this->add(0.5, 0.5, 0.5), new RedstonePowerOffSound());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,61 +23,62 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class Cactus extends Transparent{
|
||||
|
||||
protected $id = self::CACTUS;
|
||||
/** @var int */
|
||||
protected $age = 0;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.4));
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.4;
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->age;
|
||||
}
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, 15);
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Cactus";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625,
|
||||
$this->y + 0.0625,
|
||||
$this->z + 0.0625,
|
||||
$this->x + 0.9375,
|
||||
$this->y + 0.9375,
|
||||
$this->z + 0.9375
|
||||
);
|
||||
static $shrinkSize = 1 / 16;
|
||||
return AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize);
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
public function onEntityInside(Entity $entity) : void{
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||
$entity->attack($ev);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
if($down->getId() !== BlockLegacyIds::SAND and !$down->isSameType($this)){
|
||||
$this->getWorld()->useBreakOn($this);
|
||||
}else{
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
foreach(Facing::HORIZONTAL as $side){
|
||||
$b = $this->getSide($side);
|
||||
if($b->isSolid()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
$this->getWorld()->useBreakOn($this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -89,48 +90,42 @@ class Cactus extends Transparent{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
||||
if($this->meta === 0x0f){
|
||||
if(!$this->getSide(Facing::DOWN)->isSameType($this)){
|
||||
if($this->age === 15){
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||
if($b->getId() === self::AIR){
|
||||
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
|
||||
$b = $this->getWorld()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||
if($b->getId() === BlockLegacyIds::AIR){
|
||||
$ev = new BlockGrowEvent($b, VanillaBlocks::CACTUS());
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
break;
|
||||
}
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
$this->getWorld()->setBlock($b, $ev->getNewState());
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
$this->age = 0;
|
||||
$this->getWorld()->setBlock($this, $this);
|
||||
}else{
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
++$this->age;
|
||||
$this->getWorld()->setBlock($this, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === self::SAND or $down->getId() === self::CACTUS){
|
||||
$block0 = $this->getSide(Vector3::SIDE_NORTH);
|
||||
$block1 = $this->getSide(Vector3::SIDE_SOUTH);
|
||||
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
||||
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
||||
if(!$block0->isSolid() and !$block1->isSolid() and !$block2->isSolid() and !$block3->isSolid()){
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return true;
|
||||
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->getId() === BlockLegacyIds::SAND or $down->isSameType($this)){
|
||||
foreach(Facing::HORIZONTAL as $side){
|
||||
if($this->getSide($side)->isSolid()){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -23,60 +23,57 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\EffectInstance;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\entity\effect\EffectInstance;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\item\FoodSource;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class Cake extends Transparent implements FoodSource{
|
||||
|
||||
protected $id = self::CAKE_BLOCK;
|
||||
/** @var int */
|
||||
protected $bites = 0;
|
||||
|
||||
protected $itemId = Item::CAKE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.5));
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->bites;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Cake";
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->bites = BlockDataSerializer::readBoundedInt("bites", $stateMeta, 0, 6);
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b111;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
$f = $this->getDamage() * 0.125; //1 slice width
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625 + $f,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
$this->x + 1 - 0.0625,
|
||||
$this->y + 0.5,
|
||||
$this->z + 1 - 0.0625
|
||||
);
|
||||
return AxisAlignedBB::one()
|
||||
->contract(1 / 16, 0, 1 / 16)
|
||||
->trim(Facing::UP, 0.5)
|
||||
->trim(Facing::WEST, $this->bites / 8);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::AIR){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
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->getId() !== BlockLegacyIds::AIR){
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){ //Replace with common break method
|
||||
$this->getWorld()->setBlock($this, VanillaBlocks::AIR());
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +85,7 @@ class Cake extends Transparent implements FoodSource{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$player->consumeObject($this);
|
||||
return true;
|
||||
@ -114,9 +111,9 @@ class Cake extends Transparent implements FoodSource{
|
||||
*/
|
||||
public function getResidue(){
|
||||
$clone = clone $this;
|
||||
$clone->meta++;
|
||||
if($clone->meta > 0x06){
|
||||
$clone = BlockFactory::get(Block::AIR);
|
||||
$clone->bites++;
|
||||
if($clone->bites > 6){
|
||||
$clone = VanillaBlocks::AIR();
|
||||
}
|
||||
return $clone;
|
||||
}
|
||||
@ -129,6 +126,6 @@ class Cake extends Transparent implements FoodSource{
|
||||
}
|
||||
|
||||
public function onConsume(Living $consumer) : void{
|
||||
$this->level->setBlock($this, $this->getResidue());
|
||||
$this->world->setBlock($this, $this->getResidue());
|
||||
}
|
||||
}
|
||||
|
@ -23,58 +23,39 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class Carpet extends Flowable{
|
||||
|
||||
protected $id = self::CARPET;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.1;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.1));
|
||||
}
|
||||
|
||||
public function isSolid() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Carpet";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.0625,
|
||||
$this->z + 1
|
||||
);
|
||||
return AxisAlignedBB::one()->trim(Facing::UP, 15 / 16);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::AIR){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
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->getId() !== BlockLegacyIds::AIR){
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){
|
||||
$this->getWorld()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,28 +24,18 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use function mt_rand;
|
||||
|
||||
class Carrot extends Crops{
|
||||
|
||||
protected $id = self::CARROT_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Carrot Block";
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1)
|
||||
VanillaItems::CARROT()->setCount($this->age >= 7 ? mt_rand(1, 4) : 1)
|
||||
];
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get(Item::CARROT);
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
return VanillaItems::CARROT();
|
||||
}
|
||||
}
|
||||
|
56
src/pocketmine/block/CarvedPumpkin.php
Normal file
56
src/pocketmine/block/CarvedPumpkin.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?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\BlockDataSerializer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class CarvedPumpkin extends Opaque{
|
||||
|
||||
/** @var int */
|
||||
protected $facing = Facing::NORTH;
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
|
||||
}
|
||||
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing);
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b11;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
}
|
@ -23,112 +23,89 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Chest as TileChest;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Chest as TileChest;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class Chest extends Transparent{
|
||||
|
||||
protected $id = self::CHEST;
|
||||
/** @var int */
|
||||
protected $facing = Facing::NORTH;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(2.5, BlockToolType::AXE));
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2.5;
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeHorizontalFacing($this->facing);
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Chest";
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->facing = BlockDataSerializer::readHorizontalFacing($stateMeta);
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
public function getStateBitmask() : int{
|
||||
return 0b111;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
//these are slightly bigger than in PC
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.025,
|
||||
$this->y,
|
||||
$this->z + 0.025,
|
||||
$this->x + 0.975,
|
||||
$this->y + 0.95,
|
||||
$this->z + 0.975
|
||||
);
|
||||
return AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$faces = [
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3
|
||||
];
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
}
|
||||
|
||||
$chest = null;
|
||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
if(($this->meta === 4 or $this->meta === 5) and ($side === 4 or $side === 5)){
|
||||
continue;
|
||||
}elseif(($this->meta === 3 or $this->meta === 2) and ($side === 2 or $side === 3)){
|
||||
continue;
|
||||
}
|
||||
$c = $this->getSide($side);
|
||||
if($c->getId() === $this->id and $c->getDamage() === $this->meta){
|
||||
$tile = $this->getLevel()->getTile($c);
|
||||
if($tile instanceof TileChest and !$tile->isPaired()){
|
||||
$chest = $tile;
|
||||
break;
|
||||
public function onPostPlace() : void{
|
||||
$tile = $this->world->getTile($this);
|
||||
if($tile instanceof TileChest){
|
||||
foreach([
|
||||
Facing::rotateY($this->facing, true),
|
||||
Facing::rotateY($this->facing, false)
|
||||
] as $side){
|
||||
$c = $this->getSide($side);
|
||||
if($c instanceof Chest and $c->isSameType($this) and $c->facing === $this->facing){
|
||||
$pair = $this->world->getTile($c);
|
||||
if($pair instanceof TileChest and !$pair->isPaired()){
|
||||
$pair->pairWith($tile);
|
||||
$tile->pairWith($pair);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
$tile = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this, $face, $item, $player));
|
||||
|
||||
if($chest instanceof TileChest and $tile instanceof TileChest){
|
||||
$chest->pairWith($tile);
|
||||
$tile->pairWith($chest);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
|
||||
$t = $this->getLevel()->getTile($this);
|
||||
$chest = null;
|
||||
if($t instanceof TileChest){
|
||||
$chest = $t;
|
||||
}else{
|
||||
$chest = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this));
|
||||
}
|
||||
$chest = $this->getWorld()->getTile($this);
|
||||
if($chest instanceof TileChest){
|
||||
if(
|
||||
!$this->getSide(Facing::UP)->isTransparent() or
|
||||
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Facing::UP)->isTransparent()) or
|
||||
!$chest->canOpenWith($item->getCustomName())
|
||||
){
|
||||
return true;
|
||||
}
|
||||
|
||||
if(
|
||||
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
||||
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
||||
!$chest->canOpenWith($item->getCustomName())
|
||||
){
|
||||
return true;
|
||||
$player->setCurrentWindow($chest->getInventory());
|
||||
}
|
||||
|
||||
$player->addWindow($chest->getInventory());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
|
@ -24,31 +24,17 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\VanillaItems;
|
||||
|
||||
class Clay extends Solid{
|
||||
class Clay extends Opaque{
|
||||
|
||||
protected $id = self::CLAY_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Clay Block";
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.6, BlockToolType::SHOVEL));
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::CLAY_BALL, 0, 4)
|
||||
VanillaItems::CLAY()->setCount(4)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -23,30 +23,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\ToolTier;
|
||||
|
||||
class Coal extends Solid{
|
||||
class Coal extends Opaque{
|
||||
|
||||
protected $id = self::COAL_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Coal Block";
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(5.0, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0));
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
|
@ -24,37 +24,19 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\ToolTier;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use function mt_rand;
|
||||
|
||||
class CoalOre extends Solid{
|
||||
class CoalOre extends Opaque{
|
||||
|
||||
protected $id = self::COAL_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Coal Ore";
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(3.0, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel()));
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::COAL)
|
||||
VanillaItems::COAL()
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -23,29 +23,21 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Hoe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class InvisibleBedrock extends Transparent{
|
||||
class CoarseDirt extends Dirt{
|
||||
|
||||
protected $id = self::INVISIBLE_BEDROCK;
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($face === Facing::UP and $item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
$this->getWorld()->setBlock($this, VanillaBlocks::DIRT());
|
||||
return true;
|
||||
}
|
||||
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Invisible Bedrock";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getBlastResistance() : float{
|
||||
return 18000000;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,117 +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\item\TieredTool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class CobblestoneWall extends Transparent{
|
||||
public const NONE_MOSSY_WALL = 0;
|
||||
public const MOSSY_WALL = 1;
|
||||
public const GRANITE_WALL = 2;
|
||||
public const DIORITE_WALL = 3;
|
||||
public const ANDESITE_WALL = 4;
|
||||
public const SANDSTONE_WALL = 5;
|
||||
public const BRICK_WALL = 6;
|
||||
public const STONE_BRICK_WALL = 7;
|
||||
public const MOSSY_STONE_BRICK_WALL = 8;
|
||||
public const NETHER_BRICK_WALL = 9;
|
||||
public const END_STONE_BRICK_WALL = 10;
|
||||
public const PRISMARINE_WALL = 11;
|
||||
public const RED_SANDSTONE_WALL = 12;
|
||||
public const RED_NETHER_BRICK_WALL = 13;
|
||||
|
||||
protected $id = self::COBBLESTONE_WALL;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
self::NONE_MOSSY_WALL => "Cobblestone",
|
||||
self::MOSSY_WALL => "Mossy Cobblestone",
|
||||
self::GRANITE_WALL => "Granite",
|
||||
self::DIORITE_WALL => "Diorite",
|
||||
self::ANDESITE_WALL => "Andesite",
|
||||
self::SANDSTONE_WALL => "Sandstone",
|
||||
self::BRICK_WALL => "Brick",
|
||||
self::STONE_BRICK_WALL => "Stone Brick",
|
||||
self::MOSSY_STONE_BRICK_WALL => "Mossy Stone Brick",
|
||||
self::NETHER_BRICK_WALL => "Nether Brick",
|
||||
self::END_STONE_BRICK_WALL => "End Stone Brick",
|
||||
self::PRISMARINE_WALL => "Prismarine",
|
||||
self::RED_SANDSTONE_WALL => "Red Sandstone",
|
||||
self::RED_NETHER_BRICK_WALL => "Red Nether Brick"
|
||||
];
|
||||
return ($names[$this->getVariant()] ?? "Unknown") . " Wall";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
//walls don't have any special collision boxes like fences do
|
||||
|
||||
$north = $this->canConnect($this->getSide(Vector3::SIDE_NORTH));
|
||||
$south = $this->canConnect($this->getSide(Vector3::SIDE_SOUTH));
|
||||
$west = $this->canConnect($this->getSide(Vector3::SIDE_WEST));
|
||||
$east = $this->canConnect($this->getSide(Vector3::SIDE_EAST));
|
||||
|
||||
$inset = 0.25;
|
||||
if(
|
||||
$this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR and //if there is a block on top, it stays as a post
|
||||
(
|
||||
($north and $south and !$west and !$east) or
|
||||
(!$north and !$south and $west and $east)
|
||||
)
|
||||
){
|
||||
//If connected to two sides on the same axis but not any others, AND there is not a block on top, there is no post and the wall is thinner
|
||||
$inset = 0.3125;
|
||||
}
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + ($west ? 0 : $inset),
|
||||
$this->y,
|
||||
$this->z + ($north ? 0 : $inset),
|
||||
$this->x + 1 - ($east ? 0 : $inset),
|
||||
$this->y + 1.5,
|
||||
$this->z + 1 - ($south ? 0 : $inset)
|
||||
);
|
||||
}
|
||||
|
||||
public function canConnect(Block $block){
|
||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||
}
|
||||
}
|
@ -25,43 +25,25 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\VanillaItems;
|
||||
|
||||
class Cobweb extends Flowable{
|
||||
|
||||
protected $id = self::COBWEB;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(4.0, BlockToolType::SWORD | BlockToolType::SHEARS, 1));
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Cobweb";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 4;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_SWORD | BlockToolType::TYPE_SHEARS;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
public function onEntityInside(Entity $entity) : void{
|
||||
$entity->resetFallDistance();
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::STRING)
|
||||
VanillaItems::STRING()
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -23,29 +23,102 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\TreeType;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function mt_rand;
|
||||
|
||||
class CocoaBlock extends Transparent{
|
||||
|
||||
protected $id = self::COCOA_BLOCK;
|
||||
/** @var int */
|
||||
protected $facing = Facing::NORTH;
|
||||
/** @var int */
|
||||
protected $age = 0;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.2, BlockToolType::AXE, 0, 15.0));
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Cocoa Block";
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing(Facing::opposite($this->facing)) | ($this->age << 2);
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.2;
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->facing = Facing::opposite(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03));
|
||||
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta >> 2, 0, 2);
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
//TODO
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return AxisAlignedBB::one()
|
||||
->squash(Facing::axis(Facing::rotateY($this->facing, true)), (6 - $this->age) / 16) //sides
|
||||
->trim(Facing::DOWN, (7 - $this->age * 2) / 16)
|
||||
->trim(Facing::UP, 0.25)
|
||||
->trim(Facing::opposite($this->facing), 1 / 16) //gap between log and pod
|
||||
->trim($this->facing, (11 - $this->age * 2) / 16); //outward face
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(Facing::axis($face) !== Facing::AXIS_Y and $blockClicked instanceof Wood and $blockClicked->getTreeType()->equals(TreeType::JUNGLE())){
|
||||
$this->facing = $face;
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->age < 2 and $item instanceof Fertilizer){
|
||||
$this->age++;
|
||||
$this->world->setBlock($this, $this);
|
||||
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$side = $this->getSide(Facing::opposite($this->facing));
|
||||
if(!($side instanceof Wood) or !$side->getTreeType()->equals(TreeType::JUNGLE())){
|
||||
$this->world->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->age < 2 and mt_rand(1, 5) === 1){
|
||||
$this->age++;
|
||||
$this->world->setBlock($this, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
VanillaItems::COCOA_BEANS()->setCount($this->age === 2 ? mt_rand(2, 3) : 1)
|
||||
];
|
||||
}
|
||||
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
return VanillaItems::COCOA_BEANS();
|
||||
}
|
||||
}
|
||||
|
@ -23,30 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\ToolTier;
|
||||
|
||||
class Concrete extends Solid{
|
||||
class Concrete extends Opaque{
|
||||
|
||||
protected $id = Block::CONCRETE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 1.8;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(1.8, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel()));
|
||||
}
|
||||
}
|
||||
|
@ -23,33 +23,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\block\utils\Fallable;
|
||||
use pocketmine\block\utils\FallableTrait;
|
||||
use pocketmine\math\Facing;
|
||||
|
||||
class ConcretePowder extends Fallable{
|
||||
|
||||
protected $id = self::CONCRETE_POWDER;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
class ConcretePowder extends Opaque implements Fallable{
|
||||
use FallableTrait {
|
||||
onNearbyBlockChange as protected startFalling;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete Powder";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.5, BlockToolType::SHOVEL));
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(($block = $this->checkAdjacentWater()) !== null){
|
||||
$this->level->setBlock($this, $block);
|
||||
$this->world->setBlock($this, $block);
|
||||
}else{
|
||||
parent::onNearbyBlockChange();
|
||||
$this->startFalling();
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,9 +55,12 @@ class ConcretePowder extends Fallable{
|
||||
* @return null|Block
|
||||
*/
|
||||
private function checkAdjacentWater() : ?Block{
|
||||
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
||||
foreach(Facing::ALL as $i){
|
||||
if($i === Facing::DOWN){
|
||||
continue;
|
||||
}
|
||||
if($this->getSide($i) instanceof Water){
|
||||
return BlockFactory::get(Block::CONCRETE, $this->meta);
|
||||
return BlockFactory::get(BlockLegacyIds::CONCRETE, $this->idInfo->getVariant());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,31 +23,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\CraftingGrid;
|
||||
use pocketmine\crafting\CraftingGrid;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class CraftingTable extends Solid{
|
||||
class CraftingTable extends Opaque{
|
||||
|
||||
protected $id = self::CRAFTING_TABLE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(2.5, BlockToolType::AXE));
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2.5;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Crafting Table";
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
||||
}
|
||||
|
@ -23,40 +23,60 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function mt_rand;
|
||||
|
||||
abstract class Crops extends Flowable{
|
||||
/** @var int */
|
||||
protected $age = 0;
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($blockReplace->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? BlockBreakInfo::instant());
|
||||
}
|
||||
|
||||
return true;
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->age;
|
||||
}
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, 7);
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b111;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($blockReplace->getSide(Facing::DOWN)->getId() === BlockLegacyIds::FARMLAND){
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->age < 7 and $item instanceof Fertilizer){
|
||||
$block = clone $this;
|
||||
$block->meta += mt_rand(2, 5);
|
||||
if($block->meta > 7){
|
||||
$block->meta = 7;
|
||||
$block->age += mt_rand(2, 5);
|
||||
if($block->age > 7){
|
||||
$block->age = 7;
|
||||
}
|
||||
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||
$this->getWorld()->setBlock($this, $ev->getNewState());
|
||||
}
|
||||
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -65,8 +85,8 @@ abstract class Crops extends Flowable{
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
if($this->getSide(Facing::DOWN)->getId() !== BlockLegacyIds::FARMLAND){
|
||||
$this->getWorld()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,15 +95,13 @@ abstract class Crops extends Flowable{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if($this->meta < 0x07){
|
||||
$block = clone $this;
|
||||
++$block->meta;
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||
}
|
||||
if($this->age < 7 and mt_rand(0, 2) === 1){
|
||||
$block = clone $this;
|
||||
++$block->age;
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getWorld()->setBlock($this, $ev->getNewState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +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\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Dandelion extends Flowable{
|
||||
|
||||
protected $id = self::DANDELION;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Dandelion";
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
}
|
@ -23,28 +23,91 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use function cos;
|
||||
use function max;
|
||||
use function round;
|
||||
use const M_PI;
|
||||
|
||||
class DaylightSensor extends Transparent{
|
||||
/** @var BlockIdentifierFlattened */
|
||||
protected $idInfo;
|
||||
|
||||
protected $id = self::DAYLIGHT_SENSOR;
|
||||
/** @var int */
|
||||
protected $power = 0;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
/** @var bool */
|
||||
protected $inverted = false;
|
||||
|
||||
public function __construct(BlockIdentifierFlattened $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.2, BlockToolType::AXE));
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Daylight Sensor";
|
||||
public function getId() : int{
|
||||
return $this->inverted ? $this->idInfo->getSecondId() : parent::getId();
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.2;
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->power;
|
||||
}
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->power = BlockDataSerializer::readBoundedInt("power", $stateMeta, 0, 15);
|
||||
$this->inverted = $id === $this->idInfo->getSecondId();
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
public function isInverted() : bool{
|
||||
return $this->inverted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $inverted
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setInverted(bool $inverted = true) : self{
|
||||
$this->inverted = $inverted;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return AxisAlignedBB::one()->trim(Facing::UP, 0.5);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$this->inverted = !$this->inverted;
|
||||
$this->power = $this->recalculatePower();
|
||||
$this->world->setBlock($this, $this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onScheduledUpdate() : void{
|
||||
$this->power = $this->recalculatePower();
|
||||
$this->world->setBlock($this, $this);
|
||||
$this->world->scheduleDelayedBlockUpdate($this, 20);
|
||||
}
|
||||
|
||||
private function recalculatePower() : int{
|
||||
$lightLevel = $this->world->getRealBlockSkyLightAt($this->x, $this->y, $this->z);
|
||||
if($this->inverted){
|
||||
return 15 - $lightLevel;
|
||||
}
|
||||
|
||||
$sunAngle = $this->world->getSunAnglePercentage();
|
||||
return max(0, (int) round(15 * cos(($sunAngle + ((($sunAngle < 0.5 ? 0 : 1) - $sunAngle) / 5)) * 2 * M_PI)));
|
||||
}
|
||||
|
||||
//TODO
|
||||
|
@ -24,49 +24,37 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function mt_rand;
|
||||
|
||||
class DeadBush extends Flowable{
|
||||
|
||||
protected $id = self::DEAD_BUSH;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? BlockBreakInfo::instant(BlockToolType::SHEARS, 1));
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Dead Bush";
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if(!$this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(!$this->getSide(Facing::DOWN)->isTransparent()){
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
if($this->getSide(Facing::DOWN)->isTransparent()){
|
||||
$this->getWorld()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_SHEARS;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if(!$this->isCompatibleWithTool($item)){
|
||||
if(!$this->breakInfo->isToolCompatible($item)){
|
||||
return [
|
||||
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
|
||||
VanillaItems::STICK()->setCount(mt_rand(0, 2))
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -25,11 +25,5 @@ namespace pocketmine\block;
|
||||
|
||||
class DetectorRail extends RedstoneRail{
|
||||
|
||||
protected $id = self::DETECTOR_RAIL;
|
||||
|
||||
public function getName() : string{
|
||||
return "Detector Rail";
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -24,37 +24,19 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\ToolTier;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use function mt_rand;
|
||||
|
||||
class DiamondOre extends Solid{
|
||||
class DiamondOre extends Opaque{
|
||||
|
||||
protected $id = self::DIAMOND_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Diamond Ore";
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(3.0, BlockToolType::PICKAXE, ToolTier::IRON()->getHarvestLevel()));
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::DIAMOND)
|
||||
VanillaItems::DIAMOND()
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -25,39 +25,20 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Hoe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class Dirt extends Solid{
|
||||
class Dirt extends Opaque{
|
||||
|
||||
protected $id = self::DIRT;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(0.5, BlockToolType::SHOVEL));
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
if($this->meta === 1){
|
||||
return "Coarse Dirt";
|
||||
}
|
||||
return "Dirt";
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item instanceof Hoe){
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($face === Facing::UP and $item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
if($this->meta === 1){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
}else{
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
|
||||
}
|
||||
$this->getWorld()->setBlock($this, VanillaBlocks::FARMLAND());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -23,271 +23,144 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\sound\DoorSound;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\DoorSound;
|
||||
|
||||
|
||||
abstract class Door extends Transparent{
|
||||
class Door extends Transparent{
|
||||
/** @var int */
|
||||
protected $facing = Facing::NORTH;
|
||||
/** @var bool */
|
||||
protected $top = false;
|
||||
/** @var bool */
|
||||
protected $hingeRight = false;
|
||||
|
||||
/** @var bool */
|
||||
protected $open = false;
|
||||
/** @var bool */
|
||||
protected $powered = false;
|
||||
|
||||
|
||||
protected function writeStateToMeta() : int{
|
||||
if($this->top){
|
||||
return BlockLegacyMetadata::DOOR_FLAG_TOP |
|
||||
($this->hingeRight ? BlockLegacyMetadata::DOOR_TOP_FLAG_RIGHT : 0) |
|
||||
($this->powered ? BlockLegacyMetadata::DOOR_TOP_FLAG_POWERED : 0);
|
||||
}
|
||||
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing(Facing::rotateY($this->facing, true)) | ($this->open ? BlockLegacyMetadata::DOOR_BOTTOM_FLAG_OPEN : 0);
|
||||
}
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->top = $stateMeta & BlockLegacyMetadata::DOOR_FLAG_TOP;
|
||||
if($this->top){
|
||||
$this->hingeRight = ($stateMeta & BlockLegacyMetadata::DOOR_TOP_FLAG_RIGHT) !== 0;
|
||||
$this->powered = ($stateMeta & BlockLegacyMetadata::DOOR_TOP_FLAG_POWERED) !== 0;
|
||||
}else{
|
||||
$this->facing = Facing::rotateY(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03), false);
|
||||
$this->open = ($stateMeta & BlockLegacyMetadata::DOOR_BOTTOM_FLAG_OPEN) !== 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : void{
|
||||
parent::readStateFromWorld();
|
||||
|
||||
//copy door properties from other half
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
if($other instanceof Door and $other->isSameType($this)){
|
||||
if($this->top){
|
||||
$this->facing = $other->facing;
|
||||
$this->open = $other->open;
|
||||
}else{
|
||||
$this->hingeRight = $other->hingeRight;
|
||||
$this->powered = $other->powered;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getFullDamage(){
|
||||
$damage = $this->getDamage();
|
||||
$isUp = ($damage & 0x08) > 0;
|
||||
|
||||
if($isUp){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN)->getDamage();
|
||||
$up = $damage;
|
||||
}else{
|
||||
$down = $damage;
|
||||
$up = $this->getSide(Vector3::SIDE_UP)->getDamage();
|
||||
}
|
||||
|
||||
$isRight = ($up & 0x01) > 0;
|
||||
|
||||
return $down & 0x07 | ($isUp ? 8 : 0) | ($isRight ? 0x10 : 0);
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
$f = 0.1875;
|
||||
$damage = $this->getFullDamage();
|
||||
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 2,
|
||||
$this->z + 1
|
||||
);
|
||||
|
||||
$j = $damage & 0x03;
|
||||
$isOpen = (($damage & 0x04) > 0);
|
||||
$isRight = (($damage & 0x10) > 0);
|
||||
|
||||
if($j === 0){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + $f
|
||||
);
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + $f,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}elseif($j === 1){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
$bb->setBounds(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + $f,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + $f
|
||||
);
|
||||
}
|
||||
}elseif($j === 2){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + $f
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}elseif($j === 3){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + $f,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $bb;
|
||||
return AxisAlignedBB::one()
|
||||
->extend(Facing::UP, 1)
|
||||
->trim($this->open ? Facing::rotateY($this->facing, !$this->hingeRight) : $this->facing, 13 / 16);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
||||
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
||||
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
||||
}
|
||||
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){ //Replace with common break method
|
||||
$this->getWorld()->useBreakOn($this); //this will delete both halves if they exist
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($face === Vector3::SIDE_UP){
|
||||
$blockUp = $this->getSide(Vector3::SIDE_UP);
|
||||
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($face === Facing::UP){
|
||||
$blockUp = $this->getSide(Facing::UP);
|
||||
$blockDown = $this->getSide(Facing::DOWN);
|
||||
if(!$blockUp->canBeReplaced() or $blockDown->isTransparent()){
|
||||
return false;
|
||||
}
|
||||
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
||||
$faces = [
|
||||
0 => 3,
|
||||
1 => 4,
|
||||
2 => 2,
|
||||
3 => 5
|
||||
];
|
||||
$next = $this->getSide($faces[($direction + 2) % 4]);
|
||||
$next2 = $this->getSide($faces[$direction]);
|
||||
$metaUp = 0x08;
|
||||
if($next->getId() === $this->getId() or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge
|
||||
$metaUp |= 0x01;
|
||||
|
||||
if($player !== null){
|
||||
$this->facing = $player->getHorizontalFacing();
|
||||
}
|
||||
|
||||
$this->setDamage($player->getDirection() & 0x03);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom
|
||||
$this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
|
||||
$next = $this->getSide(Facing::rotateY($this->facing, false));
|
||||
$next2 = $this->getSide(Facing::rotateY($this->facing, true));
|
||||
|
||||
if($next->isSameType($this) or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge
|
||||
$this->hingeRight = true;
|
||||
}
|
||||
|
||||
$topHalf = clone $this;
|
||||
$topHalf->top = true;
|
||||
|
||||
$tx->addBlock($blockReplace, $this)->addBlock($blockUp, $topHalf);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if(($this->getDamage() & 0x08) === 0x08){ //Top
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === $this->getId()){
|
||||
$meta = $down->getDamage() ^ 0x04;
|
||||
$this->level->setBlock($down, BlockFactory::get($this->getId(), $meta), true);
|
||||
$this->level->addSound(new DoorSound($this));
|
||||
return true;
|
||||
}
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$this->open = !$this->open;
|
||||
|
||||
return false;
|
||||
}else{
|
||||
$this->meta ^= 0x04;
|
||||
$this->level->setBlock($this, $this, true);
|
||||
$this->level->addSound(new DoorSound($this));
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
if($other instanceof Door and $other->isSameType($this)){
|
||||
$other->open = $this->open;
|
||||
$this->world->setBlock($other, $other);
|
||||
}
|
||||
|
||||
$this->world->setBlock($this, $this);
|
||||
$this->world->addSound($this, new DoorSound());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if(($this->meta & 0x08) === 0){ //bottom half only
|
||||
return parent::getDropsForCompatibleTool($item);
|
||||
public function getDrops(Item $item) : array{
|
||||
if(!$this->top){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
if(($this->getDamage() & 0x08) === 0x08){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === $this->getId()){
|
||||
return [$this, $down];
|
||||
}
|
||||
}else{
|
||||
$up = $this->getSide(Vector3::SIDE_UP);
|
||||
if($up->getId() === $this->getId()){
|
||||
return [$this, $up];
|
||||
}
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
if($other->isSameType($this)){
|
||||
return [$this, $other];
|
||||
}
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
}
|
||||
|
@ -24,42 +24,38 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class DoublePlant extends Flowable{
|
||||
public const BITFLAG_TOP = 0x08;
|
||||
|
||||
protected $id = self::DOUBLE_PLANT;
|
||||
/** @var bool */
|
||||
protected $top = false;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? BlockBreakInfo::instant());
|
||||
}
|
||||
|
||||
public function canBeReplaced() : bool{
|
||||
return $this->meta === 2 or $this->meta === 3; //grass or fern
|
||||
protected function writeStateToMeta() : int{
|
||||
return ($this->top ? BlockLegacyMetadata::DOUBLE_PLANT_FLAG_TOP : 0);
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
0 => "Sunflower",
|
||||
1 => "Lilac",
|
||||
2 => "Double Tallgrass",
|
||||
3 => "Large Fern",
|
||||
4 => "Rose Bush",
|
||||
5 => "Peony"
|
||||
];
|
||||
return $names[$this->getVariant()] ?? "";
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->top = ($stateMeta & BlockLegacyMetadata::DOUBLE_PLANT_FLAG_TOP) !== 0;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$id = $blockReplace->getSide(Vector3::SIDE_DOWN)->getId();
|
||||
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Vector3::SIDE_UP)->canBeReplaced()){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, false, false);
|
||||
$this->getLevel()->setBlock($blockReplace->getSide(Vector3::SIDE_UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1000;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$id = $blockReplace->getSide(Facing::DOWN)->getId();
|
||||
if(($id === BlockLegacyIds::GRASS or $id === BlockLegacyIds::DIRT) and $blockReplace->getSide(Facing::UP)->canBeReplaced()){
|
||||
$top = clone $this;
|
||||
$top->top = true;
|
||||
$tx->addBlock($blockReplace, $this)->addBlock($blockReplace->getSide(Facing::UP), $top);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -71,56 +67,28 @@ class DoublePlant extends Flowable{
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidHalfPlant() : bool{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
$other = $this->getSide(Vector3::SIDE_DOWN);
|
||||
}else{
|
||||
$other = $this->getSide(Vector3::SIDE_UP);
|
||||
}
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
|
||||
return (
|
||||
$other->getId() === $this->getId() and
|
||||
$other->getVariant() === $this->getVariant() and
|
||||
($other->getDamage() & self::BITFLAG_TOP) !== ($this->getDamage() & self::BITFLAG_TOP)
|
||||
$other instanceof DoublePlant and
|
||||
$other->isSameType($this) and
|
||||
$other->top !== $this->top
|
||||
);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
if(!$this->isValidHalfPlant() or (!$this->top and $this->getSide(Facing::DOWN)->isTransparent())){
|
||||
$this->getWorld()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x07;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return ($this->meta === 2 or $this->meta === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return ($this->meta === 2 or $this->meta === 3) ? 1 : 0; //only grass or fern require shears
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
if(mt_rand(0, 24) === 0){
|
||||
return [
|
||||
ItemFactory::get(Item::SEEDS)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
return $this->top ? parent::getDrops($item) : [];
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
if($this->isValidHalfPlant()){
|
||||
return [$this, $this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP)];
|
||||
return [$this, $this->getSide($this->top ? Facing::DOWN : Facing::UP)];
|
||||
}
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
|
@ -1,47 +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\item\TieredTool;
|
||||
|
||||
class DoubleStoneSlab extends DoubleSlab{
|
||||
|
||||
protected $id = self::DOUBLE_STONE_SLAB;
|
||||
|
||||
public function getSlabId() : int{
|
||||
return self::STONE_SLAB;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
}
|
@ -24,31 +24,25 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use function mt_rand;
|
||||
|
||||
class IronDoor extends Door{
|
||||
class DoubleTallGrass extends DoublePlant{
|
||||
|
||||
protected $id = self::IRON_DOOR_BLOCK;
|
||||
|
||||
protected $itemId = Item::IRON_DOOR;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? BlockBreakInfo::instant(BlockToolType::SHEARS, 1));
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Iron Door";
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->top and !$this->breakInfo->isToolCompatible($item) and mt_rand(0, 7) === 0){
|
||||
return [
|
||||
VanillaItems::WHEAT_SEEDS()
|
||||
];
|
||||
}
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
}
|
86
src/pocketmine/block/DragonEgg.php
Normal file
86
src/pocketmine/block/DragonEgg.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?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\Fallable;
|
||||
use pocketmine\block\utils\FallableTrait;
|
||||
use pocketmine\event\block\BlockTeleportEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ToolTier;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\particle\DragonEggTeleportParticle;
|
||||
use pocketmine\world\World;
|
||||
use function max;
|
||||
use function min;
|
||||
use function mt_rand;
|
||||
|
||||
class DragonEgg extends Transparent implements Fallable{
|
||||
use FallableTrait;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(3.0, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel()));
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function tickFalling() : ?Block{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$this->teleport();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
|
||||
$this->teleport();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function teleport() : void{
|
||||
for($tries = 0; $tries < 16; ++$tries){
|
||||
$block = $this->world->getBlockAt(
|
||||
$this->x + mt_rand(-16, 16),
|
||||
max(0, min(World::Y_MAX - 1, $this->y + mt_rand(-8, 8))),
|
||||
$this->z + mt_rand(-16, 16)
|
||||
);
|
||||
if($block instanceof Air){
|
||||
$ev = new BlockTeleportEvent($this, $block);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
break;
|
||||
}else{
|
||||
$block = $ev->getTo();
|
||||
}
|
||||
$this->world->addParticle($this, new DragonEggTeleportParticle($this->x - $block->x, $this->y - $block->y, $this->z - $block->z));
|
||||
$this->world->setBlock($this, VanillaBlocks::AIR());
|
||||
$this->world->setBlock($block, $this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,15 +23,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class LitRedstoneLamp extends RedstoneLamp{
|
||||
class DriedKelp extends Opaque{
|
||||
|
||||
protected $id = self::LIT_REDSTONE_LAMP;
|
||||
|
||||
public function getName() : string{
|
||||
return "Lit Redstone Lamp";
|
||||
public function getFlameEncouragement() : int{
|
||||
return 30;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 15;
|
||||
public function getFlammability() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 4000;
|
||||
}
|
||||
}
|
62
src/pocketmine/block/Element.php
Normal file
62
src/pocketmine/block/Element.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?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;
|
||||
|
||||
class Element extends Opaque{
|
||||
|
||||
/** @var int */
|
||||
private $atomicWeight;
|
||||
/** @var int */
|
||||
private $group;
|
||||
/** @var string */
|
||||
private $symbol;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo, string $symbol, int $atomicWeight, int $group){
|
||||
parent::__construct($idInfo, $name, $breakInfo);
|
||||
$this->atomicWeight = $atomicWeight;
|
||||
$this->group = $group;
|
||||
$this->symbol = $symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getAtomicWeight() : int{
|
||||
return $this->atomicWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getGroup() : int{
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSymbol() : string{
|
||||
return $this->symbol;
|
||||
}
|
||||
}
|
@ -24,37 +24,19 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\item\ToolTier;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use function mt_rand;
|
||||
|
||||
class EmeraldOre extends Solid{
|
||||
class EmeraldOre extends Opaque{
|
||||
|
||||
protected $id = self::EMERALD_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Emerald Ore";
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, ?BlockBreakInfo $breakInfo = null){
|
||||
parent::__construct($idInfo, $name, $breakInfo ?? new BlockBreakInfo(3.0, BlockToolType::PICKAXE, ToolTier::IRON()->getHarvestLevel()));
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::EMERALD)
|
||||
VanillaItems::EMERALD()
|
||||
];
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user