mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-14 05:15:11 +00:00
Compare commits
1232 Commits
Author | SHA1 | Date | |
---|---|---|---|
d72f6a3ac6 | |||
3b34268ed6 | |||
76dad46e13 | |||
eb3530b6e6 | |||
b392651354 | |||
e0b07ff308 | |||
729f831b8f | |||
29e2d92098 | |||
f75a05d7fa | |||
3dae873731 | |||
5257755dc5 | |||
3214da8642 | |||
794142fe49 | |||
ff27c5f7db | |||
4d4362801f | |||
0babe0a1ab | |||
d696ebcda3 | |||
9f5c16bc46 | |||
8865bb73ba | |||
2dee1dbc28 | |||
0f0b6f0efa | |||
d5f13d8be2 | |||
27ae959e89 | |||
f8f39687e2 | |||
94737934de | |||
debb469de1 | |||
73dc0598e4 | |||
141fbde660 | |||
69952ae2af | |||
71f2a34616 | |||
d17cd65803 | |||
a8d5e8c5f6 | |||
089e62b44e | |||
f1cc168d26 | |||
f6e53f826b | |||
986b4e0651 | |||
dc07ac33d3 | |||
9c5cec77b1 | |||
f48b703533 | |||
70636f6eb4 | |||
ead9aae23c | |||
13068ba3a7 | |||
b54854529f | |||
974d08efd6 | |||
289553fa46 | |||
e38866c4ba | |||
58a95f8836 | |||
e032b8fe20 | |||
a27c14c00c | |||
003c002208 | |||
d417b1e2f5 | |||
65e468e3c2 | |||
a11cf8c296 | |||
d455188d03 | |||
14fba36636 | |||
43ac3fbf3e | |||
352162a6e6 | |||
b3601c9390 | |||
817fec9e3d | |||
ceeef7c729 | |||
7f1b2a0ee5 | |||
27324a3aeb | |||
33b5da3749 | |||
40e88f1686 | |||
4c65a0cdaa | |||
806f03bd37 | |||
39820be836 | |||
c948aa94aa | |||
5d0d1aa4c5 | |||
9b8be22015 | |||
b0b28ec6ed | |||
2fb4704269 | |||
0c0eb72b1b | |||
466107d3b8 | |||
4f59d3487a | |||
65220b4f7f | |||
85eb6b30a5 | |||
1c2eb35025 | |||
85ed7efcb4 | |||
183489e863 | |||
ac060f2ec6 | |||
6c85d4d254 | |||
f506c922b5 | |||
a5b08fc8f2 | |||
c3c4c80b70 | |||
5695fa9086 | |||
f78808bad0 | |||
dc0082162b | |||
ff4aa148ef | |||
63e86fe806 | |||
ab05bc7379 | |||
1a395a51c9 | |||
142c8f067b | |||
cd3c96aad2 | |||
19c47fa71f | |||
d670bc8bf8 | |||
7bd8d09023 | |||
5a970541f9 | |||
e561fa6222 | |||
025dde19ce | |||
28bfe9fbb4 | |||
cd53fa162b | |||
748e9705ba | |||
219ed81389 | |||
6a7196530c | |||
01fe497c49 | |||
3bbd088a09 | |||
85effa5240 | |||
81c5b83bd9 | |||
ef31a9fc66 | |||
dc56a99473 | |||
9477034a4a | |||
5844b59b12 | |||
3af18917f0 | |||
61528393c2 | |||
59b8453228 | |||
8cb48bfe1d | |||
8fb4d7b982 | |||
13f114f30e | |||
eccd258aeb | |||
bd5f379c4c | |||
2588895ab0 | |||
432999a7d7 | |||
68699dbff9 | |||
bfbe3d83de | |||
c32c21464c | |||
16faafa1ef | |||
4d6ac57a26 | |||
73ba1ba224 | |||
8b79253d3b | |||
1122131c8d | |||
a50ef2af6f | |||
72e4660800 | |||
e6285a0312 | |||
5420e76a9a | |||
de46a81cf4 | |||
0cdc04f9b5 | |||
8b1a84f2bf | |||
155e516f74 | |||
ea0a47dff7 | |||
0a6ce18322 | |||
11d73e5bb8 | |||
492ad6bb66 | |||
82e8eb46ac | |||
c7868a810d | |||
2cc22a29c1 | |||
8e2829bdd4 | |||
af79e787ea | |||
65c53e6512 | |||
5503fadf13 | |||
99964709c9 | |||
b85f3bd149 | |||
57d274901d | |||
f3e1c82246 | |||
908b627846 | |||
afb21c1df2 | |||
988be2a96b | |||
afe67f7502 | |||
b257348a3a | |||
12c66d3362 | |||
92fd2d35a4 | |||
61077c48f1 | |||
e0c61071e1 | |||
813d431208 | |||
ee112b992d | |||
c9b33e2b9f | |||
2f2be84b12 | |||
5a7736b179 | |||
e648f1c91e | |||
5116e11cea | |||
9c05e37fbe | |||
fb4796f35e | |||
0c2ba66078 | |||
c29cd8e2eb | |||
a13b0c98a1 | |||
e6ff908e18 | |||
c47ecb55c0 | |||
c19d2fe891 | |||
f195f24f4f | |||
4b5f279a3e | |||
89260d788c | |||
a7cd081002 | |||
361be8fe36 | |||
b01e4ab417 | |||
177b963d8e | |||
8d1a1628de | |||
6f80b8979d | |||
3c8eb29d4e | |||
b94bbf6f5e | |||
314a8a1297 | |||
547503e8f4 | |||
f74ff1fcd4 | |||
6c351357ab | |||
3433406cff | |||
b307cd0aa1 | |||
c9b83d7276 | |||
e22b6ff566 | |||
af88f49a21 | |||
599d5253db | |||
54cb5ee0fa | |||
cdae8b42eb | |||
a45a4a91ae | |||
21378b7f27 | |||
502aed41b0 | |||
125837324f | |||
609dff1aae | |||
b03212053c | |||
fd4ac885bb | |||
f35886f18a | |||
a9eaa55427 | |||
5c41f79be4 | |||
34c2b62ffe | |||
e42a691da9 | |||
3b3fb5e662 | |||
01ffe8bf57 | |||
4abf4aecad | |||
b29f83ee99 | |||
4bc57f00b8 | |||
ff61e1e018 | |||
fb20bb3832 | |||
3333df31df | |||
c09fcb2df2 | |||
c7cdaeae85 | |||
4416cd5a28 | |||
cb93095857 | |||
c8f396ecbc | |||
cb06be615a | |||
0d3c11699c | |||
3667e95ff6 | |||
0e2dc51ec8 | |||
eaf85b028a | |||
9479a1a0ab | |||
1bb2d162ab | |||
ee868bcccc | |||
cbc8576d4a | |||
edcf296086 | |||
9e27c47116 | |||
a0368a843e | |||
3f64906263 | |||
19bb8a00df | |||
4816a66fb8 | |||
06f4e1e4c2 | |||
5b8166c1f0 | |||
30c5cad5b3 | |||
a7a7fe3895 | |||
55ac2f07dc | |||
0660888029 | |||
0476e6bcfc | |||
72bd37e442 | |||
f95fcecb5b | |||
61391b6e23 | |||
fbb6f1f81c | |||
712df04bc4 | |||
1563e25378 | |||
ed84252942 | |||
3d90625020 | |||
9f6b914925 | |||
0e614ea8fd | |||
401bd09d60 | |||
649671cc69 | |||
e755e1dc23 | |||
e34a444dde | |||
78f9985377 | |||
fac2bd3379 | |||
fcfd51dfc7 | |||
ccc76cf338 | |||
10a73488ed | |||
9c5114084b | |||
11630ab1aa | |||
a3068b39a2 | |||
edbc73a72c | |||
3a0c8dd594 | |||
16fa26405a | |||
57423540f0 | |||
8f8821c904 | |||
094102fe92 | |||
2aef83e7d7 | |||
5c3e78e1d3 | |||
18666e5a60 | |||
f72163c173 | |||
7407e504b6 | |||
0e396dc47d | |||
d2204da1d5 | |||
2a51269305 | |||
928041ddf1 | |||
007f4f9350 | |||
46e9f0cec6 | |||
606d56b55d | |||
78a62a8b27 | |||
c5bdd7dd64 | |||
8ee37a3033 | |||
7e3e63f342 | |||
8ef1e54e20 | |||
eaf3a86981 | |||
317a48d9b0 | |||
bc14660e55 | |||
b1bb9fbd1c | |||
96181f8cf5 | |||
4771e3dc28 | |||
2e9117d102 | |||
06493da7d9 | |||
bd303b1062 | |||
fe731b9018 | |||
1a24afc6d1 | |||
bef906b0f0 | |||
37e8dd6444 | |||
02ee0f23c0 | |||
cda472333c | |||
47cf58be8a | |||
ccf9691927 | |||
16fa958416 | |||
bac57c159f | |||
38b2d83799 | |||
c134b1cd8a | |||
62deafda48 | |||
31b6df4376 | |||
b296ae1b87 | |||
f9e42b716a | |||
34c1d455a7 | |||
af8936dba5 | |||
e8ffab1787 | |||
ecc1e1f698 | |||
ea5931e274 | |||
988cf7f535 | |||
e156fb47e8 | |||
efc5f34877 | |||
dd0d8842d5 | |||
7bdc564ccc | |||
69fff23f1a | |||
ae43698e88 | |||
0987e03c03 | |||
97c124edf9 | |||
56501178b7 | |||
da663deea1 | |||
972c911485 | |||
0d8858f948 | |||
da71540fce | |||
ec9b39862b | |||
efca8077d5 | |||
5066d5225b | |||
aefaf73685 | |||
15401d740f | |||
5920b0ba40 | |||
dea75a0687 | |||
873e8740e0 | |||
260c55f23a | |||
9ed430acb9 | |||
f0241043de | |||
135f1c95e4 | |||
5431807e43 | |||
d49ae832e8 | |||
ff9d013005 | |||
b0e1317818 | |||
8653afb0fb | |||
995b56aaa0 | |||
3ecddf312d | |||
470243ca6f | |||
3f21e59917 | |||
fdd74a4f46 | |||
a43b46a93c | |||
0604dfc9e5 | |||
dd2c3db285 | |||
c95e283507 | |||
6afbd1f55c | |||
0682c93f5a | |||
da90ae85da | |||
e87127f309 | |||
0237a50d90 | |||
8b53e4150e | |||
1c43538238 | |||
68887105b2 | |||
104e90b794 | |||
994062f6dc | |||
69a41a5ed4 | |||
3903b70ef5 | |||
692e63ad7c | |||
4d1be4d41d | |||
5f0310a8b6 | |||
9b01fb3d89 | |||
f28405fcfb | |||
9c07c206f6 | |||
d0d701f232 | |||
07cae8a129 | |||
6869ee1c2d | |||
26155acff2 | |||
b550cf5163 | |||
48fa19fdcd | |||
bac986d0b2 | |||
215bac8dd7 | |||
3709ba172b | |||
ef034f2d68 | |||
ab18332572 | |||
48595630fc | |||
4102205ba6 | |||
9e85ee4a7a | |||
e8e6b9304c | |||
23849b7f63 | |||
d2f68836c6 | |||
d19db5d2e4 | |||
98cdc80d37 | |||
8273f789ee | |||
29eccba5f0 | |||
9984b15de6 | |||
6ea01e0dd4 | |||
46331df7db | |||
691c49fb32 | |||
db815360d1 | |||
6e297168c2 | |||
95dbb00d4c | |||
50e29a5ed8 | |||
9f3fb935b5 | |||
e30b1ee2c7 | |||
574b7f6343 | |||
e8b6b56330 | |||
c368ebb5e7 | |||
fa920aa868 | |||
a421d32273 | |||
6c21c23444 | |||
55e0d9c520 | |||
37ee3f2775 | |||
bfdcc12e81 | |||
b2299e08e0 | |||
d7741050c5 | |||
6cff08cd65 | |||
fec42f16ba | |||
deb0cee8a0 | |||
c0dafe7872 | |||
340881d590 | |||
e2e960e43d | |||
500fd2d842 | |||
0b550b346b | |||
1424114cf2 | |||
a8980a0f67 | |||
69aa7c5ac1 | |||
11b74868ee | |||
9a53de0903 | |||
0f8101d4a6 | |||
55ecac4c80 | |||
2a1d1e90a2 | |||
4444a79468 | |||
4cbeee3ab8 | |||
a251960c1c | |||
52f734799e | |||
42171f6e06 | |||
1fe4fdc67c | |||
af4f30d1c8 | |||
3e2926441d | |||
0b33762be0 | |||
e6f89213dc | |||
f8d249b240 | |||
b39afa20d1 | |||
7027a9b972 | |||
b02f3f4090 | |||
8564912149 | |||
873535f719 | |||
78f4fcf6ab | |||
90b749c260 | |||
d5398b2781 | |||
d7a66ad755 | |||
b3f88e7b73 | |||
55adc1ef63 | |||
868d236ddc | |||
59e9c84806 | |||
a110317d1b | |||
b169d89291 | |||
74bef7f423 | |||
8db7867881 | |||
d8f8afe531 | |||
7dabf305f8 | |||
ed0053d0ee | |||
28255e35d1 | |||
0fc9170bbf | |||
7e2efae024 | |||
e9fa07b550 | |||
8ac32824a2 | |||
1322defead | |||
d084b7a34b | |||
c2d0605b1e | |||
0ff0b33047 | |||
114df07622 | |||
4a88db7f43 | |||
d3ea29d527 | |||
d2f1a3cf5b | |||
f9c2ed6200 | |||
e47a711494 | |||
2ea7a9e216 | |||
9f60484212 | |||
3031d89ec5 | |||
883e135bc0 | |||
4448f603a6 | |||
9365525efa | |||
17bee5e349 | |||
c6e0753c3e | |||
2ae7ba275b | |||
6aa0a82341 | |||
0af08a7375 | |||
81c1613e5d | |||
9cf8f608d8 | |||
dd4f26a9cf | |||
f976545f56 | |||
9929fb0abd | |||
37e453b875 | |||
b7578fef9c | |||
09eb904f6b | |||
b47d6bbc22 | |||
aa26ddf8b1 | |||
119c72980f | |||
eba888449d | |||
dac76f0e0f | |||
89fe8f7f10 | |||
2d77b1e364 | |||
e59a4296f8 | |||
6856761946 | |||
4fe3401182 | |||
e80ad22702 | |||
c22ab37372 | |||
1f9d672cfc | |||
974cbae725 | |||
b53f88027e | |||
9a0f723dff | |||
ab2003a85d | |||
4befd9095a | |||
06623d788a | |||
730ee74a65 | |||
700e0afee0 | |||
4b9712fdee | |||
dbd015b866 | |||
a498b0415a | |||
5b01cf72dd | |||
ec21c2baa0 | |||
11a0d9b502 | |||
a7fc245291 | |||
6db51e2380 | |||
d6f35f2342 | |||
d1df72ec78 | |||
9bd6d5c67e | |||
aaa23361d1 | |||
691d92a959 | |||
50101663f2 | |||
e369966890 | |||
63f57841de | |||
ac3bba0a11 | |||
1ff3df6ff0 | |||
4e29b216bf | |||
809dad2ac8 | |||
e238d583b8 | |||
3f89bd7bff | |||
8da7e789fd | |||
0766952f39 | |||
eeee1fbe73 | |||
46c224da86 | |||
3c001b310f | |||
198a106b9f | |||
1f5e0bc96d | |||
41f7c07703 | |||
f0a0c9a85f | |||
5b620d964e | |||
756840f11d | |||
df2c3136c9 | |||
a6b5cddd5a | |||
5b9453af43 | |||
8bba25f4f5 | |||
f9bd7016aa | |||
213406fc60 | |||
7ff6e5895e | |||
2e6b62fdec | |||
4fc5b9772a | |||
5d4880b0a7 | |||
2b1a0e1e72 | |||
cd022f1592 | |||
4ae3fd7734 | |||
b2249f93c0 | |||
303344783a | |||
75e0844ff5 | |||
18fabf5466 | |||
2751c59979 | |||
d99ffbd66c | |||
a34f3261cb | |||
8ce0022de6 | |||
fb6491ddeb | |||
3b961d0e5f | |||
a60fc4cc28 | |||
b747899fdd | |||
57b6451e16 | |||
8cf025a2df | |||
8480ee82ea | |||
a6c1b7bf9c | |||
c267137fde | |||
461bc94236 | |||
4fed08bcd4 | |||
e990c5a0a5 | |||
c616d9bb7c | |||
81051441ba | |||
3ecae0db19 | |||
c5bbb2bcbc | |||
24a2889758 | |||
60b26a7ea8 | |||
22b52f03d1 | |||
df76c02e7a | |||
d343187e58 | |||
c5ad127854 | |||
0f6dc9082a | |||
2b6dcbc2e2 | |||
763c8ebfe3 | |||
c572e9bb6a | |||
89521f166d | |||
49d3a42120 | |||
c523595e85 | |||
7c7e4f2093 | |||
88c1014f03 | |||
e32180ce93 | |||
e105578be0 | |||
a9d98bdf73 | |||
c601352777 | |||
77c71e22b2 | |||
1c13ba5656 | |||
f970be0e4d | |||
11a3f9f1b9 | |||
09771849ae | |||
57a310230a | |||
130c55d9f1 | |||
2712befa82 | |||
a4e250a3e6 | |||
23b97d8e2d | |||
1fb5043eb1 | |||
b0b1b29de4 | |||
1c3b641e37 | |||
f3063e797f | |||
8dcc88712c | |||
04191ec44a | |||
62ea7c93a9 | |||
cf06b5b8cf | |||
a8ec51daac | |||
6a7b77fee2 | |||
da42c8d020 | |||
b902f9ded0 | |||
9bb8a8f761 | |||
63b14a083c | |||
627a7c951a | |||
bb2685ca65 | |||
d38709a7ae | |||
b559a65346 | |||
b92a2ded8a | |||
22f25dfbdb | |||
6bf840c72e | |||
745be19a56 | |||
e05bee5ffb | |||
087ba0cc1d | |||
d8d994351b | |||
0029efa370 | |||
df13e967fd | |||
097c260dbb | |||
a219b727f2 | |||
710c162604 | |||
409c8c1703 | |||
376926c700 | |||
c3fabe833e | |||
3e09ff5350 | |||
7255065106 | |||
a7f10d8ccf | |||
76f1add3b3 | |||
fcc9e62c65 | |||
42613618a5 | |||
1bbeb62457 | |||
64893426fa | |||
3d50aafcc4 | |||
50fed41642 | |||
3f971a0c65 | |||
a27b29897c | |||
a90132a30e | |||
dfbd857771 | |||
323d96d5c1 | |||
f495ba1d0b | |||
643cf0ebf8 | |||
1614206a6d | |||
0ae2c6302a | |||
4f59c1b26c | |||
00916ade0c | |||
f4ee2912db | |||
a0de9b0d46 | |||
03e8cd3ed4 | |||
7af4e70f64 | |||
c864647cd1 | |||
92ed9e6125 | |||
c32026333f | |||
915224c8e5 | |||
734bc6c4a7 | |||
d36b24c518 | |||
d554d8060b | |||
b48243fd09 | |||
5c63e06b0f | |||
3be83e09f2 | |||
f24be2b055 | |||
92cffc00d0 | |||
e87e974323 | |||
a3f6338626 | |||
21aef97ba7 | |||
ed0d1978aa | |||
d64561b0b1 | |||
d234d3e45e | |||
5056754cea | |||
2dc3cf8162 | |||
8c5a81cf5c | |||
2b58f2bafd | |||
5dadf12374 | |||
0d4e473bdd | |||
11cedc4011 | |||
3f2455f090 | |||
9d26a224a2 | |||
c4ad390463 | |||
42e14f749e | |||
484557935e | |||
485f573955 | |||
71e0521286 | |||
3f07f06874 | |||
10279e11ed | |||
673e444456 | |||
89c49d77c6 | |||
c3a795e876 | |||
4199c3796f | |||
ecbf21acea | |||
45c89d084c | |||
56f90a2901 | |||
bf6af269c8 | |||
73d1f84072 | |||
a29424f5b3 | |||
ff3af492f8 | |||
80b804f7aa | |||
3a78735982 | |||
ab32784c74 | |||
816234a379 | |||
b7bf92a5e9 | |||
dcca000ead | |||
c4ea51f985 | |||
8202bb1cd8 | |||
b75758e35e | |||
38a06f76f8 | |||
84f99ed418 | |||
fd63f19199 | |||
66d44aa814 | |||
f3089f577e | |||
9516ef1632 | |||
e982a57cb5 | |||
f57fa2252b | |||
02cc370855 | |||
0a5d14a840 | |||
3ec2994d7f | |||
da4a2d8552 | |||
dc9351b024 | |||
786f416f2e | |||
a67d2ae978 | |||
089180fef4 | |||
15baf09339 | |||
083dde8395 | |||
fffa4b9501 | |||
22b5de09b4 | |||
71a8b0340c | |||
e544055bbc | |||
8f5db7c297 | |||
a5edfa368e | |||
27f55e4c96 | |||
9b6b3f50a1 | |||
1fb0ba6fc0 | |||
f1d378468e | |||
9ebd6d6b0f | |||
58e32086c0 | |||
8c0d441a13 | |||
25fb5140a2 | |||
f5a49b6d55 | |||
189f12a644 | |||
5a8917f6f2 | |||
f3e436592a | |||
35747874f6 | |||
59445902b8 | |||
2eb62c85f6 | |||
ad2a39bf13 | |||
0847358070 | |||
8766d4050c | |||
54f41dc145 | |||
ded45bddfe | |||
b044550475 | |||
a70fa15690 | |||
bd1d7b8d75 | |||
1513a0e092 | |||
c4150d4520 | |||
2f47597d75 | |||
56883f9ff9 | |||
7cdd26add5 | |||
717b866605 | |||
ef97c8f99e | |||
84932ce908 | |||
6bfc309a0a | |||
06e8c6a3ad | |||
71271a0e03 | |||
f87e96026c | |||
b63ad032a9 | |||
d9b0e373bb | |||
8e1b3edd2c | |||
32262d9bb5 | |||
4c1b10b24b | |||
61dc9d7f6b | |||
da9731ef59 | |||
e6f64c609e | |||
8c7fbf379b | |||
3d2ca457f8 | |||
1579f41056 | |||
34a3e0d8b1 | |||
d42217ff57 | |||
70a4f73d73 | |||
7d43dffac4 | |||
804a062c3a | |||
22a4639162 | |||
39d02a67d2 | |||
77d45bf116 | |||
f79182852b | |||
a107ad7404 | |||
7a072931df | |||
f428a9bf52 | |||
2e720b48d9 | |||
a6e79bedf5 | |||
a5ba570fdf | |||
0d5164af02 | |||
534af770f8 | |||
619a9892e5 | |||
63b109f23e | |||
79ed377c7a | |||
2da8ce7a20 | |||
959dd4cbf1 | |||
0a3788f9ac | |||
cdda74ef93 | |||
bbe428a874 | |||
755919c496 | |||
88b216a17b | |||
8020912448 | |||
5571ae05b5 | |||
bc985198a0 | |||
27b2710c56 | |||
1755b25808 | |||
a78133d0e3 | |||
a51a16a55c | |||
099562d582 | |||
ae76e8f08f | |||
42a08e7e4a | |||
b193d9f919 | |||
24d64eedab | |||
0c9d16f1ef | |||
d246933e3e | |||
41d7b8c0e4 | |||
2622c34542 | |||
5c9419b55c | |||
83c40f4502 | |||
372202b3dc | |||
917c744266 | |||
2281fe4e67 | |||
cf538d83bf | |||
7e9c38a9d9 | |||
ccad97727f | |||
e3ebf8bb61 | |||
cb6b59a52a | |||
53dbbd5f97 | |||
51908ec45a | |||
a2543ff80d | |||
20f3030709 | |||
3aa58f54dc | |||
6e08b622b3 | |||
5c12a95151 | |||
604900d4c5 | |||
5f07c5df1c | |||
6422ed7722 | |||
5f33ef35e3 | |||
ec949840b2 | |||
e45e84b236 | |||
dfe68c9788 | |||
35b8f0bf25 | |||
d4dc1c8a0c | |||
517f9a3c3a | |||
636c35dcf1 | |||
d22f0da1de | |||
310de5a2b2 | |||
06a9c98ded | |||
5c7b05c2ba | |||
9c86763322 | |||
35490ca41c | |||
47c7872c88 | |||
f84abcd1fe | |||
b5dd147ec7 | |||
f8ce01e2fd | |||
3907a2b6ba | |||
0dd68e587f | |||
1171cd2493 | |||
330e93e5e3 | |||
e2579e0a2a | |||
2020fcd18e | |||
5a9a576bfa | |||
b8caf34e62 | |||
456d9a722a | |||
344c980cff | |||
167492087f | |||
db215283a2 | |||
6a507bb149 | |||
dc757c25c8 | |||
73267ae077 | |||
a72e6ee706 | |||
8ec0a4d0d6 | |||
89ea7f0a76 | |||
df65f1009c | |||
a6ca37429c | |||
4bf9fb278b | |||
15d81154e6 | |||
93e5c80962 | |||
c19ab97610 | |||
dbaf851be7 | |||
7aa8bd18d3 | |||
53067c26d7 | |||
04581e2700 | |||
93597dcd50 | |||
778814a35e | |||
3cd1da196a | |||
365d4a1592 | |||
2d7f37ac47 | |||
50fcdd6e7e | |||
10317527e4 | |||
46ac4cbca1 | |||
cb9e79b398 | |||
2f1fad2745 | |||
44182dccbd | |||
2f3d2d4a0b | |||
8ac7f7f11f | |||
dbe7caab7b | |||
b581fab31a | |||
7b7dfc36d1 | |||
d63d6b73f6 | |||
a860ccd259 | |||
2bb497b716 | |||
613bd40601 | |||
398b636759 | |||
19bd283807 | |||
20d1a048dd | |||
15b76a24b7 | |||
2d51971b84 | |||
f08e411cad | |||
1257378198 | |||
758a68aa2c | |||
bfce478e72 | |||
681dd469a2 | |||
3edbea8545 | |||
ada8cbb545 | |||
0ac5e03ce9 | |||
9b02b8e51e | |||
6c7dada232 | |||
25bc95cd1e | |||
213bf8366a | |||
4e693e91e6 | |||
a1622fa345 | |||
0ec869932f | |||
79acaa3253 | |||
da3742b39e | |||
d26fcf7dee | |||
812424a619 | |||
1bdc61dd5f | |||
86fc33fe26 | |||
70eb41470c | |||
3a5709bf5e | |||
5ad66c3c9b | |||
7885b54824 | |||
532dc0fb6f | |||
54ccc330d5 | |||
e12618c705 | |||
7d5f2eac8d | |||
e964dd2ca8 | |||
dbb594f130 | |||
8f434b9edd | |||
34972c3327 | |||
037c34d961 | |||
4518d9d9ce | |||
1a5228e7a6 | |||
495bfda044 | |||
41b1fa7b48 | |||
e689fd545b | |||
889cd5e206 | |||
e1ddf90695 | |||
2f325b8c91 | |||
ac4f00be81 | |||
914450c30b | |||
25554f0d61 | |||
e1a61cb51a | |||
fe5620f097 | |||
faef4e8736 | |||
0d19f6c968 | |||
ecf662bf74 | |||
8cba2e0346 | |||
dfc8a6ffdd | |||
262728b091 | |||
4572ec8175 | |||
0f6949ac34 | |||
df8e0cf1f5 | |||
ad87c11ae1 | |||
fa82cb26d8 | |||
fd2a7797bd | |||
e5a2cfb65f | |||
b96bb7d824 | |||
896cca0778 | |||
59cf8e95f0 | |||
99038c752c | |||
88afedd1e8 | |||
c43e21235d | |||
3f7e7352fb | |||
32d6ea0fba | |||
28c787371a | |||
dba14c9f08 | |||
0e35ee8cb7 | |||
da5b7f47df | |||
d418dd7a09 | |||
f3209ccc33 | |||
4a4c28cd8c | |||
eba8d77034 | |||
13e4772f98 | |||
4bc2f28c6d | |||
663469dfa7 | |||
963abb718f | |||
1f2fb73297 | |||
ff55b520b9 | |||
cedd8abf0c | |||
496732999c | |||
6a8105f5a0 | |||
0a566f8218 | |||
829dd02eea | |||
b11c350b2b | |||
f624e36faf | |||
14ce9c10bb | |||
b27aaaeeb2 | |||
f1083bd9c4 | |||
199fa61aef | |||
af82a6bbe1 | |||
004f7ef82e | |||
89ebd2b880 | |||
799183e13e | |||
260ac47588 | |||
4ff4434a22 | |||
5d8bb84269 | |||
9eebfa7cc3 | |||
d3021c6281 | |||
9097d6c4d3 | |||
da43ae82fe | |||
60b405d944 | |||
92a752053d | |||
0537c66849 | |||
d94995e161 | |||
58bc08838b | |||
fc0619ee6e | |||
a5764b3ae9 | |||
8bf469f7fc | |||
3b9a5c5ccc | |||
4c36ca58e2 | |||
a67fa5c007 | |||
839a789180 | |||
e61c3e8bf6 | |||
7ce6c8aa13 | |||
9abcc99c10 | |||
5c8a625d88 | |||
259f0425a9 | |||
9cdea43794 | |||
e007fad5b8 | |||
5cf2fcbbb7 | |||
9e6cbb5b6a | |||
64b3d02974 | |||
640df1003c | |||
2b402e525a | |||
e2871fad8e | |||
41d02003c2 | |||
156ecd9bd8 | |||
fa7736efbb | |||
d71a7ff2fa | |||
8184a6b114 | |||
b8d44ff162 | |||
f6611a38bc | |||
24ed823d96 | |||
f624871b3f | |||
9cd6b3e1c7 | |||
aad1eb5b3e | |||
bff5bf25ae | |||
cda90fd7f1 | |||
9f44adf04a | |||
c4793241f5 | |||
7532c609fb | |||
13f28d8454 | |||
5a97c378fc | |||
e5d62ec901 | |||
cfd975009e | |||
73257ffde7 | |||
8252bea699 | |||
ea935a1af5 | |||
e8a5fa8a37 | |||
db734675d8 | |||
6ede56015d | |||
5334099fbf | |||
82e9072223 | |||
2c11742f9e | |||
bd4a63b668 | |||
cd36af46bf | |||
aa7d55e21d | |||
31e8efa6d1 | |||
facca13139 | |||
fffeeddca6 | |||
e6ba3ce8a6 | |||
11cae2f0c0 | |||
f5a18df835 | |||
1cc7027f92 | |||
8776b71d63 | |||
0b9d0f3cdc | |||
e419d76367 | |||
36cde9f352 | |||
05c602a044 | |||
0db7e57a15 | |||
205e47c0c4 | |||
e328d00cca | |||
ccbcc14600 | |||
e544bc0d4b | |||
fd27227cc7 | |||
b42966f61b | |||
ca86ec2ec2 | |||
97b6183404 | |||
0587d03c03 | |||
c7f1b605f2 | |||
f069df65a8 | |||
1e624e7bb9 | |||
f16a530849 | |||
7137b8a8a4 | |||
ab57914322 | |||
260869c0d5 | |||
9135877da1 | |||
07cb603231 | |||
f59094e6d6 | |||
d8acae5495 | |||
239fe909be | |||
c22576a266 | |||
bac788fd00 | |||
f6d96c5827 | |||
b1458db47b | |||
2d2c9379cd | |||
3400771770 | |||
e12ecaf629 | |||
1303cbfe02 | |||
ad4a211cba | |||
d1e56c4611 | |||
d9bbab54f4 | |||
07cf4eb7a9 | |||
50a7663369 | |||
651ef500a3 | |||
30f2e75278 | |||
2cfc25b4f8 | |||
5bded9cff8 | |||
5816ff85ba | |||
8f7d8347ee | |||
3614d9a78d | |||
818d0e19ab | |||
17720041a3 | |||
c329ff7d4f | |||
8794292788 | |||
0a39e580e9 | |||
c4580dd56d | |||
fab81d28bc | |||
039478223e | |||
64b5db4bf2 | |||
c85f4256c7 | |||
1192b8bdf1 | |||
6dcd2a4ece | |||
3fff0a0656 | |||
e1e1bfa5e3 | |||
1eedac87b2 | |||
cda3e6f4dc | |||
e6a58e2690 | |||
27350c4673 | |||
0d5704b156 | |||
f355044626 | |||
4794ba236a | |||
6490a49c70 | |||
5cd7e11b29 | |||
08e3b8ffdc | |||
9232f4509c | |||
cef77907c6 | |||
06ec8b8397 | |||
ee08286eca | |||
a83211f96a | |||
0b3c4ee496 | |||
54de518634 | |||
a908197907 | |||
3e23a568ca | |||
dadc5c1b87 | |||
870c66d1fe | |||
1a467420e3 | |||
02fcfcc383 | |||
09961b5cd0 | |||
71a472e0eb | |||
e65bc5c3ae | |||
2ae37cc1c5 | |||
9a67192f74 | |||
4cfceeeb8e | |||
3e4e0d51df | |||
cb76f8a5df | |||
0591458ef6 | |||
eeddaced9f | |||
c237ff538c | |||
23b00bea5b | |||
cde2c10c1d | |||
87fb42cabd | |||
6566dd8c8f | |||
1e65ac0d85 | |||
cb247a5f28 | |||
bb048fb361 | |||
9e993aa83f | |||
fab12707ae | |||
51f299f196 | |||
2bb52cf811 | |||
6afc689529 | |||
5a17a0d1aa | |||
b38c81c96f | |||
0fabc0c199 | |||
ec5598dbb1 | |||
7b98d203f4 | |||
4635b93f4d | |||
a8433697ad | |||
680cdb8e3e | |||
eaa78fe849 | |||
eedea4998b | |||
4e5a80c481 | |||
4d54dc30c1 | |||
ac5339414a | |||
9fd922fe6a | |||
fdaf9dce73 | |||
732e27751c | |||
932c489de1 |
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -20,8 +20,9 @@ assignees: ''
|
|||||||
<!-- try the `version` command | LATEST IS NOT A VALID VERSION -->
|
<!-- try the `version` command | LATEST IS NOT A VALID VERSION -->
|
||||||
* PocketMine-MP:
|
* PocketMine-MP:
|
||||||
* PHP:
|
* PHP:
|
||||||
|
* Using JIT: yes/no (delete as appropriate) <!-- look for the giant yellow warning in the log that says you're using JIT -->
|
||||||
* Server OS:
|
* Server OS:
|
||||||
* Game version: PE/Win10 (delete as appropriate)
|
* Game version: Android/iOS/Win10/Xbox/PS4/Switch (delete as appropriate)
|
||||||
|
|
||||||
### Plugins
|
### Plugins
|
||||||
<!--- use the `plugins` command and paste the output below -->
|
<!--- use the `plugins` command and paste the output below -->
|
||||||
|
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Help & support on Discord
|
||||||
|
url: https://discord.gg/bmSAZBG
|
||||||
|
about: We don't accept support requests on the issue tracker. Please try asking on Discord instead.
|
||||||
|
- name: Help & support on forums
|
||||||
|
url: https://forums.pmmp.io
|
||||||
|
about: We don't accept support requests on the issue tracker. Please try asking on forums instead.
|
||||||
|
- name: Documentation
|
||||||
|
url: https://pmmp.rtfd.io
|
||||||
|
about: PocketMine-MP documentation
|
1
.github/ISSUE_TEMPLATE/crash.md
vendored
1
.github/ISSUE_TEMPLATE/crash.md
vendored
@ -9,6 +9,7 @@ assignees: ''
|
|||||||
|
|
||||||
<!--- submit crashdump files to https://crash.pmmp.io -->
|
<!--- 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 -->
|
<!--- or, copy the data between ===BEGIN CRASH DUMP=== and ===END CRASH DUMP and paste it on a site like https://pastebin.com -->
|
||||||
|
<!--- DON'T JUST PASTE the crashdump into an issue -->
|
||||||
Link to crashdump:
|
Link to crashdump:
|
||||||
|
|
||||||
<!--- write additional information about the crash to help us find the problem -->
|
<!--- write additional information about the crash to help us find the problem -->
|
||||||
|
14
.github/ISSUE_TEMPLATE/help---support.md
vendored
14
.github/ISSUE_TEMPLATE/help---support.md
vendored
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
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/bmSAZBG
|
|
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
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.
|
|
8
.github/dependabot.yml
vendored
Normal file
8
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: composer
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
time: "10:00"
|
||||||
|
open-pull-requests-limit: 10
|
16
.github/support.yml
vendored
16
.github/support.yml
vendored
@ -1,16 +0,0 @@
|
|||||||
# Configuration for support-requests - https://github.com/dessant/support-requests
|
|
||||||
|
|
||||||
# Label used to mark issues as support requests
|
|
||||||
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: >
|
|
||||||
Thanks, but this issue tracker is not intended for support requests. Please read the guidelines on [submitting an issue](https://github.com/pmmp/PocketMine-MP/blob/master/CONTRIBUTING.md#creating-an-issue).
|
|
||||||
|
|
||||||
|
|
||||||
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bmSAZBG) | [Forums](https://forums.pmmp.io)
|
|
||||||
|
|
||||||
# Whether to close issues marked as support requests
|
|
||||||
close: true
|
|
||||||
# Whether to lock issues marked as support requests
|
|
||||||
lock: false
|
|
113
.github/workflows/draft-release.yml
vendored
Normal file
113
.github/workflows/draft-release.yml
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
name: Draft release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: "*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
draft:
|
||||||
|
name: Create GitHub draft release
|
||||||
|
if: "startsWith(github.event.head_commit.message, 'Release ')"
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@2.12.0
|
||||||
|
with:
|
||||||
|
php-version: 8.0
|
||||||
|
|
||||||
|
- name: Restore Composer package cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/composer/files
|
||||||
|
~/.cache/composer/vcs
|
||||||
|
key: "composer-v2-cache-${{ hashFiles('./composer.lock') }}"
|
||||||
|
restore-keys: |
|
||||||
|
composer-v2-cache-
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
||||||
|
|
||||||
|
- name: Patch VersionInfo
|
||||||
|
run: |
|
||||||
|
BUILD_NUMBER=2000+$GITHUB_RUN_NUMBER #to stay above jenkins
|
||||||
|
echo "Build number: $BUILD_NUMBER"
|
||||||
|
sed -i "s/const BUILD_NUMBER = 0/const BUILD_NUMBER = ${BUILD_NUMBER}/" src/pocketmine/VersionInfo.php
|
||||||
|
|
||||||
|
- name: Minify BedrockData JSON files
|
||||||
|
run: php src/pocketmine/resources/vanilla/.minify_json.php
|
||||||
|
|
||||||
|
- name: Run preprocessor
|
||||||
|
run: |
|
||||||
|
PM_PREPROCESSOR_PATH="$GITHUB_WORKSPACE/build/preprocessor"
|
||||||
|
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path=src --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||||
|
#dump the diff of preprocessor replacements to a patch in case it has bugs
|
||||||
|
git diff > preprocessor_diff.patch
|
||||||
|
VENDOR_PM="$GITHUB_WORKSPACE/vendor"
|
||||||
|
VENDOR_PM_BACKUP="$GITHUB_WORKSPACE/vendor-before-preprocess"
|
||||||
|
cp -r "$VENDOR_PM" "$VENDOR_PM_BACKUP"
|
||||||
|
for f in $(ls $VENDOR_PM/pocketmine); do
|
||||||
|
echo "Processing directory \"$f\"..."
|
||||||
|
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path="$VENDOR_PM/pocketmine/$f/src" --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||||
|
echo "Checking for changes in \"$f\"..."
|
||||||
|
DIFF=$(git diff --no-index "$VENDOR_PM_BACKUP/pocketmine/$f" "$VENDOR_PM/pocketmine/$f" || true)
|
||||||
|
if [ "$DIFF" != "" ]; then
|
||||||
|
PATCH="$GITHUB_WORKSPACE/preprocessor_diff_$f.patch"
|
||||||
|
echo "$DIFF" > "$PATCH"
|
||||||
|
echo "Generated patch file \"$PATCH\""
|
||||||
|
else
|
||||||
|
echo "No diff generated for \"$f\" (preprocessor made no changes)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Build PocketMine-MP.phar
|
||||||
|
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Get PocketMine-MP release version
|
||||||
|
id: get-pm-version
|
||||||
|
run: |
|
||||||
|
echo ::set-output name=PM_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\BASE_VERSION;')
|
||||||
|
echo ::set-output name=MCPE_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;')
|
||||||
|
echo ::set-output name=PM_VERSION_SHORT::$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\BASE_VERSION); array_pop($v); echo implode(".", $v);')
|
||||||
|
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\BASE_VERSION);')
|
||||||
|
|
||||||
|
- name: Generate build info
|
||||||
|
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} > build_info.json
|
||||||
|
|
||||||
|
- name: Upload release artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: release_artifacts
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}/PocketMine-MP.phar
|
||||||
|
${{ github.workspace }}/start.*
|
||||||
|
${{ github.workspace }}/build_info.json
|
||||||
|
|
||||||
|
- name: Create draft release
|
||||||
|
uses: ncipollo/release-action@v1.8.6
|
||||||
|
with:
|
||||||
|
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
|
||||||
|
commit: ${{ github.sha }}
|
||||||
|
draft: true
|
||||||
|
name: PocketMine-MP ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||||
|
tag: ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
body: |
|
||||||
|
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
|
||||||
|
|
||||||
|
Please see the [changelogs](/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||||
|
|
||||||
|
- name: Upload preprocessor diffs
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: preprocessor_diffs
|
||||||
|
path: ${{ github.workspace }}/preprocessor_diff*.patch
|
||||||
|
|
227
.github/workflows/main.yml
vendored
Normal file
227
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-php:
|
||||||
|
name: Prepare PHP
|
||||||
|
runs-on: ${{ matrix.image }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
image: [ubuntu-20.04]
|
||||||
|
php: [8.0.11]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Build and prepare PHP cache
|
||||||
|
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
install-path: "./bin"
|
||||||
|
|
||||||
|
phpstan:
|
||||||
|
name: PHPStan analysis
|
||||||
|
needs: build-php
|
||||||
|
runs-on: ${{ matrix.image }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
image: [ubuntu-20.04]
|
||||||
|
php: [8.0.11]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
install-path: "./bin"
|
||||||
|
|
||||||
|
- name: Install Composer
|
||||||
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
|
- name: Restore Composer package cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/composer/files
|
||||||
|
~/.cache/composer/vcs
|
||||||
|
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||||
|
restore-keys: |
|
||||||
|
composer-v2-cache-
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: php composer.phar install --prefer-dist --no-interaction
|
||||||
|
|
||||||
|
- name: Run PHPStan
|
||||||
|
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
|
||||||
|
|
||||||
|
phpunit:
|
||||||
|
name: PHPUnit tests
|
||||||
|
needs: build-php
|
||||||
|
runs-on: ${{ matrix.image }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
image: [ubuntu-20.04]
|
||||||
|
php: [8.0.11]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
install-path: "./bin"
|
||||||
|
|
||||||
|
- name: Install Composer
|
||||||
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
|
- name: Restore Composer package cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/composer/files
|
||||||
|
~/.cache/composer/vcs
|
||||||
|
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||||
|
restore-keys: |
|
||||||
|
composer-v2-cache-
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: php composer.phar install --prefer-dist --no-interaction
|
||||||
|
|
||||||
|
- name: Run PHPUnit tests
|
||||||
|
run: ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
|
||||||
|
|
||||||
|
integration:
|
||||||
|
name: Integration tests
|
||||||
|
needs: build-php
|
||||||
|
runs-on: ${{ matrix.image }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
image: [ubuntu-20.04]
|
||||||
|
php: [8.0.11]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
install-path: "./bin"
|
||||||
|
|
||||||
|
- name: Install Composer
|
||||||
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
|
- name: Restore Composer package cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/composer/files
|
||||||
|
~/.cache/composer/vcs
|
||||||
|
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||||
|
restore-keys: |
|
||||||
|
composer-v2-cache-
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: php composer.phar install --no-dev --prefer-dist --no-interaction
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
run: ./tests/travis.sh -t4
|
||||||
|
|
||||||
|
preprocessor:
|
||||||
|
name: Preprocessor tests
|
||||||
|
needs: build-php
|
||||||
|
runs-on: ${{ matrix.image }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
image: [ubuntu-20.04]
|
||||||
|
php: [8.0.11]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
install-path: "./bin"
|
||||||
|
|
||||||
|
- name: Install Composer
|
||||||
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
|
- name: Restore Composer package cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/composer/files
|
||||||
|
~/.cache/composer/vcs
|
||||||
|
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||||
|
restore-keys: |
|
||||||
|
composer-v2-cache-
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: php composer.phar install --no-dev --prefer-dist --no-interaction
|
||||||
|
|
||||||
|
- name: Run preprocessor
|
||||||
|
run: |
|
||||||
|
PM_PREPROCESSOR_PATH="$GITHUB_WORKSPACE/build/preprocessor"
|
||||||
|
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path=src --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||||
|
|
||||||
|
#dump the diff of preprocessor replacements to a patch in case it has bugs
|
||||||
|
git diff > preprocessor_diff.patch
|
||||||
|
|
||||||
|
VENDOR_PM="$GITHUB_WORKSPACE/vendor"
|
||||||
|
VENDOR_PM_BACKUP="$GITHUB_WORKSPACE/vendor-before-preprocess"
|
||||||
|
cp -r "$VENDOR_PM" "$VENDOR_PM_BACKUP"
|
||||||
|
for f in $(ls $VENDOR_PM/pocketmine); do
|
||||||
|
echo "Processing directory \"$f\"..."
|
||||||
|
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path="$VENDOR_PM/pocketmine/$f/src" --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||||
|
echo "Checking for changes in \"$f\"..."
|
||||||
|
DIFF=$(git diff --no-index "$VENDOR_PM_BACKUP/pocketmine/$f" "$VENDOR_PM/pocketmine/$f" || true)
|
||||||
|
if [ "$DIFF" != "" ]; then
|
||||||
|
PATCH="$GITHUB_WORKSPACE/preprocessor_diff_$f.patch"
|
||||||
|
echo "$DIFF" > "$PATCH"
|
||||||
|
echo "Generated patch file \"$PATCH\""
|
||||||
|
else
|
||||||
|
echo "No diff generated for \"$f\" (preprocessor made no changes)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Upload preprocessor diffs
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: preprocessor_diffs_${{ matrix.php }}_${{ matrix.image }}
|
||||||
|
path: ${{ github.workspace }}/preprocessor_diff*.patch
|
||||||
|
|
||||||
|
codestyle:
|
||||||
|
name: Code Style checks
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup PHP and tools
|
||||||
|
uses: shivammathur/setup-php@2.15.0
|
||||||
|
with:
|
||||||
|
php-version: 8.0
|
||||||
|
tools: php-cs-fixer:3.2
|
||||||
|
|
||||||
|
- name: Run PHP-CS-Fixer
|
||||||
|
run: php-cs-fixer fix --dry-run --diff
|
22
.github/workflows/support.yml
vendored
Normal file
22
.github/workflows/support.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
name: 'Manage support request issues'
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [labeled, unlabeled, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
support:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: dessant/support-requests@v2
|
||||||
|
with:
|
||||||
|
github-token: ${{ github.token }}
|
||||||
|
support-label: "Support request"
|
||||||
|
issue-comment: >
|
||||||
|
Thanks, but this issue tracker is not intended for support requests. Please read the guidelines on [submitting an issue](https://github.com/pmmp/PocketMine-MP/blob/master/CONTRIBUTING.md#creating-an-issue).
|
||||||
|
|
||||||
|
|
||||||
|
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bmSAZBG) | [Forums](https://forums.pmmp.io)
|
||||||
|
|
||||||
|
close-issue: true
|
||||||
|
lock-issue: false
|
49
.github/workflows/update-php-versions.php
vendored
Normal file
49
.github/workflows/update-php-versions.php
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?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);
|
||||||
|
|
||||||
|
const VERSIONS = [
|
||||||
|
"8.0"
|
||||||
|
];
|
||||||
|
|
||||||
|
$workflowFile = file_get_contents(__DIR__ . '/main.yml');
|
||||||
|
$newWorkflowFile = $workflowFile;
|
||||||
|
foreach(VERSIONS as $v){
|
||||||
|
$releaseInfo = file_get_contents("https://secure.php.net/releases?json&version=$v");
|
||||||
|
if($releaseInfo === false){
|
||||||
|
throw new \RuntimeException("Failed to contact php.net API");
|
||||||
|
}
|
||||||
|
$data = json_decode($releaseInfo, true);
|
||||||
|
if(!is_array($data) || !isset($data["version"]) || !is_string($data["version"]) || preg_match('/^\d+\.\d+\.\d+(-[A-Za-z\d]+)?$/', $data["version"]) === 0){
|
||||||
|
throw new \RuntimeException("Invalid data returned by API");
|
||||||
|
}
|
||||||
|
$updated = preg_replace("/$v\.\d+/", $data["version"], $newWorkflowFile);
|
||||||
|
if($updated !== $newWorkflowFile){
|
||||||
|
echo "Updated $v revision to " . $data["version"] . "\n";
|
||||||
|
}
|
||||||
|
$newWorkflowFile = $updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($workflowFile !== $newWorkflowFile){
|
||||||
|
echo "Writing modified workflow file\n";
|
||||||
|
file_put_contents(__DIR__ . '/main.yml', $newWorkflowFile);
|
||||||
|
}
|
45
.github/workflows/update-updater-api.yml
vendored
Normal file
45
.github/workflows/update-updater-api.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
name: Update update.pmmp.io API info
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install jq
|
||||||
|
run: sudo apt update && sudo apt install jq -y
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: pmmp/update.pmmp.io
|
||||||
|
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
|
||||||
|
|
||||||
|
- name: Get actual tag name
|
||||||
|
id: tag-name
|
||||||
|
run: echo ::set-output name=TAG_NAME::$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
|
||||||
|
|
||||||
|
- name: Download new release information
|
||||||
|
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
||||||
|
|
||||||
|
- name: Detect channel
|
||||||
|
id: channel
|
||||||
|
run: echo ::set-output name=CHANNEL::$(jq -r '.channel' new_build_info.json)
|
||||||
|
|
||||||
|
- name: Copy release information
|
||||||
|
run: |
|
||||||
|
cp new_build_info.json channels/${{ steps.channel.outputs.CHANNEL }}.json
|
||||||
|
rm new_build_info.json
|
||||||
|
|
||||||
|
- name: Commit changes
|
||||||
|
run: |
|
||||||
|
git config user.name github-actions
|
||||||
|
git config user.email github-actions@github.com
|
||||||
|
git add .
|
||||||
|
git diff-index --quiet HEAD || git commit -m "New ${{ steps.channel.outputs.CHANNEL }} release: ${{ github.repository }} ${{ steps.tag-name.outputs.TAG_NAME }}"
|
||||||
|
|
||||||
|
- name: Push changes
|
||||||
|
run: git push
|
11
.gitignore
vendored
11
.gitignore
vendored
@ -16,7 +16,9 @@ server.lock
|
|||||||
/phpstan.neon
|
/phpstan.neon
|
||||||
|
|
||||||
# Common IDEs
|
# Common IDEs
|
||||||
.idea/
|
.idea/*
|
||||||
|
!.idea/codeStyles/
|
||||||
|
!.idea/fileTemplates/
|
||||||
nbproject/*
|
nbproject/*
|
||||||
|
|
||||||
# Windows image file caches
|
# Windows image file caches
|
||||||
@ -41,3 +43,10 @@ test_data/*
|
|||||||
|
|
||||||
# Doxygen
|
# Doxygen
|
||||||
Documentation/*
|
Documentation/*
|
||||||
|
|
||||||
|
# PHPUnit
|
||||||
|
/.phpunit.result.cache
|
||||||
|
|
||||||
|
# php-cs-fixer
|
||||||
|
/.php_cs.cache
|
||||||
|
/.php-cs-fixer.cache
|
||||||
|
14
.gitmodules
vendored
14
.gitmodules
vendored
@ -1,15 +1,15 @@
|
|||||||
[submodule "src/pocketmine/lang/locale"]
|
[submodule "src/pocketmine/lang/locale"]
|
||||||
path = src/pocketmine/lang/locale
|
path = src/pocketmine/lang/locale
|
||||||
url = https://github.com/pmmp/PocketMine-Language.git
|
url = https://github.com/pmmp/Language.git
|
||||||
[submodule "tests/preprocessor"]
|
[submodule "tests/preprocessor"]
|
||||||
path = build/preprocessor
|
path = build/preprocessor
|
||||||
url = https://github.com/pmmp/preprocessor.git
|
url = https://github.com/pmmp/preprocessor.git
|
||||||
[submodule "tests/plugins/PocketMine-DevTools"]
|
[submodule "tests/plugins/DevTools"]
|
||||||
path = tests/plugins/PocketMine-DevTools
|
path = tests/plugins/DevTools
|
||||||
url = https://github.com/pmmp/PocketMine-DevTools.git
|
url = https://github.com/pmmp/DevTools.git
|
||||||
[submodule "src/pocketmine/resources/vanilla"]
|
|
||||||
path = src/pocketmine/resources/vanilla
|
|
||||||
url = https://github.com/pmmp/BedrockData.git
|
|
||||||
[submodule "build/php"]
|
[submodule "build/php"]
|
||||||
path = build/php
|
path = build/php
|
||||||
url = https://github.com/pmmp/php-build-scripts.git
|
url = https://github.com/pmmp/php-build-scripts.git
|
||||||
|
[submodule "src/pocketmine/resources/vanilla"]
|
||||||
|
path = src/pocketmine/resources/vanilla
|
||||||
|
url = https://github.com/pmmp/BedrockData.git
|
||||||
|
71
.idea/codeStyles/Project.xml
generated
Normal file
71
.idea/codeStyles/Project.xml
generated
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
|
<HTMLCodeStyleSettings>
|
||||||
|
<option name="HTML_TEXT_WRAP" value="0" />
|
||||||
|
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="thead,tbody,tfoot" />
|
||||||
|
</HTMLCodeStyleSettings>
|
||||||
|
<PHPCodeStyleSettings>
|
||||||
|
<option name="ALIGN_PHPDOC_PARAM_NAMES" value="true" />
|
||||||
|
<option name="PHPDOC_BLANK_LINES_AROUND_PARAMETERS" value="true" />
|
||||||
|
<option name="LOWER_CASE_BOOLEAN_CONST" value="true" />
|
||||||
|
<option name="LOWER_CASE_NULL_CONST" value="true" />
|
||||||
|
<option name="VARIABLE_NAMING_STYLE" value="CAMEL_CASE" />
|
||||||
|
<option name="SPACES_WITHIN_SHORT_ECHO_TAGS" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_CLOSURE_LEFT_PARENTHESIS" value="false" />
|
||||||
|
<option name="FORCE_SHORT_DECLARATION_ARRAY_STYLE" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_COLON_IN_RETURN_TYPE" value="true" />
|
||||||
|
</PHPCodeStyleSettings>
|
||||||
|
<editorconfig>
|
||||||
|
<option name="ENABLED" value="false" />
|
||||||
|
</editorconfig>
|
||||||
|
<codeStyleSettings language="HTML">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="JSON">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="4" />
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="PHP">
|
||||||
|
<option name="CLASS_BRACE_STYLE" value="1" />
|
||||||
|
<option name="METHOD_BRACE_STYLE" value="1" />
|
||||||
|
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||||
|
<option name="ALIGN_MULTILINE_FOR" value="false" />
|
||||||
|
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
|
||||||
|
<option name="SPACE_AFTER_TYPE_CAST" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_CLASS_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_METHOD_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_IF_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_ELSE_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_WHILE_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_FOR_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_DO_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_SWITCH_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_TRY_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_CATCH_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_FINALLY_LBRACE" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_ELSE_KEYWORD" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_WHILE_KEYWORD" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_CATCH_KEYWORD" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_FINALLY_KEYWORD" value="false" />
|
||||||
|
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="neon">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
8
.idea/fileTemplates/code/PHP Constructor.php
generated
Normal file
8
.idea/fileTemplates/code/PHP Constructor.php
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#if(${THROWS_DOC} != "")
|
||||||
|
/**
|
||||||
|
${THROWS_DOC}
|
||||||
|
*/
|
||||||
|
#end
|
||||||
|
public function __construct(${PARAM_LIST}) {
|
||||||
|
${BODY}
|
||||||
|
}
|
6
.idea/fileTemplates/code/PHP Fluent Setter Method.php
generated
Normal file
6
.idea/fileTemplates/code/PHP Fluent Setter Method.php
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/** @return $this */
|
||||||
|
public function set${NAME}(#if (${SCALAR_TYPE_HINT})${SCALAR_TYPE_HINT} #else#end$${PARAM_NAME})#if(${RETURN_TYPE}): self#else#end
|
||||||
|
{
|
||||||
|
$this->${FIELD_NAME} = $${PARAM_NAME};
|
||||||
|
return $this;
|
||||||
|
}
|
3
.idea/fileTemplates/code/PHP Getter Method.php
generated
Normal file
3
.idea/fileTemplates/code/PHP Getter Method.php
generated
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#if(${TYPE_HINT} != ${RETURN_TYPE} && ${TYPE_HINT} != "")/** @return ${TYPE_HINT} */#end
|
||||||
|
public ${STATIC} function ${GET_OR_IS}${NAME}()#if(${RETURN_TYPE}): ${RETURN_TYPE}#else#end
|
||||||
|
{ return #if(${STATIC} == "static")self::$${FIELD_NAME};#else$this->${FIELD_NAME};#end }
|
2
.idea/fileTemplates/code/PHP Setter Method.php
generated
Normal file
2
.idea/fileTemplates/code/PHP Setter Method.php
generated
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
public ${STATIC} function set${NAME}(#if (${SCALAR_TYPE_HINT})${SCALAR_TYPE_HINT} #end$${PARAM_NAME})#if (${VOID_RETURN_TYPE}):void #end
|
||||||
|
{#if (${STATIC} == "static") self::$${FIELD_NAME} = $${PARAM_NAME}; #else $this->${FIELD_NAME} = $${PARAM_NAME}; #end}
|
0
.idea/fileTemplates/includes/PHP Class Doc Comment.php
generated
Normal file
0
.idea/fileTemplates/includes/PHP Class Doc Comment.php
generated
Normal file
21
.idea/fileTemplates/includes/PHP File Header.php
generated
Normal file
21
.idea/fileTemplates/includes/PHP File Header.php
generated
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* 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);
|
5
.idea/fileTemplates/includes/PHP Function Doc Comment.php
generated
Normal file
5
.idea/fileTemplates/includes/PHP Function Doc Comment.php
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#if (${THROWS_DOC} != "")
|
||||||
|
/**
|
||||||
|
${THROWS_DOC}
|
||||||
|
*/
|
||||||
|
#end
|
0
.idea/fileTemplates/includes/PHP Interface Doc Comment.php
generated
Normal file
0
.idea/fileTemplates/includes/PHP Interface Doc Comment.php
generated
Normal file
1
.idea/fileTemplates/includes/PHP Property Doc Comment.php
generated
Normal file
1
.idea/fileTemplates/includes/PHP Property Doc Comment.php
generated
Normal file
@ -0,0 +1 @@
|
|||||||
|
/** @var ${TYPE_HINT} */
|
0
.idea/fileTemplates/includes/PHP Trait Doc Comment.php
generated
Normal file
0
.idea/fileTemplates/includes/PHP Trait Doc Comment.php
generated
Normal file
10
.idea/fileTemplates/internal/PHP Class.php
generated
Normal file
10
.idea/fileTemplates/internal/PHP Class.php
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
#parse("PHP File Header.php")
|
||||||
|
|
||||||
|
#if (${NAMESPACE})
|
||||||
|
namespace ${NAMESPACE};
|
||||||
|
#end
|
||||||
|
|
||||||
|
final class ${NAME} {
|
||||||
|
|
||||||
|
}
|
4
.idea/fileTemplates/internal/PHP File.php
generated
Normal file
4
.idea/fileTemplates/internal/PHP File.php
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
#parse("PHP File Header.php")
|
||||||
|
|
||||||
|
|
10
.idea/fileTemplates/internal/PHP Interface.php
generated
Normal file
10
.idea/fileTemplates/internal/PHP Interface.php
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
#parse("PHP File Header.php")
|
||||||
|
|
||||||
|
#if (${NAMESPACE})
|
||||||
|
namespace ${NAMESPACE};
|
||||||
|
#end
|
||||||
|
|
||||||
|
interface ${NAME} {
|
||||||
|
|
||||||
|
}
|
10
.idea/fileTemplates/internal/PHP Trait.php
generated
Normal file
10
.idea/fileTemplates/internal/PHP Trait.php
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
#parse("PHP File Header.php")
|
||||||
|
|
||||||
|
#if (${NAMESPACE})
|
||||||
|
namespace ${NAMESPACE};
|
||||||
|
#end
|
||||||
|
|
||||||
|
trait ${NAME} {
|
||||||
|
|
||||||
|
}
|
77
.php-cs-fixer.php
Normal file
77
.php-cs-fixer.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$finder = PhpCsFixer\Finder::create()
|
||||||
|
->in(__DIR__ . '/src')
|
||||||
|
->in(__DIR__ . '/build')
|
||||||
|
->in(__DIR__ . '/tests')
|
||||||
|
->notPath('plugins/DevTools')
|
||||||
|
->notPath('preprocessor')
|
||||||
|
->notContains('#ifndef COMPILE') //preprocessor will break if these are changed
|
||||||
|
->notName('PocketMine.php');
|
||||||
|
|
||||||
|
return (new PhpCsFixer\Config)
|
||||||
|
->setRiskyAllowed(true)
|
||||||
|
->setRules([
|
||||||
|
'align_multiline_comment' => [
|
||||||
|
'comment_type' => 'phpdocs_only'
|
||||||
|
],
|
||||||
|
'array_indentation' => true,
|
||||||
|
'array_syntax' => [
|
||||||
|
'syntax' => 'short'
|
||||||
|
],
|
||||||
|
'blank_line_after_namespace' => true,
|
||||||
|
'blank_line_after_opening_tag' => true,
|
||||||
|
'blank_line_before_statement' => [
|
||||||
|
'statements' => [
|
||||||
|
'declare'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'cast_spaces' => [
|
||||||
|
'space' => 'single'
|
||||||
|
],
|
||||||
|
'concat_space' => [
|
||||||
|
'spacing' => 'one'
|
||||||
|
],
|
||||||
|
'declare_strict_types' => true,
|
||||||
|
'elseif' => true,
|
||||||
|
'global_namespace_import' => [
|
||||||
|
'import_constants' => true,
|
||||||
|
'import_functions' => true,
|
||||||
|
'import_classes' => null,
|
||||||
|
],
|
||||||
|
'indentation_type' => true,
|
||||||
|
'native_function_invocation' => [
|
||||||
|
'scope' => 'namespaced',
|
||||||
|
'include' => ['@all'],
|
||||||
|
],
|
||||||
|
'no_closing_tag' => true,
|
||||||
|
'no_empty_phpdoc' => true,
|
||||||
|
'no_extra_blank_lines' => true,
|
||||||
|
'no_superfluous_phpdoc_tags' => [
|
||||||
|
'allow_mixed' => true,
|
||||||
|
],
|
||||||
|
'no_trailing_whitespace' => true,
|
||||||
|
'no_trailing_whitespace_in_comment' => true,
|
||||||
|
'no_whitespace_in_blank_line' => true,
|
||||||
|
'no_unused_imports' => true,
|
||||||
|
'ordered_imports' => [
|
||||||
|
'imports_order' => [
|
||||||
|
'class',
|
||||||
|
'function',
|
||||||
|
'const',
|
||||||
|
],
|
||||||
|
'sort_algorithm' => 'alpha'
|
||||||
|
],
|
||||||
|
'phpdoc_line_span' => [
|
||||||
|
'property' => 'single',
|
||||||
|
'method' => null,
|
||||||
|
'const' => null
|
||||||
|
],
|
||||||
|
'phpdoc_trim' => true,
|
||||||
|
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||||
|
'single_import_per_statement' => true,
|
||||||
|
'strict_param' => true,
|
||||||
|
])
|
||||||
|
->setFinder($finder)
|
||||||
|
->setIndent("\t")
|
||||||
|
->setLineEnding("\n");
|
25
.travis.yml
25
.travis.yml
@ -1,25 +0,0 @@
|
|||||||
language: php
|
|
||||||
|
|
||||||
php:
|
|
||||||
- 7.2
|
|
||||||
- 7.3
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
|
||||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
|
||||||
- git clone https://github.com/pmmp/pthreads.git
|
|
||||||
- cd pthreads
|
|
||||||
- git checkout 1b7da492b944146fa9680f6399bd9c6c6c6095e0
|
|
||||||
- phpize
|
|
||||||
- ./configure
|
|
||||||
- make
|
|
||||||
- make install
|
|
||||||
- cd ..
|
|
||||||
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
|
||||||
- composer install
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./tests/travis.sh -t4
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
44
BUILDING.md
Normal file
44
BUILDING.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Building
|
||||||
|
## Pre-requisites
|
||||||
|
- A bash shell (git bash is sufficient for Windows)
|
||||||
|
- [`git`](https://git-scm.com) available in your shell
|
||||||
|
- PHP 8.0 or newer available in your shell
|
||||||
|
- [`composer`](https://getcomposer.org) available in your shell
|
||||||
|
|
||||||
|
## Custom PHP binaries
|
||||||
|
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
||||||
|
|
||||||
|
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-8.0-Aggregate)
|
||||||
|
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
||||||
|
|
||||||
|
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
||||||
|
|
||||||
|
## Setting up environment
|
||||||
|
1. `git clone --recursive https://github.com/pmmp/PocketMine-MP.git`
|
||||||
|
2. `composer install`
|
||||||
|
|
||||||
|
## Checking out a different branch to build
|
||||||
|
1. `git checkout <branch to checkout>`
|
||||||
|
2. `git submodule update --init`
|
||||||
|
3. Re-run `composer install` to synchronize dependencies.
|
||||||
|
|
||||||
|
## Optimizing for release builds
|
||||||
|
1. Add the flags `--no-dev --classmap-authoritative` to your `composer install` command. This will reduce build size and improve autoloading speed.
|
||||||
|
2. Preprocess the source code by running `build/preprocessor/PreProcessor.php`. Usage instructions are provided in `build/preprocessor/README.md`.
|
||||||
|
|
||||||
|
### Note
|
||||||
|
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
|
||||||
|
|
||||||
|
## Building `PocketMine-MP.phar`
|
||||||
|
Run `composer make-server` using your preferred PHP binary. It'll drop a `PocketMine-MP.phar` into the current working directory.
|
||||||
|
|
||||||
|
You can also use the `--out` option to change the output filename.
|
||||||
|
|
||||||
|
There is a bug in PHP that might cause an error which looks like this:
|
||||||
|
```
|
||||||
|
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
|
||||||
|
```
|
||||||
|
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 8.0.3.
|
||||||
|
|
||||||
|
## Running PocketMine-MP from source code
|
||||||
|
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.
|
181
CONTRIBUTING.md
181
CONTRIBUTING.md
@ -2,125 +2,102 @@
|
|||||||
|
|
||||||
# PocketMine-MP Contribution Guidelines
|
# PocketMine-MP Contribution Guidelines
|
||||||
|
|
||||||
|
PocketMine-MP is an open source project, and contributions from the community are welcomed, as long as they comply with our quality standards and licensing.
|
||||||
|
|
||||||
## Creating an Issue
|
Code contributions must be submitted using [GitHub Pull Requests](https://github.com/pmmp/PocketMine-MP/pulls), where they will be reviewed by maintainers.
|
||||||
- If you are reporting a bug:
|
|
||||||
- **make sure that you are using the latest supported version** before opening an issue.
|
|
||||||
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
|
|
||||||
- **[Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue)** to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
|
|
||||||
- **Do not report plugin issues here.** If your issue is related to a plugin, contact the plugin's original author instead.
|
|
||||||
- **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and will be closed. If you need help, please see [here](README.md#discussion) and do not misuse our issue tracker.
|
|
||||||
- **No generic titles** such as "Question", "Help", "Crash Report" etc. A good issue report provides a quick summary in the title. If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
|
|
||||||
- **Provide information in the issue body, not in the title.** No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
|
|
||||||
- **No generic issue reports.** For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
|
|
||||||
<br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
|
|
||||||
<br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
|
|
||||||
<br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
|
|
||||||
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.
|
|
||||||
- If your issue is related to the PocketMine-MP website, forums, etc., please [talk to a human directly](README.md#discussion).
|
|
||||||
|
|
||||||
|
Small contributions (e.g. minor bug fixes) can be submitted as pull requests directly.
|
||||||
|
|
||||||
|
Larger contributions like feature additions should be preceded by a [Change Proposal](#rfcs--change-proposals) to allow maintainers and other people to discuss and decide if it's a good idea or not.
|
||||||
|
|
||||||
## Contributing
|
## Useful documentation from github.com
|
||||||
To contribute to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
|
- [About pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)
|
||||||
|
- [About forks](https://docs.github.com/en/github/collaborating-with-pull-requests/working-with-forks/about-forks)
|
||||||
|
- [Creating a pull request from a fork](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)
|
||||||
|
|
||||||
### Licensing
|
## Other things you'll need
|
||||||
By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
|
- [git](https://git-scm.com/)
|
||||||
|
|
||||||
### Contribution standards
|
## Making a pull request
|
||||||
- **We enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**.
|
The basic procedure to create a pull request is:
|
||||||
We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself.
|
1. [Fork the repository on GitHub](https://github.com/pmmp/PocketMine-MP/fork). This gives you your own copy of the repository to make changes to.
|
||||||
- **If a contribution does not meet our standards, changes may be requested or the pull request may be closed.**
|
2. Create a branch on your fork for your changes.
|
||||||
|
3. Make the changes you want to make on this branch.
|
||||||
|
4. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project.
|
||||||
|
|
||||||
### Pull requests
|
## Pull request reviews
|
||||||
- **Create a new branch for each pull request.** Do not create a pull request with commits that exist in another pull request.
|
Pull requests will be reviewed by maintainers when they are available.
|
||||||
|
Note that there might be a long wait time before a reviewer looks at your PR.
|
||||||
|
|
||||||
|
Depending on the changes, maintainers might ask you to make changes to the PR to fix problems or to improve the code.
|
||||||
|
**Do not delete your fork** while your pull request remains open, otherwise you won't be able to make any requested changes and the PR will end up being declined.
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
The following are required as a minimum for pull requests. PRs that don't meet these requirements will be declined unless updated to meet them.
|
||||||
|
|
||||||
|
#### Licensing
|
||||||
|
PocketMine-MP is licensed under [LGPLv3 license](LICENSE).
|
||||||
|
By proposing a pull request, you agree to your code being distributed within PocketMine-MP under the same license.
|
||||||
|
If you take code from other projects, that code MUST be licensed under an LGPL-compatible license.
|
||||||
|
|
||||||
|
#### PRs should be about exactly ONE thing
|
||||||
|
If you want to make multiple changes, those changes should each be contributed as separate pull requests. **DO NOT** mix unrelated changes.
|
||||||
|
|
||||||
|
#### PRs must not include unnecessary/unrelated changes
|
||||||
|
Do not include changes which aren't strictly necessary. This makes it harder to review a PR, because the code diff becomes larger and harder to review.
|
||||||
|
This means:
|
||||||
|
- don't reformat or rearrange existing code
|
||||||
|
- don't change things that aren't related to the PR's objective
|
||||||
|
- don't rewrite existing code just to make it "look nicer"
|
||||||
|
- don't change PhpDocs to native types in code you didn't write
|
||||||
|
|
||||||
|
#### Tests must be provided
|
||||||
|
Where possible, PHPUnit tests should be written for new or changed code.
|
||||||
|
If that's not possible (e.g. for in-game functionality), the code must be tested manually and details of the tests done must be provided.
|
||||||
|
**Simply saying "Tested" is not acceptable** and will lead to your PR being declined.
|
||||||
|
|
||||||
|
#### Comments and documentation must be written in American English
|
||||||
|
English is the shared languages of all current maintainers.
|
||||||
|
|
||||||
|
#### Code must be in the PocketMine-MP style
|
||||||
|
It's your responsibility to ensure your code matches the formatting and styling of the rest of the code.
|
||||||
|
If you use PhpStorm, a `Project` code style is provided, which you can use to automatically format new code.
|
||||||
|
You can also use [`php-cs-fixer`](https://github.com/FriendsOfPHP/PHP-CS-Fixer) to format your code.
|
||||||
|
|
||||||
|
### Recommendations
|
||||||
|
|
||||||
|
- **Do not edit code directly on github.com.** We recommend learning how to use [`git`](https://git-scm.com). `git` allows you to "clone" a repository onto your computer, so that you can make changes using an IDE.
|
||||||
|
- **Use an IDE, not a text editor.** We recommend PhpStorm or VSCode.
|
||||||
|
- **Create a new branch on your fork for each pull request.** This allows you to use the same fork to make multiple pull requests at the same time.
|
||||||
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||||
- **Do not include multiple unrelated changes in one commit.** An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set. See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits. See the [documentation on `git add`](https://git-scm.com/docs/git-add) for information on how to isolate local changes for committing.
|
- **Do not include multiple unrelated changes in one commit.** An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set. See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits. See the [documentation on `git add`](https://git-scm.com/docs/git-add) for information on how to isolate local changes for committing.
|
||||||
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
|
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
|
||||||
- **It is inadvisable to create large pull requests with lots of changes** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
|
- **Do not make large pull requests without an RFC.** Large changes should be discussed beforehand using the [RFC / Change Proposal](#rfcs--change-proposals) process. Large changes are much harder to review and are more likely to be declined if maintainers don't have a good idea what you're trying to do in advance.
|
||||||
- **You may be asked to rebase your pull request** if the branch becomes outdated and/or if possibly conflicting changes are made to the target branch. To see how to do this, read [this page](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request).
|
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit.
|
||||||
- **Details should be provided of tests done.** Simply saying "Tested" or equivalent is not acceptable.
|
|
||||||
|
|
||||||
### Code contributions
|
|
||||||
- **Avoid committing changes directly on GitHub. This includes use of the web editor, and also uploading files.** The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
|
|
||||||
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
|
|
||||||
- **Make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
|
|
||||||
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
|
|
||||||
- **The code must be clear** and written in English, comments included.
|
|
||||||
|
|
||||||
|
|
||||||
**Thanks for contributing to PocketMine-MP!**
|
**Thanks for contributing to PocketMine-MP!**
|
||||||
|
|
||||||
|
## RFCs / Change Proposals
|
||||||
|
Change Proposals are issues or discussions which describe a new feature proposal or behavioural change.
|
||||||
|
They are used to get feedback from maintainers and the community about an idea for a change, to decide whether or not it's a good idea.
|
||||||
|
|
||||||
|
### Submitting an RFC
|
||||||
|
RFCs should be submitted using Issues or Discussions.
|
||||||
|
RFCs _can_ be submitted as pull requests if you've already written the code, but this is not recommended, since it's not guaranteed that an RFC will pass, in which case your effort would be wasted.
|
||||||
|
|
||||||
### Code Syntax
|
RFCs should include the following:
|
||||||
|
- A summary of what you want to change
|
||||||
|
- Why you want to change it (e.g. what problems it solves)
|
||||||
|
- Alternative methods you've considered to solve the problem. This should include any possible ways that what you want can be done without the change.
|
||||||
|
|
||||||
It is mainly [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) with a few exceptions.
|
### Voting on RFCs
|
||||||
|
Community members can vote on RFCs. This gives maintainers an idea of how popular the idea is.
|
||||||
|
Votes can be cast using :+1: and :-1: reactions.
|
||||||
|
|
||||||
- Opening braces MUST go on the same line, and MUST NOT have spaces before.
|
**Please don't downvote without providing a reason why!**
|
||||||
- `else if` MUST be written as `elseif`. _(It is in PSR-2, but using a SHOULD)_
|
|
||||||
- Control structure keywords or opening braces MUST NOT have one space before or after them.
|
|
||||||
- Code MUST use tabs for indenting.
|
|
||||||
- Long arrays MAY be split across multiple lines, where each subsequent line is indented once.
|
|
||||||
- Files MUST use only the `<?php` tag.
|
|
||||||
- Files MUST NOT have an ending `?>` tag.
|
|
||||||
- Code MUST use namespaces.
|
|
||||||
- Strings SHOULD use the double quote `"` except when the single quote is required.
|
|
||||||
- All code SHOULD have parameter and type declarations where possible.
|
|
||||||
- Strict types SHOULD be enabled on new files where it is sensible to do so.
|
|
||||||
- All constant declarations SHOULD be preceded by a visibility modifier.
|
|
||||||
|
|
||||||
```php
|
### Implementing RFCs
|
||||||
<?php
|
Anyone can write the code to implement an RFC, and submit a pull request for it. It doesn't have to be the RFC author.
|
||||||
|
|
||||||
declare(strict_types=1);
|
Implementations should be submitted as pull requests. The pull request description must include a link to the RFC.
|
||||||
|
|
||||||
namespace pocketmine\example;
|
|
||||||
|
|
||||||
class ExampleClass{
|
|
||||||
|
|
||||||
public const EXAMPLE_CLASS_CONSTANT = 1;
|
|
||||||
|
|
||||||
public $examplePublicVariable = "defaultValue";
|
|
||||||
private $examplePrivateVariable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance of ExampleClass
|
|
||||||
*
|
|
||||||
* @param string $firstArgument the first argument
|
|
||||||
* @param string|null $secondArgument default null
|
|
||||||
*/
|
|
||||||
public function __construct(string $firstArgument, ?string &$secondArgument = null){
|
|
||||||
if($firstArgument === "exampleValue"){ //Remember to use === instead of == when possible
|
|
||||||
//do things
|
|
||||||
}elseif($firstArgument === "otherValue"){
|
|
||||||
$secondArgument = function(){
|
|
||||||
$this->examplePrivateVariable = [
|
|
||||||
0 => "value1",
|
|
||||||
1 => "value2",
|
|
||||||
2 => "value3",
|
|
||||||
3 => "value4",
|
|
||||||
4 => "value5",
|
|
||||||
5 => "value6",
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function doStuff(string $stuff) : string{
|
|
||||||
return $stuff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- TODO: RFC and voting on the forums instead -->
|
|
||||||
### RFC and Voting
|
|
||||||
* These are big Pull Requests or contributions that change important behavior.
|
|
||||||
* RFCs will be tagged with the *PR: RFC* label
|
|
||||||
* A vote will be held once the RFC is ready. All users can vote commenting on the Pull Request
|
|
||||||
* Comments MUST use "Yes" or "No" on the FIRST sentence to signify the vote, except when they don't want it to be counted.
|
|
||||||
* If your comment is a voting comment, specify the reason of your vote or it won't be counted.
|
|
||||||
* After voting has been closed, no further votes will be counted.
|
|
||||||
* An RFC will be rejected if less than 50% + 1 (simple majority) has voted Yes.
|
|
||||||
* If the RFC is approved, Team Members have the final word on its implementation or rejection.
|
|
||||||
* RFCs with complex voting options will specify the vote percentage or other details.
|
|
||||||
|
13
README.md
13
README.md
@ -3,7 +3,12 @@
|
|||||||
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[](https://travis-ci.org/pmmp/PocketMine-MP)
|
<p align="center">
|
||||||
|
<img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" />
|
||||||
|
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img src="https://img.shields.io/github/v/tag/pmmp/PocketMine-MP?label=release&logo=github" alt="GitHub tag (latest semver)" /></a>
|
||||||
|
<a href="https://hub.docker.com/r/pmmp/pocketmine-mp"><img src="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image" alt="Docker image version (latest semver)" /></a>
|
||||||
|
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
- [Documentation](http://pmmp.readthedocs.org/)
|
- [Documentation](http://pmmp.readthedocs.org/)
|
||||||
@ -13,12 +18,14 @@
|
|||||||
|
|
||||||
## Discussion/Help
|
## Discussion/Help
|
||||||
- [Forums](https://forums.pmmp.io/)
|
- [Forums](https://forums.pmmp.io/)
|
||||||
- [Community Discord](https://discord.gg/bmSAZBG)
|
- [Discord](https://discord.gg/bmSAZBG)
|
||||||
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
|
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
|
||||||
|
|
||||||
## For developers
|
## For developers
|
||||||
|
* [Building and running from source](BUILDING.md)
|
||||||
|
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
||||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
||||||
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
|
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
|
||||||
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||||
* [Contributing Guidelines](CONTRIBUTING.md)
|
* [Contributing Guidelines](CONTRIBUTING.md)
|
||||||
|
|
||||||
|
25
SECURITY.md
Normal file
25
SECURITY.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
**DO NOT report vulnerabilities on the GitHub issue tracker.**
|
||||||
|
GitHub is public and anyone can see the issues you post on the issue tracker, including people who would exploit vulnerabilities for their own gain.
|
||||||
|
|
||||||
|
**WARNING: You may put live servers at risk by reporting a vulnerability on the GitHub issue tracker.**
|
||||||
|
|
||||||
|
**Contact us** by sending an email to [**team@pmmp.io**](mailto:team@pmmp.io?subject=Security%20Vulnerability%20in%20PocketMine-MP). Include the following information:
|
||||||
|
|
||||||
|
- Version of PocketMine-MP
|
||||||
|
- Detailed description of the vulnerability (e.g. how to exploit it, what the effects are)
|
||||||
|
|
||||||
|
Please note that we can't guarantee a reply to every email.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
### Do you offer a bug bounty?
|
||||||
|
No.
|
||||||
|
|
||||||
|
### How soon can I expect a fix for a vulnerability I've reported?
|
||||||
|
This depends on the nature of the problem. We can't provide any general ETA (nor would it be wise to provide one).
|
||||||
|
In general, it depends on when developers have time to look into the problem, how complex the problem is to fix, and how many users it impacts.
|
||||||
|
|
||||||
|
When a fix for a severe vulnerability is pushed, a patch release for the target version will usually be released within 24 hours so that users can update.
|
43
build/generate-build-info-json.php
Normal file
43
build/generate-build-info-json.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?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);
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
if(count($argv) !== 4){
|
||||||
|
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)>");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
|
||||||
|
"base_version" => \pocketmine\BASE_VERSION,
|
||||||
|
"build" => \pocketmine\BUILD_NUMBER,
|
||||||
|
"is_dev" => \pocketmine\IS_DEVELOPMENT_BUILD,
|
||||||
|
"channel" => \pocketmine\BUILD_CHANNEL,
|
||||||
|
"git_commit" => $argv[1],
|
||||||
|
"mcpe_version" => \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK,
|
||||||
|
"date" => time(), //TODO: maybe we should embed this in VersionInfo?
|
||||||
|
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
|
||||||
|
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
|
||||||
|
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
|
@ -21,36 +21,26 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\build_script;
|
namespace pocketmine\build\make_release;
|
||||||
|
|
||||||
use pocketmine\utils\VersionString;
|
use pocketmine\utils\VersionString;
|
||||||
|
use function count;
|
||||||
use function dirname;
|
use function dirname;
|
||||||
use function fgets;
|
use function fgets;
|
||||||
use function file_get_contents;
|
use function file_get_contents;
|
||||||
use function file_put_contents;
|
use function file_put_contents;
|
||||||
use function preg_quote;
|
use function fwrite;
|
||||||
use function preg_replace;
|
use function preg_replace;
|
||||||
use function sleep;
|
use function sleep;
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
use function system;
|
use function system;
|
||||||
use const pocketmine\BASE_VERSION;
|
use const pocketmine\BASE_VERSION;
|
||||||
|
use const STDERR;
|
||||||
use const STDIN;
|
use const STDIN;
|
||||||
|
|
||||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
if(isset($argv[1])){
|
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
|
||||||
$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 = file_get_contents($versionInfoPath);
|
||||||
$versionInfo = preg_replace(
|
$versionInfo = preg_replace(
|
||||||
$pattern = '/^const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
$pattern = '/^const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
||||||
@ -59,22 +49,57 @@ function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev
|
|||||||
);
|
);
|
||||||
$versionInfo = preg_replace(
|
$versionInfo = preg_replace(
|
||||||
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
|
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
|
||||||
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';',
|
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false') . ';',
|
||||||
|
$versionInfo
|
||||||
|
);
|
||||||
|
$versionInfo = preg_replace(
|
||||||
|
'/^const BUILD_CHANNEL = ".*";$/m',
|
||||||
|
'const BUILD_CHANNEL = "' . $channel . '";',
|
||||||
$versionInfo
|
$versionInfo
|
||||||
);
|
);
|
||||||
file_put_contents($versionInfoPath, $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);
|
* @param string[] $argv
|
||||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
* @phpstan-param list<string> $argv
|
||||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
*/
|
||||||
system('git tag ' . $currentVer->getBaseVersion());
|
function main(array $argv) : void{
|
||||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
|
if(count($argv) < 2){
|
||||||
system('git add "' . $versionInfoPath . '"');
|
fwrite(STDERR, "Arguments: <channel> [release version]\n");
|
||||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
exit(1);
|
||||||
echo "pushing changes in 5 seconds\n";
|
}
|
||||||
sleep(5);
|
if(isset($argv[2])){
|
||||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
$currentVer = new VersionString($argv[2]);
|
||||||
|
}else{
|
||||||
|
$currentVer = new VersionString(BASE_VERSION);
|
||||||
|
}
|
||||||
|
$nextVer = new VersionString(sprintf(
|
||||||
|
"%u.%u.%u",
|
||||||
|
$currentVer->getMajor(),
|
||||||
|
$currentVer->getMinor(),
|
||||||
|
$currentVer->getPatch() + 1
|
||||||
|
));
|
||||||
|
|
||||||
|
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
||||||
|
echo "please add appropriate notes to the changelog and press enter...";
|
||||||
|
fgets(STDIN);
|
||||||
|
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
||||||
|
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
|
||||||
|
if($result === 0){
|
||||||
|
echo "error: no changelog changes detected; aborting\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||||
|
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $argv[1]);
|
||||||
|
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 5 seconds\n";
|
||||||
|
sleep(5);
|
||||||
|
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
main($argv);
|
||||||
|
Submodule build/php updated: 8308571448...365356dec1
Submodule build/preprocessor updated: b01f50c50e...1b9304de61
176
build/server-phar.php
Normal file
176
build/server-phar.php
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<?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\server_phar;
|
||||||
|
|
||||||
|
use pocketmine\utils\Git;
|
||||||
|
use function array_map;
|
||||||
|
use function count;
|
||||||
|
use function dirname;
|
||||||
|
use function file_exists;
|
||||||
|
use function getcwd;
|
||||||
|
use function getopt;
|
||||||
|
use function implode;
|
||||||
|
use function ini_get;
|
||||||
|
use function microtime;
|
||||||
|
use function preg_quote;
|
||||||
|
use function realpath;
|
||||||
|
use function round;
|
||||||
|
use function rtrim;
|
||||||
|
use function sprintf;
|
||||||
|
use function str_replace;
|
||||||
|
use function unlink;
|
||||||
|
use const PHP_EOL;
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $strings
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
function preg_quote_array(array $strings, string $delim) : array{
|
||||||
|
return array_map(function(string $str) use ($delim) : string{ return preg_quote($str, $delim); }, $strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $includedPaths
|
||||||
|
* @param mixed[] $metadata
|
||||||
|
* @phpstan-param array<string, mixed> $metadata
|
||||||
|
*
|
||||||
|
* @return \Generator|string[]
|
||||||
|
*/
|
||||||
|
function buildPhar(string $pharPath, string $basePath, array $includedPaths, array $metadata, string $stub, int $signatureAlgo = \Phar::SHA1, ?int $compression = null){
|
||||||
|
$basePath = rtrim(str_replace("/", DIRECTORY_SEPARATOR, $basePath), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||||
|
$includedPaths = array_map(function(string $path) : string{
|
||||||
|
return rtrim(str_replace("/", DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||||
|
}, $includedPaths);
|
||||||
|
yield "Creating output file $pharPath";
|
||||||
|
if(file_exists($pharPath)){
|
||||||
|
yield "Phar file already exists, overwriting...";
|
||||||
|
try{
|
||||||
|
\Phar::unlinkArchive($pharPath);
|
||||||
|
}catch(\PharException $e){
|
||||||
|
//unlinkArchive() doesn't like dodgy phars
|
||||||
|
unlink($pharPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield "Adding files...";
|
||||||
|
|
||||||
|
$start = microtime(true);
|
||||||
|
$phar = new \Phar($pharPath);
|
||||||
|
$phar->setMetadata($metadata);
|
||||||
|
$phar->setStub($stub);
|
||||||
|
$phar->setSignatureAlgorithm($signatureAlgo);
|
||||||
|
$phar->startBuffering();
|
||||||
|
|
||||||
|
//If paths contain any of these, they will be excluded
|
||||||
|
$excludedSubstrings = preg_quote_array([
|
||||||
|
realpath($pharPath), //don't add the phar to itself
|
||||||
|
], '/');
|
||||||
|
|
||||||
|
$folderPatterns = preg_quote_array([
|
||||||
|
DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR,
|
||||||
|
DIRECTORY_SEPARATOR . '.' //"Hidden" files, git dirs etc
|
||||||
|
], '/');
|
||||||
|
|
||||||
|
//Only exclude these within the basedir, otherwise the project won't get built if it itself is in a directory that matches these patterns
|
||||||
|
$basePattern = preg_quote(rtrim($basePath, DIRECTORY_SEPARATOR), '/');
|
||||||
|
foreach($folderPatterns as $p){
|
||||||
|
$excludedSubstrings[] = $basePattern . '.*' . $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
$regex = sprintf('/^(?!.*(%s))^%s(%s).*/i',
|
||||||
|
implode('|', $excludedSubstrings), //String may not contain any of these substrings
|
||||||
|
preg_quote($basePath, '/'), //String must start with this path...
|
||||||
|
implode('|', preg_quote_array($includedPaths, '/')) //... and must be followed by one of these relative paths, if any were specified. If none, this will produce a null capturing group which will allow anything.
|
||||||
|
);
|
||||||
|
|
||||||
|
$directory = new \RecursiveDirectoryIterator($basePath, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::CURRENT_AS_PATHNAME); //can't use fileinfo because of symlinks
|
||||||
|
$iterator = new \RecursiveIteratorIterator($directory);
|
||||||
|
$regexIterator = new \RegexIterator($iterator, $regex);
|
||||||
|
|
||||||
|
$count = count($phar->buildFromIterator($regexIterator, $basePath));
|
||||||
|
yield "Added $count files";
|
||||||
|
|
||||||
|
if($compression !== null){
|
||||||
|
yield "Compressing files...";
|
||||||
|
$phar->compressFiles($compression);
|
||||||
|
yield "Finished compression";
|
||||||
|
}
|
||||||
|
$phar->stopBuffering();
|
||||||
|
|
||||||
|
yield "Done in " . round(microtime(true) - $start, 3) . "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() : void{
|
||||||
|
if(ini_get("phar.readonly") == 1){
|
||||||
|
echo "Set phar.readonly to 0 with -dphar.readonly=0" . PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(file_exists(dirname(__DIR__) . '/vendor/phpunit')){
|
||||||
|
echo "Remove Composer dev dependencies before building (composer install --no-dev)" . PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts = getopt("", ["out:", "git:"]);
|
||||||
|
if(isset($opts["git"])){
|
||||||
|
$gitHash = $opts["git"];
|
||||||
|
}else{
|
||||||
|
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
||||||
|
echo "Git hash detected as $gitHash" . PHP_EOL;
|
||||||
|
}
|
||||||
|
foreach(buildPhar(
|
||||||
|
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||||
|
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||||
|
[
|
||||||
|
'src',
|
||||||
|
'vendor'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'git' => $gitHash
|
||||||
|
],
|
||||||
|
<<<'STUB'
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$tmpDir = sys_get_temp_dir();
|
||||||
|
if(!is_readable($tmpDir) or !is_writable($tmpDir)){
|
||||||
|
echo "ERROR: tmpdir $tmpDir is not accessible." . PHP_EOL;
|
||||||
|
echo "Check that the directory exists, and that the current user has read/write permissions for it." . PHP_EOL;
|
||||||
|
echo "Alternatively, set 'sys_temp_dir' to a different directory in your php.ini file." . PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require("phar://" . __FILE__ . "/src/pocketmine/PocketMine.php");
|
||||||
|
__HALT_COMPILER();
|
||||||
|
STUB
|
||||||
|
,
|
||||||
|
\Phar::SHA1,
|
||||||
|
\Phar::GZ
|
||||||
|
) as $line){
|
||||||
|
echo $line . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
@ -33,3 +33,65 @@ Plugin developers should **only** update their required API to this version if y
|
|||||||
- `SkinImage` now throws `InvalidArgumentException` if it receives an unexpected amount of bytes for the given image heigh/width.
|
- `SkinImage` now throws `InvalidArgumentException` if it receives an unexpected amount of bytes for the given image heigh/width.
|
||||||
- Fixed broken code in `PlayerAuthInputPacket::create()`.
|
- Fixed broken code in `PlayerAuthInputPacket::create()`.
|
||||||
- Removed some dead constants from `NetworkInventoryAction`.
|
- Removed some dead constants from `NetworkInventoryAction`.
|
||||||
|
|
||||||
|
# 3.11.3
|
||||||
|
- Fixed some PHPStan false-positives in release builds.
|
||||||
|
- Git hash is now correctly detected for source builds when the working directory is not the repository root.
|
||||||
|
- Added a specialized build script `build/server-phar.php` for creating server phars.
|
||||||
|
- Fixed timings crashing the server.
|
||||||
|
- Timings chains now work correctly.
|
||||||
|
- Fixed some minor timing errors in chained timings.
|
||||||
|
- Forcing resource packs no longer causes removal of client-sided resource packs. If this behaviour is desired, use a vanilla resource pack at the bottom of your resource stack (as was necessary for non-forced packs).
|
||||||
|
- Added documentation to the API to clarify that effect durations are in ticks.
|
||||||
|
|
||||||
|
# 3.11.4
|
||||||
|
- Fixed performance issue in leaf decay.
|
||||||
|
- Fixed entity position desync when entities stop moving, but still have velocity on the client.
|
||||||
|
- Fixed a crash when encountering truncated `level.dat` files in LevelDB worlds.
|
||||||
|
- Core code is now analyzed using PHPStan level 6.
|
||||||
|
- The core constants `pocketmine\PATH` and `pocketmine\RESOURCE_PATH` are now unconditionally available when including the Composer autoloader.
|
||||||
|
- Populate type information in lots of places where it was previously missing; this will improve the quality of static analysis for plugins.
|
||||||
|
- `MainLogger::logException()` now logs previous exceptions recursively.
|
||||||
|
- `MainLogger::logException()` now always logs exceptions as `critical`.
|
||||||
|
|
||||||
|
# 3.11.5
|
||||||
|
- PHPStan and PHPUnit are now managed as Composer dev dependencies.
|
||||||
|
- Core code is now analyzed using PHPStan level 6 (full, including iterable types checking).
|
||||||
|
- Improved type information available to PHPStan in many areas.
|
||||||
|
- Mass-removal of useless PHPDoc.
|
||||||
|
- Fixed incorrect documentation of `Internet::getURL()`, `Internet::postURL()` and `Internet::simpleCurl()`.
|
||||||
|
- Fixed crash on use of case-mismatched recursive command aliases.
|
||||||
|
- Basic build instructions are now provided in `BUILDING.md`.
|
||||||
|
- `build/server-phar.php` now uses GZIP compression on created phars, providing a 75% size reduction.
|
||||||
|
- `ClientboundMapItemDataPacket` now uses `MapDecoration` objects for decorations instead of associative arrays.
|
||||||
|
- Updated Composer dependencies to get bug fixes in `pocketmine/nbt` and other libraries.
|
||||||
|
- Packages `pocketmine/classloader` and `pocketmine/log` are now required; these provide classes previously part of `pocketmine/spl`. This change has no effect on API compatibility.
|
||||||
|
|
||||||
|
# 3.11.6
|
||||||
|
- Core code, tests and build scripts are now analyzed using `phpstan-strict-rules` and `phpstan-phpunit` rules.
|
||||||
|
- Added more PHPStan-specific type annotations to improve static analysis.
|
||||||
|
- Fixed more incorrect PHPDoc types.
|
||||||
|
- Added a workaround for player movement not working since 1.14.30.
|
||||||
|
- Fixed lava and water buckets being edible since 1.13.
|
||||||
|
- `AutoUpdater` is now created before any plugins are loaded.
|
||||||
|
- Fixed trees not generating below y=2 in custom generators.
|
||||||
|
- Fixed crash when opening a chest improperly unpaired from its pair (destroyed, setBlock(), unloaded, etc.).
|
||||||
|
- `ThreadManager` is now lazily initialized.
|
||||||
|
- Removed raw NBT storage from `Item` internals. The following methods are now deprecated:
|
||||||
|
- `Item::setCompoundTag()`
|
||||||
|
|
||||||
|
# 3.11.7
|
||||||
|
- Build system: Fixed crash reports of Jenkins builds being rejected by the crash archive as invalid.
|
||||||
|
- Introduced a new dependency on `pocketmine/log-pthreads`, which contains classes separated from `pocketmine/log`.
|
||||||
|
- Fixed minimum composer stability preventing any newer version of `pocketmine/pocketmine-mp` being installed than 3.3.4 by replacing `daverandom/callback-validator` with [`pocketmine/callback-validator`](https://github.com/pmmp/CallbackValidator).
|
||||||
|
- Fixed every player seeing eating particles when any player eats.
|
||||||
|
- Fixed setting held item not working during `BlockBreakEvent`, `PlayerInteractEvent` and `EntityDamageEvent`.
|
||||||
|
- Fixed some incorrect documented types in `PlayerQuitEvent` reported by PHPStan.
|
||||||
|
- Fixed documentation of `Item->pop()` return value.
|
||||||
|
- Fixed server crash on encountering corrupted compressed data stored in region files.
|
||||||
|
- Protocol: Split screen header is now properly accounted for during decoding. Note that split screen is still not supported natively, but their packets can be decoded properly now.
|
||||||
|
- Protocol: Fixed wrong order of fields in `UpdateTradePacket`.
|
||||||
|
- Protocol: Fixed loss of `fullSkinId` when decoding network skins.
|
||||||
|
- Fixed RCON not being able to bind to port after a fast server restart.
|
||||||
|
|
||||||
|
|
||||||
|
58
changelogs/3.12.md
Normal file
58
changelogs/3.12.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.14.60**
|
||||||
|
|
||||||
|
### 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.12.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.14.60
|
||||||
|
- Removed compatibility with 1.14.0-1.14.30
|
||||||
|
|
||||||
|
# 3.12.1
|
||||||
|
- Fixed parsing of single-line doc comments for event handlers, e.g. `/** @ignoreCancelled */` should now work correctly.
|
||||||
|
- The server will no longer crash on failure to load `level.dat` contents, but will gracefully shutdown instead without producing a crashdump.
|
||||||
|
- Fixed some bugs in login verification that could cause undefined behaviour.
|
||||||
|
- Fixed item-use behaviour when sneaking - sneaking and clicking a block with an empty hand, and sneaking and using an item, both now follow vanilla behaviour.
|
||||||
|
- `start.sh` will now work on platforms where `/bin/bash` is not available, as long as `/usr/bin/env` knows where bash is.
|
||||||
|
|
||||||
|
# 3.12.2
|
||||||
|
- Fixed permission default timings not being reported in timings reports (they were never stopped, only started).
|
||||||
|
- Resource packs with a directory tree like `pack.zip/MyPack/manifest.json` are now supported. Note that the manifest closest to the root will be used.
|
||||||
|
- Fixed `SkinImage` height and width being inverted at the protocol layer.
|
||||||
|
- Fixed blocks being able to be placed inside the spawn protection radius by clicking the side of a block outside the radius.
|
||||||
|
- Fixed server crash when `network.compression-level` is overridden by a CLI parameter.
|
||||||
|
- Fixed moving entities spawning themselves to players registered on chunks when the players haven't received the chunk yet.
|
||||||
|
- Cocoa pods now drop cocoa beans when broken instead of the block itself.
|
||||||
|
|
||||||
|
# 3.12.3
|
||||||
|
- Core code is now analyzed using PHPStan level 8 (using baselines). While not all the code is level 8 compliant, this does mean that new code will be held to a higher standard, ensuring quality going forwards.
|
||||||
|
- Players no longer burn when melee-attacked by other players. (vanilla parity)
|
||||||
|
- Arrows shot by burning players are no longer on fire. (vanilla parity)
|
||||||
|
- Fixed a crash that could occur with plugins on Unix filesystems that had backslashes in their names.
|
||||||
|
- Cleaned up a whole bunch of unknowns in the protocol layer. Many new constants have been added.
|
||||||
|
- Fixed player walking sounds.
|
||||||
|
- Default generation queue size has been raised to 32 (previously 8). The previous default was selected in a time when PHP was much less performant than it is today, and in today's world it just needlessly slows things down.
|
||||||
|
- Double plants are now burned away by fire.
|
||||||
|
- Snow layers can now be stacked. (vanilla parity)
|
||||||
|
- Resource pack sending chunk size has been reduced to 128 KB (previously 1 MB). This change was made after analyzing the effects that larger pack chunk sizes have on RakNet. Given the technical evidence, a smaller size, while slightly less bandwidth-efficient, should be more manageable for RakNet due to lower split reassembly overhead and reduced memory pressure.
|
||||||
|
- Fixed "switching" (an exploit often complained about by PvP players). Now, the previous damage is subtracted from current damage when an entity is attacked while on cooldown. This means that attacking with a wooden sword and then diamond sword while attack cooldown is active will only deal as much damage as the diamond sword would have, instead of the combined total. This can be controlled using the `EntityDamageEvent::MODIFIER_PREVIOUS_DAMAGE_COOLDOWN` modifier. (vanilla parity)
|
||||||
|
- Fixed projectiles knocking mobs back in unexpected directions on collision.
|
||||||
|
- Fixed inventories not being synchronized on failed inventory transactions.
|
||||||
|
- Vector3s decoded from packets are no longer rounded directly. Instead, the player movement handler takes responsibility for rounding the coordinates to prevent anti cheat doing something it's not supposed to.
|
||||||
|
- `mobflame` particle can now be spawned using the `/particle` command.
|
||||||
|
- Fixed several internal errors that could occur while modifying writable books.
|
||||||
|
- Fixed swapping writable book pages not working in some cases.
|
||||||
|
- `WritableBook->getPageText()` no longer throws an exception when the page doesn't exist, but returns null (as it was originally intended to).
|
||||||
|
|
||||||
|
# 3.12.4
|
||||||
|
- Fixed absorption hearts not being consumed.
|
||||||
|
|
||||||
|
# 3.12.5
|
||||||
|
- Fixed broken attack cooldowns.
|
||||||
|
|
||||||
|
# 3.12.6
|
||||||
|
- Fixed entities not getting movement updates after teleports.
|
||||||
|
- Fixed slow flight in spectator mode when starting from the ground and after teleportation.
|
||||||
|
- Errors communicating with the crash archive on automatic crash submission are now logged.
|
131
changelogs/3.13.md
Normal file
131
changelogs/3.13.md
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.14.60**
|
||||||
|
|
||||||
|
This is a feature release, containing various minor API additions, deprecations and a few minor features.
|
||||||
|
|
||||||
|
### 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.13.0
|
||||||
|
## Core
|
||||||
|
- PHP 7.3.0 or newer is now required.
|
||||||
|
- Player movement processing has been revamped. It's now more tolerant of network lag and doesn't have as many problems with falling.
|
||||||
|
|
||||||
|
## User Interface
|
||||||
|
- `/time` now supports additional aliases `noon`, `sunset`, `midnight` and `sunrise`.
|
||||||
|
- Removed warnings when a plugin registers a handler for a deprecated event. Since this warning is developer-focused, and too specific to be useful, it just caused annoyance and confusion to users who didn't know what it meant.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### General
|
||||||
|
- It's now possible to require a specific operating system using the `os` directive in `plugin.yml`. More information about this directive can be found in the [developer documentation](https://github.com/pmmp/DeveloperDocs).
|
||||||
|
|
||||||
|
### Player
|
||||||
|
- `Player->resetItemCooldown()` now accepts a second parameter, allowing plugins to provide a custom duration.
|
||||||
|
- The following methods have been deprecated and have recommended replacements:
|
||||||
|
- `Player->addTitle()` -> `Player->sendTitle()`
|
||||||
|
- `Player->addSubTitle()` -> `Player->sendSubTitle()`
|
||||||
|
- `Player->addActionBarMessage()` -> `Player->sendActionBarMessage()`
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- The following methods have been deprecated:
|
||||||
|
- `EntityDespawnEvent->getType()`
|
||||||
|
- `EntityDespawnEvent->getPosition()`
|
||||||
|
- `EntityDespawnEvent->isCreature()`
|
||||||
|
- `EntityDespawnEvent->isHuman()`
|
||||||
|
- `EntityDespawnEvent->isProjectile()`
|
||||||
|
- `EntityDespawnEvent->isVehicle()`
|
||||||
|
- `EntityDespawnEvent->isItem()`
|
||||||
|
- `EntitySpawnEvent->getType()`
|
||||||
|
- `EntitySpawnEvent->getPosition()`
|
||||||
|
- `EntitySpawnEvent->isCreature()`
|
||||||
|
- `EntitySpawnEvent->isHuman()`
|
||||||
|
- `EntitySpawnEvent->isProjectile()`
|
||||||
|
- `EntitySpawnEvent->isVehicle()`
|
||||||
|
- `EntitySpawnEvent->isItem()`
|
||||||
|
- Added the following API methods:
|
||||||
|
- `EntityDeathEvent->getXpDropAmount()`
|
||||||
|
- `EntityDeathEvent->setXpDropAmount()`
|
||||||
|
- `PlayerDeathEvent::__construct()` now accepts a fourth (optional) parameter `int $xp`.
|
||||||
|
- `EntityDeathEvent::__construct()` now accepts a third (optional) parameter `int $xp`.
|
||||||
|
|
||||||
|
### Inventory
|
||||||
|
- The following classes have been deprecated:
|
||||||
|
- `Recipe`
|
||||||
|
- The following methods have been deprecated:
|
||||||
|
- `CraftingManager->registerRecipe()`
|
||||||
|
- `Recipe->registerToCraftingManager()` (and all its implementations)
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- New `Enchantment` type ID constants have been added.
|
||||||
|
- `ItemFactory::fromStringSingle()` has been added. This works exactly the same as `ItemFactory::fromString()`, but it has a return type of `Item` instead of `Item|Item[]` (more static analysis friendly).
|
||||||
|
|
||||||
|
### Level
|
||||||
|
- Added the following API methods:
|
||||||
|
- `Position->getLevelNonNull()`: this is the same as `Position->getLevel()`, but throws an `AssumptionFailedError` if the level is null or invalid (more static analysis friendly).
|
||||||
|
- `Level->getTimeOfDay()`
|
||||||
|
- The following constants have been changed:
|
||||||
|
- `Level::TIME_DAY` now has a value of `1000`
|
||||||
|
- `Level::TIME_NIGHT` now has a value of `13000`
|
||||||
|
- Added the following constants:
|
||||||
|
- `Level::TIME_MIDNIGHT`
|
||||||
|
- `Level::TIME_NOON`
|
||||||
|
- The following types of particles now accept optional `Color` parameters in the constructor:
|
||||||
|
- `EnchantParticle`
|
||||||
|
- `InstantEnchantParticle`
|
||||||
|
|
||||||
|
### Network
|
||||||
|
- Added the following API methods:
|
||||||
|
- `RakLibInterface->setPacketLimit()`
|
||||||
|
|
||||||
|
### Scheduler
|
||||||
|
AsyncTask thread-local storage has been improved, making it simpler and easier to use.
|
||||||
|
- `AsyncTask->fetchLocal()` no longer deletes stored thread-local data. Instead, the storage behaves more like properties, and gets deleted when the AsyncTask object goes out of scope.
|
||||||
|
- `AsyncTask->peekLocal()` has been `@deprecated` (use `fetchLocal()` instead).
|
||||||
|
- Notices are no longer emitted if an async task doesn't fetch its locally stored data.
|
||||||
|
- The following methods have been deprecated:
|
||||||
|
- `AsyncTask->getFromThreadStore()` (use its worker's corresponding method)
|
||||||
|
- `AsyncTask->saveToThreadStore()` (use its worker's corresponding method)
|
||||||
|
- `AsyncTask->removeFromThreadStore()` (use its worker's corresponding method)
|
||||||
|
|
||||||
|
### Utils
|
||||||
|
- The following functions have been deprecated and have recommended replacements:
|
||||||
|
- `Utils::getMemoryUsage()` -> split into `Process::getMemoryUsage()` and `Process::getAdvancedMemoryUsage()` (not 1:1 replacement!!)
|
||||||
|
- `Utils::getRealMemoryUsage()` -> `Process::getRealMemoryUsage()`
|
||||||
|
- `Utils::getThreadCount()` -> `Process::getThreadCount()`
|
||||||
|
- `Utils::kill()` -> `Process::kill()`
|
||||||
|
- `Utils::execute()` -> `Process::execute()`
|
||||||
|
- Added the following constants:
|
||||||
|
- `Utils::OS_WINDOWS`
|
||||||
|
- `Utils::OS_IOS`
|
||||||
|
- `Utils::OS_MACOS`
|
||||||
|
- `Utils::OS_ANDROID`
|
||||||
|
- `Utils::OS_LINUX`
|
||||||
|
- `Utils::OS_BSD`
|
||||||
|
- `Utils::OS_UNKNOWN`
|
||||||
|
- Added the following API methods:
|
||||||
|
- `Config->getPath()`
|
||||||
|
- `Utils::recursiveUnlink()`
|
||||||
|
- `Terminal::write()`
|
||||||
|
- `Terminal::writeLine()`
|
||||||
|
|
||||||
|
# 3.13.1
|
||||||
|
- Fixed issues with `server.lock` not being unlocked on some platforms. Now, the server explicitly releases it before exiting.
|
||||||
|
- `/timings` now sends a usage message when using an unknown subcommand. Previously, it would just give no output.
|
||||||
|
- `/whitelist` now sends a usage message when using an unknown subcommand. Previously, it would just give no output.
|
||||||
|
- The output from `/timings` is now broadcasted on the `pocketmine.broadcast.admin` broadcast channel for auditability, similarly to other operator commands.
|
||||||
|
- Fixed `ShapedRecipe` deprecation warning on PHP 7.4.
|
||||||
|
- Fixed some potential crashes with Bedrock worlds when chunk data is corrupted or missing.
|
||||||
|
- Fixed a bug in region handling that caused region loaders to overestimate the amount of space used in the file. This resulted in an up to 4 MB growth of the file size every time the region was reloaded after writing a chunk.
|
||||||
|
- Region handlers now try to reuse free space in region files before putting the chunk at the end of the file. Previously, space was only reused if the new version of the chunk was <= the size of the old. This fixes endless growth of region files.
|
||||||
|
- Regions now never directly overwrite old copies of chunks when saving; instead they try to find an alternative location (preferring unused space within the file first). This avoids chunk corruption on power failure (the old copy of the chunk won't be damaged, so a rollback might occur instead), and as happy side effect, causes oversized regions to gradually shrink towards their most packed state over time, saving disk space.
|
||||||
|
- Regions now have a hard size cap at 64 GB. This is because the header pointers will overflow beyond 64 GB (besides, a normal region shouldn't be this big anyway).
|
||||||
|
- Fixed a crash that could occur when reading a too-short region header.
|
||||||
|
- `VerifyLoginTask` now only copies JWTs to verify instead of the entire login packet. This reduces the amount of data copied between threads, improving performance.
|
||||||
|
- Added a fast-fail check to `VerifyLoginTask` by checking the JWT header's `x5u` against the expected public key.
|
||||||
|
- `Skin->validate()` now throws `InvalidSkinException` instead of `\InvalidArgumentException`.
|
||||||
|
- A debug message is now logged when a player is kicked for having an invalid skin, giving a brief line of detail why.
|
||||||
|
- Fixed players not being kicked for having an invalid `resourcePatch`.
|
||||||
|
- Fixed block meta value of cake being preserved when using pick-block.
|
||||||
|
- Fixed explosions not fully destroying multi-block objects like beds and doors.
|
40
changelogs/3.14.md
Normal file
40
changelogs/3.14.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.16.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.14.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.16.0.
|
||||||
|
- Removed compatibility with 1.14.60.
|
||||||
|
|
||||||
|
## Known issues (please don't open issues for these)
|
||||||
|
- Walls don't connect to each other
|
||||||
|
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||||
|
- New blocks, items & mobs aren't implemented
|
||||||
|
- Nether doesn't exist
|
||||||
|
|
||||||
|
# 3.14.1
|
||||||
|
- All skins are now trusted, bypassing the client-side trusted skin setting. Note that this means that NSFW skin filtering will **not** apply.
|
||||||
|
- Fixed projectile motion being altered by ladders.
|
||||||
|
- Fixed client-sided crashes when pressing E repeatedly very quickly on a high-latency connection.
|
||||||
|
- `/plugins`, `/whitelist list`, `/banlist` and `/list` now show output in alphabetical order.
|
||||||
|
- Some `pocketmine\event` APIs which accept arrays now have more robust type checking, fixing type errors caused by plugin input occurring in core code.
|
||||||
|
- `Attribute::getAttributeByName()` is now aware of the `minecraft:lava_movement` attribute.
|
||||||
|
|
||||||
|
# 3.14.2
|
||||||
|
- Exception stack traces are now logged as CRITICAL. It's hoped that users will recognize that they are just as important as the error message and not leave them out when asking for help with errors on Discord.
|
||||||
|
- `TaskScheduler` no longer accepts tasks that already have a handler. This fixes undefined behaviour which occurs when scheduling the same task instance twice, but it does break plugins such as **MyPlot** which unintentionally used this buggy behaviour.
|
||||||
|
- Players will now correctly receive the needed number of spawn chunks if they are teleported between `PlayerLoginEvent` and `PlayerJoinEvent`. This fixes a bug that could occur when teleporting players in delayed tasks between login and join.
|
||||||
|
- `PlayerRespawnEvent->setRespawnPosition()` now throws an exception if the provided `Position` has an invalid world associated with it (null or unloaded).
|
||||||
|
- Fixed a crash that occurred when stats reporting was enabled.
|
||||||
|
|
||||||
|
# 3.14.3
|
||||||
|
- Fixed deprecation error when running `/whitelist list` on PHP 7.4.
|
||||||
|
- Fixed podzol breaking animation being incorrect (incorrect hardness).
|
||||||
|
- `Entity::getSaveId()` now reports the class name in the message thrown for unregistered entities.
|
||||||
|
- Fixed `CraftingManager->validate()` producing different results when called multiple times for the same transaction.
|
||||||
|
- Fixed various issues with batch-crafting items using the recipe book and shift-clicking.
|
||||||
|
- `tests/plugins/PocketMine-DevTools` submodule has been renamed to `tests/plugins/DevTools`.
|
54
changelogs/3.15.md
Normal file
54
changelogs/3.15.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.16.20**
|
||||||
|
|
||||||
|
### 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.15.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.16.20.
|
||||||
|
- Removed compatibility with 1.16.0.
|
||||||
|
|
||||||
|
## Known issues (please don't open issues for these)
|
||||||
|
- Walls don't connect to each other
|
||||||
|
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||||
|
- New blocks, items & mobs aren't implemented
|
||||||
|
- Nether doesn't exist
|
||||||
|
|
||||||
|
# 3.15.1
|
||||||
|
- Fixed various PHP 7.4 compatibility issues in Composer dependencies (primarily callback-validator).
|
||||||
|
- Fixed LevelDB worlds with corrupted `level.dat` crashing the server instead of failing gracefully.
|
||||||
|
- Fixed error spam when using strings for layers in flatworld presets (`e.g. bedrock,3xdirt,grass`).
|
||||||
|
- Fixed blocks not getting updated properly on explosions.
|
||||||
|
- Fixed `BlockGrowEvent` not being called when sugarcane grows.
|
||||||
|
- Potato crops now drop poisonous potatoes when harvested.
|
||||||
|
- Fixed the wrong number of potatoes being dropped when harvesting potato crops.
|
||||||
|
- Players no longer get pullbacks when sprinting on slabs, stairs and various other blocks when `player.anti-cheat.allow-movement-cheats` is set to `false`. (This bug has been around for over 5 years, so many of you will be used to its existence.)
|
||||||
|
- Fixed entity collision box calculation not taking clip distance into account.
|
||||||
|
- Entities now step up the correct height of the target block, instead of jumping into the air 0.6 blocks and falling back down.
|
||||||
|
|
||||||
|
# 3.15.2
|
||||||
|
- Fixed issues with preloading `SubChunk`.
|
||||||
|
- `/gc` and automatic garbage collection will now release unused heap blocks back to the OS. Previously, the PHP process might hold onto these blocks indefinitely even when not used, causing elevated real memory usage.
|
||||||
|
- Added some documentation to `FurnaceBurnEvent`.
|
||||||
|
|
||||||
|
# 3.15.3
|
||||||
|
- Fixed fall damage accumulation over continuous knockbacks (e.g. combo attacks in PvP).
|
||||||
|
- Fixed a bug in `Human->addXp()` that would cause a crash when saving player data.
|
||||||
|
- `Human->addXp()` will no longer modify the target's total XP if `PlayerExperienceChangeEvent` was cancelled.
|
||||||
|
- `AsyncPool->getTaskQueueSizes()` has been added to allow external detection of async pool overload. This is planned to be implemented as a core feature in the future, but it hasn't been done yet.
|
||||||
|
- `BaseInventory->canAddItem()` behaviour now matches `addItem()` by considering the max stack size of the given item.
|
||||||
|
- Fixed a bug in generator options handling for worlds loaded via `pocketmine.yml`. This fix has the following side effects:
|
||||||
|
- It's now possible to provide generator options as an `options` key when loading a world via `pocketmine.yml`.
|
||||||
|
- If generator options are not provided, the options from `server.properties` will be used, instead of using an empty preset. (It's not clear whether this is desired behaviour, but it was clearly intended, since there is code to do this which was broken until this release. As such, this behaviour is subject to change in the future.)
|
||||||
|
- Fixed a bug in region-based world loading where some files without filename extensions and names containing a region filename extension (e.g a file named `amca` in a McRegion world) would cause the world not to load. These files are now ignored.
|
||||||
|
- Default network compression level has been lowered to 6, due to level 7 being 25% more expensive for only a marginal improvement in bandwidth.
|
||||||
|
- Fixed a performance issue with chunk requesting when players trigger chunk generation on first join.
|
||||||
|
- Setup wizard will now always show IP information, even if the user chose to skip the setup wizard when prompted. (This doesn't affect `--no-wizard` in any way.)
|
||||||
|
- `Maximum memory (system)` is no longer reported in `/status` due to having a misleading output (it was the same as the current memory usage).
|
||||||
|
- The `Player Chunk Send` timer on timings reports now actually reports measurements of chunk sending, not chunk loading.
|
||||||
|
- A new parent timer `World Load` has been added to timings reports, which aggregates timings from `syncChunkLoad` and subtimings from all worlds.
|
||||||
|
|
||||||
|
# 3.15.4
|
||||||
|
- Fixed a bug in the inventory transaction system that caused the server to freeze under some circumstances.
|
24
changelogs/3.16.md
Normal file
24
changelogs/3.16.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.16.100**
|
||||||
|
|
||||||
|
### 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.16.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.16.100.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
- Added new custom composer commands `make-server` and `make-devtools` to ease setting up a development environment and building the server.
|
||||||
|
|
||||||
|
## Known issues (please don't open issues for these)
|
||||||
|
- Walls don't connect to each other
|
||||||
|
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||||
|
- New blocks, items & mobs aren't implemented
|
||||||
|
- Nether doesn't exist
|
||||||
|
|
||||||
|
# 3.16.1
|
||||||
|
- Fixed incorrect encoding of skins in the protocol.
|
||||||
|
- `/version` no longer crashes when a plugin provides `string[]` for the `author` field in `plugin.yml`.
|
||||||
|
- `author` in `plugin.yml` now accepts arrays, just like `authors`.
|
||||||
|
- Fixed `HellBiome` never being registered.
|
63
changelogs/3.17.md
Normal file
63
changelogs/3.17.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.16.200**
|
||||||
|
|
||||||
|
### 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.17.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.16.200.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
## Known issues (please don't open issues for these)
|
||||||
|
- Walls don't connect to each other
|
||||||
|
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||||
|
- New blocks, items & mobs aren't implemented
|
||||||
|
- Nether doesn't exist
|
||||||
|
|
||||||
|
# 3.17.1
|
||||||
|
- Fixed some instances of plugin-caused crashes not being detected (eval()'d code, custom plugin paths).
|
||||||
|
- Server uptime is now included in crash reports.
|
||||||
|
- Hoes now take damage when used to break sponges.
|
||||||
|
- Using lava as fuel in a furnace now leaves behind an empty bucket.
|
||||||
|
|
||||||
|
# 3.17.2
|
||||||
|
- Fixed region header corruption when chunks with larger-than-expected lengths are found. These chunks are now treated as corrupted, instead of automatically attempting to salvage them (which usually fails anyway).
|
||||||
|
- `RegionLoader->removeChunk()` now allows the space used by the removed chunk to be reused by future region saves.
|
||||||
|
- Extracted `Living->applyConsumptionResults()` from `Living->consumeObject()` (preparation for a future bug fix).
|
||||||
|
|
||||||
|
# 3.17.3
|
||||||
|
- Improved performance of chunk loading in Region-based worlds.
|
||||||
|
- Improved performance of region header validation in Region-based worlds (indirect improvement to chunk loading performance).
|
||||||
|
- Fixed some PHP 8.0 language-level compatibility issues.
|
||||||
|
- Source installations will now exit with an error when Composer dependencies are not in sync with the current Git revision. Now, it's required to run `composer install` after every git pull to make sure the correct dependency versions are installed.
|
||||||
|
|
||||||
|
# 3.17.4
|
||||||
|
- Removed `readline` support. This hasn't been maintained for many years, never worked correctly, and isn't thread-safe in any case.
|
||||||
|
- Fixed false-positives of region corruption in Region-based worlds (outdated file stat cache).
|
||||||
|
- Fixed more deprecation warnings on PHP 8.0 (optional parameter before required).
|
||||||
|
- `CraftItemEvent->getInputs()` now returns a list starting at offset 0, instead of random offsets. (Note that the contents still won't be ordered.)
|
||||||
|
- `CraftItemEvent->getOutputs()` now returns a list starting at offset 0, instead of random offsets. (Note that the contents still won't be ordered.)
|
||||||
|
- Fixed a bug that broke synchronized building, bridging, towering and more.
|
||||||
|
- Objects in memory dumps no longer show inherited properties multiple times.
|
||||||
|
|
||||||
|
# 3.17.5
|
||||||
|
- Reduced CPU wastage by the logger thread.
|
||||||
|
- Fixed LevelDB deprecation errors on PHP 8.0.
|
||||||
|
- Added some protocol changes for 1.16.200 which were previously overlooked.
|
||||||
|
- Player XUIDs are now tracked. If a player's XUID does not match the previously recorded XUID when they next join the server, they will be kicked. This can be disabled by the `player.verify-xuid` setting in `pocketmine.yml`.
|
||||||
|
- `BUILDING.md` now has a note about `build/server-phar.php`'s compression bug (a bug in PHP).
|
||||||
|
|
||||||
|
# 3.17.6
|
||||||
|
- Fixed core race conditions that could have led to server freezes (race conditions in pmmp/Snooze).
|
||||||
|
- The log message about Xbox Live authentication being enabled has been reduced to INFO, and the tip on how to turn it off removed (disabling it should usually only be done by power users anyway).
|
||||||
|
- Fixed `PlayerMoveEvent->getFrom()` returning incorrect results for players who experienced movement reversions.
|
||||||
|
- Fixed a bug in `ResourcePackClientResponsePacket` decoding that caused unexpected results when decoding the packet twice.
|
||||||
|
- XUID verification now compares XUIDs against players who are already on the server to detect mismatches to avoid unnecessary loading of playerdata.
|
||||||
|
- Fixed an inventory duplication bug which could occur when the same player joined with two devices at the same time.
|
||||||
|
- Fixed cursor item not being synced on inventory transaction rollbacks.
|
||||||
|
- Fixed items with TAG_Float in their NBT not being able to be moved around in the inventory.
|
||||||
|
|
||||||
|
# 3.17.7
|
||||||
|
- Fixed crash caused by preprocessor in 3.17.6.
|
31
changelogs/3.18.md
Normal file
31
changelogs/3.18.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.16.210**
|
||||||
|
|
||||||
|
### 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.18.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.16.210.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
## Known issues (please don't open issues for these)
|
||||||
|
- Walls don't connect to each other
|
||||||
|
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||||
|
- New blocks, items & mobs aren't implemented
|
||||||
|
- Nether doesn't exist
|
||||||
|
- Items can't be removed from item frames in Survival mode
|
||||||
|
|
||||||
|
# 3.18.1
|
||||||
|
- UPnP is now supported on all platforms instead of just Windows. Note that it's still experimental. Please file issues for any bugs that you find.
|
||||||
|
- Fixed server joining when default game mode is set to Spectator mode.
|
||||||
|
- Fixed items not being able to be removed from item frames in Survival mode.
|
||||||
|
- Fixed field order in ClientCacheBlobStatusPacket (hits and misses were inverted).
|
||||||
|
- Fixed a deadlock that could occur when MainLogger->syncFlushBuffer() was used (usually only used during exception logging).
|
||||||
|
- Updated constants for various things in the protocol.
|
||||||
|
|
||||||
|
# 3.18.2
|
||||||
|
- Fixed `InventoryCloseEvent` not being called on server-initiated inventory closures.
|
||||||
|
- `PlayerToggleFlightEvent` may now be pre-cancelled if the player attempted to enable flight when flying was not allowed. This replaces the previous behaviour of kicking the player.
|
||||||
|
- Fixed being unable to change the item in hand from the inventory window when looking at an entity.
|
31
changelogs/3.19.md
Normal file
31
changelogs/3.19.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.16.220**
|
||||||
|
|
||||||
|
### 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.19.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.16.220.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
## Known issues (please don't open issues for these)
|
||||||
|
- Walls don't connect to each other
|
||||||
|
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||||
|
- New blocks, items & mobs aren't implemented
|
||||||
|
- Nether doesn't exist
|
||||||
|
|
||||||
|
# 3.19.1
|
||||||
|
- Fixed some particles not working since 1.16.220.
|
||||||
|
- Fixed issues with creative inventory items appearing in the wrong places since 1.16.220.
|
||||||
|
- `Item->removeEnchantment()` now removes the `ench` tag from item NBT when removing the only enchantment on an item.
|
||||||
|
- Fixed temporary memory leak of repeating tasks which cancelled themselves during their `onRun()` handler (they were pushed back onto the task queue even though cancelled, and only removed at their next attempted repeat).
|
||||||
|
|
||||||
|
# 3.19.2
|
||||||
|
- Signs can now only be edited by the player who placed them. They will become finalized if the chunk containing them is unloaded and reloaded, or if the creating player quits the server.
|
||||||
|
|
||||||
|
# 3.19.3
|
||||||
|
- Fixed `Worker->quit()` returning without stopping the thread.
|
||||||
|
- Added some protocol constants in `SetDisplayObjectivePacket`.
|
||||||
|
- Fixed possible client crash caused by `CraftingDataPacket`.
|
11
changelogs/3.20.md
Normal file
11
changelogs/3.20.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.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.20.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.17.0
|
||||||
|
- Removed compatibility with earlier versions.
|
15
changelogs/3.21.md
Normal file
15
changelogs/3.21.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.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.21.0
|
||||||
|
- PHP 7.4 is now required as a minimum.
|
||||||
|
- A workaround for player movement added in 1.14.30 has been removed.
|
||||||
|
|
||||||
|
# 3.21.1
|
||||||
|
- Fixed so-called 'pot lag' - a bug that could occur when using items while rapidly switching hotbar slots.
|
||||||
|
- Plugins in crashdumps are now ordered alphabetically for easier reading.
|
36
changelogs/3.22.md
Normal file
36
changelogs/3.22.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.10**
|
||||||
|
|
||||||
|
### 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.22.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.17.10.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
# 3.22.1
|
||||||
|
- Added a giant yellow startup warning if using OPcache JIT on PHP 8.0. JIT is currently considered highly unstable and not recommended for production use.
|
||||||
|
- When using a bad PHP binary, the bootstrap will now report the used `php.ini` path. This can be useful for debugging issues with extension loading when the wrong `php.ini` file is loaded for some reason.
|
||||||
|
- Fixed `start.cmd` causing the wrong `php.ini` to be loaded on Windows when a global PHP installation is used.
|
||||||
|
- A debug message is now logged containing expected vs. actual XUID of players when an XUID mismatch is detected.
|
||||||
|
- Improved the documentation for `Player->getUniqueId()`.
|
||||||
|
- Fixed a mistake in the documentation of `PlayerAuthInputFlags`.
|
||||||
|
- Fixed incorrect encoding of `NpcDialoguePacket`.
|
||||||
|
|
||||||
|
# 3.22.2
|
||||||
|
- PHP 8.0 is now the primary supported version. PHP 7.4 is still supported for now, but it will be dropped in the coming weeks. It's recommended to start testing your servers on 8.0 now so you're ready.
|
||||||
|
- Fixed items in the crafting grid getting deleted on server-side disconnect or session timeout.
|
||||||
|
- A warning is now logged on startup if a debug build of PHP is used to run the server (because it has a significant performance impact).
|
||||||
|
- GitHub Actions is now used to build new releases, instead of Jenkins. You can see build logs [here](https://github.com/pmmp/PocketMine-MP/actions/workflows/draft-release.yml).
|
||||||
|
|
||||||
|
# 3.22.3
|
||||||
|
- Fixed a bug in the release build of 3.22.2 which caused the crash archive to reject all crashdumps.
|
||||||
|
- Fixed possible server crash during player spawning.
|
||||||
|
|
||||||
|
# 3.22.4
|
||||||
|
- Fixed a bug which broke the build of 3.22.3.
|
||||||
|
|
||||||
|
# 3.22.5
|
||||||
|
- Added a workaround for polyfilled solid-colour Persona skin replacements turning into a corrupted mess (caused by https://bugs.mojang.com/browse/MCPE-130275).
|
14
changelogs/3.23.md
Normal file
14
changelogs/3.23.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.30**
|
||||||
|
|
||||||
|
### 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.23.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.17.30.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
# 3.23.1
|
||||||
|
- Fixed broken build of 3.23.0.
|
12
changelogs/3.24.md
Normal file
12
changelogs/3.24.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.30**
|
||||||
|
|
||||||
|
### 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.24.0
|
||||||
|
- PHP 8.0 is now required as a minimum.
|
||||||
|
- Fixed stats reporting checking the wrong `pocketmine.yml` property.
|
||||||
|
- Fixed `Projectile->move()` not respecting the given `dx`/`dy`/`dz` and using its own motion instead.
|
27
changelogs/3.25.md
Normal file
27
changelogs/3.25.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.40**
|
||||||
|
|
||||||
|
### 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.25.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.17.40.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
# 3.25.1
|
||||||
|
- Fixed autosave bug that caused unmodified chunks to be saved at least once (during the first autosave after they were loaded).
|
||||||
|
- `Entity->spawnTo()` now has an additional sanity check for matching worlds (might expose a few new errors in plugins).
|
||||||
|
- Fixed a missing field in `CraftRecipeAuto` item stack request type.
|
||||||
|
|
||||||
|
# 3.25.2
|
||||||
|
- Now analysed using level 9 on PHPStan 1.0.0.
|
||||||
|
- `ext-pthreads` v4.0.0 or newer is now required.
|
||||||
|
- Fixed crash in `Player->showPlayer()` when the target is not in the same world.
|
||||||
|
- `Human->setLifetimeTotalXp()` now limits the maximum value to 2^31.
|
||||||
|
- Fixed players, who died in hardcore mode and were unbanned, getting re-banned on next server join.
|
||||||
|
|
||||||
|
# 3.25.3
|
||||||
|
- Fixed crash when players try to pickup XP while already having max XP.
|
||||||
|
- Added a sanity check to `Human->setCurrentTotalXp()` to try and catch an elusive bug that's been appearing in the wild - please get in touch if you know how to reproduce it!
|
@ -1,15 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "pocketmine/pocketmine-mp",
|
"name": "pocketmine/pocketmine-mp",
|
||||||
"description": "A server software for Minecraft: Pocket Edition written in PHP",
|
"description": "A server software for Minecraft: Bedrock Edition written in PHP",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"homepage": "https://pmmp.io",
|
"homepage": "https://pmmp.io",
|
||||||
"license": "LGPL-3.0",
|
"license": "LGPL-3.0",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.0",
|
"php": "^8.0",
|
||||||
"php-64bit": "*",
|
"php-64bit": "*",
|
||||||
"ext-bcmath": "*",
|
|
||||||
"ext-curl": "*",
|
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
|
"ext-curl": "*",
|
||||||
"ext-date": "*",
|
"ext-date": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
@ -17,27 +16,39 @@
|
|||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"ext-pcre": "*",
|
"ext-pcre": "*",
|
||||||
"ext-phar": "*",
|
"ext-phar": "*",
|
||||||
"ext-pthreads": "~3.2.0",
|
"ext-pthreads": "^4.0",
|
||||||
"ext-reflection": "*",
|
"ext-reflection": "*",
|
||||||
|
"ext-simplexml": "*",
|
||||||
"ext-sockets": "*",
|
"ext-sockets": "*",
|
||||||
"ext-spl": "*",
|
"ext-spl": "*",
|
||||||
"ext-yaml": ">=2.0.0",
|
"ext-yaml": ">=2.0.0",
|
||||||
"ext-zip": "*",
|
"ext-zip": "*",
|
||||||
"ext-zlib": ">=1.2.11",
|
"ext-zlib": ">=1.2.11",
|
||||||
"pocketmine/raklib": "^0.12.5",
|
"composer-runtime-api": "^2.0",
|
||||||
"pocketmine/spl": "^0.3.0",
|
"adhocore/json-comment": "^1.1",
|
||||||
"pocketmine/binaryutils": "^0.1.9",
|
"pocketmine/binaryutils": "^0.1.9",
|
||||||
"pocketmine/nbt": "^0.2.10",
|
"pocketmine/callback-validator": "^1.0.2",
|
||||||
|
"pocketmine/classloader": "^0.1.0",
|
||||||
|
"pocketmine/log": "^0.2.0",
|
||||||
|
"pocketmine/log-pthreads": "^0.1.0",
|
||||||
"pocketmine/math": "^0.2.0",
|
"pocketmine/math": "^0.2.0",
|
||||||
|
"pocketmine/nbt": "^0.2.18",
|
||||||
|
"pocketmine/raklib": "^0.12.7",
|
||||||
"pocketmine/snooze": "^0.1.0",
|
"pocketmine/snooze": "^0.1.0",
|
||||||
"daverandom/callback-validator": "dev-master",
|
"pocketmine/spl": "^0.4.0"
|
||||||
"adhocore/json-comment": "^0.0.7"
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "1.1.1",
|
||||||
|
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||||
|
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||||
|
"phpunit/phpunit": "^9.2"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"": ["src"]
|
"": ["src"]
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
"src/pocketmine/CoreConstants.php",
|
||||||
"src/pocketmine/GlobalConstants.php",
|
"src/pocketmine/GlobalConstants.php",
|
||||||
"src/pocketmine/VersionInfo.php"
|
"src/pocketmine/VersionInfo.php"
|
||||||
]
|
]
|
||||||
@ -47,30 +58,17 @@
|
|||||||
"pocketmine\\": "tests/phpunit/"
|
"pocketmine\\": "tests/phpunit/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"repositories": [
|
"config": {
|
||||||
{
|
"platform": {
|
||||||
"type": "vcs",
|
"php": "8.0.0"
|
||||||
"url": "https://github.com/pmmp/RakLib"
|
|
||||||
},
|
},
|
||||||
{
|
"sort-packages": true
|
||||||
"type": "vcs",
|
|
||||||
"url": "https://github.com/pmmp/SPL"
|
|
||||||
},
|
},
|
||||||
{
|
"scripts": {
|
||||||
"type": "vcs",
|
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/DevTools/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||||
"url": "https://github.com/pmmp/BinaryUtils"
|
"make-server": [
|
||||||
},
|
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
||||||
{
|
"@php -dphar.readonly=0 build/server-phar.php"
|
||||||
"type": "vcs",
|
|
||||||
"url": "https://github.com/pmmp/NBT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "vcs",
|
|
||||||
"url": "https://github.com/pmmp/Math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "vcs",
|
|
||||||
"url": "https://github.com/pmmp/Snooze"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
2639
composer.lock
generated
2639
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,6 @@ This site contains auto-generated API documentation for PocketMine-MP (and depen
|
|||||||
This site can be accessed via https://apidoc.pmmp.io.
|
This site can be accessed via https://apidoc.pmmp.io.
|
||||||
|
|
||||||
### Additional developer resources
|
### Additional developer resources
|
||||||
- [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
|
- [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
|
||||||
- [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
- [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||||
- [DeveloperDocs](https://github.com/pmmp/DeveloperDocs/) - Reference, guides and specifications for the PocketMine-MP API
|
- [DeveloperDocs](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
||||||
|
@ -1,126 +1,52 @@
|
|||||||
includes:
|
includes:
|
||||||
- tests/phpstan/configs/debug-const-checks.neon
|
- tests/phpstan/configs/actual-problems.neon
|
||||||
- tests/phpstan/configs/gc-hacks.neon
|
- tests/phpstan/configs/gc-hacks.neon
|
||||||
- tests/phpstan/configs/optional-com-dotnet.neon
|
- tests/phpstan/configs/php-bugs.neon
|
||||||
- tests/phpstan/configs/optional-leveldb.neon
|
|
||||||
- tests/phpstan/configs/phpstan-bugs.neon
|
- tests/phpstan/configs/phpstan-bugs.neon
|
||||||
|
- tests/phpstan/configs/phpunit-wiring-tests.neon
|
||||||
- tests/phpstan/configs/pthreads-bugs.neon
|
- tests/phpstan/configs/pthreads-bugs.neon
|
||||||
- tests/phpstan/configs/runtime-type-checks.neon
|
- tests/phpstan/configs/runtime-type-checks.neon
|
||||||
|
- tests/phpstan/configs/spl-fixed-array-sucks.neon
|
||||||
|
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||||
|
- vendor/phpstan/phpstan-phpunit/rules.neon
|
||||||
|
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
level: 5
|
level: 9
|
||||||
autoload_files:
|
checkMissingCallableSignature: true
|
||||||
|
treatPhpDocTypesAsCertain: false
|
||||||
|
bootstrapFiles:
|
||||||
- tests/phpstan/bootstrap.php
|
- tests/phpstan/bootstrap.php
|
||||||
|
scanDirectories:
|
||||||
|
- build
|
||||||
|
- tests/plugins/TesterPlugin
|
||||||
|
scanFiles:
|
||||||
- src/pocketmine/PocketMine.php
|
- src/pocketmine/PocketMine.php
|
||||||
paths:
|
paths:
|
||||||
|
- build
|
||||||
- src
|
- src
|
||||||
|
- tests/phpunit
|
||||||
|
- tests/plugins/TesterPlugin
|
||||||
|
excludePaths:
|
||||||
|
analyseAndScan:
|
||||||
|
- build/php
|
||||||
|
- build/preprocessor
|
||||||
|
analyse:
|
||||||
|
- src/pocketmine/block/StoneSlab.php #overrides STONE constant
|
||||||
|
- src/pocketmine/item/Potion.php #overrides WATER constant
|
||||||
|
dynamicConstantNames:
|
||||||
|
- pocketmine\DEBUG
|
||||||
|
- pocketmine\IS_DEVELOPMENT_BUILD
|
||||||
|
stubFiles:
|
||||||
|
- tests/phpstan/stubs/chunkutils.stub
|
||||||
|
- tests/phpstan/stubs/leveldb.stub
|
||||||
|
- tests/phpstan/stubs/pthreads.stub
|
||||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||||
ignoreErrors:
|
staticReflectionClassNamePatterns:
|
||||||
-
|
- "#^COM$#"
|
||||||
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
|
typeAliases:
|
||||||
count: 1
|
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
|
||||||
path: src/pocketmine/Server.php
|
#what we actually need is something that accepts an infinite number of parameters, but in the absence of that,
|
||||||
|
#we'll just fill it with 10 - it's very unlikely to encounter a callable with 10 parameters anyway.
|
||||||
-
|
anyCallable: 'callable(never, never, never, never, never, never, never, never, never, never) : mixed'
|
||||||
message: "#^Call to an undefined method pocketmine\\\\command\\\\CommandSender\\:\\:teleport\\(\\)\\.$#"
|
anyClosure: '\Closure(never, never, never, never, never, never, never, never, never, never) : mixed'
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/command/defaults/TeleportCommand.php
|
|
||||||
# comment: "not actually possible, but high cost to fix warning"
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Array \\(array\\<string\\>\\) does not accept pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/pocketmine/entity/Entity.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Invalid array key type pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/entity/Entity.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\EntityDeathEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\Living but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/event/entity/EntityDeathEvent.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\EntityShootBowEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\Living but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/event/entity/EntityShootBowEvent.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property pocketmine\\\\event\\\\entity\\\\EntityShootBowEvent\\:\\:\\$projectile \\(pocketmine\\\\entity\\\\projectile\\\\Projectile\\) does not accept pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/event/entity/EntityShootBowEvent.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ItemDespawnEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\object\\\\ItemEntity but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/event/entity/ItemDespawnEvent.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ItemSpawnEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\object\\\\ItemEntity but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/event/entity/ItemSpawnEvent.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ProjectileHitEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\projectile\\\\Projectile but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/event/entity/ProjectileHitEvent.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ProjectileLaunchEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\projectile\\\\Projectile but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/event/entity/ProjectileLaunchEvent.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constructor of class pocketmine\\\\level\\\\generator\\\\hell\\\\Nether has an unused parameter \\$options\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/level/generator/hell/Nether.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constructor of class pocketmine\\\\level\\\\generator\\\\normal\\\\Normal has an unused parameter \\$options\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/level/generator/normal/Normal.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Used constant pocketmine\\\\RESOURCE_PATH not found\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/network/mcpe/protocol/StartGamePacket.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constructor of class pocketmine\\\\scheduler\\\\TaskScheduler has an unused parameter \\$logger\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/scheduler/TaskScheduler.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\COMPOSER_AUTOLOADER_PATH not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\DATA not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\GIT_COMMIT not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\PATH not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\PLUGIN_PATH not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\RESOURCE_PATH not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\START_TIME not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\VERSION not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
|
@ -31,7 +31,8 @@ use pocketmine\utils\TextFormat;
|
|||||||
*/
|
*/
|
||||||
abstract class Achievement{
|
abstract class Achievement{
|
||||||
/**
|
/**
|
||||||
* @var array[]
|
* @var mixed[][]
|
||||||
|
* @phpstan-var array<string, array{name: string, requires: list<string>}>
|
||||||
*/
|
*/
|
||||||
public static $list = [
|
public static $list = [
|
||||||
/*"openInventory" => array(
|
/*"openInventory" => array(
|
||||||
@ -106,13 +107,6 @@ abstract class Achievement{
|
|||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Player $player
|
|
||||||
* @param string $achievementId
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function broadcast(Player $player, string $achievementId) : bool{
|
public static function broadcast(Player $player, string $achievementId) : bool{
|
||||||
if(isset(Achievement::$list[$achievementId])){
|
if(isset(Achievement::$list[$achievementId])){
|
||||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||||
@ -129,11 +123,7 @@ abstract class Achievement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $achievementId
|
* @param string[] $requires
|
||||||
* @param string $achievementName
|
|
||||||
* @param array $requires
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public static function add(string $achievementId, string $achievementName, array $requires = []) : bool{
|
public static function add(string $achievementId, string $achievementName, array $requires = []) : bool{
|
||||||
if(!isset(Achievement::$list[$achievementId])){
|
if(!isset(Achievement::$list[$achievementId])){
|
||||||
|
@ -25,12 +25,16 @@ namespace pocketmine;
|
|||||||
|
|
||||||
abstract class Collectable extends \Threaded{
|
abstract class Collectable extends \Threaded{
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
private $isGarbage = false;
|
private $isGarbage = false;
|
||||||
|
|
||||||
public function isGarbage() : bool{
|
public function isGarbage() : bool{
|
||||||
return $this->isGarbage;
|
return $this->isGarbage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setGarbage(){
|
public function setGarbage(){
|
||||||
$this->isGarbage = true;
|
$this->isGarbage = true;
|
||||||
}
|
}
|
||||||
|
37
src/pocketmine/CoreConstants.php
Normal file
37
src/pocketmine/CoreConstants.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?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 function define;
|
||||||
|
use function defined;
|
||||||
|
use function dirname;
|
||||||
|
|
||||||
|
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||||
|
if(defined('pocketmine\_CORE_CONSTANTS_INCLUDED')){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
|
||||||
|
|
||||||
|
define('pocketmine\PATH', dirname(__DIR__, 2) . '/');
|
||||||
|
define('pocketmine\RESOURCE_PATH', __DIR__ . '/resources/');
|
@ -23,13 +23,14 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
|
use Composer\InstalledVersions;
|
||||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||||
use pocketmine\plugin\PluginBase;
|
use pocketmine\plugin\PluginBase;
|
||||||
use pocketmine\plugin\PluginLoadOrder;
|
use pocketmine\plugin\PluginLoadOrder;
|
||||||
use pocketmine\plugin\PluginManager;
|
use pocketmine\plugin\PluginManager;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\utils\VersionString;
|
use pocketmine\utils\VersionString;
|
||||||
use raklib\RakLib;
|
|
||||||
use function base64_encode;
|
use function base64_encode;
|
||||||
use function date;
|
use function date;
|
||||||
use function error_get_last;
|
use function error_get_last;
|
||||||
@ -45,7 +46,9 @@ use function is_dir;
|
|||||||
use function is_resource;
|
use function is_resource;
|
||||||
use function json_encode;
|
use function json_encode;
|
||||||
use function json_last_error_msg;
|
use function json_last_error_msg;
|
||||||
|
use function ksort;
|
||||||
use function max;
|
use function max;
|
||||||
|
use function microtime;
|
||||||
use function mkdir;
|
use function mkdir;
|
||||||
use function ob_end_clean;
|
use function ob_end_clean;
|
||||||
use function ob_get_contents;
|
use function ob_get_contents;
|
||||||
@ -54,10 +57,10 @@ use function php_uname;
|
|||||||
use function phpinfo;
|
use function phpinfo;
|
||||||
use function phpversion;
|
use function phpversion;
|
||||||
use function preg_replace;
|
use function preg_replace;
|
||||||
|
use function sprintf;
|
||||||
use function str_split;
|
use function str_split;
|
||||||
use function strpos;
|
use function strpos;
|
||||||
use function substr;
|
use function substr;
|
||||||
use function time;
|
|
||||||
use function zend_version;
|
use function zend_version;
|
||||||
use function zlib_encode;
|
use function zlib_encode;
|
||||||
use const E_COMPILE_ERROR;
|
use const E_COMPILE_ERROR;
|
||||||
@ -79,6 +82,7 @@ use const FILE_IGNORE_NEW_LINES;
|
|||||||
use const JSON_UNESCAPED_SLASHES;
|
use const JSON_UNESCAPED_SLASHES;
|
||||||
use const PHP_EOL;
|
use const PHP_EOL;
|
||||||
use const PHP_OS;
|
use const PHP_OS;
|
||||||
|
use const SORT_STRING;
|
||||||
|
|
||||||
class CrashDump{
|
class CrashDump{
|
||||||
|
|
||||||
@ -88,7 +92,7 @@ class CrashDump{
|
|||||||
* having their content changed, version format changing, etc.
|
* having their content changed, version format changing, etc.
|
||||||
* It is not necessary to increase this when adding new fields.
|
* It is not necessary to increase this when adding new fields.
|
||||||
*/
|
*/
|
||||||
private const FORMAT_VERSION = 2;
|
private const FORMAT_VERSION = 4;
|
||||||
|
|
||||||
private const PLUGIN_INVOLVEMENT_NONE = "none";
|
private const PLUGIN_INVOLVEMENT_NONE = "none";
|
||||||
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
|
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
|
||||||
@ -96,8 +100,14 @@ class CrashDump{
|
|||||||
|
|
||||||
/** @var Server */
|
/** @var Server */
|
||||||
private $server;
|
private $server;
|
||||||
|
/** @var resource */
|
||||||
private $fp;
|
private $fp;
|
||||||
|
/** @var float */
|
||||||
private $time;
|
private $time;
|
||||||
|
/**
|
||||||
|
* @var mixed[]
|
||||||
|
* @phpstan-var array<string, mixed>
|
||||||
|
*/
|
||||||
private $data = [];
|
private $data = [];
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $encodedData = "";
|
private $encodedData = "";
|
||||||
@ -105,19 +115,21 @@ class CrashDump{
|
|||||||
private $path;
|
private $path;
|
||||||
|
|
||||||
public function __construct(Server $server){
|
public function __construct(Server $server){
|
||||||
$this->time = time();
|
$this->time = microtime(true);
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
if(!is_dir($this->server->getDataPath() . "crashdumps")){
|
if(!is_dir($this->server->getDataPath() . "crashdumps")){
|
||||||
mkdir($this->server->getDataPath() . "crashdumps");
|
mkdir($this->server->getDataPath() . "crashdumps");
|
||||||
}
|
}
|
||||||
$this->path = $this->server->getDataPath() . "crashdumps/" . date("D_M_j-H.i.s-T_Y", $this->time) . ".log";
|
$this->path = $this->server->getDataPath() . "crashdumps/" . date("D_M_j-H.i.s-T_Y", (int) $this->time) . ".log";
|
||||||
$this->fp = @fopen($this->path, "wb");
|
$fp = @fopen($this->path, "wb");
|
||||||
if(!is_resource($this->fp)){
|
if(!is_resource($fp)){
|
||||||
throw new \RuntimeException("Could not create Crash Dump");
|
throw new \RuntimeException("Could not create Crash Dump");
|
||||||
}
|
}
|
||||||
|
$this->fp = $fp;
|
||||||
$this->data["format_version"] = self::FORMAT_VERSION;
|
$this->data["format_version"] = self::FORMAT_VERSION;
|
||||||
$this->data["time"] = $this->time;
|
$this->data["time"] = $this->time;
|
||||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
$this->data["uptime"] = $this->time - \pocketmine\START_TIME;
|
||||||
|
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", (int) $this->time));
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->baseCrash();
|
$this->baseCrash();
|
||||||
$this->generalData();
|
$this->generalData();
|
||||||
@ -134,15 +146,22 @@ class CrashDump{
|
|||||||
return $this->path;
|
return $this->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getEncodedData(){
|
public function getEncodedData(){
|
||||||
return $this->encodedData;
|
return $this->encodedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed[]
|
||||||
|
* @phpstan-return array<string, mixed>
|
||||||
|
*/
|
||||||
public function getData() : array{
|
public function getData() : array{
|
||||||
return $this->data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function encodeData(){
|
private function encodeData() : void{
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
@ -151,19 +170,23 @@ class CrashDump{
|
|||||||
if($json === false){
|
if($json === false){
|
||||||
throw new \RuntimeException("Failed to encode crashdump JSON: " . json_last_error_msg());
|
throw new \RuntimeException("Failed to encode crashdump JSON: " . json_last_error_msg());
|
||||||
}
|
}
|
||||||
$this->encodedData = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
|
$zlibEncoded = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
|
||||||
|
if($zlibEncoded === false) throw new AssumptionFailedError("ZLIB compression failed");
|
||||||
|
$this->encodedData = $zlibEncoded;
|
||||||
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
|
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
|
||||||
$this->addLine($line);
|
$this->addLine($line);
|
||||||
}
|
}
|
||||||
$this->addLine("===END CRASH DUMP===");
|
$this->addLine("===END CRASH DUMP===");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function pluginsData(){
|
private function pluginsData() : void{
|
||||||
if($this->server->getPluginManager() instanceof PluginManager){
|
if($this->server->getPluginManager() instanceof PluginManager){
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("Loaded plugins:");
|
$this->addLine("Loaded plugins:");
|
||||||
$this->data["plugins"] = [];
|
$this->data["plugins"] = [];
|
||||||
foreach($this->server->getPluginManager()->getPlugins() as $p){
|
$plugins = $this->server->getPluginManager()->getPlugins();
|
||||||
|
ksort($plugins, SORT_STRING);
|
||||||
|
foreach($plugins as $p){
|
||||||
$d = $p->getDescription();
|
$d = $p->getDescription();
|
||||||
$this->data["plugins"][$d->getName()] = [
|
$this->data["plugins"][$d->getName()] = [
|
||||||
"name" => $d->getName(),
|
"name" => $d->getName(),
|
||||||
@ -182,14 +205,21 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function extraData(){
|
private function extraData() : void{
|
||||||
global $argv;
|
global $argv;
|
||||||
|
|
||||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||||
$this->data["parameters"] = (array) $argv;
|
$this->data["parameters"] = (array) $argv;
|
||||||
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
|
if(($serverDotProperties = @file_get_contents($this->server->getDataPath() . "server.properties")) !== false){
|
||||||
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
|
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $serverDotProperties);
|
||||||
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
|
}else{
|
||||||
|
$this->data["server.properties"] = $serverDotProperties;
|
||||||
|
}
|
||||||
|
if(($pocketmineDotYml = @file_get_contents($this->server->getDataPath() . "pocketmine.yml")) !== false){
|
||||||
|
$this->data["pocketmine.yml"] = $pocketmineDotYml;
|
||||||
|
}else{
|
||||||
|
$this->data["pocketmine.yml"] = "";
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
$this->data["pocketmine.yml"] = "";
|
$this->data["pocketmine.yml"] = "";
|
||||||
$this->data["server.properties"] = "";
|
$this->data["server.properties"] = "";
|
||||||
@ -209,13 +239,16 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function baseCrash(){
|
private function baseCrash() : void{
|
||||||
global $lastExceptionError, $lastError;
|
global $lastExceptionError, $lastError;
|
||||||
|
|
||||||
if(isset($lastExceptionError)){
|
if(isset($lastExceptionError)){
|
||||||
$error = $lastExceptionError;
|
$error = $lastExceptionError;
|
||||||
}else{
|
}else{
|
||||||
$error = (array) error_get_last();
|
$error = error_get_last();
|
||||||
|
if($error === null){
|
||||||
|
throw new \RuntimeException("Crash error information missing - did something use exit()?");
|
||||||
|
}
|
||||||
$error["trace"] = Utils::currentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
$error["trace"] = Utils::currentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
||||||
$errorConversion = [
|
$errorConversion = [
|
||||||
E_ERROR => "E_ERROR",
|
E_ERROR => "E_ERROR",
|
||||||
@ -275,11 +308,13 @@ class CrashDump{
|
|||||||
|
|
||||||
if($this->server->getProperty("auto-report.send-code", true) !== false and file_exists($error["fullFile"])){
|
if($this->server->getProperty("auto-report.send-code", true) !== false and file_exists($error["fullFile"])){
|
||||||
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
|
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
|
||||||
|
if($file !== false){
|
||||||
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 and isset($file[$l]); ++$l){
|
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 and isset($file[$l]); ++$l){
|
||||||
$this->addLine("[" . ($l + 1) . "] " . $file[$l]);
|
$this->addLine("[" . ($l + 1) . "] " . $file[$l]);
|
||||||
$this->data["code"][$l + 1] = $file[$l];
|
$this->data["code"][$l + 1] = $file[$l];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("Backtrace:");
|
$this->addLine("Backtrace:");
|
||||||
@ -290,8 +325,8 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
|
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
|
||||||
$frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub
|
$frameCleanPath = Utils::cleanPath($filePath);
|
||||||
if(strpos($frameCleanPath, "plugins") === 0 and file_exists($filePath)){
|
if(strpos($frameCleanPath, Utils::CLEAN_PATH_SRC_PREFIX) !== 0){
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
if($crashFrame){
|
if($crashFrame){
|
||||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||||
@ -301,6 +336,7 @@ class CrashDump{
|
|||||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_INDIRECT;
|
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_INDIRECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(file_exists($filePath)){
|
||||||
$reflection = new \ReflectionClass(PluginBase::class);
|
$reflection = new \ReflectionClass(PluginBase::class);
|
||||||
$file = $reflection->getProperty("file");
|
$file = $reflection->getProperty("file");
|
||||||
$file->setAccessible(true);
|
$file->setAccessible(true);
|
||||||
@ -312,13 +348,23 @@ class CrashDump{
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generalData(){
|
private function generalData() : void{
|
||||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||||
|
$composerLibraries = [];
|
||||||
|
foreach(InstalledVersions::getInstalledPackages() as $package){
|
||||||
|
$composerLibraries[$package] = sprintf(
|
||||||
|
"%s@%s",
|
||||||
|
InstalledVersions::getPrettyVersion($package) ?? "unknown",
|
||||||
|
InstalledVersions::getReference($package) ?? "unknown"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$this->data["general"] = [];
|
$this->data["general"] = [];
|
||||||
$this->data["general"]["name"] = $this->server->getName();
|
$this->data["general"]["name"] = $this->server->getName();
|
||||||
$this->data["general"]["base_version"] = \pocketmine\BASE_VERSION;
|
$this->data["general"]["base_version"] = \pocketmine\BASE_VERSION;
|
||||||
@ -326,24 +372,38 @@ class CrashDump{
|
|||||||
$this->data["general"]["is_dev"] = \pocketmine\IS_DEVELOPMENT_BUILD;
|
$this->data["general"]["is_dev"] = \pocketmine\IS_DEVELOPMENT_BUILD;
|
||||||
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
||||||
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
|
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
|
||||||
$this->data["general"]["raklib"] = RakLib::VERSION;
|
|
||||||
$this->data["general"]["uname"] = php_uname("a");
|
$this->data["general"]["uname"] = php_uname("a");
|
||||||
$this->data["general"]["php"] = phpversion();
|
$this->data["general"]["php"] = phpversion();
|
||||||
$this->data["general"]["zend"] = zend_version();
|
$this->data["general"]["zend"] = zend_version();
|
||||||
$this->data["general"]["php_os"] = PHP_OS;
|
$this->data["general"]["php_os"] = PHP_OS;
|
||||||
$this->data["general"]["os"] = Utils::getOS();
|
$this->data["general"]["os"] = Utils::getOS();
|
||||||
|
$this->data["general"]["composer_libraries"] = $composerLibraries;
|
||||||
$this->addLine($this->server->getName() . " version: " . $version->getFullVersion(true) . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "]");
|
$this->addLine($this->server->getName() . " version: " . $version->getFullVersion(true) . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "]");
|
||||||
$this->addLine("Git commit: " . \pocketmine\GIT_COMMIT);
|
$this->addLine("Git commit: " . \pocketmine\GIT_COMMIT);
|
||||||
$this->addLine("uname -a: " . php_uname("a"));
|
$this->addLine("uname -a: " . php_uname("a"));
|
||||||
$this->addLine("PHP Version: " . phpversion());
|
$this->addLine("PHP Version: " . phpversion());
|
||||||
$this->addLine("Zend version: " . zend_version());
|
$this->addLine("Zend version: " . zend_version());
|
||||||
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
|
$this->addLine("OS: " . PHP_OS . ", " . Utils::getOS());
|
||||||
|
$this->addLine("Composer libraries: ");
|
||||||
|
foreach($composerLibraries as $library => $libraryVersion){
|
||||||
|
$this->addLine("- $library $libraryVersion");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $line
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addLine($line = ""){
|
public function addLine($line = ""){
|
||||||
fwrite($this->fp, $line . PHP_EOL);
|
fwrite($this->fp, $line . PHP_EOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function add($str){
|
public function add($str){
|
||||||
fwrite($this->fp, $str);
|
fwrite($this->fp, $str);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||||
if(defined('pocketmine\_GLOBAL_CONSTANTS_INCLUDED')){
|
if(defined('pocketmine\_GLOBAL_CONSTANTS_INCLUDED')){
|
||||||
return;
|
return;
|
||||||
|
@ -27,33 +27,21 @@ use pocketmine\permission\ServerOperator;
|
|||||||
|
|
||||||
interface IPlayer extends ServerOperator{
|
interface IPlayer extends ServerOperator{
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isOnline() : bool;
|
public function isOnline() : bool;
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getName() : string;
|
public function getName() : string;
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isBanned() : bool;
|
public function isBanned() : bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $banned
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBanned(bool $banned);
|
public function setBanned(bool $banned);
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isWhitelisted() : bool;
|
public function isWhitelisted() : bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setWhitelisted(bool $value);
|
public function setWhitelisted(bool $value);
|
||||||
|
|
||||||
@ -72,9 +60,6 @@ interface IPlayer extends ServerOperator{
|
|||||||
*/
|
*/
|
||||||
public function getLastPlayed();
|
public function getLastPlayed();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasPlayedBefore() : bool;
|
public function hasPlayedBefore() : bool;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ use pocketmine\event\server\LowMemoryEvent;
|
|||||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||||
use pocketmine\scheduler\GarbageCollectionTask;
|
use pocketmine\scheduler\GarbageCollectionTask;
|
||||||
use pocketmine\timings\Timings;
|
use pocketmine\timings\Timings;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
|
use pocketmine\utils\Process;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use function arsort;
|
use function arsort;
|
||||||
use function count;
|
use function count;
|
||||||
@ -38,6 +40,7 @@ use function fwrite;
|
|||||||
use function gc_collect_cycles;
|
use function gc_collect_cycles;
|
||||||
use function gc_disable;
|
use function gc_disable;
|
||||||
use function gc_enable;
|
use function gc_enable;
|
||||||
|
use function gc_mem_caches;
|
||||||
use function get_class;
|
use function get_class;
|
||||||
use function get_declared_classes;
|
use function get_declared_classes;
|
||||||
use function implode;
|
use function implode;
|
||||||
@ -48,6 +51,7 @@ use function is_object;
|
|||||||
use function is_resource;
|
use function is_resource;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
use function json_encode;
|
use function json_encode;
|
||||||
|
use function mb_strtoupper;
|
||||||
use function min;
|
use function min;
|
||||||
use function mkdir;
|
use function mkdir;
|
||||||
use function preg_match;
|
use function preg_match;
|
||||||
@ -56,7 +60,6 @@ use function round;
|
|||||||
use function spl_object_hash;
|
use function spl_object_hash;
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
use function strtoupper;
|
|
||||||
use function substr;
|
use function substr;
|
||||||
use const JSON_PRETTY_PRINT;
|
use const JSON_PRETTY_PRINT;
|
||||||
use const JSON_UNESCAPED_SLASHES;
|
use const JSON_UNESCAPED_SLASHES;
|
||||||
@ -115,7 +118,7 @@ class MemoryManager{
|
|||||||
$this->init();
|
$this->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function init(){
|
private function init() : void{
|
||||||
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
||||||
|
|
||||||
$defaultMemory = 1024;
|
$defaultMemory = 1024;
|
||||||
@ -125,7 +128,7 @@ class MemoryManager{
|
|||||||
if($m <= 0){
|
if($m <= 0){
|
||||||
$defaultMemory = 0;
|
$defaultMemory = 0;
|
||||||
}else{
|
}else{
|
||||||
switch(strtoupper($matches[2])){
|
switch(mb_strtoupper($matches[2])){
|
||||||
case "K":
|
case "K":
|
||||||
$defaultMemory = $m / 1024;
|
$defaultMemory = $m / 1024;
|
||||||
break;
|
break;
|
||||||
@ -169,38 +172,25 @@ class MemoryManager{
|
|||||||
gc_enable();
|
gc_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isLowMemory() : bool{
|
public function isLowMemory() : bool{
|
||||||
return $this->lowMemory;
|
return $this->lowMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function canUseChunkCache() : bool{
|
public function canUseChunkCache() : bool{
|
||||||
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
|
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the allowed chunk radius based on the current memory usage.
|
* Returns the allowed chunk radius based on the current memory usage.
|
||||||
*
|
|
||||||
* @param int $distance
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getViewDistance(int $distance) : int{
|
public function getViewDistance(int $distance) : int{
|
||||||
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? (int) min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers garbage collection and cache cleanup to try and free memory.
|
* Triggers garbage collection and cache cleanup to try and free memory.
|
||||||
*
|
*
|
||||||
* @param int $memory
|
* @return void
|
||||||
* @param int $limit
|
|
||||||
* @param bool $global
|
|
||||||
* @param int $triggerCount
|
|
||||||
*/
|
*/
|
||||||
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
|
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",
|
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
|
||||||
@ -230,13 +220,15 @@ class MemoryManager{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called every tick to update the memory manager state.
|
* Called every tick to update the memory manager state.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function check(){
|
public function check(){
|
||||||
Timings::$memoryManagerTimer->startTiming();
|
Timings::$memoryManagerTimer->startTiming();
|
||||||
|
|
||||||
if(($this->memoryLimit > 0 or $this->globalMemoryLimit > 0) and ++$this->checkTicker >= $this->checkRate){
|
if(($this->memoryLimit > 0 or $this->globalMemoryLimit > 0) and ++$this->checkTicker >= $this->checkRate){
|
||||||
$this->checkTicker = 0;
|
$this->checkTicker = 0;
|
||||||
$memory = Utils::getMemoryUsage(true);
|
$memory = Process::getAdvancedMemoryUsage();
|
||||||
$trigger = false;
|
$trigger = false;
|
||||||
if($this->memoryLimit > 0 and $memory[0] > $this->memoryLimit){
|
if($this->memoryLimit > 0 and $memory[0] > $this->memoryLimit){
|
||||||
$trigger = 0;
|
$trigger = 0;
|
||||||
@ -268,9 +260,6 @@ class MemoryManager{
|
|||||||
Timings::$memoryManagerTimer->stopTiming();
|
Timings::$memoryManagerTimer->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function triggerGarbageCollector() : int{
|
public function triggerGarbageCollector() : int{
|
||||||
Timings::$garbageCollectorTimer->startTiming();
|
Timings::$garbageCollectorTimer->startTiming();
|
||||||
|
|
||||||
@ -285,6 +274,7 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$cycles = gc_collect_cycles();
|
$cycles = gc_collect_cycles();
|
||||||
|
gc_mem_caches();
|
||||||
|
|
||||||
Timings::$garbageCollectorTimer->stopTiming();
|
Timings::$garbageCollectorTimer->stopTiming();
|
||||||
|
|
||||||
@ -294,9 +284,7 @@ class MemoryManager{
|
|||||||
/**
|
/**
|
||||||
* Dumps the server memory into the specified output folder.
|
* Dumps the server memory into the specified output folder.
|
||||||
*
|
*
|
||||||
* @param string $outputFolder
|
* @return void
|
||||||
* @param int $maxNesting
|
|
||||||
* @param int $maxStringSize
|
|
||||||
*/
|
*/
|
||||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, 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");
|
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||||
@ -314,15 +302,13 @@ class MemoryManager{
|
|||||||
* Static memory dumper accessible from any thread.
|
* Static memory dumper accessible from any thread.
|
||||||
*
|
*
|
||||||
* @param mixed $startingObject
|
* @param mixed $startingObject
|
||||||
* @param string $outputFolder
|
|
||||||
* @param int $maxNesting
|
|
||||||
* @param int $maxStringSize
|
|
||||||
* @param \Logger $logger
|
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \ReflectionException
|
* @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){
|
||||||
$hardLimit = ini_get('memory_limit');
|
$hardLimit = ini_get('memory_limit');
|
||||||
|
if($hardLimit === false) throw new AssumptionFailedError("memory_limit INI directive should always exist");
|
||||||
ini_set('memory_limit', '-1');
|
ini_set('memory_limit', '-1');
|
||||||
gc_disable();
|
gc_disable();
|
||||||
|
|
||||||
@ -356,7 +342,7 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$staticCount++;
|
$staticCount++;
|
||||||
self::continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$staticProperties[$className][$property->getName()] = self::continueDump($property->getValue(), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(count($staticProperties[$className]) === 0){
|
if(count($staticProperties[$className]) === 0){
|
||||||
@ -389,14 +375,14 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$globalCount++;
|
$globalCount++;
|
||||||
self::continueDump($value, $globalVariables[$varName], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||||
$logger->info("[Dump] Wrote $globalCount global variables");
|
$logger->info("[Dump] Wrote $globalCount global variables");
|
||||||
}
|
}
|
||||||
|
|
||||||
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
|
|
||||||
do{
|
do{
|
||||||
$continue = false;
|
$continue = false;
|
||||||
@ -422,8 +408,8 @@ class MemoryManager{
|
|||||||
"properties" => []
|
"properties" => []
|
||||||
];
|
];
|
||||||
|
|
||||||
if($reflection->getParentClass()){
|
if(($parent = $reflection->getParentClass()) !== false){
|
||||||
$info["parent"] = $reflection->getParentClass()->getName();
|
$info["parent"] = $parent->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(count($reflection->getInterfaceNames()) > 0){
|
if(count($reflection->getInterfaceNames()) > 0){
|
||||||
@ -437,21 +423,24 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$name = $property->getName();
|
$name = $property->getName();
|
||||||
if($reflection !== $original and !$property->isPublic()){
|
if($reflection !== $original){
|
||||||
|
if($property->isPrivate()){
|
||||||
$name = $reflection->getName() . ":" . $name;
|
$name = $reflection->getName() . ":" . $name;
|
||||||
|
}else{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(!$property->isPublic()){
|
if(!$property->isPublic()){
|
||||||
$property->setAccessible(true);
|
$property->setAccessible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::continueDump($property->getValue($object), $info["properties"][$name], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$info["properties"][$name] = self::continueDump($property->getValue($object), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
|
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}while($continue);
|
}while($continue);
|
||||||
|
|
||||||
$logger->info("[Dump] Wrote " . count($objects) . " objects");
|
$logger->info("[Dump] Wrote " . count($objects) . " objects");
|
||||||
@ -472,17 +461,14 @@ class MemoryManager{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $from
|
* @param mixed $from
|
||||||
* @param mixed &$data
|
* @param object[] $objects reference parameter
|
||||||
* @param object[] &$objects
|
* @param int[] $refCounts reference parameter
|
||||||
* @param int[] &$refCounts
|
*
|
||||||
* @param int $recursion
|
* @return mixed
|
||||||
* @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, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
|
||||||
if($maxNesting <= 0){
|
if($maxNesting <= 0){
|
||||||
$data = "(error) NESTING LIMIT REACHED";
|
return "(error) NESTING LIMIT REACHED";
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--$maxNesting;
|
--$maxNesting;
|
||||||
@ -498,12 +484,11 @@ class MemoryManager{
|
|||||||
$data = "(object) $hash@" . get_class($from);
|
$data = "(object) $hash@" . get_class($from);
|
||||||
}elseif(is_array($from)){
|
}elseif(is_array($from)){
|
||||||
if($recursion >= 5){
|
if($recursion >= 5){
|
||||||
$data = "(error) ARRAY RECURSION LIMIT REACHED";
|
return "(error) ARRAY RECURSION LIMIT REACHED";
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
$data = [];
|
$data = [];
|
||||||
foreach($from as $key => $value){
|
foreach($from as $key => $value){
|
||||||
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
$data[$key] = self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
||||||
}
|
}
|
||||||
}elseif(is_string($from)){
|
}elseif(is_string($from)){
|
||||||
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
||||||
@ -512,5 +497,7 @@ class MemoryManager{
|
|||||||
}else{
|
}else{
|
||||||
$data = $from;
|
$data = $from;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,6 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
/** @var CompoundTag|null */
|
/** @var CompoundTag|null */
|
||||||
private $namedtag = null;
|
private $namedtag = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Server $server
|
|
||||||
* @param string $name
|
|
||||||
*/
|
|
||||||
public function __construct(Server $server, string $name){
|
public function __construct(Server $server, string $name){
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
@ -57,6 +53,9 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Server
|
||||||
|
*/
|
||||||
public function getServer(){
|
public function getServer(){
|
||||||
return $this->server;
|
return $this->server;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine {
|
namespace pocketmine {
|
||||||
|
|
||||||
|
use Composer\InstalledVersions;
|
||||||
|
use pocketmine\utils\Git;
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
|
use pocketmine\utils\Process;
|
||||||
use pocketmine\utils\ServerKiller;
|
use pocketmine\utils\ServerKiller;
|
||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
use pocketmine\utils\Timezone;
|
use pocketmine\utils\Timezone;
|
||||||
@ -33,8 +36,12 @@ namespace pocketmine {
|
|||||||
|
|
||||||
require_once __DIR__ . '/VersionInfo.php';
|
require_once __DIR__ . '/VersionInfo.php';
|
||||||
|
|
||||||
const MIN_PHP_VERSION = "7.2.0";
|
const MIN_PHP_VERSION = "8.0.0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $message
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function critical_error($message){
|
function critical_error($message){
|
||||||
echo "[ERROR] $message" . PHP_EOL;
|
echo "[ERROR] $message" . PHP_EOL;
|
||||||
}
|
}
|
||||||
@ -67,7 +74,6 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$extensions = [
|
$extensions = [
|
||||||
"bcmath" => "BC Math",
|
|
||||||
"curl" => "cURL",
|
"curl" => "cURL",
|
||||||
"ctype" => "ctype",
|
"ctype" => "ctype",
|
||||||
"date" => "Date",
|
"date" => "Date",
|
||||||
@ -97,8 +103,8 @@ namespace pocketmine {
|
|||||||
if(substr_count($pthreads_version, ".") < 2){
|
if(substr_count($pthreads_version, ".") < 2){
|
||||||
$pthreads_version = "0.$pthreads_version";
|
$pthreads_version = "0.$pthreads_version";
|
||||||
}
|
}
|
||||||
if(version_compare($pthreads_version, "3.2.0") < 0){
|
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") > 0){
|
||||||
$messages[] = "pthreads >= 3.2.0 is required, while you have $pthreads_version.";
|
$messages[] = "pthreads ^4.0.0 is required, while you have $pthreads_version.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +122,14 @@ namespace pocketmine {
|
|||||||
return $messages;
|
return $messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Logger $logger
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function emit_performance_warnings(\Logger $logger){
|
function emit_performance_warnings(\Logger $logger){
|
||||||
|
if(PHP_DEBUG !== 0){
|
||||||
|
$logger->warning("This PHP binary was compiled in debug mode. This has a major impact on performance.");
|
||||||
|
}
|
||||||
if(extension_loaded("xdebug")){
|
if(extension_loaded("xdebug")){
|
||||||
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
||||||
}
|
}
|
||||||
@ -129,8 +142,29 @@ namespace pocketmine {
|
|||||||
if(\Phar::running(true) === ""){
|
if(\Phar::running(true) === ""){
|
||||||
$logger->warning("Non-packaged installation detected. This will degrade autoloading speed and make startup times longer.");
|
$logger->warning("Non-packaged installation detected. This will degrade autoloading speed and make startup times longer.");
|
||||||
}
|
}
|
||||||
|
if(function_exists('opcache_get_status') && ($opcacheStatus = opcache_get_status(false)) !== false){
|
||||||
|
$jitEnabled = $opcacheStatus["jit"]["on"] ?? false;
|
||||||
|
if($jitEnabled !== false){
|
||||||
|
$logger->warning(<<<'JIT_WARNING'
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------- ! WARNING ! ---------------------------------------
|
||||||
|
You're using PHP 8.0 with JIT enabled. This provides significant performance improvements.
|
||||||
|
HOWEVER, it is EXPERIMENTAL, and has already been seen to cause weird and unexpected bugs.
|
||||||
|
Proceed with caution.
|
||||||
|
If you want to report any bugs, make sure to mention that you are using PHP 8.0 with JIT.
|
||||||
|
To turn off JIT, change `opcache.jit` to `0` in your php.ini file.
|
||||||
|
-------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JIT_WARNING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function set_ini_entries(){
|
function set_ini_entries(){
|
||||||
ini_set("allow_url_fopen", '1');
|
ini_set("allow_url_fopen", '1');
|
||||||
ini_set("display_errors", '1');
|
ini_set("display_errors", '1');
|
||||||
@ -139,14 +173,19 @@ namespace pocketmine {
|
|||||||
ini_set('assert.exception', '1');
|
ini_set('assert.exception', '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function server(){
|
function server(){
|
||||||
if(count($messages = check_platform_dependencies()) > 0){
|
if(count($messages = check_platform_dependencies()) > 0){
|
||||||
echo PHP_EOL;
|
echo PHP_EOL;
|
||||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
critical_error("Selected PHP binary does not satisfy some requirements.");
|
||||||
foreach($messages as $m){
|
foreach($messages as $m){
|
||||||
echo " - $m" . PHP_EOL;
|
echo " - $m" . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
critical_error("PHP binary used: " . $binary);
|
||||||
|
critical_error("Loaded php.ini: " . (($file = php_ini_loaded_file()) !== false ? $file : "none"));
|
||||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
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;
|
echo PHP_EOL;
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -156,27 +195,20 @@ namespace pocketmine {
|
|||||||
error_reporting(-1);
|
error_reporting(-1);
|
||||||
set_ini_entries();
|
set_ini_entries();
|
||||||
|
|
||||||
if(\Phar::running(true) !== ""){
|
|
||||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
|
||||||
}else{
|
|
||||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
$opts = getopt("", ["bootstrap:"]);
|
$opts = getopt("", ["bootstrap:"]);
|
||||||
if(isset($opts["bootstrap"])){
|
if(isset($opts["bootstrap"])){
|
||||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
$bootstrap = ($real = realpath($opts["bootstrap"])) !== false ? $real : $opts["bootstrap"];
|
||||||
}else{
|
}else{
|
||||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
$bootstrap = dirname(__FILE__, 3) . '/vendor/autoload.php';
|
||||||
}
|
}
|
||||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
|
||||||
|
|
||||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
if($bootstrap === false or !is_file($bootstrap)){
|
||||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
|
||||||
}else{
|
|
||||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||||
|
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||||
|
|
||||||
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||||
|
|
||||||
@ -186,12 +218,7 @@ namespace pocketmine {
|
|||||||
$gitHash = str_repeat("00", 20);
|
$gitHash = str_repeat("00", 20);
|
||||||
|
|
||||||
if(\Phar::running(true) === ""){
|
if(\Phar::running(true) === ""){
|
||||||
if(Utils::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
$gitHash = Git::getRepositoryStatePretty(\pocketmine\PATH);
|
||||||
$gitHash = trim($out);
|
|
||||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
|
||||||
$gitHash .= "-dirty";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
$phar = new \Phar(\Phar::running(false));
|
$phar = new \Phar(\Phar::running(false));
|
||||||
$meta = $phar->getMetadata();
|
$meta = $phar->getMetadata();
|
||||||
@ -202,7 +229,18 @@ namespace pocketmine {
|
|||||||
|
|
||||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||||
|
|
||||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
$composerGitHash = InstalledVersions::getReference('pocketmine/pocketmine-mp');
|
||||||
|
if($composerGitHash !== null){
|
||||||
|
$currentGitHash = explode("-", \pocketmine\GIT_COMMIT)[0];
|
||||||
|
if($currentGitHash !== $composerGitHash){
|
||||||
|
critical_error("Composer dependencies and/or autoloader are out of sync.");
|
||||||
|
critical_error("- Current revision is $currentGitHash");
|
||||||
|
critical_error("- Composer dependencies were last synchronized for revision $composerGitHash");
|
||||||
|
critical_error("Out-of-sync Composer dependencies may result in crashes and classes not being found.");
|
||||||
|
critical_error("Please synchronize Composer dependencies before running the server.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||||
|
|
||||||
@ -213,7 +251,12 @@ namespace pocketmine {
|
|||||||
mkdir(\pocketmine\DATA, 0777, true);
|
mkdir(\pocketmine\DATA, 0777, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
define('pocketmine\LOCK_FILE', fopen(\pocketmine\DATA . 'server.lock', "a+b"));
|
$lockFile = fopen(\pocketmine\DATA . 'server.lock', "a+b");
|
||||||
|
if($lockFile === false){
|
||||||
|
critical_error("Unable to open server.lock file. Please check that the current user has read/write permissions to it.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
define('pocketmine\LOCK_FILE', $lockFile);
|
||||||
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
|
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
|
//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
|
//other server wrote its PID and released exclusive lock before we get our lock
|
||||||
@ -261,7 +304,6 @@ namespace pocketmine {
|
|||||||
|
|
||||||
//TODO: move this to a Server field
|
//TODO: move this to a Server field
|
||||||
define('pocketmine\START_TIME', microtime(true));
|
define('pocketmine\START_TIME', microtime(true));
|
||||||
ThreadManager::init();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||||
@ -279,7 +321,7 @@ namespace pocketmine {
|
|||||||
|
|
||||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||||
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
||||||
Utils::kill(getmypid());
|
Process::kill(Process::pid());
|
||||||
}
|
}
|
||||||
}while(false);
|
}while(false);
|
||||||
|
|
||||||
@ -288,10 +330,16 @@ namespace pocketmine {
|
|||||||
|
|
||||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||||
|
|
||||||
|
if(!flock(\pocketmine\LOCK_FILE, LOCK_UN)){
|
||||||
|
critical_error("Failed to release the server.lock file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!fclose(\pocketmine\LOCK_FILE)){
|
||||||
|
critical_error("Could not close server.lock resource.");
|
||||||
|
}
|
||||||
|
|
||||||
exit($exitCode);
|
exit($exitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
|
||||||
\pocketmine\server();
|
\pocketmine\server();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
|
use const PTHREADS_INHERIT_ALL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class must be extended by all custom threading classes
|
* This class must be extended by all custom threading classes
|
||||||
*/
|
*/
|
||||||
@ -33,12 +35,19 @@ abstract class Thread extends \Thread{
|
|||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
protected $composerAutoloaderPath;
|
protected $composerAutoloaderPath;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
protected $isKilled = false;
|
protected $isKilled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \ClassLoader|null
|
||||||
|
*/
|
||||||
public function getClassLoader(){
|
public function getClassLoader(){
|
||||||
return $this->classLoader;
|
return $this->classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setClassLoader(\ClassLoader $loader = null){
|
public function setClassLoader(\ClassLoader $loader = null){
|
||||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||||
|
|
||||||
@ -54,6 +63,8 @@ abstract class Thread extends \Thread{
|
|||||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||||
* (unless you are using a custom autoloader).
|
* (unless you are using a custom autoloader).
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function registerClassLoader(){
|
public function registerClassLoader(){
|
||||||
if($this->composerAutoloaderPath !== null){
|
if($this->composerAutoloaderPath !== null){
|
||||||
@ -64,7 +75,10 @@ abstract class Thread extends \Thread{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function start(int $options = PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
if($this->getClassLoader() === null){
|
if($this->getClassLoader() === null){
|
||||||
@ -75,6 +89,8 @@ abstract class Thread extends \Thread{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function quit(){
|
public function quit(){
|
||||||
$this->isKilled = true;
|
$this->isKilled = true;
|
||||||
|
@ -28,9 +28,13 @@ use function spl_object_hash;
|
|||||||
|
|
||||||
class ThreadManager extends \Volatile{
|
class ThreadManager extends \Volatile{
|
||||||
|
|
||||||
/** @var ThreadManager */
|
/** @var ThreadManager|null */
|
||||||
private static $instance = null;
|
private static $instance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function init(){
|
public static function init(){
|
||||||
self::$instance = new ThreadManager();
|
self::$instance = new ThreadManager();
|
||||||
}
|
}
|
||||||
@ -39,24 +43,31 @@ class ThreadManager extends \Volatile{
|
|||||||
* @return ThreadManager
|
* @return ThreadManager
|
||||||
*/
|
*/
|
||||||
public static function getInstance(){
|
public static function getInstance(){
|
||||||
|
if(self::$instance === null){
|
||||||
|
self::$instance = new ThreadManager();
|
||||||
|
}
|
||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Worker|Thread $thread
|
* @param Worker|Thread $thread
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add($thread){
|
public function add($thread){
|
||||||
if($thread instanceof Thread or $thread instanceof Worker){
|
if($thread instanceof Thread or $thread instanceof Worker){
|
||||||
$this->{spl_object_hash($thread)} = $thread;
|
$this[spl_object_hash($thread)] = $thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Worker|Thread $thread
|
* @param Worker|Thread $thread
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function remove($thread){
|
public function remove($thread){
|
||||||
if($thread instanceof Thread or $thread instanceof Worker){
|
if($thread instanceof Thread or $thread instanceof Worker){
|
||||||
unset($this->{spl_object_hash($thread)});
|
unset($this[spl_object_hash($thread)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,12 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
|
use function defined;
|
||||||
|
|
||||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||||
// TODO: drop this file and use a final class with constants
|
// TODO: drop this file and use a final class with constants
|
||||||
if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
||||||
@ -28,8 +32,8 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
|||||||
}
|
}
|
||||||
const _VERSION_INFO_INCLUDED = true;
|
const _VERSION_INFO_INCLUDED = true;
|
||||||
|
|
||||||
|
|
||||||
const NAME = "PocketMine-MP";
|
const NAME = "PocketMine-MP";
|
||||||
const BASE_VERSION = "3.11.2";
|
const BASE_VERSION = "3.25.3";
|
||||||
const IS_DEVELOPMENT_BUILD = false;
|
const IS_DEVELOPMENT_BUILD = false;
|
||||||
const BUILD_NUMBER = 0;
|
const BUILD_NUMBER = 0;
|
||||||
|
const BUILD_CHANNEL = "stable";
|
||||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
|
use const PTHREADS_INHERIT_ALL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class must be extended by all custom threading classes
|
* This class must be extended by all custom threading classes
|
||||||
*/
|
*/
|
||||||
@ -33,12 +35,19 @@ abstract class Worker extends \Worker{
|
|||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
protected $composerAutoloaderPath;
|
protected $composerAutoloaderPath;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
protected $isKilled = false;
|
protected $isKilled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \ClassLoader|null
|
||||||
|
*/
|
||||||
public function getClassLoader(){
|
public function getClassLoader(){
|
||||||
return $this->classLoader;
|
return $this->classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setClassLoader(\ClassLoader $loader = null){
|
public function setClassLoader(\ClassLoader $loader = null){
|
||||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||||
|
|
||||||
@ -54,6 +63,8 @@ abstract class Worker extends \Worker{
|
|||||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||||
* (unless you are using a custom autoloader).
|
* (unless you are using a custom autoloader).
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function registerClassLoader(){
|
public function registerClassLoader(){
|
||||||
if($this->composerAutoloaderPath !== null){
|
if($this->composerAutoloaderPath !== null){
|
||||||
@ -64,7 +75,10 @@ abstract class Worker extends \Worker{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function start(int $options = PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
if($this->getClassLoader() === null){
|
if($this->getClassLoader() === null){
|
||||||
@ -75,11 +89,13 @@ abstract class Worker extends \Worker{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function quit(){
|
public function quit(){
|
||||||
$this->isKilled = true;
|
$this->isKilled = true;
|
||||||
|
|
||||||
if($this->isRunning()){
|
if(!$this->isShutdown()){
|
||||||
while($this->unstack() !== null);
|
while($this->unstack() !== null);
|
||||||
$this->notify();
|
$this->notify();
|
||||||
$this->shutdown();
|
$this->shutdown();
|
||||||
|
@ -26,7 +26,6 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Air block
|
* Air block
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +78,7 @@ class Anvil extends Fallable{
|
|||||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
$inset = 0.125;
|
$inset = 0.125;
|
||||||
|
|
||||||
if($this->meta & 0x01){ //east/west
|
if(($this->meta & 0x01) !== 0){ //east/west
|
||||||
return new AxisAlignedBB(
|
return new AxisAlignedBB(
|
||||||
$this->x,
|
$this->x,
|
||||||
$this->y,
|
$this->y,
|
||||||
@ -110,6 +110,6 @@ class Anvil extends Fallable{
|
|||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
|
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
|
||||||
$this->meta = $this->getVariant() | $direction;
|
$this->meta = $this->getVariant() | $direction;
|
||||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
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)){
|
if(!$blockReplace->getSide(Vector3::SIDE_DOWN)->isTransparent() and $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true)){
|
||||||
$this->tryReconnect();
|
$this->tryReconnect();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -99,6 +99,11 @@ abstract class BaseRail extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int[] $connections
|
||||||
|
* @param int[][] $lookup
|
||||||
|
* @phpstan-param array<int, list<int>> $lookup
|
||||||
|
*/
|
||||||
protected static function searchState(array $connections, array $lookup) : int{
|
protected static function searchState(array $connections, array $lookup) : int{
|
||||||
$meta = array_search($connections, $lookup, true);
|
$meta = array_search($connections, $lookup, true);
|
||||||
if($meta === false){
|
if($meta === false){
|
||||||
@ -114,9 +119,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
/**
|
/**
|
||||||
* Returns a meta value for the rail with the given connections.
|
* Returns a meta value for the rail with the given connections.
|
||||||
*
|
*
|
||||||
* @param array $connections
|
* @param int[] $connections
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException if no state matches the given connections
|
* @throws \InvalidArgumentException if no state matches the given connections
|
||||||
*/
|
*/
|
||||||
@ -164,6 +167,12 @@ abstract class BaseRail extends Flowable{
|
|||||||
return $connections;
|
return $connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int[] $constraints
|
||||||
|
*
|
||||||
|
* @return true[]
|
||||||
|
* @phpstan-return array<int, true>
|
||||||
|
*/
|
||||||
private function getPossibleConnectionDirections(array $constraints) : array{
|
private function getPossibleConnectionDirections(array $constraints) : array{
|
||||||
switch(count($constraints)){
|
switch(count($constraints)){
|
||||||
case 0:
|
case 0:
|
||||||
@ -188,6 +197,10 @@ abstract class BaseRail extends Flowable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true[]
|
||||||
|
* @phpstan-return array<int, true>
|
||||||
|
*/
|
||||||
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
|
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
|
||||||
$opposite = Vector3::getOppositeSide($constraint & ~self::FLAG_ASCEND);
|
$opposite = Vector3::getOppositeSide($constraint & ~self::FLAG_ASCEND);
|
||||||
|
|
||||||
@ -247,6 +260,9 @@ abstract class BaseRail extends Flowable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int[] $connections
|
||||||
|
*/
|
||||||
private function updateState(array $connections) : void{
|
private function updateState(array $connections) : void{
|
||||||
if(count($connections) === 1){
|
if(count($connections) === 1){
|
||||||
$connections[] = Vector3::getOppositeSide($connections[0] & ~self::FLAG_ASCEND);
|
$connections[] = Vector3::getOppositeSide($connections[0] & ~self::FLAG_ASCEND);
|
||||||
@ -263,7 +279,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
|
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
|
||||||
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
|
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
|
||||||
)){
|
)){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,13 +69,13 @@ class Bed extends Transparent{
|
|||||||
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isOccupied() : bool{
|
public function isOccupied() : bool{
|
||||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setOccupied(bool $occupied = true){
|
public function setOccupied(bool $occupied = true){
|
||||||
if($occupied){
|
if($occupied){
|
||||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
$this->meta |= self::BITFLAG_OCCUPIED;
|
||||||
@ -83,19 +83,13 @@ class Bed extends Transparent{
|
|||||||
$this->meta &= ~self::BITFLAG_OCCUPIED;
|
$this->meta &= ~self::BITFLAG_OCCUPIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getLevel()->setBlock($this, $this, false, false);
|
$this->getLevelNonNull()->setBlock($this, $this, false, false);
|
||||||
|
|
||||||
if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){
|
if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){
|
||||||
$other->setOccupied($occupied);
|
$other->setOccupied($occupied);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $meta
|
|
||||||
* @param bool $isHead
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
|
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
|
||||||
$rotation = $meta & 0x03;
|
$rotation = $meta & 0x03;
|
||||||
$side = -1;
|
$side = -1;
|
||||||
@ -122,9 +116,6 @@ class Bed extends Transparent{
|
|||||||
return $side;
|
return $side;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Bed|null
|
|
||||||
*/
|
|
||||||
public function getOtherHalf() : ?Bed{
|
public function getOtherHalf() : ?Bed{
|
||||||
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
|
$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))){
|
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
|
||||||
@ -146,7 +137,7 @@ class Bed extends Transparent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
|
$time = $this->getLevelNonNull()->getTimeOfDay();
|
||||||
|
|
||||||
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
|
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
|
||||||
|
|
||||||
@ -177,11 +168,11 @@ class Bed extends Transparent{
|
|||||||
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
||||||
$next = $this->getSide(self::getOtherHalfSide($meta));
|
$next = $this->getSide(self::getOtherHalfSide($meta));
|
||||||
if($next->canBeReplaced() and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
if($next->canBeReplaced() and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
|
||||||
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
|
$this->getLevelNonNull()->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->getLevelNonNull(), TileBed::createNBT($this, $face, $item, $player));
|
||||||
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player));
|
Tile::createTile(Tile::BED, $this->getLevelNonNull(), TileBed::createNBT($next, $face, $item, $player));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -203,7 +194,7 @@ class Bed extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function getItem() : Item{
|
private function getItem() : Item{
|
||||||
$tile = $this->getLevel()->getTile($this);
|
$tile = $this->getLevelNonNull()->getTile($this);
|
||||||
if($tile instanceof TileBed){
|
if($tile instanceof TileBed){
|
||||||
return ItemFactory::get($this->getItemId(), $tile->getColor());
|
return ItemFactory::get($this->getItemId(), $tile->getColor());
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ use pocketmine\math\RayTraceResult;
|
|||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\metadata\Metadatable;
|
use pocketmine\metadata\Metadatable;
|
||||||
use pocketmine\metadata\MetadataValue;
|
use pocketmine\metadata\MetadataValue;
|
||||||
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\plugin\Plugin;
|
use pocketmine\plugin\Plugin;
|
||||||
use function array_merge;
|
use function array_merge;
|
||||||
@ -50,12 +50,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* Returns a new Block instance with the specified ID, meta and position.
|
* Returns a new Block instance with the specified ID, meta and position.
|
||||||
*
|
*
|
||||||
* This function redirects to {@link BlockFactory#get}.
|
* 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{
|
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
|
||||||
return BlockFactory::get($id, $meta, $pos);
|
return BlockFactory::get($id, $meta, $pos);
|
||||||
@ -73,7 +67,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/** @var AxisAlignedBB|null */
|
/** @var AxisAlignedBB|null */
|
||||||
protected $boundingBox = null;
|
protected $boundingBox = null;
|
||||||
|
|
||||||
|
|
||||||
/** @var AxisAlignedBB[]|null */
|
/** @var AxisAlignedBB[]|null */
|
||||||
protected $collisionBoxes = null;
|
protected $collisionBoxes = null;
|
||||||
|
|
||||||
@ -90,16 +83,10 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
$this->itemId = $itemId;
|
$this->itemId = $itemId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return $this->fallbackName ?? "Unknown";
|
return $this->fallbackName ?? "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
final public function getId() : int{
|
final public function getId() : int{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
@ -107,8 +94,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* Returns the ID of the item form of the block.
|
* 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).
|
* Used for drops for blocks (some blocks such as doors have a different item ID).
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getItemId() : int{
|
public function getItemId() : int{
|
||||||
return $this->itemId ?? $this->getId();
|
return $this->itemId ?? $this->getId();
|
||||||
@ -116,22 +101,15 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getRuntimeId() : int{
|
public function getRuntimeId() : int{
|
||||||
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getDamage());
|
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getDamage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
final public function getDamage() : int{
|
final public function getDamage() : int{
|
||||||
return $this->meta;
|
return $this->meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $meta
|
|
||||||
*/
|
|
||||||
final public function setDamage(int $meta) : void{
|
final public function setDamage(int $meta) : void{
|
||||||
if($meta < 0 or $meta > 0xf){
|
if($meta < 0 or $meta > 0xf){
|
||||||
throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta");
|
throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta");
|
||||||
@ -145,8 +123,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
*
|
*
|
||||||
* If your block should not have any meta value when it's dropped as an item, override this to return 0 in
|
* If your block should not have any meta value when it's dropped as an item, override this to return 0 in
|
||||||
* descendent classes.
|
* descendent classes.
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return -1;
|
return -1;
|
||||||
@ -154,24 +130,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the block meta, stripped of non-variant flags.
|
* Returns the block meta, stripped of non-variant flags.
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getVariant() : int{
|
public function getVariant() : int{
|
||||||
return $this->meta & $this->getVariantBitmask();
|
return $this->meta & $this->getVariantBitmask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AKA: Block->isPlaceable
|
* AKA: Block->isPlaceable
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function canBePlaced() : bool{
|
public function canBePlaced() : bool{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function canBeReplaced() : bool{
|
public function canBeReplaced() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -182,34 +152,18 @@ 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.
|
* 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
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : 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);
|
return $this->getLevelNonNull()->setBlock($this, $this, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the block can be broken with an specific Item
|
* Returns if the block can be broken with an specific Item
|
||||||
*
|
|
||||||
* @param Item $item
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isBreakable(Item $item) : bool{
|
public function isBreakable(Item $item) : bool{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return BlockToolType::TYPE_NONE;
|
return BlockToolType::TYPE_NONE;
|
||||||
}
|
}
|
||||||
@ -223,8 +177,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
||||||
*
|
*
|
||||||
* @see Item::getBlockToolHarvestLevel()
|
* @see Item::getBlockToolHarvestLevel()
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getToolHarvestLevel() : int{
|
public function getToolHarvestLevel() : int{
|
||||||
return 0;
|
return 0;
|
||||||
@ -236,10 +188,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
*
|
*
|
||||||
* In most cases this is also used to determine whether block drops should be created or not, except in some
|
* 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.
|
* special cases such as vines.
|
||||||
*
|
|
||||||
* @param Item $tool
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isCompatibleWithTool(Item $tool) : bool{
|
public function isCompatibleWithTool(Item $tool) : bool{
|
||||||
if($this->getHardness() < 0){
|
if($this->getHardness() < 0){
|
||||||
@ -254,23 +202,14 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Do the actions needed so the block is broken with the Item
|
* Do the actions needed so the block is broken with the Item
|
||||||
*
|
|
||||||
* @param Item $item
|
|
||||||
* @param Player|null $player
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
public function onBreak(Item $item, Player $player = null) : bool{
|
||||||
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
return $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the seconds that this block takes to be broken using an specific Item
|
* 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
|
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||||
*/
|
*/
|
||||||
public function getBreakTime(Item $item) : float{
|
public function getBreakTime(Item $item) : float{
|
||||||
@ -300,8 +239,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether random block updates will be done on this block.
|
* Returns whether random block updates will be done on this block.
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function ticksRandomly() : bool{
|
public function ticksRandomly() : bool{
|
||||||
return false;
|
return false;
|
||||||
@ -324,11 +261,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Do actions when activated by Item. Returns if it has done anything
|
* Do actions when activated by Item. Returns if it has done anything
|
||||||
*
|
|
||||||
* @param Item $item
|
|
||||||
* @param Player|null $player
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
return false;
|
return false;
|
||||||
@ -336,7 +268,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a base value used to compute block break times.
|
* Returns a base value used to compute block break times.
|
||||||
* @return float
|
|
||||||
*/
|
*/
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 10;
|
return 10;
|
||||||
@ -344,15 +275,11 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||||
* @return float
|
|
||||||
*/
|
*/
|
||||||
public function getBlastResistance() : float{
|
public function getBlastResistance() : float{
|
||||||
return $this->getHardness() * 5;
|
return $this->getHardness() * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getFrictionFactor() : float{
|
public function getFrictionFactor() : float{
|
||||||
return 0.6;
|
return 0.6;
|
||||||
}
|
}
|
||||||
@ -380,16 +307,11 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* Examples of this behaviour include leaves and cobwebs.
|
* Examples of this behaviour include leaves and cobwebs.
|
||||||
*
|
*
|
||||||
* Light-diffusing blocks are included by the heightmap.
|
* Light-diffusing blocks are included by the heightmap.
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function diffusesSkyLight() : bool{
|
public function diffusesSkyLight() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isTransparent() : bool{
|
public function isTransparent() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -400,7 +322,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* AKA: Block->isFlowable
|
* AKA: Block->isFlowable
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function canBeFlowedInto() : bool{
|
public function canBeFlowedInto() : bool{
|
||||||
return false;
|
return false;
|
||||||
@ -416,21 +337,17 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether entities can climb up this block.
|
* Returns whether entities can climb up this block.
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function canClimb() : bool{
|
public function canClimb() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
|
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the block position to a new Position object
|
* Sets the block position to a new Position object
|
||||||
*
|
|
||||||
* @param Position $v
|
|
||||||
*/
|
*/
|
||||||
final public function position(Position $v) : void{
|
final public function position(Position $v) : void{
|
||||||
$this->x = (int) $v->x;
|
$this->x = (int) $v->x;
|
||||||
@ -443,8 +360,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* Returns an array of Item objects to be dropped
|
* Returns an array of Item objects to be dropped
|
||||||
*
|
*
|
||||||
* @param Item $item
|
|
||||||
*
|
|
||||||
* @return Item[]
|
* @return Item[]
|
||||||
*/
|
*/
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
@ -462,8 +377,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
|
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
|
||||||
*
|
|
||||||
* @return Item[]
|
* @return Item[]
|
||||||
*/
|
*/
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
@ -475,8 +388,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
|
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
|
||||||
*
|
|
||||||
* @return Item[]
|
* @return Item[]
|
||||||
*/
|
*/
|
||||||
public function getSilkTouchDrops(Item $item) : array{
|
public function getSilkTouchDrops(Item $item) : array{
|
||||||
@ -487,10 +398,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns how much XP will be dropped by breaking this block with the given item.
|
* Returns how much XP will be dropped by breaking this block with the given item.
|
||||||
*
|
|
||||||
* @param Item $item
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getXpDropForTool(Item $item) : 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->isCompatibleWithTool($item)){
|
||||||
@ -502,8 +409,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns how much XP this block will drop when broken with an appropriate tool.
|
* Returns how much XP this block will drop when broken with an appropriate tool.
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
protected function getXpDropAmount() : int{
|
protected function getXpDropAmount() : int{
|
||||||
return 0;
|
return 0;
|
||||||
@ -512,8 +417,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
|
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
|
||||||
* themselves anyway, this is implicitly true.
|
* themselves anyway, this is implicitly true.
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isAffectedBySilkTouch() : bool{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return true;
|
return true;
|
||||||
@ -521,7 +424,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the item that players will equip when middle-clicking on this block.
|
* Returns the item that players will equip when middle-clicking on this block.
|
||||||
* @return Item
|
|
||||||
*/
|
*/
|
||||||
public function getPickedItem() : Item{
|
public function getPickedItem() : Item{
|
||||||
return ItemFactory::get($this->getItemId(), $this->getVariant());
|
return ItemFactory::get($this->getItemId(), $this->getVariant());
|
||||||
@ -529,7 +431,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time in ticks which the block will fuel a furnace for.
|
* Returns the time in ticks which the block will fuel a furnace for.
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
return 0;
|
return 0;
|
||||||
@ -538,8 +439,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
||||||
* fire.
|
* fire.
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getFlameEncouragement() : int{
|
public function getFlameEncouragement() : int{
|
||||||
return 0;
|
return 0;
|
||||||
@ -547,8 +446,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the base flammability of this block. Higher values lead to the block burning away more quickly.
|
* Returns the base flammability of this block. Higher values lead to the block burning away more quickly.
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getFlammability() : int{
|
public function getFlammability() : int{
|
||||||
return 0;
|
return 0;
|
||||||
@ -556,8 +453,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether fire lit on this block will burn indefinitely.
|
* Returns whether fire lit on this block will burn indefinitely.
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function burnsForever() : bool{
|
public function burnsForever() : bool{
|
||||||
return false;
|
return false;
|
||||||
@ -565,8 +460,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this block can catch fire.
|
* Returns whether this block can catch fire.
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isFlammable() : bool{
|
public function isFlammable() : bool{
|
||||||
return $this->getFlammability() > 0;
|
return $this->getFlammability() > 0;
|
||||||
@ -582,14 +475,11 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* Returns the Block on the side $side, works like Vector3::getSide()
|
* Returns the Block on the side $side, works like Vector3::getSide()
|
||||||
*
|
*
|
||||||
* @param int $side
|
|
||||||
* @param int $step
|
|
||||||
*
|
|
||||||
* @return Block
|
* @return Block
|
||||||
*/
|
*/
|
||||||
public function getSide(int $side, int $step = 1){
|
public function getSide(int $side, int $step = 1){
|
||||||
if($this->isValid()){
|
if($this->isValid()){
|
||||||
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
|
return $this->getLevelNonNull()->getBlock(Vector3::getSide($side, $step));
|
||||||
}
|
}
|
||||||
|
|
||||||
return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));
|
return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));
|
||||||
@ -643,10 +533,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for collision against an AxisAlignedBB
|
* Checks for collision against an AxisAlignedBB
|
||||||
*
|
|
||||||
* @param AxisAlignedBB $bb
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||||
foreach($this->getCollisionBoxes() as $bb2){
|
foreach($this->getCollisionBoxes() as $bb2){
|
||||||
@ -658,9 +544,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Entity $entity
|
|
||||||
*/
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -680,16 +563,13 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @return AxisAlignedBB[]
|
* @return AxisAlignedBB[]
|
||||||
*/
|
*/
|
||||||
protected function recalculateCollisionBoxes() : array{
|
protected function recalculateCollisionBoxes() : array{
|
||||||
if($bb = $this->recalculateBoundingBox()){
|
if(($bb = $this->recalculateBoundingBox()) !== null){
|
||||||
return [$bb];
|
return [$bb];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return AxisAlignedBB|null
|
|
||||||
*/
|
|
||||||
public function getBoundingBox() : ?AxisAlignedBB{
|
public function getBoundingBox() : ?AxisAlignedBB{
|
||||||
if($this->boundingBox === null){
|
if($this->boundingBox === null){
|
||||||
$this->boundingBox = $this->recalculateBoundingBox();
|
$this->boundingBox = $this->recalculateBoundingBox();
|
||||||
@ -697,9 +577,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return $this->boundingBox;
|
return $this->boundingBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return AxisAlignedBB|null
|
|
||||||
*/
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
return new AxisAlignedBB(
|
return new AxisAlignedBB(
|
||||||
$this->x,
|
$this->x,
|
||||||
@ -720,12 +597,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
$this->collisionBoxes = null;
|
$this->collisionBoxes = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Vector3 $pos1
|
|
||||||
* @param Vector3 $pos2
|
|
||||||
*
|
|
||||||
* @return RayTraceResult|null
|
|
||||||
*/
|
|
||||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||||
$bbs = $this->getCollisionBoxes();
|
$bbs = $this->getCollisionBoxes();
|
||||||
if(count($bbs) === 0){
|
if(count($bbs) === 0){
|
||||||
|
@ -25,30 +25,54 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Position;
|
use pocketmine\level\Position;
|
||||||
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
|
||||||
use function min;
|
use function min;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages block registration and instance creation
|
* Manages block registration and instance creation
|
||||||
*/
|
*/
|
||||||
class BlockFactory{
|
class BlockFactory{
|
||||||
/** @var \SplFixedArray<Block> */
|
/**
|
||||||
private static $fullList = null;
|
* @var \SplFixedArray|Block[]
|
||||||
|
* @phpstan-var \SplFixedArray<Block>
|
||||||
|
*/
|
||||||
|
private static $fullList;
|
||||||
|
|
||||||
/** @var \SplFixedArray<bool> */
|
/**
|
||||||
public static $solid = null;
|
* @var \SplFixedArray|bool[]
|
||||||
/** @var \SplFixedArray<bool> */
|
* @phpstan-var \SplFixedArray<bool>
|
||||||
public static $transparent = null;
|
*/
|
||||||
/** @var \SplFixedArray<float> */
|
public static $solid;
|
||||||
public static $hardness = null;
|
/**
|
||||||
/** @var \SplFixedArray<int> */
|
* @var \SplFixedArray|bool[]
|
||||||
public static $light = null;
|
* @phpstan-var \SplFixedArray<bool>
|
||||||
/** @var \SplFixedArray<int> */
|
*/
|
||||||
public static $lightFilter = null;
|
public static $transparent;
|
||||||
/** @var \SplFixedArray<bool> */
|
/**
|
||||||
public static $diffusesSkyLight = null;
|
* @var \SplFixedArray|float[]
|
||||||
/** @var \SplFixedArray<float> */
|
* @phpstan-var \SplFixedArray<float>
|
||||||
public static $blastResistance = null;
|
*/
|
||||||
|
public static $hardness;
|
||||||
|
/**
|
||||||
|
* @var \SplFixedArray|int[]
|
||||||
|
* @phpstan-var \SplFixedArray<int>
|
||||||
|
*/
|
||||||
|
public static $light;
|
||||||
|
/**
|
||||||
|
* @var \SplFixedArray|int[]
|
||||||
|
* @phpstan-var \SplFixedArray<int>
|
||||||
|
*/
|
||||||
|
public static $lightFilter;
|
||||||
|
/**
|
||||||
|
* @var \SplFixedArray|bool[]
|
||||||
|
* @phpstan-var \SplFixedArray<bool>
|
||||||
|
*/
|
||||||
|
public static $diffusesSkyLight;
|
||||||
|
/**
|
||||||
|
* @var \SplFixedArray|float[]
|
||||||
|
* @phpstan-var \SplFixedArray<float>
|
||||||
|
*/
|
||||||
|
public static $blastResistance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
||||||
@ -334,7 +358,6 @@ class BlockFactory{
|
|||||||
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
|
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
|
||||||
* will not automatically appear there.
|
* will not automatically appear there.
|
||||||
*
|
*
|
||||||
* @param Block $block
|
|
||||||
* @param bool $override Whether to override existing registrations
|
* @param bool $override Whether to override existing registrations
|
||||||
*
|
*
|
||||||
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
|
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
|
||||||
@ -364,12 +387,6 @@ class BlockFactory{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Block instance with the specified ID, meta and position.
|
* Returns a new Block instance with the specified ID, meta and position.
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* @param int $meta
|
|
||||||
* @param Position $pos
|
|
||||||
*
|
|
||||||
* @return Block
|
|
||||||
*/
|
*/
|
||||||
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
|
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
|
||||||
if($meta < 0 or $meta > 0xf){
|
if($meta < 0 or $meta > 0xf){
|
||||||
@ -398,7 +415,7 @@ class BlockFactory{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* @return \SplFixedArray
|
* @phpstan-return \SplFixedArray<Block>
|
||||||
*/
|
*/
|
||||||
public static function getBlockStatesArray() : \SplFixedArray{
|
public static function getBlockStatesArray() : \SplFixedArray{
|
||||||
return self::$fullList;
|
return self::$fullList;
|
||||||
@ -406,10 +423,6 @@ class BlockFactory{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a specified block ID is already registered in the block factory.
|
* Returns whether a specified block ID is already registered in the block factory.
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public static function isRegistered(int $id) : bool{
|
public static function isRegistered(int $id) : bool{
|
||||||
$b = self::$fullList[$id << 4];
|
$b = self::$fullList[$id << 4];
|
||||||
@ -419,11 +432,6 @@ class BlockFactory{
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* @param int $meta
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||||
return RuntimeBlockMapping::toStaticRuntimeId($id, $meta);
|
return RuntimeBlockMapping::toStaticRuntimeId($id, $meta);
|
||||||
@ -433,8 +441,6 @@ class BlockFactory{
|
|||||||
* @deprecated
|
* @deprecated
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
* @param int $runtimeId
|
|
||||||
*
|
|
||||||
* @return int[] [id, meta]
|
* @return int[] [id, meta]
|
||||||
*/
|
*/
|
||||||
public static function fromStaticRuntimeId(int $runtimeId) : array{
|
public static function fromStaticRuntimeId(int $runtimeId) : array{
|
||||||
|
@ -35,5 +35,6 @@ interface BlockToolType{
|
|||||||
public const TYPE_PICKAXE = 1 << 2;
|
public const TYPE_PICKAXE = 1 << 2;
|
||||||
public const TYPE_AXE = 1 << 3;
|
public const TYPE_AXE = 1 << 3;
|
||||||
public const TYPE_SHEARS = 1 << 4;
|
public const TYPE_SHEARS = 1 << 4;
|
||||||
|
public const TYPE_HOE = 1 << 5;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ class BoneBlock extends Solid{
|
|||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
||||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
|
@ -68,18 +68,18 @@ class BurningFurnace extends Solid{
|
|||||||
3 => 3
|
3 => 3
|
||||||
];
|
];
|
||||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player));
|
Tile::createTile(Tile::FURNACE, $this->getLevelNonNull(), TileFurnace::createNBT($this, $face, $item, $player));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$furnace = $this->getLevel()->getTile($this);
|
$furnace = $this->getLevelNonNull()->getTile($this);
|
||||||
if(!($furnace instanceof TileFurnace)){
|
if(!($furnace instanceof TileFurnace)){
|
||||||
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevelNonNull(), TileFurnace::createNBT($this));
|
||||||
if(!($furnace instanceof TileFurnace)){
|
if(!($furnace instanceof TileFurnace)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -72,12 +72,12 @@ class Cactus extends Transparent{
|
|||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}else{
|
}else{
|
||||||
for($side = 2; $side <= 5; ++$side){
|
for($side = 2; $side <= 5; ++$side){
|
||||||
$b = $this->getSide($side);
|
$b = $this->getSide($side);
|
||||||
if($b->isSolid()){
|
if($b->isSolid()){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,23 +92,23 @@ class Cactus extends Transparent{
|
|||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
||||||
if($this->meta === 0x0f){
|
if($this->meta === 0x0f){
|
||||||
for($y = 1; $y < 3; ++$y){
|
for($y = 1; $y < 3; ++$y){
|
||||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
$b = $this->getLevelNonNull()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||||
if($b->getId() === self::AIR){
|
if($b->getId() === self::AIR){
|
||||||
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
|
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if($ev->isCancelled()){
|
if($ev->isCancelled()){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
$this->getLevelNonNull()->setBlock($b, $ev->getNewState(), true);
|
||||||
}else{
|
}else{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->meta = 0;
|
$this->meta = 0;
|
||||||
$this->getLevel()->setBlock($this, $this);
|
$this->getLevelNonNull()->setBlock($this, $this);
|
||||||
}else{
|
}else{
|
||||||
++$this->meta;
|
++$this->meta;
|
||||||
$this->getLevel()->setBlock($this, $this);
|
$this->getLevelNonNull()->setBlock($this, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ class Cactus extends Transparent{
|
|||||||
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
||||||
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
||||||
if(!$block0->isSolid() and !$block1->isSolid() and !$block2->isSolid() and !$block3->isSolid()){
|
if(!$block0->isSolid() and !$block1->isSolid() and !$block2->isSolid() and !$block3->isSolid()){
|
||||||
$this->getLevel()->setBlock($this, $this, true);
|
$this->getLevelNonNull()->setBlock($this, $this, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
if($down->getId() !== self::AIR){
|
if($down->getId() !== self::AIR){
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +109,10 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getVariantBitmask() : int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Block
|
* @return Block
|
||||||
*/
|
*/
|
||||||
|
@ -64,7 +64,7 @@ class Carpet extends Flowable{
|
|||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
if($down->getId() !== self::AIR){
|
if($down->getId() !== self::AIR){
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ class Carpet extends Flowable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ class Chest extends Transparent{
|
|||||||
}
|
}
|
||||||
$c = $this->getSide($side);
|
$c = $this->getSide($side);
|
||||||
if($c->getId() === $this->id and $c->getDamage() === $this->meta){
|
if($c->getId() === $this->id and $c->getDamage() === $this->meta){
|
||||||
$tile = $this->getLevel()->getTile($c);
|
$tile = $this->getLevelNonNull()->getTile($c);
|
||||||
if($tile instanceof TileChest and !$tile->isPaired()){
|
if($tile instanceof TileChest and !$tile->isPaired()){
|
||||||
$chest = $tile;
|
$chest = $tile;
|
||||||
break;
|
break;
|
||||||
@ -89,8 +89,8 @@ class Chest extends Transparent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
$tile = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this, $face, $item, $player));
|
$tile = Tile::createTile(Tile::CHEST, $this->getLevelNonNull(), TileChest::createNBT($this, $face, $item, $player));
|
||||||
|
|
||||||
if($chest instanceof TileChest and $tile instanceof TileChest){
|
if($chest instanceof TileChest and $tile instanceof TileChest){
|
||||||
$chest->pairWith($tile);
|
$chest->pairWith($tile);
|
||||||
@ -103,12 +103,12 @@ class Chest extends Transparent{
|
|||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
|
|
||||||
$t = $this->getLevel()->getTile($this);
|
$t = $this->getLevelNonNull()->getTile($this);
|
||||||
$chest = null;
|
$chest = null;
|
||||||
if($t instanceof TileChest){
|
if($t instanceof TileChest){
|
||||||
$chest = $t;
|
$chest = $t;
|
||||||
}else{
|
}else{
|
||||||
$chest = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this));
|
$chest = Tile::createTile(Tile::CHEST, $this->getLevelNonNull(), TileChest::createNBT($this));
|
||||||
if(!($chest instanceof TileChest)){
|
if(!($chest instanceof TileChest)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ class Chest extends Transparent{
|
|||||||
|
|
||||||
if(
|
if(
|
||||||
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
||||||
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
(($pair = $chest->getPair()) !== null and !$pair->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
||||||
!$chest->canOpenWith($item->getCustomName())
|
!$chest->canOpenWith($item->getCustomName())
|
||||||
){
|
){
|
||||||
return true;
|
return true;
|
||||||
|
@ -111,6 +111,9 @@ class CobblestoneWall extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function canConnect(Block $block){
|
public function canConnect(Block $block){
|
||||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\ItemFactory;
|
||||||
|
use pocketmine\item\ItemIds;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class CocoaBlock extends Transparent{
|
class CocoaBlock extends Transparent{
|
||||||
|
|
||||||
protected $id = self::COCOA_BLOCK;
|
protected $id = self::COCOA_BLOCK;
|
||||||
@ -48,4 +53,14 @@ class CocoaBlock extends Transparent{
|
|||||||
public function isAffectedBySilkTouch() : bool{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
return [
|
||||||
|
ItemFactory::get(ItemIds::DYE, 3, ($this->meta >> 2) === 2 ? mt_rand(2, 3) : 1)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPickedItem() : Item{
|
||||||
|
return ItemFactory::get(ItemIds::DYE, 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,16 +53,10 @@ class ConcretePowder extends Fallable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return null|Block
|
|
||||||
*/
|
|
||||||
public function tickFalling() : ?Block{
|
public function tickFalling() : ?Block{
|
||||||
return $this->checkAdjacentWater();
|
return $this->checkAdjacentWater();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return null|Block
|
|
||||||
*/
|
|
||||||
private function checkAdjacentWater() : ?Block{
|
private function checkAdjacentWater() : ?Block{
|
||||||
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
||||||
if($this->getSide($i) instanceof Water){
|
if($this->getSide($i) instanceof Water){
|
||||||
|
@ -25,7 +25,10 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\inventory\CraftingGrid;
|
use pocketmine\inventory\CraftingGrid;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\network\mcpe\protocol\ContainerOpenPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\WindowTypes;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
use function array_key_exists;
|
||||||
|
|
||||||
class CraftingTable extends Solid{
|
class CraftingTable extends Solid{
|
||||||
|
|
||||||
@ -50,6 +53,19 @@ class CraftingTable extends Solid{
|
|||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
||||||
|
|
||||||
|
if(!array_key_exists($windowId = Player::HARDCODED_CRAFTING_GRID_WINDOW_ID, $player->openHardcodedWindows)){
|
||||||
|
//TODO: HACK! crafting grid doesn't fit very well into the current PM container system, so this hack allows
|
||||||
|
//it to carry on working approximately the same way as it did in 1.14
|
||||||
|
$pk = new ContainerOpenPacket();
|
||||||
|
$pk->windowId = $windowId;
|
||||||
|
$pk->type = WindowTypes::WORKBENCH;
|
||||||
|
$pk->x = $this->getFloorX();
|
||||||
|
$pk->y = $this->getFloorY();
|
||||||
|
$pk->z = $this->getFloorZ();
|
||||||
|
$player->sendDataPacket($pk);
|
||||||
|
$player->openHardcodedWindows[$windowId] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -33,7 +33,7 @@ abstract class Crops extends Flowable{
|
|||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
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){
|
if($blockReplace->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -41,7 +41,6 @@ abstract class Crops extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
@ -53,10 +52,10 @@ abstract class Crops extends Flowable{
|
|||||||
$ev = new BlockGrowEvent($this, $block);
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
$this->getLevelNonNull()->setBlock($this, $ev->getNewState(), true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$item->count--;
|
$item->pop();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -66,7 +65,7 @@ abstract class Crops extends Flowable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ abstract class Crops extends Flowable{
|
|||||||
$ev = new BlockGrowEvent($this, $block);
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
$this->getLevelNonNull()->setBlock($this, $ev->getNewState(), true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,10 @@ class Dandelion extends Flowable{
|
|||||||
return "Dandelion";
|
return "Dandelion";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -53,7 +52,7 @@ class Dandelion extends Flowable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class DeadBush extends Flowable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +54,9 @@ class Dirt extends Solid{
|
|||||||
if($item instanceof Hoe){
|
if($item instanceof Hoe){
|
||||||
$item->applyDamage(1);
|
$item->applyDamage(1);
|
||||||
if($this->meta === 1){
|
if($this->meta === 1){
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||||
}else{
|
}else{
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -29,14 +29,13 @@ use pocketmine\math\AxisAlignedBB;
|
|||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
|
|
||||||
abstract class Door extends Transparent{
|
abstract class Door extends Transparent{
|
||||||
|
|
||||||
public function isSolid() : bool{
|
public function isSolid() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFullDamage(){
|
private function getFullDamage() : int{
|
||||||
$damage = $this->getDamage();
|
$damage = $this->getDamage();
|
||||||
$isUp = ($damage & 0x08) > 0;
|
$isUp = ($damage & 0x08) > 0;
|
||||||
|
|
||||||
@ -202,9 +201,9 @@ abstract class Door extends Transparent{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
||||||
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
||||||
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
$this->getLevelNonNull()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,8 +230,8 @@ abstract class Door extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->setDamage($player->getDirection() & 0x03);
|
$this->setDamage($player->getDirection() & 0x03);
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true); //Bottom
|
||||||
$this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
|
$this->getLevelNonNull()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,8 +57,8 @@ class DoublePlant extends Flowable{
|
|||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$id = $blockReplace->getSide(Vector3::SIDE_DOWN)->getId();
|
$id = $blockReplace->getSide(Vector3::SIDE_DOWN)->getId();
|
||||||
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Vector3::SIDE_UP)->canBeReplaced()){
|
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Vector3::SIDE_UP)->canBeReplaced()){
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, false, false);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, false, false);
|
||||||
$this->getLevel()->setBlock($blockReplace->getSide(Vector3::SIDE_UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
|
$this->getLevelNonNull()->setBlock($blockReplace->getSide(Vector3::SIDE_UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -68,10 +68,9 @@ class DoublePlant extends Flowable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this double-plant has a corresponding other half.
|
* Returns whether this double-plant has a corresponding other half.
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isValidHalfPlant() : bool{
|
public function isValidHalfPlant() : bool{
|
||||||
if($this->meta & self::BITFLAG_TOP){
|
if(($this->meta & self::BITFLAG_TOP) !== 0){
|
||||||
$other = $this->getSide(Vector3::SIDE_DOWN);
|
$other = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
}else{
|
}else{
|
||||||
$other = $this->getSide(Vector3::SIDE_UP);
|
$other = $this->getSide(Vector3::SIDE_UP);
|
||||||
@ -86,7 +85,7 @@ class DoublePlant extends Flowable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
|
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ class DoublePlant extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($this->meta & self::BITFLAG_TOP){
|
if(($this->meta & self::BITFLAG_TOP) !== 0){
|
||||||
if($this->isCompatibleWithTool($item)){
|
if($this->isCompatibleWithTool($item)){
|
||||||
return parent::getDrops($item);
|
return parent::getDrops($item);
|
||||||
}
|
}
|
||||||
@ -125,4 +124,12 @@ class DoublePlant extends Flowable{
|
|||||||
|
|
||||||
return parent::getAffectedBlocks();
|
return parent::getAffectedBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,9 @@ class EnchantingTable extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), TileEnchantTable::createNBT($this, $face, $item, $player));
|
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevelNonNull(), TileEnchantTable::createNBT($this, $face, $item, $player));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,8 @@ class EnderChest extends Chest{
|
|||||||
|
|
||||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||||
|
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this, $face, $item, $player));
|
Tile::createTile(Tile::ENDER_CHEST, $this->getLevelNonNull(), TileEnderChest::createNBT($this, $face, $item, $player));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -78,12 +78,12 @@ class EnderChest extends Chest{
|
|||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
|
|
||||||
$t = $this->getLevel()->getTile($this);
|
$t = $this->getLevelNonNull()->getTile($this);
|
||||||
$enderChest = null;
|
$enderChest = null;
|
||||||
if($t instanceof TileEnderChest){
|
if($t instanceof TileEnderChest){
|
||||||
$enderChest = $t;
|
$enderChest = $t;
|
||||||
}else{
|
}else{
|
||||||
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this));
|
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevelNonNull(), TileEnderChest::createNBT($this));
|
||||||
if(!($enderChest instanceof TileEnderChest)){
|
if(!($enderChest instanceof TileEnderChest)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user